libkdepim

kscoringeditor.cpp

00001 /*
00002     kscoringeditor.cpp
00003 
00004     Copyright (c) 2001 Mathias Waack
00005     Copyright (C) 2005 by Volker Krause <volker.krause@rwth-aachen.de>
00006 
00007     Author: Mathias Waack <mathias@atoll-net.de>
00008 
00009     This program is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013     You should have received a copy of the GNU General Public License
00014     along with this program; if not, write to the Free Software Foundation,
00015     Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US
00016 */
00017 
00018 #undef QT_NO_COMPAT
00019 
00020 #include "kscoring.h"
00021 #include "kscoringeditor.h"
00022 
00023 #include <kdebug.h>
00024 #include <klocale.h>
00025 #include <kcombobox.h>
00026 #include <kcolorcombo.h>
00027 #include <kiconloader.h>
00028 #include <kregexpeditorinterface.h>
00029 #include <ktrader.h>
00030 #include <kparts/componentfactory.h>
00031 
00032 
00033 #include <qlabel.h>
00034 #include <qpushbutton.h>
00035 #include <qlayout.h>
00036 #include <qtooltip.h>
00037 #include <qcheckbox.h>
00038 #include <qbuttongroup.h>
00039 #include <qradiobutton.h>
00040 #include <qwidgetstack.h>
00041 #include <qapplication.h>
00042 #include <qtimer.h>
00043 #include <qhbox.h>
00044 
00045 // works for both ListBox and ComboBox
00046 template <class T> static int setCurrentItem(T *box, const QString& s)
00047 {
00048   int cnt = box->count();
00049   for (int i=0;i<cnt;++i) {
00050     if (box->text(i) == s) {
00051       box->setCurrentItem(i);
00052       return i;
00053     }
00054   }
00055   return -1;
00056 }
00057 
00058 
00059 //============================================================================
00060 //
00061 // class SingleConditionWidget (editor for one condition, used in ConditionEditWidget)
00062 //
00063 //============================================================================
00064 SingleConditionWidget::SingleConditionWidget(KScoringManager *m,QWidget *p, const char *n)
00065   : QFrame(p,n), manager(m)
00066 {
00067   QBoxLayout *topL = new QVBoxLayout(this,5);
00068   QBoxLayout *firstRow = new QHBoxLayout(topL);
00069   neg = new QCheckBox(i18n("Not"),this);
00070   QToolTip::add(neg,i18n("Negate this condition"));
00071   firstRow->addWidget(neg);
00072   headers = new KComboBox(this);
00073   headers->insertStringList(manager->getDefaultHeaders());
00074   headers->setEditable( true );
00075   QToolTip::add(headers,i18n("Select the header to match this condition against"));
00076   firstRow->addWidget(headers,1);
00077   matches = new KComboBox(this);
00078   matches->insertStringList(KScoringExpression::conditionNames());
00079   QToolTip::add(matches,i18n("Select the type of match"));
00080   firstRow->addWidget(matches,1);
00081   connect( matches, SIGNAL( activated( int ) ), SLOT( toggleRegExpButton( int ) ) );
00082   QHBoxLayout *secondRow = new QHBoxLayout( topL );
00083   secondRow->setSpacing( 1 );
00084   expr = new KLineEdit( this );
00085   QToolTip::add(expr,i18n("The condition for the match"));
00086   // reserve space for at least 20 characters
00087   expr->setMinimumWidth(fontMetrics().maxWidth()*20);
00088   secondRow->addWidget( expr );
00089   regExpButton = new QPushButton( i18n("Edit..."), this );
00090   secondRow->addWidget( regExpButton );
00091   connect( regExpButton, SIGNAL( clicked() ), SLOT( showRegExpDialog() ) );
00092 
00093   // occupy at much width as possible
00094   setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed));
00095   setFrameStyle(Box | Sunken);
00096   setLineWidth(1);
00097 }
00098 
00099 SingleConditionWidget::~SingleConditionWidget()
00100 {}
00101 
00102 void SingleConditionWidget::setCondition(KScoringExpression *e)
00103 {
00104   neg->setChecked(e->isNeg());
00105   headers->setCurrentText( e->getHeader() );
00106   setCurrentItem(matches,KScoringExpression::getNameForCondition(e->getCondition()));
00107   toggleRegExpButton( matches->currentItem() );
00108   expr->setText(e->getExpression());
00109 }
00110 
00111 KScoringExpression* SingleConditionWidget::createCondition() const
00112 {
00113   QString head = headers->currentText();
00114   QString match = matches->currentText();
00115   int condType = KScoringExpression::getConditionForName(match);
00116   match = KScoringExpression::getTypeString(condType);
00117   QString cond = expr->text();
00118   QString negs = (neg->isChecked())?"1":"0";
00119   return new KScoringExpression(head,match,cond,negs);
00120 }
00121 
00122 void SingleConditionWidget::clear()
00123 {
00124   neg->setChecked(false);
00125   expr->clear();
00126 }
00127 
00128 void SingleConditionWidget::toggleRegExpButton( int selected )
00129 {
00130   bool isRegExp = KScoringExpression::MATCH == selected &&
00131       KScoringExpression::MATCHCS == selected &&
00132       !KTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty();
00133   regExpButton->setEnabled( isRegExp );
00134 }
00135 
00136 void SingleConditionWidget::showRegExpDialog()
00137 {
00138   QDialog *editorDialog = KParts::ComponentFactory::createInstanceFromQuery<QDialog>( "KRegExpEditor/KRegExpEditor" );
00139   if ( editorDialog ) {
00140     KRegExpEditorInterface *editor = static_cast<KRegExpEditorInterface *>( editorDialog->qt_cast( "KRegExpEditorInterface" ) );
00141     Q_ASSERT( editor ); // This should not fail!
00142     editor->setRegExp( expr->text() );
00143     editorDialog->exec();
00144     expr->setText( editor->regExp() );
00145   }
00146 }
00147 
00148 //============================================================================
00149 //
00150 // class ConditionEditWidget (the widget to edit the conditions of a rule)
00151 //
00152 //============================================================================
00153 ConditionEditWidget::ConditionEditWidget(KScoringManager *m, QWidget *p, const char *n)
00154   : KWidgetLister(1,8,p,n), manager(m)
00155 {
00156   // create one initial widget
00157   addWidgetAtEnd();
00158 }
00159 
00160 ConditionEditWidget::~ConditionEditWidget()
00161 {}
00162 
00163 QWidget* ConditionEditWidget::createWidget(QWidget *parent)
00164 {
00165   return new SingleConditionWidget(manager,parent);
00166 }
00167 
00168 void ConditionEditWidget::clearWidget(QWidget *w)
00169 {
00170   Q_ASSERT( w->isA("SingleConditionWidget") );
00171   SingleConditionWidget *sw = dynamic_cast<SingleConditionWidget*>(w);
00172   if (sw)
00173     sw->clear();
00174 }
00175 
00176 void ConditionEditWidget::slotEditRule(KScoringRule *rule)
00177 {
00178   KScoringRule::ScoreExprList l;
00179   if (rule) l = rule->getExpressions();
00180   if (!rule || l.count() == 0) {
00181     slotClear();
00182   } else {
00183     setNumberOfShownWidgetsTo(l.count());
00184     KScoringExpression *e = l.first();
00185     SingleConditionWidget *scw = static_cast<SingleConditionWidget*>(mWidgetList.first());
00186     while (e && scw) {
00187       scw->setCondition(e);
00188       e = l.next();
00189       scw = static_cast<SingleConditionWidget*>(mWidgetList.next());
00190     }
00191   }
00192 }
00193 
00194 void ConditionEditWidget::updateRule(KScoringRule *rule)
00195 {
00196   rule->cleanExpressions();
00197   for(QWidget *w = mWidgetList.first(); w; w = mWidgetList.next()) {
00198     if (! w->isA("SingleConditionWidget")) {
00199       kdWarning(5100) << "there is a widget in ConditionEditWidget "
00200                       << "which isn't a SingleConditionWidget" << endl;
00201     } else {
00202       SingleConditionWidget *saw = dynamic_cast<SingleConditionWidget*>(w);
00203       if (saw)
00204         rule->addExpression(saw->createCondition());
00205     }
00206   }
00207 }
00208 
00209 //============================================================================
00210 //
00211 // class SingleActionWidget (editor for one action, used in ActionEditWidget)
00212 //
00213 //============================================================================
00214 SingleActionWidget::SingleActionWidget(KScoringManager *m,QWidget *p, const char *n)
00215   : QWidget(p,n), notifyEditor(0), scoreEditor(0), colorEditor(0),manager(m)
00216 {
00217   QHBoxLayout *topL = new QHBoxLayout(this,0,5);
00218   types = new KComboBox(this);
00219   types->setEditable(false);
00220   topL->addWidget(types);
00221   stack = new QWidgetStack(this);
00222   topL->addWidget(stack);
00223 
00224   dummyLabel = new QLabel(i18n("Select an action."), stack);
00225   stack->addWidget(dummyLabel, 0);
00226 
00227   // init widget stack and the types combo box
00228   int index = 1;
00229   types->insertItem(QString::null);
00230   QStringList l = ActionBase::userNames();
00231   for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
00232     QString name = *it;
00233     int feature = ActionBase::getTypeForUserName(name);
00234     if (manager->hasFeature(feature)) {
00235       types->insertItem(name);
00236       QWidget *w=0;
00237       switch (feature) {
00238         case ActionBase::SETSCORE:
00239           w = scoreEditor = new KIntSpinBox(-99999,99999,1,0,10, stack);
00240           break;
00241         case ActionBase::NOTIFY:
00242           w = notifyEditor = new KLineEdit(stack);
00243           break;
00244         case ActionBase::COLOR:
00245           w = colorEditor = new KColorCombo(stack);
00246           break;
00247         case ActionBase::MARKASREAD:
00248           w = new QLabel( stack ); // empty dummy
00249           break;
00250       }
00251       stack->addWidget(w,index++);
00252     }
00253   }
00254 
00255   connect(types,SIGNAL(activated(int)),stack,SLOT(raiseWidget(int)));
00256 
00257   // raise the dummy label
00258   types->setCurrentItem(0);
00259   stack->raiseWidget(dummyLabel);
00260 }
00261 
00262 SingleActionWidget::~SingleActionWidget()
00263 {
00264 }
00265 
00266 void SingleActionWidget::setAction(ActionBase *act)
00267 {
00268   kdDebug(5100) << "SingleActionWidget::setAction()" << endl;
00269   setCurrentItem(types,ActionBase::userName(act->getType()));
00270   int index = types->currentItem();
00271   stack->raiseWidget(index);
00272   switch (act->getType()) {
00273     case ActionBase::SETSCORE:
00274       scoreEditor->setValue(act->getValueString().toInt());
00275       break;
00276     case ActionBase::NOTIFY:
00277       notifyEditor->setText(act->getValueString());
00278       break;
00279     case ActionBase::COLOR:
00280       colorEditor->setColor(QColor(act->getValueString()));
00281       break;
00282     case ActionBase::MARKASREAD:
00283       // nothing
00284       break;
00285     default:
00286       kdWarning(5100) << "unknown action type in SingleActionWidget::setAction()" << endl;
00287   }
00288 }
00289 
00290 ActionBase* SingleActionWidget::createAction() const
00291 {
00292   // no action selected...
00293   if (types->currentText().isEmpty())
00294     return 0;
00295 
00296   int type = ActionBase::getTypeForUserName(types->currentText());
00297   switch (type) {
00298     case ActionBase::SETSCORE:
00299       return new ActionSetScore(scoreEditor->value());
00300     case ActionBase::NOTIFY:
00301       return new ActionNotify(notifyEditor->text());
00302     case ActionBase::COLOR:
00303       return new ActionColor(colorEditor->color().name());
00304     case ActionBase::MARKASREAD:
00305       return new ActionMarkAsRead();
00306     default:
00307       kdWarning(5100) << "unknown action type in SingleActionWidget::getValue()" << endl;
00308       return 0;
00309   }
00310 }
00311 
00312 void SingleActionWidget::clear()
00313 {
00314   if (scoreEditor) scoreEditor->setValue(0);
00315   if (notifyEditor) notifyEditor->clear();
00316   if (colorEditor) colorEditor->setCurrentItem(0);
00317   types->setCurrentItem(0);
00318   stack->raiseWidget(dummyLabel);
00319 }
00320 
00321 //============================================================================
00322 //
00323 // class ActionEditWidget (the widget to edit the actions of a rule)
00324 //
00325 //============================================================================
00326 ActionEditWidget::ActionEditWidget(KScoringManager *m,QWidget *p, const char *n)
00327   : KWidgetLister(1,8,p,n), manager(m)
00328 {
00329   // create one initial widget
00330   addWidgetAtEnd();
00331 }
00332 
00333 ActionEditWidget::~ActionEditWidget()
00334 {}
00335 
00336 QWidget* ActionEditWidget::createWidget( QWidget *parent )
00337 {
00338   return new SingleActionWidget(manager,parent);
00339 }
00340 
00341 void ActionEditWidget::slotEditRule(KScoringRule *rule)
00342 {
00343   KScoringRule::ActionList l;
00344   if (rule) l = rule->getActions();
00345   if (!rule || l.count() == 0) {
00346     slotClear();
00347   } else {
00348     setNumberOfShownWidgetsTo(l.count());
00349     ActionBase *act = l.first();
00350     SingleActionWidget *saw = static_cast<SingleActionWidget*>(mWidgetList.first());
00351     while (act && saw) {
00352       saw->setAction(act);
00353       act = l.next();
00354       saw = static_cast<SingleActionWidget*>(mWidgetList.next());
00355     }
00356   }
00357 }
00358 
00359 void ActionEditWidget::updateRule(KScoringRule *rule)
00360 {
00361   rule->cleanActions();
00362   for(QWidget *w = mWidgetList.first(); w; w = mWidgetList.next()) {
00363     if (! w->isA("SingleActionWidget")) {
00364       kdWarning(5100) << "there is a widget in ActionEditWidget "
00365                       << "which isn't a SingleActionWidget" << endl;
00366     } else {
00367       SingleActionWidget *saw = dynamic_cast<SingleActionWidget*>(w);
00368       if (saw)
00369       {
00370         ActionBase *act = saw->createAction();
00371         if (act)
00372           rule->addAction(act);
00373       }
00374     }
00375   }
00376 }
00377 
00378 void ActionEditWidget::clearWidget(QWidget *w)
00379 {
00380   Q_ASSERT( w->isA("SingleActionWidget") );
00381   SingleActionWidget *sw = dynamic_cast<SingleActionWidget*>(w);
00382   if (sw)
00383     sw->clear();
00384 }
00385 
00386 //============================================================================
00387 //
00388 // class RuleEditWidget (the widget to edit one rule)
00389 //
00390 //============================================================================
00391 RuleEditWidget::RuleEditWidget(KScoringManager *m,QWidget *p, const char *n)
00392   : QWidget(p,n), dirty(false), manager(m), oldRuleName(QString::null)
00393 {
00394   kdDebug(5100) << "RuleEditWidget::RuleEditWidget()" << endl;
00395   if ( !n ) setName( "RuleEditWidget" );
00396   QVBoxLayout *topLayout = new QVBoxLayout( this, 5, KDialog::spacingHint() );
00397 
00398   //------------- Name, Servers, Groups ---------------------
00399   QGroupBox *groupB = new QGroupBox(i18n("Properties"),this);
00400   topLayout->addWidget(groupB);
00401   QGridLayout* groupL = new QGridLayout(groupB, 6,2, 8,5);
00402   groupL->addRowSpacing(0, fontMetrics().lineSpacing()-4);
00403 
00404   // name
00405   ruleNameEdit = new KLineEdit( groupB, "ruleNameEdit" );
00406   groupL->addWidget( ruleNameEdit, 1, 1 );
00407   QLabel *ruleNameLabel = new QLabel(ruleNameEdit, i18n("&Name:"), groupB, "ruleNameLabel");
00408   groupL->addWidget( ruleNameLabel, 1, 0 );
00409 
00410   // groups
00411   groupsEdit = new KLineEdit( groupB, "groupsEdit" );
00412   groupL->addWidget( groupsEdit, 2, 1 );
00413   QLabel *groupsLabel = new QLabel(groupsEdit, i18n("&Groups:"), groupB, "groupsLabel");
00414   groupL->addWidget( groupsLabel, 2, 0 );
00415 
00416   QPushButton *groupsBtn = new QPushButton(i18n("A&dd Group"), groupB);
00417   connect(groupsBtn,SIGNAL(clicked()),SLOT(slotAddGroup()));
00418   groupL->addWidget( groupsBtn, 3, 0 );
00419 
00420   groupsBox = new KComboBox( false, groupB, "groupsBox" );
00421   groupsBox->setDuplicatesEnabled(false);
00422   groupsBox->insertStringList(manager->getGroups());
00423   groupsBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
00424   groupL->addWidget( groupsBox, 3, 1 );
00425 
00426   // expires
00427   expireCheck = new QCheckBox(i18n("&Expire rule automatically"), groupB);
00428   groupL->addMultiCellWidget( expireCheck, 4,4, 0,1 );
00429   expireEdit = new KIntSpinBox(1,99999,1,30,10, groupB, "expireWidget");
00430   expireEdit->setSuffix(i18n(" days"));
00431   groupL->addWidget( expireEdit, 5, 1 );
00432   expireLabel = new QLabel(expireEdit, i18n("&Rule is valid for:"), groupB, "expireLabel");
00433   groupL->addWidget( expireLabel, 5, 0 );
00434   expireLabel->setEnabled(false);
00435   expireEdit->setEnabled(false);
00436 
00437   connect(expireCheck, SIGNAL(toggled(bool)), expireLabel, SLOT(setEnabled(bool)));
00438   connect(expireCheck, SIGNAL(toggled(bool)), expireEdit, SLOT(setEnabled(bool)));
00439 
00440   //------------- Conditions ---------------------
00441   QGroupBox *groupConds = new QGroupBox(i18n("Conditions"), this);
00442   topLayout->addWidget(groupConds);
00443   QGridLayout *condL = new QGridLayout(groupConds, 3,2, 8,5);
00444 
00445   condL->addRowSpacing(0, fontMetrics().lineSpacing()-4);
00446 
00447   QButtonGroup *buttonGroup = new QButtonGroup(groupConds);
00448   buttonGroup->hide();
00449   linkModeAnd = new QRadioButton(i18n("Match a&ll conditions"), groupConds);
00450   buttonGroup->insert(linkModeAnd);
00451   condL->addWidget(linkModeAnd, 1,0);
00452   linkModeOr = new QRadioButton(i18n("Matc&h any condition"), groupConds);
00453   buttonGroup->insert(linkModeOr);
00454   condL->addWidget(linkModeOr, 1,1);
00455   linkModeAnd->setChecked(true);
00456 
00457   condEditor = new ConditionEditWidget(manager,groupConds);
00458   condL->addMultiCellWidget(condEditor, 2,2, 0,1);
00459   connect(condEditor,SIGNAL(widgetRemoved()),this,SLOT(slotShrink()));
00460 
00461   //------------- Actions ---------------------
00462   QGroupBox *groupActions = new QGroupBox(i18n("Actions"), this);
00463   topLayout->addWidget(groupActions);
00464   QBoxLayout *actionL = new QVBoxLayout(groupActions,8,5);
00465   actionL->addSpacing(fontMetrics().lineSpacing()-4);
00466   actionEditor = new ActionEditWidget(manager,groupActions);
00467   actionL->addWidget(actionEditor);
00468   connect(actionEditor,SIGNAL(widgetRemoved()),this,SLOT(slotShrink()));
00469 
00470   topLayout->addStretch(1);
00471 
00472   kdDebug(5100) << "constructed RuleEditWidget" << endl;
00473 }
00474 
00475 RuleEditWidget::~RuleEditWidget()
00476 {
00477 }
00478 
00479 void RuleEditWidget::slotEditRule(const QString& ruleName)
00480 {
00481   kdDebug(5100) << "RuleEditWidget::slotEditRule(" << ruleName << ")" << endl;
00482 //   // first update the old rule if there is one
00483 //   kdDebug(5100) << "let see if we have a rule with name " << oldRuleName << endl;
00484 //   KScoringRule *rule;
00485 //   if (!oldRuleName.isNull() && oldRuleName != ruleName) {
00486 //     rule = manager->findRule(oldRuleName);
00487 //     if (rule) {
00488 //       kdDebug(5100) << "updating rule " << rule->getName() << endl;
00489 //       updateRule(rule);
00490 //     }
00491 //   }
00492 
00493   KScoringRule* rule = manager->findRule(ruleName);
00494   if (!rule) {
00495     kdDebug(5100) << "no rule for ruleName " << ruleName << endl;
00496     clearContents();
00497     return;
00498   }
00499   oldRuleName = rule->getName();
00500   ruleNameEdit->setText(rule->getName());
00501   groupsEdit->setText(rule->getGroups().join(";"));
00502 
00503   bool b = rule->getExpireDate().isValid();
00504   expireCheck->setChecked(b);
00505   expireEdit->setEnabled(b);
00506   expireLabel->setEnabled(b);
00507   if (b)
00508     expireEdit->setValue(QDate::currentDate().daysTo(rule->getExpireDate()));
00509   else
00510     expireEdit->setValue(30);
00511   if (rule->getLinkMode() == KScoringRule::AND) {
00512     linkModeAnd->setChecked(true);
00513   }
00514   else {
00515     linkModeOr->setChecked(true);
00516   }
00517 
00518   condEditor->slotEditRule(rule);
00519   actionEditor->slotEditRule(rule);
00520 
00521   kdDebug(5100) << "RuleEditWidget::slotEditRule() ready" << endl;
00522 }
00523 
00524 void RuleEditWidget::clearContents()
00525 {
00526   ruleNameEdit->setText("");
00527   groupsEdit->setText("");
00528   expireCheck->setChecked(false);
00529   expireEdit->setValue(30);
00530   expireEdit->setEnabled(false);
00531   condEditor->slotEditRule(0);
00532   actionEditor->slotEditRule(0);
00533   oldRuleName = QString::null;
00534 }
00535 
00536 void RuleEditWidget::updateRule(KScoringRule *rule)
00537 {
00538   oldRuleName = QString::null;
00539   QString groups = groupsEdit->text();
00540   if (groups.isEmpty())
00541     rule->setGroups(QStringList(".*"));
00542   else
00543     rule->setGroups(QStringList::split(";",groups));
00544   bool b = expireCheck->isChecked();
00545   if (b)
00546     rule->setExpireDate(QDate::currentDate().addDays(expireEdit->value()));
00547   else
00548     rule->setExpireDate(QDate());
00549   actionEditor->updateRule(rule);
00550   rule->setLinkMode(linkModeAnd->isChecked()?KScoringRule::AND:KScoringRule::OR);
00551   condEditor->updateRule(rule);
00552   if (rule->getName() != ruleNameEdit->text())
00553     manager->setRuleName(rule,ruleNameEdit->text());
00554 }
00555 
00556 void RuleEditWidget::updateRule()
00557 {
00558   KScoringRule *rule = manager->findRule(oldRuleName);
00559   if (rule) updateRule(rule);
00560 }
00561 
00562 void RuleEditWidget::slotAddGroup()
00563 {
00564   QString grp = groupsBox->currentText();
00565   if ( grp.isEmpty() )
00566       return;
00567   QString txt = groupsEdit->text().stripWhiteSpace();
00568   if ( txt == ".*" || txt.isEmpty() ) groupsEdit->setText(grp);
00569   else groupsEdit->setText(txt + ";" + grp);
00570 }
00571 
00572 void RuleEditWidget::setDirty()
00573 {
00574   kdDebug(5100) << "RuleEditWidget::setDirty()" << endl;
00575   if (dirty) return;
00576   dirty = true;
00577 }
00578 
00579 void RuleEditWidget::slotShrink()
00580 {
00581   emit(shrink());
00582 }
00583 
00584 //============================================================================
00585 //
00586 // class RuleListWidget (the widget for managing a list of rules)
00587 //
00588 //============================================================================
00589 RuleListWidget::RuleListWidget(KScoringManager *m, bool standalone, QWidget *p, const char *n)
00590   : QWidget(p,n), alone(standalone), manager(m)
00591 {
00592   kdDebug(5100) << "RuleListWidget::RuleListWidget()" << endl;
00593   if (!n) setName("RuleListWidget");
00594   QVBoxLayout *topL = new QVBoxLayout(this,standalone? 0:5,KDialog::spacingHint());
00595   ruleList = new KListBox(this);
00596   if (standalone) {
00597     connect(ruleList,SIGNAL(doubleClicked(QListBoxItem*)),
00598             this,SLOT(slotEditRule(QListBoxItem*)));
00599     connect(ruleList,SIGNAL(returnPressed(QListBoxItem*)),
00600             this,SLOT(slotEditRule(QListBoxItem*)));
00601   }
00602   connect(ruleList, SIGNAL(currentChanged(QListBoxItem*)),
00603           this, SLOT(slotRuleSelected(QListBoxItem*)));
00604   topL->addWidget(ruleList);
00605 
00606   QHBoxLayout *btnL = new QHBoxLayout( topL, KDialog::spacingHint() );
00607   mRuleUp = new QPushButton( this );
00608   mRuleUp->setPixmap( BarIcon( "up", KIcon::SizeSmall ) );
00609   QToolTip::add( mRuleUp, i18n("Move rule up") );
00610   btnL->addWidget( mRuleUp );
00611   connect( mRuleUp, SIGNAL( clicked() ), SLOT( slotRuleUp() ) );
00612   mRuleDown = new QPushButton( this );
00613   mRuleDown->setPixmap( BarIcon( "down", KIcon::SizeSmall ) );
00614   QToolTip::add( mRuleDown, i18n("Move rule down") );
00615   btnL->addWidget( mRuleDown );
00616   connect( mRuleDown, SIGNAL( clicked() ), SLOT( slotRuleDown() ) );
00617 
00618   btnL = new QHBoxLayout( topL, KDialog::spacingHint() );
00619   editRule=0L;
00620   newRule = new QPushButton(this);
00621   newRule->setPixmap( BarIcon( "filenew", KIcon::SizeSmall ) );
00622   QToolTip::add(newRule,i18n("New rule")),
00623   btnL->addWidget(newRule);
00624   connect(newRule, SIGNAL(clicked()), this, SLOT(slotNewRule()));
00625   // if we're standalone, we need an additional edit button
00626   if (standalone) {
00627     editRule = new QPushButton(this);
00628     editRule->setIconSet( BarIconSet("edit", KIcon::SizeSmall) );
00629     QToolTip::add(editRule,i18n("Edit rule"));
00630     btnL->addWidget(editRule);
00631     connect(editRule,SIGNAL(clicked()),this,SLOT(slotEditRule()));
00632   }
00633   delRule = new QPushButton(this);
00634   delRule->setIconSet( BarIconSet( "editdelete", KIcon::SizeSmall ) );
00635   QToolTip::add(delRule,i18n("Remove rule"));
00636   btnL->addWidget(delRule);
00637   connect(delRule, SIGNAL(clicked()), this, SLOT(slotDelRule()));
00638   copyRule = new QPushButton(this);
00639   copyRule->setIconSet(BarIconSet("editcopy", KIcon::SizeSmall));
00640   QToolTip::add(copyRule,i18n("Copy rule"));
00641   btnL->addWidget(copyRule);
00642   connect(copyRule, SIGNAL(clicked()), this, SLOT(slotCopyRule()));
00643 
00644   // the group filter
00645   QBoxLayout *filterL = new QVBoxLayout(topL,KDialog::spacingHint());
00646   KComboBox *filterBox = new KComboBox(this);
00647   QStringList l = m->getGroups();
00648   filterBox->insertItem(i18n("<all groups>"));
00649   filterBox->insertStringList(l);
00650   filterBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
00651   connect(filterBox,SIGNAL(activated(const QString&)),
00652           this,SLOT(slotGroupFilter(const QString&)));
00653   slotGroupFilter(i18n("<all groups>"));
00654   QLabel *lab = new QLabel(filterBox,i18n("Sho&w only rules for group:"),this);
00655   filterL->addWidget(lab);
00656   filterL->addWidget(filterBox);
00657 
00658   connect(manager,SIGNAL(changedRules()),
00659           this,SLOT(updateRuleList()));
00660   connect(manager,SIGNAL(changedRuleName(const QString&,const QString&)),
00661           this,SLOT(slotRuleNameChanged(const QString&,const QString&)));
00662 
00663   updateRuleList();
00664   updateButton();
00665 }
00666 
00667 RuleListWidget::~RuleListWidget()
00668 {
00669 }
00670 
00671 void RuleListWidget::updateButton()
00672 {
00673   bool state = ruleList->count() > 0;
00674   if(editRule)
00675     editRule->setEnabled(state);
00676   delRule->setEnabled(state);
00677   copyRule->setEnabled(state);
00678 
00679   QListBoxItem *item = ruleList->item( ruleList->currentItem() );
00680   if ( item ) {
00681     mRuleUp->setEnabled( item->prev() != 0 );
00682     mRuleDown->setEnabled( item->next() != 0 );
00683   }
00684 }
00685 
00686 void RuleListWidget::updateRuleList()
00687 {
00688   emit leavingRule();
00689   kdDebug(5100) << "RuleListWidget::updateRuleList()" << endl;
00690   QString curr = ruleList->currentText();
00691   ruleList->clear();
00692   if (group == i18n("<all groups>")) {
00693     QStringList l = manager->getRuleNames();
00694     ruleList->insertStringList(l);
00695   } else {
00696     KScoringManager::ScoringRuleList l = manager->getAllRules();
00697     for (KScoringRule* rule = l.first(); rule; rule = l.next() ) {
00698       if (rule->matchGroup(group)) ruleList->insertItem(rule->getName());
00699     }
00700   }
00701   int index = setCurrentItem(ruleList,curr);
00702   if (index <0) {
00703     ruleList->setCurrentItem(0);
00704     slotRuleSelected(ruleList->currentText());
00705   }
00706   else {
00707     slotRuleSelected(curr);
00708   }
00709 }
00710 
00711 void RuleListWidget::updateRuleList(const KScoringRule *rule)
00712 {
00713   kdDebug(5100) << "RuleListWidget::updateRuleList(" << rule->getName() << ")" << endl;
00714   QString name = rule->getName();
00715   updateRuleList();
00716   slotRuleSelected(name);
00717 }
00718 
00719 void RuleListWidget::slotRuleNameChanged(const QString& oldName, const QString& newName)
00720 {
00721   int ind = ruleList->currentItem();
00722   for (uint i=0;i<ruleList->count();++i)
00723     if (ruleList->text(i) == oldName) {
00724       ruleList->changeItem(newName,i);
00725       ruleList->setCurrentItem(ind);
00726       return;
00727     }
00728 }
00729 
00730 void RuleListWidget::slotEditRule(const QString& s)
00731 {
00732   emit ruleEdited(s);
00733 }
00734 
00735 void RuleListWidget::slotEditRule()
00736 {
00737   if (ruleList->currentItem() >= 0) {
00738     emit ruleEdited(ruleList->currentText());
00739   }
00740   else if (ruleList->count() == 0)
00741     emit ruleEdited(QString::null);
00742 }
00743 
00744 void RuleListWidget::slotEditRule(QListBoxItem* item)
00745 {
00746   slotEditRule(item->text());
00747 }
00748 
00749 void RuleListWidget::slotGroupFilter(const QString& s)
00750 {
00751   group = s;
00752   updateRuleList();
00753 }
00754 
00755 void RuleListWidget::slotRuleSelected(const QString& ruleName)
00756 {
00757   emit leavingRule();
00758   kdDebug(5100) << "RuleListWidget::slotRuleSelected(" << ruleName << ")" << endl;
00759   if (ruleName != ruleList->currentText()) {
00760     setCurrentItem(ruleList,ruleName);
00761   }
00762   updateButton();
00763   emit ruleSelected(ruleName);
00764 }
00765 
00766 void RuleListWidget::slotRuleSelected(QListBoxItem *item)
00767 {
00768   if (!item) return;
00769   QString ruleName = item->text();
00770   slotRuleSelected(ruleName);
00771 }
00772 
00773 void RuleListWidget::slotRuleSelected(int index)
00774 {
00775   uint idx = index;
00776   if (idx >= ruleList->count()) return;
00777   QString ruleName = ruleList->text(index);
00778   slotRuleSelected(ruleName);
00779 }
00780 
00781 void RuleListWidget::slotNewRule()
00782 {
00783   emit leavingRule();
00784   KScoringRule *rule = manager->addRule();
00785   updateRuleList(rule);
00786   if (alone) slotEditRule(rule->getName());
00787   updateButton();
00788 }
00789 
00790 void RuleListWidget::slotDelRule()
00791 {
00792   KScoringRule *rule = manager->findRule(ruleList->currentText());
00793   if (rule)
00794     manager->deleteRule(rule);
00795   // goto the next rule
00796   if (!alone) slotEditRule();
00797   updateButton();
00798 }
00799 
00800 void RuleListWidget::slotCopyRule()
00801 {
00802   emit leavingRule();
00803   QString ruleName = ruleList->currentText();
00804   KScoringRule *rule = manager->findRule(ruleName);
00805   if (rule) {
00806     KScoringRule *nrule = manager->copyRule(rule);
00807     updateRuleList(nrule);
00808     slotEditRule(nrule->getName());
00809   }
00810   updateButton();
00811 }
00812 
00813 void RuleListWidget::slotRuleUp()
00814 {
00815   KScoringRule *rule = 0, *below = 0;
00816   QListBoxItem *item = ruleList->item( ruleList->currentItem() );
00817   if ( item ) {
00818     rule = manager->findRule( item->text() );
00819     item = item->prev();
00820     if ( item )
00821       below = manager->findRule( item->text() );
00822   }
00823   if ( rule && below )
00824     manager->moveRuleAbove( rule, below );
00825   updateRuleList();
00826   updateButton();
00827 }
00828 
00829 void RuleListWidget::slotRuleDown()
00830 {
00831   KScoringRule *rule = 0, *above = 0;
00832   QListBoxItem *item = ruleList->item( ruleList->currentItem() );
00833   if ( item ) {
00834     rule = manager->findRule( item->text() );
00835     item = item->next();
00836     if ( item )
00837       above = manager->findRule( item->text() );
00838   }
00839   if ( rule && above )
00840     manager->moveRuleBelow( rule, above );
00841   updateRuleList();
00842   updateButton();
00843 }
00844 
00845 //============================================================================
00846 //
00847 // class KScoringEditor (the score edit dialog)
00848 //
00849 //============================================================================
00850 KScoringEditor* KScoringEditor::scoreEditor = 0;
00851 
00852 KScoringEditor::KScoringEditor(KScoringManager* m,
00853                                QWidget *parent, const char *name)
00854   : KDialogBase(parent,name,false,i18n("Rule Editor"),Ok|Apply|Cancel,Ok,true), manager(m)
00855 {
00856   manager->pushRuleList();
00857   if (!scoreEditor) scoreEditor = this;
00858   kdDebug(5100) << "KScoringEditor::KScoringEditor()" << endl;
00859   if (!name) setName("KScoringEditor");
00860   // the left side gives an overview about all rules, the right side
00861   // shows a detailed view of an selected rule
00862   QWidget *w = new QWidget(this);
00863   setMainWidget(w);
00864   QHBoxLayout *hbl = new QHBoxLayout(w,0,spacingHint());
00865   ruleLister = new RuleListWidget(manager,false,w);
00866   hbl->addWidget(ruleLister);
00867   ruleEditor = new RuleEditWidget(manager,w);
00868   hbl->addWidget(ruleEditor);
00869   connect(ruleLister,SIGNAL(ruleSelected(const QString&)),
00870           ruleEditor, SLOT(slotEditRule(const QString&)));
00871   connect(ruleLister, SIGNAL(leavingRule()),
00872           ruleEditor, SLOT(updateRule()));
00873   connect(ruleEditor, SIGNAL(shrink()), SLOT(slotShrink()));
00874   connect(this,SIGNAL(finished()),SLOT(slotFinished()));
00875   ruleLister->slotRuleSelected(0);
00876   resize(550, sizeHint().height());
00877 }
00878 
00879 void KScoringEditor::setDirty()
00880 {
00881   QPushButton *applyBtn = actionButton(Apply);
00882   applyBtn->setEnabled(true);
00883 }
00884 
00885 KScoringEditor::~KScoringEditor()
00886 {
00887   scoreEditor = 0;
00888 }
00889 
00890 KScoringEditor* KScoringEditor::createEditor(KScoringManager* m,
00891                                              QWidget *parent, const char *name)
00892 {
00893   if (scoreEditor) return scoreEditor;
00894   else return new KScoringEditor(m,parent,name);
00895 }
00896 
00897 void KScoringEditor::setRule(KScoringRule* r)
00898 {
00899   kdDebug(5100) << "KScoringEditor::setRule(" << r->getName() << ")" << endl;
00900   QString ruleName = r->getName();
00901   ruleLister->slotRuleSelected(ruleName);
00902 }
00903 
00904 void KScoringEditor::slotShrink()
00905 {
00906   QTimer::singleShot(5, this, SLOT(slotDoShrink()));
00907 }
00908 
00909 void KScoringEditor::slotDoShrink()
00910 {
00911   updateGeometry();
00912   QApplication::sendPostedEvents();
00913   resize(width(),sizeHint().height());
00914 }
00915 
00916 void KScoringEditor::slotApply()
00917 {
00918   QString ruleName = ruleLister->currentRule();
00919   KScoringRule *rule = manager->findRule(ruleName);
00920   if (rule) {
00921     ruleEditor->updateRule(rule);
00922     ruleLister->updateRuleList(rule);
00923   }
00924   manager->removeTOS();
00925   manager->pushRuleList();
00926 }
00927 
00928 void KScoringEditor::slotOk()
00929 {
00930   slotApply();
00931   manager->removeTOS();
00932   KDialogBase::slotOk();
00933   manager->editorReady();
00934 }
00935 
00936 void KScoringEditor::slotCancel()
00937 {
00938   manager->popRuleList();
00939   KDialogBase::slotCancel();
00940 }
00941 
00942 void KScoringEditor::slotFinished()
00943 {
00944   delayedDestruct();
00945 }
00946 
00947 //============================================================================
00948 //
00949 // class KScoringEditorWidgetDialog (a dialog for the KScoringEditorWidget)
00950 //
00951 //============================================================================
00952 KScoringEditorWidgetDialog::KScoringEditorWidgetDialog(KScoringManager *m, const QString& r, QWidget *p, const char *n)
00953   : KDialogBase(p,n,true,i18n("Edit Rule"),
00954                 KDialogBase::Ok|KDialogBase::Apply|KDialogBase::Close,
00955                 KDialogBase::Ok,true),
00956     manager(m), ruleName(r)
00957 {
00958   QFrame *f = makeMainWidget();
00959   QBoxLayout *topL = new QVBoxLayout(f);
00960   ruleEditor = new RuleEditWidget(manager,f);
00961   connect(ruleEditor, SIGNAL(shrink()), SLOT(slotShrink()));
00962   topL->addWidget(ruleEditor);
00963   ruleEditor->slotEditRule(ruleName);
00964   resize(0,0);
00965 }
00966 
00967 void KScoringEditorWidgetDialog::slotApply()
00968 {
00969   KScoringRule *rule = manager->findRule(ruleName);
00970   if (rule) {
00971     ruleEditor->updateRule(rule);
00972     ruleName = rule->getName();
00973   }
00974 }
00975 
00976 void KScoringEditorWidgetDialog::slotOk()
00977 {
00978   slotApply();
00979   KDialogBase::slotOk();
00980 }
00981 
00982 void KScoringEditorWidgetDialog::slotShrink()
00983 {
00984   QTimer::singleShot(5, this, SLOT(slotDoShrink()));
00985 }
00986 
00987 void KScoringEditorWidgetDialog::slotDoShrink()
00988 {
00989   updateGeometry();
00990   QApplication::sendPostedEvents();
00991   resize(width(),sizeHint().height());
00992 }
00993 
00994 //============================================================================
00995 //
00996 // class KScoringEditorWidget (a reusable widget for config dialog...)
00997 //
00998 //============================================================================
00999 KScoringEditorWidget::KScoringEditorWidget(KScoringManager *m,QWidget *p, const char *n)
01000   : QWidget(p,n), manager(m)
01001 {
01002   QBoxLayout *topL = new QVBoxLayout(this);
01003   ruleLister = new RuleListWidget(manager,true,this);
01004   topL->addWidget(ruleLister);
01005   connect(ruleLister,SIGNAL(ruleEdited(const QString&)),
01006           this,SLOT(slotRuleEdited(const QString &)));
01007 }
01008 
01009 KScoringEditorWidget::~KScoringEditorWidget()
01010 {
01011   manager->editorReady();
01012 }
01013 
01014 void KScoringEditorWidget::slotRuleEdited(const QString& ruleName)
01015 {
01016   KScoringEditorWidgetDialog dlg(manager,ruleName,this);
01017   dlg.exec();
01018   ruleLister->updateRuleList();
01019 }
01020 
01021 #include "kscoringeditor.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys