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
44 template <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 //============================================================================
62 SingleConditionWidget::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, TQT_SIGNAL( activated( int ) ), TQT_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, TQT_SIGNAL( clicked() ), TQT_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 
97 SingleConditionWidget::~SingleConditionWidget()
98 {}
99 
100 void 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 
109 KScoringExpression* 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 
120 void SingleConditionWidget::clear()
121 {
122  neg->setChecked(false);
123  expr->clear();
124 }
125 
126 void 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 
134 void 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 //============================================================================
151 ConditionEditWidget::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 
158 ConditionEditWidget::~ConditionEditWidget()
159 {}
160 
161 TQWidget* 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 
174 void 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 
192 void 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 //============================================================================
212 SingleActionWidget::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,TQT_SIGNAL(activated(int)),stack,TQT_SLOT(raiseWidget(int)));
255 
256  // raise the dummy label
257  types->setCurrentItem(0);
258  stack->raiseWidget(dummyLabel);
259 }
260 
261 SingleActionWidget::~SingleActionWidget()
262 {
263 }
264 
265 void 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 
289 ActionBase* 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 
311 void 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 //============================================================================
325 ActionEditWidget::ActionEditWidget(KScoringManager *m,TQWidget *p, const char *n)
326  : KWidgetLister(1,8,p,n), manager(m)
327 {
328  // create one initial widget
329  addWidgetAtEnd();
330 }
331 
332 ActionEditWidget::~ActionEditWidget()
333 {}
334 
335 TQWidget* ActionEditWidget::createWidget( TQWidget *parent )
336 {
337  return new SingleActionWidget(manager,parent);
338 }
339 
340 void 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 
358 void 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 //============================================================================
390 RuleEditWidget::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,TQT_SIGNAL(clicked()),TQT_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, TQT_SIGNAL(valueChanged(int)), TQT_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, TQT_SIGNAL(toggled(bool)), expireLabel, TQT_SLOT(setEnabled(bool)));
439  connect(expireCheck, TQT_SIGNAL(toggled(bool)), expireEdit, TQT_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,TQT_SIGNAL(widgetRemoved()),this,TQT_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,TQT_SIGNAL(widgetRemoved()),this,TQT_SLOT(slotShrink()));
470 
471  topLayout->addStretch(1);
472 
473  kdDebug(5100) << "constructed RuleEditWidget" << endl;
474 }
475 
476 RuleEditWidget::~RuleEditWidget()
477 {
478 }
479 
480 void 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 
525 void 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 
537 void 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 
557 void RuleEditWidget::updateRule()
558 {
559  KScoringRule *rule = manager->findRule(oldRuleName);
560  if (rule) updateRule(rule);
561 }
562 
563 void 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 
573 void RuleEditWidget::setDirty()
574 {
575  kdDebug(5100) << "RuleEditWidget::setDirty()" << endl;
576  if (dirty) return;
577  dirty = true;
578 }
579 
580 void RuleEditWidget::slotShrink()
581 {
582  emit(shrink());
583 }
584 
585 void 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 //============================================================================
595 RuleListWidget::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,TQT_SIGNAL(doubleClicked(TQListBoxItem*)),
604  this,TQT_SLOT(slotEditRule(TQListBoxItem*)));
605  connect(ruleList,TQT_SIGNAL(returnPressed(TQListBoxItem*)),
606  this,TQT_SLOT(slotEditRule(TQListBoxItem*)));
607  }
608  connect(ruleList, TQT_SIGNAL(currentChanged(TQListBoxItem*)),
609  this, TQT_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, TQT_SIGNAL( clicked() ), TQT_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, TQT_SIGNAL( clicked() ), TQT_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, TQT_SIGNAL(clicked()), this, TQT_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,TQT_SIGNAL(clicked()),this,TQT_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, TQT_SIGNAL(clicked()), this, TQT_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, TQT_SIGNAL(clicked()), this, TQT_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,TQT_SIGNAL(activated(const TQString&)),
658  this,TQT_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,TQT_SIGNAL(changedRules()),
665  this,TQT_SLOT(updateRuleList()));
666  connect(manager,TQT_SIGNAL(changedRuleName(const TQString&,const TQString&)),
667  this,TQT_SLOT(slotRuleNameChanged(const TQString&,const TQString&)));
668 
669  updateRuleList();
670  updateButton();
671 }
672 
673 RuleListWidget::~RuleListWidget()
674 {
675 }
676 
677 void 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 
692 void 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 
717 void 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 
725 void 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 
736 void RuleListWidget::slotEditRule(const TQString& s)
737 {
738  emit ruleEdited(s);
739 }
740 
741 void 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 
750 void RuleListWidget::slotEditRule(TQListBoxItem* item)
751 {
752  slotEditRule(item->text());
753 }
754 
755 void RuleListWidget::slotGroupFilter(const TQString& s)
756 {
757  group = s;
758  updateRuleList();
759 }
760 
761 void 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 
772 void RuleListWidget::slotRuleSelected(TQListBoxItem *item)
773 {
774  if (!item) return;
775  TQString ruleName = item->text();
776  slotRuleSelected(ruleName);
777 }
778 
779 void 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 
787 void RuleListWidget::slotNewRule()
788 {
789  emit leavingRule();
790  KScoringRule *rule = manager->addRule();
791  updateRuleList(rule);
792  if (alone) slotEditRule(rule->getName());
793  updateButton();
794 }
795 
796 void 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 
806 void 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 
819 void 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 
835 void 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 //============================================================================
856 KScoringEditor* KScoringEditor::scoreEditor = 0;
857 
858 KScoringEditor::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,TQT_SIGNAL(ruleSelected(const TQString&)),
876  ruleEditor, TQT_SLOT(slotEditRule(const TQString&)));
877  connect(ruleLister, TQT_SIGNAL(leavingRule()),
878  ruleEditor, TQT_SLOT(updateRule()));
879  connect(ruleEditor, TQT_SIGNAL(shrink()), TQT_SLOT(slotShrink()));
880  connect(this,TQT_SIGNAL(finished()),TQT_SLOT(slotFinished()));
881  ruleLister->slotRuleSelected(0);
882  resize(550, sizeHint().height());
883 }
884 
885 void KScoringEditor::setDirty()
886 {
887  TQPushButton *applyBtn = actionButton(Apply);
888  applyBtn->setEnabled(true);
889 }
890 
891 KScoringEditor::~KScoringEditor()
892 {
893  scoreEditor = 0;
894 }
895 
896 KScoringEditor* 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 
903 void KScoringEditor::setRule(KScoringRule* r)
904 {
905  kdDebug(5100) << "KScoringEditor::setRule(" << r->getName() << ")" << endl;
906  TQString ruleName = r->getName();
907  ruleLister->slotRuleSelected(ruleName);
908 }
909 
910 void KScoringEditor::slotShrink()
911 {
912  TQTimer::singleShot(5, this, TQT_SLOT(slotDoShrink()));
913 }
914 
915 void KScoringEditor::slotDoShrink()
916 {
917  updateGeometry();
918  TQApplication::sendPostedEvents();
919  resize(width(),sizeHint().height());
920 }
921 
922 void 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 
934 void KScoringEditor::slotOk()
935 {
936  slotApply();
937  manager->removeTOS();
938  KDialogBase::slotOk();
939  manager->editorReady();
940 }
941 
942 void KScoringEditor::slotCancel()
943 {
944  manager->popRuleList();
945  KDialogBase::slotCancel();
946 }
947 
948 void KScoringEditor::slotFinished()
949 {
950  delayedDestruct();
951 }
952 
953 //============================================================================
954 //
955 // class KScoringEditorWidgetDialog (a dialog for the KScoringEditorWidget)
956 //
957 //============================================================================
958 KScoringEditorWidgetDialog::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, TQT_SIGNAL(shrink()), TQT_SLOT(slotShrink()));
968  topL->addWidget(ruleEditor);
969  ruleEditor->slotEditRule(ruleName);
970  resize(0,0);
971 }
972 
973 void KScoringEditorWidgetDialog::slotApply()
974 {
975  KScoringRule *rule = manager->findRule(ruleName);
976  if (rule) {
977  ruleEditor->updateRule(rule);
978  ruleName = rule->getName();
979  }
980 }
981 
982 void KScoringEditorWidgetDialog::slotOk()
983 {
984  slotApply();
985  KDialogBase::slotOk();
986 }
987 
988 void KScoringEditorWidgetDialog::slotShrink()
989 {
990  TQTimer::singleShot(5, this, TQT_SLOT(slotDoShrink()));
991 }
992 
993 void 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 //============================================================================
1005 KScoringEditorWidget::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,TQT_SIGNAL(ruleEdited(const TQString&)),
1012  this,TQT_SLOT(slotRuleEdited(const TQString &)));
1013 }
1014 
1015 KScoringEditorWidget::~KScoringEditorWidget()
1016 {
1017  manager->editorReady();
1018 }
1019 
1020 void KScoringEditorWidget::slotRuleEdited(const TQString& ruleName)
1021 {
1022  KScoringEditorWidgetDialog dlg(manager,ruleName,this);
1023  dlg.exec();
1024  ruleLister->updateRuleList();
1025 }
1026 
1027 #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.