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 <tqlabel.h>
00034 #include <tqpushbutton.h>
00035 #include <tqlayout.h>
00036 #include <tqtooltip.h>
00037 #include <tqcheckbox.h>
00038 #include <tqbuttongroup.h>
00039 #include <tqradiobutton.h>
00040 #include <tqwidgetstack.h>
00041 #include <tqapplication.h>
00042 #include <tqtimer.h>
00043 #include <tqhbox.h>
00044 
00045 // works for both ListBox and ComboBox
00046 template <class T> static int setCurrentItem(T *box, const TQString& 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,TQWidget *p, const char *n)
00065   : TQFrame(p,n), manager(m)
00066 {
00067   TQBoxLayout *topL = new TQVBoxLayout(this,5);
00068   TQBoxLayout *firstRow = new TQHBoxLayout(topL);
00069   neg = new TQCheckBox(i18n("Not"),this);
00070   TQToolTip::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   TQToolTip::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   TQToolTip::add(matches,i18n("Select the type of match"));
00080   firstRow->addWidget(matches,1);
00081   connect( matches, TQT_SIGNAL( activated( int ) ), TQT_SLOT( toggleRegExpButton( int ) ) );
00082   TQHBoxLayout *secondRow = new TQHBoxLayout( topL );
00083   secondRow->setSpacing( 1 );
00084   expr = new KLineEdit( this );
00085   TQToolTip::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 TQPushButton( i18n("Edit..."), this );
00090   secondRow->addWidget( regExpButton );
00091   connect( regExpButton, TQT_SIGNAL( clicked() ), TQT_SLOT( showRegExpDialog() ) );
00092 
00093   // occupy at much width as possible
00094   setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding,TQSizePolicy::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   TQString head = headers->currentText();
00114   TQString match = matches->currentText();
00115   int condType = KScoringExpression::getConditionForName(match);
00116   match = KScoringExpression::getTypeString(condType);
00117   TQString cond = expr->text();
00118   TQString 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   TQDialog *editorDialog = KParts::ComponentFactory::createInstanceFromQuery<TQDialog>( "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, TQWidget *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 TQWidget* ConditionEditWidget::createWidget(TQWidget *parent)
00164 {
00165   return new SingleConditionWidget(manager,parent);
00166 }
00167 
00168 void ConditionEditWidget::clearWidget(TQWidget *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(TQWidget *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,TQWidget *p, const char *n)
00215   : TQWidget(p,n), notifyEditor(0), scoreEditor(0), colorEditor(0),manager(m)
00216 {
00217   TQHBoxLayout *topL = new TQHBoxLayout(this,0,5);
00218   types = new KComboBox(this);
00219   types->setEditable(false);
00220   topL->addWidget(types);
00221   stack = new TQWidgetStack(this);
00222   topL->addWidget(stack);
00223 
00224   dummyLabel = new TQLabel(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(TQString::null);
00230   TQStringList l = ActionBase::userNames();
00231   for ( TQStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
00232     TQString name = *it;
00233     int feature = ActionBase::getTypeForUserName(name);
00234     if (manager->hasFeature(feature)) {
00235       types->insertItem(name);
00236       TQWidget *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 TQLabel( stack ); // empty dummy
00249           break;
00250       }
00251       if ( w )
00252         stack->addWidget(w,index++);
00253     }
00254   }
00255 
00256   connect(types,TQT_SIGNAL(activated(int)),stack,TQT_SLOT(raiseWidget(int)));
00257 
00258   // raise the dummy label
00259   types->setCurrentItem(0);
00260   stack->raiseWidget(dummyLabel);
00261 }
00262 
00263 SingleActionWidget::~SingleActionWidget()
00264 {
00265 }
00266 
00267 void SingleActionWidget::setAction(ActionBase *act)
00268 {
00269   kdDebug(5100) << "SingleActionWidget::setAction()" << endl;
00270   setCurrentItem(types,ActionBase::userName(act->getType()));
00271   int index = types->currentItem();
00272   stack->raiseWidget(index);
00273   switch (act->getType()) {
00274     case ActionBase::SETSCORE:
00275       scoreEditor->setValue(act->getValueString().toInt());
00276       break;
00277     case ActionBase::NOTIFY:
00278       notifyEditor->setText(act->getValueString());
00279       break;
00280     case ActionBase::COLOR:
00281       colorEditor->setColor(TQColor(act->getValueString()));
00282       break;
00283     case ActionBase::MARKASREAD:
00284       // nothing
00285       break;
00286     default:
00287       kdWarning(5100) << "unknown action type in SingleActionWidget::setAction()" << endl;
00288   }
00289 }
00290 
00291 ActionBase* SingleActionWidget::createAction() const
00292 {
00293   // no action selected...
00294   if (types->currentText().isEmpty())
00295     return 0;
00296 
00297   int type = ActionBase::getTypeForUserName(types->currentText());
00298   switch (type) {
00299     case ActionBase::SETSCORE:
00300       return new ActionSetScore(scoreEditor->value());
00301     case ActionBase::NOTIFY:
00302       return new ActionNotify(notifyEditor->text());
00303     case ActionBase::COLOR:
00304       return new ActionColor(colorEditor->color().name());
00305     case ActionBase::MARKASREAD:
00306       return new ActionMarkAsRead();
00307     default:
00308       kdWarning(5100) << "unknown action type in SingleActionWidget::getValue()" << endl;
00309       return 0;
00310   }
00311 }
00312 
00313 void SingleActionWidget::clear()
00314 {
00315   if (scoreEditor) scoreEditor->setValue(0);
00316   if (notifyEditor) notifyEditor->clear();
00317   if (colorEditor) colorEditor->setCurrentItem(0);
00318   types->setCurrentItem(0);
00319   stack->raiseWidget(dummyLabel);
00320 }
00321 
00322 //============================================================================
00323 //
00324 // class ActionEditWidget (the widget to edit the actions of a rule)
00325 //
00326 //============================================================================
00327 ActionEditWidget::ActionEditWidget(KScoringManager *m,TQWidget *p, const char *n)
00328   : KWidgetLister(1,8,p,n), manager(m)
00329 {
00330   // create one initial widget
00331   addWidgetAtEnd();
00332 }
00333 
00334 ActionEditWidget::~ActionEditWidget()
00335 {}
00336 
00337 TQWidget* ActionEditWidget::createWidget( TQWidget *parent )
00338 {
00339   return new SingleActionWidget(manager,parent);
00340 }
00341 
00342 void ActionEditWidget::slotEditRule(KScoringRule *rule)
00343 {
00344   KScoringRule::ActionList l;
00345   if (rule) l = rule->getActions();
00346   if (!rule || l.count() == 0) {
00347     slotClear();
00348   } else {
00349     setNumberOfShownWidgetsTo(l.count());
00350     ActionBase *act = l.first();
00351     SingleActionWidget *saw = static_cast<SingleActionWidget*>(mWidgetList.first());
00352     while (act && saw) {
00353       saw->setAction(act);
00354       act = l.next();
00355       saw = static_cast<SingleActionWidget*>(mWidgetList.next());
00356     }
00357   }
00358 }
00359 
00360 void ActionEditWidget::updateRule(KScoringRule *rule)
00361 {
00362   rule->cleanActions();
00363   for(TQWidget *w = mWidgetList.first(); w; w = mWidgetList.next()) {
00364     if (! w->isA("SingleActionWidget")) {
00365       kdWarning(5100) << "there is a widget in ActionEditWidget "
00366                       << "which isn't a SingleActionWidget" << endl;
00367     } else {
00368       SingleActionWidget *saw = dynamic_cast<SingleActionWidget*>(w);
00369       if (saw)
00370       {
00371         ActionBase *act = saw->createAction();
00372         if (act)
00373           rule->addAction(act);
00374       }
00375     }
00376   }
00377 }
00378 
00379 void ActionEditWidget::clearWidget(TQWidget *w)
00380 {
00381   Q_ASSERT( w->isA("SingleActionWidget") );
00382   SingleActionWidget *sw = dynamic_cast<SingleActionWidget*>(w);
00383   if (sw)
00384     sw->clear();
00385 }
00386 
00387 //============================================================================
00388 //
00389 // class RuleEditWidget (the widget to edit one rule)
00390 //
00391 //============================================================================
00392 RuleEditWidget::RuleEditWidget(KScoringManager *m,TQWidget *p, const char *n)
00393   : TQWidget(p,n), dirty(false), manager(m), oldRuleName(TQString::null)
00394 {
00395   kdDebug(5100) << "RuleEditWidget::RuleEditWidget()" << endl;
00396   if ( !n ) setName( "RuleEditWidget" );
00397   TQVBoxLayout *topLayout = new TQVBoxLayout( this, 5, KDialog::spacingHint() );
00398 
00399   //------------- Name, Servers, Groups ---------------------
00400   TQGroupBox *groupB = new TQGroupBox(i18n("Properties"),this);
00401   topLayout->addWidget(groupB);
00402   TQGridLayout* groupL = new TQGridLayout(groupB, 6,2, 8,5);
00403   groupL->addRowSpacing(0, fontMetrics().lineSpacing()-4);
00404 
00405   // name
00406   ruleNameEdit = new KLineEdit( groupB, "ruleNameEdit" );
00407   groupL->addWidget( ruleNameEdit, 1, 1 );
00408   TQLabel *ruleNameLabel = new TQLabel(ruleNameEdit, i18n("&Name:"), groupB, "ruleNameLabel");
00409   groupL->addWidget( ruleNameLabel, 1, 0 );
00410 
00411   // groups
00412   groupsEdit = new KLineEdit( groupB, "groupsEdit" );
00413   groupL->addWidget( groupsEdit, 2, 1 );
00414   TQLabel *groupsLabel = new TQLabel(groupsEdit, i18n("&Groups:"), groupB, "groupsLabel");
00415   groupL->addWidget( groupsLabel, 2, 0 );
00416 
00417   TQPushButton *groupsBtn = new TQPushButton(i18n("A&dd Group"), groupB);
00418   connect(groupsBtn,TQT_SIGNAL(clicked()),TQT_SLOT(slotAddGroup()));
00419   groupL->addWidget( groupsBtn, 3, 0 );
00420 
00421   groupsBox = new KComboBox( false, groupB, "groupsBox" );
00422   groupsBox->setDuplicatesEnabled(false);
00423   groupsBox->insertStringList(manager->getGroups());
00424   groupsBox->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed));
00425   groupL->addWidget( groupsBox, 3, 1 );
00426 
00427   // expires
00428   expireCheck = new TQCheckBox(i18n("&Expire rule automatically"), groupB);
00429   groupL->addMultiCellWidget( expireCheck, 4,4, 0,1 );
00430   expireEdit = new KIntSpinBox(1,99999,1,30,10, groupB, "expireWidget");
00431   //Init suffix
00432   slotExpireEditChanged(30);
00433   connect(expireEdit, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotExpireEditChanged(int)));
00434   groupL->addWidget( expireEdit, 5, 1 );
00435   expireLabel = new TQLabel(expireEdit, i18n("&Rule is valid for:"), groupB, "expireLabel");
00436   groupL->addWidget( expireLabel, 5, 0 );
00437   expireLabel->setEnabled(false);
00438   expireEdit->setEnabled(false);
00439 
00440   connect(expireCheck, TQT_SIGNAL(toggled(bool)), expireLabel, TQT_SLOT(setEnabled(bool)));
00441   connect(expireCheck, TQT_SIGNAL(toggled(bool)), expireEdit, TQT_SLOT(setEnabled(bool)));
00442 
00443   //------------- Conditions ---------------------
00444   TQGroupBox *groupConds = new TQGroupBox(i18n("Conditions"), this);
00445   topLayout->addWidget(groupConds);
00446   TQGridLayout *condL = new TQGridLayout(groupConds, 3,2, 8,5);
00447 
00448   condL->addRowSpacing(0, fontMetrics().lineSpacing()-4);
00449 
00450   TQButtonGroup *buttonGroup = new TQButtonGroup(groupConds);
00451   buttonGroup->hide();
00452   linkModeAnd = new TQRadioButton(i18n("Match a&ll conditions"), groupConds);
00453   buttonGroup->insert(linkModeAnd);
00454   condL->addWidget(linkModeAnd, 1,0);
00455   linkModeOr = new TQRadioButton(i18n("Matc&h any condition"), groupConds);
00456   buttonGroup->insert(linkModeOr);
00457   condL->addWidget(linkModeOr, 1,1);
00458   linkModeAnd->setChecked(true);
00459 
00460   condEditor = new ConditionEditWidget(manager,groupConds);
00461   condL->addMultiCellWidget(condEditor, 2,2, 0,1);
00462   connect(condEditor,TQT_SIGNAL(widgetRemoved()),this,TQT_SLOT(slotShrink()));
00463 
00464   //------------- Actions ---------------------
00465   TQGroupBox *groupActions = new TQGroupBox(i18n("Actions"), this);
00466   topLayout->addWidget(groupActions);
00467   TQBoxLayout *actionL = new TQVBoxLayout(groupActions,8,5);
00468   actionL->addSpacing(fontMetrics().lineSpacing()-4);
00469   actionEditor = new ActionEditWidget(manager,groupActions);
00470   actionL->addWidget(actionEditor);
00471   connect(actionEditor,TQT_SIGNAL(widgetRemoved()),this,TQT_SLOT(slotShrink()));
00472 
00473   topLayout->addStretch(1);
00474 
00475   kdDebug(5100) << "constructed RuleEditWidget" << endl;
00476 }
00477 
00478 RuleEditWidget::~RuleEditWidget()
00479 {
00480 }
00481 
00482 void RuleEditWidget::slotEditRule(const TQString& ruleName)
00483 {
00484   kdDebug(5100) << "RuleEditWidget::slotEditRule(" << ruleName << ")" << endl;
00485 //   // first update the old rule if there is one
00486 //   kdDebug(5100) << "let see if we have a rule with name " << oldRuleName << endl;
00487 //   KScoringRule *rule;
00488 //   if (!oldRuleName.isNull() && oldRuleName != ruleName) {
00489 //     rule = manager->findRule(oldRuleName);
00490 //     if (rule) {
00491 //       kdDebug(5100) << "updating rule " << rule->getName() << endl;
00492 //       updateRule(rule);
00493 //     }
00494 //   }
00495 
00496   KScoringRule* rule = manager->findRule(ruleName);
00497   if (!rule) {
00498     kdDebug(5100) << "no rule for ruleName " << ruleName << endl;
00499     clearContents();
00500     return;
00501   }
00502   oldRuleName = rule->getName();
00503   ruleNameEdit->setText(rule->getName());
00504   groupsEdit->setText(rule->getGroups().join(";"));
00505 
00506   bool b = rule->getExpireDate().isValid();
00507   expireCheck->setChecked(b);
00508   expireEdit->setEnabled(b);
00509   expireLabel->setEnabled(b);
00510   if (b)
00511     expireEdit->setValue(TQDate::currentDate().daysTo(rule->getExpireDate()));
00512   else
00513     expireEdit->setValue(30);
00514   if (rule->getLinkMode() == KScoringRule::AND) {
00515     linkModeAnd->setChecked(true);
00516   }
00517   else {
00518     linkModeOr->setChecked(true);
00519   }
00520 
00521   condEditor->slotEditRule(rule);
00522   actionEditor->slotEditRule(rule);
00523 
00524   kdDebug(5100) << "RuleEditWidget::slotEditRule() ready" << endl;
00525 }
00526 
00527 void RuleEditWidget::clearContents()
00528 {
00529   ruleNameEdit->setText("");
00530   groupsEdit->setText("");
00531   expireCheck->setChecked(false);
00532   expireEdit->setValue(30);
00533   expireEdit->setEnabled(false);
00534   condEditor->slotEditRule(0);
00535   actionEditor->slotEditRule(0);
00536   oldRuleName = TQString::null;
00537 }
00538 
00539 void RuleEditWidget::updateRule(KScoringRule *rule)
00540 {
00541   oldRuleName = TQString::null;
00542   TQString groups = groupsEdit->text();
00543   if (groups.isEmpty())
00544     rule->setGroups(TQStringList(".*"));
00545   else
00546     rule->setGroups(TQStringList::split(";",groups));
00547   bool b = expireCheck->isChecked();
00548   if (b)
00549     rule->setExpireDate(TQDate::currentDate().addDays(expireEdit->value()));
00550   else
00551     rule->setExpireDate(TQDate());
00552   actionEditor->updateRule(rule);
00553   rule->setLinkMode(linkModeAnd->isChecked()?KScoringRule::AND:KScoringRule::OR);
00554   condEditor->updateRule(rule);
00555   if (rule->getName() != ruleNameEdit->text())
00556     manager->setRuleName(rule,ruleNameEdit->text());
00557 }
00558 
00559 void RuleEditWidget::updateRule()
00560 {
00561   KScoringRule *rule = manager->findRule(oldRuleName);
00562   if (rule) updateRule(rule);
00563 }
00564 
00565 void RuleEditWidget::slotAddGroup()
00566 {
00567   TQString grp = groupsBox->currentText();
00568   if ( grp.isEmpty() )
00569       return;
00570   TQString txt = groupsEdit->text().stripWhiteSpace();
00571   if ( txt == ".*" || txt.isEmpty() ) groupsEdit->setText(grp);
00572   else groupsEdit->setText(txt + ";" + grp);
00573 }
00574 
00575 void RuleEditWidget::setDirty()
00576 {
00577   kdDebug(5100) << "RuleEditWidget::setDirty()" << endl;
00578   if (dirty) return;
00579   dirty = true;
00580 }
00581 
00582 void RuleEditWidget::slotShrink()
00583 {
00584   emit(shrink());
00585 }
00586 
00587 void RuleEditWidget::slotExpireEditChanged(int value)
00588 {
00589   expireEdit->setSuffix(i18n(" day", " days", value));
00590 }
00591 
00592 //============================================================================
00593 //
00594 // class RuleListWidget (the widget for managing a list of rules)
00595 //
00596 //============================================================================
00597 RuleListWidget::RuleListWidget(KScoringManager *m, bool standalone, TQWidget *p, const char *n)
00598   : TQWidget(p,n), alone(standalone), manager(m)
00599 {
00600   kdDebug(5100) << "RuleListWidget::RuleListWidget()" << endl;
00601   if (!n) setName("RuleListWidget");
00602   TQVBoxLayout *topL = new TQVBoxLayout(this,standalone? 0:5,KDialog::spacingHint());
00603   ruleList = new KListBox(this);
00604   if (standalone) {
00605     connect(ruleList,TQT_SIGNAL(doubleClicked(TQListBoxItem*)),
00606             this,TQT_SLOT(slotEditRule(TQListBoxItem*)));
00607     connect(ruleList,TQT_SIGNAL(returnPressed(TQListBoxItem*)),
00608             this,TQT_SLOT(slotEditRule(TQListBoxItem*)));
00609   }
00610   connect(ruleList, TQT_SIGNAL(currentChanged(TQListBoxItem*)),
00611           this, TQT_SLOT(slotRuleSelected(TQListBoxItem*)));
00612   topL->addWidget(ruleList);
00613 
00614   TQHBoxLayout *btnL = new TQHBoxLayout( topL, KDialog::spacingHint() );
00615   mRuleUp = new TQPushButton( this );
00616   mRuleUp->setPixmap( BarIcon( "up", KIcon::SizeSmall ) );
00617   TQToolTip::add( mRuleUp, i18n("Move rule up") );
00618   btnL->addWidget( mRuleUp );
00619   connect( mRuleUp, TQT_SIGNAL( clicked() ), TQT_SLOT( slotRuleUp() ) );
00620   mRuleDown = new TQPushButton( this );
00621   mRuleDown->setPixmap( BarIcon( "down", KIcon::SizeSmall ) );
00622   TQToolTip::add( mRuleDown, i18n("Move rule down") );
00623   btnL->addWidget( mRuleDown );
00624   connect( mRuleDown, TQT_SIGNAL( clicked() ), TQT_SLOT( slotRuleDown() ) );
00625 
00626   btnL = new TQHBoxLayout( topL, KDialog::spacingHint() );
00627   editRule=0L;
00628   newRule = new TQPushButton(this);
00629   newRule->setPixmap( BarIcon( "filenew", KIcon::SizeSmall ) );
00630   TQToolTip::add(newRule,i18n("New rule")),
00631   btnL->addWidget(newRule);
00632   connect(newRule, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotNewRule()));
00633   // if we're standalone, we need an additional edit button
00634   if (standalone) {
00635     editRule = new TQPushButton(this);
00636     editRule->setIconSet( BarIconSet("edit", KIcon::SizeSmall) );
00637     TQToolTip::add(editRule,i18n("Edit rule"));
00638     btnL->addWidget(editRule);
00639     connect(editRule,TQT_SIGNAL(clicked()),this,TQT_SLOT(slotEditRule()));
00640   }
00641   delRule = new TQPushButton(this);
00642   delRule->setIconSet( BarIconSet( "editdelete", KIcon::SizeSmall ) );
00643   TQToolTip::add(delRule,i18n("Remove rule"));
00644   btnL->addWidget(delRule);
00645   connect(delRule, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotDelRule()));
00646   copyRule = new TQPushButton(this);
00647   copyRule->setIconSet(BarIconSet("editcopy", KIcon::SizeSmall));
00648   TQToolTip::add(copyRule,i18n("Copy rule"));
00649   btnL->addWidget(copyRule);
00650   connect(copyRule, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotCopyRule()));
00651 
00652   // the group filter
00653   TQBoxLayout *filterL = new TQVBoxLayout(topL,KDialog::spacingHint());
00654   KComboBox *filterBox = new KComboBox(this);
00655   TQStringList l = m->getGroups();
00656   filterBox->insertItem(i18n("<all groups>"));
00657   filterBox->insertStringList(l);
00658   filterBox->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed));
00659   connect(filterBox,TQT_SIGNAL(activated(const TQString&)),
00660           this,TQT_SLOT(slotGroupFilter(const TQString&)));
00661   slotGroupFilter(i18n("<all groups>"));
00662   TQLabel *lab = new TQLabel(filterBox,i18n("Sho&w only rules for group:"),this);
00663   filterL->addWidget(lab);
00664   filterL->addWidget(filterBox);
00665 
00666   connect(manager,TQT_SIGNAL(changedRules()),
00667           this,TQT_SLOT(updateRuleList()));
00668   connect(manager,TQT_SIGNAL(changedRuleName(const TQString&,const TQString&)),
00669           this,TQT_SLOT(slotRuleNameChanged(const TQString&,const TQString&)));
00670 
00671   updateRuleList();
00672   updateButton();
00673 }
00674 
00675 RuleListWidget::~RuleListWidget()
00676 {
00677 }
00678 
00679 void RuleListWidget::updateButton()
00680 {
00681   bool state = ruleList->count() > 0;
00682   if(editRule)
00683     editRule->setEnabled(state);
00684   delRule->setEnabled(state);
00685   copyRule->setEnabled(state);
00686 
00687   TQListBoxItem *item = ruleList->item( ruleList->currentItem() );
00688   if ( item ) {
00689     mRuleUp->setEnabled( item->prev() != 0 );
00690     mRuleDown->setEnabled( item->next() != 0 );
00691   }
00692 }
00693 
00694 void RuleListWidget::updateRuleList()
00695 {
00696   emit leavingRule();
00697   kdDebug(5100) << "RuleListWidget::updateRuleList()" << endl;
00698   TQString curr = ruleList->currentText();
00699   ruleList->clear();
00700   if (group == i18n("<all groups>")) {
00701     TQStringList l = manager->getRuleNames();
00702     ruleList->insertStringList(l);
00703   } else {
00704     KScoringManager::ScoringRuleList l = manager->getAllRules();
00705     for (KScoringRule* rule = l.first(); rule; rule = l.next() ) {
00706       if (rule->matchGroup(group)) ruleList->insertItem(rule->getName());
00707     }
00708   }
00709   int index = setCurrentItem(ruleList,curr);
00710   if (index <0) {
00711     ruleList->setCurrentItem(0);
00712     slotRuleSelected(ruleList->currentText());
00713   }
00714   else {
00715     slotRuleSelected(curr);
00716   }
00717 }
00718 
00719 void RuleListWidget::updateRuleList(const KScoringRule *rule)
00720 {
00721   kdDebug(5100) << "RuleListWidget::updateRuleList(" << rule->getName() << ")" << endl;
00722   TQString name = rule->getName();
00723   updateRuleList();
00724   slotRuleSelected(name);
00725 }
00726 
00727 void RuleListWidget::slotRuleNameChanged(const TQString& oldName, const TQString& newName)
00728 {
00729   int ind = ruleList->currentItem();
00730   for (uint i=0;i<ruleList->count();++i)
00731     if (ruleList->text(i) == oldName) {
00732       ruleList->changeItem(newName,i);
00733       ruleList->setCurrentItem(ind);
00734       return;
00735     }
00736 }
00737 
00738 void RuleListWidget::slotEditRule(const TQString& s)
00739 {
00740   emit ruleEdited(s);
00741 }
00742 
00743 void RuleListWidget::slotEditRule()
00744 {
00745   if (ruleList->currentItem() >= 0) {
00746     emit ruleEdited(ruleList->currentText());
00747   }
00748   else if (ruleList->count() == 0)
00749     emit ruleEdited(TQString::null);
00750 }
00751 
00752 void RuleListWidget::slotEditRule(TQListBoxItem* item)
00753 {
00754   slotEditRule(item->text());
00755 }
00756 
00757 void RuleListWidget::slotGroupFilter(const TQString& s)
00758 {
00759   group = s;
00760   updateRuleList();
00761 }
00762 
00763 void RuleListWidget::slotRuleSelected(const TQString& ruleName)
00764 {
00765   emit leavingRule();
00766   kdDebug(5100) << "RuleListWidget::slotRuleSelected(" << ruleName << ")" << endl;
00767   if (ruleName != ruleList->currentText()) {
00768     setCurrentItem(ruleList,ruleName);
00769   }
00770   updateButton();
00771   emit ruleSelected(ruleName);
00772 }
00773 
00774 void RuleListWidget::slotRuleSelected(TQListBoxItem *item)
00775 {
00776   if (!item) return;
00777   TQString ruleName = item->text();
00778   slotRuleSelected(ruleName);
00779 }
00780 
00781 void RuleListWidget::slotRuleSelected(int index)
00782 {
00783   uint idx = index;
00784   if (idx >= ruleList->count()) return;
00785   TQString ruleName = ruleList->text(index);
00786   slotRuleSelected(ruleName);
00787 }
00788 
00789 void RuleListWidget::slotNewRule()
00790 {
00791   emit leavingRule();
00792   KScoringRule *rule = manager->addRule();
00793   updateRuleList(rule);
00794   if (alone) slotEditRule(rule->getName());
00795   updateButton();
00796 }
00797 
00798 void RuleListWidget::slotDelRule()
00799 {
00800   KScoringRule *rule = manager->findRule(ruleList->currentText());
00801   if (rule)
00802     manager->deleteRule(rule);
00803   // goto the next rule
00804   if (!alone) slotEditRule();
00805   updateButton();
00806 }
00807 
00808 void RuleListWidget::slotCopyRule()
00809 {
00810   emit leavingRule();
00811   TQString ruleName = ruleList->currentText();
00812   KScoringRule *rule = manager->findRule(ruleName);
00813   if (rule) {
00814     KScoringRule *nrule = manager->copyRule(rule);
00815     updateRuleList(nrule);
00816     slotEditRule(nrule->getName());
00817   }
00818   updateButton();
00819 }
00820 
00821 void RuleListWidget::slotRuleUp()
00822 {
00823   KScoringRule *rule = 0, *below = 0;
00824   TQListBoxItem *item = ruleList->item( ruleList->currentItem() );
00825   if ( item ) {
00826     rule = manager->findRule( item->text() );
00827     item = item->prev();
00828     if ( item )
00829       below = manager->findRule( item->text() );
00830   }
00831   if ( rule && below )
00832     manager->moveRuleAbove( rule, below );
00833   updateRuleList();
00834   updateButton();
00835 }
00836 
00837 void RuleListWidget::slotRuleDown()
00838 {
00839   KScoringRule *rule = 0, *above = 0;
00840   TQListBoxItem *item = ruleList->item( ruleList->currentItem() );
00841   if ( item ) {
00842     rule = manager->findRule( item->text() );
00843     item = item->next();
00844     if ( item )
00845       above = manager->findRule( item->text() );
00846   }
00847   if ( rule && above )
00848     manager->moveRuleBelow( rule, above );
00849   updateRuleList();
00850   updateButton();
00851 }
00852 
00853 //============================================================================
00854 //
00855 // class KScoringEditor (the score edit dialog)
00856 //
00857 //============================================================================
00858 KScoringEditor* KScoringEditor::scoreEditor = 0;
00859 
00860 KScoringEditor::KScoringEditor(KScoringManager* m,
00861                                TQWidget *parent, const char *name)
00862   : KDialogBase(parent,name,false,i18n("Rule Editor"),Ok|Apply|Cancel,Ok,true), manager(m)
00863 {
00864   manager->pushRuleList();
00865   if (!scoreEditor) scoreEditor = this;
00866   kdDebug(5100) << "KScoringEditor::KScoringEditor()" << endl;
00867   if (!name) setName("KScoringEditor");
00868   // the left side gives an overview about all rules, the right side
00869   // shows a detailed view of an selected rule
00870   TQWidget *w = new TQWidget(this);
00871   setMainWidget(w);
00872   TQHBoxLayout *hbl = new TQHBoxLayout(w,0,spacingHint());
00873   ruleLister = new RuleListWidget(manager,false,w);
00874   hbl->addWidget(ruleLister);
00875   ruleEditor = new RuleEditWidget(manager,w);
00876   hbl->addWidget(ruleEditor);
00877   connect(ruleLister,TQT_SIGNAL(ruleSelected(const TQString&)),
00878           ruleEditor, TQT_SLOT(slotEditRule(const TQString&)));
00879   connect(ruleLister, TQT_SIGNAL(leavingRule()),
00880           ruleEditor, TQT_SLOT(updateRule()));
00881   connect(ruleEditor, TQT_SIGNAL(shrink()), TQT_SLOT(slotShrink()));
00882   connect(this,TQT_SIGNAL(finished()),TQT_SLOT(slotFinished()));
00883   ruleLister->slotRuleSelected(0);
00884   resize(550, sizeHint().height());
00885 }
00886 
00887 void KScoringEditor::setDirty()
00888 {
00889   TQPushButton *applyBtn = actionButton(Apply);
00890   applyBtn->setEnabled(true);
00891 }
00892 
00893 KScoringEditor::~KScoringEditor()
00894 {
00895   scoreEditor = 0;
00896 }
00897 
00898 KScoringEditor* KScoringEditor::createEditor(KScoringManager* m,
00899                                              TQWidget *parent, const char *name)
00900 {
00901   if (scoreEditor) return scoreEditor;
00902   else return new KScoringEditor(m,parent,name);
00903 }
00904 
00905 void KScoringEditor::setRule(KScoringRule* r)
00906 {
00907   kdDebug(5100) << "KScoringEditor::setRule(" << r->getName() << ")" << endl;
00908   TQString ruleName = r->getName();
00909   ruleLister->slotRuleSelected(ruleName);
00910 }
00911 
00912 void KScoringEditor::slotShrink()
00913 {
00914   TQTimer::singleShot(5, this, TQT_SLOT(slotDoShrink()));
00915 }
00916 
00917 void KScoringEditor::slotDoShrink()
00918 {
00919   updateGeometry();
00920   TQApplication::sendPostedEvents();
00921   resize(width(),sizeHint().height());
00922 }
00923 
00924 void KScoringEditor::slotApply()
00925 {
00926   TQString ruleName = ruleLister->currentRule();
00927   KScoringRule *rule = manager->findRule(ruleName);
00928   if (rule) {
00929     ruleEditor->updateRule(rule);
00930     ruleLister->updateRuleList(rule);
00931   }
00932   manager->removeTOS();
00933   manager->pushRuleList();
00934 }
00935 
00936 void KScoringEditor::slotOk()
00937 {
00938   slotApply();
00939   manager->removeTOS();
00940   KDialogBase::slotOk();
00941   manager->editorReady();
00942 }
00943 
00944 void KScoringEditor::slotCancel()
00945 {
00946   manager->popRuleList();
00947   KDialogBase::slotCancel();
00948 }
00949 
00950 void KScoringEditor::slotFinished()
00951 {
00952   delayedDestruct();
00953 }
00954 
00955 //============================================================================
00956 //
00957 // class KScoringEditorWidgetDialog (a dialog for the KScoringEditorWidget)
00958 //
00959 //============================================================================
00960 KScoringEditorWidgetDialog::KScoringEditorWidgetDialog(KScoringManager *m, const TQString& r, TQWidget *p, const char *n)
00961   : KDialogBase(p,n,true,i18n("Edit Rule"),
00962                 KDialogBase::Ok|KDialogBase::Apply|KDialogBase::Close,
00963                 KDialogBase::Ok,true),
00964     manager(m), ruleName(r)
00965 {
00966   TQFrame *f = makeMainWidget();
00967   TQBoxLayout *topL = new TQVBoxLayout(f);
00968   ruleEditor = new RuleEditWidget(manager,f);
00969   connect(ruleEditor, TQT_SIGNAL(shrink()), TQT_SLOT(slotShrink()));
00970   topL->addWidget(ruleEditor);
00971   ruleEditor->slotEditRule(ruleName);
00972   resize(0,0);
00973 }
00974 
00975 void KScoringEditorWidgetDialog::slotApply()
00976 {
00977   KScoringRule *rule = manager->findRule(ruleName);
00978   if (rule) {
00979     ruleEditor->updateRule(rule);
00980     ruleName = rule->getName();
00981   }
00982 }
00983 
00984 void KScoringEditorWidgetDialog::slotOk()
00985 {
00986   slotApply();
00987   KDialogBase::slotOk();
00988 }
00989 
00990 void KScoringEditorWidgetDialog::slotShrink()
00991 {
00992   TQTimer::singleShot(5, this, TQT_SLOT(slotDoShrink()));
00993 }
00994 
00995 void KScoringEditorWidgetDialog::slotDoShrink()
00996 {
00997   updateGeometry();
00998   TQApplication::sendPostedEvents();
00999   resize(width(),sizeHint().height());
01000 }
01001 
01002 //============================================================================
01003 //
01004 // class KScoringEditorWidget (a reusable widget for config dialog...)
01005 //
01006 //============================================================================
01007 KScoringEditorWidget::KScoringEditorWidget(KScoringManager *m,TQWidget *p, const char *n)
01008   : TQWidget(p,n), manager(m)
01009 {
01010   TQBoxLayout *topL = new TQVBoxLayout(this);
01011   ruleLister = new RuleListWidget(manager,true,this);
01012   topL->addWidget(ruleLister);
01013   connect(ruleLister,TQT_SIGNAL(ruleEdited(const TQString&)),
01014           this,TQT_SLOT(slotRuleEdited(const TQString &)));
01015 }
01016 
01017 KScoringEditorWidget::~KScoringEditorWidget()
01018 {
01019   manager->editorReady();
01020 }
01021 
01022 void KScoringEditorWidget::slotRuleEdited(const TQString& ruleName)
01023 {
01024   KScoringEditorWidgetDialog dlg(manager,ruleName,this);
01025   dlg.exec();
01026   ruleLister->updateRuleList();
01027 }
01028 
01029 #include "kscoringeditor.moc"