split message into several paras and fix file extension markup
[kdepim.git] / knode / kscoringeditor.cpp
blob01b97dc49daeb4c260995352f9c2d509a05608c7
1 /*
2 kscoringeditor.cpp
4 Copyright (c) 2001 Mathias Waack <mathias@atoll-net.de>
5 Copyright (C) 2005 by Volker Krause <vkrause@kde.org>
7 Author: Mathias Waack <mathias@atoll-net.de>
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
18 #undef QT_NO_COMPAT
20 #include "kscoringeditor.h"
21 #include "kscoring.h"
23 #include <KDebug>
24 #include <KColorCombo>
25 #include <KComboBox>
26 #include <KIconLoader>
27 #include <KIntSpinBox>
28 #include <KLineEdit>
29 #include <KLocale>
30 #include <kregexpeditorinterface.h>
31 #include <KServiceTypeTrader>
32 #include <KPushButton>
34 #include <QLabel>
35 #include <QPushButton>
36 #include <QLayout>
37 #include <QCheckBox>
38 #include <QRadioButton>
39 #include <QApplication>
40 #include <QTimer>
41 #include <QButtonGroup>
42 #include <QGroupBox>
43 #include <QGridLayout>
44 #include <QFrame>
45 #include <QHBoxLayout>
46 #include <QBoxLayout>
47 #include <QVBoxLayout>
49 using namespace KPIM;
51 static int setCurrentItem( K3ListBox *box, const QString &s )
53 int cnt = box->count();
54 for ( int i=0; i<cnt; ++i ) {
55 if ( box->text( i ) == s ) {
56 box->setCurrentItem( i );
57 return i;
60 return -1;
63 //============================================================================
65 // class SingleConditionWidget (editor for one condition, used in ConditionEditWidget)
67 //============================================================================
68 SingleConditionWidget::SingleConditionWidget( KScoringManager *m, QWidget *p, const char * )
69 : QFrame( p ), manager( m )
71 QBoxLayout *topL = new QVBoxLayout( this );
72 topL->setMargin( 5 );
73 QBoxLayout *firstRow = new QHBoxLayout();
74 topL->addItem( firstRow );
75 neg = new QCheckBox( i18n( "Not" ), this );
76 neg->setToolTip( i18n( "Negate this condition" ) );
77 firstRow->addWidget( neg );
78 headers = new KComboBox( this );
79 headers->addItems( manager->getDefaultHeaders() );
80 headers->setEditable( true );
81 headers->setToolTip( i18n( "Select the header to match this condition against" ) );
82 firstRow->addWidget( headers, 1 );
83 matches = new KComboBox( this );
84 matches->addItems( KScoringExpression::conditionNames() );
85 matches->setToolTip( i18n( "Select the type of match" ) );
86 firstRow->addWidget( matches, 1 );
87 connect( matches, SIGNAL(activated(int)), SLOT(toggleRegExpButton(int)) );
88 QHBoxLayout *secondRow = new QHBoxLayout();
89 secondRow->setSpacing( 1 );
90 topL->addItem( secondRow );
92 expr = new KLineEdit( this );
93 expr->setToolTip( i18n( "The condition for the match" ) );
94 // reserve space for at least 20 characters
95 expr->setMinimumWidth( fontMetrics().maxWidth() * 20 );
96 secondRow->addWidget( expr );
97 regExpButton = new QPushButton( i18n( "Edit..." ), this );
98 secondRow->addWidget( regExpButton );
99 connect( regExpButton, SIGNAL(clicked()), SLOT(showRegExpDialog()) );
101 regExpButton->setEnabled(!KServiceTypeTrader::self()->query( "KRegExpEditor/KRegExpEditor" ).isEmpty());
103 // occupy at much width as possible
104 setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
105 setFrameStyle( Box | Sunken );
106 setLineWidth( 1 );
109 SingleConditionWidget::~SingleConditionWidget()
112 void SingleConditionWidget::setCondition( KScoringExpression *e )
114 neg->setChecked( e->isNeg() );
115 headers->setItemText( headers->currentIndex(), e->getHeader() );
116 matches->setCurrentItem( KScoringExpression::getNameForCondition( e->getCondition() ) );
117 toggleRegExpButton( matches->currentIndex() );
118 expr->setText( e->getExpression() );
121 KScoringExpression *SingleConditionWidget::createCondition() const
123 QString head = headers->currentText();
124 QString match = matches->currentText();
125 int condType = KScoringExpression::getConditionForName( match );
126 match = KScoringExpression::getTypeString( condType );
127 QString cond = expr->text();
128 QString negs = ( neg->isChecked() ) ? "1" : "0";
129 return new KScoringExpression( head, match, cond, negs );
132 void SingleConditionWidget::clear()
134 neg->setChecked( false );
135 expr->clear();
138 void SingleConditionWidget::toggleRegExpButton( int selected )
140 bool isRegExp = ( KScoringExpression::MATCH == selected ||
141 KScoringExpression::MATCHCS == selected ) &&
142 !KServiceTypeTrader::self()->query( "KRegExpEditor/KRegExpEditor" ).isEmpty();
143 regExpButton->setEnabled( isRegExp );
146 void SingleConditionWidget::showRegExpDialog()
148 QDialog *editorDialog =
149 KServiceTypeTrader::createInstanceFromQuery<QDialog>(
150 "KRegExpEditor/KRegExpEditor", QString() );
151 if ( editorDialog ) {
152 KRegExpEditorInterface *editor = qobject_cast<KRegExpEditorInterface *>( editorDialog );
153 Q_ASSERT( editor ); // This should not fail!
154 editor->setRegExp( expr->text() );
155 editorDialog->exec();
156 expr->setText( editor->regExp() );
160 //============================================================================
162 // class ConditionEditWidget (the widget to edit the conditions of a rule)
164 //============================================================================
165 ConditionEditWidget::ConditionEditWidget( KScoringManager *m, QWidget *p, const char* )
166 : KWidgetLister( 1, 8, p ), manager( m )
168 // create one initial widget
169 addWidgetAtEnd();
172 ConditionEditWidget::~ConditionEditWidget()
175 QWidget *ConditionEditWidget::createWidget( QWidget *parent )
177 return new SingleConditionWidget( manager, parent );
180 void ConditionEditWidget::clearWidget( QWidget *w )
182 SingleActionWidget *sw = qobject_cast<SingleActionWidget *>(w);
183 Q_ASSERT( w );
184 if ( sw ) {
185 sw->clear();
189 void ConditionEditWidget::slotEditRule( KScoringRule *rule )
191 KScoringRule::ScoreExprList l;
192 if ( rule ) {
193 l = rule->getExpressions();
195 if ( !rule || l.count() == 0 ) {
196 slotClear();
197 } else {
198 setNumberOfShownWidgetsTo( l.count() );
199 KScoringExpression *e = l.first();
200 QList<QWidget*> widgetList = widgets();
201 QList<QWidget*>::ConstIterator it = widgetList.constBegin();
202 while ( e && it != widgetList.constEnd() ) {
203 SingleConditionWidget *scw = qobject_cast<SingleConditionWidget *>( *it );
204 scw->setCondition( e );
205 e = l.next();
206 ++it;
211 void ConditionEditWidget::updateRule( KScoringRule *rule )
213 rule->cleanExpressions();
214 foreach ( QWidget* w, widgets() ) {
215 SingleConditionWidget *saw = qobject_cast<SingleConditionWidget*>( w );
216 if ( saw ) {
217 rule->addExpression( saw->createCondition() );
218 } else {
219 kWarning(5100) <<"there is a widget in ConditionEditWidget"
220 << "which isn't a KPIM::SingleConditionWidget";
225 //============================================================================
227 // class SingleActionWidget (editor for one action, used in ActionEditWidget)
229 //============================================================================
230 SingleActionWidget::SingleActionWidget( KScoringManager *m, QWidget *p, const char *n )
231 : QWidget( p ), notifyEditor( 0 ), scoreEditor( 0 ),
232 colorEditor( 0 ), manager( m )
234 setObjectName( n );
235 QHBoxLayout *topL = new QHBoxLayout( this );
236 topL->setMargin( 0 );
237 topL->setSpacing( 5 );
239 types = new KComboBox( this );
240 types->setEditable( false );
241 topL->addWidget( types );
242 stack = new QStackedWidget( this );
243 topL->addWidget( stack );
245 dummyLabel = new QLabel( i18n( "Select an action." ), stack );
246 stack->insertWidget( 0, dummyLabel );
248 // init widget stack and the types combo box
249 int index = 1;
250 types->addItem( QString() );
251 QStringList l = ActionBase::userNames();
252 for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it ) {
253 QString name = *it;
254 int feature = ActionBase::getTypeForUserName( name );
255 if ( manager->hasFeature( feature ) ) {
256 types->addItem( name );
257 QWidget *w = 0;
258 switch( feature ) {
259 case ActionBase::SETSCORE:
260 w = scoreEditor = new KIntSpinBox( stack );
261 scoreEditor->setRange( -99999, 99999 );
262 scoreEditor->setValue( 30 );
263 break;
264 case ActionBase::NOTIFY:
265 w = notifyEditor = new KLineEdit( stack );
266 break;
267 case ActionBase::COLOR:
268 w = colorEditor = new KColorCombo( stack );
269 break;
270 case ActionBase::MARKASREAD:
271 w = new QLabel( stack ); // empty dummy
272 break;
274 if ( w ) {
275 stack->insertWidget( index++, w );
280 connect( types, SIGNAL(activated(int)), stack, SLOT(setCurrentIndex(int)) );
282 // raise the dummy label
283 types->setCurrentIndex( 0 );
284 stack->setCurrentWidget( dummyLabel );
287 SingleActionWidget::~SingleActionWidget()
291 void SingleActionWidget::setAction( ActionBase *act )
293 kDebug(5100) <<"SingleActionWidget::setAction()";
295 int index = types->findText( act->userName() );
296 if( index == -1 ) {
297 kWarning(5100) <<"unknown action in SingleActionWidget::setAction()";
298 index = 0;
301 types->setCurrentIndex( index );
302 stack->setCurrentIndex( index );
303 switch( act->getType() ) {
304 case ActionBase::SETSCORE:
305 scoreEditor->setValue( act->getValueString().toInt() );
306 break;
307 case ActionBase::NOTIFY:
308 notifyEditor->setText( act->getValueString() );
309 break;
310 case ActionBase::COLOR:
311 colorEditor->setColor( QColor( act->getValueString() ) );
312 break;
313 case ActionBase::MARKASREAD:
314 // nothing
315 break;
316 default:
317 kWarning(5100) <<"unknown action type in SingleActionWidget::setAction()";
321 ActionBase *SingleActionWidget::createAction() const
323 // no action selected...
324 if ( types->currentText().isEmpty() ) {
325 return 0;
328 int type = ActionBase::getTypeForUserName( types->currentText() );
329 switch ( type ) {
330 case ActionBase::SETSCORE:
331 return new ActionSetScore( scoreEditor->value() );
332 case ActionBase::NOTIFY:
333 return new ActionNotify( notifyEditor->text() );
334 case ActionBase::COLOR:
335 return new ActionColor( colorEditor->color().name() );
336 case ActionBase::MARKASREAD:
337 return new ActionMarkAsRead();
338 default:
339 kWarning(5100) <<"unknown action type in SingleActionWidget::getValue()";
340 return 0;
344 void SingleActionWidget::clear()
346 if ( scoreEditor ) {
347 scoreEditor->setValue( 0 );
349 if ( notifyEditor ) {
350 notifyEditor->clear();
352 if ( colorEditor ) {
353 colorEditor->setCurrentIndex( 0 );
356 types->setCurrentIndex( 0 );
357 stack->setCurrentWidget( dummyLabel );
360 //============================================================================
362 // class ActionEditWidget (the widget to edit the actions of a rule)
364 //============================================================================
365 ActionEditWidget::ActionEditWidget( KScoringManager *m, QWidget *p, const char* )
366 : KWidgetLister( 1, 8, p ), manager( m )
368 // create one initial widget
369 addWidgetAtEnd();
372 ActionEditWidget::~ActionEditWidget()
375 QWidget *ActionEditWidget::createWidget( QWidget *parent )
377 return new SingleActionWidget( manager, parent );
380 void ActionEditWidget::slotEditRule( KScoringRule *rule )
382 KScoringRule::ActionList l;
383 if ( rule ) {
384 l = rule->getActions();
386 if ( !rule || l.count() == 0 ) {
387 slotClear();
388 } else {
389 setNumberOfShownWidgetsTo( l.count() );
390 ActionBase *act = l.first();
391 QList<QWidget*> widgetList = widgets();
392 QList<QWidget*>::ConstIterator it = widgetList.constBegin();
393 while ( act && it != widgetList.constEnd() ) {
394 SingleActionWidget *saw = qobject_cast<SingleActionWidget*>( *it );
395 saw->setAction( act );
396 act = l.next();
397 ++it;
402 void ActionEditWidget::updateRule( KScoringRule *rule )
404 rule->cleanActions();
405 foreach ( QWidget *w, widgets() ) {
406 SingleActionWidget *saw = qobject_cast<SingleActionWidget*>( w );
407 if (saw) {
408 ActionBase *act = saw->createAction();
409 if ( act ) {
410 rule->addAction( act );
412 } else {
413 kWarning(5100) <<"there is a widget in ActionEditWidget"
414 << "which isn't a KPIM::SingleActionWidget";
419 void ActionEditWidget::clearWidget( QWidget *w )
421 SingleActionWidget *sw = qobject_cast<SingleActionWidget *>(w);
422 Q_ASSERT( w );
423 if ( sw ) {
424 sw->clear();
428 //============================================================================
430 // class RuleEditWidget (the widget to edit one rule)
432 //============================================================================
433 RuleEditWidget::RuleEditWidget( KScoringManager *m, QWidget *p, const char *n )
434 : QWidget( p ), dirty( false ), manager( m ), oldRuleName( QString() )
436 kDebug(5100) <<"RuleEditWidget::RuleEditWidget()";
438 setObjectName( n != 0 ? n : "RuleEditWidget" );
440 QVBoxLayout *topLayout = new QVBoxLayout( this );
441 topLayout->setMargin( 5 );
442 topLayout->setSpacing( KDialog::spacingHint() );
444 //------------- Name, Servers, Groups ---------------------
445 QGroupBox *groupB = new QGroupBox( i18n( "Properties" ), this );
446 topLayout->addWidget( groupB );
447 QGridLayout *groupL = new QGridLayout( groupB );
448 groupL->setMargin( 8 );
449 groupL->setSpacing( 5 );
451 groupL->addItem( new QSpacerItem( 0, fontMetrics().lineSpacing() - 4 ), 0, 0 );
453 // name
454 ruleNameEdit = new KLineEdit( groupB );
455 groupL->addWidget( ruleNameEdit, 1, 1 );
456 QLabel *ruleNameLabel = new QLabel( i18nc( "@label rule name", "&Name:" ), groupB );
457 ruleNameLabel->setBuddy( ruleNameEdit );
458 ruleNameLabel->setObjectName( "ruleNameLabel" );
459 groupL->addWidget( ruleNameLabel, 1, 0 );
461 // groups
462 groupsEdit = new KLineEdit( groupB );
463 groupL->addWidget( groupsEdit, 2, 1 );
464 QLabel *groupsLabel = new QLabel( i18n( "&Groups:" ), groupB );
465 groupsLabel->setBuddy( groupsEdit );
466 groupsLabel->setObjectName( "groupsLabel" );
467 groupL->addWidget( groupsLabel, 2, 0 );
469 QPushButton *groupsBtn = new QPushButton( i18n( "A&dd Group" ), groupB );
470 connect( groupsBtn, SIGNAL(clicked()), SLOT(slotAddGroup()) );
471 groupL->addWidget( groupsBtn, 3, 0 );
473 groupsBox = new KComboBox( false, groupB );
474 groupsBox->setDuplicatesEnabled( false );
475 groupsBox->addItems( manager->getGroups() );
476 groupsBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
477 groupL->addWidget( groupsBox, 3, 1 );
479 // expires
480 expireCheck = new QCheckBox( i18n( "&Expire rule automatically" ), groupB );
481 groupL->addWidget( expireCheck, 4, 0, 1, 2 );
482 expireEdit = new KIntSpinBox( groupB );
483 expireEdit->setRange( 1, 9999 );
484 expireEdit->setValue( 30 );
485 slotExpireEditChanged(30 );
486 connect( expireEdit, SIGNAL(valueChanged(int)), SLOT(slotExpireEditChanged(int)) );
487 groupL->addWidget( expireEdit, 5, 1 );
488 expireLabel = new QLabel( i18n( "&Rule is valid for:" ), groupB );
489 expireLabel->setBuddy( expireEdit );
490 expireLabel->setObjectName( "expireLabel" );
491 groupL->addWidget( expireLabel, 5, 0 );
492 expireLabel->setEnabled( false );
493 expireEdit->setEnabled( false );
495 connect( expireCheck, SIGNAL(toggled(bool)), expireLabel, SLOT(setEnabled(bool)) );
496 connect( expireCheck, SIGNAL(toggled(bool)), expireEdit, SLOT(setEnabled(bool)) );
498 //------------- Conditions ---------------------
499 QGroupBox *groupConds = new QGroupBox( i18n( "Conditions" ), this );
500 topLayout->addWidget( groupConds );
501 QGridLayout *condL = new QGridLayout( groupConds );
502 condL->setMargin( 8 );
503 condL->setSpacing( 5 );
505 condL->addItem( new QSpacerItem( 0, fontMetrics().lineSpacing() - 4 ), 0, 0 );
507 QButtonGroup *buttonGroup = new QButtonGroup( groupConds );
509 linkModeAnd = new QRadioButton( i18n( "Match a&ll conditions" ), groupConds );
510 buttonGroup->addButton( linkModeAnd );
511 condL->addWidget( linkModeAnd, 1, 0 );
512 linkModeOr = new QRadioButton( i18n( "Matc&h any condition" ), groupConds );
513 buttonGroup->addButton( linkModeOr );
514 condL->addWidget( linkModeOr, 1, 1 );
515 linkModeAnd->setChecked( true );
517 condEditor = new ConditionEditWidget( manager, groupConds );
518 condL->addWidget( condEditor, 2, 0, 1, 2 );
519 connect( condEditor, SIGNAL(widgetRemoved()), this, SLOT(slotShrink()) );
521 //------------- Actions ---------------------
522 QGroupBox *groupActions = new QGroupBox( i18n( "Actions" ), this );
523 topLayout->addWidget( groupActions );
524 QBoxLayout *actionL = new QVBoxLayout( groupActions );
525 actionL->setMargin( 8 );
526 actionL->setSpacing( 5 );
527 actionL->addSpacing( fontMetrics().lineSpacing() - 4 );
528 actionEditor = new ActionEditWidget( manager, groupActions );
529 actionL->addWidget( actionEditor );
530 connect( actionEditor, SIGNAL(widgetRemoved()), this, SLOT(slotShrink()) );
532 topLayout->addStretch( 1 );
534 kDebug(5100) <<"constructed RuleEditWidget";
537 RuleEditWidget::~RuleEditWidget()
541 void RuleEditWidget::slotEditRule( const QString &ruleName )
543 KScoringRule *rule = manager->findRule( ruleName );
544 if ( !rule ) {
545 kDebug(5100) <<"no rule for ruleName" << ruleName;
546 clearContents();
547 return;
549 oldRuleName = rule->getName();
550 ruleNameEdit->setText( rule->getName() );
551 groupsEdit->setText( rule->getGroups().join( ";" ) );
553 bool b = rule->getExpireDate().isValid();
554 expireCheck->setChecked( b );
555 expireEdit->setEnabled( b );
556 expireLabel->setEnabled( b );
557 if ( b ) {
558 expireEdit->setValue( QDate::currentDate().daysTo( rule->getExpireDate() ) );
559 } else {
560 expireEdit->setValue( 30 );
562 if ( rule->getLinkMode() == KScoringRule::AND ) {
563 linkModeAnd->setChecked( true );
564 } else {
565 linkModeOr->setChecked( true );
568 condEditor->slotEditRule( rule );
569 actionEditor->slotEditRule( rule );
571 kDebug(5100) <<"RuleEditWidget::slotEditRule() ready";
574 void RuleEditWidget::clearContents()
576 ruleNameEdit->setText( "" );
577 groupsEdit->setText( "" );
578 expireCheck->setChecked( false );
579 expireEdit->setValue( 30 );
580 expireEdit->setEnabled( false );
581 condEditor->slotEditRule( 0 );
582 actionEditor->slotEditRule( 0 );
583 oldRuleName.clear();
586 void RuleEditWidget::updateRule( KScoringRule *rule )
588 oldRuleName.clear();
589 QString groups = groupsEdit->text();
590 if ( groups.isEmpty() ) {
591 rule->setGroups( QStringList( ".*" ) );
592 } else {
593 rule->setGroups( groups.split( ';', QString::SkipEmptyParts ) );
595 bool b = expireCheck->isChecked();
596 if ( b ) {
597 rule->setExpireDate( QDate::currentDate().addDays( expireEdit->value() ) );
598 } else {
599 rule->setExpireDate( QDate() );
601 actionEditor->updateRule( rule );
602 rule->setLinkMode( linkModeAnd->isChecked() ? KScoringRule::AND : KScoringRule::OR );
603 condEditor->updateRule( rule );
604 if ( rule->getName() != ruleNameEdit->text() ) {
605 manager->setRuleName( rule, ruleNameEdit->text() );
609 void RuleEditWidget::updateRule()
611 KScoringRule *rule = manager->findRule( oldRuleName );
612 if ( rule ) {
613 updateRule( rule );
617 void RuleEditWidget::slotAddGroup()
619 QString grp = groupsBox->currentText();
620 if ( grp.isEmpty() ) {
621 return;
623 QString txt = groupsEdit->text().trimmed();
624 if ( txt == ".*" || txt.isEmpty() ) {
625 groupsEdit->setText( grp );
626 } else {
627 groupsEdit->setText( txt + ';' + grp );
631 void RuleEditWidget::setDirty()
633 kDebug(5100) <<"RuleEditWidget::setDirty()";
634 if ( dirty ) {
635 return;
637 dirty = true;
640 void RuleEditWidget::slotShrink()
642 emit( shrink() );
645 void RuleEditWidget::slotExpireEditChanged( int value )
647 expireEdit->setSuffix( i18np( " day", " days", value ) );
650 //============================================================================
652 // class RuleListWidget (the widget for managing a list of rules)
654 //============================================================================
655 RuleListWidget::RuleListWidget( KScoringManager *m, bool standalone, QWidget *p, const char *n )
656 : QWidget( p ), alone( standalone ), manager( m )
658 kDebug(5100) <<"RuleListWidget::RuleListWidget()";
659 setObjectName( n != 0 ? n : "RuleListWidget" );
660 QVBoxLayout *topL = new QVBoxLayout( this );
661 topL->setMargin( standalone ? 0 : 5 );
662 topL->setSpacing( KDialog::spacingHint() );
664 ruleList = new K3ListBox( this );
665 if ( standalone ) {
666 connect( ruleList, SIGNAL(doubleClicked(Q3ListBoxItem*)),
667 this, SLOT(slotEditRule(Q3ListBoxItem*)) );
668 connect( ruleList, SIGNAL(returnPressed(Q3ListBoxItem*)),
669 this, SLOT(slotEditRule(Q3ListBoxItem*)) );
671 connect( ruleList, SIGNAL(currentChanged(Q3ListBoxItem*)),
672 this, SLOT(slotRuleSelected(Q3ListBoxItem*)) );
673 topL->addWidget( ruleList );
675 QHBoxLayout *btnL = new QHBoxLayout();
676 btnL->setSpacing( KDialog::spacingHint() );
678 topL->addItem( btnL );
680 mRuleUp = new QPushButton( this );
681 mRuleUp->setIcon( KIcon( "go-up" ) );
682 mRuleUp->setToolTip( i18n( "Move rule up" ) );
683 btnL->addWidget( mRuleUp );
684 connect( mRuleUp, SIGNAL(clicked()), SLOT(slotRuleUp()) );
685 mRuleDown = new QPushButton( this );
686 mRuleDown->setIcon( KIcon( "go-down" ) );
687 mRuleDown->setToolTip( i18n( "Move rule down" ) );
688 btnL->addWidget( mRuleDown );
689 connect( mRuleDown, SIGNAL(clicked()), SLOT(slotRuleDown()) );
691 btnL = new QHBoxLayout();
692 btnL->setSpacing( KDialog::spacingHint() );
694 topL->addItem( btnL );
696 editRule = 0;
697 newRule = new QPushButton( this );
698 newRule->setIcon( KIcon( "document-new" ) );
699 newRule->setToolTip( i18n( "New rule" ) ),
700 btnL->addWidget( newRule );
701 connect( newRule, SIGNAL(clicked()), this, SLOT(slotNewRule()) );
702 // if we're standalone, we need an additional edit button
703 if ( standalone ) {
704 editRule = new QPushButton( this );
705 editRule->setIcon( KIcon( "document-properties" ) );
706 editRule->setToolTip( i18n( "Edit rule" ) );
707 btnL->addWidget( editRule );
708 connect( editRule, SIGNAL(clicked()), this, SLOT(slotEditRule()) );
710 delRule = new QPushButton( this );
711 delRule->setIcon( KIcon( "edit-delete" ) );
712 delRule->setToolTip( i18n( "Remove rule" ) );
713 btnL->addWidget( delRule );
714 connect( delRule, SIGNAL(clicked()), this, SLOT(slotDelRule()) );
715 copyRule = new QPushButton( this );
716 copyRule->setIcon( KIcon( "edit-copy" ) );
717 copyRule->setToolTip( i18n( "Copy rule" ) );
718 btnL->addWidget( copyRule );
719 connect( copyRule, SIGNAL(clicked()), this, SLOT(slotCopyRule()) );
721 // the group filter
722 QBoxLayout *filterL = new QVBoxLayout();
723 topL->addItem( filterL );
724 filterL->setSpacing( KDialog::spacingHint() );
726 KComboBox *filterBox = new KComboBox( this );
727 QStringList l = m->getGroups();
728 filterBox->addItem( i18n( "<placeholder>all groups</placeholder>" ) );
729 filterBox->addItems( l );
730 filterBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
731 connect( filterBox, SIGNAL(activated(QString)),
732 this, SLOT(slotGroupFilter(QString)) );
733 slotGroupFilter( i18n( "<placeholder>all groups</placeholder>" ) );
734 QLabel *lab = new QLabel( i18n( "Sho&w only rules for group:" ), this );
735 lab->setBuddy( filterBox );
737 filterL->addWidget( lab );
738 filterL->addWidget( filterBox );
740 connect( manager, SIGNAL(changedRules()), this, SLOT(updateRuleList()) );
741 connect( manager, SIGNAL(changedRuleName(QString,QString)),
742 this, SLOT(slotRuleNameChanged(QString,QString)) );
744 updateRuleList();
745 updateButton();
748 RuleListWidget::~RuleListWidget()
752 void RuleListWidget::updateButton()
754 bool state = ruleList->count() > 0;
755 if( editRule ) {
756 editRule->setEnabled( state );
758 delRule->setEnabled( state );
759 copyRule->setEnabled( state );
761 Q3ListBoxItem *item = ruleList->item( ruleList->currentItem() );
762 if ( item ) {
763 mRuleUp->setEnabled( item->prev() != 0 );
764 mRuleDown->setEnabled( item->next() != 0 );
768 void RuleListWidget::updateRuleList()
770 emit leavingRule();
771 kDebug(5100) <<"RuleListWidget::updateRuleList()";
772 QString curr = ruleList->currentText();
773 ruleList->clear();
774 if ( group == i18n( "<placeholder>all groups</placeholder>" ) ) {
775 QStringList l = manager->getRuleNames();
776 ruleList->insertStringList( l );
777 } else {
778 KScoringManager::ScoringRuleList l = manager->getAllRules();
779 for ( KScoringRule *rule = l.first(); rule; rule = l.next() ) {
780 if ( rule->matchGroup( group ) ) {
781 ruleList->insertItem( rule->getName() );
785 int index = setCurrentItem( ruleList, curr );
786 if ( index < 0 ) {
787 ruleList->setCurrentItem( 0 );
788 slotRuleSelected( ruleList->currentText() );
789 } else {
790 slotRuleSelected( curr );
794 void RuleListWidget::updateRuleList( const KScoringRule *rule )
796 kDebug(5100) <<"RuleListWidget::updateRuleList(" << rule->getName() <<")";
797 QString name = rule->getName();
798 updateRuleList();
799 slotRuleSelected(name);
802 void RuleListWidget::slotRuleNameChanged( const QString &oldName, const QString &newName )
804 int ind = ruleList->currentItem();
805 for ( uint i=0; i<ruleList->count(); ++i ) {
806 if ( ruleList->text(i) == oldName ) {
807 ruleList->changeItem( newName, i );
808 ruleList->setCurrentItem( ind );
809 return;
814 void RuleListWidget::slotEditRule( const QString &s )
816 emit ruleEdited( s );
819 void RuleListWidget::slotEditRule()
821 if ( ruleList->currentItem() >= 0 ) {
822 emit ruleEdited( ruleList->currentText() );
823 } else if ( ruleList->count() == 0 ) {
824 emit ruleEdited( QString() );
828 void RuleListWidget::slotEditRule( Q3ListBoxItem *item )
830 slotEditRule( item->text() );
833 void RuleListWidget::slotGroupFilter( const QString &s )
835 group = s;
836 updateRuleList();
839 void RuleListWidget::slotRuleSelected( const QString &ruleName )
841 emit leavingRule();
842 kDebug(5100) <<"RuleListWidget::slotRuleSelected(" << ruleName <<")";
843 if ( ruleName != ruleList->currentText() ) {
844 setCurrentItem( ruleList, ruleName );
846 updateButton();
847 emit ruleSelected( ruleName );
850 void RuleListWidget::slotRuleSelected( Q3ListBoxItem *item )
852 if ( !item ) {
853 return;
855 QString ruleName = item->text();
856 slotRuleSelected( ruleName );
859 void RuleListWidget::slotRuleSelected( int index )
861 uint idx = index;
862 if ( idx >= ruleList->count() ) {
863 return;
865 QString ruleName = ruleList->text( index );
866 slotRuleSelected( ruleName );
869 void RuleListWidget::slotNewRule()
871 emit leavingRule();
872 KScoringRule *rule = manager->addRule();
873 updateRuleList( rule );
874 if ( alone ) {
875 slotEditRule( rule->getName() );
877 updateButton();
880 void RuleListWidget::slotDelRule()
882 KScoringRule *rule = manager->findRule( ruleList->currentText() );
883 if ( rule ) {
884 manager->deleteRule( rule );
886 // goto the next rule
887 if ( !alone ) {
888 slotEditRule();
890 updateButton();
893 void RuleListWidget::slotCopyRule()
895 emit leavingRule();
896 QString ruleName = ruleList->currentText();
897 KScoringRule *rule = manager->findRule( ruleName );
898 if ( rule ) {
899 KScoringRule *nrule = manager->copyRule( rule );
900 updateRuleList( nrule );
901 slotEditRule( nrule->getName() );
903 updateButton();
906 void RuleListWidget::slotRuleUp()
908 KScoringRule *rule = 0, *below = 0;
909 Q3ListBoxItem *item = ruleList->item( ruleList->currentItem() );
910 if ( item ) {
911 rule = manager->findRule( item->text() );
912 item = item->prev();
913 if ( item ) {
914 below = manager->findRule( item->text() );
917 if ( rule && below ) {
918 manager->moveRuleAbove( rule, below );
920 updateRuleList();
921 updateButton();
924 void RuleListWidget::slotRuleDown()
926 KScoringRule *rule = 0, *above = 0;
927 Q3ListBoxItem *item = ruleList->item( ruleList->currentItem() );
928 if ( item ) {
929 rule = manager->findRule( item->text() );
930 item = item->next();
931 if ( item ) {
932 above = manager->findRule( item->text() );
935 if ( rule && above ) {
936 manager->moveRuleBelow( rule, above );
938 updateRuleList();
939 updateButton();
942 //============================================================================
944 // class KScoringEditor (the score edit dialog)
946 //============================================================================
947 KScoringEditor *KScoringEditor::scoreEditor = 0;
949 KScoringEditor::KScoringEditor( KScoringManager *m, QWidget *parent )
950 : KDialog( parent ), manager( m )
952 setCaption( i18n( "Rule Editor" ) );
953 setButtons( Ok|Apply|Cancel );
954 setDefaultButton( Ok );
955 setModal( false );
956 showButtonSeparator( true );
957 manager->pushRuleList();
958 if ( !scoreEditor ) {
959 scoreEditor = this;
961 kDebug(5100) <<"KScoringEditor::KScoringEditor()";
962 // the left side gives an overview about all rules, the right side
963 // shows a detailed view of an selected rule
964 QWidget *w = new QWidget( this );
965 setMainWidget( w );
966 QHBoxLayout *hbl = new QHBoxLayout( w );
967 hbl->setMargin( 0 );
968 hbl->setSpacing( spacingHint() );
970 ruleLister = new RuleListWidget( manager, false, w );
971 hbl->addWidget( ruleLister );
972 ruleEditor = new RuleEditWidget( manager, w );
973 hbl->addWidget( ruleEditor );
974 connect( ruleLister, SIGNAL(ruleSelected(QString)),
975 ruleEditor, SLOT(slotEditRule(QString)) );
976 connect( ruleLister, SIGNAL(leavingRule()), ruleEditor, SLOT(updateRule()) );
977 connect( ruleEditor, SIGNAL(shrink()), SLOT(slotShrink()) );
978 connect( this, SIGNAL(finished()), SLOT(slotFinished()) );
979 connect( this, SIGNAL(okClicked()), SLOT(slotOk()) );
980 connect( this, SIGNAL(cancelClicked()), SLOT(slotCancel()) );
981 connect( this, SIGNAL(applyClicked()), SLOT(slotApply()) );
982 ruleLister->slotRuleSelected( 0 );
983 resize( 550, sizeHint().height() );
986 void KScoringEditor::setDirty()
988 enableButton( Apply, true );
991 KScoringEditor::~KScoringEditor()
993 scoreEditor = 0;
996 KScoringEditor *KScoringEditor::createEditor( KScoringManager *m, QWidget *parent )
998 if ( scoreEditor ) {
999 return scoreEditor;
1000 } else {
1001 return new KScoringEditor( m, parent );
1005 void KScoringEditor::setRule( KScoringRule *r )
1007 kDebug(5100) <<"KScoringEditor::setRule(" << r->getName() <<")";
1008 QString ruleName = r->getName();
1009 ruleLister->slotRuleSelected( ruleName );
1012 void KScoringEditor::slotShrink()
1014 QTimer::singleShot( 5, this, SLOT(slotDoShrink()) );
1017 void KScoringEditor::slotDoShrink()
1019 updateGeometry();
1020 QApplication::sendPostedEvents();
1021 resize( width(), sizeHint().height() );
1024 void KScoringEditor::slotApply()
1026 QString ruleName = ruleLister->currentRule();
1027 KScoringRule *rule = manager->findRule( ruleName );
1028 if ( rule ) {
1029 ruleEditor->updateRule( rule );
1030 ruleLister->updateRuleList( rule );
1032 manager->removeTOS();
1033 manager->pushRuleList();
1036 void KScoringEditor::slotOk()
1038 slotApply();
1039 manager->removeTOS();
1040 manager->editorReady();
1043 void KScoringEditor::slotCancel()
1045 manager->popRuleList();
1046 KDialog::reject();
1049 void KScoringEditor::slotFinished()
1051 delayedDestruct();
1054 //============================================================================
1056 // class KScoringEditorWidgetDialog (a dialog for the KScoringEditorWidget)
1058 //============================================================================
1059 KScoringEditorWidgetDialog::KScoringEditorWidgetDialog( KScoringManager *m,
1060 const QString &r,
1061 QWidget *p )
1062 : KDialog( p ), manager( m ), ruleName( r )
1064 setCaption( i18n( "Edit Rule" ) );
1065 setButtons( KDialog::Ok|KDialog::Apply|KDialog::Cancel );
1066 setDefaultButton( KDialog::Ok );
1067 setModal( true );
1068 showButtonSeparator( true );
1069 QFrame *f = new QFrame( this );
1070 setMainWidget( f );
1071 QBoxLayout *topL = new QVBoxLayout( f );
1072 ruleEditor = new RuleEditWidget( manager, f );
1073 connect( ruleEditor, SIGNAL(shrink()), SLOT(slotShrink()) );
1074 connect( this, SIGNAL(okClicked()), SLOT(slotOk()) );
1075 topL->addWidget( ruleEditor );
1076 ruleEditor->slotEditRule( ruleName );
1077 resize( 0, 0 );
1080 void KScoringEditorWidgetDialog::slotApply()
1082 KScoringRule *rule = manager->findRule( ruleName );
1083 if ( rule ) {
1084 ruleEditor->updateRule( rule );
1085 ruleName = rule->getName();
1089 void KScoringEditorWidgetDialog::slotOk()
1091 slotApply();
1092 KDialog::accept();
1095 void KScoringEditorWidgetDialog::slotShrink()
1097 QTimer::singleShot( 5, this, SLOT(slotDoShrink()) );
1100 void KScoringEditorWidgetDialog::slotDoShrink()
1102 updateGeometry();
1103 QApplication::sendPostedEvents();
1104 resize( width(), sizeHint().height() );
1107 //============================================================================
1109 // class KScoringEditorWidget (a reusable widget for config dialog...)
1111 //============================================================================
1112 KScoringEditorWidget::KScoringEditorWidget( KScoringManager *m, QWidget *p, const char *n )
1113 : QWidget( p ), manager( m )
1115 setObjectName( n );
1116 QBoxLayout *topL = new QVBoxLayout( this );
1117 ruleLister = new RuleListWidget( manager, true, this );
1118 topL->addWidget( ruleLister );
1119 connect( ruleLister, SIGNAL(ruleEdited(QString)),
1120 this, SLOT(slotRuleEdited(QString)) );
1123 KScoringEditorWidget::~KScoringEditorWidget()
1125 manager->editorReady();
1128 void KScoringEditorWidget::slotRuleEdited( const QString &ruleName )
1130 KScoringEditorWidgetDialog dlg( manager, ruleName, this );
1131 dlg.exec();
1132 ruleLister->updateRuleList();
1135 #include "kscoringeditor.moc"