1/* This file is part of the KDE libraries
2 Copyright (c) 2003 Scott Wheeler <wheeler@kde.org>
3 Copyright (c) 2005 Rafal Rzepecki <divide@users.sourceforge.net>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20#ifndef KLISTVIEWSEARCHLINE_H
21#define KLISTVIEWSEARCHLINE_H
22
23#include <kde3support_export.h>
24#include <klineedit.h>
25#include <khbox.h>
26
27class K3ListView;
28class Q3ListViewItem;
29
30/**
31 * This class makes it easy to add a search line for filtering the items in
32 * listviews based on a simple text search.
33 *
34 * No changes to the application other than instantiating this class with
35 * appropriate K3ListViews should be needed.
36 */
37
38class KDE3SUPPORT_EXPORT K3ListViewSearchLine : public KLineEdit
39{
40 Q_OBJECT
41
42public:
43
44 /**
45 * Constructs a K3ListViewSearchLine with \a listView being the K3ListView to
46 * be filtered.
47 *
48 * If \a listView is null then the widget will be disabled until listviews
49 * are set with setListView(), setListViews() or added with addListView().
50 */
51 K3ListViewSearchLine(QWidget *parent = 0, K3ListView *listView = 0);
52
53 /**
54 * Constructs a K3ListViewSearchLine with \a listViews being the list of
55 * pointers to K3ListViews to be filtered.
56 *
57 * If \a listViews is empty then the widget will be disabled until listviews
58 * are set with setListView(), setListViews() or added with addListView().
59 */
60 K3ListViewSearchLine(QWidget *parent,
61 const QList<K3ListView *> &listViews);
62
63
64 /**
65 * Destroys the K3ListViewSearchLine.
66 */
67 virtual ~K3ListViewSearchLine();
68
69 /**
70 * Returns true if the search is case sensitive. This defaults to false.
71 *
72 * @see setCaseSensitive()
73 */
74 bool caseSensitive() const;
75
76 /**
77 * Returns the current list of columns that will be searched. If the
78 * returned list is empty all visible columns will be searched.
79 *
80 * @see setSearchColumns
81 */
82 QList<int> searchColumns() const;
83
84 /**
85 * If this is true (the default) then the parents of matched items will also
86 * be shown.
87 *
88 * @see setKeepParentsVisible()
89 */
90 bool keepParentsVisible() const;
91
92 /**
93 * Returns the listview that is currently filtered by the search.
94 * If there are multiple listviews filtered, it returns 0.
95 *
96 * @see setListView(), listViews()
97 */
98 K3ListView *listView() const;
99
100 /**
101 * Returns the list of pointers to listviews that are currently filtered by
102 * the search.
103 *
104 * @see setListViews(), addListView(), listView()
105 */
106 const QList<K3ListView *> &listViews() const;
107
108public Q_SLOTS:
109 /**
110 * Adds a K3ListView to the list of listviews filtered by this search line.
111 * If \a lv is null then the widget will be disabled.
112 *
113 * @see listView(), setListViews(), removeListView()
114 */
115 void addListView(K3ListView *lv);
116
117 /**
118 * Removes a K3ListView from the list of listviews filtered by this search
119 * line. Does nothing if \a lv is 0 or is not filtered by the quick search
120 * line.
121 *
122 * @see listVew(), setListViews(), addListView()
123 */
124 void removeListView(K3ListView *lv);
125
126 /**
127 * Updates search to only make visible the items that match \a s. If
128 * \a s is null then the line edit's text will be used.
129 */
130 virtual void updateSearch(const QString &s = QString());
131
132 /**
133 * Make the search case sensitive or case insensitive.
134 *
135 * @see caseSenstive()
136 */
137 void setCaseSensitive(bool cs);
138
139 /**
140 * When a search is active on a list that's organized into a tree view if
141 * a parent or ancesestor of an item is does not match the search then it
142 * will be hidden and as such so too will any children that match.
143 *
144 * If this is set to true (the default) then the parents of matching items
145 * will be shown.
146 *
147 * @see keepParentsVisible
148 */
149 void setKeepParentsVisible(bool v);
150
151 /**
152 * Sets the list of columns to be searched. The default is to search all,
153 * visible columns which can be restored by passing \a columns as an empty
154 * list.
155 * If listviews to be filtered have different numbers or labels of columns
156 * this method has no effect.
157 *
158 * @see searchColumns
159 */
160 void setSearchColumns(const QList<int> &columns);
161
162 /**
163 * Sets the K3ListView that is filtered by this search line, replacing any
164 * previously filtered listviews. If \a lv is null then the widget will be
165 * disabled.
166 *
167 * @see listView(), setListViews()
168 */
169 void setListView(K3ListView *lv);
170
171 /**
172 * Sets K3ListViews that are filtered by this search line, replacing any
173 * previously filtered listviews. If \a lvs is empty then the widget will
174 * be disabled.
175 *
176 * @see listViews(), addListView(), setListView()
177 */
178 void setListViews(const QList<K3ListView *> &lv);
179
180
181 protected:
182
183 /**
184 * Returns true if \a item matches the search \a s. This will be evaluated
185 * based on the value of caseSensitive(). This can be overridden in
186 * subclasses to implement more complicated matching schemes.
187 */
188 virtual bool itemMatches(const Q3ListViewItem *item, const QString &s) const;
189
190 /**
191 * Re-implemented for internal reasons. API not affected.
192 */
193 virtual void contextMenuEvent( QContextMenuEvent*e );
194
195 /**
196 * Updates search to only make visible appropriate items in \a listView. If
197 * \a listView is null then nothing is done.
198 */
199 virtual void updateSearch(K3ListView *listView);
200
201 /**
202 * Connects signals of this listview to the appropriate slots of the search
203 * line.
204 */
205 virtual void connectListView(K3ListView *);
206 /**
207 * Disconnects signals of a listviews from the search line.
208 */
209 virtual void disconnectListView(K3ListView *);
210
211 /**
212 * Checks columns in all listviews and decides whether choosing columns to
213 * filter on makes any sense.
214 *
215 * Returns false if either of the following is true:
216 * * there are no listviews connected,
217 * * the listviews have different numbers of columns,
218 * * the listviews have only one column,
219 * * the listviews differ in column labels.
220 *
221 * Otherwise it returns true.
222 *
223 * @see setSearchColumns()
224 */
225 virtual bool canChooseColumnsCheck();
226
227protected Q_SLOTS:
228 /**
229 * When keys are pressed a new search string is created and a timer is
230 * activated. The most recent search is activated when this timer runs out
231 * if another key has not yet been pressed.
232 *
233 * This method makes @param search the most recent search and starts the
234 * timer.
235 *
236 * Together with activateSearch() this makes it such that searches are not
237 * started until there is a short break in the users typing.
238 *
239 * @see activateSearch()
240 */
241 void queueSearch(const QString &search);
242
243 /**
244 * When the timer started with queueSearch() expires this slot is called.
245 * If there has been another timer started then this slot does nothing.
246 * However if there are no other pending searches this starts the list view
247 * search.
248 *
249 * @see queueSearch()
250 */
251 void activateSearch();
252
253private:
254
255 /**
256 * This is used after changing the list of listviews. If choosing columns
257 * doesn't make sense, it forces filtering over all columns.
258 *
259 * @see canChooseColumnsCheck()
260 */
261 void checkColumns();
262
263 /**
264 * This is used in case parent items of matching items shouldn't be
265 * visible. It hides all items that don't match the search string.
266 */
267 void checkItemParentsNotVisible(K3ListView *listView);
268
269 /**
270 * This is used in case parent items of matching items should be visible.
271 * It makes a recursive call to all children. It returns true if at least
272 * one item in the subtree with the given root item is visible.
273 */
274 bool checkItemParentsVisible(Q3ListViewItem *item, Q3ListViewItem *highestHiddenParent = 0);
275
276private Q_SLOTS:
277 void itemAdded(Q3ListViewItem *item) const;
278 void listViewDeleted( QObject *listView );
279 void searchColumnsMenuActivated(QAction*);
280
281private:
282 class K3ListViewSearchLinePrivate;
283 K3ListViewSearchLinePrivate *d;
284};
285
286/**
287 * Creates a widget featuring a K3ListViewSearchLine, a label with the text
288 * "Search" and a button to clear the search.
289 */
290class KDE3SUPPORT_EXPORT K3ListViewSearchLineWidget : public KHBox
291{
292 Q_OBJECT
293
294public:
295 /**
296 * Creates a K3ListViewSearchLineWidget for \a listView with \a parent as the
297 * parent with and \a name.
298 */
299 K3ListViewSearchLineWidget(K3ListView *listView = 0, QWidget *parent = 0);
300
301 /**
302 * Destroys the K3ListViewSearchLineWidget
303 */
304 ~K3ListViewSearchLineWidget();
305
306 /**
307 * Creates the search line. This can be useful to reimplement in cases where
308 * a K3ListViewSearchLine subclass is used.
309 */
310 virtual K3ListViewSearchLine *createSearchLine(K3ListView *listView);
311
312 /**
313 * Returns a pointer to the search line.
314 */
315 K3ListViewSearchLine *searchLine() const;
316
317protected Q_SLOTS:
318 /**
319 * Creates the widgets inside of the widget. This is called from the
320 * constructor via a single shot timer so that it it guaranteed to run
321 * after construction is complete. This makes it suitable for overriding in
322 * subclasses.
323 */
324 virtual void createWidgets();
325
326private:
327 class K3ListViewSearchLineWidgetPrivate;
328 K3ListViewSearchLineWidgetPrivate *d;
329};
330
331#endif
332