kmail

kmfilterdlg.cpp

00001 // -*- mode: C++; c-file-style: "gnu" -*-
00002 // kmfilterdlg.cpp
00003 // Author: Marc Mutz <Marc@Mutz.com>
00004 // based on work by Stefan Taferner <taferner@kde.org>
00005 // This code is under the GPL
00006 
00007 #include <config.h>
00008 #include "kmfilterdlg.h"
00009 
00010 // other KMail headers:
00011 #include "kmsearchpatternedit.h"
00012 #include "kmfiltermgr.h"
00013 #include "kmmainwidget.h"
00014 #include "accountmanager.h"
00015 using KMail::AccountManager;
00016 
00017 // other KDE headers:
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 #include <kkeybutton.h>
00028 #include <klistview.h>
00029 #include <kpushbutton.h>
00030 
00031 // other Qt headers:
00032 #include <qlayout.h>
00033 #include <qlabel.h>
00034 #include <qcombobox.h>
00035 #include <qwidgetstack.h>
00036 #include <qtooltip.h>
00037 #include <qwhatsthis.h>
00038 #include <qcheckbox.h>
00039 #include <qhbox.h>
00040 #include <qvalidator.h>
00041 #include <qtabwidget.h>
00042 
00043 // other headers:
00044 #include <assert.h>
00045 
00046 
00047 // What's this help texts
00048 const char * _wt_filterlist =
00049 I18N_NOOP( "<qt><p>This is the list of defined filters. "
00050        "They are processed top-to-bottom.</p>"
00051        "<p>Click on any filter to edit it "
00052        "using the controls in the right-hand half "
00053        "of the dialog.</p></qt>" );
00054 const char * _wt_filterlist_new =
00055 I18N_NOOP( "<qt><p>Click this button to create a new filter.</p>"
00056        "<p>The filter will be inserted just before the currently-"
00057        "selected one, but you can always change that "
00058        "later on.</p>"
00059        "<p>If you have clicked this button accidentally, you can undo this "
00060        "by clicking on the <em>Delete</em> button.</p></qt>" );
00061 const char * _wt_filterlist_copy =
00062 I18N_NOOP( "<qt><p>Click this button to copy a filter.</p>"
00063        "<p>If you have clicked this button accidentally, you can undo this "
00064        "by clicking on the <em>Delete</em> button.</p></qt>" );
00065 const char * _wt_filterlist_delete =
00066 I18N_NOOP( "<qt><p>Click this button to <em>delete</em> the currently-"
00067        "selected filter from the list above.</p>"
00068        "<p>There is no way to get the filter back once "
00069        "it is deleted, but you can always leave the "
00070        "dialog by clicking <em>Cancel</em> to discard the "
00071        "changes made.</p></qt>" );
00072 const char * _wt_filterlist_up =
00073 I18N_NOOP( "<qt><p>Click this button to move the currently-"
00074        "selected filter <em>up</em> one in the list above.</p>"
00075        "<p>This is useful since the order of the filters in the list "
00076        "determines the order in which they are tried on messages: "
00077        "The topmost filter gets tried first.</p>"
00078        "<p>If you have clicked this button accidentally, you can undo this "
00079        "by clicking on the <em>Down</em> button.</p></qt>" );
00080 const char * _wt_filterlist_down =
00081 I18N_NOOP( "<qt><p>Click this button to move the currently-"
00082        "selected filter <em>down</em> one in the list above.</p>"
00083        "<p>This is useful since the order of the filters in the list "
00084        "determines the order in which they are tried on messages: "
00085        "The topmost filter gets tried first.</p>"
00086        "<p>If you have clicked this button accidentally, you can undo this "
00087        "by clicking on the <em>Up</em> button.</p></qt>" );
00088 const char * _wt_filterlist_rename =
00089 I18N_NOOP( "<qt><p>Click this button to rename the currently-selected filter.</p>"
00090        "<p>Filters are named automatically, as long as they start with "
00091        "\"&lt;\".</p>"
00092        "<p>If you have renamed a filter accidentally and want automatic "
00093        "naming back, click this button and select <em>Clear</em> followed "
00094        "by <em>OK</em> in the appearing dialog.</p></qt>" );
00095 const char * _wt_filterdlg_showLater =
00096 I18N_NOOP( "<qt><p>Check this button to force the confirmation dialog to be "
00097        "displayed.</p><p>This is useful if you have defined a ruleset that tags "
00098            "messages to be downloaded later. Without the possibility to force "
00099            "the dialog popup, these messages could never be downloaded if no "
00100            "other large messages were waiting on the server, or if you wanted to "
00101            "change the ruleset to tag the messages differently.</p></qt>" );
00102 
00103 // The anchor of the filter dialog's help.
00104 const char * KMFilterDlgHelpAnchor =  "filters-id" ;
00105 const char * KMPopFilterDlgHelpAnchor =  "popfilters-id" ;
00106 
00107 //=============================================================================
00108 //
00109 // class KMFilterDlg (the filter dialog)
00110 //
00111 //=============================================================================
00112 
00113 KMFilterDlg::KMFilterDlg(QWidget* parent, const char* name, bool popFilter, bool createDummyFilter )
00114   : KDialogBase( parent, name, FALSE /* modality */,
00115          (popFilter)? i18n("POP3 Filter Rules"): i18n("Filter Rules") /* caption*/,
00116          Help|Ok|Apply|Cancel /* button mask */,
00117          Ok /* default btn */, FALSE /* separator */),
00118   bPopFilter(popFilter)
00119 {
00120   KWin::setIcons( winId(), kapp->icon(), kapp->miniIcon() );
00121   setHelp( (bPopFilter)? KMPopFilterDlgHelpAnchor: KMFilterDlgHelpAnchor );
00122 
00123   QWidget *w = new QWidget( this );
00124   setMainWidget( w );
00125   QHBoxLayout *topLayout = new QHBoxLayout( w, 0, spacingHint(), "topLayout" );
00126   QHBoxLayout *hbl = topLayout;
00127   QVBoxLayout *vbl2 = 0;
00128   QWidget *page1 = 0;
00129   QWidget *page2 = 0;
00130 
00131   mFilterList = new KMFilterListBox( i18n("Available Filters"), w, 0, bPopFilter);
00132   topLayout->addWidget( mFilterList, 1 /*stretch*/ );
00133 
00134   if(!bPopFilter) {
00135     QTabWidget *tabWidget = new QTabWidget( w, "kmfd_tab" );
00136     tabWidget->setMargin( KDialog::marginHint() );
00137     topLayout->addWidget( tabWidget );
00138 
00139     page1 = new QWidget( tabWidget );
00140     tabWidget->addTab( page1, i18n("&General") );
00141     hbl = new QHBoxLayout( page1, 0, spacingHint(), "kmfd_hbl" );
00142 
00143     page2 = new QWidget( tabWidget );
00144     tabWidget->addTab( page2, i18n("A&dvanced") );
00145     vbl2 = new QVBoxLayout( page2, 0, spacingHint(), "kmfd_vbl2" );
00146   }
00147 
00148   QVBoxLayout *vbl = new QVBoxLayout( hbl, spacingHint(), "kmfd_vbl" );
00149   hbl->setStretchFactor( vbl, 2 );
00150 
00151   mPatternEdit = new KMSearchPatternEdit( i18n("Filter Criteria"), bPopFilter ? w : page1 , "spe", bPopFilter);
00152   vbl->addWidget( mPatternEdit, 0, Qt::AlignTop );
00153 
00154   if(bPopFilter){
00155     mActionGroup = new KMPopFilterActionWidget( i18n("Filter Action"), w );
00156     vbl->addWidget( mActionGroup, 0, Qt::AlignTop );
00157 
00158     mGlobalsBox = new QVGroupBox(i18n("Global Options"), w);
00159     mShowLaterBtn = new QCheckBox(i18n("Always &show matched 'Download Later' messages in confirmation dialog"), mGlobalsBox);
00160     QWhatsThis::add( mShowLaterBtn, i18n(_wt_filterdlg_showLater) );
00161     vbl->addWidget( mGlobalsBox, 0, Qt::AlignTop );
00162   }
00163   else {
00164     QGroupBox *agb = new QGroupBox( 1 /*column*/, Vertical, i18n("Filter Actions"), page1 );
00165     mActionLister = new KMFilterActionWidgetLister( agb );
00166     vbl->addWidget( agb, 0, Qt::AlignTop );
00167 
00168     mAdvOptsGroup = new QGroupBox ( 1 /*columns*/, Vertical,
00169                     i18n("Advanced Options"), page2);
00170     {
00171       QWidget *adv_w = new QWidget( mAdvOptsGroup );
00172       QGridLayout *gl = new QGridLayout( adv_w, 8 /*rows*/, 3 /*cols*/,
00173                              0 /*border*/, spacingHint() );
00174 
00175       QVBoxLayout *vbl3 = new QVBoxLayout( gl, spacingHint(), "vbl3" );
00176       vbl3->addStretch( 1 );
00177       mApplyOnIn = new QCheckBox( i18n("Apply this filter to incoming messages:"), adv_w );
00178       vbl3->addWidget( mApplyOnIn );
00179       QButtonGroup *bg = new QButtonGroup( 0, "bg" );
00180       bg->setExclusive( true );
00181       mApplyOnForAll = new QRadioButton( i18n("from all accounts"), adv_w );
00182       bg->insert( mApplyOnForAll );
00183       vbl3->addWidget( mApplyOnForAll );
00184       mApplyOnForTraditional = new QRadioButton( i18n("from all but online IMAP accounts"), adv_w );
00185       bg->insert( mApplyOnForTraditional );
00186       vbl3->addWidget( mApplyOnForTraditional );
00187       mApplyOnForChecked = new QRadioButton( i18n("from checked accounts only"), adv_w );
00188       bg->insert( mApplyOnForChecked );
00189       vbl3->addWidget( mApplyOnForChecked );
00190       vbl3->addStretch( 2 );
00191 
00192       mAccountList = new KListView( adv_w, "accountList" );
00193       mAccountList->addColumn( i18n("Account Name") );
00194       mAccountList->addColumn( i18n("Type") );
00195       mAccountList->setAllColumnsShowFocus( true );
00196       mAccountList->setFrameStyle( QFrame::WinPanel + QFrame::Sunken );
00197       mAccountList->setSorting( -1 );
00198       gl->addMultiCellWidget( mAccountList, 0, 3, 1, 3 );
00199 
00200       mApplyOnOut = new QCheckBox( i18n("Apply this filter to &sent messages"), adv_w );
00201       gl->addMultiCellWidget( mApplyOnOut, 4, 4, 0, 3 );
00202 
00203       mApplyOnCtrlJ = new QCheckBox( i18n("Apply this filter on manual &filtering"), adv_w );
00204       gl->addMultiCellWidget( mApplyOnCtrlJ, 5, 5, 0, 3 );
00205 
00206       mStopProcessingHere = new QCheckBox( i18n("If this filter &matches, stop processing here"), adv_w );
00207       gl->addMultiCellWidget( mStopProcessingHere,
00208                   6, 6, /*from to row*/
00209                   0, 3 /*from to col*/ );
00210       mConfigureShortcut = new QCheckBox( i18n("Add this filter to the Apply Filter menu"), adv_w );
00211       gl->addMultiCellWidget( mConfigureShortcut, 7, 7, 0, 1 );
00212       QLabel *keyButtonLabel = new QLabel( i18n( "Shortcut:" ), adv_w );
00213       keyButtonLabel->setAlignment( AlignVCenter | AlignRight );
00214       gl->addMultiCellWidget( keyButtonLabel, 7, 7, 2, 2 );
00215       mKeyButton = new KKeyButton( adv_w, "FilterShortcutSelector" );
00216       gl->addMultiCellWidget( mKeyButton, 7, 7, 3, 3 );
00217       mConfigureToolbar = new QCheckBox( i18n("Additionally add this filter to the toolbar"), adv_w );
00218       gl->addMultiCellWidget( mConfigureToolbar, 8, 8, 0, 3 );
00219       mConfigureToolbar->setEnabled( false );
00220 
00221       QHBox *hbox = new QHBox( adv_w );
00222       mFilterActionLabel = new QLabel( i18n( "Icon for this filter:" ),
00223                                        hbox );
00224       mFilterActionLabel->setEnabled( false );
00225 
00226       mFilterActionIconButton = new KIconButton( hbox );
00227       mFilterActionLabel->setBuddy( mFilterActionIconButton );
00228       mFilterActionIconButton->setIconType( KIcon::NoGroup, KIcon::Any, true );
00229       mFilterActionIconButton->setIconSize( 16 );
00230       mFilterActionIconButton->setIcon( "gear" );
00231       mFilterActionIconButton->setEnabled( false );
00232 
00233       gl->addMultiCellWidget( hbox, 9, 9, 0, 3 );
00234     }
00235     vbl2->addWidget( mAdvOptsGroup, 0, Qt::AlignTop );
00236   }
00237   // spacer:
00238   vbl->addStretch( 1 );
00239 
00240   // load the filter parts into the edit widgets
00241   connect( mFilterList, SIGNAL(filterSelected(KMFilter*)),
00242        this, SLOT(slotFilterSelected(KMFilter*)) );
00243 
00244   if (bPopFilter){
00245     // set the state of the global setting 'show later msgs'
00246     connect( mShowLaterBtn, SIGNAL(toggled(bool)),
00247              mFilterList, SLOT(slotShowLaterToggled(bool)));
00248 
00249     // set the action in the filter when changed
00250     connect( mActionGroup, SIGNAL(actionChanged(const KMPopFilterAction)),
00251          this, SLOT(slotActionChanged(const KMPopFilterAction)) );
00252   } else {
00253     // transfer changes from the 'Apply this filter on...'
00254     // combo box to the filter
00255     connect( mApplyOnIn, SIGNAL(clicked()),
00256          this, SLOT(slotApplicabilityChanged()) );
00257     connect( mApplyOnForAll, SIGNAL(clicked()),
00258          this, SLOT(slotApplicabilityChanged()) );
00259     connect( mApplyOnForTraditional, SIGNAL(clicked()),
00260          this, SLOT(slotApplicabilityChanged()) );
00261     connect( mApplyOnForChecked, SIGNAL(clicked()),
00262          this, SLOT(slotApplicabilityChanged()) );
00263     connect( mApplyOnOut, SIGNAL(clicked()),
00264          this, SLOT(slotApplicabilityChanged()) );
00265     connect( mApplyOnCtrlJ, SIGNAL(clicked()),
00266          this, SLOT(slotApplicabilityChanged()) );
00267     connect( mAccountList, SIGNAL(clicked(QListViewItem*)),
00268          this, SLOT(slotApplicableAccountsChanged()) );
00269     connect( mAccountList, SIGNAL(spacePressed(QListViewItem*)),
00270          this, SLOT(slotApplicableAccountsChanged()) );
00271     
00272     // transfer changes from the 'stop processing here'
00273     // check box to the filter
00274     connect( mStopProcessingHere, SIGNAL(toggled(bool)),
00275          this, SLOT(slotStopProcessingButtonToggled(bool)) );
00276 
00277     connect( mConfigureShortcut, SIGNAL(toggled(bool)),
00278          this, SLOT(slotConfigureShortcutButtonToggled(bool)) );
00279 
00280     connect( mKeyButton, SIGNAL( capturedShortcut( const KShortcut& ) ),
00281              this, SLOT( slotCapturedShortcutChanged( const KShortcut& ) ) );
00282 
00283     connect( mConfigureToolbar, SIGNAL(toggled(bool)),
00284          this, SLOT(slotConfigureToolbarButtonToggled(bool)) );
00285 
00286     connect( mFilterActionIconButton, SIGNAL( iconChanged( QString ) ),
00287              this, SLOT( slotFilterActionIconChanged( QString ) ) );
00288   }
00289 
00290   // reset all widgets here
00291   connect( mFilterList, SIGNAL(resetWidgets()),
00292        this, SLOT(slotReset()) );
00293 
00294   connect( mFilterList, SIGNAL( applyWidgets() ),
00295            this, SLOT( slotUpdateFilter() ) );
00296 
00297   // support auto-naming the filter
00298   connect( mPatternEdit, SIGNAL(maybeNameChanged()),
00299        mFilterList, SLOT(slotUpdateFilterName()) );
00300 
00301   // apply changes on 'Apply'
00302   connect( this, SIGNAL(applyClicked()),
00303        mFilterList, SLOT(slotApplyFilterChanges()) );
00304 
00305   // apply changes on 'OK'
00306   connect( this, SIGNAL(okClicked()),
00307        mFilterList, SLOT(slotApplyFilterChanges()) );
00308 
00309   // save dialog size on 'OK'
00310   connect( this, SIGNAL(okClicked()),
00311        this, SLOT(slotSaveSize()) );
00312 
00313   // destruct the dialog on OK, close and Cancel
00314   connect( this, SIGNAL(finished()),
00315        this, SLOT(slotFinished()) );
00316 
00317   KConfigGroup geometry( KMKernel::config(), "Geometry");
00318   const char * configKey
00319     = bPopFilter ? "popFilterDialogSize" : "filterDialogSize";
00320   if ( geometry.hasKey( configKey ) )
00321     resize( geometry.readSizeEntry( configKey ) );
00322   else
00323     adjustSize();
00324 
00325   // load the filter list (emits filterSelected())
00326   mFilterList->loadFilterList( createDummyFilter );
00327 }
00328 
00329 void KMFilterDlg::slotFinished() {
00330     delayedDestruct();
00331 }
00332 
00333 void KMFilterDlg::slotSaveSize() {
00334   KConfigGroup geometry( KMKernel::config(), "Geometry" );
00335   geometry.writeEntry( bPopFilter ? "popFilterDialogSize" : "filterDialogSize", size() );
00336 }
00337 
00339 void KMFilterDlg::slotActionChanged(const KMPopFilterAction aAction)
00340 {
00341   mFilter->setAction(aAction);
00342 }
00343 
00344 void KMFilterDlg::slotFilterSelected( KMFilter* aFilter )
00345 {
00346   assert( aFilter );
00347 
00348   if (bPopFilter){
00349     mActionGroup->setAction( aFilter->action() );
00350     mGlobalsBox->setEnabled(true);
00351     mShowLaterBtn->setChecked(mFilterList->showLaterMsgs());
00352   } else {
00353     mActionLister->setActionList( aFilter->actions() );
00354 
00355     mAdvOptsGroup->setEnabled( true );
00356   }
00357 
00358   mPatternEdit->setSearchPattern( aFilter->pattern() );
00359   mFilter = aFilter;
00360 
00361   if (!bPopFilter) {
00362     kdDebug(5006) << "apply on inbound == "
00363           << aFilter->applyOnInbound() << endl;
00364     kdDebug(5006) << "apply on outbound == "
00365           << aFilter->applyOnOutbound() << endl;
00366     kdDebug(5006) << "apply on explicit == "
00367           << aFilter->applyOnExplicit() << endl;
00368 
00369     // NOTE: setting these values activates the slot that sets them in
00370     // the filter! So make sure we have the correct values _before_ we
00371     // set the first one:
00372     const bool applyOnIn = aFilter->applyOnInbound();
00373     const bool applyOnForAll = aFilter->applicability() == KMFilter::All;
00374     const bool applyOnTraditional = aFilter->applicability() == KMFilter::ButImap;
00375     const bool applyOnOut = aFilter->applyOnOutbound();
00376     const bool applyOnExplicit = aFilter->applyOnExplicit();
00377     const bool stopHere = aFilter->stopProcessingHere();
00378     const bool configureShortcut = aFilter->configureShortcut();
00379     const bool configureToolbar = aFilter->configureToolbar();
00380     const QString icon = aFilter->icon();
00381     const KShortcut shortcut( aFilter->shortcut() );
00382 
00383     mApplyOnIn->setChecked( applyOnIn );
00384     mApplyOnForAll->setEnabled( applyOnIn );
00385     mApplyOnForTraditional->setEnabled( applyOnIn );
00386     mApplyOnForChecked->setEnabled( applyOnIn );
00387     mApplyOnForAll->setChecked( applyOnForAll );
00388     mApplyOnForTraditional->setChecked( applyOnTraditional );
00389     mApplyOnForChecked->setChecked( !applyOnForAll && !applyOnTraditional );
00390     mAccountList->setEnabled( mApplyOnForChecked->isEnabled() && mApplyOnForChecked->isChecked() );
00391     slotUpdateAccountList();
00392     mApplyOnOut->setChecked( applyOnOut );
00393     mApplyOnCtrlJ->setChecked( applyOnExplicit );
00394     mStopProcessingHere->setChecked( stopHere );
00395     mConfigureShortcut->setChecked( configureShortcut );
00396     mKeyButton->setShortcut( shortcut, false );
00397     mConfigureToolbar->setChecked( configureToolbar );
00398     mFilterActionIconButton->setIcon( icon );
00399   }
00400 }
00401 
00402 void KMFilterDlg::slotReset()
00403 {
00404   mFilter = 0;
00405   mPatternEdit->reset();
00406 
00407   if(bPopFilter) {
00408     mActionGroup->reset();
00409     mGlobalsBox->setEnabled( false );
00410   } else {
00411     mActionLister->reset();
00412     mAdvOptsGroup->setEnabled( false );
00413     slotUpdateAccountList();
00414   }
00415 }
00416 
00417 void KMFilterDlg::slotUpdateFilter()
00418 {
00419   mPatternEdit->updateSearchPattern();
00420   if ( !bPopFilter ) {
00421     mActionLister->updateActionList();
00422   }
00423 }
00424 
00425 void KMFilterDlg::slotApplicabilityChanged()
00426 {
00427   if ( mFilter ) {
00428     mFilter->setApplyOnInbound( mApplyOnIn->isChecked() );
00429     mFilter->setApplyOnOutbound( mApplyOnOut->isChecked() );
00430     mFilter->setApplyOnExplicit( mApplyOnCtrlJ->isChecked() );
00431     if ( mApplyOnForAll->isChecked() )
00432       mFilter->setApplicability( KMFilter::All );
00433     else if ( mApplyOnForTraditional->isChecked() )
00434       mFilter->setApplicability( KMFilter::ButImap );
00435     else if ( mApplyOnForChecked->isChecked() )
00436       mFilter->setApplicability( KMFilter::Checked );
00437       
00438     mApplyOnForAll->setEnabled( mApplyOnIn->isChecked() );
00439     mApplyOnForTraditional->setEnabled(  mApplyOnIn->isChecked() );
00440     mApplyOnForChecked->setEnabled( mApplyOnIn->isChecked() );
00441     mAccountList->setEnabled( mApplyOnForChecked->isEnabled() && mApplyOnForChecked->isChecked() );
00442 
00443     // Advanced tab functionality - Update list of accounts this filter applies to
00444     QListViewItemIterator it( mAccountList );
00445     while ( it.current() ) {
00446       QCheckListItem *item = dynamic_cast<QCheckListItem*>( it.current() );
00447       if (item) {
00448     int id = item->text( 2 ).toInt();
00449       item->setOn( mFilter->applyOnAccount( id ) );
00450       }
00451       ++it;
00452     }
00453 
00454     kdDebug(5006) << "KMFilterDlg: setting filter to be applied at "
00455                   << ( mFilter->applyOnInbound() ? "incoming " : "" )
00456                   << ( mFilter->applyOnOutbound() ? "outgoing " : "" )
00457                   << ( mFilter->applyOnExplicit() ? "explicit CTRL-J" : "" )
00458                   << endl;
00459   }
00460 }
00461 
00462 void KMFilterDlg::slotApplicableAccountsChanged()
00463 {
00464   if ( mFilter && mApplyOnForChecked->isEnabled() && mApplyOnForChecked->isChecked() ) {
00465     // Advanced tab functionality - Update list of accounts this filter applies to
00466     QListViewItemIterator it( mAccountList );
00467     while ( it.current() ) {
00468       QCheckListItem *item = dynamic_cast<QCheckListItem*>( it.current() );
00469       if (item) {
00470     int id = item->text( 2 ).toInt();
00471     mFilter->setApplyOnAccount( id, item->isOn() );
00472       }
00473       ++it;
00474     }
00475   }
00476 }
00477 
00478 void KMFilterDlg::slotStopProcessingButtonToggled( bool aChecked )
00479 {
00480   if ( mFilter )
00481     mFilter->setStopProcessingHere( aChecked );
00482 }
00483 
00484 void KMFilterDlg::slotConfigureShortcutButtonToggled( bool aChecked )
00485 {
00486   if ( mFilter ) {
00487     mFilter->setConfigureShortcut( aChecked );
00488     mConfigureToolbar->setEnabled( aChecked );
00489     mFilterActionIconButton->setEnabled( aChecked );
00490     mFilterActionLabel->setEnabled( aChecked );
00491   }
00492 }
00493 
00494 void KMFilterDlg::slotCapturedShortcutChanged( const KShortcut& sc )
00495 {
00496   KShortcut mySc(sc);
00497   if ( mySc == mKeyButton->shortcut() ) return;
00498   // FIXME work around a problem when reseting the shortcut via the shortcut dialog
00499   // somehow the returned shortcut does not evaluate to true in KShortcut::isNull(),
00500   // so we additionally have to check for an empty string
00501   if ( mySc.isNull() || mySc.toString().isEmpty() )
00502     mySc.clear();
00503   if ( !mySc.isNull() && !( kmkernel->getKMMainWidget()->shortcutIsValid( mySc ) ) ) {
00504     QString msg( i18n( "The selected shortcut is already used, "
00505           "please select a different one." ) );
00506     KMessageBox::sorry( this, msg );
00507   } else {
00508     mKeyButton->setShortcut( mySc, false );
00509     if ( mFilter )
00510       mFilter->setShortcut( mKeyButton->shortcut() );
00511   }
00512 }
00513 
00514 void KMFilterDlg::slotConfigureToolbarButtonToggled( bool aChecked )
00515 {
00516   if ( mFilter )
00517     mFilter->setConfigureToolbar( aChecked );
00518 }
00519 
00520 void KMFilterDlg::slotFilterActionIconChanged( QString icon )
00521 {
00522   if ( mFilter )
00523     mFilter->setIcon( icon );
00524 }
00525 
00526 void KMFilterDlg::slotUpdateAccountList()
00527 {
00528   mAccountList->clear();
00529   QListViewItem *top = 0;
00530   for( KMAccount *a = kmkernel->acctMgr()->first(); a!=0;
00531        a = kmkernel->acctMgr()->next() ) {
00532     QCheckListItem *listItem =
00533       new QCheckListItem( mAccountList, top, a->name(), QCheckListItem::CheckBox );
00534     listItem->setText( 1, a->type() );
00535     listItem->setText( 2, QString( "%1" ).arg( a->id() ) );
00536     if ( mFilter )
00537       listItem->setOn( mFilter->applyOnAccount( a->id() ) );
00538     top = listItem;
00539   }
00540 
00541   QListViewItem *listItem = mAccountList->firstChild();
00542   if ( listItem ) {
00543     mAccountList->setCurrentItem( listItem );
00544     mAccountList->setSelected( listItem, true );
00545   }
00546 }
00547 
00548 //=============================================================================
00549 //
00550 // class KMFilterListBox (the filter list manipulator)
00551 //
00552 //=============================================================================
00553 
00554 KMFilterListBox::KMFilterListBox( const QString & title, QWidget *parent, const char* name, bool popFilter )
00555   : QGroupBox( 1, Horizontal, title, parent, name ),
00556     bPopFilter(popFilter)
00557 {
00558   mFilterList.setAutoDelete(TRUE);
00559   mIdxSelItem = -1;
00560 
00561   //----------- the list box
00562   mListBox = new QListBox(this);
00563   mListBox->setMinimumWidth(150);
00564   QWhatsThis::add( mListBox, i18n(_wt_filterlist) );
00565 
00566   //----------- the first row of buttons
00567   QHBox *hb = new QHBox(this);
00568   hb->setSpacing(4);
00569   mBtnUp = new KPushButton( QString::null, hb );
00570   mBtnUp->setAutoRepeat( true );
00571   mBtnUp->setIconSet( BarIconSet( "up", KIcon::SizeSmall ) );
00572   mBtnUp->setMinimumSize( mBtnUp->sizeHint() * 1.2 );
00573   mBtnDown = new KPushButton( QString::null, hb );
00574   mBtnDown->setAutoRepeat( true );
00575   mBtnDown->setIconSet( BarIconSet( "down", KIcon::SizeSmall ) );
00576   mBtnDown->setMinimumSize( mBtnDown->sizeHint() * 1.2 );
00577   QToolTip::add( mBtnUp, i18n("Up") );
00578   QToolTip::add( mBtnDown, i18n("Down") );
00579   QWhatsThis::add( mBtnUp, i18n(_wt_filterlist_up) );
00580   QWhatsThis::add( mBtnDown, i18n(_wt_filterlist_down) );
00581 
00582   //----------- the second row of buttons
00583   hb = new QHBox(this);
00584   hb->setSpacing(4);
00585   mBtnNew = new QPushButton( QString::null, hb );
00586   mBtnNew->setPixmap( BarIcon( "filenew", KIcon::SizeSmall ) );
00587   mBtnNew->setMinimumSize( mBtnNew->sizeHint() * 1.2 );
00588   mBtnCopy = new QPushButton( QString::null, hb );
00589   mBtnCopy->setPixmap( BarIcon( "editcopy", KIcon::SizeSmall ) );
00590   mBtnCopy->setMinimumSize( mBtnCopy->sizeHint() * 1.2 );
00591   mBtnDelete = new QPushButton( QString::null, hb );
00592   mBtnDelete->setPixmap( BarIcon( "editdelete", KIcon::SizeSmall ) );
00593   mBtnDelete->setMinimumSize( mBtnDelete->sizeHint() * 1.2 );
00594   mBtnRename = new QPushButton( i18n("Rename..."), hb );
00595   QToolTip::add( mBtnNew, i18n("New") );
00596   QToolTip::add( mBtnCopy, i18n("Copy") );
00597   QToolTip::add( mBtnDelete, i18n("Delete"));
00598   QWhatsThis::add( mBtnNew, i18n(_wt_filterlist_new) );
00599   QWhatsThis::add( mBtnCopy, i18n(_wt_filterlist_copy) );
00600   QWhatsThis::add( mBtnDelete, i18n(_wt_filterlist_delete) );
00601   QWhatsThis::add( mBtnRename, i18n(_wt_filterlist_rename) );
00602 
00603 
00604   //----------- now connect everything
00605   connect( mListBox, SIGNAL(highlighted(int)),
00606        this, SLOT(slotSelected(int)) );
00607   connect( mListBox, SIGNAL( doubleClicked ( QListBoxItem * )),
00608            this, SLOT( slotRename()) );
00609   connect( mBtnUp, SIGNAL(clicked()),
00610        this, SLOT(slotUp()) );
00611   connect( mBtnDown, SIGNAL(clicked()),
00612        this, SLOT(slotDown()) );
00613   connect( mBtnNew, SIGNAL(clicked()),
00614        this, SLOT(slotNew()) );
00615   connect( mBtnCopy, SIGNAL(clicked()),
00616        this, SLOT(slotCopy()) );
00617   connect( mBtnDelete, SIGNAL(clicked()),
00618        this, SLOT(slotDelete()) );
00619   connect( mBtnRename, SIGNAL(clicked()),
00620        this, SLOT(slotRename()) );
00621 
00622   // the dialog should call loadFilterList()
00623   // when all signals are connected.
00624   enableControls();
00625 }
00626 
00627 
00628 void KMFilterListBox::createFilter( const QCString & field,
00629                     const QString & value )
00630 {
00631   KMSearchRule *newRule = KMSearchRule::createInstance( field, KMSearchRule::FuncContains, value );
00632 
00633   KMFilter *newFilter = new KMFilter(0, bPopFilter);
00634   newFilter->pattern()->append( newRule );
00635   newFilter->pattern()->setName( QString("<%1>:%2").arg( field ).arg( value) );
00636 
00637   KMFilterActionDesc *desc = (*kmkernel->filterActionDict())["transfer"];
00638   if ( desc )
00639     newFilter->actions()->append( desc->create() );
00640 
00641   insertFilter( newFilter );
00642   enableControls();
00643 }
00644 
00645 bool KMFilterListBox::showLaterMsgs()
00646 {
00647     return mShowLater;
00648 }
00649 
00650 void KMFilterListBox::slotUpdateFilterName()
00651 {
00652   KMSearchPattern *p = mFilterList.at(mIdxSelItem)->pattern();
00653   if ( !p ) return;
00654 
00655   QString shouldBeName = p->name();
00656   QString displayedName = mListBox->text( mIdxSelItem );
00657 
00658   if ( shouldBeName.stripWhiteSpace().isEmpty() ) {
00659     mFilterList.at(mIdxSelItem)->setAutoNaming( true );
00660   }
00661 
00662   if ( mFilterList.at(mIdxSelItem)->isAutoNaming() ) {
00663     // auto-naming of patterns
00664     if ( p->first() && !p->first()->field().stripWhiteSpace().isEmpty() )
00665       shouldBeName = QString( "<%1>: %2" ).arg( p->first()->field() ).arg( p->first()->contents() );
00666     else
00667       shouldBeName = "<" + i18n("unnamed") + ">";
00668     p->setName( shouldBeName );
00669   }
00670 
00671   if ( displayedName == shouldBeName ) return;
00672 
00673   mListBox->blockSignals(TRUE);
00674   mListBox->changeItem( shouldBeName, mIdxSelItem );
00675   mListBox->blockSignals(FALSE);
00676 }
00677 
00678 void KMFilterListBox::slotShowLaterToggled(bool aOn)
00679 {
00680   mShowLater = aOn;
00681 }
00682 
00683 void KMFilterListBox::slotApplyFilterChanges()
00684 {
00685   if ( mIdxSelItem >= 0 )
00686     slotSelected( mListBox->currentItem() );
00687 
00688   // by now all edit widgets should have written back
00689   // their widget's data into our filter list.
00690 
00691   KMFilterMgr *fm;
00692   if (bPopFilter)
00693     fm = kmkernel->popFilterMgr();
00694   else
00695     fm = kmkernel->filterMgr();
00696 
00697   QValueList<KMFilter*> newFilters;
00698   QStringList emptyFilters;
00699   QPtrListIterator<KMFilter> it( mFilterList );
00700   for ( it.toFirst() ; it.current() ; ++it ) {
00701     KMFilter *f = new KMFilter( **it ); // deep copy
00702     f->purify();
00703     if ( !f->isEmpty() )
00704       // the filter is valid:
00705       newFilters.append( f );
00706     else {
00707       // the filter is invalid:
00708       emptyFilters << f->name();
00709       delete f;
00710     }
00711   }
00712   if (bPopFilter)
00713     fm->setShowLaterMsgs(mShowLater);
00714 
00715   // block attemts to use filters (currently a no-op)
00716   fm->beginUpdate();
00717   fm->setFilters( newFilters );
00718   if (fm->atLeastOneOnlineImapFolderTarget()) {
00719     QString str = i18n("At least one filter targets a folder on an online "
00720                "IMAP account. Such filters will only be applied "
00721                "when manually filtering and when filtering "
00722                "incoming online IMAP mail.");
00723     KMessageBox::information( this, str, QString::null, 
00724                   "filterDlgOnlineImapCheck" );
00725   }
00726   // allow usage of the filters again.
00727   fm->endUpdate();
00728   fm->writeConfig();
00729 
00730   // report on invalid filters:
00731   if ( !emptyFilters.empty() ) {
00732     QString msg = i18n("The following filters have not been saved because they "
00733                "were invalid (e.g. containing no actions or no search "
00734                "rules).");
00735     KMessageBox::informationList( 0, msg, emptyFilters, QString::null,
00736                   "ShowInvalidFilterWarning" );
00737   }
00738 }
00739 
00740 void KMFilterListBox::slotSelected( int aIdx )
00741 {
00742   mIdxSelItem = aIdx;
00743   // QPtrList::at(i) will return 0 if i is out of range.
00744   KMFilter *f = mFilterList.at(aIdx);
00745   if ( f )
00746     emit filterSelected( f );
00747   else
00748     emit resetWidgets();
00749   enableControls();
00750 }
00751 
00752 void KMFilterListBox::slotNew()
00753 {
00754   // just insert a new filter.
00755   insertFilter( new KMFilter(0, bPopFilter) );
00756   enableControls();
00757 }
00758 
00759 void KMFilterListBox::slotCopy()
00760 {
00761   if ( mIdxSelItem < 0 ) {
00762     kdDebug(5006) << "KMFilterListBox::slotCopy called while no filter is selected, ignoring." << endl;
00763     return;
00764   }
00765 
00766   // make sure that all changes are written to the filter before we copy it
00767   emit applyWidgets();
00768 
00769   KMFilter *filter = mFilterList.at( mIdxSelItem );
00770 
00771   // enableControls should make sure this method is
00772   // never called when no filter is selected.
00773   assert( filter );
00774 
00775   // inserts a copy of the current filter.
00776   insertFilter( new KMFilter( *filter ) );
00777   enableControls();
00778 }
00779 
00780 void KMFilterListBox::slotDelete()
00781 {
00782   if ( mIdxSelItem < 0 ) {
00783     kdDebug(5006) << "KMFilterListBox::slotDelete called while no filter is selected, ignoring." << endl;
00784     return;
00785   }
00786 
00787   int oIdxSelItem = mIdxSelItem;
00788   mIdxSelItem = -1;
00789   // unselect all
00790   mListBox->selectAll(FALSE);
00791   // broadcast that all widgets let go
00792   // of the filter
00793   emit resetWidgets();
00794 
00795   // remove the filter from both the filter list...
00796   mFilterList.remove( oIdxSelItem );
00797   // and the listbox
00798   mListBox->removeItem( oIdxSelItem );
00799 
00800   int count = (int)mListBox->count();
00801   // and set the new current item.
00802   if ( count > oIdxSelItem )
00803     // oIdxItem is still a valid index
00804     mListBox->setSelected( oIdxSelItem, TRUE );
00805   else if ( count )
00806     // oIdxSelIdx is no longer valid, but the
00807     // list box isn't empty
00808     mListBox->setSelected( count - 1, TRUE );
00809   // the list is empty - keep index -1
00810 
00811   enableControls();
00812 }
00813 
00814 void KMFilterListBox::slotUp()
00815 {
00816   if ( mIdxSelItem < 0 ) {
00817     kdDebug(5006) << "KMFilterListBox::slotUp called while no filter is selected, ignoring." << endl;
00818     return;
00819   }
00820   if ( mIdxSelItem == 0 ) {
00821     kdDebug(5006) << "KMFilterListBox::slotUp called while the _topmost_ filter is selected, ignoring." << endl;
00822     return;
00823   }
00824 
00825   swapNeighbouringFilters( mIdxSelItem, mIdxSelItem - 1 );
00826   enableControls();
00827 }
00828 
00829 void KMFilterListBox::slotDown()
00830 {
00831   if ( mIdxSelItem < 0 ) {
00832     kdDebug(5006) << "KMFilterListBox::slotDown called while no filter is selected, ignoring." << endl;
00833     return;
00834   }
00835   if ( mIdxSelItem == (int)mListBox->count() - 1 ) {
00836     kdDebug(5006) << "KMFilterListBox::slotDown called while the _last_ filter is selected, ignoring." << endl;
00837     return;
00838   }
00839 
00840   swapNeighbouringFilters( mIdxSelItem, mIdxSelItem + 1);
00841   enableControls();
00842 }
00843 
00844 void KMFilterListBox::slotRename()
00845 {
00846   if ( mIdxSelItem < 0 ) {
00847     kdDebug(5006) << "KMFilterListBox::slotRename called while no filter is selected, ignoring." << endl;
00848     return;
00849   }
00850 
00851   bool okPressed = FALSE;
00852   KMFilter *filter = mFilterList.at( mIdxSelItem );
00853 
00854   // enableControls should make sure this method is
00855   // never called when no filter is selected.
00856   assert( filter );
00857 
00858   // allow empty names - those will turn auto-naming on again
00859   QValidator *validator = new QRegExpValidator( QRegExp( ".*" ), 0 );
00860   QString newName = KInputDialog::getText
00861     (
00862      i18n("Rename Filter"),
00863      i18n("Rename filter \"%1\" to:\n(leave the field empty for automatic naming)")
00864         .arg( filter->pattern()->name() ) /*label*/,
00865      filter->pattern()->name() /* initial value */,
00866      &okPressed, topLevelWidget(), 0, validator
00867      );
00868   delete validator;
00869 
00870   if ( !okPressed ) return;
00871 
00872   if ( newName.isEmpty() ) {
00873     // bait for slotUpdateFilterName to
00874     // use automatic naming again.
00875     filter->pattern()->setName( "<>" );
00876     filter->setAutoNaming( true );
00877   } else {
00878     filter->pattern()->setName( newName );
00879     filter->setAutoNaming( false );
00880   }
00881 
00882   slotUpdateFilterName();
00883 }
00884 
00885 void KMFilterListBox::enableControls()
00886 {
00887   bool theFirst = ( mIdxSelItem == 0 );
00888   bool theLast = ( mIdxSelItem >= (int)mFilterList.count() - 1 );
00889   bool aFilterIsSelected = ( mIdxSelItem >= 0 );
00890 
00891   mBtnUp->setEnabled( aFilterIsSelected && !theFirst );
00892   mBtnDown->setEnabled( aFilterIsSelected && !theLast );
00893   mBtnCopy->setEnabled( aFilterIsSelected );
00894   mBtnDelete->setEnabled( aFilterIsSelected );
00895   mBtnRename->setEnabled( aFilterIsSelected );
00896 
00897   if ( aFilterIsSelected )
00898     mListBox->ensureCurrentVisible();
00899 }
00900 
00901 void KMFilterListBox::loadFilterList( bool createDummyFilter )
00902 {
00903   assert(mListBox);
00904   setEnabled(FALSE);
00905   // we don't want the insertion to
00906   // cause flicker in the edit widgets.
00907   blockSignals(TRUE);
00908 
00909   // clear both lists
00910   mFilterList.clear();
00911   mListBox->clear();
00912 
00913   const KMFilterMgr *manager = 0;
00914   if(bPopFilter)
00915   {
00916     mShowLater = kmkernel->popFilterMgr()->showLaterMsgs();
00917     manager = kmkernel->popFilterMgr();
00918   }
00919   else
00920   {
00921     manager = kmkernel->filterMgr();
00922   }
00923   Q_ASSERT( manager );
00924 
00925   QValueListConstIterator<KMFilter*> it;
00926   for ( it = manager->filters().constBegin() ; it != manager->filters().constEnd() ; ++it ) {
00927     mFilterList.append( new KMFilter( **it ) ); // deep copy
00928     mListBox->insertItem( (*it)->pattern()->name() );
00929   }
00930 
00931   blockSignals(FALSE);
00932   setEnabled(TRUE);
00933 
00934   // create an empty filter when there's none, to avoid a completely
00935   // disabled dialog (usability tests indicated that the new-filter
00936   // button is too hard to find that way):
00937   if ( !mListBox->count() && createDummyFilter )
00938     slotNew();
00939 
00940   if ( mListBox->count() > 0 )
00941     mListBox->setSelected( 0, true );
00942 
00943   enableControls();
00944 }
00945 
00946 void KMFilterListBox::insertFilter( KMFilter* aFilter )
00947 {
00948   // must be really a filter...
00949   assert( aFilter );
00950 
00951   // if mIdxSelItem < 0, QListBox::insertItem will append.
00952   mListBox->insertItem( aFilter->pattern()->name(), mIdxSelItem );
00953   if ( mIdxSelItem < 0 ) {
00954     // none selected -> append
00955     mFilterList.append( aFilter );
00956     mListBox->setSelected( mListBox->count() - 1, TRUE );
00957     //    slotSelected( mListBox->count() - 1 );
00958   } else {
00959     // insert just before selected
00960     mFilterList.insert( mIdxSelItem, aFilter );
00961     mListBox->setSelected( mIdxSelItem, TRUE );
00962     //    slotSelected( mIdxSelItem );
00963   }
00964 
00965 }
00966 
00967 void KMFilterListBox::swapNeighbouringFilters( int untouchedOne, int movedOne )
00968 {
00969   // must be neighbours...
00970   assert( untouchedOne - movedOne == 1 || movedOne - untouchedOne == 1 );
00971 
00972   // untouchedOne is at idx. to move it down(up),
00973   // remove item at idx+(-)1 w/o deleting it.
00974   QListBoxItem *item = mListBox->item( movedOne );
00975   mListBox->takeItem( item );
00976   // now selected item is at idx(idx-1), so
00977   // insert the other item at idx, ie. above(below).
00978   mListBox->insertItem( item, untouchedOne );
00979 
00980   KMFilter* filter = mFilterList.take( movedOne );
00981   mFilterList.insert( untouchedOne, filter );
00982 
00983   mIdxSelItem += movedOne - untouchedOne;
00984 }
00985 
00986 
00987 //=============================================================================
00988 //
00989 // class KMFilterActionWidget
00990 //
00991 //=============================================================================
00992 
00993 KMFilterActionWidget::KMFilterActionWidget( QWidget *parent, const char* name )
00994   : QHBox( parent, name )
00995 {
00996   int i;
00997   mActionList.setAutoDelete(TRUE);
00998 
00999   mComboBox = new QComboBox( FALSE, this );
01000   assert( mComboBox );
01001   mWidgetStack = new QWidgetStack(this);
01002   assert( mWidgetStack );
01003 
01004   setSpacing( 4 );
01005 
01006   QPtrListIterator<KMFilterActionDesc> it ( kmkernel->filterActionDict()->list() );
01007   for ( i=0, it.toFirst() ; it.current() ; ++it, ++i ) {
01008     //create an instance:
01009     KMFilterAction *a = (*it)->create();
01010     // append to the list of actions:
01011     mActionList.append( a );
01012     // add parameter widget to widget stack:
01013     mWidgetStack->addWidget( a->createParamWidget( mWidgetStack ), i );
01014     // add (i18n-ized) name to combo box
01015     mComboBox->insertItem( (*it)->label );
01016   }
01017   // widget for the case where no action is selected.
01018   mWidgetStack->addWidget( new QLabel( i18n("Please select an action."), mWidgetStack ), i );
01019   mWidgetStack->raiseWidget(i);
01020   mComboBox->insertItem( " " );
01021   mComboBox->setCurrentItem(i);
01022 
01023   // don't show scroll bars.
01024   mComboBox->setSizeLimit( mComboBox->count() );
01025   // layout management:
01026   // o the combo box is not to be made larger than it's sizeHint(),
01027   //   the parameter widget should grow instead.
01028   // o the whole widget takes all space horizontally, but is fixed vertically.
01029   mComboBox->adjustSize();
01030   mComboBox->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
01031   setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
01032   updateGeometry();
01033 
01034   // redirect focus to the filter action combo box
01035   setFocusProxy( mComboBox );
01036 
01037   // now connect the combo box and the widget stack
01038   connect( mComboBox, SIGNAL(activated(int)),
01039        mWidgetStack, SLOT(raiseWidget(int)) );
01040 }
01041 
01042 void KMFilterActionWidget::setAction( const KMFilterAction* aAction )
01043 {
01044   int i=0;
01045   bool found = FALSE;
01046   int count = mComboBox->count() - 1 ; // last entry is the empty one
01047   QString label = ( aAction ) ? aAction->label() : QString::null ;
01048 
01049   // find the index of typeOf(aAction) in mComboBox
01050   // and clear the other widgets on the way.
01051   for ( ; i < count ; i++ )
01052     if ( aAction && mComboBox->text(i) == label ) {
01053       //...set the parameter widget to the settings
01054       // of aAction...
01055       aAction->setParamWidgetValue( mWidgetStack->widget(i) );
01056       //...and show the correct entry of
01057       // the combo box
01058       mComboBox->setCurrentItem(i); // (mm) also raise the widget, but doesn't
01059       mWidgetStack->raiseWidget(i);
01060       found = TRUE;
01061     } else // clear the parameter widget
01062       mActionList.at(i)->clearParamWidget( mWidgetStack->widget(i) );
01063   if ( found ) return;
01064 
01065   // not found, so set the empty widget
01066   mComboBox->setCurrentItem( count ); // last item
01067   mWidgetStack->raiseWidget( count) ;
01068 }
01069 
01070 KMFilterAction * KMFilterActionWidget::action()
01071 {
01072   // look up the action description via the label
01073   // returned by QComboBox::currentText()...
01074   KMFilterActionDesc *desc = (*kmkernel->filterActionDict())[ mComboBox->currentText() ];
01075   if ( desc ) {
01076     // ...create an instance...
01077     KMFilterAction *fa = desc->create();
01078     if ( fa ) {
01079       // ...and apply the setting of the parameter widget.
01080       fa->applyParamWidgetValue( mWidgetStack->visibleWidget() );
01081       return fa;
01082     }
01083   }
01084 
01085   return 0;
01086 }
01087 
01088 //=============================================================================
01089 //
01090 // class KMFilterActionWidgetLister (the filter action editor)
01091 //
01092 //=============================================================================
01093 
01094 KMFilterActionWidgetLister::KMFilterActionWidgetLister( QWidget *parent, const char* name )
01095   : KWidgetLister( 1, FILTER_MAX_ACTIONS, parent, name )
01096 {
01097   mActionList = 0;
01098 }
01099 
01100 KMFilterActionWidgetLister::~KMFilterActionWidgetLister()
01101 {
01102 }
01103 
01104 void KMFilterActionWidgetLister::setActionList( QPtrList<KMFilterAction> *aList )
01105 {
01106   assert ( aList );
01107 
01108   if ( mActionList )
01109     regenerateActionListFromWidgets();
01110 
01111   mActionList = aList;
01112 
01113   ((QWidget*)parent())->setEnabled( TRUE );
01114 
01115   if ( aList->count() == 0 ) {
01116     slotClear();
01117     return;
01118   }
01119 
01120   int superfluousItems = (int)mActionList->count() - mMaxWidgets ;
01121   if ( superfluousItems > 0 ) {
01122     kdDebug(5006) << "KMFilterActionWidgetLister: Clipping action list to "
01123           << mMaxWidgets << " items!" << endl;
01124 
01125     for ( ; superfluousItems ; superfluousItems-- )
01126       mActionList->removeLast();
01127   }
01128 
01129   // set the right number of widgets
01130   setNumberOfShownWidgetsTo( mActionList->count() );
01131 
01132   // load the actions into the widgets
01133   QPtrListIterator<KMFilterAction> aIt( *mActionList );
01134   QPtrListIterator<QWidget> wIt( mWidgetList );
01135   for ( aIt.toFirst(), wIt.toFirst() ;
01136     aIt.current() && wIt.current() ; ++aIt, ++wIt )
01137     ((KMFilterActionWidget*)(*wIt))->setAction( (*aIt) );
01138 }
01139 
01140 void KMFilterActionWidgetLister::reset()
01141 {
01142   if ( mActionList )
01143     regenerateActionListFromWidgets();
01144 
01145   mActionList = 0;
01146   slotClear();
01147   ((QWidget*)parent())->setEnabled( FALSE );
01148 }
01149 
01150 QWidget* KMFilterActionWidgetLister::createWidget( QWidget *parent )
01151 {
01152   return new KMFilterActionWidget(parent);
01153 }
01154 
01155 void KMFilterActionWidgetLister::clearWidget( QWidget *aWidget )
01156 {
01157   if ( aWidget )
01158     ((KMFilterActionWidget*)aWidget)->setAction(0);
01159 }
01160 
01161 void KMFilterActionWidgetLister::regenerateActionListFromWidgets()
01162 {
01163   if ( !mActionList ) return;
01164 
01165   mActionList->clear();
01166 
01167   QPtrListIterator<QWidget> it( mWidgetList );
01168   for ( it.toFirst() ; it.current() ; ++it ) {
01169     KMFilterAction *a = ((KMFilterActionWidget*)(*it))->action();
01170     if ( a )
01171       mActionList->append( a );
01172   }
01173 
01174 }
01175 
01176 //=============================================================================
01177 //
01178 // class KMPopFilterActionWidget
01179 //
01180 //=============================================================================
01181 
01182 KMPopFilterActionWidget::KMPopFilterActionWidget( const QString& title, QWidget *parent, const char* name )
01183   : QVButtonGroup( title, parent, name )
01184 {
01185   mActionMap[Down] = new QRadioButton( i18n("&Download mail"), this );
01186   mActionMap[Later] = new QRadioButton( i18n("Download mail la&ter"), this );
01187   mActionMap[Delete] = new QRadioButton( i18n("D&elete mail from server"), this );
01188   mIdMap[id(mActionMap[Later])] = Later;
01189   mIdMap[id(mActionMap[Down])] = Down;
01190   mIdMap[id(mActionMap[Delete])] = Delete;
01191 
01192   connect( this, SIGNAL(clicked(int)),
01193        this, SLOT( slotActionClicked(int)) );
01194 }
01195 
01196 void KMPopFilterActionWidget::setAction( KMPopFilterAction aAction )
01197 {
01198   if( aAction == NoAction)
01199   {
01200     aAction = Later;
01201   }
01202 
01203   mAction = aAction;
01204 
01205   blockSignals( true );
01206   if(!mActionMap[aAction]->isChecked())
01207   {
01208     mActionMap[aAction]->setChecked(true);
01209   }
01210   blockSignals( false );
01211 
01212   setEnabled(true);
01213 }
01214 
01215 KMPopFilterAction  KMPopFilterActionWidget::action()
01216 {
01217   return mAction;
01218 }
01219 
01220 void KMPopFilterActionWidget::slotActionClicked(int aId)
01221 {
01222   emit actionChanged(mIdMap[aId]);
01223   setAction(mIdMap[aId]);
01224 }
01225 
01226 void KMPopFilterActionWidget::reset()
01227 {
01228   blockSignals(TRUE);
01229   mActionMap[Down]->setChecked( TRUE );
01230   blockSignals(FALSE);
01231 
01232   setEnabled( FALSE );
01233 }
01234 
01235 #include "kmfilterdlg.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys