File indexing completed on 2024-05-05 05:37:09

0001 /*
0002    SPDX-FileCopyrightText: 2003 Scott Wheeler <wheeler@kde.org>
0003    SPDX-FileCopyrightText: 2005 Rafal Rzepecki <divide@users.sourceforge.net>
0004    SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org>
0005    SPDX-FileCopyrightText: 2007 Pino Toscano <pino@kde.org>
0006 
0007    SPDX-License-Identifier: LGPL-2.0-only
0008 */
0009 
0010 #ifndef KTREEVIEWSEARCHLINE_H
0011 #define KTREEVIEWSEARCHLINE_H
0012 
0013 #include <klineedit.h>
0014 
0015 class QModelIndex;
0016 class QTreeView;
0017 
0018 class KTreeViewSearchLinePrivate;
0019 class KTreeViewSearchLineWidgetPrivate;
0020 
0021 /**
0022  * This class makes it easy to add a search line for filtering the items in
0023  * listviews based on a simple text search.
0024  *
0025  * No changes to the application other than instantiating this class with
0026  * appropriate QTreeViews should be needed.
0027  */
0028 
0029 class KTreeViewSearchLine : public KLineEdit
0030 {
0031     Q_OBJECT
0032 
0033     Q_PROPERTY(Qt::CaseSensitivity caseSensitity READ caseSensitivity WRITE setCaseSensitivity)
0034     Q_PROPERTY(bool keepParentsVisible READ keepParentsVisible WRITE setKeepParentsVisible)
0035 
0036 public:
0037     /**
0038      * Constructs a KTreeViewSearchLine with \a treeView being the QTreeView to
0039      * be filtered.
0040      *
0041      * If \a treeView is null then the widget will be disabled until listviews
0042      * are set with setTreeView(), setTreeViews() or added with addTreeView().
0043      */
0044     explicit KTreeViewSearchLine(QWidget *parent = nullptr, QTreeView *treeView = nullptr);
0045 
0046     /**
0047      * Constructs a KTreeViewSearchLine with \a treeViews being the list of
0048      * pointers to QTreeViews to be filtered.
0049      *
0050      * If \a treeViews is empty then the widget will be disabled until listviews
0051      * are set with setTreeView(), setTreeViews() or added with addTreeView().
0052      */
0053     KTreeViewSearchLine(QWidget *parent, const QList<QTreeView *> &treeViews);
0054 
0055     /**
0056      * Destroys the KTreeViewSearchLine.
0057      */
0058     ~KTreeViewSearchLine() override;
0059 
0060     /**
0061      * Returns true if the search is case sensitive.  This defaults to false.
0062      *
0063      * @see setCaseSensitive()
0064      */
0065     Qt::CaseSensitivity caseSensitivity() const;
0066 
0067     /**
0068      * Returns the current list of columns that will be searched.  If the
0069      * returned list is empty all visible columns will be searched.
0070      *
0071      * @see setSearchColumns
0072      */
0073     QList<int> searchColumns() const;
0074 
0075     /**
0076      * If this is true (the default) then the parents of matched items will also
0077      * be shown.
0078      *
0079      * @see setKeepParentsVisible()
0080      */
0081     bool keepParentsVisible() const;
0082 
0083     /**
0084      * Returns the listview that is currently filtered by the search.
0085      * If there are multiple listviews filtered, it returns 0.
0086      *
0087      * @see setTreeView(), treeView()
0088      */
0089     QTreeView *treeView() const;
0090 
0091     /**
0092      * Returns the list of pointers to listviews that are currently filtered by
0093      * the search.
0094      *
0095      * @see setTreeViews(), addTreeView(), treeView()
0096      */
0097     QList<QTreeView *> treeViews() const;
0098 
0099 public Q_SLOTS:
0100     /**
0101      * Adds a QTreeView to the list of listviews filtered by this search line.
0102      * If \a treeView is null then the widget will be disabled.
0103      *
0104      * @see treeView(), setTreeViews(), removeTreeView()
0105      */
0106     void addTreeView(QTreeView *treeView);
0107 
0108     /**
0109      * Removes a QTreeView from the list of listviews filtered by this search
0110      * line. Does nothing if \a treeView is 0 or is not filtered by the quick search
0111      * line.
0112      *
0113      * @see listVew(), setTreeView(), addTreeView()
0114      */
0115     void removeTreeView(QTreeView *treeView);
0116 
0117     /**
0118      * Updates search to only make visible the items that match \a pattern.  If
0119      * \a s is null then the line edit's text will be used.
0120      */
0121     virtual void updateSearch(const QString &pattern = QString());
0122 
0123     /**
0124      * Make the search case sensitive or case insensitive.
0125      *
0126      * @see caseSenstivity()
0127      */
0128     void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity);
0129 
0130     /**
0131      * When a search is active on a list that's organized into a tree view if
0132      * a parent or ancestor of an item is does not match the search then it
0133      * will be hidden and as such so too will any children that match.
0134      *
0135      * If this is set to true (the default) then the parents of matching items
0136      * will be shown.
0137      *
0138      * @see keepParentsVisible
0139      */
0140     void setKeepParentsVisible(bool value);
0141 
0142     /**
0143      * Sets the list of columns to be searched.  The default is to search all,
0144      * visible columns which can be restored by passing \a columns as an empty
0145      * list.
0146      * If listviews to be filtered have different numbers or labels of columns
0147      * this method has no effect.
0148      *
0149      * @see searchColumns
0150      */
0151     void setSearchColumns(const QList<int> &columns);
0152 
0153     /**
0154      * Sets the QTreeView that is filtered by this search line, replacing any
0155      * previously filtered listviews.  If \a treeView is null then the widget will be
0156      * disabled.
0157      *
0158      * @see treeView(), setTreeViews()
0159      */
0160     void setTreeView(QTreeView *treeView);
0161 
0162     /**
0163      * Sets QTreeViews that are filtered by this search line, replacing any
0164      * previously filtered listviews.  If \a treeViews is empty then the widget will
0165      * be disabled.
0166      *
0167      * @see treeViews(), addTreeView(), setTreeView()
0168      */
0169     void setTreeViews(const QList<QTreeView *> &treeViews);
0170 
0171     /**
0172      * Returns true if \a item matches the search \a pattern.  This will be evaluated
0173      * based on the value of caseSensitive().  This can be overridden in
0174      * subclasses to implement more complicated matching schemes.
0175      */
0176     virtual bool itemMatches(const QModelIndex &item, int row, const QString &pattern) const;
0177 
0178     /**
0179      * Checks columns in all listviews and decides whether choosing columns to
0180      * filter on makes any sense.
0181      *
0182      * Returns false if either of the following is true:
0183      * * there are no listviews connected,
0184      * * the listviews have different numbers of columns,
0185      * * the listviews have only one column,
0186      * * the listviews differ in column labels.
0187      *
0188      * Otherwise it returns true.
0189      *
0190      * @see setSearchColumns()
0191      */
0192     virtual bool canChooseColumnsCheck();
0193 
0194 protected:
0195     /**
0196      * Re-implemented for internal reasons.  API not affected.
0197      */
0198     void contextMenuEvent(QContextMenuEvent *) override;
0199 
0200     /**
0201      * Updates search to only make visible appropriate items in \a treeView.  If
0202      * \a treeView is null then nothing is done.
0203      */
0204     virtual void updateSearch(QTreeView *treeView);
0205 
0206     /**
0207      * Connects signals of this listview to the appropriate Q_SLOTS of the search
0208      * line.
0209      */
0210     virtual void connectTreeView(QTreeView *);
0211 
0212     /**
0213      * Disconnects signals of a listviews from the search line.
0214      */
0215     virtual void disconnectTreeView(QTreeView *);
0216 
0217 protected Q_SLOTS:
0218     /**
0219      * When keys are pressed a new search string is created and a timer is
0220      * activated.  The most recent search is activated when this timer runs out
0221      * if another key has not yet been pressed.
0222      *
0223      * This method makes @param search the most recent search and starts the
0224      * timer.
0225      *
0226      * Together with activateSearch() this makes it such that searches are not
0227      * started until there is a short break in the users typing.
0228      *
0229      * @see activateSearch()
0230      */
0231     void queueSearch(const QString &search);
0232 
0233     /**
0234      * When the timer started with queueSearch() expires this slot is called.
0235      * If there has been another timer started then this slot does nothing.
0236      * However if there are no other pending searches this starts the list view
0237      * search.
0238      *
0239      * @see queueSearch()
0240      */
0241     void activateSearch();
0242 
0243 private:
0244     KTreeViewSearchLinePrivate *const d;
0245 
0246     // Q_PRIVATE_SLOT( d, void rowsInserted( const QModelIndex&, int, int ) const )
0247     Q_PRIVATE_SLOT(d, void treeViewDeleted(QObject *))
0248     Q_PRIVATE_SLOT(d, void slotColumnActivated(QAction *))
0249     Q_PRIVATE_SLOT(d, void slotAllVisibleColumns())
0250 
0251 private Q_SLOTS:
0252     void rowsInserted(const QModelIndex &parent, int start, int end) const;
0253 };
0254 
0255 /**
0256  * Creates a widget featuring a KTreeViewSearchLine, a label with the text
0257  * "Search" and a button to clear the search.
0258  */
0259 class KTreeViewSearchLineWidget : public QWidget
0260 {
0261     Q_OBJECT
0262 
0263 public:
0264     /**
0265      * Creates a KTreeViewSearchLineWidget for \a treeView with \a parent as the
0266      * parent.
0267      */
0268     explicit KTreeViewSearchLineWidget(QWidget *parent = nullptr, QTreeView *treeView = nullptr);
0269 
0270     /**
0271      * Destroys the KTreeViewSearchLineWidget
0272      */
0273     ~KTreeViewSearchLineWidget() override;
0274 
0275     /**
0276      * Returns a pointer to the search line.
0277      */
0278     KTreeViewSearchLine *searchLine() const;
0279 
0280 protected Q_SLOTS:
0281     /**
0282      * Creates the widgets inside of the widget.  This is called from the
0283      * constructor via a single shot timer so that it it guaranteed to run
0284      * after construction is complete.  This makes it suitable for overriding in
0285      * subclasses.
0286      */
0287     virtual void createWidgets();
0288 
0289 protected:
0290     /**
0291      * Creates the search line.  This can be useful to reimplement in cases where
0292      * a KTreeViewSearchLine subclass is used.
0293      *
0294      * It is const because it is be called from searchLine(), which to the user
0295      * doesn't conceptually alter the widget.
0296      */
0297     virtual KTreeViewSearchLine *createSearchLine(QTreeView *treeView) const;
0298 
0299 private:
0300     KTreeViewSearchLineWidgetPrivate *const d;
0301 };
0302 
0303 #endif