Backport r950340 | aacid | 2009-04-06 23:21:18 +0200 (Mon, 06 Apr 2009) | 4 lines
[kdepim.git] / kmail / kmfilterdlg.cpp
blob0dd350c9c5064f52c9fc3d0e9919c101f0869983
1 /*
2 Filter Dialog
3 Author: Marc Mutz <Marc@Mutz.com>
4 based upon work by Stefan Taferner <taferner@kde.org>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "kmfilterdlg.h"
23 // other KMail headers:
24 #include "kmsearchpatternedit.h"
25 #include "kmfiltermgr.h"
26 #include "kmmainwidget.h"
27 #include "accountmanager.h"
28 using KMail::AccountManager;
29 #include "filterimporterexporter.h"
30 using KMail::FilterImporterExporter;
32 // other KDE headers:
33 #include <kcombobox.h>
34 #include <kmessagebox.h>
35 #include <kdebug.h>
36 #include <klocale.h>
37 #include <kinputdialog.h>
38 #include <kiconloader.h>
39 #include <kwindowsystem.h>
40 #include <kconfig.h>
41 #include <kicondialog.h>
42 #include <kkeysequencewidget.h>
43 #include <kpushbutton.h>
44 #include <kconfiggroup.h>
45 #include <ktabwidget.h>
46 #include <kvbox.h>
48 // Qt headers:
49 #include <QCheckBox>
50 #include <QGridLayout>
51 #include <QLabel>
52 #include <QListWidget>
53 #include <QStackedWidget>
54 #include <QVBoxLayout>
55 #include <QTreeWidget>
57 // other headers:
58 #include <assert.h>
61 // What's this help texts
62 const char * _wt_filterlist =
63 I18N_NOOP( "<qt><p>This is the list of defined filters. "
64 "They are processed top-to-bottom.</p>"
65 "<p>Click on any filter to edit it "
66 "using the controls in the right-hand half "
67 "of the dialog.</p></qt>" );
68 const char * _wt_filterlist_new =
69 I18N_NOOP( "<qt><p>Click this button to create a new filter.</p>"
70 "<p>The filter will be inserted just before the currently-"
71 "selected one, but you can always change that "
72 "later on.</p>"
73 "<p>If you have clicked this button accidentally, you can undo this "
74 "by clicking on the <em>Delete</em> button.</p></qt>" );
75 const char * _wt_filterlist_copy =
76 I18N_NOOP( "<qt><p>Click this button to copy a filter.</p>"
77 "<p>If you have clicked this button accidentally, you can undo this "
78 "by clicking on the <em>Delete</em> button.</p></qt>" );
79 const char * _wt_filterlist_delete =
80 I18N_NOOP( "<qt><p>Click this button to <em>delete</em> the currently-"
81 "selected filter from the list above.</p>"
82 "<p>There is no way to get the filter back once "
83 "it is deleted, but you can always leave the "
84 "dialog by clicking <em>Cancel</em> to discard the "
85 "changes made.</p></qt>" );
86 const char * _wt_filterlist_up =
87 I18N_NOOP( "<qt><p>Click this button to move the currently-"
88 "selected filter <em>up</em> one in the list above.</p>"
89 "<p>This is useful since the order of the filters in the list "
90 "determines the order in which they are tried on messages: "
91 "The topmost filter gets tried first.</p>"
92 "<p>If you have clicked this button accidentally, you can undo this "
93 "by clicking on the <em>Down</em> button.</p></qt>" );
94 const char * _wt_filterlist_down =
95 I18N_NOOP( "<qt><p>Click this button to move the currently-"
96 "selected filter <em>down</em> one in the list above.</p>"
97 "<p>This is useful since the order of the filters in the list "
98 "determines the order in which they are tried on messages: "
99 "The topmost filter gets tried first.</p>"
100 "<p>If you have clicked this button accidentally, you can undo this "
101 "by clicking on the <em>Up</em> button.</p></qt>" );
102 const char * _wt_filterlist_rename =
103 I18N_NOOP( "<qt><p>Click this button to rename the currently-selected filter.</p>"
104 "<p>Filters are named automatically, as long as they start with "
105 "\"&lt;\".</p>"
106 "<p>If you have renamed a filter accidentally and want automatic "
107 "naming back, click this button and select <em>Clear</em> followed "
108 "by <em>OK</em> in the appearing dialog.</p></qt>" );
109 const char * _wt_filterdlg_showLater =
110 I18N_NOOP( "<qt><p>Check this button to force the confirmation dialog to be "
111 "displayed.</p><p>This is useful if you have defined a ruleset that tags "
112 "messages to be downloaded later. Without the possibility to force "
113 "the dialog popup, these messages could never be downloaded if no "
114 "other large messages were waiting on the server, or if you wanted to "
115 "change the ruleset to tag the messages differently.</p></qt>" );
117 // The anchor of the filter dialog's help.
118 const char * KMFilterDlgHelpAnchor = "filters-id" ;
119 const char * KMPopFilterDlgHelpAnchor = "popfilters-id" ;
121 //=============================================================================
123 // class KMFilterDlg (the filter dialog)
125 //=============================================================================
127 KMFilterDlg::KMFilterDlg(QWidget* parent, bool popFilter, bool createDummyFilter )
128 : KDialog( parent ),
129 bPopFilter(popFilter)
131 if ( popFilter )
132 setCaption( i18n("POP3 Filter Rules") );
133 else
134 setCaption( i18n("Filter Rules") );
135 setButtons( Help|Ok|Apply|Cancel|User1|User2 );
136 setModal( false );
137 KWindowSystem::setIcons( winId(), qApp->windowIcon().pixmap(IconSize(KIconLoader::Desktop),IconSize(KIconLoader::Desktop)), qApp->windowIcon().pixmap(IconSize(KIconLoader::Small),IconSize(KIconLoader::Small)) );
138 setHelp( (bPopFilter)? KMPopFilterDlgHelpAnchor: KMFilterDlgHelpAnchor );
139 setButtonText( User1, i18n("Import...") );
140 setButtonText( User2, i18n("Export...") );
141 connect( this, SIGNAL(user1Clicked()),
142 this, SLOT( slotImportFilters()) );
143 connect( this, SIGNAL(user2Clicked()),
144 this, SLOT( slotExportFilters()) );
146 QWidget *w = new QWidget( this );
147 setMainWidget( w );
148 QHBoxLayout *topLayout = new QHBoxLayout( w );
149 topLayout->setObjectName( "topLayout" );
150 topLayout->setSpacing( spacingHint() );
151 topLayout->setMargin( 0 );
152 QHBoxLayout *hbl = topLayout;
153 QVBoxLayout *vbl2 = 0;
154 QWidget *page1 = 0;
155 QWidget *page2 = 0;
157 mFilterList = new KMFilterListBox( i18n("Available Filters"), w, 0, bPopFilter);
158 topLayout->addWidget( mFilterList, 1 /*stretch*/ );
160 if(!bPopFilter) {
161 KTabWidget *tabWidget = new KTabWidget( w );
162 tabWidget->setObjectName( "kmfd_tab" );
163 topLayout->addWidget( tabWidget );
165 page1 = new QWidget( tabWidget );
166 tabWidget->addTab( page1, i18nc("General mail filter settings.", "General") );
167 hbl = new QHBoxLayout( page1 );
168 hbl->setObjectName( "kmfd_hbl" );
169 hbl->setSpacing( spacingHint() );
170 hbl->setMargin( 0 );
172 page2 = new QWidget( tabWidget );
173 tabWidget->addTab( page2, i18nc("Advanced mail filter settings.","Advanced") );
174 vbl2 = new QVBoxLayout( page2 );
175 vbl2->setObjectName( "kmfd_vbl2" );
176 vbl2->setSpacing( spacingHint() );
177 vbl2->setMargin( 0 );
180 QVBoxLayout *vbl = new QVBoxLayout();
181 hbl->addLayout( vbl );
182 vbl->setObjectName( "kmfd_vbl" );
183 vbl->setSpacing( spacingHint() );
184 hbl->setStretchFactor( vbl, 2 );
186 mPatternEdit = new KMSearchPatternEdit( i18n("Filter Criteria"),
187 bPopFilter ? w : page1, bPopFilter );
188 vbl->addWidget( mPatternEdit, 0, Qt::AlignTop );
190 if(bPopFilter){
191 mActionGroup = new KMPopFilterActionWidget( i18n("Filter Action"), w );
192 vbl->addWidget( mActionGroup, 0, Qt::AlignTop );
194 mGlobalsBox = new QGroupBox( i18n("Global Options"), w);
195 QHBoxLayout *layout = new QHBoxLayout;
196 mShowLaterBtn = new QCheckBox( i18n("Always &show matched 'Download Later' messages in confirmation dialog"), mGlobalsBox);
197 mShowLaterBtn->setWhatsThis( i18n(_wt_filterdlg_showLater) );
198 layout->addWidget( mShowLaterBtn );
199 mGlobalsBox->setLayout( layout );
200 vbl->addWidget( mGlobalsBox, 0, Qt::AlignTop );
202 else {
203 QGroupBox *agb = new QGroupBox( i18n("Filter Actions"), page1 );
204 QHBoxLayout *layout = new QHBoxLayout;
205 mActionLister = new KMFilterActionWidgetLister( agb );
206 layout->addWidget( mActionLister );
207 agb->setLayout( layout );
208 vbl->addWidget( agb, 0, Qt::AlignTop );
210 mAdvOptsGroup = new QGroupBox (i18n("Advanced Options"), page2);
212 QGridLayout *gl = new QGridLayout();
213 QVBoxLayout *vbl3 = new QVBoxLayout();
214 gl->addLayout( vbl3, 0, 0 );
215 vbl3->setObjectName( "vbl3" );
216 vbl3->setSpacing( spacingHint() );
217 vbl3->addStretch( 1 );
218 mApplyOnIn = new QCheckBox( i18n("Apply this filter to incoming messages:"), mAdvOptsGroup );
219 vbl3->addWidget( mApplyOnIn );
220 QButtonGroup *bg = new QButtonGroup( mAdvOptsGroup );
221 bg->setObjectName( "bg" );
222 mApplyOnForAll = new QRadioButton( i18n("from all accounts"), mAdvOptsGroup );
223 bg->addButton( mApplyOnForAll );
224 vbl3->addWidget( mApplyOnForAll );
225 mApplyOnForTraditional = new QRadioButton( i18n("from all but online IMAP accounts"), mAdvOptsGroup );
226 bg->addButton( mApplyOnForTraditional );
227 vbl3->addWidget( mApplyOnForTraditional );
228 mApplyOnForChecked = new QRadioButton( i18n("from checked accounts only"), mAdvOptsGroup );
229 bg->addButton( mApplyOnForChecked );
230 vbl3->addWidget( mApplyOnForChecked );
231 vbl3->addStretch( 2 );
233 mAccountList = new QTreeWidget( mAdvOptsGroup );
234 mAccountList->setObjectName( "accountList" );
235 mAccountList->setColumnCount( 2 );
236 QStringList headerNames;
237 headerNames << i18n("Account Name") << i18n("Type");
238 mAccountList->setHeaderItem( new QTreeWidgetItem( headerNames ) );
239 mAccountList->setAllColumnsShowFocus( true );
240 mAccountList->setFrameStyle( QFrame::WinPanel + QFrame::Sunken );
241 mAccountList->setSortingEnabled( false );
242 mAccountList->setRootIsDecorated( false );
243 gl->addWidget( mAccountList, 0, 1, 4, 3 );
245 mApplyOnOut = new QCheckBox( i18n("Apply this filter to &sent messages"), mAdvOptsGroup );
246 gl->addWidget( mApplyOnOut, 4, 0, 1, 4 );
248 mApplyOnCtrlJ = new QCheckBox( i18n("Apply this filter on manual &filtering"), mAdvOptsGroup );
249 gl->addWidget( mApplyOnCtrlJ, 5, 0, 1, 4 );
251 mStopProcessingHere = new QCheckBox( i18n("If this filter &matches, stop processing here"), mAdvOptsGroup );
252 gl->addWidget( mStopProcessingHere, 6, 0, 1, 4 );
253 mConfigureShortcut = new QCheckBox( i18n("Add this filter to the Apply Filter menu"), mAdvOptsGroup );
254 gl->addWidget( mConfigureShortcut, 7, 0, 1, 2 );
255 QLabel *keyButtonLabel = new QLabel( i18n( "Shortcut:" ), mAdvOptsGroup );
256 keyButtonLabel->setAlignment( Qt::AlignVCenter | Qt::AlignRight );
257 gl->addWidget( keyButtonLabel, 7, 2, 1, 1);
258 mKeySeqWidget = new KKeySequenceWidget( mAdvOptsGroup );
259 mKeySeqWidget->setObjectName( "FilterShortcutSelector" );
260 gl->addWidget( mKeySeqWidget, 7, 3, 1, 1);
261 mKeySeqWidget->setEnabled( false );
262 mKeySeqWidget->setCheckActionCollections(
263 kmkernel->getKMMainWidget()->actionCollections() );
264 mConfigureToolbar = new QCheckBox( i18n("Additionally add this filter to the toolbar"), mAdvOptsGroup );
265 gl->addWidget( mConfigureToolbar, 8, 0, 1, 4 );
266 mConfigureToolbar->setEnabled( false );
268 KHBox *hbox = new KHBox( mAdvOptsGroup );
269 mFilterActionLabel = new QLabel( i18n( "Icon for this filter:" ),
270 hbox );
271 mFilterActionLabel->setEnabled( false );
273 mFilterActionIconButton = new KIconButton( hbox );
274 mFilterActionLabel->setBuddy( mFilterActionIconButton );
275 mFilterActionIconButton->setIconType( KIconLoader::NoGroup, KIconLoader::Action, false );
276 mFilterActionIconButton->setIconSize( 16 );
277 mFilterActionIconButton->setIcon( "system-run" );
278 mFilterActionIconButton->setEnabled( false );
280 gl->addWidget( hbox, 9, 0, 1, 4 );
282 mAdvOptsGroup->setLayout( gl );
284 vbl2->addWidget( mAdvOptsGroup, 0, Qt::AlignTop );
286 // spacer:
287 vbl->addStretch( 1 );
289 // load the filter parts into the edit widgets
290 connect( mFilterList, SIGNAL(filterSelected(KMFilter*)),
291 this, SLOT(slotFilterSelected(KMFilter*)) );
293 if (bPopFilter){
294 // set the state of the global setting 'show later msgs'
295 connect( mShowLaterBtn, SIGNAL(toggled(bool)),
296 mFilterList, SLOT(slotShowLaterToggled(bool)));
298 // set the action in the filter when changed
299 connect( mActionGroup, SIGNAL(actionChanged(const KMPopFilterAction)),
300 this, SLOT(slotActionChanged(const KMPopFilterAction)) );
301 } else {
302 // transfer changes from the 'Apply this filter on...'
303 // combo box to the filter
304 connect( mApplyOnIn, SIGNAL(clicked()),
305 this, SLOT(slotApplicabilityChanged()) );
306 connect( mApplyOnForAll, SIGNAL(clicked()),
307 this, SLOT(slotApplicabilityChanged()) );
308 connect( mApplyOnForTraditional, SIGNAL(clicked()),
309 this, SLOT(slotApplicabilityChanged()) );
310 connect( mApplyOnForChecked, SIGNAL(clicked()),
311 this, SLOT(slotApplicabilityChanged()) );
312 connect( mApplyOnOut, SIGNAL(clicked()),
313 this, SLOT(slotApplicabilityChanged()) );
314 connect( mApplyOnCtrlJ, SIGNAL(clicked()),
315 this, SLOT(slotApplicabilityChanged()) );
316 connect( mAccountList, SIGNAL( itemChanged(QTreeWidgetItem *,int) ),
317 this, SLOT( slotApplicableAccountsChanged() ) );
319 // transfer changes from the 'stop processing here'
320 // check box to the filter
321 connect( mStopProcessingHere, SIGNAL(toggled(bool)),
322 this, SLOT(slotStopProcessingButtonToggled(bool)) );
324 connect( mConfigureShortcut, SIGNAL(toggled(bool)),
325 this, SLOT(slotConfigureShortcutButtonToggled(bool)) );
327 connect( mKeySeqWidget, SIGNAL( keySequenceChanged( const QKeySequence& ) ),
328 this, SLOT( slotShortcutChanged( const QKeySequence& ) ) );
330 connect( mConfigureToolbar, SIGNAL(toggled(bool)),
331 this, SLOT(slotConfigureToolbarButtonToggled(bool)) );
333 connect( mFilterActionIconButton, SIGNAL( iconChanged( const QString& ) ),
334 this, SLOT( slotFilterActionIconChanged( const QString& ) ) );
337 // reset all widgets here
338 connect( mFilterList, SIGNAL(resetWidgets()),
339 this, SLOT(slotReset()) );
341 connect( mFilterList, SIGNAL( applyWidgets() ),
342 this, SLOT( slotUpdateFilter() ) );
344 // support auto-naming the filter
345 connect( mPatternEdit, SIGNAL(maybeNameChanged()),
346 mFilterList, SLOT(slotUpdateFilterName()) );
348 // apply changes on 'Apply'
349 connect( this, SIGNAL(applyClicked()),
350 mFilterList, SLOT(slotApplyFilterChanges()) );
352 // apply changes on 'OK'
353 connect( this, SIGNAL(okClicked()),
354 mFilterList, SLOT(slotApplyFilterChanges()) );
356 // save dialog size on 'OK'
357 connect( this, SIGNAL(okClicked()),
358 this, SLOT(slotSaveSize()) );
360 // destruct the dialog on OK, close and Cancel
361 connect( this, SIGNAL(finished()),
362 this, SLOT(slotFinished()) );
364 KConfigGroup geometry( KMKernel::config(), "Geometry");
365 const char * configKey
366 = bPopFilter ? "popFilterDialogSize" : "filterDialogSize";
367 if ( geometry.hasKey( configKey ) )
368 resize( geometry.readEntry( configKey, QSize() ));
369 else
370 adjustSize();
372 // load the filter list (emits filterSelected())
373 mFilterList->loadFilterList( createDummyFilter );
376 void KMFilterDlg::slotFinished() {
377 deleteLater();
380 void KMFilterDlg::slotSaveSize() {
381 KConfigGroup geometry( KMKernel::config(), "Geometry" );
382 geometry.writeEntry( bPopFilter ? "popFilterDialogSize" : "filterDialogSize", size() );
385 /** Set action of popFilter */
386 void KMFilterDlg::slotActionChanged(const KMPopFilterAction aAction)
388 mFilter->setAction(aAction);
391 void KMFilterDlg::slotFilterSelected( KMFilter* aFilter )
393 assert( aFilter );
395 if (bPopFilter){
396 mActionGroup->setAction( aFilter->action() );
397 mGlobalsBox->setEnabled(true);
398 mShowLaterBtn->setChecked(mFilterList->showLaterMsgs());
399 } else {
400 mActionLister->setActionList( aFilter->actions() );
402 mAdvOptsGroup->setEnabled( true );
405 mPatternEdit->setSearchPattern( aFilter->pattern() );
406 mFilter = aFilter;
408 if (!bPopFilter) {
409 kDebug(5006) << "apply on inbound ==" << aFilter->applyOnInbound();
410 kDebug(5006) << "apply on outbound ==" << aFilter->applyOnOutbound();
411 kDebug(5006) << "apply on explicit ==" << aFilter->applyOnExplicit();
413 // NOTE: setting these values activates the slot that sets them in
414 // the filter! So make sure we have the correct values _before_ we
415 // set the first one:
416 const bool applyOnIn = aFilter->applyOnInbound();
417 const bool applyOnForAll = aFilter->applicability() == KMFilter::All;
418 const bool applyOnTraditional = aFilter->applicability() == KMFilter::ButImap;
419 const bool applyOnOut = aFilter->applyOnOutbound();
420 const bool applyOnExplicit = aFilter->applyOnExplicit();
421 const bool stopHere = aFilter->stopProcessingHere();
422 const bool configureShortcut = aFilter->configureShortcut();
423 const bool configureToolbar = aFilter->configureToolbar();
424 const QString icon = aFilter->icon();
425 const KShortcut shortcut( aFilter->shortcut() );
427 mApplyOnIn->setChecked( applyOnIn );
428 mApplyOnForAll->setEnabled( applyOnIn );
429 mApplyOnForTraditional->setEnabled( applyOnIn );
430 mApplyOnForChecked->setEnabled( applyOnIn );
431 mApplyOnForAll->setChecked( applyOnForAll );
432 mApplyOnForTraditional->setChecked( applyOnTraditional );
433 mApplyOnForChecked->setChecked( !applyOnForAll && !applyOnTraditional );
434 mAccountList->setEnabled( mApplyOnForChecked->isEnabled() && mApplyOnForChecked->isChecked() );
435 slotUpdateAccountList();
436 mApplyOnOut->setChecked( applyOnOut );
437 mApplyOnCtrlJ->setChecked( applyOnExplicit );
438 mStopProcessingHere->setChecked( stopHere );
439 mConfigureShortcut->setChecked( configureShortcut );
440 mKeySeqWidget->setKeySequence( shortcut.primary(),
441 KKeySequenceWidget::NoValidate );
442 mConfigureToolbar->setChecked( configureToolbar );
443 mFilterActionIconButton->setIcon( icon );
447 void KMFilterDlg::slotReset()
449 mFilter = 0;
450 mPatternEdit->reset();
452 if(bPopFilter) {
453 mActionGroup->reset();
454 mGlobalsBox->setEnabled( false );
455 } else {
456 mActionLister->reset();
457 mAdvOptsGroup->setEnabled( false );
458 slotUpdateAccountList();
462 void KMFilterDlg::slotUpdateFilter()
464 mPatternEdit->updateSearchPattern();
465 if ( !bPopFilter ) {
466 mActionLister->updateActionList();
470 void KMFilterDlg::slotApplicabilityChanged()
472 if ( mFilter ) {
473 mFilter->setApplyOnInbound( mApplyOnIn->isChecked() );
474 mFilter->setApplyOnOutbound( mApplyOnOut->isChecked() );
475 mFilter->setApplyOnExplicit( mApplyOnCtrlJ->isChecked() );
476 if ( mApplyOnForAll->isChecked() )
477 mFilter->setApplicability( KMFilter::All );
478 else if ( mApplyOnForTraditional->isChecked() )
479 mFilter->setApplicability( KMFilter::ButImap );
480 else if ( mApplyOnForChecked->isChecked() )
481 mFilter->setApplicability( KMFilter::Checked );
483 mApplyOnForAll->setEnabled( mApplyOnIn->isChecked() );
484 mApplyOnForTraditional->setEnabled( mApplyOnIn->isChecked() );
485 mApplyOnForChecked->setEnabled( mApplyOnIn->isChecked() );
486 mAccountList->setEnabled( mApplyOnForChecked->isEnabled() && mApplyOnForChecked->isChecked() );
488 // Advanced tab functionality - Update list of accounts this filter applies to
489 QTreeWidgetItemIterator it( mAccountList );
490 while( QTreeWidgetItem * item = *it ) {
491 int id = item->text( 2 ).toInt();
492 item->setCheckState( 0, mFilter->applyOnAccount( id ) ? Qt::Checked :
493 Qt::Unchecked );
494 ++it;
497 kDebug(5006) << "Setting filter to be applied at"
498 << ( mFilter->applyOnInbound() ? "incoming " : "" )
499 << ( mFilter->applyOnOutbound() ? "outgoing " : "" )
500 << ( mFilter->applyOnExplicit() ? "explicit CTRL-J" : "" );
504 void KMFilterDlg::slotApplicableAccountsChanged()
506 // Advanced tab functionality - Update list of accounts this filter applies to
507 if ( mFilter && mApplyOnForChecked->isEnabled() && mApplyOnForChecked->isChecked() ) {
509 QTreeWidgetItemIterator it( mAccountList );
511 while( QTreeWidgetItem *item = *it ) {
512 int id = item->text( 2 ).toInt();
513 mFilter->setApplyOnAccount( id, item->checkState( 0 ) == Qt::Checked );
514 ++it;
519 void KMFilterDlg::slotStopProcessingButtonToggled( bool aChecked )
521 if ( mFilter )
522 mFilter->setStopProcessingHere( aChecked );
525 void KMFilterDlg::slotConfigureShortcutButtonToggled( bool aChecked )
527 if ( mFilter ) {
528 mFilter->setConfigureShortcut( aChecked );
529 mKeySeqWidget->setEnabled( aChecked );
530 mConfigureToolbar->setEnabled( aChecked );
531 mFilterActionIconButton->setEnabled( aChecked );
532 mFilterActionLabel->setEnabled( aChecked );
536 void KMFilterDlg::slotShortcutChanged( const QKeySequence &newSeq )
538 if ( mFilter ) {
539 mKeySeqWidget->applyStealShortcut();
540 mFilter->setShortcut( KShortcut( newSeq ) );
544 void KMFilterDlg::slotConfigureToolbarButtonToggled( bool aChecked )
546 if ( mFilter )
547 mFilter->setConfigureToolbar( aChecked );
550 void KMFilterDlg::slotFilterActionIconChanged( const QString &icon )
552 if ( mFilter )
553 mFilter->setIcon( icon );
556 void KMFilterDlg::slotUpdateAccountList()
558 mAccountList->clear();
560 QTreeWidgetItem *top = 0;
562 // Block the signals here, otherwise we end up calling
563 // slotApplicableAccountsChanged(), which will read the incomplete item
564 // state and write that back to the filter
565 mAccountList->blockSignals( true );
566 QList<KMAccount*>::iterator accountIt = kmkernel->acctMgr()->begin();
567 while ( accountIt != kmkernel->acctMgr()->end() ) {
568 KMAccount *account = *accountIt;
569 ++accountIt;
570 QTreeWidgetItem *listItem = new QTreeWidgetItem( mAccountList, top );
571 listItem->setText( 0, account->name() );
572 listItem->setText( 1, KAccount::displayNameForType( account->type() ) );
573 listItem->setText( 2, QString( "%1" ).arg( account->id() ) );
574 if ( mFilter )
575 listItem->setCheckState( 0, mFilter->applyOnAccount( account->id() ) ?
576 Qt::Checked : Qt::Unchecked );
577 top = listItem;
579 mAccountList->blockSignals( false );
581 // make sure our hidden column is really hidden (Qt tends to re-show it)
582 mAccountList->hideColumn( 2 );
583 mAccountList->resizeColumnToContents( 0 );
584 mAccountList->resizeColumnToContents( 1 );
586 top = mAccountList->topLevelItem( 0 );
587 if ( top ) {
588 mAccountList->setCurrentItem( top );
592 //=============================================================================
594 // class KMFilterListBox (the filter list manipulator)
596 //=============================================================================
598 KMFilterListBox::KMFilterListBox( const QString & title, QWidget *parent,
599 const char* name, bool popFilter )
600 : QGroupBox( title, parent ),
601 bPopFilter(popFilter)
603 setObjectName( name );
604 QVBoxLayout *layout = new QVBoxLayout();
606 mIdxSelItem = -1;
608 //----------- the list box
609 mListWidget = new QListWidget(this);
610 mListWidget->setMinimumWidth(150);
611 mListWidget->setWhatsThis( i18n(_wt_filterlist) );
613 layout->addWidget( mListWidget );
615 //----------- the first row of buttons
616 KHBox *hb = new KHBox(this);
617 hb->setSpacing(4);
618 mBtnUp = new KPushButton( QString(), hb );
619 mBtnUp->setAutoRepeat( true );
620 mBtnUp->setIcon( KIcon( "go-up" ) );
621 mBtnUp->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) );
622 mBtnUp->setMinimumSize( mBtnUp->sizeHint() * 1.2 );
623 mBtnDown = new KPushButton( QString(), hb );
624 mBtnDown->setAutoRepeat( true );
625 mBtnDown->setIcon( KIcon( "go-down" ) );
626 mBtnDown->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) );
627 mBtnDown->setMinimumSize( mBtnDown->sizeHint() * 1.2 );
628 mBtnUp->setToolTip( i18nc("Move selected filter up.", "Up") );
629 mBtnDown->setToolTip( i18nc("Move selected filter down.", "Down") );
630 mBtnUp->setWhatsThis( i18n(_wt_filterlist_up) );
631 mBtnDown->setWhatsThis( i18n(_wt_filterlist_down) );
633 layout->addWidget( hb );
635 //----------- the second row of buttons
636 hb = new KHBox(this);
637 hb->setSpacing(4);
638 mBtnNew = new QPushButton( QString(), hb );
639 mBtnNew->setIcon( KIcon( "document-new" ) );
640 mBtnNew->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) );
641 mBtnNew->setMinimumSize( mBtnNew->sizeHint() * 1.2 );
642 mBtnCopy = new QPushButton( QString(), hb );
643 mBtnCopy->setIcon( KIcon( "edit-copy" ) );
644 mBtnCopy->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) );
645 mBtnCopy->setMinimumSize( mBtnCopy->sizeHint() * 1.2 );
646 mBtnDelete = new QPushButton( QString(), hb );
647 mBtnDelete->setIcon( KIcon( "edit-delete" ) );
648 mBtnDelete->setIconSize( QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall ) );
649 mBtnDelete->setMinimumSize( mBtnDelete->sizeHint() * 1.2 );
650 mBtnRename = new QPushButton( i18n("Rename..."), hb );
651 mBtnNew->setToolTip( i18nc("@action:button in filter list manipulator", "New") );
652 mBtnCopy->setToolTip( i18n("Copy") );
653 mBtnDelete->setToolTip( i18n("Delete"));
654 mBtnNew->setWhatsThis( i18n(_wt_filterlist_new) );
655 mBtnCopy->setWhatsThis( i18n(_wt_filterlist_copy) );
656 mBtnDelete->setWhatsThis( i18n(_wt_filterlist_delete) );
657 mBtnRename->setWhatsThis( i18n(_wt_filterlist_rename) );
659 layout->addWidget( hb );
660 setLayout( layout );
662 //----------- now connect everything
663 connect( mListWidget, SIGNAL(currentRowChanged(int)),
664 this, SLOT(slotSelected(int)) );
665 connect( mListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
666 this, SLOT( slotRename()) );
667 connect( mBtnUp, SIGNAL(clicked()),
668 this, SLOT(slotUp()) );
669 connect( mBtnDown, SIGNAL(clicked()),
670 this, SLOT(slotDown()) );
671 connect( mBtnNew, SIGNAL(clicked()),
672 this, SLOT(slotNew()) );
673 connect( mBtnCopy, SIGNAL(clicked()),
674 this, SLOT(slotCopy()) );
675 connect( mBtnDelete, SIGNAL(clicked()),
676 this, SLOT(slotDelete()) );
677 connect( mBtnRename, SIGNAL(clicked()),
678 this, SLOT(slotRename()) );
680 // the dialog should call loadFilterList()
681 // when all signals are connected.
682 enableControls();
686 KMFilterListBox::~KMFilterListBox()
688 qDeleteAll( mFilterList );
692 void KMFilterListBox::createFilter( const QByteArray & field,
693 const QString & value )
695 KMSearchRule *newRule = KMSearchRule::createInstance( field, KMSearchRule::FuncContains, value );
697 KMFilter *newFilter = new KMFilter( bPopFilter );
698 newFilter->pattern()->append( newRule );
699 newFilter->pattern()->setName( QString("<%1>:%2").arg( QString::fromLatin1( field ) ).arg( value) );
701 KMFilterActionDesc *desc = kmkernel->filterActionDict()->value( "transfer" );
702 if ( desc )
703 newFilter->actions()->append( desc->create() );
705 insertFilter( newFilter );
706 enableControls();
709 bool KMFilterListBox::showLaterMsgs()
711 return mShowLater;
714 void KMFilterListBox::slotUpdateFilterName()
716 if ( mIdxSelItem < 0 ) {
717 kDebug(5006) << "Called while no filter is selected, ignoring. idx=" << mIdxSelItem;
718 return;
721 KMSearchPattern *p = mFilterList.at(mIdxSelItem)->pattern();
722 if ( !p ) return;
724 QString shouldBeName = p->name();
725 QString displayedName = mListWidget->item( mIdxSelItem )->text();
727 if ( shouldBeName.trimmed().isEmpty() ) {
728 mFilterList.at(mIdxSelItem)->setAutoNaming( true );
731 if ( mFilterList.at(mIdxSelItem)->isAutoNaming() ) {
732 // auto-naming of patterns
733 if ( p->first() && !p->first()->field().trimmed().isEmpty() )
734 shouldBeName = QString( "<%1>: %2" ).arg( QString::fromLatin1( p->first()->field() ) ).arg( p->first()->contents() );
735 else
736 shouldBeName = '<' + i18n("unnamed") + '>';
737 p->setName( shouldBeName );
740 if ( displayedName == shouldBeName ) return;
742 mListWidget->blockSignals(true);
743 mListWidget->item( mIdxSelItem )->setText( shouldBeName );
744 mListWidget->blockSignals(false);
747 void KMFilterListBox::slotShowLaterToggled(bool aOn)
749 mShowLater = aOn;
752 void KMFilterListBox::slotApplyFilterChanges()
754 if ( mIdxSelItem >= 0 ) {
755 emit applyWidgets();
756 slotSelected( mListWidget->currentRow() );
759 // by now all edit widgets should have written back
760 // their widget's data into our filter list.
762 KMFilterMgr *fm;
763 if ( bPopFilter )
764 fm = kmkernel->popFilterMgr();
765 else
766 fm = kmkernel->filterMgr();
768 QList<KMFilter *> newFilters = filtersForSaving();
770 if ( bPopFilter )
771 fm->setShowLaterMsgs( mShowLater );
773 fm->setFilters( newFilters );
774 if ( fm->atLeastOneOnlineImapFolderTarget() ) {
775 QString str = i18n("At least one filter targets a folder on an online "
776 "IMAP account. Such filters will only be applied "
777 "when manually filtering and when filtering "
778 "incoming online IMAP mail.");
779 KMessageBox::information( this, str, QString(), "filterDlgOnlineImapCheck" );
783 QList<KMFilter *> KMFilterListBox::filtersForSaving() const
785 const_cast<KMFilterListBox*>( this )->applyWidgets(); // signals aren't const
786 QList<KMFilter *> filters;
787 QStringList emptyFilters;
788 foreach ( KMFilter *const it, mFilterList ) {
789 KMFilter *f = new KMFilter( *it ); // deep copy
790 f->purify();
791 if ( !f->isEmpty() )
792 // the filter is valid:
793 filters.append( f );
794 else {
795 // the filter is invalid:
796 emptyFilters << f->name();
797 delete f;
801 // report on invalid filters:
802 if ( !emptyFilters.empty() ) {
803 QString msg = i18n("The following filters have not been saved because they "
804 "were invalid (e.g. containing no actions or no search "
805 "rules).");
806 KMessageBox::informationList( 0, msg, emptyFilters, QString(),
807 "ShowInvalidFilterWarning" );
809 return filters;
812 void KMFilterListBox::slotSelected( int aIdx )
814 kDebug(5006) << "idx=" << aIdx;
815 mIdxSelItem = aIdx;
817 if ( mIdxSelItem >= 0 && mIdxSelItem < mFilterList.count() ) {
818 KMFilter *f = mFilterList.at(aIdx);
819 if ( f )
820 emit filterSelected( f );
821 else
822 emit resetWidgets();
823 } else {
824 emit resetWidgets();
826 enableControls();
829 void KMFilterListBox::slotNew()
831 // just insert a new filter.
832 insertFilter( new KMFilter( bPopFilter ) );
833 enableControls();
836 void KMFilterListBox::slotCopy()
838 if ( mIdxSelItem < 0 ) {
839 kDebug(5006) << "Called while no filter is selected, ignoring.";
840 return;
843 // make sure that all changes are written to the filter before we copy it
844 emit applyWidgets();
846 KMFilter *filter = mFilterList.at( mIdxSelItem );
848 // enableControls should make sure this method is
849 // never called when no filter is selected.
850 assert( filter );
852 // inserts a copy of the current filter.
853 insertFilter( new KMFilter( *filter ) );
854 enableControls();
857 void KMFilterListBox::slotDelete()
859 if ( mIdxSelItem < 0 ) {
860 kDebug(5006) << "Called while no filter is selected, ignoring.";
861 return;
864 int oIdxSelItem = mIdxSelItem;
865 mIdxSelItem = -1;
866 // unselect all
867 // TODO remove this line: mListWidget->clearSelection();
868 // broadcast that all widgets let go
869 // of the filter
870 emit resetWidgets();
872 // remove the filter from both the filter list...
873 mFilterList.takeAt( oIdxSelItem );
874 // and the listbox
875 mListWidget->takeItem( oIdxSelItem );
877 int count = mListWidget->count();
878 // and set the new current item.
879 if ( count > oIdxSelItem )
880 // oIdxItem is still a valid index
881 mListWidget->setCurrentRow( oIdxSelItem );
882 else if ( count )
883 // oIdxSelIdx is no longer valid, but the
884 // list box isn't empty
885 mListWidget->setCurrentRow( count - 1 );
887 // work around a problem when deleting the first item in a QListWidget:
888 // after takeItem, slotSelectionChanged is emitted with 1, but the row 0
889 // remains selected and another selectCurrentRow(0) does not trigger the
890 // selectionChanged signal
891 // (qt-copy as of 2006-12-22 / gungl)
892 if ( oIdxSelItem == 0 )
893 slotSelected( 0 );
895 mIdxSelItem = mListWidget->currentRow();
896 enableControls();
899 void KMFilterListBox::slotUp()
901 if ( mIdxSelItem < 0 ) {
902 kDebug(5006) << "Called while no filter is selected, ignoring.";
903 return;
905 if ( mIdxSelItem == 0 ) {
906 kDebug(5006) << "Called while the _topmost_ filter is selected, ignoring.";
907 return;
910 swapNeighbouringFilters( mIdxSelItem, mIdxSelItem - 1 );
911 enableControls();
914 void KMFilterListBox::slotDown()
916 if ( mIdxSelItem < 0 ) {
917 kDebug(5006) << "Called while no filter is selected, ignoring.";
918 return;
920 if ( mIdxSelItem == (int)mListWidget->count() - 1 ) {
921 kDebug(5006) << "Called while the _last_ filter is selected, ignoring.";
922 return;
925 swapNeighbouringFilters( mIdxSelItem, mIdxSelItem + 1);
926 enableControls();
929 void KMFilterListBox::slotRename()
931 if ( mIdxSelItem < 0 ) {
932 kDebug(5006) << "Called while no filter is selected, ignoring.";
933 return;
936 bool okPressed = false;
937 KMFilter *filter = mFilterList.at( mIdxSelItem );
939 // enableControls should make sure this method is
940 // never called when no filter is selected.
941 assert( filter );
943 // allow empty names - those will turn auto-naming on again
944 QValidator *validator = new QRegExpValidator( QRegExp( ".*" ), 0 );
945 QString newName = KInputDialog::getText
947 i18n("Rename Filter"),
948 i18n("Rename filter \"%1\" to:\n(leave the field empty for automatic naming)",
949 filter->pattern()->name() ) /*label*/,
950 filter->pattern()->name() /* initial value */,
951 &okPressed, topLevelWidget(), validator
953 delete validator;
955 if ( !okPressed ) return;
957 if ( newName.isEmpty() ) {
958 // bait for slotUpdateFilterName to
959 // use automatic naming again.
960 filter->pattern()->setName( "<>" );
961 filter->setAutoNaming( true );
962 } else {
963 filter->pattern()->setName( newName );
964 filter->setAutoNaming( false );
967 slotUpdateFilterName();
970 void KMFilterListBox::enableControls()
972 bool theFirst = ( mIdxSelItem == 0 );
973 bool theLast = ( mIdxSelItem >= (int)mFilterList.count() - 1 );
974 bool aFilterIsSelected = ( mIdxSelItem >= 0 );
976 mBtnUp->setEnabled( aFilterIsSelected && !theFirst );
977 mBtnDown->setEnabled( aFilterIsSelected && !theLast );
978 mBtnCopy->setEnabled( aFilterIsSelected );
979 mBtnDelete->setEnabled( aFilterIsSelected );
980 mBtnRename->setEnabled( aFilterIsSelected );
982 if ( aFilterIsSelected )
983 mListWidget->scrollToItem( mListWidget->currentItem() );
986 void KMFilterListBox::loadFilterList( bool createDummyFilter )
988 assert(mListWidget);
989 setEnabled(false);
990 emit resetWidgets();
991 // we don't want the insertion to
992 // cause flicker in the edit widgets.
993 blockSignals(true);
995 // clear both lists
996 mFilterList.clear();
997 mListWidget->clear();
999 const KMFilterMgr *manager = 0;
1000 if(bPopFilter)
1002 mShowLater = kmkernel->popFilterMgr()->showLaterMsgs();
1003 manager = kmkernel->popFilterMgr();
1005 else
1007 manager = kmkernel->filterMgr();
1009 Q_ASSERT( manager );
1011 QList<KMFilter*>::const_iterator it;
1012 for ( it = manager->filters().constBegin() ;
1013 it != manager->filters().constEnd();
1014 ++it ) {
1015 mFilterList.append( new KMFilter( **it ) ); // deep copy
1016 mListWidget->addItem( (*it)->pattern()->name() );
1019 blockSignals(false);
1020 setEnabled(true);
1022 // create an empty filter when there's none, to avoid a completely
1023 // disabled dialog (usability tests indicated that the new-filter
1024 // button is too hard to find that way):
1025 if ( !mListWidget->count() && createDummyFilter )
1026 slotNew();
1028 if ( mListWidget->count() > 0 )
1029 mListWidget->setCurrentRow( 0 );
1031 enableControls();
1034 void KMFilterListBox::insertFilter( KMFilter* aFilter )
1036 // must be really a filter...
1037 assert( aFilter );
1039 // if mIdxSelItem < 0, QListBox::insertItem will append.
1040 mListWidget->insertItem( mIdxSelItem, aFilter->pattern()->name() );
1041 if ( mIdxSelItem < 0 ) {
1042 // none selected -> append
1043 mFilterList.append( aFilter );
1044 mListWidget->setCurrentRow( mListWidget->count() - 1 );
1045 } else {
1046 // insert just before selected
1047 mFilterList.insert( mIdxSelItem, aFilter );
1048 mListWidget->setCurrentRow( mIdxSelItem );
1053 void KMFilterListBox::appendFilter( KMFilter* aFilter )
1055 mFilterList.append( aFilter );
1056 mListWidget->addItems( QStringList( aFilter->pattern()->name() ) );
1059 void KMFilterListBox::swapNeighbouringFilters( int untouchedOne, int movedOne )
1061 // must be neighbours...
1062 assert( untouchedOne - movedOne == 1 || movedOne - untouchedOne == 1 );
1064 // untouchedOne is at idx. to move it down(up),
1065 // remove item at idx+(-)1 w/o deleting it.
1066 QListWidgetItem *item = mListWidget->item( movedOne );
1067 mListWidget->takeItem( movedOne );
1068 // now selected item is at idx(idx-1), so
1069 // insert the other item at idx, ie. above(below).
1070 mListWidget->insertItem( untouchedOne, item );
1072 KMFilter* filter = mFilterList.takeAt( movedOne );
1073 mFilterList.insert( untouchedOne, filter );
1075 mIdxSelItem += movedOne - untouchedOne;
1079 //=============================================================================
1081 // class KMFilterActionWidget
1083 //=============================================================================
1085 KMFilterActionWidget::KMFilterActionWidget( QWidget *parent, const char* name )
1086 : KHBox( parent )
1088 setObjectName( name );
1090 int i;
1092 mComboBox = new KComboBox( this );
1093 mComboBox->setEditable( false );
1094 assert( mComboBox );
1095 mWidgetStack = new QStackedWidget(this);
1096 assert( mWidgetStack );
1098 setSpacing( 4 );
1100 QList<KMFilterActionDesc*> list = kmkernel->filterActionDict()->list();
1101 QList<KMFilterActionDesc*>::const_iterator it;
1102 for ( i=0, it = list.constBegin() ; it != list.constEnd() ; ++it, ++i ) {
1103 //create an instance:
1104 KMFilterAction *a = (*it)->create();
1105 // append to the list of actions:
1106 mActionList.append( a );
1107 // add parameter widget to widget stack:
1108 mWidgetStack->insertWidget( i, a->createParamWidget( mWidgetStack ) );
1109 // add (i18n-ized) name to combo box
1110 mComboBox->addItem( (*it)->label );
1112 // widget for the case where no action is selected.
1113 mWidgetStack->insertWidget( i,new QLabel( i18n("Please select an action."), mWidgetStack ) );
1114 mWidgetStack->setCurrentIndex(i);
1115 mComboBox->addItem( " " );
1116 mComboBox->setCurrentIndex(i);
1118 // don't show scroll bars.
1119 mComboBox->setMaxCount( mComboBox->count() );
1120 // layout management:
1121 // o the combo box is not to be made larger than it's sizeHint(),
1122 // the parameter widget should grow instead.
1123 // o the whole widget takes all space horizontally, but is fixed vertically.
1124 mComboBox->adjustSize();
1125 mComboBox->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
1126 setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
1127 updateGeometry();
1129 // redirect focus to the filter action combo box
1130 setFocusProxy( mComboBox );
1132 // now connect the combo box and the widget stack
1133 connect( mComboBox, SIGNAL(activated(int)),
1134 mWidgetStack, SLOT(setCurrentIndex (int)) );
1137 KMFilterActionWidget::~KMFilterActionWidget()
1139 qDeleteAll( mActionList );
1142 void KMFilterActionWidget::setAction( const KMFilterAction* aAction )
1144 bool found = false;
1145 int count = mComboBox->count() - 1 ; // last entry is the empty one
1146 QString label = ( aAction ) ? aAction->label() : QString() ;
1148 // find the index of typeOf(aAction) in mComboBox
1149 // and clear the other widgets on the way.
1150 for ( int i = 0; i < count ; i++ )
1151 if ( aAction && mComboBox->itemText(i) == label ) {
1152 //...set the parameter widget to the settings
1153 // of aAction...
1154 aAction->setParamWidgetValue( mWidgetStack->widget(i) );
1155 //...and show the correct entry of
1156 // the combo box
1157 mComboBox->setCurrentIndex(i); // (mm) also raise the widget, but doesn't
1158 mWidgetStack->setCurrentIndex(i);
1159 found = true;
1160 } else // clear the parameter widget
1161 mActionList.at(i)->clearParamWidget( mWidgetStack->widget(i) );
1162 if ( found ) return;
1164 // not found, so set the empty widget
1165 mComboBox->setCurrentIndex( count ); // last item
1166 mWidgetStack->setCurrentIndex( count) ;
1169 KMFilterAction * KMFilterActionWidget::action() const
1171 // look up the action description via the label
1172 // returned by KComboBox::currentText()...
1173 KMFilterActionDesc *desc = kmkernel->filterActionDict()->value( mComboBox->currentText() );
1174 if ( desc ) {
1175 // ...create an instance...
1176 KMFilterAction *fa = desc->create();
1177 if ( fa ) {
1178 // ...and apply the setting of the parameter widget.
1179 fa->applyParamWidgetValue( mWidgetStack->currentWidget() );
1180 return fa;
1184 return 0;
1187 //=============================================================================
1189 // class KMFilterActionWidgetLister (the filter action editor)
1191 //=============================================================================
1193 KMFilterActionWidgetLister::KMFilterActionWidgetLister( QWidget *parent, const char* name )
1194 : KWidgetLister( 1, FILTER_MAX_ACTIONS, parent, name )
1196 mActionList = 0;
1199 KMFilterActionWidgetLister::~KMFilterActionWidgetLister()
1203 void KMFilterActionWidgetLister::setActionList( QList<KMFilterAction*> *aList )
1205 assert ( aList );
1207 if ( mActionList )
1208 regenerateActionListFromWidgets();
1210 mActionList = aList;
1212 ((QWidget*)parent())->setEnabled( true );
1214 if ( aList->count() == 0 ) {
1215 slotClear();
1216 return;
1219 int superfluousItems = (int)mActionList->count() - mMaxWidgets ;
1220 if ( superfluousItems > 0 ) {
1221 kDebug(5006) <<"KMFilterActionWidgetLister: Clipping action list to"
1222 << mMaxWidgets << "items!";
1224 for ( ; superfluousItems ; superfluousItems-- )
1225 mActionList->removeLast();
1228 // set the right number of widgets
1229 setNumberOfShownWidgetsTo( mActionList->count() );
1231 // load the actions into the widgets
1232 QList<KMFilterAction*>::const_iterator aIt;
1233 QList<QWidget*>::ConstIterator wIt = mWidgetList.constBegin();
1234 for ( aIt = mActionList->constBegin();
1235 ( aIt != mActionList->constEnd() && wIt != mWidgetList.constEnd() );
1236 ++aIt, ++wIt )
1237 static_cast<KMFilterActionWidget*>( *wIt )->setAction( ( *aIt ) );
1240 void KMFilterActionWidgetLister::reset()
1242 if ( mActionList )
1243 regenerateActionListFromWidgets();
1245 mActionList = 0;
1246 slotClear();
1247 ((QWidget*)parent())->setEnabled( false );
1250 QWidget* KMFilterActionWidgetLister::createWidget( QWidget *parent )
1252 return new KMFilterActionWidget(parent);
1255 void KMFilterActionWidgetLister::clearWidget( QWidget *aWidget )
1257 if ( aWidget )
1258 ((KMFilterActionWidget*)aWidget)->setAction(0);
1261 void KMFilterActionWidgetLister::regenerateActionListFromWidgets()
1263 if ( !mActionList ) return;
1265 mActionList->clear();
1267 foreach ( const QWidget* w, mWidgetList ) {
1268 KMFilterAction *a = static_cast<const KMFilterActionWidget*>( w )->action();
1269 if ( a )
1270 mActionList->append( a );
1275 //=============================================================================
1277 // class KMPopFilterActionWidget
1279 //=============================================================================
1281 KMPopFilterActionWidget::KMPopFilterActionWidget( const QString& title, QWidget *parent, const char* name )
1282 : QGroupBox( title, parent )
1284 setObjectName( name );
1285 QVBoxLayout *layout = new QVBoxLayout( this );
1286 QButtonGroup *bg = new QButtonGroup( this );
1288 QRadioButton *downBtn = new QRadioButton( i18n("&Download mail"), this );
1289 QRadioButton *laterBtn = new QRadioButton( i18n("Download mail la&ter"), this );
1290 QRadioButton *deleteBtn = new QRadioButton( i18n("D&elete mail from server"), this );
1292 layout->addWidget( downBtn );
1293 layout->addWidget( laterBtn );
1294 layout->addWidget( deleteBtn );
1295 bg->addButton( downBtn );
1296 bg->addButton( laterBtn );
1297 bg->addButton( deleteBtn );
1299 mActionMap.insert( Down, downBtn );
1300 mActionMap.insert( Later, laterBtn );
1301 mActionMap.insert( Delete, deleteBtn );
1303 mButtonMap.insert( downBtn, Down );
1304 mButtonMap.insert( laterBtn, Later );
1305 mButtonMap.insert( deleteBtn, Delete );
1307 connect( bg, SIGNAL(buttonClicked(QAbstractButton*)),
1308 this, SLOT(slotActionClicked(QAbstractButton*)) );
1311 void KMPopFilterActionWidget::setAction( KMPopFilterAction aAction )
1313 if( aAction == NoAction)
1315 aAction = Later;
1318 mAction = aAction;
1320 blockSignals( true );
1321 if(!mActionMap[aAction]->isChecked())
1323 mActionMap[aAction]->setChecked(true);
1325 blockSignals( false );
1327 setEnabled(true);
1330 KMPopFilterAction KMPopFilterActionWidget::action()
1332 return mAction;
1335 void KMPopFilterActionWidget::slotActionClicked( QAbstractButton *btn )
1337 emit actionChanged( mButtonMap[btn] );
1338 setAction( mButtonMap[btn] );
1341 void KMPopFilterActionWidget::reset()
1343 blockSignals(true);
1344 mActionMap[Down]->setChecked( true );
1345 blockSignals(false);
1347 setEnabled( false );
1350 void KMFilterDlg::slotImportFilters()
1352 FilterImporterExporter importer( this, bPopFilter );
1353 QList<KMFilter *> filters = importer.importFilters();
1355 // FIXME message box how many were imported?
1356 if ( filters.isEmpty() ) return;
1358 QList<KMFilter*>::ConstIterator it;
1360 for ( it = filters.constBegin() ; it != filters.constEnd() ; ++it ) {
1361 mFilterList->appendFilter( *it ); // no need to deep copy, ownership passes to the list
1365 void KMFilterDlg::slotExportFilters()
1367 FilterImporterExporter exporter( this, bPopFilter );
1368 QList<KMFilter *> filters = mFilterList->filtersForSaving();
1369 exporter.exportFilters( filters );
1370 QList<KMFilter *>::ConstIterator it;
1371 for ( it = filters.constBegin(); it != filters.constEnd(); ++it )
1372 delete *it;
1375 #include "kmfilterdlg.moc"