1/**
2 * This file is part of the KDE project
3 * Copyright (C) 2007, 2009 Rafael Fernández López <ereslibre@kde.org>
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 as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#ifndef KCATEGORIZEDVIEW_H
22#define KCATEGORIZEDVIEW_H
23
24#include <QtGui/QListView>
25
26#include <kdeui_export.h>
27
28class KCategoryDrawer;
29class KCategoryDrawerV2;
30
31/**
32 * @short Item view for listing items in a categorized fashion optionally
33 *
34 * KCategorizedView basically has the same functionality as QListView, only that it also lets you
35 * layout items in a way that they are categorized visually.
36 *
37 * For it to work you will need to set a KCategorizedSortFilterProxyModel and a KCategoryDrawer
38 * with methods setModel() and setCategoryDrawer() respectively. Also, the model will need to be
39 * flagged as categorized with KCategorizedSortFilterProxyModel::setCategorizedModel(true).
40 *
41 * The way it works (if categorization enabled):
42 *
43 * - When sorting, it does more things than QListView does. It will ask the model for the
44 * special role CategorySortRole (@see KCategorizedSortFilterProxyModel). This can return
45 * a QString or an int in order to tell the view the order of categories. In this sense, for
46 * instance, if we are sorting by name ascending, "A" would be before than "B". If we are
47 * sorting by size ascending, 512 bytes would be before 1024 bytes. This way categories are
48 * also sorted.
49 *
50 * - When the view has to paint, it will ask the model with the role CategoryDisplayRole
51 * (@see KCategorizedSortFilterProxyModel). It will for instance return "F" for "foo.pdf" if
52 * we are sorting by name ascending, or "Small" if a certain item has 100 bytes, for example.
53 *
54 * For drawing categories, KCategoryDrawer will be used. You can inherit this class to do your own
55 * drawing.
56 *
57 * @note All examples cited before talk about filesystems and such, but have present that this
58 * is a completely generic class, and it can be used for whatever your purpose is. For
59 * instance when talking about animals, you can separate them by "Mammal" and "Oviparous". In
60 * this very case, for example, the CategorySortRole and the CategoryDisplayRole could be the
61 * same ("Mammal" and "Oviparous").
62 *
63 * @note There is a really performance boost if CategorySortRole returns an int instead of a QString.
64 * Have present that this role is asked (n * log n) times when sorting and compared. Comparing
65 * ints is always faster than comparing strings, whithout mattering how fast the string
66 * comparison is. Consider thinking of a way of returning ints instead of QStrings if your
67 * model can contain a high number of items.
68 *
69 * @warning Note that for really drawing items in blocks you will need some things to be done:
70 * - The model set to this view has to be (or inherit if you want to do special stuff
71 * in it) KCategorizedSortFilterProxyModel.
72 * - This model needs to be set setCategorizedModel to true.
73 * - Set a category drawer by calling setCategoryDrawer.
74 *
75 * @see KCategorizedSortFilterProxyModel, KCategoryDrawer
76 *
77 * @author Rafael Fernández López <ereslibre@kde.org>
78 */
79class KDEUI_EXPORT KCategorizedView
80 : public QListView
81{
82 Q_OBJECT
83 Q_PROPERTY(int categorySpacing READ categorySpacing WRITE setCategorySpacing)
84 Q_PROPERTY(bool alternatingBlockColors READ alternatingBlockColors WRITE setAlternatingBlockColors)
85 Q_PROPERTY(bool collapsibleBlocks READ collapsibleBlocks WRITE setCollapsibleBlocks)
86
87public:
88 KCategorizedView(QWidget *parent = 0);
89
90 ~KCategorizedView();
91
92 /**
93 * Reimplemented from QAbstractItemView.
94 */
95 virtual void setModel(QAbstractItemModel *model);
96
97 /**
98 * Calls to setGridSizeOwn().
99 */
100 void setGridSize(const QSize &size);
101
102 /**
103 * @warning note that setGridSize is not virtual in the base class (QListView), so if you are
104 * calling to this method, make sure you have a KCategorizedView pointer around. This
105 * means that something like:
106 * @code
107 * QListView *lv = new KCategorizedView();
108 * lv->setGridSize(mySize);
109 * @endcode
110 *
111 * will not call to the expected setGridSize method. Instead do something like this:
112 *
113 * @code
114 * QListView *lv;
115 * ...
116 * KCategorizedView *cv = qobject_cast<KCategorizedView*>(lv);
117 * if (cv) {
118 * cv->setGridSizeOwn(mySize);
119 * } else {
120 * lv->setGridSize(mySize);
121 * }
122 * @endcode
123 *
124 * @note this method will call to QListView::setGridSize among other operations.
125 *
126 * @since 4.4
127 */
128 void setGridSizeOwn(const QSize &size);
129
130 /**
131 * Reimplemented from QAbstractItemView.
132 */
133 virtual QRect visualRect(const QModelIndex &index) const;
134
135 /**
136 * Returns the current category drawer.
137 */
138 KCategoryDrawer *categoryDrawer() const;
139
140 /**
141 * The category drawer that will be used for drawing categories.
142 */
143 void setCategoryDrawer(KCategoryDrawer *categoryDrawer);
144
145 /**
146 * @return Category spacing. The spacing between categories.
147 *
148 * @since 4.4
149 */
150 int categorySpacing() const;
151
152 /**
153 * Stablishes the category spacing. This is the spacing between categories.
154 *
155 * @since 4.4
156 */
157 void setCategorySpacing(int categorySpacing);
158
159 /**
160 * @return Whether blocks should be drawn with alternating colors.
161 *
162 * @since 4.4
163 */
164 bool alternatingBlockColors() const;
165
166 /**
167 * Sets whether blocks should be drawn with alternating colors.
168 *
169 * @since 4.4
170 */
171 void setAlternatingBlockColors(bool enable);
172
173 /**
174 * @return Whether blocks can be collapsed or not.
175 *
176 * @since 4.4
177 */
178 bool collapsibleBlocks() const;
179
180 /**
181 * Sets whether blocks can be collapsed or not.
182 *
183 * @since 4.4
184 */
185 void setCollapsibleBlocks(bool enable);
186
187 /**
188 * @return Block of indexes that are into @p category.
189 *
190 * @since 4.5
191 */
192 QModelIndexList block(const QString &category);
193
194 /**
195 * @return Block of indexes that are represented by @p representative.
196 *
197 * @since 4.5
198 */
199 QModelIndexList block(const QModelIndex &representative);
200
201 /**
202 * Reimplemented from QAbstractItemView.
203 */
204 virtual QModelIndex indexAt(const QPoint &point) const;
205
206 /**
207 * Reimplemented from QAbstractItemView.
208 */
209 virtual void reset();
210
211protected:
212 /**
213 * Reimplemented from QWidget.
214 */
215 virtual void paintEvent(QPaintEvent *event);
216
217 /**
218 * Reimplemented from QWidget.
219 */
220 virtual void resizeEvent(QResizeEvent *event);
221
222 /**
223 * Reimplemented from QAbstractItemView.
224 */
225 virtual void setSelection(const QRect &rect,
226 QItemSelectionModel::SelectionFlags flags);
227
228 /**
229 * Reimplemented from QWidget.
230 */
231 virtual void mouseMoveEvent(QMouseEvent *event);
232
233 /**
234 * Reimplemented from QWidget.
235 */
236 virtual void mousePressEvent(QMouseEvent *event);
237
238 /**
239 * Reimplemented from QWidget.
240 */
241 virtual void mouseReleaseEvent(QMouseEvent *event);
242
243 /**
244 * Reimplemented from QWidget.
245 */
246 virtual void leaveEvent(QEvent *event);
247
248 /**
249 * Reimplemented from QAbstractItemView.
250 */
251 virtual void startDrag(Qt::DropActions supportedActions);
252
253 /**
254 * Reimplemented from QAbstractItemView.
255 */
256 virtual void dragMoveEvent(QDragMoveEvent *event);
257
258 /**
259 * Reimplemented from QAbstractItemView.
260 */
261 virtual void dragEnterEvent(QDragEnterEvent *event);
262
263 /**
264 * Reimplemented from QAbstractItemView.
265 */
266 virtual void dragLeaveEvent(QDragLeaveEvent *event);
267
268 /**
269 * Reimplemented from QAbstractItemView.
270 */
271 virtual void dropEvent(QDropEvent *event);
272
273 /**
274 * Reimplemented from QAbstractItemView.
275 */
276 virtual QModelIndex moveCursor(CursorAction cursorAction,
277 Qt::KeyboardModifiers modifiers);
278
279 /**
280 * Reimplemented from QAbstractItemView.
281 */
282 virtual void rowsAboutToBeRemoved(const QModelIndex &parent,
283 int start,
284 int end);
285
286 /**
287 * Reimplemented from QAbstractItemView.
288 */
289 virtual void updateGeometries();
290
291 /**
292 * Reimplemented from QAbstractItemView.
293 */
294 virtual void currentChanged(const QModelIndex &current,
295 const QModelIndex &previous);
296
297 /**
298 * Reimplemented from QAbstractItemView.
299 */
300 virtual void dataChanged(const QModelIndex &topLeft,
301 const QModelIndex &bottomRight);
302
303 /**
304 * Reimplemented from QAbstractItemView.
305 */
306 virtual void rowsInserted(const QModelIndex &parent,
307 int start,
308 int end);
309
310protected Q_SLOTS:
311 /**
312 * @internal
313 * @warning Deprecated since 4.4.
314 */
315#ifndef KDE_NO_DEPRECATED
316 virtual KDE_DEPRECATED void rowsInsertedArtifficial(const QModelIndex &parent,
317 int start,
318 int end);
319#endif
320
321 /**
322 * @internal
323 * @warning Deprecated since 4.4.
324 */
325#ifndef KDE_NO_DEPRECATED
326 virtual KDE_DEPRECATED void rowsRemoved(const QModelIndex &parent,
327 int start,
328 int end);
329#endif
330
331 /**
332 * @internal
333 * Reposition items as needed.
334 */
335 virtual void slotLayoutChanged();
336
337private:
338 class Private;
339 Private *const d;
340
341 Q_PRIVATE_SLOT(d, void _k_slotCollapseOrExpandClicked(QModelIndex))
342};
343
344#endif // KCATEGORIZEDVIEW_H
345