File indexing completed on 2024-06-23 05:17:51
0001 /* 0002 SPDX-FileCopyrightText: 2014-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include "search/searchpattern.h" 0010 #include <QGroupBox> 0011 #include <QList> 0012 #include <QListWidgetItem> 0013 class QListWidget; 0014 class QPushButton; 0015 class QModelIndex; 0016 class KListWidgetSearchLine; 0017 /** 0018 * This is a complex widget that is used to manipulate a mail program's filter 0019 * list. It consists of an internal list of filters, which is a deep 0020 * copy of the list KMFilterMgr manages, a QListBox displaying that list, 0021 * and a few buttons used to create new filters, delete them, rename them 0022 * and change the order of filters. 0023 * 0024 * It does not provide means to change the actual filter (besides the name), 0025 * but relies on auxiliary widgets (SearchPatternEdit and KMFilterActionEdit) 0026 * to do that. 0027 * 0028 * Communication with this widget is quite easy: simply create an instance, 0029 * connect the signals filterSelected, resetWidgets and applyWidgets with 0030 * a slot that does the right thing and there you go... 0031 * 0032 * This widget will operate on it's own copy of the filter list as 0033 * long as you don't call slotApplyFilterChanges. It will then 0034 * transfer the altered filter list back to KMFilterMgr. 0035 * 0036 * @short A complex widget that allows managing a list of MailCommon::MailFilter's. 0037 * @author Marc Mutz <mutz@kde.org>, based upon work by Stefan Taferner <taferner@kde.org>. 0038 * @see MailCommon::MailFilter KMFilterDialog KMFilterActionEdit SearchPatternEdit 0039 */ 0040 0041 namespace MailCommon 0042 { 0043 class MailFilter; 0044 0045 class QListWidgetFilterItem : public QListWidgetItem 0046 { 0047 public: 0048 explicit QListWidgetFilterItem(const QString &text, QListWidget *parent = nullptr); 0049 ~QListWidgetFilterItem() override; 0050 0051 void setFilter(MailCommon::MailFilter *filter); 0052 [[nodiscard]] MailCommon::MailFilter *filter() const; 0053 0054 private: 0055 MailCommon::MailFilter *mFilter = nullptr; 0056 }; 0057 0058 class KMFilterListBox : public QGroupBox 0059 { 0060 Q_OBJECT 0061 public: 0062 /** 0063 * Constructor. 0064 */ 0065 explicit KMFilterListBox(const QString &title, QWidget *widget = nullptr); 0066 0067 /** 0068 * Destructor. 0069 */ 0070 ~KMFilterListBox() override; 0071 0072 /** 0073 * Called from KMFilterDialog. Creates a new filter and presets 0074 * the first rule with "field equals value". It's there mainly to 0075 * support "rapid filter creation" from a context menu. You should 0076 * instead call KMFilterMgr::createFilter. 0077 * @see KMFilterMgr::createFilter KMFilterDialog::createFilter 0078 */ 0079 void createFilter(const QByteArray &field, const QString &value); 0080 0081 /** 0082 * Loads the filter list and selects the first filter. Should be 0083 * called when all signals are connected properly. If createDummyFilter 0084 * is true, an empty filter is created to improve the usability of the 0085 * dialog in case no filter has been defined so far. 0086 */ 0087 void loadFilterList(bool createDummyFilter); 0088 0089 void insertFilter(MailCommon::MailFilter *aFilter); 0090 0091 void appendFilter(MailCommon::MailFilter *aFilter); 0092 0093 /** 0094 * Returns a list of _copies_ of the current list of filters. 0095 * The list owns the contents and thus the caller needs to clean them up. 0096 * @param closeAfterSaving If @c true user is given option to continue editing 0097 * after being warned about invalid filters. Otherwise, user is just warned. 0098 * @param wasCanceled If @c true then the operation was canceled. 0099 */ 0100 QList<MailCommon::MailFilter *> filtersForSaving(bool closeAfterSaving, bool &wasCanceled) const; 0101 0102 QStringList selectedFilterId(SearchRule::RequiredPart &requiredPart, const QString &resource) const; 0103 0104 Q_SIGNALS: 0105 /** 0106 * Emitted when a new filter has been selected by the user or if the 0107 * current filter has changed after a 'new' or 'delete' operation. 0108 */ 0109 void filterSelected(MailCommon::MailFilter *filter); 0110 0111 /** 0112 * Emitted when this widget wants the edit widgets to let go of 0113 * their filter reference. Everyone holding a reference to a filter 0114 * should update it from the contents of the widgets used to edit 0115 * it and set their internal reference to 0. 0116 */ 0117 void resetWidgets(); 0118 0119 /** 0120 * Emitted when this widget wants the edit widgets to apply the changes 0121 * to the current filter. 0122 */ 0123 void applyWidgets(); 0124 0125 /** 0126 * Emitted when the user decides to continue editing after being warned 0127 * about invalid filters. 0128 */ 0129 void abortClosing() const; 0130 0131 /** 0132 * Emitted when a new filter is created. 0133 */ 0134 void filterCreated(); 0135 0136 /** 0137 * Emitted when a filter is deleted. 0138 */ 0139 void filterRemoved(const QList<MailCommon::MailFilter *> &filter); 0140 0141 /** 0142 * Emitted when a filter is updated (e.g. renamed). 0143 */ 0144 void filterUpdated(MailCommon::MailFilter *filter); 0145 0146 /** 0147 * Emitted whenever the order in which the filters are displayed is changed. 0148 */ 0149 void filterOrderAltered(); 0150 0151 public Q_SLOTS: 0152 /** 0153 * Called when the name of a filter might have changed (e.g. through 0154 * changing the first rule in SearchPatternEdit). Updates the corresponding 0155 * entry in the listbox and (if necessary) auto-names the filter. 0156 */ 0157 void slotUpdateFilterName(); 0158 0159 void slotAccepted(); 0160 void slotApplied(); 0161 0162 protected Q_SLOTS: 0163 /** 0164 * Called when the user clicks on a filter in the filter list. 0165 * Calculates the corresponding filter and emits the filterSelected signal. 0166 */ 0167 void slotSelected(int aIdx); 0168 0169 /** 0170 * Called when the user clicks the 'New' button. 0171 * Creates a new empty filter just before the current one. 0172 */ 0173 void slotNew(); 0174 0175 /** 0176 * Called when the user clicks the 'Copy' button. Creates a copy 0177 * of the current filter and inserts it just before the current one. 0178 */ 0179 void slotCopy(); 0180 0181 /** 0182 * Called when the user clicks the 'Delete' button. Deletes the 0183 * current filter. 0184 */ 0185 void slotDelete(); 0186 0187 /** 0188 * Called when the user clicks the 'Up' button. Moves the current 0189 * filter up one line. 0190 */ 0191 void slotUp(); 0192 0193 /** 0194 * Called when the user clicks the 'Down' button. Moves the current 0195 * filter down one line. 0196 */ 0197 void slotDown(); 0198 0199 /** 0200 * Called when the user clicks the 'Rename' button. Pops up a 0201 * dialog prompting to enter the new name. 0202 */ 0203 void slotRename(); 0204 0205 void slotRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int); 0206 0207 /** 0208 * Called when the user clicks the 'Top' button. Moves the current 0209 * filter to top. 0210 */ 0211 void slotTop(); 0212 0213 /** 0214 * Called when the user clicks the 'Bottom' button. Moves the current 0215 * filter to bottom. 0216 */ 0217 void slotBottom(); 0218 0219 void slotFilterEnabledChanged(QListWidgetItem *item); 0220 0221 void slotSelectionChanged(); 0222 0223 protected: 0224 /** The listbox displaying the filter list. */ 0225 QListWidget *mListWidget = nullptr; 0226 0227 /** The various action buttons. */ 0228 QPushButton *mBtnNew = nullptr; 0229 QPushButton *mBtnCopy = nullptr; 0230 QPushButton *mBtnDelete = nullptr; 0231 QPushButton *mBtnUp = nullptr; 0232 QPushButton *mBtnDown = nullptr; 0233 QPushButton *mBtnRename = nullptr; 0234 QPushButton *mBtnTop = nullptr; 0235 QPushButton *mBtnBottom = nullptr; 0236 KListWidgetSearchLine *mSearchListWidget = nullptr; 0237 bool eventFilter(QObject *obj, QEvent *event) override; 0238 0239 private: 0240 void applyFilterChanged(bool closeAfterSaving); 0241 void enableControls(); 0242 bool itemIsValid(QListWidgetItem *item) const; 0243 QList<QListWidgetItem *> selectedFilter(); 0244 void swapNeighbouringFilters(int untouchedOne, int movedOne); 0245 }; 0246 }