summaryrefslogtreecommitdiffstats
path: root/libkdepim/kscoringeditor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libkdepim/kscoringeditor.cpp')
-rw-r--r--libkdepim/kscoringeditor.cpp1029
1 files changed, 1029 insertions, 0 deletions
diff --git a/libkdepim/kscoringeditor.cpp b/libkdepim/kscoringeditor.cpp
new file mode 100644
index 00000000..4ead5b8d
--- /dev/null
+++ b/libkdepim/kscoringeditor.cpp
@@ -0,0 +1,1029 @@
+/*
+ kscoringeditor.cpp
+
+ Copyright (c) 2001 Mathias Waack
+ Copyright (C) 2005 by Volker Krause <volker.krause@rwth-aachen.de>
+
+ Author: Mathias Waack <mathias@atoll-net.de>
+
+ 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.
+ 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 Street, Fifth Floor, Boston, MA 02110-1301, US
+*/
+
+#undef QT_NO_COMPAT
+
+#include "kscoring.h"
+#include "kscoringeditor.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kcombobox.h>
+#include <kcolorcombo.h>
+#include <kiconloader.h>
+#include <kregexpeditorinterface.h>
+#include <ktrader.h>
+#include <kparts/componentfactory.h>
+
+
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qcheckbox.h>
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+#include <qwidgetstack.h>
+#include <qapplication.h>
+#include <qtimer.h>
+#include <qhbox.h>
+
+// works for both ListBox and ComboBox
+template <class T> static int setCurrentItem(T *box, const QString& s)
+{
+ int cnt = box->count();
+ for (int i=0;i<cnt;++i) {
+ if (box->text(i) == s) {
+ box->setCurrentItem(i);
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+//============================================================================
+//
+// class SingleConditionWidget (editor for one condition, used in ConditionEditWidget)
+//
+//============================================================================
+SingleConditionWidget::SingleConditionWidget(KScoringManager *m,QWidget *p, const char *n)
+ : QFrame(p,n), manager(m)
+{
+ QBoxLayout *topL = new QVBoxLayout(this,5);
+ QBoxLayout *firstRow = new QHBoxLayout(topL);
+ neg = new QCheckBox(i18n("Not"),this);
+ QToolTip::add(neg,i18n("Negate this condition"));
+ firstRow->addWidget(neg);
+ headers = new KComboBox(this);
+ headers->insertStringList(manager->getDefaultHeaders());
+ headers->setEditable( true );
+ QToolTip::add(headers,i18n("Select the header to match this condition against"));
+ firstRow->addWidget(headers,1);
+ matches = new KComboBox(this);
+ matches->insertStringList(KScoringExpression::conditionNames());
+ QToolTip::add(matches,i18n("Select the type of match"));
+ firstRow->addWidget(matches,1);
+ connect( matches, SIGNAL( activated( int ) ), SLOT( toggleRegExpButton( int ) ) );
+ QHBoxLayout *secondRow = new QHBoxLayout( topL );
+ secondRow->setSpacing( 1 );
+ expr = new KLineEdit( this );
+ QToolTip::add(expr,i18n("The condition for the match"));
+ // reserve space for at least 20 characters
+ expr->setMinimumWidth(fontMetrics().maxWidth()*20);
+ secondRow->addWidget( expr );
+ regExpButton = new QPushButton( i18n("Edit..."), this );
+ secondRow->addWidget( regExpButton );
+ connect( regExpButton, SIGNAL( clicked() ), SLOT( showRegExpDialog() ) );
+
+ // occupy at much width as possible
+ setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed));
+ setFrameStyle(Box | Sunken);
+ setLineWidth(1);
+}
+
+SingleConditionWidget::~SingleConditionWidget()
+{}
+
+void SingleConditionWidget::setCondition(KScoringExpression *e)
+{
+ neg->setChecked(e->isNeg());
+ headers->setCurrentText( e->getHeader() );
+ setCurrentItem(matches,KScoringExpression::getNameForCondition(e->getCondition()));
+ toggleRegExpButton( matches->currentItem() );
+ expr->setText(e->getExpression());
+}
+
+KScoringExpression* SingleConditionWidget::createCondition() const
+{
+ QString head = headers->currentText();
+ QString match = matches->currentText();
+ int condType = KScoringExpression::getConditionForName(match);
+ match = KScoringExpression::getTypeString(condType);
+ QString cond = expr->text();
+ QString negs = (neg->isChecked())?"1":"0";
+ return new KScoringExpression(head,match,cond,negs);
+}
+
+void SingleConditionWidget::clear()
+{
+ neg->setChecked(false);
+ expr->clear();
+}
+
+void SingleConditionWidget::toggleRegExpButton( int selected )
+{
+ bool isRegExp = (KScoringExpression::MATCH == selected ||
+ KScoringExpression::MATCHCS == selected) &&
+ !KTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty();
+ regExpButton->setEnabled( isRegExp );
+}
+
+void SingleConditionWidget::showRegExpDialog()
+{
+ QDialog *editorDialog = KParts::ComponentFactory::createInstanceFromQuery<QDialog>( "KRegExpEditor/KRegExpEditor" );
+ if ( editorDialog ) {
+ KRegExpEditorInterface *editor = static_cast<KRegExpEditorInterface *>( editorDialog->qt_cast( "KRegExpEditorInterface" ) );
+ Q_ASSERT( editor ); // This should not fail!
+ editor->setRegExp( expr->text() );
+ editorDialog->exec();
+ expr->setText( editor->regExp() );
+ }
+}
+
+//============================================================================
+//
+// class ConditionEditWidget (the widget to edit the conditions of a rule)
+//
+//============================================================================
+ConditionEditWidget::ConditionEditWidget(KScoringManager *m, QWidget *p, const char *n)
+ : KWidgetLister(1,8,p,n), manager(m)
+{
+ // create one initial widget
+ addWidgetAtEnd();
+}
+
+ConditionEditWidget::~ConditionEditWidget()
+{}
+
+QWidget* ConditionEditWidget::createWidget(QWidget *parent)
+{
+ return new SingleConditionWidget(manager,parent);
+}
+
+void ConditionEditWidget::clearWidget(QWidget *w)
+{
+ Q_ASSERT( w->isA("SingleConditionWidget") );
+ SingleConditionWidget *sw = dynamic_cast<SingleConditionWidget*>(w);
+ if (sw)
+ sw->clear();
+}
+
+void ConditionEditWidget::slotEditRule(KScoringRule *rule)
+{
+ KScoringRule::ScoreExprList l;
+ if (rule) l = rule->getExpressions();
+ if (!rule || l.count() == 0) {
+ slotClear();
+ } else {
+ setNumberOfShownWidgetsTo(l.count());
+ KScoringExpression *e = l.first();
+ SingleConditionWidget *scw = static_cast<SingleConditionWidget*>(mWidgetList.first());
+ while (e && scw) {
+ scw->setCondition(e);
+ e = l.next();
+ scw = static_cast<SingleConditionWidget*>(mWidgetList.next());
+ }
+ }
+}
+
+void ConditionEditWidget::updateRule(KScoringRule *rule)
+{
+ rule->cleanExpressions();
+ for(QWidget *w = mWidgetList.first(); w; w = mWidgetList.next()) {
+ if (! w->isA("SingleConditionWidget")) {
+ kdWarning(5100) << "there is a widget in ConditionEditWidget "
+ << "which isn't a SingleConditionWidget" << endl;
+ } else {
+ SingleConditionWidget *saw = dynamic_cast<SingleConditionWidget*>(w);
+ if (saw)
+ rule->addExpression(saw->createCondition());
+ }
+ }
+}
+
+//============================================================================
+//
+// class SingleActionWidget (editor for one action, used in ActionEditWidget)
+//
+//============================================================================
+SingleActionWidget::SingleActionWidget(KScoringManager *m,QWidget *p, const char *n)
+ : QWidget(p,n), notifyEditor(0), scoreEditor(0), colorEditor(0),manager(m)
+{
+ QHBoxLayout *topL = new QHBoxLayout(this,0,5);
+ types = new KComboBox(this);
+ types->setEditable(false);
+ topL->addWidget(types);
+ stack = new QWidgetStack(this);
+ topL->addWidget(stack);
+
+ dummyLabel = new QLabel(i18n("Select an action."), stack);
+ stack->addWidget(dummyLabel, 0);
+
+ // init widget stack and the types combo box
+ int index = 1;
+ types->insertItem(QString::null);
+ QStringList l = ActionBase::userNames();
+ for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
+ QString name = *it;
+ int feature = ActionBase::getTypeForUserName(name);
+ if (manager->hasFeature(feature)) {
+ types->insertItem(name);
+ QWidget *w=0;
+ switch (feature) {
+ case ActionBase::SETSCORE:
+ w = scoreEditor = new KIntSpinBox(-99999,99999,1,0,10, stack);
+ break;
+ case ActionBase::NOTIFY:
+ w = notifyEditor = new KLineEdit(stack);
+ break;
+ case ActionBase::COLOR:
+ w = colorEditor = new KColorCombo(stack);
+ break;
+ case ActionBase::MARKASREAD:
+ w = new QLabel( stack ); // empty dummy
+ break;
+ }
+ if ( w )
+ stack->addWidget(w,index++);
+ }
+ }
+
+ connect(types,SIGNAL(activated(int)),stack,SLOT(raiseWidget(int)));
+
+ // raise the dummy label
+ types->setCurrentItem(0);
+ stack->raiseWidget(dummyLabel);
+}
+
+SingleActionWidget::~SingleActionWidget()
+{
+}
+
+void SingleActionWidget::setAction(ActionBase *act)
+{
+ kdDebug(5100) << "SingleActionWidget::setAction()" << endl;
+ setCurrentItem(types,ActionBase::userName(act->getType()));
+ int index = types->currentItem();
+ stack->raiseWidget(index);
+ switch (act->getType()) {
+ case ActionBase::SETSCORE:
+ scoreEditor->setValue(act->getValueString().toInt());
+ break;
+ case ActionBase::NOTIFY:
+ notifyEditor->setText(act->getValueString());
+ break;
+ case ActionBase::COLOR:
+ colorEditor->setColor(QColor(act->getValueString()));
+ break;
+ case ActionBase::MARKASREAD:
+ // nothing
+ break;
+ default:
+ kdWarning(5100) << "unknown action type in SingleActionWidget::setAction()" << endl;
+ }
+}
+
+ActionBase* SingleActionWidget::createAction() const
+{
+ // no action selected...
+ if (types->currentText().isEmpty())
+ return 0;
+
+ int type = ActionBase::getTypeForUserName(types->currentText());
+ switch (type) {
+ case ActionBase::SETSCORE:
+ return new ActionSetScore(scoreEditor->value());
+ case ActionBase::NOTIFY:
+ return new ActionNotify(notifyEditor->text());
+ case ActionBase::COLOR:
+ return new ActionColor(colorEditor->color().name());
+ case ActionBase::MARKASREAD:
+ return new ActionMarkAsRead();
+ default:
+ kdWarning(5100) << "unknown action type in SingleActionWidget::getValue()" << endl;
+ return 0;
+ }
+}
+
+void SingleActionWidget::clear()
+{
+ if (scoreEditor) scoreEditor->setValue(0);
+ if (notifyEditor) notifyEditor->clear();
+ if (colorEditor) colorEditor->setCurrentItem(0);
+ types->setCurrentItem(0);
+ stack->raiseWidget(dummyLabel);
+}
+
+//============================================================================
+//
+// class ActionEditWidget (the widget to edit the actions of a rule)
+//
+//============================================================================
+ActionEditWidget::ActionEditWidget(KScoringManager *m,QWidget *p, const char *n)
+ : KWidgetLister(1,8,p,n), manager(m)
+{
+ // create one initial widget
+ addWidgetAtEnd();
+}
+
+ActionEditWidget::~ActionEditWidget()
+{}
+
+QWidget* ActionEditWidget::createWidget( QWidget *parent )
+{
+ return new SingleActionWidget(manager,parent);
+}
+
+void ActionEditWidget::slotEditRule(KScoringRule *rule)
+{
+ KScoringRule::ActionList l;
+ if (rule) l = rule->getActions();
+ if (!rule || l.count() == 0) {
+ slotClear();
+ } else {
+ setNumberOfShownWidgetsTo(l.count());
+ ActionBase *act = l.first();
+ SingleActionWidget *saw = static_cast<SingleActionWidget*>(mWidgetList.first());
+ while (act && saw) {
+ saw->setAction(act);
+ act = l.next();
+ saw = static_cast<SingleActionWidget*>(mWidgetList.next());
+ }
+ }
+}
+
+void ActionEditWidget::updateRule(KScoringRule *rule)
+{
+ rule->cleanActions();
+ for(QWidget *w = mWidgetList.first(); w; w = mWidgetList.next()) {
+ if (! w->isA("SingleActionWidget")) {
+ kdWarning(5100) << "there is a widget in ActionEditWidget "
+ << "which isn't a SingleActionWidget" << endl;
+ } else {
+ SingleActionWidget *saw = dynamic_cast<SingleActionWidget*>(w);
+ if (saw)
+ {
+ ActionBase *act = saw->createAction();
+ if (act)
+ rule->addAction(act);
+ }
+ }
+ }
+}
+
+void ActionEditWidget::clearWidget(QWidget *w)
+{
+ Q_ASSERT( w->isA("SingleActionWidget") );
+ SingleActionWidget *sw = dynamic_cast<SingleActionWidget*>(w);
+ if (sw)
+ sw->clear();
+}
+
+//============================================================================
+//
+// class RuleEditWidget (the widget to edit one rule)
+//
+//============================================================================
+RuleEditWidget::RuleEditWidget(KScoringManager *m,QWidget *p, const char *n)
+ : QWidget(p,n), dirty(false), manager(m), oldRuleName(QString::null)
+{
+ kdDebug(5100) << "RuleEditWidget::RuleEditWidget()" << endl;
+ if ( !n ) setName( "RuleEditWidget" );
+ QVBoxLayout *topLayout = new QVBoxLayout( this, 5, KDialog::spacingHint() );
+
+ //------------- Name, Servers, Groups ---------------------
+ QGroupBox *groupB = new QGroupBox(i18n("Properties"),this);
+ topLayout->addWidget(groupB);
+ QGridLayout* groupL = new QGridLayout(groupB, 6,2, 8,5);
+ groupL->addRowSpacing(0, fontMetrics().lineSpacing()-4);
+
+ // name
+ ruleNameEdit = new KLineEdit( groupB, "ruleNameEdit" );
+ groupL->addWidget( ruleNameEdit, 1, 1 );
+ QLabel *ruleNameLabel = new QLabel(ruleNameEdit, i18n("&Name:"), groupB, "ruleNameLabel");
+ groupL->addWidget( ruleNameLabel, 1, 0 );
+
+ // groups
+ groupsEdit = new KLineEdit( groupB, "groupsEdit" );
+ groupL->addWidget( groupsEdit, 2, 1 );
+ QLabel *groupsLabel = new QLabel(groupsEdit, i18n("&Groups:"), groupB, "groupsLabel");
+ groupL->addWidget( groupsLabel, 2, 0 );
+
+ QPushButton *groupsBtn = new QPushButton(i18n("A&dd Group"), groupB);
+ connect(groupsBtn,SIGNAL(clicked()),SLOT(slotAddGroup()));
+ groupL->addWidget( groupsBtn, 3, 0 );
+
+ groupsBox = new KComboBox( false, groupB, "groupsBox" );
+ groupsBox->setDuplicatesEnabled(false);
+ groupsBox->insertStringList(manager->getGroups());
+ groupsBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+ groupL->addWidget( groupsBox, 3, 1 );
+
+ // expires
+ expireCheck = new QCheckBox(i18n("&Expire rule automatically"), groupB);
+ groupL->addMultiCellWidget( expireCheck, 4,4, 0,1 );
+ expireEdit = new KIntSpinBox(1,99999,1,30,10, groupB, "expireWidget");
+ //Init suffix
+ slotExpireEditChanged(30);
+ connect(expireEdit, SIGNAL(valueChanged(int)), SLOT(slotExpireEditChanged(int)));
+ groupL->addWidget( expireEdit, 5, 1 );
+ expireLabel = new QLabel(expireEdit, i18n("&Rule is valid for:"), groupB, "expireLabel");
+ groupL->addWidget( expireLabel, 5, 0 );
+ expireLabel->setEnabled(false);
+ expireEdit->setEnabled(false);
+
+ connect(expireCheck, SIGNAL(toggled(bool)), expireLabel, SLOT(setEnabled(bool)));
+ connect(expireCheck, SIGNAL(toggled(bool)), expireEdit, SLOT(setEnabled(bool)));
+
+ //------------- Conditions ---------------------
+ QGroupBox *groupConds = new QGroupBox(i18n("Conditions"), this);
+ topLayout->addWidget(groupConds);
+ QGridLayout *condL = new QGridLayout(groupConds, 3,2, 8,5);
+
+ condL->addRowSpacing(0, fontMetrics().lineSpacing()-4);
+
+ QButtonGroup *buttonGroup = new QButtonGroup(groupConds);
+ buttonGroup->hide();
+ linkModeAnd = new QRadioButton(i18n("Match a&ll conditions"), groupConds);
+ buttonGroup->insert(linkModeAnd);
+ condL->addWidget(linkModeAnd, 1,0);
+ linkModeOr = new QRadioButton(i18n("Matc&h any condition"), groupConds);
+ buttonGroup->insert(linkModeOr);
+ condL->addWidget(linkModeOr, 1,1);
+ linkModeAnd->setChecked(true);
+
+ condEditor = new ConditionEditWidget(manager,groupConds);
+ condL->addMultiCellWidget(condEditor, 2,2, 0,1);
+ connect(condEditor,SIGNAL(widgetRemoved()),this,SLOT(slotShrink()));
+
+ //------------- Actions ---------------------
+ QGroupBox *groupActions = new QGroupBox(i18n("Actions"), this);
+ topLayout->addWidget(groupActions);
+ QBoxLayout *actionL = new QVBoxLayout(groupActions,8,5);
+ actionL->addSpacing(fontMetrics().lineSpacing()-4);
+ actionEditor = new ActionEditWidget(manager,groupActions);
+ actionL->addWidget(actionEditor);
+ connect(actionEditor,SIGNAL(widgetRemoved()),this,SLOT(slotShrink()));
+
+ topLayout->addStretch(1);
+
+ kdDebug(5100) << "constructed RuleEditWidget" << endl;
+}
+
+RuleEditWidget::~RuleEditWidget()
+{
+}
+
+void RuleEditWidget::slotEditRule(const QString& ruleName)
+{
+ kdDebug(5100) << "RuleEditWidget::slotEditRule(" << ruleName << ")" << endl;
+// // first update the old rule if there is one
+// kdDebug(5100) << "let see if we have a rule with name " << oldRuleName << endl;
+// KScoringRule *rule;
+// if (!oldRuleName.isNull() && oldRuleName != ruleName) {
+// rule = manager->findRule(oldRuleName);
+// if (rule) {
+// kdDebug(5100) << "updating rule " << rule->getName() << endl;
+// updateRule(rule);
+// }
+// }
+
+ KScoringRule* rule = manager->findRule(ruleName);
+ if (!rule) {
+ kdDebug(5100) << "no rule for ruleName " << ruleName << endl;
+ clearContents();
+ return;
+ }
+ oldRuleName = rule->getName();
+ ruleNameEdit->setText(rule->getName());
+ groupsEdit->setText(rule->getGroups().join(";"));
+
+ bool b = rule->getExpireDate().isValid();
+ expireCheck->setChecked(b);
+ expireEdit->setEnabled(b);
+ expireLabel->setEnabled(b);
+ if (b)
+ expireEdit->setValue(QDate::currentDate().daysTo(rule->getExpireDate()));
+ else
+ expireEdit->setValue(30);
+ if (rule->getLinkMode() == KScoringRule::AND) {
+ linkModeAnd->setChecked(true);
+ }
+ else {
+ linkModeOr->setChecked(true);
+ }
+
+ condEditor->slotEditRule(rule);
+ actionEditor->slotEditRule(rule);
+
+ kdDebug(5100) << "RuleEditWidget::slotEditRule() ready" << endl;
+}
+
+void RuleEditWidget::clearContents()
+{
+ ruleNameEdit->setText("");
+ groupsEdit->setText("");
+ expireCheck->setChecked(false);
+ expireEdit->setValue(30);
+ expireEdit->setEnabled(false);
+ condEditor->slotEditRule(0);
+ actionEditor->slotEditRule(0);
+ oldRuleName = QString::null;
+}
+
+void RuleEditWidget::updateRule(KScoringRule *rule)
+{
+ oldRuleName = QString::null;
+ QString groups = groupsEdit->text();
+ if (groups.isEmpty())
+ rule->setGroups(QStringList(".*"));
+ else
+ rule->setGroups(QStringList::split(";",groups));
+ bool b = expireCheck->isChecked();
+ if (b)
+ rule->setExpireDate(QDate::currentDate().addDays(expireEdit->value()));
+ else
+ rule->setExpireDate(QDate());
+ actionEditor->updateRule(rule);
+ rule->setLinkMode(linkModeAnd->isChecked()?KScoringRule::AND:KScoringRule::OR);
+ condEditor->updateRule(rule);
+ if (rule->getName() != ruleNameEdit->text())
+ manager->setRuleName(rule,ruleNameEdit->text());
+}
+
+void RuleEditWidget::updateRule()
+{
+ KScoringRule *rule = manager->findRule(oldRuleName);
+ if (rule) updateRule(rule);
+}
+
+void RuleEditWidget::slotAddGroup()
+{
+ QString grp = groupsBox->currentText();
+ if ( grp.isEmpty() )
+ return;
+ QString txt = groupsEdit->text().stripWhiteSpace();
+ if ( txt == ".*" || txt.isEmpty() ) groupsEdit->setText(grp);
+ else groupsEdit->setText(txt + ";" + grp);
+}
+
+void RuleEditWidget::setDirty()
+{
+ kdDebug(5100) << "RuleEditWidget::setDirty()" << endl;
+ if (dirty) return;
+ dirty = true;
+}
+
+void RuleEditWidget::slotShrink()
+{
+ emit(shrink());
+}
+
+void RuleEditWidget::slotExpireEditChanged(int value)
+{
+ expireEdit->setSuffix(i18n(" day", " days", value));
+}
+
+//============================================================================
+//
+// class RuleListWidget (the widget for managing a list of rules)
+//
+//============================================================================
+RuleListWidget::RuleListWidget(KScoringManager *m, bool standalone, QWidget *p, const char *n)
+ : QWidget(p,n), alone(standalone), manager(m)
+{
+ kdDebug(5100) << "RuleListWidget::RuleListWidget()" << endl;
+ if (!n) setName("RuleListWidget");
+ QVBoxLayout *topL = new QVBoxLayout(this,standalone? 0:5,KDialog::spacingHint());
+ ruleList = new KListBox(this);
+ if (standalone) {
+ connect(ruleList,SIGNAL(doubleClicked(QListBoxItem*)),
+ this,SLOT(slotEditRule(QListBoxItem*)));
+ connect(ruleList,SIGNAL(returnPressed(QListBoxItem*)),
+ this,SLOT(slotEditRule(QListBoxItem*)));
+ }
+ connect(ruleList, SIGNAL(currentChanged(QListBoxItem*)),
+ this, SLOT(slotRuleSelected(QListBoxItem*)));
+ topL->addWidget(ruleList);
+
+ QHBoxLayout *btnL = new QHBoxLayout( topL, KDialog::spacingHint() );
+ mRuleUp = new QPushButton( this );
+ mRuleUp->setPixmap( BarIcon( "up", KIcon::SizeSmall ) );
+ QToolTip::add( mRuleUp, i18n("Move rule up") );
+ btnL->addWidget( mRuleUp );
+ connect( mRuleUp, SIGNAL( clicked() ), SLOT( slotRuleUp() ) );
+ mRuleDown = new QPushButton( this );
+ mRuleDown->setPixmap( BarIcon( "down", KIcon::SizeSmall ) );
+ QToolTip::add( mRuleDown, i18n("Move rule down") );
+ btnL->addWidget( mRuleDown );
+ connect( mRuleDown, SIGNAL( clicked() ), SLOT( slotRuleDown() ) );
+
+ btnL = new QHBoxLayout( topL, KDialog::spacingHint() );
+ editRule=0L;
+ newRule = new QPushButton(this);
+ newRule->setPixmap( BarIcon( "filenew", KIcon::SizeSmall ) );
+ QToolTip::add(newRule,i18n("New rule")),
+ btnL->addWidget(newRule);
+ connect(newRule, SIGNAL(clicked()), this, SLOT(slotNewRule()));
+ // if we're standalone, we need an additional edit button
+ if (standalone) {
+ editRule = new QPushButton(this);
+ editRule->setIconSet( BarIconSet("edit", KIcon::SizeSmall) );
+ QToolTip::add(editRule,i18n("Edit rule"));
+ btnL->addWidget(editRule);
+ connect(editRule,SIGNAL(clicked()),this,SLOT(slotEditRule()));
+ }
+ delRule = new QPushButton(this);
+ delRule->setIconSet( BarIconSet( "editdelete", KIcon::SizeSmall ) );
+ QToolTip::add(delRule,i18n("Remove rule"));
+ btnL->addWidget(delRule);
+ connect(delRule, SIGNAL(clicked()), this, SLOT(slotDelRule()));
+ copyRule = new QPushButton(this);
+ copyRule->setIconSet(BarIconSet("editcopy", KIcon::SizeSmall));
+ QToolTip::add(copyRule,i18n("Copy rule"));
+ btnL->addWidget(copyRule);
+ connect(copyRule, SIGNAL(clicked()), this, SLOT(slotCopyRule()));
+
+ // the group filter
+ QBoxLayout *filterL = new QVBoxLayout(topL,KDialog::spacingHint());
+ KComboBox *filterBox = new KComboBox(this);
+ QStringList l = m->getGroups();
+ filterBox->insertItem(i18n("<all groups>"));
+ filterBox->insertStringList(l);
+ filterBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+ connect(filterBox,SIGNAL(activated(const QString&)),
+ this,SLOT(slotGroupFilter(const QString&)));
+ slotGroupFilter(i18n("<all groups>"));
+ QLabel *lab = new QLabel(filterBox,i18n("Sho&w only rules for group:"),this);
+ filterL->addWidget(lab);
+ filterL->addWidget(filterBox);
+
+ connect(manager,SIGNAL(changedRules()),
+ this,SLOT(updateRuleList()));
+ connect(manager,SIGNAL(changedRuleName(const QString&,const QString&)),
+ this,SLOT(slotRuleNameChanged(const QString&,const QString&)));
+
+ updateRuleList();
+ updateButton();
+}
+
+RuleListWidget::~RuleListWidget()
+{
+}
+
+void RuleListWidget::updateButton()
+{
+ bool state = ruleList->count() > 0;
+ if(editRule)
+ editRule->setEnabled(state);
+ delRule->setEnabled(state);
+ copyRule->setEnabled(state);
+
+ QListBoxItem *item = ruleList->item( ruleList->currentItem() );
+ if ( item ) {
+ mRuleUp->setEnabled( item->prev() != 0 );
+ mRuleDown->setEnabled( item->next() != 0 );
+ }
+}
+
+void RuleListWidget::updateRuleList()
+{
+ emit leavingRule();
+ kdDebug(5100) << "RuleListWidget::updateRuleList()" << endl;
+ QString curr = ruleList->currentText();
+ ruleList->clear();
+ if (group == i18n("<all groups>")) {
+ QStringList l = manager->getRuleNames();
+ ruleList->insertStringList(l);
+ } else {
+ KScoringManager::ScoringRuleList l = manager->getAllRules();
+ for (KScoringRule* rule = l.first(); rule; rule = l.next() ) {
+ if (rule->matchGroup(group)) ruleList->insertItem(rule->getName());
+ }
+ }
+ int index = setCurrentItem(ruleList,curr);
+ if (index <0) {
+ ruleList->setCurrentItem(0);
+ slotRuleSelected(ruleList->currentText());
+ }
+ else {
+ slotRuleSelected(curr);
+ }
+}
+
+void RuleListWidget::updateRuleList(const KScoringRule *rule)
+{
+ kdDebug(5100) << "RuleListWidget::updateRuleList(" << rule->getName() << ")" << endl;
+ QString name = rule->getName();
+ updateRuleList();
+ slotRuleSelected(name);
+}
+
+void RuleListWidget::slotRuleNameChanged(const QString& oldName, const QString& newName)
+{
+ int ind = ruleList->currentItem();
+ for (uint i=0;i<ruleList->count();++i)
+ if (ruleList->text(i) == oldName) {
+ ruleList->changeItem(newName,i);
+ ruleList->setCurrentItem(ind);
+ return;
+ }
+}
+
+void RuleListWidget::slotEditRule(const QString& s)
+{
+ emit ruleEdited(s);
+}
+
+void RuleListWidget::slotEditRule()
+{
+ if (ruleList->currentItem() >= 0) {
+ emit ruleEdited(ruleList->currentText());
+ }
+ else if (ruleList->count() == 0)
+ emit ruleEdited(QString::null);
+}
+
+void RuleListWidget::slotEditRule(QListBoxItem* item)
+{
+ slotEditRule(item->text());
+}
+
+void RuleListWidget::slotGroupFilter(const QString& s)
+{
+ group = s;
+ updateRuleList();
+}
+
+void RuleListWidget::slotRuleSelected(const QString& ruleName)
+{
+ emit leavingRule();
+ kdDebug(5100) << "RuleListWidget::slotRuleSelected(" << ruleName << ")" << endl;
+ if (ruleName != ruleList->currentText()) {
+ setCurrentItem(ruleList,ruleName);
+ }
+ updateButton();
+ emit ruleSelected(ruleName);
+}
+
+void RuleListWidget::slotRuleSelected(QListBoxItem *item)
+{
+ if (!item) return;
+ QString ruleName = item->text();
+ slotRuleSelected(ruleName);
+}
+
+void RuleListWidget::slotRuleSelected(int index)
+{
+ uint idx = index;
+ if (idx >= ruleList->count()) return;
+ QString ruleName = ruleList->text(index);
+ slotRuleSelected(ruleName);
+}
+
+void RuleListWidget::slotNewRule()
+{
+ emit leavingRule();
+ KScoringRule *rule = manager->addRule();
+ updateRuleList(rule);
+ if (alone) slotEditRule(rule->getName());
+ updateButton();
+}
+
+void RuleListWidget::slotDelRule()
+{
+ KScoringRule *rule = manager->findRule(ruleList->currentText());
+ if (rule)
+ manager->deleteRule(rule);
+ // goto the next rule
+ if (!alone) slotEditRule();
+ updateButton();
+}
+
+void RuleListWidget::slotCopyRule()
+{
+ emit leavingRule();
+ QString ruleName = ruleList->currentText();
+ KScoringRule *rule = manager->findRule(ruleName);
+ if (rule) {
+ KScoringRule *nrule = manager->copyRule(rule);
+ updateRuleList(nrule);
+ slotEditRule(nrule->getName());
+ }
+ updateButton();
+}
+
+void RuleListWidget::slotRuleUp()
+{
+ KScoringRule *rule = 0, *below = 0;
+ QListBoxItem *item = ruleList->item( ruleList->currentItem() );
+ if ( item ) {
+ rule = manager->findRule( item->text() );
+ item = item->prev();
+ if ( item )
+ below = manager->findRule( item->text() );
+ }
+ if ( rule && below )
+ manager->moveRuleAbove( rule, below );
+ updateRuleList();
+ updateButton();
+}
+
+void RuleListWidget::slotRuleDown()
+{
+ KScoringRule *rule = 0, *above = 0;
+ QListBoxItem *item = ruleList->item( ruleList->currentItem() );
+ if ( item ) {
+ rule = manager->findRule( item->text() );
+ item = item->next();
+ if ( item )
+ above = manager->findRule( item->text() );
+ }
+ if ( rule && above )
+ manager->moveRuleBelow( rule, above );
+ updateRuleList();
+ updateButton();
+}
+
+//============================================================================
+//
+// class KScoringEditor (the score edit dialog)
+//
+//============================================================================
+KScoringEditor* KScoringEditor::scoreEditor = 0;
+
+KScoringEditor::KScoringEditor(KScoringManager* m,
+ QWidget *parent, const char *name)
+ : KDialogBase(parent,name,false,i18n("Rule Editor"),Ok|Apply|Cancel,Ok,true), manager(m)
+{
+ manager->pushRuleList();
+ if (!scoreEditor) scoreEditor = this;
+ kdDebug(5100) << "KScoringEditor::KScoringEditor()" << endl;
+ if (!name) setName("KScoringEditor");
+ // the left side gives an overview about all rules, the right side
+ // shows a detailed view of an selected rule
+ QWidget *w = new QWidget(this);
+ setMainWidget(w);
+ QHBoxLayout *hbl = new QHBoxLayout(w,0,spacingHint());
+ ruleLister = new RuleListWidget(manager,false,w);
+ hbl->addWidget(ruleLister);
+ ruleEditor = new RuleEditWidget(manager,w);
+ hbl->addWidget(ruleEditor);
+ connect(ruleLister,SIGNAL(ruleSelected(const QString&)),
+ ruleEditor, SLOT(slotEditRule(const QString&)));
+ connect(ruleLister, SIGNAL(leavingRule()),
+ ruleEditor, SLOT(updateRule()));
+ connect(ruleEditor, SIGNAL(shrink()), SLOT(slotShrink()));
+ connect(this,SIGNAL(finished()),SLOT(slotFinished()));
+ ruleLister->slotRuleSelected(0);
+ resize(550, sizeHint().height());
+}
+
+void KScoringEditor::setDirty()
+{
+ QPushButton *applyBtn = actionButton(Apply);
+ applyBtn->setEnabled(true);
+}
+
+KScoringEditor::~KScoringEditor()
+{
+ scoreEditor = 0;
+}
+
+KScoringEditor* KScoringEditor::createEditor(KScoringManager* m,
+ QWidget *parent, const char *name)
+{
+ if (scoreEditor) return scoreEditor;
+ else return new KScoringEditor(m,parent,name);
+}
+
+void KScoringEditor::setRule(KScoringRule* r)
+{
+ kdDebug(5100) << "KScoringEditor::setRule(" << r->getName() << ")" << endl;
+ QString ruleName = r->getName();
+ ruleLister->slotRuleSelected(ruleName);
+}
+
+void KScoringEditor::slotShrink()
+{
+ QTimer::singleShot(5, this, SLOT(slotDoShrink()));
+}
+
+void KScoringEditor::slotDoShrink()
+{
+ updateGeometry();
+ QApplication::sendPostedEvents();
+ resize(width(),sizeHint().height());
+}
+
+void KScoringEditor::slotApply()
+{
+ QString ruleName = ruleLister->currentRule();
+ KScoringRule *rule = manager->findRule(ruleName);
+ if (rule) {
+ ruleEditor->updateRule(rule);
+ ruleLister->updateRuleList(rule);
+ }
+ manager->removeTOS();
+ manager->pushRuleList();
+}
+
+void KScoringEditor::slotOk()
+{
+ slotApply();
+ manager->removeTOS();
+ KDialogBase::slotOk();
+ manager->editorReady();
+}
+
+void KScoringEditor::slotCancel()
+{
+ manager->popRuleList();
+ KDialogBase::slotCancel();
+}
+
+void KScoringEditor::slotFinished()
+{
+ delayedDestruct();
+}
+
+//============================================================================
+//
+// class KScoringEditorWidgetDialog (a dialog for the KScoringEditorWidget)
+//
+//============================================================================
+KScoringEditorWidgetDialog::KScoringEditorWidgetDialog(KScoringManager *m, const QString& r, QWidget *p, const char *n)
+ : KDialogBase(p,n,true,i18n("Edit Rule"),
+ KDialogBase::Ok|KDialogBase::Apply|KDialogBase::Close,
+ KDialogBase::Ok,true),
+ manager(m), ruleName(r)
+{
+ QFrame *f = makeMainWidget();
+ QBoxLayout *topL = new QVBoxLayout(f);
+ ruleEditor = new RuleEditWidget(manager,f);
+ connect(ruleEditor, SIGNAL(shrink()), SLOT(slotShrink()));
+ topL->addWidget(ruleEditor);
+ ruleEditor->slotEditRule(ruleName);
+ resize(0,0);
+}
+
+void KScoringEditorWidgetDialog::slotApply()
+{
+ KScoringRule *rule = manager->findRule(ruleName);
+ if (rule) {
+ ruleEditor->updateRule(rule);
+ ruleName = rule->getName();
+ }
+}
+
+void KScoringEditorWidgetDialog::slotOk()
+{
+ slotApply();
+ KDialogBase::slotOk();
+}
+
+void KScoringEditorWidgetDialog::slotShrink()
+{
+ QTimer::singleShot(5, this, SLOT(slotDoShrink()));
+}
+
+void KScoringEditorWidgetDialog::slotDoShrink()
+{
+ updateGeometry();
+ QApplication::sendPostedEvents();
+ resize(width(),sizeHint().height());
+}
+
+//============================================================================
+//
+// class KScoringEditorWidget (a reusable widget for config dialog...)
+//
+//============================================================================
+KScoringEditorWidget::KScoringEditorWidget(KScoringManager *m,QWidget *p, const char *n)
+ : QWidget(p,n), manager(m)
+{
+ QBoxLayout *topL = new QVBoxLayout(this);
+ ruleLister = new RuleListWidget(manager,true,this);
+ topL->addWidget(ruleLister);
+ connect(ruleLister,SIGNAL(ruleEdited(const QString&)),
+ this,SLOT(slotRuleEdited(const QString &)));
+}
+
+KScoringEditorWidget::~KScoringEditorWidget()
+{
+ manager->editorReady();
+}
+
+void KScoringEditorWidget::slotRuleEdited(const QString& ruleName)
+{
+ KScoringEditorWidgetDialog dlg(manager,ruleName,this);
+ dlg.exec();
+ ruleLister->updateRuleList();
+}
+
+#include "kscoringeditor.moc"