kmail

kmfilterdlg.cpp
1// kmfilterdlg.cpp
2// Author: Marc Mutz <Marc@Mutz.com>
3// based on work by Stefan Taferner <taferner@kde.org>
4// This code is under the GPL
5
6#include <config.h>
7#include "kmfilterdlg.h"
8
9// other KMail headers:
10#include "kmsearchpatternedit.h"
11#include "kmfiltermgr.h"
12#include "kmmainwidget.h"
13#include "accountmanager.h"
15#include "filterimporterexporter.h"
17#include "foldersetselector.h"
18#include "globalsettings.h"
19
20// other KDE headers:
21#include <tdemessagebox.h>
22#include <kdebug.h>
23#include <tdelocale.h>
24#include <kinputdialog.h>
25#include <kiconloader.h>
26#include <tdeapplication.h>
27#include <twin.h>
28#include <tdeconfig.h>
29#include <kicondialog.h>
30#include <kkeybutton.h>
31#include <tdelistview.h>
32#include <kpushbutton.h>
33
34// other TQt headers:
35#include <tqlayout.h>
36#include <tqlabel.h>
37#include <tqcombobox.h>
38#include <tqwidgetstack.h>
39#include <tqtooltip.h>
40#include <tqwhatsthis.h>
41#include <tqcheckbox.h>
42#include <tqhbox.h>
43#include <tqvalidator.h>
44#include <tqtabwidget.h>
45
46// other headers:
47#include <assert.h>
48
49using namespace KMail;
50
51
52// What's this help texts
53const char * _wt_filterlist =
54I18N_NOOP( "<qt><p>This is the list of defined filters. "
55 "They are processed top-to-bottom.</p>"
56 "<p>Click on any filter to edit it "
57 "using the controls in the right-hand half "
58 "of the dialog.</p></qt>" );
59const char * _wt_filterlist_new =
60I18N_NOOP( "<qt><p>Click this button to create a new filter.</p>"
61 "<p>The filter will be inserted just before the currently-"
62 "selected one, but you can always change that "
63 "later on.</p>"
64 "<p>If you have clicked this button accidentally, you can undo this "
65 "by clicking on the <em>Delete</em> button.</p></qt>" );
66const char * _wt_filterlist_copy =
67I18N_NOOP( "<qt><p>Click this button to copy a filter.</p>"
68 "<p>If you have clicked this button accidentally, you can undo this "
69 "by clicking on the <em>Delete</em> button.</p></qt>" );
70const char * _wt_filterlist_delete =
71I18N_NOOP( "<qt><p>Click this button to <em>delete</em> the currently-"
72 "selected filter from the list above.</p>"
73 "<p>There is no way to get the filter back once "
74 "it is deleted, but you can always leave the "
75 "dialog by clicking <em>Cancel</em> to discard the "
76 "changes made.</p></qt>" );
77const char * _wt_filterlist_top =
78I18N_NOOP( "<qt><p>Click this button to move the currently-"
79 "selected filter to the <em>top</em> of the list above.</p>"
80 "<p>This is useful since the order of the filters in the list "
81 "determines the order in which they are tried on messages: "
82 "The topmost filter gets tried first.</p></qt>" );
83const char * _wt_filterlist_up =
84I18N_NOOP( "<qt><p>Click this button to move the currently-"
85 "selected filter <em>up</em> one in the list above.</p>"
86 "<p>This is useful since the order of the filters in the list "
87 "determines the order in which they are tried on messages: "
88 "The topmost filter gets tried first.</p>"
89 "<p>If you have clicked this button accidentally, you can undo this "
90 "by clicking on the <em>Down</em> button.</p></qt>" );
91const char * _wt_filterlist_down =
92I18N_NOOP( "<qt><p>Click this button to move the currently-"
93 "selected filter <em>down</em> one in the list above.</p>"
94 "<p>This is useful since the order of the filters in the list "
95 "determines the order in which they are tried on messages: "
96 "The topmost filter gets tried first.</p>"
97 "<p>If you have clicked this button accidentally, you can undo this "
98 "by clicking on the <em>Up</em> button.</p></qt>" );
99const char * _wt_filterlist_bot =
100I18N_NOOP( "<qt><p>Click this button to move the currently-"
101 "selected filter to the <em>bottom</em> of the list above.</p>"
102 "<p>This is useful since the order of the filters in the list "
103 "determines the order in which they are tried on messages: "
104 "The topmost filter gets tried first.</p></qt>" );
105const char * _wt_filterlist_rename =
106I18N_NOOP( "<qt><p>Click this button to rename the currently-selected filter.</p>"
107 "<p>Filters are named automatically, as long as they start with "
108 "\"&lt;\".</p>"
109 "<p>If you have renamed a filter accidentally and want automatic "
110 "naming back, click this button and select <em>Clear</em> followed "
111 "by <em>OK</em> in the appearing dialog.</p></qt>" );
112const char * _wt_filterdlg_showLater =
113I18N_NOOP( "<qt><p>Check this button to force the confirmation dialog to be "
114 "displayed.</p><p>This is useful if you have defined a ruleset that tags "
115 "messages to be downloaded later. Without the possibility to force "
116 "the dialog popup, these messages could never be downloaded if no "
117 "other large messages were waiting on the server, or if you wanted to "
118 "change the ruleset to tag the messages differently.</p></qt>" );
119
120// The anchor of the filter dialog's help.
121const char * KMFilterDlgHelpAnchor = "filters-id" ;
122const char * KMPopFilterDlgHelpAnchor = "popfilters-id" ;
123
124//=============================================================================
125//
126// class KMFilterDlg (the filter dialog)
127//
128//=============================================================================
129
130KMFilterDlg::KMFilterDlg(TQWidget* parent, const char* name, bool popFilter, bool createDummyFilter )
131 : KDialogBase( parent, name, false /* modality */,
132 (popFilter)? i18n("POP3 Filter Rules"): i18n("Filter Rules") /* caption*/,
133 Help|Ok|Apply|Cancel|User1|User2 /* button mask */,
134 Ok /* default btn */, false /* separator */),
135 bPopFilter(popFilter)
136{
137 KWin::setIcons( winId(), tdeApp->icon(), tdeApp->miniIcon() );
138 setHelp( (bPopFilter)? KMPopFilterDlgHelpAnchor: KMFilterDlgHelpAnchor );
139 setButtonText( User1, i18n("Import") );
140 setButtonText( User2, i18n("Export") );
141 connect( this, TQ_SIGNAL(user1Clicked()),
142 this, TQ_SLOT( slotImportFilters()) );
143 connect( this, TQ_SIGNAL(user2Clicked()),
144 this, TQ_SLOT( slotExportFilters()) );
145
146 TQWidget *w = new TQWidget( this );
147 setMainWidget( w );
148 TQHBoxLayout *topLayout = new TQHBoxLayout( w, 0, spacingHint(), "topLayout" );
149 TQHBoxLayout *hbl = topLayout;
150 TQVBoxLayout *vbl2 = 0;
151 TQWidget *page1 = 0;
152 TQWidget *page2 = 0;
153
154 mFilterList = new KMFilterListBox( i18n("Available Filters"), w, 0, bPopFilter);
155 topLayout->addWidget( mFilterList, 1 /*stretch*/ );
156
157 if(!bPopFilter) {
158 TQTabWidget *tabWidget = new TQTabWidget( w, "kmfd_tab" );
159 tabWidget->setMargin( KDialog::marginHint() );
160 topLayout->addWidget( tabWidget );
161
162 page1 = new TQWidget( tabWidget );
163 tabWidget->addTab( page1, i18n("&General") );
164 hbl = new TQHBoxLayout( page1, 0, spacingHint(), "kmfd_hbl" );
165
166 page2 = new TQWidget( tabWidget );
167 tabWidget->addTab( page2, i18n("A&dvanced") );
168 vbl2 = new TQVBoxLayout( page2, 0, spacingHint(), "kmfd_vbl2" );
169 }
170
171 TQVBoxLayout *vbl = new TQVBoxLayout( hbl, spacingHint(), "kmfd_vbl" );
172 hbl->setStretchFactor( vbl, 2 );
173
174 mPatternEdit = new KMSearchPatternEdit( i18n("Filter Criteria"), bPopFilter ? w : page1 , "spe", bPopFilter);
175 vbl->addWidget( mPatternEdit, 0, TQt::AlignTop );
176
177 if(bPopFilter){
178 mActionGroup = new KMPopFilterActionWidget( i18n("Filter Action"), w );
179 vbl->addWidget( mActionGroup, 0, TQt::AlignTop );
180
181 mGlobalsBox = new TQVGroupBox(i18n("Global Options"), w);
182 mShowLaterBtn = new TQCheckBox(i18n("Always &show matched 'Download Later' messages in confirmation dialog"), mGlobalsBox);
183 TQWhatsThis::add( mShowLaterBtn, i18n(_wt_filterdlg_showLater) );
184 vbl->addWidget( mGlobalsBox, 0, TQt::AlignTop );
185 }
186 else {
187 TQGroupBox *agb = new TQGroupBox( 1 /*column*/, TQt::Vertical, i18n("Filter Actions"), page1 );
188 mActionLister = new KMFilterActionWidgetLister( agb );
189 vbl->addWidget( agb, 0, TQt::AlignTop );
190
191 mAdvOptsGroup = new TQGroupBox ( 1 /*columns*/, TQt::Vertical,
192 i18n("Advanced Options"), page2);
193 {
194 TQWidget *adv_w = new TQWidget( mAdvOptsGroup );
195 TQGridLayout *gl = new TQGridLayout( adv_w, 8 /*rows*/, 3 /*cols*/,
196 0 /*border*/, spacingHint() );
197
198 TQVBoxLayout *vbl3 = new TQVBoxLayout( gl, spacingHint(), "vbl3" );
199 vbl3->addStretch( 1 );
200 mApplyOnIn = new TQCheckBox( i18n("Apply this filter to incoming messages:"), adv_w );
201 vbl3->addWidget( mApplyOnIn );
202 TQButtonGroup *bg = new TQButtonGroup( 0, "bg" );
203 bg->setExclusive( true );
204 mApplyOnForAll = new TQRadioButton( i18n("from all accounts"), adv_w );
205 bg->insert( mApplyOnForAll );
206 vbl3->addWidget( mApplyOnForAll );
207 mApplyOnForTraditional = new TQRadioButton( i18n("from all but online IMAP accounts"), adv_w );
208 bg->insert( mApplyOnForTraditional );
209 vbl3->addWidget( mApplyOnForTraditional );
210 mApplyOnForChecked = new TQRadioButton( i18n("from checked accounts only"), adv_w );
211 bg->insert( mApplyOnForChecked );
212 vbl3->addWidget( mApplyOnForChecked );
213 vbl3->addStretch( 2 );
214
215 mAccountList = new TDEListView( adv_w, "accountList" );
216 mAccountList->addColumn( i18n("Account Name") );
217 mAccountList->addColumn( i18n("Type") );
218 mAccountList->setAllColumnsShowFocus( true );
219 mAccountList->setFrameStyle( TQFrame::WinPanel + TQFrame::Sunken );
220 mAccountList->setSorting( -1 );
221 gl->addMultiCellWidget( mAccountList, 0, 3, 1, 3 );
222
223 mApplyOnOut = new TQCheckBox( i18n("Apply this filter to &sent messages"), adv_w );
224 gl->addMultiCellWidget( mApplyOnOut, 4, 4, 0, 3 );
225
226 mApplyOnCtrlJ = new TQCheckBox( i18n("Apply this filter on manual &filtering"), adv_w );
227 gl->addMultiCellWidget( mApplyOnCtrlJ, 5, 5, 0, 3 );
228
229 mStopProcessingHere = new TQCheckBox( i18n("If this filter &matches, stop processing here"), adv_w );
230 gl->addMultiCellWidget( mStopProcessingHere,
231 6, 6, /*from to row*/
232 0, 3 /*from to col*/ );
233 mConfigureShortcut = new TQCheckBox( i18n("Add this filter to the Apply Filter menu"), adv_w );
234 gl->addMultiCellWidget( mConfigureShortcut, 7, 7, 0, 1 );
235 TQLabel *keyButtonLabel = new TQLabel( i18n( "Shortcut:" ), adv_w );
236 keyButtonLabel->setAlignment( AlignVCenter | AlignRight );
237 gl->addMultiCellWidget( keyButtonLabel, 7, 7, 2, 2 );
238 mKeyButton = new KKeyButton( adv_w, "FilterShortcutSelector" );
239 gl->addMultiCellWidget( mKeyButton, 7, 7, 3, 3 );
240 mKeyButton->setEnabled( false );
241 mConfigureToolbar = new TQCheckBox( i18n("Additionally add this filter to the toolbar"), adv_w );
242 gl->addMultiCellWidget( mConfigureToolbar, 8, 8, 0, 3 );
243 mConfigureToolbar->setEnabled( false );
244
245 TQHBox *hbox = new TQHBox( adv_w );
246 mFilterActionLabel = new TQLabel( i18n( "Icon for this filter:" ),
247 hbox );
248 mFilterActionLabel->setEnabled( false );
249
250 mFilterActionIconButton = new TDEIconButton( hbox );
251 mFilterActionLabel->setBuddy( mFilterActionIconButton );
252 mFilterActionIconButton->setIconType( TDEIcon::NoGroup, TDEIcon::Any, true );
253 mFilterActionIconButton->setIconSize( 16 );
254 mFilterActionIconButton->setIcon( "gear" );
255 mFilterActionIconButton->setEnabled( false );
256
257 gl->addMultiCellWidget( hbox, 9, 9, 0, 3 );
258 }
259 vbl2->addWidget( mAdvOptsGroup, 0, TQt::AlignTop );
260 }
261 // spacer:
262 vbl->addStretch( 1 );
263
264 // load the filter parts into the edit widgets
265 connect( mFilterList, TQ_SIGNAL(filterSelected(KMFilter*)),
266 this, TQ_SLOT(slotFilterSelected(KMFilter*)) );
267
268 if (bPopFilter){
269 // set the state of the global setting 'show later msgs'
270 connect( mShowLaterBtn, TQ_SIGNAL(toggled(bool)),
271 mFilterList, TQ_SLOT(slotShowLaterToggled(bool)));
272
273 // set the action in the filter when changed
274 connect( mActionGroup, TQ_SIGNAL(actionChanged(const KMPopFilterAction)),
275 this, TQ_SLOT(slotActionChanged(const KMPopFilterAction)) );
276 } else {
277 // transfer changes from the 'Apply this filter on...'
278 // combo box to the filter
279 connect( mApplyOnIn, TQ_SIGNAL(clicked()),
280 this, TQ_SLOT(slotApplicabilityChanged()) );
281 connect( mApplyOnForAll, TQ_SIGNAL(clicked()),
282 this, TQ_SLOT(slotApplicabilityChanged()) );
283 connect( mApplyOnForTraditional, TQ_SIGNAL(clicked()),
284 this, TQ_SLOT(slotApplicabilityChanged()) );
285 connect( mApplyOnForChecked, TQ_SIGNAL(clicked()),
286 this, TQ_SLOT(slotApplicabilityChanged()) );
287 connect( mApplyOnOut, TQ_SIGNAL(clicked()),
288 this, TQ_SLOT(slotApplicabilityChanged()) );
289 connect( mApplyOnCtrlJ, TQ_SIGNAL(clicked()),
290 this, TQ_SLOT(slotApplicabilityChanged()) );
291 connect( mAccountList, TQ_SIGNAL(clicked(TQListViewItem*)),
292 this, TQ_SLOT(slotApplicableAccountsChanged()) );
293 connect( mAccountList, TQ_SIGNAL(spacePressed(TQListViewItem*)),
294 this, TQ_SLOT(slotApplicableAccountsChanged()) );
295
296 // transfer changes from the 'stop processing here'
297 // check box to the filter
298 connect( mStopProcessingHere, TQ_SIGNAL(toggled(bool)),
299 this, TQ_SLOT(slotStopProcessingButtonToggled(bool)) );
300
301 connect( mConfigureShortcut, TQ_SIGNAL(toggled(bool)),
302 this, TQ_SLOT(slotConfigureShortcutButtonToggled(bool)) );
303
304 connect( mKeyButton, TQ_SIGNAL( capturedShortcut( const TDEShortcut& ) ),
305 this, TQ_SLOT( slotCapturedShortcutChanged( const TDEShortcut& ) ) );
306
307 connect( mConfigureToolbar, TQ_SIGNAL(toggled(bool)),
308 this, TQ_SLOT(slotConfigureToolbarButtonToggled(bool)) );
309
310 connect( mFilterActionIconButton, TQ_SIGNAL( iconChanged( TQString ) ),
311 this, TQ_SLOT( slotFilterActionIconChanged( TQString ) ) );
312 }
313
314 // reset all widgets here
315 connect( mFilterList, TQ_SIGNAL(resetWidgets()),
316 this, TQ_SLOT(slotReset()) );
317
318 connect( mFilterList, TQ_SIGNAL( applyWidgets() ),
319 this, TQ_SLOT( slotUpdateFilter() ) );
320
321 // support auto-naming the filter
322 connect( mPatternEdit, TQ_SIGNAL(maybeNameChanged()),
323 mFilterList, TQ_SLOT(slotUpdateFilterName()) );
324
325 // apply changes on 'Apply'
326 connect( this, TQ_SIGNAL(applyClicked()),
327 mFilterList, TQ_SLOT(slotApplyFilterChanges()) );
328
329 // apply changes on 'OK'
330 connect( this, TQ_SIGNAL(okClicked()),
331 mFilterList, TQ_SLOT(slotApplyFilterChanges()) );
332
333 // save dialog size on 'OK'
334 connect( this, TQ_SIGNAL(okClicked()),
335 this, TQ_SLOT(slotSaveSize()) );
336
337 // destruct the dialog on OK, close and Cancel
338 connect( this, TQ_SIGNAL(finished()),
339 this, TQ_SLOT(slotFinished()) );
340
341 TDEConfigGroup geometry( KMKernel::config(), "Geometry");
342 const char * configKey
343 = bPopFilter ? "popFilterDialogSize" : "filterDialogSize";
344 if ( geometry.hasKey( configKey ) )
345 resize( geometry.readSizeEntry( configKey ) );
346 else
347 adjustSize();
348
349 // load the filter list (emits filterSelected())
350 mFilterList->loadFilterList( createDummyFilter );
351}
352
353void KMFilterDlg::slotFinished() {
354 delayedDestruct();
355}
356
357void KMFilterDlg::slotSaveSize() {
358 TDEConfigGroup geometry( KMKernel::config(), "Geometry" );
359 geometry.writeEntry( bPopFilter ? "popFilterDialogSize" : "filterDialogSize", size() );
360}
361
363void KMFilterDlg::slotActionChanged(const KMPopFilterAction aAction)
364{
365 mFilter->setAction(aAction);
366}
367
368void KMFilterDlg::slotFilterSelected( KMFilter* aFilter )
369{
370 assert( aFilter );
371
372 if (bPopFilter){
373 mActionGroup->setAction( aFilter->action() );
374 mGlobalsBox->setEnabled( true );
375 mShowLaterBtn->setChecked(mFilterList->showLaterMsgs());
376 } else {
377 mActionLister->setActionList( aFilter->actions() );
378
379 mAdvOptsGroup->setEnabled( true );
380 }
381
382 mPatternEdit->setSearchPattern( aFilter->pattern() );
383 mFilter = aFilter;
384
385 if (!bPopFilter) {
386 kdDebug(5006) << "apply on inbound == "
387 << aFilter->applyOnInbound() << endl;
388 kdDebug(5006) << "apply on outbound == "
389 << aFilter->applyOnOutbound() << endl;
390 kdDebug(5006) << "apply on explicit == "
391 << aFilter->applyOnExplicit() << endl;
392
393 // NOTE: setting these values activates the slot that sets them in
394 // the filter! So make sure we have the correct values _before_ we
395 // set the first one:
396 const bool applyOnIn = aFilter->applyOnInbound();
397 const bool applyOnForAll = aFilter->applicability() == KMFilter::All;
398 const bool applyOnTraditional = aFilter->applicability() == KMFilter::ButImap;
399 const bool applyOnOut = aFilter->applyOnOutbound();
400 const bool applyOnExplicit = aFilter->applyOnExplicit();
401 const bool stopHere = aFilter->stopProcessingHere();
402 const bool configureShortcut = aFilter->configureShortcut();
403 const bool configureToolbar = aFilter->configureToolbar();
404 const TQString icon = aFilter->icon();
405 const TDEShortcut shortcut( aFilter->shortcut() );
406
407 mApplyOnIn->setChecked( applyOnIn );
408 mApplyOnForAll->setEnabled( applyOnIn );
409 mApplyOnForTraditional->setEnabled( applyOnIn );
410 mApplyOnForChecked->setEnabled( applyOnIn );
411 mApplyOnForAll->setChecked( applyOnForAll );
412 mApplyOnForTraditional->setChecked( applyOnTraditional );
413 mApplyOnForChecked->setChecked( !applyOnForAll && !applyOnTraditional );
414 mAccountList->setEnabled( mApplyOnForChecked->isEnabled() && mApplyOnForChecked->isChecked() );
415 slotUpdateAccountList();
416 mApplyOnOut->setChecked( applyOnOut );
417 mApplyOnCtrlJ->setChecked( applyOnExplicit );
418 mStopProcessingHere->setChecked( stopHere );
419 mConfigureShortcut->setChecked( configureShortcut );
420 mKeyButton->setShortcut( shortcut, false );
421 mConfigureToolbar->setChecked( configureToolbar );
422 mFilterActionIconButton->setIcon( icon );
423 }
424}
425
426void KMFilterDlg::slotReset()
427{
428 mFilter = 0;
430
431 if(bPopFilter) {
432 mActionGroup->reset();
433 mGlobalsBox->setEnabled( false );
434 } else {
435 mActionLister->reset();
436 mAdvOptsGroup->setEnabled( false );
437 slotUpdateAccountList();
438 }
439}
440
441void KMFilterDlg::slotUpdateFilter()
442{
444 if ( !bPopFilter ) {
445 mActionLister->updateActionList();
446 }
447}
448
449void KMFilterDlg::slotApplicabilityChanged()
450{
451 if ( mFilter ) {
452 mFilter->setApplyOnInbound( mApplyOnIn->isChecked() );
453 mFilter->setApplyOnOutbound( mApplyOnOut->isChecked() );
454 mFilter->setApplyOnExplicit( mApplyOnCtrlJ->isChecked() );
455 if ( mApplyOnForAll->isChecked() )
456 mFilter->setApplicability( KMFilter::All );
457 else if ( mApplyOnForTraditional->isChecked() )
458 mFilter->setApplicability( KMFilter::ButImap );
459 else if ( mApplyOnForChecked->isChecked() )
460 mFilter->setApplicability( KMFilter::Checked );
461
462 mApplyOnForAll->setEnabled( mApplyOnIn->isChecked() );
463 mApplyOnForTraditional->setEnabled( mApplyOnIn->isChecked() );
464 mApplyOnForChecked->setEnabled( mApplyOnIn->isChecked() );
465 mAccountList->setEnabled( mApplyOnForChecked->isEnabled() && mApplyOnForChecked->isChecked() );
466
467 // Advanced tab functionality - Update list of accounts this filter applies to
468 TQListViewItemIterator it( mAccountList );
469 while ( it.current() ) {
470 TQCheckListItem *item = dynamic_cast<TQCheckListItem*>( it.current() );
471 if (item) {
472 int id = item->text( 2 ).toInt();
473 item->setOn( mFilter->applyOnAccount( id ) );
474 }
475 ++it;
476 }
477
478 kdDebug(5006) << "KMFilterDlg: setting filter to be applied at "
479 << ( mFilter->applyOnInbound() ? "incoming " : "" )
480 << ( mFilter->applyOnOutbound() ? "outgoing " : "" )
481 << ( mFilter->applyOnExplicit() ? "explicit CTRL-J" : "" )
482 << endl;
483 }
484}
485
486void KMFilterDlg::slotApplicableAccountsChanged()
487{
488 if ( mFilter && mApplyOnForChecked->isEnabled() && mApplyOnForChecked->isChecked() ) {
489 // Advanced tab functionality - Update list of accounts this filter applies to
490 TQListViewItemIterator it( mAccountList );
491 while ( it.current() ) {
492 TQCheckListItem *item = dynamic_cast<TQCheckListItem*>( it.current() );
493 if (item) {
494 int id = item->text( 2 ).toInt();
495 mFilter->setApplyOnAccount( id, item->isOn() );
496 }
497 ++it;
498 }
499 }
500}
501
502void KMFilterDlg::slotStopProcessingButtonToggled( bool aChecked )
503{
504 if ( mFilter )
505 mFilter->setStopProcessingHere( aChecked );
506}
507
508void KMFilterDlg::slotConfigureShortcutButtonToggled( bool aChecked )
509{
510 if ( mFilter ) {
511 mFilter->setConfigureShortcut( aChecked );
512 mKeyButton->setEnabled( aChecked );
513 mConfigureToolbar->setEnabled( aChecked );
514 mFilterActionIconButton->setEnabled( aChecked );
515 mFilterActionLabel->setEnabled( aChecked );
516 }
517}
518
519void KMFilterDlg::slotCapturedShortcutChanged( const TDEShortcut& sc )
520{
521 TDEShortcut mySc(sc);
522 if ( mySc == mKeyButton->shortcut() ) return;
523 // FIXME work around a problem when reseting the shortcut via the shortcut dialog
524 // somehow the returned shortcut does not evaluate to true in TDEShortcut::isNull(),
525 // so we additionally have to check for an empty string
526 if ( mySc.isNull() || mySc.toString().isEmpty() )
527 mySc.clear();
528 if ( !mySc.isNull() && !( kmkernel->getKMMainWidget()->shortcutIsValid( mySc ) ) ) {
529 TQString msg( i18n( "The selected shortcut is already used, "
530 "please select a different one." ) );
531 KMessageBox::sorry( this, msg );
532 } else {
533 mKeyButton->setShortcut( mySc, false );
534 if ( mFilter )
535 mFilter->setShortcut( mKeyButton->shortcut() );
536 }
537}
538
539void KMFilterDlg::slotConfigureToolbarButtonToggled( bool aChecked )
540{
541 if ( mFilter )
542 mFilter->setConfigureToolbar( aChecked );
543}
544
545void KMFilterDlg::slotFilterActionIconChanged( TQString icon )
546{
547 if ( mFilter )
548 mFilter->setIcon( icon );
549}
550
551void KMFilterDlg::slotUpdateAccountList()
552{
553 mAccountList->clear();
554 TQListViewItem *top = 0;
555 for( KMAccount *a = kmkernel->acctMgr()->first(); a!=0;
556 a = kmkernel->acctMgr()->next() ) {
557 TQCheckListItem *listItem =
558 new TQCheckListItem( mAccountList, top, a->name(), TQCheckListItem::CheckBox );
559 listItem->setText( 1, a->type() );
560 listItem->setText( 2, TQString( "%1" ).arg( a->id() ) );
561 if ( mFilter )
562 listItem->setOn( mFilter->applyOnAccount( a->id() ) );
563 top = listItem;
564 }
565
566 TQListViewItem *listItem = mAccountList->firstChild();
567 if ( listItem ) {
568 mAccountList->setCurrentItem( listItem );
569 mAccountList->setSelected( listItem, true );
570 }
571}
572
573//=============================================================================
574//
575// class KMFilterListBox (the filter list manipulator)
576//
577//=============================================================================
578
579KMFilterListBox::KMFilterListBox( const TQString & title, TQWidget *parent, const char* name, bool popFilter )
580 : TQGroupBox( 1, TQt::Horizontal, title, parent, name ),
581 bPopFilter(popFilter)
582{
583 mFilterList.setAutoDelete( true );
584 mIdxSelItem = -1;
585
586 //----------- the list box
587 mListBox = new TQListBox(this);
588 mListBox->setMinimumWidth(150);
589 TQWhatsThis::add( mListBox, i18n(_wt_filterlist) );
590
591 //----------- the first row of buttons
592 TQHBox *hb = new TQHBox(this);
593 hb->setSpacing(4);
594 mBtnTop = new KPushButton( TQString(), hb );
595 mBtnTop->setAutoRepeat( true );
596 mBtnTop->setIconSet( BarIconSet( "go-top", TDEIcon::SizeSmall ) );
597 mBtnTop->setMinimumSize( mBtnTop->sizeHint() * 1.2 );
598 mBtnUp = new KPushButton( TQString(), hb );
599 mBtnUp->setAutoRepeat( true );
600 mBtnUp->setIconSet( BarIconSet( "go-up", TDEIcon::SizeSmall ) );
601 mBtnUp->setMinimumSize( mBtnUp->sizeHint() * 1.2 );
602 mBtnDown = new KPushButton( TQString(), hb );
603 mBtnDown->setAutoRepeat( true );
604 mBtnDown->setIconSet( BarIconSet( "go-down", TDEIcon::SizeSmall ) );
605 mBtnDown->setMinimumSize( mBtnDown->sizeHint() * 1.2 );
606 mBtnBot = new KPushButton( TQString(), hb );
607 mBtnBot->setAutoRepeat( true );
608 mBtnBot->setIconSet( BarIconSet( "go-bottom", TDEIcon::SizeSmall ) );
609 mBtnBot->setMinimumSize( mBtnBot->sizeHint() * 1.2 );
610 TQToolTip::add( mBtnTop, i18n("Top") );
611 TQToolTip::add( mBtnUp, i18n("Up") );
612 TQToolTip::add( mBtnDown, i18n("Down") );
613 TQToolTip::add( mBtnBot, i18n("Bottom") );
614 TQWhatsThis::add( mBtnTop, i18n(_wt_filterlist_top) );
615 TQWhatsThis::add( mBtnUp, i18n(_wt_filterlist_up) );
616 TQWhatsThis::add( mBtnDown, i18n(_wt_filterlist_down) );
617 TQWhatsThis::add( mBtnBot, i18n(_wt_filterlist_bot) );
618
619 //----------- the second row of buttons
620 hb = new TQHBox(this);
621 hb->setSpacing(4);
622 mBtnNew = new TQPushButton( TQString(), hb );
623 mBtnNew->setPixmap( BarIcon( "document-new", TDEIcon::SizeSmall ) );
624 mBtnNew->setMinimumSize( mBtnNew->sizeHint() * 1.2 );
625 mBtnCopy = new TQPushButton( TQString(), hb );
626 mBtnCopy->setIconSet( BarIconSet( "edit-copy", TDEIcon::SizeSmall ) );
627 mBtnCopy->setMinimumSize( mBtnCopy->sizeHint() * 1.2 );
628 mBtnDelete = new TQPushButton( TQString(), hb );
629 mBtnDelete->setIconSet( BarIconSet( "edit-delete", TDEIcon::SizeSmall ) );
630 mBtnDelete->setMinimumSize( mBtnDelete->sizeHint() * 1.2 );
631 mBtnRename = new TQPushButton( i18n("Rename..."), hb );
632 TQToolTip::add( mBtnNew, i18n("New") );
633 TQToolTip::add( mBtnCopy, i18n("Copy") );
634 TQToolTip::add( mBtnDelete, i18n("Delete"));
635 TQWhatsThis::add( mBtnNew, i18n(_wt_filterlist_new) );
636 TQWhatsThis::add( mBtnCopy, i18n(_wt_filterlist_copy) );
637 TQWhatsThis::add( mBtnDelete, i18n(_wt_filterlist_delete) );
638 TQWhatsThis::add( mBtnRename, i18n(_wt_filterlist_rename) );
639
640 // third row
641 if ( !popFilter ) {
642 hb = new TQHBox( this );
643 hb->setSpacing( 4 );
644 TQPushButton *btn = new TQPushButton( i18n("Select Source Folders"), hb );
645 connect( btn, TQ_SIGNAL(clicked()), TQ_SLOT(slotSelectSourceFolders()) );
646 }
647
648
649 //----------- now connect everything
650 connect( mListBox, TQ_SIGNAL(highlighted(int)),
651 this, TQ_SLOT(slotSelected(int)) );
652 connect( mListBox, TQ_SIGNAL( doubleClicked ( TQListBoxItem * )),
653 this, TQ_SLOT( slotRename()) );
654 connect( mBtnTop, TQ_SIGNAL(clicked()),
655 this, TQ_SLOT(slotTop()) );
656 connect( mBtnUp, TQ_SIGNAL(clicked()),
657 this, TQ_SLOT(slotUp()) );
658 connect( mBtnDown, TQ_SIGNAL(clicked()),
659 this, TQ_SLOT(slotDown()) );
660 connect( mBtnBot, TQ_SIGNAL(clicked()),
661 this, TQ_SLOT(slotBottom()) );
662 connect( mBtnNew, TQ_SIGNAL(clicked()),
663 this, TQ_SLOT(slotNew()) );
664 connect( mBtnCopy, TQ_SIGNAL(clicked()),
665 this, TQ_SLOT(slotCopy()) );
666 connect( mBtnDelete, TQ_SIGNAL(clicked()),
667 this, TQ_SLOT(slotDelete()) );
668 connect( mBtnRename, TQ_SIGNAL(clicked()),
669 this, TQ_SLOT(slotRename()) );
670
671 // the dialog should call loadFilterList()
672 // when all signals are connected.
673 enableControls();
674}
675
676
677void KMFilterListBox::createFilter( const TQCString & field,
678 const TQString & value )
679{
680 KMSearchRule *newRule = KMSearchRule::createInstance( field, KMSearchRule::FuncContains, value );
681
682 KMFilter *newFilter = new KMFilter(0, bPopFilter);
683 newFilter->pattern()->append( newRule );
684 newFilter->pattern()->setName( TQString("<%1>:%2").arg( TQString(field) ).arg( TQString(value) ) );
685
686 KMFilterActionDesc *desc = (*kmkernel->filterActionDict())["transfer"];
687 if ( desc )
688 newFilter->actions()->append( desc->create() );
689
690 insertFilter( newFilter );
691 enableControls();
692}
693
695{
696 return mShowLater;
697}
698
700{
701 KMSearchPattern *p = mFilterList.at(mIdxSelItem)->pattern();
702 if ( !p ) return;
703
704 TQString shouldBeName = p->name();
705 TQString displayedName = mListBox->text( mIdxSelItem );
706
707 if ( shouldBeName.stripWhiteSpace().isEmpty() ) {
708 mFilterList.at(mIdxSelItem)->setAutoNaming( true );
709 }
710
711 if ( mFilterList.at(mIdxSelItem)->isAutoNaming() ) {
712 // auto-naming of patterns
713 if ( !p->isEmpty() && p->first() && !p->first()->field().stripWhiteSpace().isEmpty() )
714 shouldBeName = TQString( "<%1>: %2" ).arg( TQString(p->first()->field()) ).arg( TQString(p->first()->contents()) );
715 else
716 shouldBeName = "<" + i18n("unnamed") + ">";
717 p->setName( shouldBeName );
718 }
719
720 if ( displayedName == shouldBeName ) return;
721
722 mListBox->blockSignals( true );
723 mListBox->changeItem( shouldBeName, mIdxSelItem );
724 mListBox->blockSignals( false );
725}
726
728{
729 mShowLater = aOn;
730}
731
733{
734 if ( mIdxSelItem >= 0 ) {
735 emit applyWidgets();
736 slotSelected( mListBox->currentItem() );
737 }
738
739 // by now all edit widgets should have written back
740 // their widget's data into our filter list.
741
742 KMFilterMgr *fm;
743 if (bPopFilter)
744 fm = kmkernel->popFilterMgr();
745 else
746 fm = kmkernel->filterMgr();
747
748 TQValueList<KMFilter*> newFilters = filtersForSaving();
749
750 if (bPopFilter)
751 fm->setShowLaterMsgs(mShowLater);
752
753 fm->setFilters( newFilters );
754 if (fm->atLeastOneOnlineImapFolderTarget()) {
755 TQString str = i18n("At least one filter targets a folder on an online "
756 "IMAP account. Such filters will only be applied "
757 "when manually filtering and when filtering "
758 "incoming online IMAP mail.");
759 KMessageBox::information( this, str, TQString(),
760 "filterDlgOnlineImapCheck" );
761 }
762}
763
764TQValueList<KMFilter*> KMFilterListBox::filtersForSaving() const
765{
766 const_cast<KMFilterListBox*>( this )->applyWidgets(); // signals aren't const
767 TQValueList<KMFilter*> filters;
768 TQStringList emptyFilters;
769 TQPtrListIterator<KMFilter> it( mFilterList );
770 for ( it.toFirst() ; it.current() ; ++it ) {
771 KMFilter *f = new KMFilter( **it ); // deep copy
772 f->purify();
773 if ( !f->isEmpty() )
774 // the filter is valid:
775 filters.append( f );
776 else {
777 // the filter is invalid:
778 emptyFilters << f->name();
779 delete f;
780 }
781 }
782
783 // report on invalid filters:
784 if ( !emptyFilters.empty() ) {
785 TQString msg = i18n("The following filters have not been saved because they "
786 "were invalid (e.g. containing no actions or no search "
787 "rules).");
788 KMessageBox::informationList( 0, msg, emptyFilters, TQString(),
789 "ShowInvalidFilterWarning" );
790 }
791 return filters;
792}
793
795{
796 mIdxSelItem = aIdx;
797 // TQPtrList::at(i) will return 0 if i is out of range.
798 KMFilter *f = mFilterList.at(aIdx);
799 if ( f )
800 emit filterSelected( f );
801 else
802 emit resetWidgets();
803 enableControls();
804}
805
807{
808 // just insert a new filter.
809 insertFilter( new KMFilter(0, bPopFilter) );
810 enableControls();
811}
812
814{
815 if ( mIdxSelItem < 0 ) {
816 kdDebug(5006) << "KMFilterListBox::slotCopy called while no filter is selected, ignoring." << endl;
817 return;
818 }
819
820 // make sure that all changes are written to the filter before we copy it
821 emit applyWidgets();
822
823 KMFilter *filter = mFilterList.at( mIdxSelItem );
824
825 // enableControls should make sure this method is
826 // never called when no filter is selected.
827 assert( filter );
828
829 // inserts a copy of the current filter.
830 insertFilter( new KMFilter( *filter ) );
831 enableControls();
832}
833
835{
836 if ( mIdxSelItem < 0 ) {
837 kdDebug(5006) << "KMFilterListBox::slotDelete called while no filter is selected, ignoring." << endl;
838 return;
839 }
840
841 int oIdxSelItem = mIdxSelItem;
842 mIdxSelItem = -1;
843 // unselect all
844 mListBox->selectAll( false );
845 // broadcast that all widgets let go
846 // of the filter
847 emit resetWidgets();
848
849 // remove the filter from both the filter list...
850 mFilterList.remove( oIdxSelItem );
851 // and the listbox
852 mListBox->removeItem( oIdxSelItem );
853
854 int count = (int)mListBox->count();
855 // and set the new current item.
856 if ( count > oIdxSelItem )
857 // oIdxItem is still a valid index
858 mListBox->setSelected( oIdxSelItem, true );
859 else if ( count )
860 // oIdxSelIdx is no longer valid, but the
861 // list box isn't empty
862 mListBox->setSelected( count - 1, true );
863 // the list is empty - keep index -1
864
865 enableControls();
866}
867
869{
870 if ( mIdxSelItem < 0 ) {
871 kdDebug(5006) << "KMFilterListBox::slotTop called while no filter is selected, ignoring." << endl;
872 return;
873 }
874 if ( mIdxSelItem == 0 ) {
875 kdDebug(5006) << "KMFilterListBox::slotTop called while the _topmost_ filter is selected, ignoring." << endl;
876 return;
877 }
878
879 swapFilters( mIdxSelItem, 0 );
880 enableControls();
881}
882
884{
885 if ( mIdxSelItem < 0 ) {
886 kdDebug(5006) << "KMFilterListBox::slotUp called while no filter is selected, ignoring." << endl;
887 return;
888 }
889 if ( mIdxSelItem == 0 ) {
890 kdDebug(5006) << "KMFilterListBox::slotUp called while the _topmost_ filter is selected, ignoring." << endl;
891 return;
892 }
893
894 swapNeighbouringFilters( mIdxSelItem, mIdxSelItem - 1 );
895 enableControls();
896}
897
899{
900 if ( mIdxSelItem < 0 ) {
901 kdDebug(5006) << "KMFilterListBox::slotDown called while no filter is selected, ignoring." << endl;
902 return;
903 }
904 if ( mIdxSelItem == (int)mListBox->count() - 1 ) {
905 kdDebug(5006) << "KMFilterListBox::slotDown called while the _last_ filter is selected, ignoring." << endl;
906 return;
907 }
908
909 swapNeighbouringFilters( mIdxSelItem, mIdxSelItem + 1);
910 enableControls();
911}
912
914{
915 if ( mIdxSelItem < 0 ) {
916 kdDebug(5006) << "KMFilterListBox::slotBottom called while no filter is selected, ignoring." << endl;
917 return;
918 }
919 if ( mIdxSelItem == (int)mListBox->count() - 1 ) {
920 kdDebug(5006) << "KMFilterListBox::slotBottom called while the _last_ filter is selected, ignoring." << endl;
921 return;
922 }
923
924 swapFilters( mIdxSelItem, mListBox->count()-1 );
925 enableControls();
926}
927
929{
930 if ( mIdxSelItem < 0 ) {
931 kdDebug(5006) << "KMFilterListBox::slotRename called while no filter is selected, ignoring." << endl;
932 return;
933 }
934
935 bool okPressed = false ;
936 KMFilter *filter = mFilterList.at( mIdxSelItem );
937
938 // enableControls should make sure this method is
939 // never called when no filter is selected.
940 assert( filter );
941
942 // allow empty names - those will turn auto-naming on again
943 TQValidator *validator = new TQRegExpValidator( TQRegExp( ".*" ), 0 );
944 TQString newName = KInputDialog::getText
945 (
946 i18n("Rename Filter"),
947 i18n("Rename filter \"%1\" to:\n(leave the field empty for automatic naming)")
948 .arg( filter->pattern()->name() ) /*label*/,
949 filter->pattern()->name() /* initial value */,
950 &okPressed, topLevelWidget(), 0, validator
951 );
952 delete validator;
953
954 if ( !okPressed ) return;
955
956 if ( newName.isEmpty() ) {
957 // bait for slotUpdateFilterName to
958 // use automatic naming again.
959 filter->pattern()->setName( "<>" );
960 filter->setAutoNaming( true );
961 } else {
962 filter->pattern()->setName( newName );
963 filter->setAutoNaming( false );
964 }
965
967}
968
969void KMFilterListBox::slotSelectSourceFolders()
970{
971 FolderSetSelector dlg( kmkernel->getKMMainWidget()->folderTree(), this );
972 dlg.setCaption( i18n( "Select Folders to Filter" ) );
973 if ( !GlobalSettings::filterSourceFolders().isEmpty() )
974 dlg.setSelectedFolders( GlobalSettings::filterSourceFolders() );
975 if ( dlg.exec() == TQDialog::Accepted ) {
976 GlobalSettings::setFilterSourceFolders( dlg.selectedFolders() );
977 }
978}
979
980void KMFilterListBox::enableControls()
981{
982 bool theFirst = ( mIdxSelItem == 0 );
983 bool theLast = ( mIdxSelItem >= (int)mFilterList.count() - 1 );
984 bool aFilterIsSelected = ( mIdxSelItem >= 0 );
985
986 mBtnTop->setEnabled( aFilterIsSelected && !theFirst );
987 mBtnUp->setEnabled( aFilterIsSelected && !theFirst );
988 mBtnDown->setEnabled( aFilterIsSelected && !theLast );
989 mBtnBot->setEnabled( aFilterIsSelected && !theLast );
990 mBtnCopy->setEnabled( aFilterIsSelected );
991 mBtnDelete->setEnabled( aFilterIsSelected );
992 mBtnRename->setEnabled( aFilterIsSelected );
993
994 if ( aFilterIsSelected )
995 mListBox->ensureCurrentVisible();
996}
997
998void KMFilterListBox::loadFilterList( bool createDummyFilter )
999{
1000 assert(mListBox);
1001 setEnabled( false );
1002 emit resetWidgets();
1003 // we don't want the insertion to
1004 // cause flicker in the edit widgets.
1005 blockSignals( true );
1006
1007 // clear both lists
1008 mFilterList.clear();
1009 mListBox->clear();
1010
1011 const KMFilterMgr *manager = 0;
1012 if(bPopFilter)
1013 {
1014 mShowLater = kmkernel->popFilterMgr()->showLaterMsgs();
1015 manager = kmkernel->popFilterMgr();
1016 }
1017 else
1018 {
1019 manager = kmkernel->filterMgr();
1020 }
1021 Q_ASSERT( manager );
1022
1023 TQValueListConstIterator<KMFilter*> it;
1024 for ( it = manager->filters().constBegin() ; it != manager->filters().constEnd() ; ++it ) {
1025 mFilterList.append( new KMFilter( **it ) ); // deep copy
1026 mListBox->insertItem( (*it)->pattern()->name() );
1027 }
1028
1029 blockSignals( false );
1030 setEnabled( true );
1031
1032 // create an empty filter when there's none, to avoid a completely
1033 // disabled dialog (usability tests indicated that the new-filter
1034 // button is too hard to find that way):
1035 if ( !mListBox->count() && createDummyFilter )
1036 slotNew();
1037
1038 if ( mListBox->count() > 0 )
1039 mListBox->setSelected( 0, true );
1040
1041 enableControls();
1042}
1043
1044void KMFilterListBox::insertFilter( KMFilter* aFilter )
1045{
1046 // must be really a filter...
1047 assert( aFilter );
1048
1049 // if mIdxSelItem < 0, TQListBox::insertItem will append.
1050 mListBox->insertItem( aFilter->pattern()->name(), mIdxSelItem );
1051 if ( mIdxSelItem < 0 ) {
1052 // none selected -> append
1053 mFilterList.append( aFilter );
1054 mListBox->setSelected( mListBox->count() - 1, true );
1055 // slotSelected( mListBox->count() - 1 );
1056 } else {
1057 // insert just before selected
1058 mFilterList.insert( mIdxSelItem, aFilter );
1059 mListBox->setSelected( mIdxSelItem, true );
1060 // slotSelected( mIdxSelItem );
1061 }
1062
1063}
1064
1065void KMFilterListBox::appendFilter( KMFilter* aFilter )
1066{
1067 mFilterList.append( aFilter );
1068 mListBox->insertItem( aFilter->pattern()->name(), -1 );
1069}
1070
1071void KMFilterListBox::swapNeighbouringFilters( int untouchedOne, int movedOne )
1072{
1073 // must be neighbours...
1074 assert( untouchedOne - movedOne == 1 || movedOne - untouchedOne == 1 );
1075
1076 // untouchedOne is at idx. to move it down(up),
1077 // remove item at idx+(-)1 w/o deleting it.
1078 TQListBoxItem *item = mListBox->item( movedOne );
1079 mListBox->takeItem( item );
1080 // now selected item is at idx(idx-1), so
1081 // insert the other item at idx, ie. above(below).
1082 mListBox->insertItem( item, untouchedOne );
1083
1084 KMFilter* filter = mFilterList.take( movedOne );
1085 mFilterList.insert( untouchedOne, filter );
1086
1087 mIdxSelItem += movedOne - untouchedOne;
1088}
1089
1090void KMFilterListBox::swapFilters( int from, int to )
1091{
1092 TQListBoxItem *item = mListBox->item( from );
1093 mListBox->takeItem( item );
1094 mListBox->insertItem( item, to );
1095
1096 KMFilter* filter = mFilterList.take( from );
1097 mFilterList.insert( to, filter );
1098
1099 mIdxSelItem = to;
1100 mListBox->setCurrentItem( mIdxSelItem );
1101 mListBox->setSelected( mIdxSelItem, true );
1102}
1103
1104//=============================================================================
1105//
1106// class KMFilterActionWidget
1107//
1108//=============================================================================
1109
1110KMFilterActionWidget::KMFilterActionWidget( TQWidget *parent, const char* name )
1111 : TQHBox( parent, name )
1112{
1113 int i;
1114 mActionList.setAutoDelete( true );
1115
1116 mComboBox = new TQComboBox( false , this );
1117 assert( mComboBox );
1118 mWidgetStack = new TQWidgetStack(this);
1119 assert( mWidgetStack );
1120
1121 setSpacing( 4 );
1122
1123 TQPtrListIterator<KMFilterActionDesc> it ( kmkernel->filterActionDict()->list() );
1124 for ( i=0, it.toFirst() ; it.current() ; ++it, ++i ) {
1125 //create an instance:
1126 KMFilterAction *a = (*it)->create();
1127 // append to the list of actions:
1128 mActionList.append( a );
1129 // add parameter widget to widget stack:
1130 mWidgetStack->addWidget( a->createParamWidget( mWidgetStack ), i );
1131 // add (i18n-ized) name to combo box
1132 mComboBox->insertItem( (*it)->label );
1133 }
1134 // widget for the case where no action is selected.
1135 mWidgetStack->addWidget( new TQLabel( i18n("Please select an action."), mWidgetStack ), i );
1136 mWidgetStack->raiseWidget(i);
1137 mComboBox->insertItem( " " );
1138 mComboBox->setCurrentItem(i);
1139
1140 // don't show scroll bars.
1141 mComboBox->setSizeLimit( mComboBox->count() );
1142 // layout management:
1143 // o the combo box is not to be made larger than it's sizeHint(),
1144 // the parameter widget should grow instead.
1145 // o the whole widget takes all space horizontally, but is fixed vertically.
1146 mComboBox->adjustSize();
1147 mComboBox->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
1148 setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Fixed ) );
1149 updateGeometry();
1150
1151 // redirect focus to the filter action combo box
1152 setFocusProxy( mComboBox );
1153
1154 // now connect the combo box and the widget stack
1155 connect( mComboBox, TQ_SIGNAL(activated(int)),
1156 mWidgetStack, TQ_SLOT(raiseWidget(int)) );
1157}
1158
1160{
1161 int i=0;
1162 bool found = false ;
1163 int count = mComboBox->count() - 1 ; // last entry is the empty one
1164 TQString label = ( aAction ) ? aAction->label() : TQString() ;
1165
1166 // find the index of typeOf(aAction) in mComboBox
1167 // and clear the other widgets on the way.
1168 for ( ; i < count ; i++ )
1169 if ( aAction && mComboBox->text(i) == label ) {
1170 //...set the parameter widget to the settings
1171 // of aAction...
1172 aAction->setParamWidgetValue( mWidgetStack->widget(i) );
1173 //...and show the correct entry of
1174 // the combo box
1175 mComboBox->setCurrentItem(i); // (mm) also raise the widget, but doesn't
1176 mWidgetStack->raiseWidget(i);
1177 found = true;
1178 } else // clear the parameter widget
1179 mActionList.at(i)->clearParamWidget( mWidgetStack->widget(i) );
1180 if ( found ) return;
1181
1182 // not found, so set the empty widget
1183 mComboBox->setCurrentItem( count ); // last item
1184 mWidgetStack->raiseWidget( count) ;
1185}
1186
1188{
1189 // look up the action description via the label
1190 // returned by TQComboBox::currentText()...
1191 KMFilterActionDesc *desc = (*kmkernel->filterActionDict())[ mComboBox->currentText() ];
1192 if ( desc ) {
1193 // ...create an instance...
1194 KMFilterAction *fa = desc->create();
1195 if ( fa ) {
1196 // ...and apply the setting of the parameter widget.
1197 fa->applyParamWidgetValue( mWidgetStack->visibleWidget() );
1198 return fa;
1199 }
1200 }
1201
1202 return 0;
1203}
1204
1205//=============================================================================
1206//
1207// class KMFilterActionWidgetLister (the filter action editor)
1208//
1209//=============================================================================
1210
1211KMFilterActionWidgetLister::KMFilterActionWidgetLister( TQWidget *parent, const char* name )
1212 : KWidgetLister( 1, FILTER_MAX_ACTIONS, parent, name )
1213{
1214 mActionList = 0;
1215}
1216
1217KMFilterActionWidgetLister::~KMFilterActionWidgetLister()
1218{
1219}
1220
1221void KMFilterActionWidgetLister::setActionList( TQPtrList<KMFilterAction> *aList )
1222{
1223 assert ( aList );
1224
1225 if ( mActionList )
1226 regenerateActionListFromWidgets();
1227
1228 mActionList = aList;
1229
1230 ((TQWidget*)parent())->setEnabled( true );
1231
1232 if ( aList->count() == 0 ) {
1233 slotClear();
1234 return;
1235 }
1236
1237 int superfluousItems = (int)mActionList->count() - mMaxWidgets ;
1238 if ( superfluousItems > 0 ) {
1239 kdDebug(5006) << "KMFilterActionWidgetLister: Clipping action list to "
1240 << mMaxWidgets << " items!" << endl;
1241
1242 for ( ; superfluousItems ; superfluousItems-- )
1243 mActionList->removeLast();
1244 }
1245
1246 // set the right number of widgets
1247 setNumberOfShownWidgetsTo( mActionList->count() );
1248
1249 // load the actions into the widgets
1250 TQPtrListIterator<KMFilterAction> aIt( *mActionList );
1251 TQPtrListIterator<TQWidget> wIt( mWidgetList );
1252 for ( aIt.toFirst(), wIt.toFirst() ;
1253 aIt.current() && wIt.current() ; ++aIt, ++wIt )
1254 ((KMFilterActionWidget*)(*wIt))->setAction( (*aIt) );
1255}
1256
1257void KMFilterActionWidgetLister::reset()
1258{
1259 if ( mActionList )
1260 regenerateActionListFromWidgets();
1261
1262 mActionList = 0;
1263 slotClear();
1264 ((TQWidget*)parent())->setEnabled( false );
1265}
1266
1267TQWidget* KMFilterActionWidgetLister::createWidget( TQWidget *parent )
1268{
1269 return new KMFilterActionWidget(parent);
1270}
1271
1272void KMFilterActionWidgetLister::clearWidget( TQWidget *aWidget )
1273{
1274 if ( aWidget )
1275 ((KMFilterActionWidget*)aWidget)->setAction(0);
1276}
1277
1278void KMFilterActionWidgetLister::regenerateActionListFromWidgets()
1279{
1280 if ( !mActionList ) return;
1281
1282 mActionList->clear();
1283
1284 TQPtrListIterator<TQWidget> it( mWidgetList );
1285 for ( it.toFirst() ; it.current() ; ++it ) {
1286 KMFilterAction *a = ((KMFilterActionWidget*)(*it))->action();
1287 if ( a )
1288 mActionList->append( a );
1289 }
1290
1291}
1292
1293//=============================================================================
1294//
1295// class KMPopFilterActionWidget
1296//
1297//=============================================================================
1298
1299KMPopFilterActionWidget::KMPopFilterActionWidget( const TQString& title, TQWidget *parent, const char* name )
1300 : TQVButtonGroup( title, parent, name )
1301{
1302 mActionMap[Down] = new TQRadioButton( i18n("&Download mail"), this );
1303 mActionMap[Later] = new TQRadioButton( i18n("Download mail la&ter"), this );
1304 mActionMap[Delete] = new TQRadioButton( i18n("D&elete mail from server"), this );
1305 mIdMap[id(mActionMap[Later])] = Later;
1306 mIdMap[id(mActionMap[Down])] = Down;
1307 mIdMap[id(mActionMap[Delete])] = Delete;
1308
1309 connect( this, TQ_SIGNAL(clicked(int)),
1310 this, TQ_SLOT( slotActionClicked(int)) );
1311}
1312
1313void KMPopFilterActionWidget::setAction( KMPopFilterAction aAction )
1314{
1315 if( aAction == NoAction)
1316 {
1317 aAction = Later;
1318 }
1319
1320 mAction = aAction;
1321
1322 blockSignals( true );
1323 if(!mActionMap[aAction]->isChecked())
1324 {
1325 mActionMap[aAction]->setChecked( true );
1326 }
1327 blockSignals( false );
1328
1329 setEnabled( true );
1330}
1331
1332KMPopFilterAction KMPopFilterActionWidget::action()
1333{
1334 return mAction;
1335}
1336
1337void KMPopFilterActionWidget::slotActionClicked(int aId)
1338{
1339 emit actionChanged(mIdMap[aId]);
1340 setAction(mIdMap[aId]);
1341}
1342
1343void KMPopFilterActionWidget::reset()
1344{
1345 blockSignals( true );
1346 mActionMap[Down]->setChecked( true );
1347 blockSignals( false );
1348
1349 setEnabled( false );
1350}
1351
1353{
1354 FilterImporterExporter importer( this, bPopFilter );
1355 TQValueList<KMFilter*> filters = importer.importFilters();
1356 // FIXME message box how many were imported?
1357 if (filters.isEmpty()) return;
1358
1359 TQValueListConstIterator<KMFilter*> it;
1360
1361 for ( it = filters.constBegin() ; it != filters.constEnd() ; ++it ) {
1362 mFilterList->appendFilter( *it ); // no need to deep copy, ownership passes to the list
1363 }
1364}
1365
1367{
1368 FilterImporterExporter exporter( this, bPopFilter );
1369 TQValueList<KMFilter*> filters = mFilterList->filtersForSaving();
1370 exporter.exportFilters( filters );
1371 TQValueList<KMFilter*>::iterator it;
1372 for ( it = filters.begin(); it != filters.end(); ++it )
1373 delete *it;
1374}
1375
1376#include "kmfilterdlg.moc"
This widgets allows to edit a single KMFilterAction (in fact any derived class that is registered in ...
Definition: kmfilterdlg.h:197
void setAction(const KMFilterAction *aAction)
Set an action.
KMFilterAction * action()
Retrieve the action.
KMFilterActionWidget(TQWidget *parent=0, const char *name=0)
Constructor.
Abstract base class for KMail's filter actions.
virtual TQWidget * createParamWidget(TQWidget *parent) const
Creates a widget for setting the filter action parameter.
virtual void setParamWidgetValue(TQWidget *paramWidget) const
The filter action shall set it's widget's contents from it's parameter.
virtual void applyParamWidgetValue(TQWidget *paramWidget)
The filter action shall set it's parameter from the widget's contents.
const TQString label() const
Returns nationalized label, ie.
KMFilterDlg(TQWidget *parent=0, const char *name=0, bool popFilter=false, bool createDummyFilter=true)
Create the filter dialog.
KMPopFilterActionWidget * mActionGroup
The widget that allows editing the popFilter actions.
Definition: kmfilterdlg.h:403
TDEListView * mAccountList
ListView that shows the accounts in the advanced tab.
Definition: kmfilterdlg.h:411
void slotExportFilters()
Called when a user clicks the export filters button.
void slotFilterSelected(KMFilter *aFilter)
Internally connected to KMFilterListBox::filterSelected.
TQRadioButton * mApplyOnForAll
For a filter applied to inbound messages selects whether to apply this filter to all accounts or to s...
Definition: kmfilterdlg.h:409
KMFilterActionWidgetLister * mActionLister
The widget that allows editing of the filter actions.
Definition: kmfilterdlg.h:401
void slotImportFilters()
Called when a user clicks the import filters button.
KMFilterListBox * mFilterList
The widget that contains the ListBox showing the filters, and the controls to remove filters,...
Definition: kmfilterdlg.h:397
KMSearchPatternEdit * mPatternEdit
The widget that allows editing of the filter pattern.
Definition: kmfilterdlg.h:399
void slotActionChanged(const KMPopFilterAction aAction)
Action for popFilter.
TQCheckBox * mApplyOnIn
Lets the user select whether to apply this filter on inbound/outbound messages, both,...
Definition: kmfilterdlg.h:406
This is a complex widget that is used to manipulate KMail's filter list.
Definition: kmfilterdlg.h:61
TQListBox * mListBox
The listbox displaying the filter list.
Definition: kmfilterdlg.h:159
void slotTop()
Called when the user clicks the 'Top' button.
KMFilterListBox(const TQString &title, TQWidget *parent=0, const char *name=0, bool popFilter=false)
Constuctor.
TQPushButton * mBtnNew
The various action buttons.
Definition: kmfilterdlg.h:161
void slotBottom()
Called when the user clicks the 'Bottom' button.
void applyWidgets()
Emitted when this widget wants the edit widgets to apply the changes to the current filter.
void loadFilterList(bool createDummyFilter)
Loads the filter list and selects the first filter.
void slotSelected(int aIdx)
Called when the user clicks on a filter in the filter list.
bool showLaterMsgs()
Returns wheather the global option 'Show Later Msgs' is set or not.
void slotRename()
Called when the user clicks the 'Rename' button.
TQPtrList< KMFilter > mFilterList
The deep copy of the filter list.
Definition: kmfilterdlg.h:157
void slotApplyFilterChanges()
Called when the user clicks either 'Apply' or 'OK' in KMFilterDlg.
void slotUp()
Called when the user clicks the 'Up' button.
TQValueList< KMFilter * > filtersForSaving() const
Returns a list of copies of the current list of filters.
void resetWidgets()
Emitted when this widget wants the edit widgets to let go of their filter reference.
void slotDown()
Called when the user clicks the 'Down' button.
void slotUpdateFilterName()
Called when the name of a filter might have changed (e.g.
void slotCopy()
Called when the user clicks the 'Copy' button.
void filterSelected(KMFilter *filter)
Emitted when a new filter has been selected by the user or if the current filter has changed after a ...
void slotNew()
Called when the user clicks the 'New' button.
int mIdxSelItem
The index of the currently selected item.
Definition: kmfilterdlg.h:164
void createFilter(const TQCString &field, const TQString &value)
Called from KMFilterDlg.
void slotDelete()
Called when the user clicks the 'Delete' button.
void slotShowLaterToggled(bool aOn)
Called when the user toggles the 'Show Download Later Msgs' Checkbox in the Global Options section.
This widget is intended to be used in the filter configuration as well as in the message search dialo...
void updateSearchPattern()
Updates the search pattern according to the current widget values.
void reset()
Called when the widget should let go of the currently referenced filter and disable itself.
void setSearchPattern(KMSearchPattern *aPattern)
Set the search pattern.
This class is an abstraction of a search over messages.
void setName(const TQString &newName)
Set the name of the search pattern.
TQString name() const
Get the name of the search pattern.
Incoming mail is sent through the list of mail filter rules before it is placed in the associated mai...
static KMSearchRule * createInstance(const TQCString &field=0, Function function=FuncContains, const TQString &contents=TQString())
Create a search rule of a certain type by instantiating the appro- priate subclass depending on the f...
The account manager is responsible for creating accounts of various types via the factory method crea...
Utility class that provides persisting of filters to/from TDEConfig.
TQValueList< KMFilter * > importFilters()
Import filters.
void exportFilters(const TQValueList< KMFilter * > &)
Export the given filter rules to a file which is asked from the user.
folderdiaquotatab.h
Definition: aboutdata.cpp:40
Auxiliary struct to KMFilterActionDict.