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