1 | /* |
2 | This file is part of the KDE libraries |
3 | SPDX-FileCopyrightText: 2003 Scott Wheeler <wheeler@kde.org> |
4 | SPDX-FileCopyrightText: 2005 Rafal Rzepecki <divide@users.sourceforge.net> |
5 | SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org> |
6 | |
7 | SPDX-License-Identifier: LGPL-2.0-or-later |
8 | */ |
9 | |
10 | #ifndef KTREEWIDGETSEARCHLINE_H |
11 | #define KTREEWIDGETSEARCHLINE_H |
12 | |
13 | #include <QLineEdit> |
14 | #include <kitemviews_export.h> |
15 | #include <memory> |
16 | |
17 | class QModelIndex; |
18 | class QTreeWidget; |
19 | class QTreeWidgetItem; |
20 | |
21 | /*! |
22 | * \class KTreeWidgetSearchLine |
23 | * \inmodule KItemViews |
24 | * |
25 | * \brief This class makes it easy to add a search line for filtering the items in |
26 | * listviews based on a simple text search. |
27 | * |
28 | * No changes to the application other than instantiating this class with |
29 | * appropriate QTreeWidgets should be needed. |
30 | */ |
31 | class KITEMVIEWS_EXPORT KTreeWidgetSearchLine : public QLineEdit |
32 | { |
33 | Q_OBJECT |
34 | |
35 | /*! |
36 | * \property KTreeWidgetSearchLine::caseSensitity |
37 | */ |
38 | Q_PROPERTY(Qt::CaseSensitivity caseSensitity READ caseSensitivity WRITE setCaseSensitivity NOTIFY caseSensitivityChanged) |
39 | |
40 | /*! |
41 | * \property KTreeWidgetSearchLine::keepParentsVisible |
42 | */ |
43 | Q_PROPERTY(bool keepParentsVisible READ keepParentsVisible WRITE setKeepParentsVisible NOTIFY keepParentsVisibleChanged) |
44 | |
45 | public: |
46 | /*! |
47 | * Constructs a KTreeWidgetSearchLine with \a treeWidget being the QTreeWidget to |
48 | * be filtered. |
49 | * |
50 | * If \a treeWidget is null then the widget will be disabled until listviews |
51 | * are set with setTreeWidget(), setTreeWidgets() or added with addTreeWidget(). |
52 | */ |
53 | explicit KTreeWidgetSearchLine(QWidget *parent = nullptr, QTreeWidget *treeWidget = nullptr); |
54 | |
55 | /*! |
56 | * Constructs a KTreeWidgetSearchLine with \a treeWidgets being the list of |
57 | * pointers to QTreeWidgets to be filtered. |
58 | * |
59 | * If \a treeWidgets is empty then the widget will be disabled until listviews |
60 | * are set with setTreeWidget(), setTreeWidgets() or added with addTreeWidget(). |
61 | */ |
62 | KTreeWidgetSearchLine(QWidget *parent, const QList<QTreeWidget *> &treeWidgets); |
63 | |
64 | ~KTreeWidgetSearchLine() override; |
65 | |
66 | /*! |
67 | * Returns true if the search is case sensitive. This defaults to false. |
68 | * |
69 | * \sa setCaseSensitivity() |
70 | */ |
71 | Qt::CaseSensitivity caseSensitivity() const; |
72 | |
73 | /*! |
74 | * Returns the current list of columns that will be searched. If the |
75 | * returned list is empty all visible columns will be searched. |
76 | * |
77 | * \sa setSearchColumns |
78 | */ |
79 | QList<int> searchColumns() const; |
80 | |
81 | /*! |
82 | * If this is true (the default) then the parents of matched items will also |
83 | * be shown. |
84 | * |
85 | * \sa setKeepParentsVisible() |
86 | */ |
87 | bool keepParentsVisible() const; |
88 | |
89 | /*! |
90 | * Returns the listview that is currently filtered by the search. |
91 | * If there are multiple listviews filtered, it returns 0. |
92 | * |
93 | * \sa setTreeWidget(), treeWidgets() |
94 | */ |
95 | QTreeWidget *treeWidget() const; |
96 | |
97 | /*! |
98 | * Returns the list of pointers to listviews that are currently filtered by |
99 | * the search. |
100 | * |
101 | * \sa setTreeWidgets(), addTreeWidget(), treeWidget() |
102 | */ |
103 | QList<QTreeWidget *> treeWidgets() const; |
104 | |
105 | Q_SIGNALS: |
106 | /*! |
107 | * This signal is emitted whenever an item gets hidden or unhidden due |
108 | * to it not matching or matching the search string. |
109 | */ |
110 | void hiddenChanged(QTreeWidgetItem *, bool); |
111 | |
112 | /*! |
113 | * This signal is emitted when user finished entering filter text or |
114 | * when he made a pause long enough, after the QTreeWidget items got filtered |
115 | * |
116 | * \a searchString is the text currently entered by the user |
117 | * \since 5.0 |
118 | */ |
119 | void searchUpdated(const QString &searchString); |
120 | |
121 | /*! |
122 | * |
123 | */ |
124 | void caseSensitivityChanged(Qt::CaseSensitivity caseSensitivity); |
125 | |
126 | /*! |
127 | * |
128 | */ |
129 | void keepParentsVisibleChanged(bool keepParentsVisible); |
130 | |
131 | public Q_SLOTS: |
132 | /*! |
133 | * Adds a QTreeWidget to the list of listviews filtered by this search line. |
134 | * If \a treeWidget is null then the widget will be disabled. |
135 | * |
136 | * \sa treeWidget(), setTreeWidgets(), removeTreeWidget() |
137 | */ |
138 | void addTreeWidget(QTreeWidget *treeWidget); |
139 | |
140 | /*! |
141 | * Removes a QTreeWidget from the list of listviews filtered by this search |
142 | * line. Does nothing if \a treeWidget is 0 or is not filtered by the quick search |
143 | * line. |
144 | * |
145 | * \sa setTreeWidgets(), addTreeWidget() |
146 | */ |
147 | void removeTreeWidget(QTreeWidget *treeWidget); |
148 | |
149 | /*! |
150 | * Updates search to only make visible the items that match \a pattern. If |
151 | * \a s is null then the line edit's text will be used. |
152 | */ |
153 | virtual void updateSearch(const QString &pattern = QString()); |
154 | |
155 | /*! |
156 | * Make the search case sensitive or case insensitive. |
157 | * |
158 | * \sa caseSensitivity() |
159 | */ |
160 | void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity); |
161 | |
162 | /*! |
163 | * When a search is active on a list that's organized into a tree view if |
164 | * a parent or ancesestor of an item is does not match the search then it |
165 | * will be hidden and as such so too will any children that match. |
166 | * |
167 | * If this is set to true (the default) then the parents of matching items |
168 | * will be shown. |
169 | * |
170 | * \warning setKeepParentsVisible(true) does not have the expected effect |
171 | * on items being added to or removed from the view while a search is active. |
172 | * When a new search starts afterwards the behavior will be normal. |
173 | * |
174 | * \sa keepParentsVisible |
175 | */ |
176 | void setKeepParentsVisible(bool value); |
177 | |
178 | /*! |
179 | * Sets the list of columns to be searched. The default is to search all, |
180 | * visible columns which can be restored by passing \a columns as an empty |
181 | * list. |
182 | * If listviews to be filtered have different numbers or labels of columns |
183 | * this method has no effect. |
184 | * |
185 | * \sa searchColumns |
186 | */ |
187 | void setSearchColumns(const QList<int> &columns); |
188 | |
189 | /*! |
190 | * Sets the QTreeWidget that is filtered by this search line, replacing any |
191 | * previously filtered listviews. If \a treeWidget is null then the widget will be |
192 | * disabled. |
193 | * |
194 | * \sa treeWidget(), setTreeWidgets() |
195 | */ |
196 | void setTreeWidget(QTreeWidget *treeWidget); |
197 | |
198 | /*! |
199 | * Sets QTreeWidgets that are filtered by this search line, replacing any |
200 | * previously filtered listviews. If \a treeWidgets is empty then the widget will |
201 | * be disabled. |
202 | * |
203 | * \sa treeWidgets(), addTreeWidget(), setTreeWidget() |
204 | */ |
205 | void setTreeWidgets(const QList<QTreeWidget *> &treeWidgets); |
206 | |
207 | protected: |
208 | /*! |
209 | * Returns true if \a item matches the search \a pattern. This will be evaluated |
210 | * based on the value of caseSensitive(). This can be overridden in |
211 | * subclasses to implement more complicated matching schemes. |
212 | */ |
213 | virtual bool itemMatches(const QTreeWidgetItem *item, const QString &pattern) const; |
214 | |
215 | void (QContextMenuEvent *) override; |
216 | |
217 | /*! |
218 | * Updates search to only make visible appropriate items in \a treeWidget. |
219 | * |
220 | * If \a treeWidget is null then nothing is done. |
221 | */ |
222 | virtual void updateSearch(QTreeWidget *treeWidget); |
223 | |
224 | /*! |
225 | * Connects signals of this listview to the appropriate slots of the search |
226 | * line. |
227 | */ |
228 | virtual void connectTreeWidget(QTreeWidget *); |
229 | |
230 | /*! |
231 | * Disconnects signals of a listviews from the search line. |
232 | */ |
233 | virtual void disconnectTreeWidget(QTreeWidget *); |
234 | |
235 | /*! |
236 | * Checks columns in all listviews and decides whether choosing columns to |
237 | * filter on makes any sense. |
238 | * |
239 | * Returns false if either of the following is true: |
240 | * * there are no listviews connected, |
241 | * * the listviews have different numbers of columns, |
242 | * * the listviews have only one column, |
243 | * * the listviews differ in column labels. |
244 | * |
245 | * Otherwise it returns true. |
246 | * |
247 | * \sa setSearchColumns() |
248 | */ |
249 | virtual bool canChooseColumnsCheck(); |
250 | |
251 | bool event(QEvent *event) override; |
252 | |
253 | private: |
254 | friend class KTreeWidgetSearchLinePrivate; |
255 | std::unique_ptr<class KTreeWidgetSearchLinePrivate> const d; |
256 | |
257 | Q_PRIVATE_SLOT(d, void _k_rowsInserted(const QModelIndex &, int, int) const) |
258 | Q_PRIVATE_SLOT(d, void _k_treeWidgetDeleted(QObject *)) |
259 | Q_PRIVATE_SLOT(d, void _k_slotColumnActivated(QAction *)) |
260 | Q_PRIVATE_SLOT(d, void _k_slotAllVisibleColumns()) |
261 | Q_PRIVATE_SLOT(d, void _k_queueSearch(const QString &)) |
262 | Q_PRIVATE_SLOT(d, void _k_activateSearch()) |
263 | }; |
264 | |
265 | #endif |
266 | |