summaryrefslogtreecommitdiffstats
path: root/kftpgrabber/src/widgets/filtereditor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kftpgrabber/src/widgets/filtereditor.cpp')
-rw-r--r--kftpgrabber/src/widgets/filtereditor.cpp625
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"
+