diff options
Diffstat (limited to 'kftpgrabber/src/widgets/filtereditor.cpp')
-rw-r--r-- | kftpgrabber/src/widgets/filtereditor.cpp | 625 |
1 files changed, 625 insertions, 0 deletions
diff --git a/kftpgrabber/src/widgets/filtereditor.cpp b/kftpgrabber/src/widgets/filtereditor.cpp new file mode 100644 index 0000000..9be3b6e --- /dev/null +++ b/kftpgrabber/src/widgets/filtereditor.cpp @@ -0,0 +1,625 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.net> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#include "filtereditor.h" +#include "listview.h" +#include "misc/filterwidgethandler.h" + +#include <qlayout.h> +#include <qhbox.h> +#include <qtooltip.h> +#include <qheader.h> +#include <qbuttongroup.h> + +#include <kiconloader.h> +#include <klocale.h> +#include <kdialog.h> +#include <kinputdialog.h> + +using namespace KFTPCore::Filter; + +namespace KFTPWidgets { + +FilterEditor::FilterEditor(QWidget *parent) + : QWidget(parent), + m_rule(0) +{ + QHBoxLayout *mainLayout = new QHBoxLayout(this, 0, KDialog::spacingHint()); + + m_listView = new FilterListView(this); + mainLayout->addWidget(m_listView, 1); + + QVBoxLayout *rightLayout = new QVBoxLayout(mainLayout); + mainLayout->setStretchFactor(rightLayout, KDialog::spacingHint()); + + m_enabledCheck = new QCheckBox(i18n("Filter &enabled"), this); + rightLayout->addWidget(m_enabledCheck); + + m_conditionsList = new FilterConditionsList(this); + rightLayout->addWidget(m_conditionsList, 0, Qt::AlignTop); + + m_actionsList = new FilterActionsList(this); + rightLayout->addWidget(m_actionsList, 0, Qt::AlignTop); + + rightLayout->addStretch(1); + + // Connect some signals + connect(m_enabledCheck, SIGNAL(clicked()), this, SLOT(slotEnabledChanged())); + + connect(m_listView, SIGNAL(ruleChanged(KFTPCore::Filter::Rule*)), this, SLOT(slotRuleChanged(KFTPCore::Filter::Rule*))); + connect(m_listView, SIGNAL(ruleRemoved()), this, SLOT(slotRuleRemoved())); + + connect(m_listView, SIGNAL(ruleChanged(KFTPCore::Filter::Rule*)), m_conditionsList, SLOT(loadRule(KFTPCore::Filter::Rule*))); + connect(m_listView, SIGNAL(ruleRemoved()), m_conditionsList, SLOT(reset())); + + connect(m_listView, SIGNAL(ruleChanged(KFTPCore::Filter::Rule*)), m_actionsList, SLOT(loadRule(KFTPCore::Filter::Rule*))); + connect(m_listView, SIGNAL(ruleRemoved()), m_actionsList, SLOT(reset())); +} + +void FilterEditor::slotRuleChanged(KFTPCore::Filter::Rule *rule) +{ + m_enabledCheck->setEnabled(true); + m_enabledCheck->setChecked(rule->isEnabled()); + + m_rule = rule; +} + +void FilterEditor::slotRuleRemoved() +{ + m_enabledCheck->setChecked(false); + m_enabledCheck->setEnabled(false); +} + +void FilterEditor::slotEnabledChanged() +{ + if (m_rule) + m_rule->setEnabled(m_enabledCheck->isChecked()); +} + +void FilterEditor::reset() +{ + m_enabledCheck->setChecked(false); + m_enabledCheck->setEnabled(false); + + m_conditionsList->reset(); + m_actionsList->reset(); + m_listView->reset(); +} + +FilterListItem::FilterListItem(ListView *parent, KFTPCore::Filter::Rule *rule) + : QListViewItem(parent), + m_rule(rule) +{ + setText(0, rule->name()); +} + +FilterListView::FilterListView(QWidget *parent) + : QGroupBox(1, Horizontal, i18n("Filters"), parent) +{ + m_listView = new ListView(this); + m_listView->setSelectionMode(QListView::Single); + m_listView->setSorting(-1); + m_listView->header()->hide(); + m_listView->setMinimumWidth(150); + m_listView->setEmptyListText(i18n("No filters.")); + m_listView->addColumn(""); + m_listView->setFullWidth(true); + + QHBox *hb = new QHBox(this); + hb->setSpacing(4); + + // Up/down buttons + m_buttonUp = new KPushButton(QString::null, hb); + m_buttonUp->setAutoRepeat(true); + m_buttonUp->setIconSet(BarIconSet("up", KIcon::SizeSmall)); + m_buttonUp->setMinimumSize(m_buttonUp->sizeHint() * 1.2); + + m_buttonDown = new KPushButton(QString::null, hb); + m_buttonDown->setAutoRepeat(true); + m_buttonDown->setIconSet(BarIconSet("down", KIcon::SizeSmall)); + m_buttonDown->setMinimumSize(m_buttonDown->sizeHint() * 1.2); + + QToolTip::add(m_buttonUp, i18n("Up")); + QToolTip::add(m_buttonDown, i18n("Down")); + + // New, copy, delete buttons + hb = new QHBox(this); + hb->setSpacing(4); + + m_buttonNew = new QPushButton(QString::null, hb); + m_buttonNew->setPixmap(BarIcon("filenew", KIcon::SizeSmall)); + m_buttonNew->setMinimumSize(m_buttonNew->sizeHint() * 1.2); + + m_buttonCopy = new QPushButton(QString::null, hb); + m_buttonCopy->setPixmap(BarIcon("editcopy", KIcon::SizeSmall)); + m_buttonCopy->setMinimumSize(m_buttonCopy->sizeHint() * 1.2); + + m_buttonDelete = new QPushButton(QString::null, hb); + m_buttonDelete->setPixmap(BarIcon("editdelete", KIcon::SizeSmall)); + m_buttonDelete->setMinimumSize(m_buttonDelete->sizeHint() * 1.2); + + m_buttonRename = new QPushButton(i18n("Rename..."), hb); + + QToolTip::add(m_buttonNew, i18n("New")); + QToolTip::add(m_buttonCopy, i18n("Copy")); + QToolTip::add(m_buttonDelete, i18n("Delete")); + + // Connect the signals + connect(m_buttonNew, SIGNAL(clicked()), this, SLOT(slotNewRule())); + connect(m_buttonDelete, SIGNAL(clicked()), this, SLOT(slotDeleteRule())); + connect(m_buttonRename, SIGNAL(clicked()), this, SLOT(slotRenameRule())); + connect(m_buttonCopy, SIGNAL(clicked()), this, SLOT(slotCopyRule())); + + connect(m_buttonUp, SIGNAL(clicked()), this, SLOT(slotUp())); + connect(m_buttonDown, SIGNAL(clicked()), this, SLOT(slotDown())); + + connect(m_listView, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(slotSelectionChanged(QListViewItem*))); + + m_buttonUp->setEnabled(false); + m_buttonDown->setEnabled(false); + m_buttonRename->setEnabled(false); + + // Reset the view, loading all the existing rules + reset(); +} + +void FilterListView::reset() +{ + m_listView->clear(); + + // Load all existing rules + Filters *filters = Filters::self(); + Filters::ConstIterator le = filters->end(); + + for (Filters::ConstIterator i = filters->begin(); i != le; ++i) { + FilterListItem *item = new FilterListItem(m_listView, (*i)); + item->moveItem(m_listView->lastItem()); + } + + // Select the first rule + m_listView->setSelected(m_listView->firstChild(), true); +} + +void FilterListView::slotSelectionChanged(QListViewItem *item) +{ + FilterListItem *selected = static_cast<FilterListItem*>(item); + + m_buttonUp->setEnabled(item->itemAbove()); + m_buttonDown->setEnabled(item->nextSibling()); + m_buttonRename->setEnabled(true); + + // Signal the rule change + emit ruleChanged(selected->rule()); +} + +void FilterListView::slotNewRule() +{ + Rule *rule = new Rule(i18n("Unnamed Rule")); + FilterListItem *selected = static_cast<FilterListItem*>(m_listView->selectedItem()); + FilterListItem *item = new FilterListItem(m_listView, rule); + + if (selected) { + Filters::self()->insert(Filters::self()->findRef(selected->rule()) + 1, rule); + item->moveItem(selected); + } else { + Filters::self()->append(rule); + } + + m_listView->setSelected(item, true); +} + +void FilterListView::slotDeleteRule() +{ + FilterListItem *selected = static_cast<FilterListItem*>(m_listView->selectedItem()); + + if (selected) { + Rule *rule = selected->rule(); + delete selected; + + emit ruleRemoved(); + + Filters::self()->removeRef(rule); + m_listView->setSelected(m_listView->lastItem(), true); + } + + if (!m_listView->selectedItem()) + m_buttonRename->setEnabled(false); +} + +void FilterListView::slotRenameRule() +{ + FilterListItem *selected = static_cast<FilterListItem*>(m_listView->selectedItem()); + + if (selected) { + QString name = KInputDialog::getText(i18n("Rename Rule"), i18n("Rename rule '%1' to:").arg(selected->rule()->name()), selected->rule()->name()); + + if (name.stripWhiteSpace().isEmpty()) + name = i18n("Unnamed Rule"); + + selected->rule()->setName(name); + selected->setText(0, name); + } +} + +void FilterListView::slotCopyRule() +{ + FilterListItem *selected = static_cast<FilterListItem*>(m_listView->selectedItem()); + + if (selected) { + Rule *rule = new Rule(selected->rule()); + FilterListItem *item = new FilterListItem(m_listView, rule); + + Filters::self()->insert(Filters::self()->findRef(selected->rule()) + 1, rule); + item->moveItem(selected); + m_listView->setSelected(item, true); + } +} + +void FilterListView::slotUp() +{ + FilterListItem *selected = static_cast<FilterListItem*>(m_listView->selectedItem()); + QListViewItem *tmp = selected->itemAbove(); + if (!tmp) + return; + + FilterListItem *previous = static_cast<FilterListItem*>(tmp->itemAbove()); + + if (selected) { + Rule *rule = Filters::self()->take(Filters::self()->findRef(selected->rule())); + + if (previous) { + Filters::self()->insert(Filters::self()->findRef(previous->rule()) + 1, rule); + selected->moveItem(previous); + } else { + Filters::self()->insert(0, rule); + m_listView->takeItem(selected); + m_listView->insertItem(selected); + m_listView->setSelected(selected, true); + } + + m_buttonUp->setEnabled(selected->itemAbove()); + m_buttonDown->setEnabled(selected->nextSibling()); + } +} + +void FilterListView::slotDown() +{ + FilterListItem *selected = static_cast<FilterListItem*>(m_listView->selectedItem()); + FilterListItem *next = static_cast<FilterListItem*>(selected->nextSibling()); + + if (selected && next) { + Rule *rule = Filters::self()->take(Filters::self()->findRef(selected->rule())); + Filters::self()->insert(Filters::self()->findRef(next->rule()) + 1, rule); + selected->moveItem(next); + + m_buttonUp->setEnabled(selected->itemAbove()); + m_buttonDown->setEnabled(selected->nextSibling()); + } +} + +FilterConditionsList::FilterConditionsList(QWidget *parent) + : QGroupBox(1, Horizontal, i18n("Conditions"), parent) +{ + setEnabled(false); + + m_buttonAll = new QRadioButton(i18n("Match a&ll of the following"), this); + m_buttonAny = new QRadioButton(i18n("Match an&y of the following"), this); + + m_buttonAll->setChecked(true); + m_buttonAny->setChecked(false); + + QButtonGroup *bg = new QButtonGroup(this); + bg->hide(); + bg->insert(m_buttonAll, (int) ConditionChain::All); + bg->insert(m_buttonAny, (int) ConditionChain::Any); + + // Connect some signals + connect(bg, SIGNAL(clicked(int)), this, SLOT(slotMatchTypeChanged(int))); + + m_lister = new FilterConditionWidgetLister(this); +} + +void FilterConditionsList::reset() +{ + m_lister->clear(); + setEnabled(false); +} + +void FilterConditionsList::loadRule(Rule *rule) +{ + m_rule = rule; + + switch (rule->conditions()->type()) { + case ConditionChain::All: m_buttonAll->setChecked(true); break; + case ConditionChain::Any: m_buttonAny->setChecked(true); break; + } + + m_lister->loadConditions(rule); + setEnabled(true); +} + +void FilterConditionsList::slotMatchTypeChanged(int type) +{ + if (m_rule) + const_cast<ConditionChain*>(m_rule->conditions())->setType((ConditionChain::Type) type); +} + +FilterConditionWidgetLister::FilterConditionWidgetLister(QWidget *parent) + : WidgetLister(parent, 0, 7), + m_rule(0) +{ + setMinimumWidth(400); +} + +void FilterConditionWidgetLister::loadConditions(KFTPCore::Filter::Rule *rule) +{ + const ConditionChain *conditions = rule->conditions(); + + // Clear the current list + setNumberShown(QMAX(conditions->count(), 0)); + + ConditionChain::ConstIterator le = conditions->end(); + QPtrList<QWidget>::Iterator wi = m_widgetList.begin(); + for (ConditionChain::ConstIterator i = conditions->begin(); i != le; ++i, ++wi) + static_cast<FilterConditionWidget*>((*wi))->setCondition((*i)); + + m_rule = rule; +} + +void FilterConditionWidgetLister::slotMore() +{ + WidgetLister::slotMore(); + + // Actually add the condition and update the latest widget + Condition *condition = new Condition(Filename, Condition::Contains, QVariant("")); + + const_cast<ConditionChain*>(m_rule->conditions())->append(condition); + static_cast<FilterConditionWidget*>(m_widgetList.last())->setCondition(condition); +} + +void FilterConditionWidgetLister::slotFewer() +{ + // Actually remove the condition + Condition *condition = static_cast<FilterConditionWidget*>(m_widgetList.last())->condition(); + const_cast<ConditionChain*>(m_rule->conditions())->remove(condition); + + WidgetLister::slotFewer(); +} + +void FilterConditionWidgetLister::slotClear() +{ + if (m_rule) + const_cast<ConditionChain*>(m_rule->conditions())->clear(); + + WidgetLister::slotClear(); +} + +QWidget *FilterConditionWidgetLister::createWidget(QWidget *parent) +{ + return new FilterConditionWidget(parent); +} + +FilterConditionWidget::FilterConditionWidget(QWidget *parent) + : QWidget(parent), + m_condition(0) +{ + QHBoxLayout *layout = new QHBoxLayout(this, 0, KDialog::spacingHint()); + + m_fieldCombo = new QComboBox(this); + m_fieldCombo->insertStringList(Filters::self()->getFieldNames()); + layout->addWidget(m_fieldCombo); + + m_typeStack = new QWidgetStack(this); + m_typeStack->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + layout->addWidget(m_typeStack); + + m_valueStack = new QWidgetStack(this); + m_valueStack->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + layout->addWidget(m_valueStack); + layout->setStretchFactor(m_valueStack, 10); + + // Initialize widgets + WidgetHandlerManager::self()->createConditionWidgets(m_typeStack, m_valueStack, this); + + // Connect signals + connect(m_fieldCombo, SIGNAL(activated(int)), this, SLOT(slotFieldChanged(int))); + + setFocusProxy(m_fieldCombo); +} + +void FilterConditionWidget::setCondition(const Condition *condition) +{ + m_condition = const_cast<Condition*>(condition); + + m_fieldCombo->setCurrentItem((int) condition->field()); + WidgetHandlerManager::self()->setCondition(m_typeStack, m_valueStack, condition); +} + +void FilterConditionWidget::slotFieldChanged(int field) +{ + WidgetHandlerManager::self()->update((Field) field, m_typeStack, m_valueStack); + + if (m_condition) { + // Update the current condition + m_condition->setField((Field) field); + slotTypeChanged(); + } +} + +void FilterConditionWidget::slotTypeChanged() +{ + if (m_condition) { + // Update the current condition + m_condition->setType(WidgetHandlerManager::self()->getConditionType(m_condition->field(), m_typeStack)); + slotValueChanged(); + } +} + +void FilterConditionWidget::slotValueChanged() +{ + if (m_condition) { + // Update the current condition + m_condition->setValue(WidgetHandlerManager::self()->getConditionValue(m_condition->field(), m_valueStack)); + } +} + +FilterActionsList::FilterActionsList(QWidget *parent) + : QGroupBox(1, Horizontal, i18n("Actions"), parent) +{ + setEnabled(false); + + m_lister = new FilterActionWidgetLister(this); +} + +void FilterActionsList::reset() +{ + m_lister->clear(); + setEnabled(false); +} + +void FilterActionsList::loadRule(Rule *rule) +{ + m_rule = rule; + + m_lister->loadActions(rule); + setEnabled(true); +} + +FilterActionWidgetLister::FilterActionWidgetLister(QWidget *parent) + : WidgetLister(parent, 0, 7), + m_rule(0) +{ + setMinimumWidth(400); +} + +void FilterActionWidgetLister::loadActions(KFTPCore::Filter::Rule *rule) +{ + const ActionChain *actions = rule->actions(); + + // Clear the current list + setNumberShown(QMAX(actions->count(), 0)); + + ActionChain::ConstIterator le = actions->end(); + QPtrList<QWidget>::Iterator wi = m_widgetList.begin(); + for (ActionChain::ConstIterator i = actions->begin(); i != le; ++i, ++wi) + static_cast<FilterActionWidget*>((*wi))->setAction((*i)); + + m_rule = rule; +} + +void FilterActionWidgetLister::slotMore() +{ + WidgetLister::slotMore(); + + // Actually add the action and update the latest widget + Action *action = new Action(Action::None, QVariant()); + + const_cast<ActionChain*>(m_rule->actions())->append(action); + static_cast<FilterActionWidget*>(m_widgetList.last())->setAction(action); +} + +void FilterActionWidgetLister::slotFewer() +{ + // Actually remove the action + Action *action = static_cast<FilterActionWidget*>(m_widgetList.last())->action(); + const_cast<ActionChain*>(m_rule->actions())->remove(action); + + WidgetLister::slotFewer(); +} + +void FilterActionWidgetLister::slotClear() +{ + if (m_rule) + const_cast<ActionChain*>(m_rule->actions())->clear(); + + WidgetLister::slotClear(); +} + +QWidget *FilterActionWidgetLister::createWidget(QWidget *parent) +{ + return new FilterActionWidget(parent); +} + +FilterActionWidget::FilterActionWidget(QWidget *parent) + : QWidget(parent), + m_action(0) +{ + QHBoxLayout *layout = new QHBoxLayout(this, 0, KDialog::spacingHint()); + + m_actionCombo = new QComboBox(this); + m_actionCombo->insertStringList(Filters::self()->getActionNames()); + layout->addWidget(m_actionCombo); + + m_valueStack = new QWidgetStack(this); + m_valueStack->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + layout->addWidget(m_valueStack); + layout->setStretchFactor(m_valueStack, 10); + + // Initialize widgets + WidgetHandlerManager::self()->createActionWidgets(m_valueStack, this); + + // Connect signals + connect(m_actionCombo, SIGNAL(activated(int)), this, SLOT(slotActionChanged(int))); + connect(m_actionCombo, SIGNAL(activated(int)), m_valueStack, SLOT(raiseWidget(int))); + + setFocusProxy(m_actionCombo); +} + +void FilterActionWidget::setAction(const Action *action) +{ + m_action = const_cast<Action*>(action); + + m_actionCombo->setCurrentItem((int) action->type()); + WidgetHandlerManager::self()->setAction(m_valueStack, action); +} + +void FilterActionWidget::slotActionChanged(int field) +{ + if (m_action) { + m_action->setType((Action::Type) field); + slotValueChanged(); + } +} + +void FilterActionWidget::slotValueChanged() +{ + if (m_action) + m_action->setValue(WidgetHandlerManager::self()->getActionValue(m_valueStack)); +} + +} + +#include "filtereditor.moc" + |