00001
00002
00003
00004
00005
00006
00007 #include <config.h>
00008 #include "kmfilterdlg.h"
00009
00010
00011 #include "kmsearchpatternedit.h"
00012 #include "kmfiltermgr.h"
00013 #include "foldersetselector.h"
00014 #include "kmmainwidget.h"
00015 #include "globalsettings.h"
00016
00017
00018 #include <kmessagebox.h>
00019 #include <kdebug.h>
00020 #include <klocale.h>
00021 #include <kinputdialog.h>
00022 #include <kiconloader.h>
00023 #include <kapplication.h>
00024 #include <kwin.h>
00025 #include <kconfig.h>
00026 #include <kicondialog.h>
00027
00028
00029 #include <qlayout.h>
00030 #include <qlabel.h>
00031 #include <qcombobox.h>
00032 #include <qwidgetstack.h>
00033 #include <qtooltip.h>
00034 #include <qwhatsthis.h>
00035 #include <qcheckbox.h>
00036 #include <qpushbutton.h>
00037 #include <qhbox.h>
00038
00039
00040 #include <assert.h>
00041
00042 using namespace KMail;
00043
00044
00045
00046 const char * _wt_filterlist =
00047 I18N_NOOP( "<qt><p>This is the list of defined filters. "
00048 "They are processed top-to-bottom.</p>"
00049 "<p>Click on any filter to edit it "
00050 "using the controls in the right-hand half "
00051 "of the dialog.</p></qt>" );
00052 const char * _wt_filterlist_new =
00053 I18N_NOOP( "<qt><p>Click this button to create a new filter.</p>"
00054 "<p>The filter will be inserted just before the currently-"
00055 "selected one, but you can always change that "
00056 "later on.</p>"
00057 "<p>If you have clicked this button accidentally, you can undo this "
00058 "by clicking on the <em>Delete</em> button.</p></qt>" );
00059 const char * _wt_filterlist_copy =
00060 I18N_NOOP( "<qt><p>Click this button to copy a filter.</p>"
00061 "<p>If you have clicked this button accidentally, you can undo this "
00062 "by clicking on the <em>Delete</em> button.</p></qt>" );
00063 const char * _wt_filterlist_delete =
00064 I18N_NOOP( "<qt><p>Click this button to <em>delete</em> the currently-"
00065 "selected filter from the list above.</p>"
00066 "<p>There is no way to get the filter back once "
00067 "it is deleted, but you can always leave the "
00068 "dialog by clicking <em>Cancel</em> to discard the "
00069 "changes made.</p></qt>" );
00070 const char * _wt_filterlist_up =
00071 I18N_NOOP( "<qt><p>Click this button to move the currently-"
00072 "selected filter <em>up</em> one in the list above.</p>"
00073 "<p>This is useful since the order of the filters in the list "
00074 "determines the order in which they are tried on messages: "
00075 "The topmost filter gets tried first.</p>"
00076 "<p>If you have clicked this button accidentally, you can undo this "
00077 "by clicking on the <em>Down</em> button.</p></qt>" );
00078 const char * _wt_filterlist_down =
00079 I18N_NOOP( "<qt><p>Click this button to move the currently-"
00080 "selected filter <em>down</em> one in the list above.</p>"
00081 "<p>This is useful since the order of the filters in the list "
00082 "determines the order in which they are tried on messages: "
00083 "The topmost filter gets tried first.</p>"
00084 "<p>If you have clicked this button accidentally, you can undo this "
00085 "by clicking on the <em>Up</em> button.</p></qt>" );
00086 const char * _wt_filterlist_rename =
00087 I18N_NOOP( "<qt><p>Click this button to rename the currently-selected filter.</p>"
00088 "<p>Filters are named automatically, as long as they start with "
00089 "\"<<\".</p>"
00090 "<p>If you have renamed a filter accidentally and want automatic "
00091 "naming back, click this button and select <em>Clear</em> followed "
00092 "by <em>OK</em> in the appearing dialog.</p></qt>" );
00093 const char * _wt_filterdlg_showLater =
00094 I18N_NOOP( "<qt><p>Check this button to force the confirmation dialog to be "
00095 "displayed.</p><p>This is useful if you have defined a ruleset that tags "
00096 "messages to be downloaded later. Without the possibility to force "
00097 "the dialog popup, these messages could never be downloaded if no "
00098 "other large messages were waiting on the server, or if you wanted to "
00099 "change the ruleset to tag the messages differently.</p></qt>" );
00100
00101
00102 const char * KMFilterDlgHelpAnchor = "filters-id" ;
00103 const char * KMPopFilterDlgHelpAnchor = "popfilters-id" ;
00104
00105
00106
00107
00108
00109
00110
00111 KMFilterDlg::KMFilterDlg(QWidget* parent, const char* name, bool popFilter)
00112 : KDialogBase( parent, name, FALSE ,
00113 (popFilter)? i18n("POP3 Filter Rules"): i18n("Filter Rules") ,
00114 Help|Ok|Apply|Cancel ,
00115 Ok , FALSE ),
00116 bPopFilter(popFilter)
00117 {
00118 KWin::setIcons( winId(), kapp->icon(), kapp->miniIcon() );
00119 setHelp( (bPopFilter)? KMPopFilterDlgHelpAnchor: KMFilterDlgHelpAnchor );
00120
00121 QWidget *w = new QWidget(this);
00122 setMainWidget(w);
00123 QHBoxLayout *hbl = new QHBoxLayout( w, 0, spacingHint(), "kmfd_hbl" );
00124
00125 mFilterList = new KMFilterListBox( i18n("Available Filters"), w, 0, bPopFilter);
00126 hbl->addWidget( mFilterList, 1 );
00127
00128 QVBoxLayout *vbl = new QVBoxLayout( hbl, spacingHint(), "kmfd_vbl" );
00129 hbl->setStretchFactor( vbl, 2 );
00130
00131 mPatternEdit = new KMSearchPatternEdit( i18n("Filter Criteria"), w , "spe", bPopFilter);
00132 vbl->addWidget( mPatternEdit, 0, Qt::AlignTop );
00133
00134 if(bPopFilter){
00135 mActionGroup = new KMPopFilterActionWidget( i18n("Filter Action"), w );
00136 vbl->addWidget( mActionGroup, 0, Qt::AlignTop );
00137
00138 mGlobalsBox = new QVGroupBox(i18n("Global Options"), w);
00139 mShowLaterBtn = new QCheckBox(i18n("Always &show matched 'Download Later' messages in confirmation dialog"), mGlobalsBox);
00140 QWhatsThis::add( mShowLaterBtn, i18n(_wt_filterdlg_showLater) );
00141 vbl->addWidget( mGlobalsBox, 0, Qt::AlignTop );
00142 }
00143 else {
00144 QGroupBox *agb = new QGroupBox( 1 , Vertical, i18n("Filter Actions"), w );
00145 mActionLister = new KMFilterActionWidgetLister( agb );
00146 vbl->addWidget( agb, 0, Qt::AlignTop );
00147
00148 mAdvOptsGroup = new QGroupBox ( 1 , Vertical,
00149 i18n("Advanced Options"), w);
00150 {
00151 QWidget *adv_w = new QWidget( mAdvOptsGroup );
00152 QGridLayout *gl = new QGridLayout( adv_w, 4 , 4 ,
00153 0 , spacingHint() );
00154 gl->setColStretch( 0, 1 );
00155 QLabel *l = new QLabel( i18n("Apply this filter"), adv_w );
00156 gl->addWidget( l, 0, 0, AlignLeft );
00157 mApplyOnIn = new QCheckBox( i18n("to &incoming messages"), adv_w );
00158 gl->addWidget( mApplyOnIn, 0, 1 );
00159 mApplyOnOut = new QCheckBox( i18n("to &sent messages"), adv_w );
00160 gl->addWidget( mApplyOnOut, 0, 2 );
00161 mApplyOnCtrlJ = new QCheckBox( i18n("on manual &filtering"), adv_w );
00162 gl->addWidget( mApplyOnCtrlJ, 0, 3 );
00163 mStopProcessingHere = new QCheckBox( i18n("If this filter &matches, stop processing here"), adv_w );
00164 gl->addMultiCellWidget( mStopProcessingHere,
00165 1, 1,
00166 0, 3 );
00167 mConfigureShortcut = new QCheckBox( i18n("Add this filter to the Apply Filter menu"), adv_w );
00168 gl->addMultiCellWidget( mConfigureShortcut, 2, 2, 0, 3 );
00169
00170 QHBox *hbox = new QHBox( adv_w );
00171 mFilterActionLabel = new QLabel( i18n( "Icon for this filter:" ),
00172 hbox );
00173 mFilterActionLabel->setEnabled( false );
00174
00175 mFilterActionIconButton = new KIconButton( hbox );
00176 mFilterActionLabel->setBuddy( mFilterActionIconButton );
00177 mFilterActionIconButton->setIconType( KIcon::NoGroup, KIcon::Any, true );
00178 mFilterActionIconButton->setIconSize( 16 );
00179 mFilterActionIconButton->setIcon( "gear" );
00180 mFilterActionIconButton->setEnabled( false );
00181
00182 gl->addMultiCellWidget( hbox, 3, 3, 0, 3 );
00183 }
00184 vbl->addWidget( mAdvOptsGroup, 0, Qt::AlignTop );
00185 }
00186
00187 vbl->addStretch( 1 );
00188
00189
00190 connect( mFilterList, SIGNAL(filterSelected(KMFilter*)),
00191 this, SLOT(slotFilterSelected(KMFilter*)) );
00192
00193 if (bPopFilter){
00194
00195 connect( mShowLaterBtn, SIGNAL(toggled(bool)),
00196 mFilterList, SLOT(slotShowLaterToggled(bool)));
00197
00198
00199 connect( mActionGroup, SIGNAL(actionChanged(const KMPopFilterAction)),
00200 this, SLOT(slotActionChanged(const KMPopFilterAction)) );
00201 } else {
00202
00203
00204 connect( mApplyOnIn, SIGNAL(clicked()),
00205 this, SLOT(slotApplicabilityChanged()) );
00206 connect( mApplyOnOut, SIGNAL(clicked()),
00207 this, SLOT(slotApplicabilityChanged()) );
00208 connect( mApplyOnCtrlJ, SIGNAL(clicked()),
00209 this, SLOT(slotApplicabilityChanged()) );
00210
00211
00212
00213 connect( mStopProcessingHere, SIGNAL(toggled(bool)),
00214 this, SLOT(slotStopProcessingButtonToggled(bool)) );
00215
00216 connect( mConfigureShortcut, SIGNAL(toggled(bool)),
00217 this, SLOT(slotConfigureShortcutButtonToggled(bool)) );
00218
00219 connect( mFilterActionIconButton, SIGNAL( iconChanged( QString ) ),
00220 this, SLOT( slotFilterActionIconChanged( QString ) ) );
00221 }
00222
00223
00224 connect( mFilterList, SIGNAL(resetWidgets()),
00225 this, SLOT(slotReset()) );
00226
00227 connect( mFilterList, SIGNAL( applyWidgets() ),
00228 this, SLOT( slotUpdateFilter() ) );
00229
00230
00231 connect( mPatternEdit, SIGNAL(maybeNameChanged()),
00232 mFilterList, SLOT(slotUpdateFilterName()) );
00233
00234
00235 connect( this, SIGNAL(applyClicked()),
00236 mFilterList, SLOT(slotApplyFilterChanges()) );
00237
00238
00239 connect( this, SIGNAL(okClicked()),
00240 mFilterList, SLOT(slotApplyFilterChanges()) );
00241
00242
00243 connect( this, SIGNAL(okClicked()),
00244 this, SLOT(slotSaveSize()) );
00245
00246
00247 connect( this, SIGNAL(finished()),
00248 this, SLOT(slotFinished()) );
00249
00250 KConfigGroup geometry( KMKernel::config(), "Geometry");
00251 const char * configKey
00252 = bPopFilter ? "popFilterDialogSize" : "filterDialogSize";
00253 if ( geometry.hasKey( configKey ) )
00254 resize( geometry.readSizeEntry( configKey ) );
00255 else
00256 adjustSize();
00257
00258
00259 mFilterList->loadFilterList();
00260 }
00261
00262 void KMFilterDlg::slotFinished() {
00263 delayedDestruct();
00264 }
00265
00266 void KMFilterDlg::slotSaveSize() {
00267 KConfigGroup geometry( KMKernel::config(), "Geometry" );
00268 geometry.writeEntry( bPopFilter ? "popFilterDialogSize" : "filterDialogSize", size() );
00269 }
00270
00272 void KMFilterDlg::slotActionChanged(const KMPopFilterAction aAction)
00273 {
00274 mFilter->setAction(aAction);
00275 }
00276
00277 void KMFilterDlg::slotFilterSelected( KMFilter* aFilter )
00278 {
00279 assert( aFilter );
00280
00281 if (bPopFilter){
00282 mActionGroup->setAction( aFilter->action() );
00283 mGlobalsBox->setEnabled(true);
00284 mShowLaterBtn->setChecked(mFilterList->showLaterMsgs());
00285 } else {
00286 mActionLister->setActionList( aFilter->actions() );
00287
00288 mAdvOptsGroup->setEnabled( true );
00289 }
00290
00291 mPatternEdit->setSearchPattern( aFilter->pattern() );
00292 mFilter = aFilter;
00293
00294 if (!bPopFilter) {
00295 kdDebug(5006) << "apply on inbound == "
00296 << aFilter->applyOnInbound() << endl;
00297 kdDebug(5006) << "apply on outbound == "
00298 << aFilter->applyOnOutbound() << endl;
00299 kdDebug(5006) << "apply on explicit == "
00300 << aFilter->applyOnExplicit() << endl;
00301
00302
00303
00304
00305 const bool applyOnIn = aFilter->applyOnInbound();
00306 const bool applyOnOut = aFilter->applyOnOutbound();
00307 const bool applyOnExplicit = aFilter->applyOnExplicit();
00308 const bool stopHere = aFilter->stopProcessingHere();
00309 const bool configureShortcut = aFilter->configureShortcut();
00310 const QString icon = aFilter->icon();
00311
00312 mApplyOnIn->setChecked( applyOnIn );
00313 mApplyOnOut->setChecked( applyOnOut );
00314 mApplyOnCtrlJ->setChecked( applyOnExplicit );
00315 mStopProcessingHere->setChecked( stopHere );
00316 mConfigureShortcut->setChecked( configureShortcut );
00317 mFilterActionIconButton->setIcon( icon );
00318 }
00319 }
00320
00321 void KMFilterDlg::slotReset()
00322 {
00323 mFilter = 0;
00324 mPatternEdit->reset();
00325
00326 if(bPopFilter) {
00327 mActionGroup->reset();
00328 mGlobalsBox->setEnabled( false );
00329 } else {
00330 mActionLister->reset();
00331 mAdvOptsGroup->setEnabled( false );
00332 }
00333 }
00334
00335 void KMFilterDlg::slotUpdateFilter()
00336 {
00337 mPatternEdit->updateSearchPattern();
00338 if ( !bPopFilter ) {
00339 mActionLister->updateActionList();
00340 }
00341 }
00342
00343 void KMFilterDlg::slotApplicabilityChanged()
00344 {
00345 if ( !mFilter )
00346 return;
00347
00348 mFilter->setApplyOnInbound( mApplyOnIn->isChecked() );
00349 mFilter->setApplyOnOutbound( mApplyOnOut->isChecked() );
00350 mFilter->setApplyOnExplicit( mApplyOnCtrlJ->isChecked() );
00351 kdDebug(5006) << "KMFilterDlg: setting filter to be applied at "
00352 << ( mFilter->applyOnInbound() ? "incoming " : "" )
00353 << ( mFilter->applyOnOutbound() ? "outgoing " : "" )
00354 << ( mFilter->applyOnExplicit() ? "explicit CTRL-J" : "" )
00355 << endl;
00356 }
00357
00358 void KMFilterDlg::slotStopProcessingButtonToggled( bool aChecked )
00359 {
00360 if ( !mFilter )
00361 return;
00362
00363 mFilter->setStopProcessingHere( aChecked );
00364 }
00365
00366 void KMFilterDlg::slotConfigureShortcutButtonToggled( bool aChecked )
00367 {
00368 if ( !mFilter )
00369 return;
00370
00371 mFilter->setConfigureShortcut( aChecked );
00372 mFilterActionIconButton->setEnabled( aChecked );
00373 mFilterActionLabel->setEnabled( aChecked );
00374 }
00375
00376 void KMFilterDlg::slotFilterActionIconChanged( QString icon )
00377 {
00378 if ( !mFilter )
00379 return;
00380
00381 mFilter->setIcon( icon );
00382 }
00383
00384
00385
00386
00387
00388
00389
00390 KMFilterListBox::KMFilterListBox( const QString & title, QWidget *parent, const char* name, bool popFilter )
00391 : QGroupBox( 1, Horizontal, title, parent, name ),
00392 bPopFilter(popFilter)
00393 {
00394 mFilterList.setAutoDelete(TRUE);
00395 mIdxSelItem = -1;
00396
00397
00398 mListBox = new QListBox(this);
00399 mListBox->setMinimumWidth(150);
00400 QWhatsThis::add( mListBox, i18n(_wt_filterlist) );
00401
00402
00403 QHBox *hb = new QHBox(this);
00404 hb->setSpacing(4);
00405 mBtnUp = new QPushButton( QString::null, hb );
00406 mBtnUp->setAutoRepeat( true );
00407 mBtnUp->setPixmap( BarIcon( "up", KIcon::SizeSmall ) );
00408 mBtnUp->setMinimumSize( mBtnUp->sizeHint() * 1.2 );
00409 mBtnDown = new QPushButton( QString::null, hb );
00410 mBtnDown->setAutoRepeat( true );
00411 mBtnDown->setPixmap( BarIcon( "down", KIcon::SizeSmall ) );
00412 mBtnDown->setMinimumSize( mBtnDown->sizeHint() * 1.2 );
00413 QToolTip::add( mBtnUp, i18n("Up") );
00414 QToolTip::add( mBtnDown, i18n("Down") );
00415 QWhatsThis::add( mBtnUp, i18n(_wt_filterlist_up) );
00416 QWhatsThis::add( mBtnDown, i18n(_wt_filterlist_down) );
00417
00418
00419 hb = new QHBox(this);
00420 hb->setSpacing(4);
00421 mBtnNew = new QPushButton( QString::null, hb );
00422 mBtnNew->setPixmap( BarIcon( "filenew", KIcon::SizeSmall ) );
00423 mBtnNew->setMinimumSize( mBtnNew->sizeHint() * 1.2 );
00424 mBtnCopy = new QPushButton( QString::null, hb );
00425 mBtnCopy->setPixmap( BarIcon( "editcopy", KIcon::SizeSmall ) );
00426 mBtnCopy->setMinimumSize( mBtnCopy->sizeHint() * 1.2 );
00427 mBtnDelete = new QPushButton( QString::null, hb );
00428 mBtnDelete->setPixmap( BarIcon( "editdelete", KIcon::SizeSmall ) );
00429 mBtnDelete->setMinimumSize( mBtnDelete->sizeHint() * 1.2 );
00430 mBtnRename = new QPushButton( i18n("Rename..."), hb );
00431 QToolTip::add( mBtnNew, i18n("New") );
00432 QToolTip::add( mBtnCopy, i18n("Copy") );
00433 QToolTip::add( mBtnDelete, i18n("Delete"));
00434 QWhatsThis::add( mBtnNew, i18n(_wt_filterlist_new) );
00435 QWhatsThis::add( mBtnCopy, i18n(_wt_filterlist_copy) );
00436 QWhatsThis::add( mBtnDelete, i18n(_wt_filterlist_delete) );
00437 QWhatsThis::add( mBtnRename, i18n(_wt_filterlist_rename) );
00438
00439
00440 if ( !popFilter ) {
00441 hb = new QHBox( this );
00442 hb->setSpacing( 4 );
00443 QPushButton *btn = new QPushButton( i18n("Select Source Folders"), hb );
00444 connect( btn, SIGNAL(clicked()), SLOT(slotSelectSourceFolders()) );
00445 }
00446
00447
00448
00449 connect( mListBox, SIGNAL(highlighted(int)),
00450 this, SLOT(slotSelected(int)) );
00451 connect( mListBox, SIGNAL( doubleClicked ( QListBoxItem * )),
00452 this, SLOT( slotRename()) );
00453 connect( mBtnUp, SIGNAL(clicked()),
00454 this, SLOT(slotUp()) );
00455 connect( mBtnDown, SIGNAL(clicked()),
00456 this, SLOT(slotDown()) );
00457 connect( mBtnNew, SIGNAL(clicked()),
00458 this, SLOT(slotNew()) );
00459 connect( mBtnCopy, SIGNAL(clicked()),
00460 this, SLOT(slotCopy()) );
00461 connect( mBtnDelete, SIGNAL(clicked()),
00462 this, SLOT(slotDelete()) );
00463 connect( mBtnRename, SIGNAL(clicked()),
00464 this, SLOT(slotRename()) );
00465
00466
00467
00468 enableControls();
00469 }
00470
00471
00472 void KMFilterListBox::createFilter( const QCString & field,
00473 const QString & value )
00474 {
00475 KMSearchRule *newRule = KMSearchRule::createInstance( field, KMSearchRule::FuncContains, value );
00476
00477 KMFilter *newFilter = new KMFilter(0, bPopFilter);
00478 newFilter->pattern()->append( newRule );
00479 newFilter->pattern()->setName( QString("<%1>:%2").arg( field ).arg( value) );
00480
00481 KMFilterActionDesc *desc = (*kmkernel->filterActionDict())["transfer"];
00482 if ( desc )
00483 newFilter->actions()->append( desc->create() );
00484
00485 insertFilter( newFilter );
00486 enableControls();
00487 }
00488
00489 bool KMFilterListBox::showLaterMsgs()
00490 {
00491 return mShowLater;
00492 }
00493
00494 void KMFilterListBox::slotUpdateFilterName()
00495 {
00496 KMSearchPattern *p = mFilterList.at(mIdxSelItem)->pattern();
00497 if ( !p ) return;
00498
00499 QString shouldBeName = p->name();
00500 QString displayedName = mListBox->text( mIdxSelItem );
00501
00502 if ( shouldBeName.stripWhiteSpace().isEmpty() || shouldBeName[0] == '<' ) {
00503
00504 if ( p->first() && !p->first()->field().stripWhiteSpace().isEmpty() )
00505 shouldBeName = QString( "<%1>: %2" ).arg( p->first()->field() ).arg( p->first()->contents() );
00506 else
00507 shouldBeName = "<" + i18n("unnamed") + ">";
00508 p->setName( shouldBeName );
00509 }
00510
00511 if ( displayedName == shouldBeName ) return;
00512
00513 mListBox->blockSignals(TRUE);
00514 mListBox->changeItem( shouldBeName, mIdxSelItem );
00515 mListBox->blockSignals(FALSE);
00516 }
00517
00518 void KMFilterListBox::slotShowLaterToggled(bool aOn)
00519 {
00520 mShowLater = aOn;
00521 }
00522
00523 void KMFilterListBox::slotApplyFilterChanges()
00524 {
00525 int oIdxSelItem = mIdxSelItem;
00526
00527 mListBox->selectAll( FALSE );
00528
00529
00530 emit resetWidgets();
00531 mIdxSelItem = -1;
00532 enableControls();
00533
00534
00535
00536
00537 KMFilterMgr *fm;
00538 if (bPopFilter)
00539 fm = kmkernel->popFilterMgr();
00540 else
00541 fm = kmkernel->filterMgr();
00542
00543
00544 fm->beginUpdate();
00545 fm->clear();
00546
00547 QStringList emptyFilters;
00548 QPtrListIterator<KMFilter> it( mFilterList );
00549 for ( it.toFirst() ; it.current() ; ++it ) {
00550 KMFilter *f = new KMFilter( **it );
00551 f->purify();
00552 if ( !f->isEmpty() )
00553
00554 fm->append( f );
00555 else {
00556
00557 emptyFilters << f->name();
00558 delete f;
00559 }
00560 }
00561 if (bPopFilter)
00562 fm->setShowLaterMsgs(mShowLater);
00563
00564
00565 fm->endUpdate();
00566 fm->writeConfig();
00567
00568
00569 if ( !emptyFilters.empty() ) {
00570 QString msg = i18n("The following filters have not been saved because they "
00571 "were invalid (e.g. containing no actions or no search "
00572 "rules).");
00573 KMessageBox::informationList( 0, msg, emptyFilters, QString::null,
00574 "ShowInvalidFilterWarning" );
00575 }
00576
00577 if ( oIdxSelItem >= 0 ) {
00578 mIdxSelItem = oIdxSelItem;
00579 mListBox->setSelected( oIdxSelItem, TRUE);
00580 slotSelected( mListBox->currentItem() );
00581 }
00582 }
00583
00584 void KMFilterListBox::slotSelected( int aIdx )
00585 {
00586 mIdxSelItem = aIdx;
00587
00588 KMFilter *f = mFilterList.at(aIdx);
00589 if ( f )
00590 emit filterSelected( f );
00591 else
00592 emit resetWidgets();
00593 enableControls();
00594 }
00595
00596 void KMFilterListBox::slotNew()
00597 {
00598
00599 insertFilter( new KMFilter(0, bPopFilter) );
00600 enableControls();
00601 }
00602
00603 void KMFilterListBox::slotCopy()
00604 {
00605 if ( mIdxSelItem < 0 ) {
00606 kdDebug(5006) << "KMFilterListBox::slotCopy called while no filter is selected, ignoring." << endl;
00607 return;
00608 }
00609
00610
00611 emit applyWidgets();
00612
00613 KMFilter *filter = mFilterList.at( mIdxSelItem );
00614
00615
00616
00617 assert( filter );
00618
00619
00620 insertFilter( new KMFilter( *filter ) );
00621 enableControls();
00622 }
00623
00624 void KMFilterListBox::slotDelete()
00625 {
00626 if ( mIdxSelItem < 0 ) {
00627 kdDebug(5006) << "KMFilterListBox::slotDelete called while no filter is selected, ignoring." << endl;
00628 return;
00629 }
00630
00631 int oIdxSelItem = mIdxSelItem;
00632 mIdxSelItem = -1;
00633
00634 mListBox->selectAll(FALSE);
00635
00636
00637 emit resetWidgets();
00638
00639
00640 mFilterList.remove( oIdxSelItem );
00641
00642 mListBox->removeItem( oIdxSelItem );
00643
00644 int count = (int)mListBox->count();
00645
00646 if ( count > oIdxSelItem )
00647
00648 mListBox->setSelected( oIdxSelItem, TRUE );
00649 else if ( (int)mListBox->count() )
00650
00651
00652 mListBox->setSelected( count - 1, TRUE );
00653
00654
00655 enableControls();
00656 }
00657
00658 void KMFilterListBox::slotUp()
00659 {
00660 if ( mIdxSelItem < 0 ) {
00661 kdDebug(5006) << "KMFilterListBox::slotUp called while no filter is selected, ignoring." << endl;
00662 return;
00663 }
00664 if ( mIdxSelItem == 0 ) {
00665 kdDebug(5006) << "KMFilterListBox::slotUp called while the _topmost_ filter is selected, ignoring." << endl;
00666 return;
00667 }
00668
00669 swapNeighbouringFilters( mIdxSelItem, mIdxSelItem - 1 );
00670 enableControls();
00671 }
00672
00673 void KMFilterListBox::slotDown()
00674 {
00675 if ( mIdxSelItem < 0 ) {
00676 kdDebug(5006) << "KMFilterListBox::slotDown called while no filter is selected, ignoring." << endl;
00677 return;
00678 }
00679 if ( mIdxSelItem == (int)mListBox->count() - 1 ) {
00680 kdDebug(5006) << "KMFilterListBox::slotDown called while the _last_ filter is selected, ignoring." << endl;
00681 return;
00682 }
00683
00684 swapNeighbouringFilters( mIdxSelItem, mIdxSelItem + 1);
00685 enableControls();
00686 }
00687
00688 void KMFilterListBox::slotRename()
00689 {
00690 if ( mIdxSelItem < 0 ) {
00691 kdDebug(5006) << "KMFilterListBox::slotRename called while no filter is selected, ignoring." << endl;
00692 return;
00693 }
00694
00695 bool okPressed = FALSE;
00696 KMFilter *filter = mFilterList.at( mIdxSelItem );
00697
00698
00699
00700 assert( filter );
00701
00702 QString newName = KInputDialog::getText
00703 (
00704 i18n("Rename Filter"),
00705 i18n("Rename filter \"%1\" to:").arg( filter->pattern()->name() ) ,
00706 filter->pattern()->name() ,
00707 &okPressed, topLevelWidget()
00708 );
00709
00710 if ( !okPressed ) return;
00711
00712 if ( newName.isEmpty() )
00713
00714
00715 filter->pattern()->setName( "<>" );
00716 else
00717 filter->pattern()->setName( newName );
00718
00719 slotUpdateFilterName();
00720 }
00721
00722 void KMFilterListBox::slotSelectSourceFolders()
00723 {
00724 FolderSetSelector dlg( kmkernel->getKMMainWidget()->folderTree(), this );
00725 dlg.setCaption( i18n( "Select Folders to Filter" ) );
00726 if ( !GlobalSettings::filterSourceFolders().isEmpty() )
00727 dlg.setSelectedFolders( GlobalSettings::filterSourceFolders() );
00728 if ( dlg.exec() == QDialog::Accepted ) {
00729 GlobalSettings::setFilterSourceFolders( dlg.selectedFolders() );
00730 }
00731 }
00732
00733 void KMFilterListBox::enableControls()
00734 {
00735 bool theFirst = ( mIdxSelItem == 0 );
00736 bool theLast = ( mIdxSelItem >= (int)mFilterList.count() - 1 );
00737 bool aFilterIsSelected = ( mIdxSelItem >= 0 );
00738
00739 mBtnUp->setEnabled( aFilterIsSelected && !theFirst );
00740 mBtnDown->setEnabled( aFilterIsSelected && !theLast );
00741 mBtnCopy->setEnabled( aFilterIsSelected );
00742 mBtnDelete->setEnabled( aFilterIsSelected );
00743 mBtnRename->setEnabled( aFilterIsSelected );
00744
00745 if ( aFilterIsSelected )
00746 mListBox->ensureCurrentVisible();
00747 }
00748
00749 void KMFilterListBox::loadFilterList()
00750 {
00751 assert(mListBox);
00752 setEnabled(FALSE);
00753
00754
00755 blockSignals(TRUE);
00756
00757
00758 mFilterList.clear();
00759 mListBox->clear();
00760
00761 QPtrList<KMFilter> *manager;
00762 if(bPopFilter)
00763 {
00764 mShowLater = kmkernel->popFilterMgr()->showLaterMsgs();
00765 manager = kmkernel->popFilterMgr();
00766 }
00767 else
00768 {
00769 manager = kmkernel->filterMgr();
00770 }
00771
00772 QPtrListIterator<KMFilter> it( *manager );
00773 for ( it.toFirst() ; it.current() ; ++it ) {
00774 mFilterList.append( new KMFilter( **it ) );
00775 mListBox->insertItem( (*it)->pattern()->name() );
00776 }
00777
00778 blockSignals(FALSE);
00779 setEnabled(TRUE);
00780
00781
00782
00783
00784 if ( !mListBox->count() )
00785 slotNew();
00786
00787 assert( mListBox->count() > 0 );
00788 mListBox->setSelected( 0, true );
00789
00790 enableControls();
00791 }
00792
00793 void KMFilterListBox::insertFilter( KMFilter* aFilter )
00794 {
00795
00796 assert( aFilter );
00797
00798
00799 mListBox->insertItem( aFilter->pattern()->name(), mIdxSelItem );
00800 if ( mIdxSelItem < 0 ) {
00801
00802 mFilterList.append( aFilter );
00803 mListBox->setSelected( mListBox->count() - 1, TRUE );
00804
00805 } else {
00806
00807 mFilterList.insert( mIdxSelItem, aFilter );
00808 mListBox->setSelected( mIdxSelItem, TRUE );
00809
00810 }
00811
00812 }
00813
00814 void KMFilterListBox::swapNeighbouringFilters( int untouchedOne, int movedOne )
00815 {
00816
00817 assert( untouchedOne - movedOne == 1 || movedOne - untouchedOne == 1 );
00818
00819
00820
00821 QListBoxItem *item = mListBox->item( movedOne );
00822 mListBox->takeItem( item );
00823
00824
00825 mListBox->insertItem( item, untouchedOne );
00826
00827 KMFilter* filter = mFilterList.take( movedOne );
00828 mFilterList.insert( untouchedOne, filter );
00829
00830 mIdxSelItem += movedOne - untouchedOne;
00831 }
00832
00833
00834
00835
00836
00837
00838
00839
00840 KMFilterActionWidget::KMFilterActionWidget( QWidget *parent, const char* name )
00841 : QHBox( parent, name )
00842 {
00843 int i;
00844 mActionList.setAutoDelete(TRUE);
00845
00846 mComboBox = new QComboBox( FALSE, this );
00847 assert( mComboBox );
00848 mWidgetStack = new QWidgetStack(this);
00849 assert( mWidgetStack );
00850
00851 setSpacing( 4 );
00852
00853 QPtrListIterator<KMFilterActionDesc> it ( kmkernel->filterActionDict()->list() );
00854 for ( i=0, it.toFirst() ; it.current() ; ++it, ++i ) {
00855
00856 KMFilterAction *a = (*it)->create();
00857
00858 mActionList.append( a );
00859
00860 mWidgetStack->addWidget( a->createParamWidget( mWidgetStack ), i );
00861
00862 mComboBox->insertItem( (*it)->label );
00863 }
00864
00865 mWidgetStack->addWidget( new QLabel( i18n("Please select an action."), mWidgetStack ), i );
00866 mWidgetStack->raiseWidget(i);
00867 mComboBox->insertItem( " " );
00868 mComboBox->setCurrentItem(i);
00869
00870
00871 mComboBox->setSizeLimit( mComboBox->count() );
00872
00873
00874
00875
00876 mComboBox->adjustSize();
00877 mComboBox->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
00878 setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
00879 updateGeometry();
00880
00881
00882 setFocusProxy( mComboBox );
00883
00884
00885 connect( mComboBox, SIGNAL(activated(int)),
00886 mWidgetStack, SLOT(raiseWidget(int)) );
00887 }
00888
00889 void KMFilterActionWidget::setAction( const KMFilterAction* aAction )
00890 {
00891 int i=0;
00892 bool found = FALSE;
00893 int count = mComboBox->count() - 1 ;
00894 QString label = ( aAction ) ? aAction->label() : QString::null ;
00895
00896
00897
00898 for ( ; i < count ; i++ )
00899 if ( aAction && mComboBox->text(i) == label ) {
00900
00901
00902 aAction->setParamWidgetValue( mWidgetStack->widget(i) );
00903
00904
00905 mComboBox->setCurrentItem(i);
00906 mWidgetStack->raiseWidget(i);
00907 found = TRUE;
00908 } else
00909 mActionList.at(i)->clearParamWidget( mWidgetStack->widget(i) );
00910 if ( found ) return;
00911
00912
00913 mComboBox->setCurrentItem( count );
00914 mWidgetStack->raiseWidget( count) ;
00915 }
00916
00917 KMFilterAction * KMFilterActionWidget::action()
00918 {
00919
00920
00921 KMFilterActionDesc *desc = (*kmkernel->filterActionDict())[ mComboBox->currentText() ];
00922 if ( desc ) {
00923
00924 KMFilterAction *fa = desc->create();
00925 if ( fa ) {
00926
00927 fa->applyParamWidgetValue( mWidgetStack->visibleWidget() );
00928 return fa;
00929 }
00930 }
00931
00932 return 0;
00933 }
00934
00935
00936
00937
00938
00939
00940
00941 KMFilterActionWidgetLister::KMFilterActionWidgetLister( QWidget *parent, const char* name )
00942 : KWidgetLister( 1, FILTER_MAX_ACTIONS, parent, name )
00943 {
00944 mActionList = 0;
00945 }
00946
00947 KMFilterActionWidgetLister::~KMFilterActionWidgetLister()
00948 {
00949 }
00950
00951 void KMFilterActionWidgetLister::setActionList( QPtrList<KMFilterAction> *aList )
00952 {
00953 assert ( aList );
00954
00955 if ( mActionList )
00956 regenerateActionListFromWidgets();
00957
00958 mActionList = aList;
00959
00960 ((QWidget*)parent())->setEnabled( TRUE );
00961
00962 if ( aList->count() == 0 ) {
00963 slotClear();
00964 return;
00965 }
00966
00967 int superfluousItems = (int)mActionList->count() - mMaxWidgets ;
00968 if ( superfluousItems > 0 ) {
00969 kdDebug(5006) << "KMFilterActionWidgetLister: Clipping action list to "
00970 << mMaxWidgets << " items!" << endl;
00971
00972 for ( ; superfluousItems ; superfluousItems-- )
00973 mActionList->removeLast();
00974 }
00975
00976
00977 setNumberOfShownWidgetsTo( mActionList->count() );
00978
00979
00980 QPtrListIterator<KMFilterAction> aIt( *mActionList );
00981 QPtrListIterator<QWidget> wIt( mWidgetList );
00982 for ( aIt.toFirst(), wIt.toFirst() ;
00983 aIt.current() && wIt.current() ; ++aIt, ++wIt )
00984 ((KMFilterActionWidget*)(*wIt))->setAction( (*aIt) );
00985 }
00986
00987 void KMFilterActionWidgetLister::reset()
00988 {
00989 if ( mActionList )
00990 regenerateActionListFromWidgets();
00991
00992 mActionList = 0;
00993 slotClear();
00994 ((QWidget*)parent())->setEnabled( FALSE );
00995 }
00996
00997 QWidget* KMFilterActionWidgetLister::createWidget( QWidget *parent )
00998 {
00999 return new KMFilterActionWidget(parent);
01000 }
01001
01002 void KMFilterActionWidgetLister::clearWidget( QWidget *aWidget )
01003 {
01004 if ( aWidget )
01005 ((KMFilterActionWidget*)aWidget)->setAction(0);
01006 }
01007
01008 void KMFilterActionWidgetLister::regenerateActionListFromWidgets()
01009 {
01010 if ( !mActionList ) return;
01011
01012 mActionList->clear();
01013
01014 QPtrListIterator<QWidget> it( mWidgetList );
01015 for ( it.toFirst() ; it.current() ; ++it ) {
01016 KMFilterAction *a = ((KMFilterActionWidget*)(*it))->action();
01017 if ( a )
01018 mActionList->append( a );
01019 }
01020
01021 }
01022
01023
01024
01025
01026
01027
01028
01029 KMPopFilterActionWidget::KMPopFilterActionWidget( const QString& title, QWidget *parent, const char* name )
01030 : QVButtonGroup( title, parent, name )
01031 {
01032 mActionMap[Down] = new QRadioButton( i18n("&Download mail"), this );
01033 mActionMap[Later] = new QRadioButton( i18n("Download mail la&ter"), this );
01034 mActionMap[Delete] = new QRadioButton( i18n("D&elete mail from server"), this );
01035 mIdMap[id(mActionMap[Later])] = Later;
01036 mIdMap[id(mActionMap[Down])] = Down;
01037 mIdMap[id(mActionMap[Delete])] = Delete;
01038
01039 connect( this, SIGNAL(clicked(int)),
01040 this, SLOT( slotActionClicked(int)) );
01041 }
01042
01043 void KMPopFilterActionWidget::setAction( KMPopFilterAction aAction )
01044 {
01045 if( aAction == NoAction)
01046 {
01047 aAction = Later;
01048 }
01049
01050 mAction = aAction;
01051
01052 blockSignals( true );
01053 if(!mActionMap[aAction]->isChecked())
01054 {
01055 mActionMap[aAction]->setChecked(true);
01056 }
01057 blockSignals( false );
01058
01059 setEnabled(true);
01060 }
01061
01062 KMPopFilterAction KMPopFilterActionWidget::action()
01063 {
01064 return mAction;
01065 }
01066
01067 void KMPopFilterActionWidget::slotActionClicked(int aId)
01068 {
01069 emit actionChanged(mIdMap[aId]);
01070 setAction(mIdMap[aId]);
01071 }
01072
01073 void KMPopFilterActionWidget::reset()
01074 {
01075 blockSignals(TRUE);
01076 mActionMap[Down]->setChecked( TRUE );
01077 blockSignals(FALSE);
01078
01079 setEnabled( FALSE );
01080 }
01081
01082 #include "kmfilterdlg.moc"