• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdepim
  • Sitemap
  • Contact Us
 

libkdepim

kscoringeditor.cpp

Go to the documentation of this file.
00001 /*
00002   kscoringeditor.cpp
00003 
00004   Copyright (c) 2001 Mathias Waack <mathias@atoll-net.de>
00005   Copyright (C) 2005 by Volker Krause <volker.krause@rwth-aachen.de>
00006 
00007   Author: Mathias Waack <mathias@atoll-net.de>
00008 
00009   This program is free software; you can redistribute it and/or modify
00010   it under the terms of the GNU General Public License as published by
00011   the Free Software Foundation; either version 2 of the License, or
00012   (at your option) any later version.
00013   You should have received a copy of the GNU General Public License
00014   along with this program; if not, write to the Free Software Foundation,
00015   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US
00016 */
00017 
00018 #undef QT_NO_COMPAT
00019 
00020 #include "kscoringeditor.h"
00021 #include "kscoring.h"
00022 
00023 #include <KDebug>
00024 #include <KColorCombo>
00025 #include <KComboBox>
00026 #include <KIconLoader>
00027 #include <KIntSpinBox>
00028 #include <KLineEdit>
00029 #include <KLocale>
00030 #include <kregexpeditorinterface.h>
00031 #include <KServiceTypeTrader>
00032 #include <KPushButton>
00033 #include <kparts/componentfactory.h>
00034 
00035 #include <QLabel>
00036 #include <QPushButton>
00037 #include <QLayout>
00038 #include <QCheckBox>
00039 #include <QRadioButton>
00040 #include <QApplication>
00041 #include <QTimer>
00042 #include <QButtonGroup>
00043 #include <QGroupBox>
00044 #include <QGridLayout>
00045 #include <QFrame>
00046 #include <QHBoxLayout>
00047 #include <QBoxLayout>
00048 #include <QVBoxLayout>
00049 
00050 using namespace KPIM;
00051 
00052 static int setCurrentItem( K3ListBox *box, const QString &s )
00053 {
00054   int cnt = box->count();
00055   for ( int i=0; i<cnt; ++i ) {
00056     if ( box->text( i ) == s ) {
00057       box->setCurrentItem( i );
00058       return i;
00059     }
00060   }
00061   return -1;
00062 }
00063 
00064 //============================================================================
00065 //
00066 // class SingleConditionWidget (editor for one condition, used in ConditionEditWidget)
00067 //
00068 //============================================================================
00069 SingleConditionWidget::SingleConditionWidget( KScoringManager *m, QWidget *p, const char * )
00070   : QFrame( p ), manager( m )
00071 {
00072   QBoxLayout *topL = new QVBoxLayout( this );
00073   topL->setMargin( 5 );
00074   QBoxLayout *firstRow = new QHBoxLayout();
00075   topL->addItem( firstRow );
00076   neg = new QCheckBox( i18n( "Not" ), this );
00077   neg->setToolTip( i18n( "Negate this condition" ) );
00078   firstRow->addWidget( neg );
00079   headers = new KComboBox( this );
00080   headers->addItems( manager->getDefaultHeaders() );
00081   headers->setEditable( true );
00082   headers->setToolTip( i18n( "Select the header to match this condition against" ) );
00083   firstRow->addWidget( headers, 1 );
00084   matches = new KComboBox( this );
00085   matches->addItems( KScoringExpression::conditionNames() );
00086   matches->setToolTip( i18n( "Select the type of match" ) );
00087   firstRow->addWidget( matches, 1 );
00088   connect( matches, SIGNAL( activated( int ) ), SLOT( toggleRegExpButton( int ) ) );
00089   QHBoxLayout *secondRow = new QHBoxLayout();
00090   secondRow->setSpacing( 1 );
00091   topL->addItem( secondRow );
00092 
00093   expr = new KLineEdit( this );
00094   expr->setToolTip( i18n( "The condition for the match" ) );
00095   // reserve space for at least 20 characters
00096   expr->setMinimumWidth( fontMetrics().maxWidth() * 20 );
00097   secondRow->addWidget( expr );
00098   regExpButton = new QPushButton( i18n( "Edit..." ), this );
00099   secondRow->addWidget( regExpButton );
00100   connect( regExpButton, SIGNAL( clicked() ), SLOT( showRegExpDialog() ) );
00101 
00102   regExpButton->setEnabled(!KServiceTypeTrader::self()->query( "KRegExpEditor/KRegExpEditor" ).isEmpty());
00103 
00104   // occupy at much width as possible
00105   setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
00106   setFrameStyle( Box | Sunken );
00107   setLineWidth( 1 );
00108 }
00109 
00110 SingleConditionWidget::~SingleConditionWidget()
00111 {}
00112 
00113 void SingleConditionWidget::setCondition( KScoringExpression *e )
00114 {
00115   neg->setChecked( e->isNeg() );
00116   headers->setItemText( headers->currentIndex(), e->getHeader() );
00117   matches->setCurrentItem( KScoringExpression::getNameForCondition( e->getCondition() ) );
00118   toggleRegExpButton( matches->currentIndex() );
00119   expr->setText( e->getExpression() );
00120 }
00121 
00122 KScoringExpression *SingleConditionWidget::createCondition() const
00123 {
00124   QString head = headers->currentText();
00125   QString match = matches->currentText();
00126   int condType = KScoringExpression::getConditionForName( match );
00127   match = KScoringExpression::getTypeString( condType );
00128   QString cond = expr->text();
00129   QString negs = ( neg->isChecked() ) ? "1" : "0";
00130   return new KScoringExpression( head, match, cond, negs );
00131 }
00132 
00133 void SingleConditionWidget::clear()
00134 {
00135   neg->setChecked( false );
00136   expr->clear();
00137 }
00138 
00139 void SingleConditionWidget::toggleRegExpButton( int selected )
00140 {
00141   bool isRegExp = ( KScoringExpression::MATCH == selected ||
00142                     KScoringExpression::MATCHCS == selected ) &&
00143                   !KServiceTypeTrader::self()->query( "KRegExpEditor/KRegExpEditor" ).isEmpty();
00144   regExpButton->setEnabled( isRegExp );
00145 }
00146 
00147 void SingleConditionWidget::showRegExpDialog()
00148 {
00149   QDialog *editorDialog =
00150     KParts::ComponentFactory::createPartInstanceFromQuery<QDialog>(
00151       "KRegExpEditor/KRegExpEditor", QString() );
00152   if ( editorDialog ) {
00153     KRegExpEditorInterface *editor = qobject_cast<KRegExpEditorInterface *>( editorDialog );
00154     Q_ASSERT( editor ); // This should not fail!
00155     editor->setRegExp( expr->text() );
00156     editorDialog->exec();
00157     expr->setText( editor->regExp() );
00158   }
00159 }
00160 
00161 //============================================================================
00162 //
00163 // class ConditionEditWidget (the widget to edit the conditions of a rule)
00164 //
00165 //============================================================================
00166 ConditionEditWidget::ConditionEditWidget( KScoringManager *m, QWidget *p, const char *n )
00167   : KWidgetLister( 1, 8, p, n ), manager( m )
00168 {
00169   // create one initial widget
00170   addWidgetAtEnd();
00171 }
00172 
00173 ConditionEditWidget::~ConditionEditWidget()
00174 {}
00175 
00176 QWidget *ConditionEditWidget::createWidget( QWidget *parent )
00177 {
00178   return new SingleConditionWidget( manager, parent );
00179 }
00180 
00181 void ConditionEditWidget::clearWidget( QWidget *w )
00182 {
00183   SingleActionWidget *sw =  qobject_cast<SingleActionWidget *>(w);
00184   Q_ASSERT( w );
00185   if ( sw ) {
00186     sw->clear();
00187   }
00188 }
00189 
00190 void ConditionEditWidget::slotEditRule( KScoringRule *rule )
00191 {
00192   KScoringRule::ScoreExprList l;
00193   if ( rule ) {
00194     l = rule->getExpressions();
00195   }
00196   if ( !rule || l.count() == 0 ) {
00197     slotClear();
00198   } else {
00199     setNumberOfShownWidgetsTo( l.count() );
00200     KScoringExpression *e = l.first();
00201     QList<QWidget*>::ConstIterator it = mWidgetList.constBegin();
00202     while ( e && it != mWidgetList.constEnd() ) {
00203       SingleConditionWidget *scw = static_cast<SingleConditionWidget *>( *it );
00204       scw->setCondition( e );
00205       e = l.next();
00206       ++it;
00207     }
00208   }
00209 }
00210 
00211 void ConditionEditWidget::updateRule( KScoringRule *rule )
00212 {
00213   rule->cleanExpressions();
00214   foreach ( QWidget* w, mWidgetList ) {
00215       if ( QString( w->metaObject()->className() ) != "SingleConditionWidget" ) {
00216       kWarning(5100) <<"there is a widget in ConditionEditWidget"
00217                      << "which isn't a SingleConditionWidget";
00218     } else {
00219       SingleConditionWidget *saw = dynamic_cast<SingleConditionWidget*>( w );
00220       if ( saw ) {
00221         rule->addExpression( saw->createCondition() );
00222       }
00223     }
00224   }
00225 }
00226 
00227 //============================================================================
00228 //
00229 // class SingleActionWidget (editor for one action, used in ActionEditWidget)
00230 //
00231 //============================================================================
00232 SingleActionWidget::SingleActionWidget( KScoringManager *m, QWidget *p, const char *n )
00233   : QWidget( p ), notifyEditor( 0 ), scoreEditor( 0 ),
00234     colorEditor( 0 ), manager( m )
00235 {
00236   setObjectName( n );
00237   QHBoxLayout *topL = new QHBoxLayout( this );
00238   topL->setMargin( 0 );
00239   topL->setSpacing( 5 );
00240 
00241   types = new KComboBox( this );
00242   types->setEditable( false );
00243   topL->addWidget( types );
00244   stack = new QStackedWidget( this );
00245   topL->addWidget( stack );
00246 
00247   dummyLabel = new QLabel( i18n( "Select an action." ), stack );
00248   stack->insertWidget( 0, dummyLabel );
00249 
00250   // init widget stack and the types combo box
00251   int index = 1;
00252   types->addItem( QString() );
00253   QStringList l = ActionBase::userNames();
00254   for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
00255     QString name = *it;
00256     int feature = ActionBase::getTypeForUserName( name );
00257     if ( manager->hasFeature( feature ) ) {
00258       types->addItem( name );
00259       QWidget *w = 0;
00260       switch( feature ) {
00261       case ActionBase::SETSCORE:
00262         w = scoreEditor = new KIntSpinBox( stack );
00263         scoreEditor->setRange( -99999, 99999 );
00264         scoreEditor->setValue( 30 );
00265         break;
00266       case ActionBase::NOTIFY:
00267         w = notifyEditor = new KLineEdit( stack );
00268         break;
00269       case ActionBase::COLOR:
00270         w = colorEditor = new KColorCombo( stack );
00271         break;
00272       case ActionBase::MARKASREAD:
00273         w = new QLabel( stack ); // empty dummy
00274         break;
00275       }
00276       if ( w ) {
00277         stack->insertWidget( index++, w );
00278       }
00279     }
00280   }
00281 
00282   connect( types, SIGNAL(activated(int)), stack, SLOT(setCurrentIndex(int)) );
00283 
00284   // raise the dummy label
00285   types->setCurrentIndex( 0 );
00286   stack->setCurrentWidget( dummyLabel );
00287 }
00288 
00289 SingleActionWidget::~SingleActionWidget()
00290 {
00291 }
00292 
00293 void SingleActionWidget::setAction( ActionBase *act )
00294 {
00295   kDebug(5100) <<"SingleActionWidget::setAction()";
00296 
00297   int index = types->currentIndex();
00298   types->setItemText( index, ActionBase::userName( act->getType() ) );
00299 
00300   stack->setCurrentIndex( index );
00301   switch( act->getType() ) {
00302   case ActionBase::SETSCORE:
00303     scoreEditor->setValue( act->getValueString().toInt() );
00304     break;
00305   case ActionBase::NOTIFY:
00306     notifyEditor->setText( act->getValueString() );
00307     break;
00308   case ActionBase::COLOR:
00309     colorEditor->setColor( QColor( act->getValueString() ) );
00310     break;
00311   case ActionBase::MARKASREAD:
00312     // nothing
00313     break;
00314   default:
00315     kWarning(5100) <<"unknown action type in SingleActionWidget::setAction()";
00316   }
00317 }
00318 
00319 ActionBase *SingleActionWidget::createAction() const
00320 {
00321   // no action selected...
00322   if ( types->currentText().isEmpty() ) {
00323     return 0;
00324   }
00325 
00326   int type = ActionBase::getTypeForUserName( types->currentText() );
00327   switch ( type ) {
00328   case ActionBase::SETSCORE:
00329     return new ActionSetScore( scoreEditor->value() );
00330   case ActionBase::NOTIFY:
00331     return new ActionNotify( notifyEditor->text() );
00332   case ActionBase::COLOR:
00333     return new ActionColor( colorEditor->color().name() );
00334   case ActionBase::MARKASREAD:
00335     return new ActionMarkAsRead();
00336   default:
00337     kWarning(5100) <<"unknown action type in SingleActionWidget::getValue()";
00338     return 0;
00339   }
00340 }
00341 
00342 void SingleActionWidget::clear()
00343 {
00344   if ( scoreEditor ) {
00345     scoreEditor->setValue( 0 );
00346   }
00347   if ( notifyEditor ) {
00348     notifyEditor->clear();
00349   }
00350   if ( colorEditor ) {
00351     colorEditor->setCurrentIndex( 0 );
00352   }
00353 
00354   types->setCurrentIndex( 0 );
00355   stack->setCurrentWidget( dummyLabel );
00356 }
00357 
00358 //============================================================================
00359 //
00360 // class ActionEditWidget (the widget to edit the actions of a rule)
00361 //
00362 //============================================================================
00363 ActionEditWidget::ActionEditWidget( KScoringManager *m, QWidget *p, const char *n )
00364   : KWidgetLister( 1, 8, p, n ), manager( m )
00365 {
00366   // create one initial widget
00367   addWidgetAtEnd();
00368 }
00369 
00370 ActionEditWidget::~ActionEditWidget()
00371 {}
00372 
00373 QWidget *ActionEditWidget::createWidget( QWidget *parent )
00374 {
00375   return new SingleActionWidget( manager, parent );
00376 }
00377 
00378 void ActionEditWidget::slotEditRule( KScoringRule *rule )
00379 {
00380   KScoringRule::ActionList l;
00381   if ( rule ) {
00382     l = rule->getActions();
00383   }
00384   if ( !rule || l.count() == 0 ) {
00385     slotClear();
00386   } else {
00387     setNumberOfShownWidgetsTo( l.count() );
00388     ActionBase *act = l.first();
00389     QList<QWidget*>::ConstIterator it = mWidgetList.constBegin();
00390     while ( act && it != mWidgetList.constEnd() ) {
00391       SingleActionWidget *saw = static_cast<SingleActionWidget*>( *it );
00392       saw->setAction( act );
00393       act = l.next();
00394       ++it;
00395     }
00396   }
00397 }
00398 
00399 void ActionEditWidget::updateRule( KScoringRule *rule )
00400 {
00401   rule->cleanActions();
00402   foreach ( QWidget *w, mWidgetList ) {
00403     if ( QString( w->metaObject()->className() ) != "SingleActionWidget" ) {
00404       kWarning(5100) <<"there is a widget in ActionEditWidget"
00405                      << "which isn't a SingleActionWidget";
00406     } else {
00407       SingleActionWidget *saw = dynamic_cast<SingleActionWidget*>( w );
00408       if (saw) {
00409         ActionBase *act = saw->createAction();
00410         if ( act ) {
00411           rule->addAction( act );
00412         }
00413       }
00414     }
00415   }
00416 }
00417 
00418 void ActionEditWidget::clearWidget( QWidget *w )
00419 {
00420   SingleActionWidget *sw =  qobject_cast<SingleActionWidget *>(w);
00421   Q_ASSERT( w );
00422   if ( sw ) {
00423     sw->clear();
00424   }
00425 }
00426 
00427 //============================================================================
00428 //
00429 // class RuleEditWidget (the widget to edit one rule)
00430 //
00431 //============================================================================
00432 RuleEditWidget::RuleEditWidget( KScoringManager *m, QWidget *p, const char *n )
00433   : QWidget( p ), dirty( false ), manager( m ), oldRuleName( QString() )
00434 {
00435   kDebug(5100) <<"RuleEditWidget::RuleEditWidget()";
00436 
00437   setObjectName( n != 0 ? n : "RuleEditWidget" );
00438 
00439   QVBoxLayout *topLayout = new QVBoxLayout( this );
00440   topLayout->setMargin( 5 );
00441   topLayout->setSpacing( KDialog::spacingHint() );
00442 
00443   //------------- Name, Servers, Groups ---------------------
00444   QGroupBox *groupB = new QGroupBox( i18n( "Properties" ), this );
00445   topLayout->addWidget( groupB );
00446   QGridLayout *groupL = new QGridLayout( groupB );
00447   groupL->setMargin( 8 );
00448   groupL->setSpacing( 5 );
00449 
00450   groupL->addItem( new QSpacerItem( 0, fontMetrics().lineSpacing() - 4 ), 0, 0 );
00451 
00452   // name
00453   ruleNameEdit = new KLineEdit( groupB );
00454   groupL->addWidget( ruleNameEdit, 1, 1 );
00455   QLabel *ruleNameLabel = new QLabel( i18nc( "@label rule name", "&Name:" ), groupB );
00456   ruleNameLabel->setBuddy( ruleNameEdit );
00457   ruleNameLabel->setObjectName( "ruleNameLabel" );
00458   groupL->addWidget( ruleNameLabel, 1, 0 );
00459 
00460   // groups
00461   groupsEdit = new KLineEdit( groupB );
00462   groupL->addWidget( groupsEdit, 2, 1 );
00463   QLabel *groupsLabel = new QLabel( i18n( "&Groups:" ), groupB );
00464   groupsLabel->setBuddy( groupsEdit );
00465   groupsLabel->setObjectName( "groupsLabel" );
00466   groupL->addWidget( groupsLabel, 2, 0 );
00467 
00468   QPushButton *groupsBtn = new QPushButton( i18n( "A&dd Group" ), groupB );
00469   connect( groupsBtn, SIGNAL(clicked()), SLOT(slotAddGroup()) );
00470   groupL->addWidget( groupsBtn, 3, 0 );
00471 
00472   groupsBox = new KComboBox( false, groupB );
00473   groupsBox->setDuplicatesEnabled( false );
00474   groupsBox->addItems( manager->getGroups() );
00475   groupsBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
00476   groupL->addWidget( groupsBox, 3, 1 );
00477 
00478   // expires
00479   expireCheck = new QCheckBox( i18n( "&Expire rule automatically" ), groupB );
00480   groupL->addWidget( expireCheck, 4, 0, 1, 2 );
00481   expireEdit = new KIntSpinBox( groupB );
00482   expireEdit->setRange( 1, 9999 );
00483   expireEdit->setValue( 30 );
00484   slotExpireEditChanged(30 );
00485   connect( expireEdit, SIGNAL(valueChanged(int)), SLOT(slotExpireEditChanged(int)) );
00486   groupL->addWidget( expireEdit, 5, 1 );
00487   expireLabel = new QLabel( i18n( "&Rule is valid for:" ), groupB );
00488   expireLabel->setBuddy( expireEdit );
00489   expireLabel->setObjectName( "expireLabel" );
00490   groupL->addWidget( expireLabel, 5, 0 );
00491   expireLabel->setEnabled( false );
00492   expireEdit->setEnabled( false );
00493 
00494   connect( expireCheck, SIGNAL(toggled(bool)), expireLabel, SLOT(setEnabled(bool)) );
00495   connect( expireCheck, SIGNAL(toggled(bool)), expireEdit, SLOT(setEnabled(bool)) );
00496 
00497   //------------- Conditions ---------------------
00498   QGroupBox *groupConds = new QGroupBox( i18n( "Conditions" ), this );
00499   topLayout->addWidget( groupConds );
00500   QGridLayout *condL = new QGridLayout( groupConds );
00501   condL->setMargin( 8 );
00502   condL->setSpacing( 5 );
00503 
00504   condL->addItem( new QSpacerItem( 0, fontMetrics().lineSpacing() - 4 ), 0, 0 );
00505 
00506   QButtonGroup *buttonGroup = new QButtonGroup( groupConds );
00507 
00508   linkModeAnd = new QRadioButton( i18n( "Match a&ll conditions" ), groupConds );
00509   buttonGroup->addButton( linkModeAnd );
00510   condL->addWidget( linkModeAnd, 1, 0 );
00511   linkModeOr = new QRadioButton( i18n( "Matc&h any condition" ), groupConds );
00512   buttonGroup->addButton( linkModeOr );
00513   condL->addWidget( linkModeOr, 1, 1 );
00514   linkModeAnd->setChecked( true );
00515 
00516   condEditor = new ConditionEditWidget( manager, groupConds );
00517   condL->addWidget( condEditor, 2, 0, 1, 2 );
00518   connect( condEditor, SIGNAL(widgetRemoved()), this, SLOT(slotShrink()) );
00519 
00520   //------------- Actions ---------------------
00521   QGroupBox *groupActions = new QGroupBox( i18n( "Actions" ), this );
00522   topLayout->addWidget( groupActions );
00523   QBoxLayout *actionL = new QVBoxLayout( groupActions );
00524   actionL->setMargin( 8 );
00525   actionL->setSpacing( 5 );
00526   actionL->addSpacing( fontMetrics().lineSpacing() - 4 );
00527   actionEditor = new ActionEditWidget( manager, groupActions );
00528   actionL->addWidget( actionEditor );
00529   connect( actionEditor, SIGNAL(widgetRemoved()), this, SLOT(slotShrink()) );
00530 
00531   topLayout->addStretch( 1 );
00532 
00533   kDebug(5100) <<"constructed RuleEditWidget";
00534 }
00535 
00536 RuleEditWidget::~RuleEditWidget()
00537 {
00538 }
00539 
00540 void RuleEditWidget::slotEditRule( const QString &ruleName )
00541 {
00542   KScoringRule *rule = manager->findRule( ruleName );
00543   if ( !rule ) {
00544     kDebug(5100) <<"no rule for ruleName" << ruleName;
00545     clearContents();
00546     return;
00547   }
00548   oldRuleName = rule->getName();
00549   ruleNameEdit->setText( rule->getName() );
00550   groupsEdit->setText( rule->getGroups().join( ";" ) );
00551 
00552   bool b = rule->getExpireDate().isValid();
00553   expireCheck->setChecked( b );
00554   expireEdit->setEnabled( b );
00555   expireLabel->setEnabled( b );
00556   if ( b ) {
00557     expireEdit->setValue( QDate::currentDate().daysTo( rule->getExpireDate() ) );
00558   } else {
00559     expireEdit->setValue( 30 );
00560   }
00561   if ( rule->getLinkMode() == KScoringRule::AND ) {
00562     linkModeAnd->setChecked( true );
00563   } else {
00564     linkModeOr->setChecked( true );
00565   }
00566 
00567   condEditor->slotEditRule( rule );
00568   actionEditor->slotEditRule( rule );
00569 
00570   kDebug(5100) <<"RuleEditWidget::slotEditRule() ready";
00571 }
00572 
00573 void RuleEditWidget::clearContents()
00574 {
00575   ruleNameEdit->setText( "" );
00576   groupsEdit->setText( "" );
00577   expireCheck->setChecked( false );
00578   expireEdit->setValue( 30 );
00579   expireEdit->setEnabled( false );
00580   condEditor->slotEditRule( 0 );
00581   actionEditor->slotEditRule( 0 );
00582   oldRuleName.clear();
00583 }
00584 
00585 void RuleEditWidget::updateRule( KScoringRule *rule )
00586 {
00587   oldRuleName.clear();
00588   QString groups = groupsEdit->text();
00589   if ( groups.isEmpty() ) {
00590     rule->setGroups( QStringList( ".*" ) );
00591   } else {
00592     rule->setGroups( groups.split( ';', QString::SkipEmptyParts ) );
00593   }
00594   bool b = expireCheck->isChecked();
00595   if ( b ) {
00596     rule->setExpireDate( QDate::currentDate().addDays( expireEdit->value() ) );
00597   } else {
00598     rule->setExpireDate( QDate() );
00599   }
00600   actionEditor->updateRule( rule );
00601   rule->setLinkMode( linkModeAnd->isChecked() ? KScoringRule::AND : KScoringRule::OR );
00602   condEditor->updateRule( rule );
00603   if ( rule->getName() != ruleNameEdit->text() ) {
00604     manager->setRuleName( rule, ruleNameEdit->text() );
00605   }
00606 }
00607 
00608 void RuleEditWidget::updateRule()
00609 {
00610   KScoringRule *rule = manager->findRule( oldRuleName );
00611   if ( rule ) {
00612     updateRule( rule );
00613   }
00614 }
00615 
00616 void RuleEditWidget::slotAddGroup()
00617 {
00618   QString grp = groupsBox->currentText();
00619   if ( grp.isEmpty() ) {
00620     return;
00621   }
00622   QString txt = groupsEdit->text().trimmed();
00623   if ( txt == ".*" || txt.isEmpty() ) {
00624     groupsEdit->setText( grp );
00625   } else {
00626     groupsEdit->setText( txt + ';' + grp );
00627   }
00628 }
00629 
00630 void RuleEditWidget::setDirty()
00631 {
00632   kDebug(5100) <<"RuleEditWidget::setDirty()";
00633   if ( dirty ) {
00634     return;
00635   }
00636   dirty = true;
00637 }
00638 
00639 void RuleEditWidget::slotShrink()
00640 {
00641   emit( shrink() );
00642 }
00643 
00644 void RuleEditWidget::slotExpireEditChanged( int value )
00645 {
00646   expireEdit->setSuffix( i18np( " day", " days", value ) );
00647 }
00648 
00649 //============================================================================
00650 //
00651 // class RuleListWidget (the widget for managing a list of rules)
00652 //
00653 //============================================================================
00654 RuleListWidget::RuleListWidget( KScoringManager *m, bool standalone, QWidget *p, const char *n )
00655   : QWidget( p ), alone( standalone ), manager( m )
00656 {
00657   kDebug(5100) <<"RuleListWidget::RuleListWidget()";
00658   setObjectName( n != 0 ? n : "RuleListWidget" );
00659   QVBoxLayout *topL = new QVBoxLayout( this );
00660   topL->setMargin( standalone ? 0 : 5 );
00661   topL->setSpacing( KDialog::spacingHint() );
00662 
00663   ruleList = new K3ListBox( this );
00664   if ( standalone ) {
00665     connect( ruleList, SIGNAL(doubleClicked(Q3ListBoxItem*)),
00666              this, SLOT(slotEditRule(Q3ListBoxItem*)) );
00667     connect( ruleList, SIGNAL(returnPressed(Q3ListBoxItem*)),
00668              this, SLOT(slotEditRule(Q3ListBoxItem*)) );
00669   }
00670   connect( ruleList, SIGNAL(currentChanged(Q3ListBoxItem*)),
00671            this, SLOT(slotRuleSelected(Q3ListBoxItem*)) );
00672   topL->addWidget( ruleList );
00673 
00674   QHBoxLayout *btnL = new QHBoxLayout();
00675   btnL->setSpacing( KDialog::spacingHint() );
00676 
00677   topL->addItem( btnL );
00678 
00679   mRuleUp = new QPushButton( this );
00680   mRuleUp->setIcon( KIcon( "go-up" ) );
00681   mRuleUp->setToolTip( i18n( "Move rule up" ) );
00682   btnL->addWidget( mRuleUp );
00683   connect( mRuleUp, SIGNAL( clicked() ), SLOT( slotRuleUp() ) );
00684   mRuleDown = new QPushButton( this );
00685   mRuleDown->setIcon( KIcon( "go-down" ) );
00686   mRuleDown->setToolTip( i18n( "Move rule down" ) );
00687   btnL->addWidget( mRuleDown );
00688   connect( mRuleDown, SIGNAL( clicked() ), SLOT( slotRuleDown() ) );
00689 
00690   btnL = new QHBoxLayout();
00691   btnL->setSpacing( KDialog::spacingHint() );
00692 
00693   topL->addItem( btnL );
00694 
00695   editRule = 0;
00696   newRule = new QPushButton( this );
00697   newRule->setIcon( KIcon( "document-new" ) );
00698   newRule->setToolTip( i18n( "New rule" ) ),
00699   btnL->addWidget( newRule );
00700   connect( newRule, SIGNAL(clicked()), this, SLOT(slotNewRule()) );
00701   // if we're standalone, we need an additional edit button
00702   if ( standalone ) {
00703     editRule = new QPushButton( this );
00704     editRule->setIcon( KIcon( "document-properties" ) );
00705     editRule->setToolTip( i18n( "Edit rule" ) );
00706     btnL->addWidget( editRule );
00707     connect( editRule, SIGNAL(clicked()), this, SLOT(slotEditRule()) );
00708   }
00709   delRule = new QPushButton( this );
00710   delRule->setIcon( KIcon( "edit-delete" ) );
00711   delRule->setToolTip( i18n( "Remove rule" ) );
00712   btnL->addWidget( delRule );
00713   connect( delRule, SIGNAL(clicked()), this, SLOT(slotDelRule()) );
00714   copyRule = new QPushButton( this );
00715   copyRule->setIcon( KIcon( "edit-copy" ) );
00716   copyRule->setToolTip( i18n( "Copy rule" ) );
00717   btnL->addWidget( copyRule );
00718   connect( copyRule, SIGNAL(clicked()), this, SLOT(slotCopyRule()) );
00719 
00720   // the group filter
00721   QBoxLayout *filterL = new QVBoxLayout();
00722   topL->addItem( filterL );
00723   filterL->setSpacing( KDialog::spacingHint() );
00724 
00725   KComboBox *filterBox = new KComboBox( this );
00726   QStringList l = m->getGroups();
00727   filterBox->addItem( i18n( "<placeholder>all groups</placeholder>" ) );
00728   filterBox->addItems( l );
00729   filterBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
00730   connect( filterBox, SIGNAL(activated(const QString&)),
00731            this, SLOT(slotGroupFilter(const QString&)) );
00732   slotGroupFilter( i18n( "<placeholder>all groups</placeholder>" ) );
00733   QLabel *lab = new QLabel( i18n( "Sho&w only rules for group:" ), this );
00734   lab->setBuddy( filterBox );
00735 
00736   filterL->addWidget( lab );
00737   filterL->addWidget( filterBox );
00738 
00739   connect( manager, SIGNAL(changedRules()), this, SLOT(updateRuleList()) );
00740   connect( manager, SIGNAL(changedRuleName(const QString&,const QString&)),
00741            this, SLOT(slotRuleNameChanged(const QString&,const QString&)) );
00742 
00743   updateRuleList();
00744   updateButton();
00745 }
00746 
00747 RuleListWidget::~RuleListWidget()
00748 {
00749 }
00750 
00751 void RuleListWidget::updateButton()
00752 {
00753   bool state = ruleList->count() > 0;
00754   if( editRule ) {
00755     editRule->setEnabled( state );
00756   }
00757   delRule->setEnabled( state );
00758   copyRule->setEnabled( state );
00759 
00760   Q3ListBoxItem *item = ruleList->item( ruleList->currentItem() );
00761   if ( item ) {
00762     mRuleUp->setEnabled( item->prev() != 0 );
00763     mRuleDown->setEnabled( item->next() != 0 );
00764   }
00765 }
00766 
00767 void RuleListWidget::updateRuleList()
00768 {
00769   emit leavingRule();
00770   kDebug(5100) <<"RuleListWidget::updateRuleList()";
00771   QString curr = ruleList->currentText();
00772   ruleList->clear();
00773   if ( group == i18n( "<placeholder>all groups</placeholder>" ) ) {
00774     QStringList l = manager->getRuleNames();
00775     ruleList->insertStringList( l );
00776   } else {
00777     KScoringManager::ScoringRuleList l = manager->getAllRules();
00778     for ( KScoringRule *rule = l.first(); rule; rule = l.next() ) {
00779       if ( rule->matchGroup( group ) ) {
00780         ruleList->insertItem( rule->getName() );
00781       }
00782     }
00783   }
00784   int index = setCurrentItem( ruleList, curr );
00785   if ( index < 0 ) {
00786     ruleList->setCurrentItem( 0 );
00787     slotRuleSelected( ruleList->currentText() );
00788   } else {
00789     slotRuleSelected( curr );
00790   }
00791 }
00792 
00793 void RuleListWidget::updateRuleList( const KScoringRule *rule )
00794 {
00795   kDebug(5100) <<"RuleListWidget::updateRuleList(" << rule->getName() <<")";
00796   QString name = rule->getName();
00797   updateRuleList();
00798   slotRuleSelected(name);
00799 }
00800 
00801 void RuleListWidget::slotRuleNameChanged( const QString &oldName, const QString &newName )
00802 {
00803   int ind = ruleList->currentItem();
00804   for ( uint i=0; i<ruleList->count(); ++i ) {
00805     if ( ruleList->text(i) == oldName ) {
00806       ruleList->changeItem( newName, i );
00807       ruleList->setCurrentItem( ind );
00808       return;
00809     }
00810   }
00811 }
00812 
00813 void RuleListWidget::slotEditRule( const QString &s )
00814 {
00815   emit ruleEdited( s );
00816 }
00817 
00818 void RuleListWidget::slotEditRule()
00819 {
00820   if ( ruleList->currentItem() >= 0 ) {
00821     emit ruleEdited( ruleList->currentText() );
00822   } else if ( ruleList->count() == 0 ) {
00823     emit ruleEdited( QString() );
00824   }
00825 }
00826 
00827 void RuleListWidget::slotEditRule( Q3ListBoxItem *item )
00828 {
00829   slotEditRule( item->text() );
00830 }
00831 
00832 void RuleListWidget::slotGroupFilter( const QString &s )
00833 {
00834   group = s;
00835   updateRuleList();
00836 }
00837 
00838 void RuleListWidget::slotRuleSelected( const QString &ruleName )
00839 {
00840   emit leavingRule();
00841   kDebug(5100) <<"RuleListWidget::slotRuleSelected(" << ruleName <<")";
00842   if ( ruleName != ruleList->currentText() ) {
00843     setCurrentItem( ruleList, ruleName );
00844   }
00845   updateButton();
00846   emit ruleSelected( ruleName );
00847 }
00848 
00849 void RuleListWidget::slotRuleSelected( Q3ListBoxItem *item )
00850 {
00851   if ( !item ) {
00852     return;
00853   }
00854   QString ruleName = item->text();
00855   slotRuleSelected( ruleName );
00856 }
00857 
00858 void RuleListWidget::slotRuleSelected( int index )
00859 {
00860   uint idx = index;
00861   if ( idx >= ruleList->count() ) {
00862     return;
00863   }
00864   QString ruleName = ruleList->text( index );
00865   slotRuleSelected( ruleName );
00866 }
00867 
00868 void RuleListWidget::slotNewRule()
00869 {
00870   emit leavingRule();
00871   KScoringRule *rule = manager->addRule();
00872   updateRuleList( rule );
00873   if ( alone ) {
00874     slotEditRule( rule->getName() );
00875   }
00876   updateButton();
00877 }
00878 
00879 void RuleListWidget::slotDelRule()
00880 {
00881   KScoringRule *rule = manager->findRule( ruleList->currentText() );
00882   if ( rule ) {
00883     manager->deleteRule( rule );
00884   }
00885   // goto the next rule
00886   if ( !alone ) {
00887     slotEditRule();
00888   }
00889   updateButton();
00890 }
00891 
00892 void RuleListWidget::slotCopyRule()
00893 {
00894   emit leavingRule();
00895   QString ruleName = ruleList->currentText();
00896   KScoringRule *rule = manager->findRule( ruleName );
00897   if ( rule ) {
00898     KScoringRule *nrule = manager->copyRule( rule );
00899     updateRuleList( nrule );
00900     slotEditRule( nrule->getName() );
00901   }
00902   updateButton();
00903 }
00904 
00905 void RuleListWidget::slotRuleUp()
00906 {
00907   KScoringRule *rule = 0, *below = 0;
00908   Q3ListBoxItem *item = ruleList->item( ruleList->currentItem() );
00909   if ( item ) {
00910     rule = manager->findRule( item->text() );
00911     item = item->prev();
00912     if ( item ) {
00913       below = manager->findRule( item->text() );
00914     }
00915   }
00916   if ( rule && below ) {
00917     manager->moveRuleAbove( rule, below );
00918   }
00919   updateRuleList();
00920   updateButton();
00921 }
00922 
00923 void RuleListWidget::slotRuleDown()
00924 {
00925   KScoringRule *rule = 0, *above = 0;
00926   Q3ListBoxItem *item = ruleList->item( ruleList->currentItem() );
00927   if ( item ) {
00928     rule = manager->findRule( item->text() );
00929     item = item->next();
00930     if ( item ) {
00931       above = manager->findRule( item->text() );
00932     }
00933   }
00934   if ( rule && above ) {
00935     manager->moveRuleBelow( rule, above );
00936   }
00937   updateRuleList();
00938   updateButton();
00939 }
00940 
00941 //============================================================================
00942 //
00943 // class KScoringEditor (the score edit dialog)
00944 //
00945 //============================================================================
00946 KScoringEditor *KScoringEditor::scoreEditor = 0;
00947 
00948 KScoringEditor::KScoringEditor( KScoringManager *m, QWidget *parent )
00949   : KDialog( parent ), manager( m )
00950 {
00951   setCaption( i18n( "Rule Editor" ) );
00952   setButto