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 TQT_NO_COMPAT 00019 00020 #include "kscoring.h" 00021 #include "kscoringeditor.h" 00022 00023 #include <kdebug.h> 00024 #include <tdelocale.h> 00025 #include <kcombobox.h> 00026 #include <kcolorcombo.h> 00027 #include <kiconloader.h> 00028 #include <kregexpeditorinterface.h> 00029 #include <ktrader.h> 00030 #include <tdeparts/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 !TDETrader::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->tqt_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()); 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(TQString(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()) 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(); 00537 } 00538 00539 void RuleEditWidget::updateRule(KScoringRule *rule) 00540 { 00541 oldRuleName = TQString(); 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 TDEListBox(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( "go-up", TDEIcon::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( "go-down", TDEIcon::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( "document-new", TDEIcon::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", TDEIcon::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( "edit-delete", TDEIcon::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("edit-copy", TDEIcon::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()); 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"