krop's commit fixes my problem in a better way, reverting
[kdepim.git] / kmail / kmfilterdlg.h
blob254b25dcd6303dae9966cb8132754a4e5a7540dc
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 #ifndef kmfilterdlg_h
22 #define kmfilterdlg_h
24 #include "kmfilter.h"
25 #include "kmfilteraction.h"
27 #include <kwidgetlister.h>
28 #include <kdialog.h>
29 #include <kvbox.h>
31 #include <QGroupBox>
32 #include <QList>
33 #include <QMap>
34 #include <QRadioButton>
35 #include <QString>
36 #include <QGridLayout>
38 class KMSearchPatternEdit;
39 class QLabel;
40 class QListWidget;
41 class QPushButton;
42 class QCheckBox;
43 class QTreeWidget;
44 class KComboBox;
45 class KIconButton;
46 class KKeySequenceWidget;
49 /** This is a complex widget that is used to manipulate KMail's filter
50 list. It consists of an internal list of filters, which is a deep
51 copy of the list KMFilterMgr manages, a QListBox displaying that list,
52 and a few buttons used to create new filters, delete them, rename them
53 and change the order of filters.
55 It does not provide means to change the actual filter (besides the
56 name), but relies on auxiliary widgets (KMSearchPatternEdit
57 and KMFilterActionEdit) to do that.
59 Communication with this widget is quite easy: simply create an
60 instance, connect the signals filterSelected, resetWidgets
61 and applyWidgets with a slot that does the right thing and there
62 you go...
64 This widget will operate on it's own copy of the filter list as
65 long as you don't call slotApplyFilterChanges. It will then
66 transfer the altered filter list back to KMFilterMgr.
68 @short A complex widget that allows managing a list of KMFilter's.
69 @author Marc Mutz <Marc@Mutz.com>, based upon work by Stefan Taferner <taferner@kde.org>.
70 @see KMFilter KMFilterDlg KMFilterActionEdit KMSearchPatternEdit
73 class KMFilterListBox : public QGroupBox
75 Q_OBJECT
76 public:
77 /** Constructor. */
78 explicit KMFilterListBox( const QString & title, QWidget* parent=0, const char* name=0, bool popFilter = false);
80 /** Destructor. */
81 ~KMFilterListBox();
83 /** Called from KMFilterDlg. Creates a new filter and presets
84 the first rule with "field equals value". It's there mainly to
85 support "rapid filter creation" from a context menu. You should
86 instead call KMFilterMgr::createFilter.
87 @see KMFilterMgr::createFilter KMFilterDlg::createFilter
89 void createFilter( const QByteArray & field, const QString & value );
91 /** Loads the filter list and selects the first filter. Should be
92 called when all signals are connected properly. If createDummyFilter
93 is true, an empty filter is created to improve the usability of the
94 dialog in case no filter has been defined so far.*/
95 void loadFilterList( bool createDummyFilter );
97 /** Returns wheather the global option 'Show Later Msgs' is set or not */
98 bool showLaterMsgs();
100 void insertFilter( KMFilter* aFilter );
102 void appendFilter( KMFilter* aFilter );
104 /** Returns a list of _copies_ of the current list of filters.
105 * The list owns the contents and thus the caller needs to clean them up.
106 * @param closeAfterSaving If true user is given option to continue editing
107 * after being warned about invalid filters. Otherwise, user is just warned. */
108 QList<KMFilter *> filtersForSaving( bool closeAfterSaving ) const;
110 signals:
111 /** Emitted when a new filter has been selected by the user or if
112 the current filter has changed after a 'new' or 'delete'
113 operation. */
114 void filterSelected( KMFilter* filter );
116 /** Emitted when this widget wants the edit widgets to let go of
117 their filter reference. Everyone holding a reference to a filter
118 should update it from the contents of the widgets used to edit
119 it and set their internal reference to 0. */
120 void resetWidgets();
122 /** Emitted when this widget wants the edit widgets to apply the changes
123 to the current filter. */
124 void applyWidgets();
126 /** Emitted when the user decides to continue editing after being warned
127 * about invalid filters. */
128 void abortClosing() const;
130 public slots:
131 /** Called when the name of a filter might have changed (e.g.
132 through changing the first rule in KMSearchPatternEdit).
133 Updates the corresponding entry in the
134 listbox and (if necessary) auto-names the filter. */
135 void slotUpdateFilterName();
136 /** Called when the user clicks either 'Apply' or 'OK' in
137 KMFilterDlg. Updates the filter list in the KMFilterMgr. */
138 void slotApplyFilterChanges( KDialog::ButtonCode );
139 /** Called when the user toggles the 'Show Download Later Msgs'
140 Checkbox in the Global Options section */
141 void slotShowLaterToggled(bool aOn);
143 protected slots:
144 /** Called when the user clicks on a filter in the filter
145 list. Calculates the corresponding filter and emits the
146 filterSelected signal. */
147 void slotSelected( int aIdx );
148 /** Called when the user clicks the 'New' button. Creates a new
149 empty filter just before the current one. */
150 void slotNew();
151 /** Called when the user clicks the 'Copy' button. Creates a copy
152 of the current filter and inserts it just before the current one. */
153 void slotCopy();
154 /** Called when the user clicks the 'Delete' button. Deletes the
155 current filter. */
156 void slotDelete();
157 /** Called when the user clicks the 'Up' button. Moves the current
158 filter up one line. */
159 void slotUp();
160 /** Called when the user clicks the 'Down' button. Moves the current
161 filter down one line. */
162 void slotDown();
163 /** Called when the user clicks the 'Rename' button. Pops up a
164 dialog prompting to enter the new name. */
165 void slotRename();
167 protected:
168 /** The deep copy of the filter list. */
169 QList<KMFilter *> mFilterList;
170 /** The listbox displaying the filter list. */
171 QListWidget *mListWidget;
172 /** The various action buttons. */
173 QPushButton *mBtnNew, *mBtnCopy, *mBtnDelete, *mBtnUp, *mBtnDown, *mBtnRename;
174 /** The index of the currently selected item. */
175 int mIdxSelItem;
176 bool mShowLater;
177 private:
178 void enableControls();
180 void swapNeighbouringFilters( int untouchedOne, int movedOne);
181 bool bPopFilter;
185 /** This widgets allows to edit a single KMFilterAction (in fact
186 any derived class that is registered in
187 KMFilterActionDict). It consists of a combo box which allows to
188 select the type of actions this widget should act upon.
190 You can load a KMFilterAction into this widget with setAction,
191 and retrieve the result of user action with action.
192 The widget will copy it's setting into the corresponding
193 parameter widget. For that, it internally creates an instance of
194 every KMFilterAction in KMFilterActionDict and asks each
195 one to create a parameter widget.
197 @short A widget to edit a single KMFilterAction.
198 @author Marc Mutz <Marc@Mutz.com>
199 @see KMFilterAction KMFilter KMFilterActionWidgetLister
202 class KMFilterActionWidget : public KHBox
204 Q_OBJECT
205 public:
206 /** Constructor. Creates a filter action widget with no type
207 selected. */
208 explicit KMFilterActionWidget( QWidget* parent=0, const char* name=0 );
210 /** Destructor. Clears mActionList. */
211 ~KMFilterActionWidget();
213 /** Set an action. The action's type is determined and the
214 corresponding widget it loaded with @p aAction's parameters and
215 then raised. If @ aAction is 0, the widget is cleared. */
216 void setAction( const KMFilterAction * aAction );
217 /** Retrieve the action. This method is necessary because the type
218 of actions can change during editing. Therefore the widget
219 always creates a new action object from the data in the combo
220 box and returns that. */
221 KMFilterAction *action() const;
223 private slots:
224 void slotFilterTypeChanged( int newIdx );
226 private:
227 /** This list holds an instance of every KMFilterAction
228 subclass. The only reason that these 'slave' actions exist is
229 that they are 'forced' to create parameter widgets
230 and to clear them on setAction. */
231 QList<KMFilterAction*> mActionList;
232 /** The combo box that contains the labels of all KMFilterActions.
233 It's @p activated(int) signal is internally
234 connected to the @p slotCboAction(int) slot of @p KMFilterActionWidget. */
235 KComboBox *mComboBox;
237 void setFilterAction( QWidget* w=0 );
238 QGridLayout *gl;
241 class KMPopFilterActionWidget : public QGroupBox
243 Q_OBJECT
244 public:
245 explicit KMPopFilterActionWidget( const QString & title,
246 QWidget * parent = 0,
247 const char * name = 0 );
248 void setAction( KMPopFilterAction aAction );
249 KMPopFilterAction action();
251 public slots:
252 void reset();
254 private slots:
255 void slotActionClicked( QAbstractButton *btn );
257 private:
258 KMPopFilterAction mAction;
259 KMFilter mFilter;
260 QMap<KMPopFilterAction, QRadioButton*> mActionMap;
261 QMap<QAbstractButton*, KMPopFilterAction> mButtonMap;
263 signals: // Signals
264 void actionChanged( const KMPopFilterAction aAction );
267 class KMFilterActionWidgetLister : public KPIM::KWidgetLister
269 Q_OBJECT
270 public:
271 explicit KMFilterActionWidgetLister( QWidget *parent=0, const char* name=0 );
273 virtual ~KMFilterActionWidgetLister();
275 void setActionList( QList<KMFilterAction*> * aList );
277 /** Updates the action list according to the current widget values */
278 void updateActionList() { regenerateActionListFromWidgets(); }
280 public slots:
281 void reset();
283 protected:
284 virtual void clearWidget( QWidget *aWidget );
285 virtual QWidget* createWidget( QWidget *parent );
287 private:
288 void regenerateActionListFromWidgets();
289 QList<KMFilterAction*> *mActionList;
295 /** The filter dialog. This is a non-modal dialog used to manage
296 KMail's filters. It should only be called through KMFilterMgr::openDialog.
297 The dialog consists of three main parts:
299 @li The KMFilterListBox in the left half allows the user to
300 select a filter to be displayed using the widgets on the right
301 half. It also has buttons to delete filters, add new ones, to
302 rename them and to change their order (maybe you will be able to
303 move the filters around by dragging later, and to optimize the
304 filters by trying to apply them to all locally available
305 KMMessage in turn and thus profiling which filters (and which
306 rules of the search patterns) matches most often and sorting the
307 filter/rules list according to the results, but I first want the
308 basic functionality in place).
310 @li The KMSearchPatternEdit in the upper-right quarter allows
311 the user to modify the filter criteria.
313 @li The KMFilterActionEdit in the lower-right quarter allows
314 the user to select the actions that will be executed for any
315 message that matches the search pattern.
317 @li (tbi) There will be another widget that will allow the user to
318 select to which folders the filter may be applied and whether it
319 should be applied on outbound or inbound message transfers or both
320 or none (meaning the filter is only applied when the user
321 explicitly hits CTRL-J). I'm not sure whether there should be a
322 per-folder filter list or a single list where you can select the
323 names of folders this rule will be applied to.
325 Upon creating the dialog, a (deep) copy of the current filter list
326 is made by KMFilterListBox. The changed filters are local to
327 KMFilterListBox until the user clicks the 'Apply' button.
329 NOTE: Though this dialog is non-modal, it completely ignores all
330 the stuff that goes on behind the scenes with folders esp. folder
331 creation, move and create. The widgets that depend on the filter
332 list and the filters that use folders as parameters are not
333 updated as you expect. I hope this will change sometime soon.
335 KMFilterDlg supports the creation of new filters through context
336 menus, dubbed "rapid filters". Call KMFilterMgr::createFilter
337 to use this. That call will be delivered to this dialog, which in
338 turn delivers it to the KMFilterListBox.
340 If you change the (DocBook) anchor for the filter dialog help,
341 make sure to change @p const @p QString @p KMFilterDlgHelpAnchor
342 in kmfilterdlg.cpp accordingly.
344 @short The filter dialog.
345 @author Marc Mutz <Marc@Mutz.com>, based upon work by Stefan Taferner <taferner@kde.org>.
346 @see KMFilter KMFilterActionEdit KMSearchPatternEdit KMFilterListBox
350 class KMFilterDlg: public KDialog
352 Q_OBJECT
353 public:
354 /** Create the filter dialog. The only class which should be able to
355 do this is KMFilterMgr. This ensures that there is only a
356 single filter dialog */
357 explicit KMFilterDlg( QWidget* parent=0, bool popFilter=false,
358 bool createDummyFilter=true );
360 /** Called from KMFilterMgr. Creates a new filter and presets
361 the first rule with "field equals value". Internally forwarded
362 to KMFilterListBox::createFilter. You should instead call
363 KMFilterMgr::createFilter. */
364 void createFilter( const QByteArray & field, const QString & value )
365 { mFilterList->createFilter( field, value ); }
367 public slots:
369 * Internally connected to KMFilterListBox::filterSelected.
370 * Just does a simple check and then calls
371 * KMSearchPatternEdit::setSearchPattern and
372 * KMFilterActionEdit::setActionList.
374 void slotFilterSelected(KMFilter * aFilter);
375 /** Action for popFilter */
376 void slotActionChanged(const KMPopFilterAction aAction);
377 /** Override QDialog::accept to allow disabling close */
378 virtual void accept();
380 protected slots:
381 void slotApplicabilityChanged();
382 void slotApplicableAccountsChanged();
383 void slotStopProcessingButtonToggled( bool aChecked );
384 void slotConfigureShortcutButtonToggled( bool aChecked );
385 void slotShortcutChanged( const QKeySequence &newSeq );
386 void slotConfigureToolbarButtonToggled( bool aChecked );
387 void slotFilterActionIconChanged( const QString &icon );
388 void slotReset();
389 void slotUpdateFilter();
390 void slotSaveSize();
391 // called when the dialog is closed (finished)
392 void slotFinished();
393 // update the list of accounts shown in the advanced tab
394 void slotUpdateAccountList();
397 /** Called when a user clicks the import filters button. Pops up
398 * a dialog asking the user which file to import from and which
399 * of the filters in that file to import. */
400 void slotImportFilters();
402 /** Called when a user clicks the export filters button. Pops up
403 * a dialog asking the user which filters to export and which
404 * file to export to. */
405 void slotExportFilters();
407 /** Called when a user decides to continue editing invalid filters */
408 void slotDisableAccept();
410 protected:
411 /** The widget that contains the ListBox showing the filters, and
412 the controls to remove filters, add new ones and to change their
413 order. */
414 KMFilterListBox *mFilterList;
415 /** The widget that allows editing of the filter pattern. */
416 KMSearchPatternEdit *mPatternEdit;
417 /** The widget that allows editing of the filter actions. */
418 KMFilterActionWidgetLister *mActionLister;
419 /** The widget that allows editing the popFilter actions. */
420 KMPopFilterActionWidget *mActionGroup;
421 /** Lets the user select whether to apply this filter on
422 inbound/outbound messages, both, or only on explicit CTRL-J. */
423 QCheckBox *mApplyOnIn, *mApplyOnOut, *mApplyBeforeOut, *mApplyOnCtrlJ;
424 /** For a filter applied to inbound messages selects whether to apply
425 this filter to all accounts or to selected accounts only. */
426 QRadioButton *mApplyOnForAll, *mApplyOnForTraditional, *mApplyOnForChecked;
427 /** ListView that shows the accounts in the advanced tab */
428 QTreeWidget *mAccountList;
430 QCheckBox *mStopProcessingHere;
431 QCheckBox *mConfigureShortcut;
432 QCheckBox *mConfigureToolbar;
433 QLabel *mFilterActionLabel;
434 KIconButton *mFilterActionIconButton;
435 KKeySequenceWidget *mKeySeqWidget;
436 QGroupBox *mAdvOptsGroup;
437 QGroupBox *mGlobalsBox;
438 QCheckBox *mShowLaterBtn;
440 KMFilter *mFilter;
441 bool bPopFilter;
442 bool mDoNotClose;
447 #endif /*kmfilterdlg_h*/