You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kftpgrabber/kftpgrabber/src/widgets/filtereditor.cpp

626 lines
18 KiB

/*
* 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 <tqlayout.h>
#include <tqhbox.h>
#include <tqtooltip.h>
#include <tqheader.h>
#include <tqbuttongroup.h>
#include <kiconloader.h>
#include <tdelocale.h>
#include <kdialog.h>
#include <kinputdialog.h>
using namespace KFTPCore::Filter;
namespace KFTPWidgets {
FilterEditor::FilterEditor(TQWidget *parent)
: TQWidget(parent),
m_rule(0)
{
TQHBoxLayout *mainLayout = new TQHBoxLayout(this, 0, KDialog::spacingHint());
m_listView = new FilterListView(this);
mainLayout->addWidget(m_listView, 1);
TQVBoxLayout *rightLayout = new TQVBoxLayout(mainLayout);
mainLayout->setStretchFactor(rightLayout, KDialog::spacingHint());
m_enabledCheck = new TQCheckBox(i18n("Filter &enabled"), this);
rightLayout->addWidget(m_enabledCheck);
m_conditionsList = new FilterConditionsList(this);
rightLayout->addWidget(m_conditionsList, 0, TQt::AlignTop);
m_actionsList = new FilterActionsList(this);
rightLayout->addWidget(m_actionsList, 0, TQt::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)
: TQListViewItem(parent),
m_rule(rule)
{
setText(0, rule->name());
}
FilterListView::FilterListView(TQWidget *parent)
: TQGroupBox(1, Horizontal, i18n("Filters"), parent)
{
m_listView = new ListView(this);
m_listView->setSelectionMode(TQListView::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);
TQHBox *hb = new TQHBox(this);
hb->setSpacing(4);
// Up/down buttons
m_buttonUp = new KPushButton(TQString::null, hb);
m_buttonUp->setAutoRepeat(true);
m_buttonUp->setIconSet(BarIconSet("go-up", TDEIcon::SizeSmall));
m_buttonUp->setMinimumSize(m_buttonUp->sizeHint() * 1.2);
m_buttonDown = new KPushButton(TQString::null, hb);
m_buttonDown->setAutoRepeat(true);
m_buttonDown->setIconSet(BarIconSet("go-down", TDEIcon::SizeSmall));
m_buttonDown->setMinimumSize(m_buttonDown->sizeHint() * 1.2);
TQToolTip::add(m_buttonUp, i18n("Up"));
TQToolTip::add(m_buttonDown, i18n("Down"));
// New, copy, delete buttons
hb = new TQHBox(this);
hb->setSpacing(4);
m_buttonNew = new TQPushButton(TQString::null, hb);
m_buttonNew->setPixmap(BarIcon("document-new", TDEIcon::SizeSmall));
m_buttonNew->setMinimumSize(m_buttonNew->sizeHint() * 1.2);
m_buttonCopy = new TQPushButton(TQString::null, hb);
m_buttonCopy->setPixmap(BarIcon("edit-copy", TDEIcon::SizeSmall));
m_buttonCopy->setMinimumSize(m_buttonCopy->sizeHint() * 1.2);
m_buttonDelete = new TQPushButton(TQString::null, hb);
m_buttonDelete->setPixmap(BarIcon("edit-delete", TDEIcon::SizeSmall));
m_buttonDelete->setMinimumSize(m_buttonDelete->sizeHint() * 1.2);
m_buttonRename = new TQPushButton(i18n("Rename..."), hb);
TQToolTip::add(m_buttonNew, i18n("New"));
TQToolTip::add(m_buttonCopy, i18n("Copy"));
TQToolTip::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(TQListViewItem*)), this, SLOT(slotSelectionChanged(TQListViewItem*)));
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(TQListViewItem *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) {
TQString 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());
TQListViewItem *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(TQWidget *parent)
: TQGroupBox(1, Horizontal, i18n("Conditions"), parent)
{
setEnabled(false);
m_buttonAll = new TQRadioButton(i18n("Match a&ll of the following"), this);
m_buttonAny = new TQRadioButton(i18n("Match an&y of the following"), this);
m_buttonAll->setChecked(true);
m_buttonAny->setChecked(false);
TQButtonGroup *bg = new TQButtonGroup(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(TQWidget *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(TQMAX(conditions->count(), 0));
ConditionChain::ConstIterator le = conditions->end();
TQPtrList<TQWidget>::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, TQVariant(""));
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();
}
TQWidget *FilterConditionWidgetLister::createWidget(TQWidget *parent)
{
return new FilterConditionWidget(parent);
}
FilterConditionWidget::FilterConditionWidget(TQWidget *parent)
: TQWidget(parent),
m_condition(0)
{
TQHBoxLayout *layout = new TQHBoxLayout(this, 0, KDialog::spacingHint());
m_fieldCombo = new TQComboBox(this);
m_fieldCombo->insertStringList(Filters::self()->getFieldNames());
layout->addWidget(m_fieldCombo);
m_typeStack = new TQWidgetStack(this);
m_typeStack->setSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::Fixed);
layout->addWidget(m_typeStack);
m_valueStack = new TQWidgetStack(this);
m_valueStack->setSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::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(TQWidget *parent)
: TQGroupBox(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(TQWidget *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(TQMAX(actions->count(), 0));
ActionChain::ConstIterator le = actions->end();
TQPtrList<TQWidget>::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, TQVariant());
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();
}
TQWidget *FilterActionWidgetLister::createWidget(TQWidget *parent)
{
return new FilterActionWidget(parent);
}
FilterActionWidget::FilterActionWidget(TQWidget *parent)
: TQWidget(parent),
m_action(0)
{
TQHBoxLayout *layout = new TQHBoxLayout(this, 0, KDialog::spacingHint());
m_actionCombo = new TQComboBox(this);
m_actionCombo->insertStringList(Filters::self()->getActionNames());
layout->addWidget(m_actionCombo);
m_valueStack = new TQWidgetStack(this);
m_valueStack->setSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::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"