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 }