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