libtdepim

kscoringeditor.cpp
1/*
2 kscoringeditor.cpp
3
4 Copyright (c) 2001 Mathias Waack
5 Copyright (C) 2005 by Volker Krause <volker.krause@rwth-aachen.de>
6
7 Author: Mathias Waack <mathias@atoll-net.de>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software Foundation,
15 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US
16*/
17
18#include "kscoring.h"
19#include "kscoringeditor.h"
20
21#include <kdebug.h>
22#include <tdelocale.h>
23#include <kcombobox.h>
24#include <kcolorcombo.h>
25#include <kiconloader.h>
26#include <kregexpeditorinterface.h>
27#include <ktrader.h>
28#include <tdeparts/componentfactory.h>
29
30
31#include <tqlabel.h>
32#include <tqpushbutton.h>
33#include <tqlayout.h>
34#include <tqtooltip.h>
35#include <tqcheckbox.h>
36#include <tqbuttongroup.h>
37#include <tqradiobutton.h>
38#include <tqwidgetstack.h>
39#include <tqapplication.h>
40#include <tqtimer.h>
41#include <tqhbox.h>
42
43// works for both ListBox and ComboBox
44template <class T> static int setCurrentItem(T *box, const TQString& s)
45{
46 int cnt = box->count();
47 for (int i=0;i<cnt;++i) {
48 if (box->text(i) == s) {
49 box->setCurrentItem(i);
50 return i;
51 }
52 }
53 return -1;
54}
55
56
57//============================================================================
58//
59// class SingleConditionWidget (editor for one condition, used in ConditionEditWidget)
60//
61//============================================================================
62SingleConditionWidget::SingleConditionWidget(KScoringManager *m,TQWidget *p, const char *n)
63 : TQFrame(p,n), manager(m)
64{
65 TQBoxLayout *topL = new TQVBoxLayout(this,5);
66 TQBoxLayout *firstRow = new TQHBoxLayout(topL);
67 neg = new TQCheckBox(i18n("Not"),this);
68 TQToolTip::add(neg,i18n("Negate this condition"));
69 firstRow->addWidget(neg);
70 headers = new KComboBox(this);
71 headers->insertStringList(manager->getDefaultHeaders());
72 headers->setEditable( true );
73 TQToolTip::add(headers,i18n("Select the header to match this condition against"));
74 firstRow->addWidget(headers,1);
75 matches = new KComboBox(this);
76 matches->insertStringList(KScoringExpression::conditionNames());
77 TQToolTip::add(matches,i18n("Select the type of match"));
78 firstRow->addWidget(matches,1);
79 connect( matches, TQ_SIGNAL( activated( int ) ), TQ_SLOT( toggleRegExpButton( int ) ) );
80 TQHBoxLayout *secondRow = new TQHBoxLayout( topL );
81 secondRow->setSpacing( 1 );
82 expr = new KLineEdit( this );
83 TQToolTip::add(expr,i18n("The condition for the match"));
84 // reserve space for at least 20 characters
85 expr->setMinimumWidth(fontMetrics().maxWidth()*20);
86 secondRow->addWidget( expr );
87 regExpButton = new TQPushButton( i18n("Edit..."), this );
88 secondRow->addWidget( regExpButton );
89 connect( regExpButton, TQ_SIGNAL( clicked() ), TQ_SLOT( showRegExpDialog() ) );
90
91 // occupy at much width as possible
92 setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding,TQSizePolicy::Fixed));
93 setFrameStyle(Box | Sunken);
94 setLineWidth(1);
95}
96
97SingleConditionWidget::~SingleConditionWidget()
98{}
99
100void SingleConditionWidget::setCondition(KScoringExpression *e)
101{
102 neg->setChecked(e->isNeg());
103 headers->setCurrentText( e->getHeader() );
104 setCurrentItem(matches,KScoringExpression::getNameForCondition(e->getCondition()));
105 toggleRegExpButton( matches->currentItem() );
106 expr->setText(e->getExpression());
107}
108
109KScoringExpression* SingleConditionWidget::createCondition() const
110{
111 TQString head = headers->currentText();
112 TQString match = matches->currentText();
113 int condType = KScoringExpression::getConditionForName(match);
114 match = KScoringExpression::getTypeString(condType);
115 TQString cond = expr->text();
116 TQString negs = (neg->isChecked())?"1":"0";
117 return new KScoringExpression(head,match,cond,negs);
118}
119
120void SingleConditionWidget::clear()
121{
122 neg->setChecked(false);
123 expr->clear();
124}
125
126void SingleConditionWidget::toggleRegExpButton( int selected )
127{
128 bool isRegExp = (KScoringExpression::MATCH == selected ||
129 KScoringExpression::MATCHCS == selected) &&
130 !TDETrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty();
131 regExpButton->setEnabled( isRegExp );
132}
133
134void SingleConditionWidget::showRegExpDialog()
135{
136 TQDialog *editorDialog = KParts::ComponentFactory::createInstanceFromQuery<TQDialog>( "KRegExpEditor/KRegExpEditor" );
137 if ( editorDialog ) {
138 KRegExpEditorInterface *editor = static_cast<KRegExpEditorInterface *>( editorDialog->tqt_cast( "KRegExpEditorInterface" ) );
139 Q_ASSERT( editor ); // This should not fail!
140 editor->setRegExp( expr->text() );
141 editorDialog->exec();
142 expr->setText( editor->regExp() );
143 }
144}
145
146//============================================================================
147//
148// class ConditionEditWidget (the widget to edit the conditions of a rule)
149//
150//============================================================================
151ConditionEditWidget::ConditionEditWidget(KScoringManager *m, TQWidget *p, const char *n)
152 : KWidgetLister(1,8,p,n), manager(m)
153{
154 // create one initial widget
155 addWidgetAtEnd();
156}
157
158ConditionEditWidget::~ConditionEditWidget()
159{}
160
161TQWidget* ConditionEditWidget::createWidget(TQWidget *parent)
162{
163 return new SingleConditionWidget(manager,parent);
164}
165
167{
168 Q_ASSERT( w->isA("SingleConditionWidget") );
169 SingleConditionWidget *sw = dynamic_cast<SingleConditionWidget*>(w);
170 if (sw)
171 sw->clear();
172}
173
174void ConditionEditWidget::slotEditRule(KScoringRule *rule)
175{
176 KScoringRule::ScoreExprList l;
177 if (rule) l = rule->getExpressions();
178 if (!rule || l.count() == 0) {
179 slotClear();
180 } else {
181 setNumberOfShownWidgetsTo(l.count());
182 KScoringExpression *e = l.first();
183 SingleConditionWidget *scw = static_cast<SingleConditionWidget*>(mWidgetList.first());
184 while (e && scw) {
185 scw->setCondition(e);
186 e = l.next();
187 scw = static_cast<SingleConditionWidget*>(mWidgetList.next());
188 }
189 }
190}
191
192void ConditionEditWidget::updateRule(KScoringRule *rule)
193{
194 rule->cleanExpressions();
195 for(TQWidget *w = mWidgetList.first(); w; w = mWidgetList.next()) {
196 if (! w->isA("SingleConditionWidget")) {
197 kdWarning(5100) << "there is a widget in ConditionEditWidget "
198 << "which isn't a SingleConditionWidget" << endl;
199 } else {
200 SingleConditionWidget *saw = dynamic_cast<SingleConditionWidget*>(w);
201 if (saw)
202 rule->addExpression(saw->createCondition());
203 }
204 }
205}
206
207//============================================================================
208//
209// class SingleActionWidget (editor for one action, used in ActionEditWidget)
210//
211//============================================================================
212SingleActionWidget::SingleActionWidget(KScoringManager *m,TQWidget *p, const char *n)
213 : TQWidget(p,n), notifyEditor(0), scoreEditor(0), colorEditor(0),manager(m)
214{
215 TQHBoxLayout *topL = new TQHBoxLayout(this,0,5);
216 types = new KComboBox(this);
217 types->setEditable(false);
218 topL->addWidget(types);
219 stack = new TQWidgetStack(this);
220 topL->addWidget(stack);
221
222 dummyLabel = new TQLabel(i18n("Select an action."), stack);
223 stack->addWidget(dummyLabel, 0);
224
225 // init widget stack and the types combo box
226 int index = 1;
227 types->insertItem(TQString());
228 TQStringList l = ActionBase::userNames();
229 for ( TQStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
230 TQString name = *it;
231 int feature = ActionBase::getTypeForUserName(name);
232 if (manager->hasFeature(feature)) {
233 types->insertItem(name);
234 TQWidget *w=0;
235 switch (feature) {
236 case ActionBase::SETSCORE:
237 w = scoreEditor = new KIntSpinBox(-99999,99999,1,0,10, stack);
238 break;
239 case ActionBase::NOTIFY:
240 w = notifyEditor = new KLineEdit(stack);
241 break;
242 case ActionBase::COLOR:
243 w = colorEditor = new KColorCombo(stack);
244 break;
245 case ActionBase::MARKASREAD:
246 w = new TQLabel( stack ); // empty dummy
247 break;
248 }
249 if ( w )
250 stack->addWidget(w,index++);
251 }
252 }
253
254 connect(types,TQ_SIGNAL(activated(int)),stack,TQ_SLOT(raiseWidget(int)));
255
256 // raise the dummy label
257 types->setCurrentItem(0);
258 stack->raiseWidget(dummyLabel);
259}
260
261SingleActionWidget::~SingleActionWidget()
262{
263}
264
265void SingleActionWidget::setAction(ActionBase *act)
266{
267 kdDebug(5100) << "SingleActionWidget::setAction()" << endl;
268 setCurrentItem(types,ActionBase::userName(act->getType()));
269 int index = types->currentItem();
270 stack->raiseWidget(index);
271 switch (act->getType()) {
272 case ActionBase::SETSCORE:
273 scoreEditor->setValue(act->getValueString().toInt());
274 break;
275 case ActionBase::NOTIFY:
276 notifyEditor->setText(act->getValueString());
277 break;
278 case ActionBase::COLOR:
279 colorEditor->setColor(TQColor(act->getValueString()));
280 break;
281 case ActionBase::MARKASREAD:
282 // nothing
283 break;
284 default:
285 kdWarning(5100) << "unknown action type in SingleActionWidget::setAction()" << endl;
286 }
287}
288
289ActionBase* SingleActionWidget::createAction() const
290{
291 // no action selected...
292 if (types->currentText().isEmpty())
293 return 0;
294
295 int type = ActionBase::getTypeForUserName(types->currentText());
296 switch (type) {
297 case ActionBase::SETSCORE:
298 return new ActionSetScore(scoreEditor->value());
299 case ActionBase::NOTIFY:
300 return new ActionNotify(notifyEditor->text());
301 case ActionBase::COLOR:
302 return new ActionColor(TQString(colorEditor->color().name()));
303 case ActionBase::MARKASREAD:
304 return new ActionMarkAsRead();
305 default:
306 kdWarning(5100) << "unknown action type in SingleActionWidget::getValue()" << endl;
307 return 0;
308 }
309}
310
311void SingleActionWidget::clear()
312{
313 if (scoreEditor) scoreEditor->setValue(0);
314 if (notifyEditor) notifyEditor->clear();
315 if (colorEditor) colorEditor->setCurrentItem(0);
316 types->setCurrentItem(0);
317 stack->raiseWidget(dummyLabel);
318}
319
320//============================================================================
321//
322// class ActionEditWidget (the widget to edit the actions of a rule)
323//
324//============================================================================
325ActionEditWidget::ActionEditWidget(KScoringManager *m,TQWidget *p, const char *n)
326 : KWidgetLister(1,8,p,n), manager(m)
327{
328 // create one initial widget
330}
331
332ActionEditWidget::~ActionEditWidget()
333{}
334
335TQWidget* ActionEditWidget::createWidget( TQWidget *parent )
336{
337 return new SingleActionWidget(manager,parent);
338}
339
340void ActionEditWidget::slotEditRule(KScoringRule *rule)
341{
342 KScoringRule::ActionList l;
343 if (rule) l = rule->getActions();
344 if (!rule || l.count() == 0) {
345 slotClear();
346 } else {
347 setNumberOfShownWidgetsTo(l.count());
348 ActionBase *act = l.first();
349 SingleActionWidget *saw = static_cast<SingleActionWidget*>(mWidgetList.first());
350 while (act && saw) {
351 saw->setAction(act);
352 act = l.next();
353 saw = static_cast<SingleActionWidget*>(mWidgetList.next());
354 }
355 }
356}
357
358void ActionEditWidget::updateRule(KScoringRule *rule)
359{
360 rule->cleanActions();
361 for(TQWidget *w = mWidgetList.first(); w; w = mWidgetList.next()) {
362 if (! w->isA("SingleActionWidget")) {
363 kdWarning(5100) << "there is a widget in ActionEditWidget "
364 << "which isn't a SingleActionWidget" << endl;
365 } else {
366 SingleActionWidget *saw = dynamic_cast<SingleActionWidget*>(w);
367 if (saw)
368 {
369 ActionBase *act = saw->createAction();
370 if (act)
371 rule->addAction(act);
372 }
373 }
374 }
375}
376
378{
379 Q_ASSERT( w->isA("SingleActionWidget") );
380 SingleActionWidget *sw = dynamic_cast<SingleActionWidget*>(w);
381 if (sw)
382 sw->clear();
383}
384
385//============================================================================
386//
387// class RuleEditWidget (the widget to edit one rule)
388//
389//============================================================================
390RuleEditWidget::RuleEditWidget(KScoringManager *m,TQWidget *p, const char *n)
391 : TQWidget(p,n), dirty(false), manager(m), oldRuleName(TQString())
392{
393 kdDebug(5100) << "RuleEditWidget::RuleEditWidget()" << endl;
394 if ( !n ) setName( "RuleEditWidget" );
395 TQVBoxLayout *topLayout = new TQVBoxLayout( this, 5, KDialog::spacingHint() );
396
397 //------------- Name, Servers, Groups ---------------------
398 TQGroupBox *groupB = new TQGroupBox(i18n("Properties"),this);
399 topLayout->addWidget(groupB);
400 TQGridLayout* groupL = new TQGridLayout(groupB, 6,2, 8,5);
401 groupL->addRowSpacing(0, fontMetrics().lineSpacing()-4);
402
403 // name
404 ruleNameEdit = new KLineEdit( groupB, "ruleNameEdit" );
405 groupL->addWidget( ruleNameEdit, 1, 1 );
406 TQLabel *ruleNameLabel = new TQLabel(ruleNameEdit, i18n("&Name:"), groupB, "ruleNameLabel");
407 groupL->addWidget( ruleNameLabel, 1, 0 );
408
409 // groups
410 groupsEdit = new KLineEdit( groupB, "groupsEdit" );
411 groupL->addWidget( groupsEdit, 2, 1 );
412 TQLabel *groupsLabel = new TQLabel(groupsEdit, i18n("&Groups:"), groupB, "groupsLabel");
413 groupL->addWidget( groupsLabel, 2, 0 );
414
415 TQPushButton *groupsBtn = new TQPushButton(i18n("A&dd Group"), groupB);
416 connect(groupsBtn,TQ_SIGNAL(clicked()),TQ_SLOT(slotAddGroup()));
417 groupL->addWidget( groupsBtn, 3, 0 );
418
419 groupsBox = new KComboBox( false, groupB, "groupsBox" );
420 groupsBox->setDuplicatesEnabled(false);
421 groupsBox->insertStringList(manager->getGroups());
422 groupsBox->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed));
423 groupL->addWidget( groupsBox, 3, 1 );
424
425 // expires
426 expireCheck = new TQCheckBox(i18n("&Expire rule automatically"), groupB);
427 groupL->addMultiCellWidget( expireCheck, 4,4, 0,1 );
428 expireEdit = new KIntSpinBox(1,99999,1,30,10, groupB, "expireWidget");
429 //Init suffix
430 slotExpireEditChanged(30);
431 connect(expireEdit, TQ_SIGNAL(valueChanged(int)), TQ_SLOT(slotExpireEditChanged(int)));
432 groupL->addWidget( expireEdit, 5, 1 );
433 expireLabel = new TQLabel(expireEdit, i18n("&Rule is valid for:"), groupB, "expireLabel");
434 groupL->addWidget( expireLabel, 5, 0 );
435 expireLabel->setEnabled(false);
436 expireEdit->setEnabled(false);
437
438 connect(expireCheck, TQ_SIGNAL(toggled(bool)), expireLabel, TQ_SLOT(setEnabled(bool)));
439 connect(expireCheck, TQ_SIGNAL(toggled(bool)), expireEdit, TQ_SLOT(setEnabled(bool)));
440
441 //------------- Conditions ---------------------
442 TQGroupBox *groupConds = new TQGroupBox(i18n("Conditions"), this);
443 topLayout->addWidget(groupConds);
444 TQGridLayout *condL = new TQGridLayout(groupConds, 3,2, 8,5);
445
446 condL->addRowSpacing(0, fontMetrics().lineSpacing()-4);
447
448 TQButtonGroup *buttonGroup = new TQButtonGroup(groupConds);
449 buttonGroup->hide();
450 linkModeAnd = new TQRadioButton(i18n("Match a&ll conditions"), groupConds);
451 buttonGroup->insert(linkModeAnd);
452 condL->addWidget(linkModeAnd, 1,0);
453 linkModeOr = new TQRadioButton(i18n("Matc&h any condition"), groupConds);
454 buttonGroup->insert(linkModeOr);
455 condL->addWidget(linkModeOr, 1,1);
456 linkModeAnd->setChecked(true);
457
458 condEditor = new ConditionEditWidget(manager,groupConds);
459 condL->addMultiCellWidget(condEditor, 2,2, 0,1);
460 connect(condEditor,TQ_SIGNAL(widgetRemoved()),this,TQ_SLOT(slotShrink()));
461
462 //------------- Actions ---------------------
463 TQGroupBox *groupActions = new TQGroupBox(i18n("Actions"), this);
464 topLayout->addWidget(groupActions);
465 TQBoxLayout *actionL = new TQVBoxLayout(groupActions,8,5);
466 actionL->addSpacing(fontMetrics().lineSpacing()-4);
467 actionEditor = new ActionEditWidget(manager,groupActions);
468 actionL->addWidget(actionEditor);
469 connect(actionEditor,TQ_SIGNAL(widgetRemoved()),this,TQ_SLOT(slotShrink()));
470
471 topLayout->addStretch(1);
472
473 kdDebug(5100) << "constructed RuleEditWidget" << endl;
474}
475
476RuleEditWidget::~RuleEditWidget()
477{
478}
479
480void RuleEditWidget::slotEditRule(const TQString& ruleName)
481{
482 kdDebug(5100) << "RuleEditWidget::slotEditRule(" << ruleName << ")" << endl;
483// // first update the old rule if there is one
484// kdDebug(5100) << "let see if we have a rule with name " << oldRuleName << endl;
485// KScoringRule *rule;
486// if (!oldRuleName.isNull() && oldRuleName != ruleName) {
487// rule = manager->findRule(oldRuleName);
488// if (rule) {
489// kdDebug(5100) << "updating rule " << rule->getName() << endl;
490// updateRule(rule);
491// }
492// }
493
494 KScoringRule* rule = manager->findRule(ruleName);
495 if (!rule) {
496 kdDebug(5100) << "no rule for ruleName " << ruleName << endl;
497 clearContents();
498 return;
499 }
500 oldRuleName = rule->getName();
501 ruleNameEdit->setText(rule->getName());
502 groupsEdit->setText(rule->getGroups().join(";"));
503
504 bool b = rule->getExpireDate().isValid();
505 expireCheck->setChecked(b);
506 expireEdit->setEnabled(b);
507 expireLabel->setEnabled(b);
508 if (b)
509 expireEdit->setValue(TQDate::currentDate().daysTo(rule->getExpireDate()));
510 else
511 expireEdit->setValue(30);
512 if (rule->getLinkMode() == KScoringRule::AND) {
513 linkModeAnd->setChecked(true);
514 }
515 else {
516 linkModeOr->setChecked(true);
517 }
518
519 condEditor->slotEditRule(rule);
520 actionEditor->slotEditRule(rule);
521
522 kdDebug(5100) << "RuleEditWidget::slotEditRule() ready" << endl;
523}
524
525void RuleEditWidget::clearContents()
526{
527 ruleNameEdit->setText("");
528 groupsEdit->setText("");
529 expireCheck->setChecked(false);
530 expireEdit->setValue(30);
531 expireEdit->setEnabled(false);
532 condEditor->slotEditRule(0);
533 actionEditor->slotEditRule(0);
534 oldRuleName = TQString();
535}
536
537void RuleEditWidget::updateRule(KScoringRule *rule)
538{
539 oldRuleName = TQString();
540 TQString groups = groupsEdit->text();
541 if (groups.isEmpty())
542 rule->setGroups(TQStringList(".*"));
543 else
544 rule->setGroups(TQStringList::split(";",groups));
545 bool b = expireCheck->isChecked();
546 if (b)
547 rule->setExpireDate(TQDate::currentDate().addDays(expireEdit->value()));
548 else
549 rule->setExpireDate(TQDate());
550 actionEditor->updateRule(rule);
551 rule->setLinkMode(linkModeAnd->isChecked()?KScoringRule::AND:KScoringRule::OR);
552 condEditor->updateRule(rule);
553 if (rule->getName() != ruleNameEdit->text())
554 manager->setRuleName(rule,ruleNameEdit->text());
555}
556
557void RuleEditWidget::updateRule()
558{
559 KScoringRule *rule = manager->findRule(oldRuleName);
560 if (rule) updateRule(rule);
561}
562
563void RuleEditWidget::slotAddGroup()
564{
565 TQString grp = groupsBox->currentText();
566 if ( grp.isEmpty() )
567 return;
568 TQString txt = groupsEdit->text().stripWhiteSpace();
569 if ( txt == ".*" || txt.isEmpty() ) groupsEdit->setText(grp);
570 else groupsEdit->setText(txt + ";" + grp);
571}
572
573void RuleEditWidget::setDirty()
574{
575 kdDebug(5100) << "RuleEditWidget::setDirty()" << endl;
576 if (dirty) return;
577 dirty = true;
578}
579
580void RuleEditWidget::slotShrink()
581{
582 emit(shrink());
583}
584
585void RuleEditWidget::slotExpireEditChanged(int value)
586{
587 expireEdit->setSuffix(i18n(" day", " days", value));
588}
589
590//============================================================================
591//
592// class RuleListWidget (the widget for managing a list of rules)
593//
594//============================================================================
595RuleListWidget::RuleListWidget(KScoringManager *m, bool standalone, TQWidget *p, const char *n)
596 : TQWidget(p,n), alone(standalone), manager(m)
597{
598 kdDebug(5100) << "RuleListWidget::RuleListWidget()" << endl;
599 if (!n) setName("RuleListWidget");
600 TQVBoxLayout *topL = new TQVBoxLayout(this,standalone? 0:5,KDialog::spacingHint());
601 ruleList = new TDEListBox(this);
602 if (standalone) {
603 connect(ruleList,TQ_SIGNAL(doubleClicked(TQListBoxItem*)),
604 this,TQ_SLOT(slotEditRule(TQListBoxItem*)));
605 connect(ruleList,TQ_SIGNAL(returnPressed(TQListBoxItem*)),
606 this,TQ_SLOT(slotEditRule(TQListBoxItem*)));
607 }
608 connect(ruleList, TQ_SIGNAL(currentChanged(TQListBoxItem*)),
609 this, TQ_SLOT(slotRuleSelected(TQListBoxItem*)));
610 topL->addWidget(ruleList);
611
612 TQHBoxLayout *btnL = new TQHBoxLayout( topL, KDialog::spacingHint() );
613 mRuleUp = new TQPushButton( this );
614 mRuleUp->setPixmap( BarIcon( "go-up", TDEIcon::SizeSmall ) );
615 TQToolTip::add( mRuleUp, i18n("Move rule up") );
616 btnL->addWidget( mRuleUp );
617 connect( mRuleUp, TQ_SIGNAL( clicked() ), TQ_SLOT( slotRuleUp() ) );
618 mRuleDown = new TQPushButton( this );
619 mRuleDown->setPixmap( BarIcon( "go-down", TDEIcon::SizeSmall ) );
620 TQToolTip::add( mRuleDown, i18n("Move rule down") );
621 btnL->addWidget( mRuleDown );
622 connect( mRuleDown, TQ_SIGNAL( clicked() ), TQ_SLOT( slotRuleDown() ) );
623
624 btnL = new TQHBoxLayout( topL, KDialog::spacingHint() );
625 editRule=0L;
626 newRule = new TQPushButton(this);
627 newRule->setPixmap( BarIcon( "document-new", TDEIcon::SizeSmall ) );
628 TQToolTip::add(newRule,i18n("New rule")),
629 btnL->addWidget(newRule);
630 connect(newRule, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotNewRule()));
631 // if we're standalone, we need an additional edit button
632 if (standalone) {
633 editRule = new TQPushButton(this);
634 editRule->setIconSet( BarIconSet("edit", TDEIcon::SizeSmall) );
635 TQToolTip::add(editRule,i18n("Edit rule"));
636 btnL->addWidget(editRule);
637 connect(editRule,TQ_SIGNAL(clicked()),this,TQ_SLOT(slotEditRule()));
638 }
639 delRule = new TQPushButton(this);
640 delRule->setIconSet( BarIconSet( "edit-delete", TDEIcon::SizeSmall ) );
641 TQToolTip::add(delRule,i18n("Remove rule"));
642 btnL->addWidget(delRule);
643 connect(delRule, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotDelRule()));
644 copyRule = new TQPushButton(this);
645 copyRule->setIconSet(BarIconSet("edit-copy", TDEIcon::SizeSmall));
646 TQToolTip::add(copyRule,i18n("Copy rule"));
647 btnL->addWidget(copyRule);
648 connect(copyRule, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotCopyRule()));
649
650 // the group filter
651 TQBoxLayout *filterL = new TQVBoxLayout(topL,KDialog::spacingHint());
652 KComboBox *filterBox = new KComboBox(this);
653 TQStringList l = m->getGroups();
654 filterBox->insertItem(i18n("<all groups>"));
655 filterBox->insertStringList(l);
656 filterBox->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed));
657 connect(filterBox,TQ_SIGNAL(activated(const TQString&)),
658 this,TQ_SLOT(slotGroupFilter(const TQString&)));
659 slotGroupFilter(i18n("<all groups>"));
660 TQLabel *lab = new TQLabel(filterBox,i18n("Sho&w only rules for group:"),this);
661 filterL->addWidget(lab);
662 filterL->addWidget(filterBox);
663
664 connect(manager,TQ_SIGNAL(changedRules()),
665 this,TQ_SLOT(updateRuleList()));
666 connect(manager,TQ_SIGNAL(changedRuleName(const TQString&,const TQString&)),
667 this,TQ_SLOT(slotRuleNameChanged(const TQString&,const TQString&)));
668
669 updateRuleList();
670 updateButton();
671}
672
673RuleListWidget::~RuleListWidget()
674{
675}
676
677void RuleListWidget::updateButton()
678{
679 bool state = ruleList->count() > 0;
680 if(editRule)
681 editRule->setEnabled(state);
682 delRule->setEnabled(state);
683 copyRule->setEnabled(state);
684
685 TQListBoxItem *item = ruleList->item( ruleList->currentItem() );
686 if ( item ) {
687 mRuleUp->setEnabled( item->prev() != 0 );
688 mRuleDown->setEnabled( item->next() != 0 );
689 }
690}
691
692void RuleListWidget::updateRuleList()
693{
694 emit leavingRule();
695 kdDebug(5100) << "RuleListWidget::updateRuleList()" << endl;
696 TQString curr = ruleList->currentText();
697 ruleList->clear();
698 if (group == i18n("<all groups>")) {
699 TQStringList l = manager->getRuleNames();
700 ruleList->insertStringList(l);
701 } else {
702 KScoringManager::ScoringRuleList l = manager->getAllRules();
703 for (KScoringRule* rule = l.first(); rule; rule = l.next() ) {
704 if (rule->matchGroup(group)) ruleList->insertItem(rule->getName());
705 }
706 }
707 int index = setCurrentItem(ruleList,curr);
708 if (index <0) {
709 ruleList->setCurrentItem(0);
710 slotRuleSelected(ruleList->currentText());
711 }
712 else {
713 slotRuleSelected(curr);
714 }
715}
716
717void RuleListWidget::updateRuleList(const KScoringRule *rule)
718{
719 kdDebug(5100) << "RuleListWidget::updateRuleList(" << rule->getName() << ")" << endl;
720 TQString name = rule->getName();
721 updateRuleList();
722 slotRuleSelected(name);
723}
724
725void RuleListWidget::slotRuleNameChanged(const TQString& oldName, const TQString& newName)
726{
727 int ind = ruleList->currentItem();
728 for (uint i=0;i<ruleList->count();++i)
729 if (ruleList->text(i) == oldName) {
730 ruleList->changeItem(newName,i);
731 ruleList->setCurrentItem(ind);
732 return;
733 }
734}
735
736void RuleListWidget::slotEditRule(const TQString& s)
737{
738 emit ruleEdited(s);
739}
740
741void RuleListWidget::slotEditRule()
742{
743 if (ruleList->currentItem() >= 0) {
744 emit ruleEdited(ruleList->currentText());
745 }
746 else if (ruleList->count() == 0)
747 emit ruleEdited(TQString());
748}
749
750void RuleListWidget::slotEditRule(TQListBoxItem* item)
751{
752 slotEditRule(item->text());
753}
754
755void RuleListWidget::slotGroupFilter(const TQString& s)
756{
757 group = s;
758 updateRuleList();
759}
760
761void RuleListWidget::slotRuleSelected(const TQString& ruleName)
762{
763 emit leavingRule();
764 kdDebug(5100) << "RuleListWidget::slotRuleSelected(" << ruleName << ")" << endl;
765 if (ruleName != ruleList->currentText()) {
766 setCurrentItem(ruleList,ruleName);
767 }
768 updateButton();
769 emit ruleSelected(ruleName);
770}
771
772void RuleListWidget::slotRuleSelected(TQListBoxItem *item)
773{
774 if (!item) return;
775 TQString ruleName = item->text();
776 slotRuleSelected(ruleName);
777}
778
779void RuleListWidget::slotRuleSelected(int index)
780{
781 uint idx = index;
782 if (idx >= ruleList->count()) return;
783 TQString ruleName = ruleList->text(index);
784 slotRuleSelected(ruleName);
785}
786
787void RuleListWidget::slotNewRule()
788{
789 emit leavingRule();
790 KScoringRule *rule = manager->addRule();
791 updateRuleList(rule);
792 if (alone) slotEditRule(rule->getName());
793 updateButton();
794}
795
796void RuleListWidget::slotDelRule()
797{
798 KScoringRule *rule = manager->findRule(ruleList->currentText());
799 if (rule)
800 manager->deleteRule(rule);
801 // goto the next rule
802 if (!alone) slotEditRule();
803 updateButton();
804}
805
806void RuleListWidget::slotCopyRule()
807{
808 emit leavingRule();
809 TQString ruleName = ruleList->currentText();
810 KScoringRule *rule = manager->findRule(ruleName);
811 if (rule) {
812 KScoringRule *nrule = manager->copyRule(rule);
813 updateRuleList(nrule);
814 slotEditRule(nrule->getName());
815 }
816 updateButton();
817}
818
819void RuleListWidget::slotRuleUp()
820{
821 KScoringRule *rule = 0, *below = 0;
822 TQListBoxItem *item = ruleList->item( ruleList->currentItem() );
823 if ( item ) {
824 rule = manager->findRule( item->text() );
825 item = item->prev();
826 if ( item )
827 below = manager->findRule( item->text() );
828 }
829 if ( rule && below )
830 manager->moveRuleAbove( rule, below );
831 updateRuleList();
832 updateButton();
833}
834
835void RuleListWidget::slotRuleDown()
836{
837 KScoringRule *rule = 0, *above = 0;
838 TQListBoxItem *item = ruleList->item( ruleList->currentItem() );
839 if ( item ) {
840 rule = manager->findRule( item->text() );
841 item = item->next();
842 if ( item )
843 above = manager->findRule( item->text() );
844 }
845 if ( rule && above )
846 manager->moveRuleBelow( rule, above );
847 updateRuleList();
848 updateButton();
849}
850
851//============================================================================
852//
853// class KScoringEditor (the score edit dialog)
854//
855//============================================================================
856KScoringEditor* KScoringEditor::scoreEditor = 0;
857
858KScoringEditor::KScoringEditor(KScoringManager* m,
859 TQWidget *parent, const char *name)
860 : KDialogBase(parent,name,false,i18n("Rule Editor"),Ok|Apply|Cancel,Ok,true), manager(m)
861{
862 manager->pushRuleList();
863 if (!scoreEditor) scoreEditor = this;
864 kdDebug(5100) << "KScoringEditor::KScoringEditor()" << endl;
865 if (!name) setName("KScoringEditor");
866 // the left side gives an overview about all rules, the right side
867 // shows a detailed view of an selected rule
868 TQWidget *w = new TQWidget(this);
869 setMainWidget(w);
870 TQHBoxLayout *hbl = new TQHBoxLayout(w,0,spacingHint());
871 ruleLister = new RuleListWidget(manager,false,w);
872 hbl->addWidget(ruleLister);
873 ruleEditor = new RuleEditWidget(manager,w);
874 hbl->addWidget(ruleEditor);
875 connect(ruleLister,TQ_SIGNAL(ruleSelected(const TQString&)),
876 ruleEditor, TQ_SLOT(slotEditRule(const TQString&)));
877 connect(ruleLister, TQ_SIGNAL(leavingRule()),
878 ruleEditor, TQ_SLOT(updateRule()));
879 connect(ruleEditor, TQ_SIGNAL(shrink()), TQ_SLOT(slotShrink()));
880 connect(this,TQ_SIGNAL(finished()),TQ_SLOT(slotFinished()));
881 ruleLister->slotRuleSelected(0);
882 resize(550, sizeHint().height());
883}
884
885void KScoringEditor::setDirty()
886{
887 TQPushButton *applyBtn = actionButton(Apply);
888 applyBtn->setEnabled(true);
889}
890
891KScoringEditor::~KScoringEditor()
892{
893 scoreEditor = 0;
894}
895
896KScoringEditor* KScoringEditor::createEditor(KScoringManager* m,
897 TQWidget *parent, const char *name)
898{
899 if (scoreEditor) return scoreEditor;
900 else return new KScoringEditor(m,parent,name);
901}
902
903void KScoringEditor::setRule(KScoringRule* r)
904{
905 kdDebug(5100) << "KScoringEditor::setRule(" << r->getName() << ")" << endl;
906 TQString ruleName = r->getName();
907 ruleLister->slotRuleSelected(ruleName);
908}
909
910void KScoringEditor::slotShrink()
911{
912 TQTimer::singleShot(5, this, TQ_SLOT(slotDoShrink()));
913}
914
915void KScoringEditor::slotDoShrink()
916{
917 updateGeometry();
918 TQApplication::sendPostedEvents();
919 resize(width(),sizeHint().height());
920}
921
922void KScoringEditor::slotApply()
923{
924 TQString ruleName = ruleLister->currentRule();
925 KScoringRule *rule = manager->findRule(ruleName);
926 if (rule) {
927 ruleEditor->updateRule(rule);
928 ruleLister->updateRuleList(rule);
929 }
930 manager->removeTOS();
931 manager->pushRuleList();
932}
933
934void KScoringEditor::slotOk()
935{
936 slotApply();
937 manager->removeTOS();
938 KDialogBase::slotOk();
939 manager->editorReady();
940}
941
942void KScoringEditor::slotCancel()
943{
944 manager->popRuleList();
945 KDialogBase::slotCancel();
946}
947
948void KScoringEditor::slotFinished()
949{
950 delayedDestruct();
951}
952
953//============================================================================
954//
955// class KScoringEditorWidgetDialog (a dialog for the KScoringEditorWidget)
956//
957//============================================================================
958KScoringEditorWidgetDialog::KScoringEditorWidgetDialog(KScoringManager *m, const TQString& r, TQWidget *p, const char *n)
959 : KDialogBase(p,n,true,i18n("Edit Rule"),
960 KDialogBase::Ok|KDialogBase::Apply|KDialogBase::Close,
961 KDialogBase::Ok,true),
962 manager(m), ruleName(r)
963{
964 TQFrame *f = makeMainWidget();
965 TQBoxLayout *topL = new TQVBoxLayout(f);
966 ruleEditor = new RuleEditWidget(manager,f);
967 connect(ruleEditor, TQ_SIGNAL(shrink()), TQ_SLOT(slotShrink()));
968 topL->addWidget(ruleEditor);
969 ruleEditor->slotEditRule(ruleName);
970 resize(0,0);
971}
972
973void KScoringEditorWidgetDialog::slotApply()
974{
975 KScoringRule *rule = manager->findRule(ruleName);
976 if (rule) {
977 ruleEditor->updateRule(rule);
978 ruleName = rule->getName();
979 }
980}
981
982void KScoringEditorWidgetDialog::slotOk()
983{
984 slotApply();
985 KDialogBase::slotOk();
986}
987
988void KScoringEditorWidgetDialog::slotShrink()
989{
990 TQTimer::singleShot(5, this, TQ_SLOT(slotDoShrink()));
991}
992
993void KScoringEditorWidgetDialog::slotDoShrink()
994{
995 updateGeometry();
996 TQApplication::sendPostedEvents();
997 resize(width(),sizeHint().height());
998}
999
1000//============================================================================
1001//
1002// class KScoringEditorWidget (a reusable widget for config dialog...)
1003//
1004//============================================================================
1005KScoringEditorWidget::KScoringEditorWidget(KScoringManager *m,TQWidget *p, const char *n)
1006 : TQWidget(p,n), manager(m)
1007{
1008 TQBoxLayout *topL = new TQVBoxLayout(this);
1009 ruleLister = new RuleListWidget(manager,true,this);
1010 topL->addWidget(ruleLister);
1011 connect(ruleLister,TQ_SIGNAL(ruleEdited(const TQString&)),
1012 this,TQ_SLOT(slotRuleEdited(const TQString &)));
1013}
1014
1015KScoringEditorWidget::~KScoringEditorWidget()
1016{
1017 manager->editorReady();
1018}
1019
1020void KScoringEditorWidget::slotRuleEdited(const TQString& ruleName)
1021{
1022 KScoringEditorWidgetDialog dlg(manager,ruleName,this);
1023 dlg.exec();
1024 ruleLister->updateRuleList();
1025}
1026
1027#include "kscoringeditor.moc"
Base class for other Action classes.
Definition: kscoring.h:84
this widget implements the action editor
void clearWidget(TQWidget *)
Called to clear a given widget.
TQWidget * createWidget(TQWidget *parent)
Because QT 2.x does not support signals/slots in template classes, we are forced to emulate this by f...
this widget implements the conditions editor
TQWidget * createWidget(TQWidget *)
Because QT 2.x does not support signals/slots in template classes, we are forced to emulate this by f...
void clearWidget(TQWidget *)
Called to clear a given widget.
Widget that manages a list of other widgets (incl.
Definition: kwidgetlister.h:66
virtual void setNumberOfShownWidgetsTo(int aNum)
Sets the number of widgets on scrren to exactly aNum.
virtual void slotClear()
Called whenever the user clicks on the 'clear' button.
void widgetRemoved()
This signal is emitted whenever a widget was removed.
TQPtrList< TQWidget > mWidgetList
The list of widgets.
virtual void addWidgetAtEnd(TQWidget *w=0)
Adds a single widget.
This widget implements the rule editor.
This widget shows a list of rules with buttons for copy, delete aso.
this widget implements an editor for one action.
this widget implements an editor for one condition.