1 | /*************************************************************************** |
2 | * Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com> * |
3 | * * |
4 | * Based on the Itemviews NG project from Trolltech Labs: * |
5 | * http://qt.gitorious.org/qt-labs/itemviews-ng * |
6 | * * |
7 | * This program is free software; you can redistribute it and/or modify * |
8 | * it under the terms of the GNU General Public License as published by * |
9 | * the Free Software Foundation; either version 2 of the License, or * |
10 | * (at your option) any later version. * |
11 | * * |
12 | * This program is distributed in the hope that it will be useful, * |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
15 | * GNU General Public License for more details. * |
16 | * * |
17 | * You should have received a copy of the GNU General Public License * |
18 | * along with this program; if not, write to the * |
19 | * Free Software Foundation, Inc., * |
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * |
21 | ***************************************************************************/ |
22 | |
23 | #ifndef KITEMMODELBASE_H |
24 | #define KITEMMODELBASE_H |
25 | |
26 | #include <libdolphin_export.h> |
27 | |
28 | #include <kitemviews/kitemrange.h> |
29 | #include <kitemviews/kitemset.h> |
30 | |
31 | #include <QHash> |
32 | #include <QObject> |
33 | #include <QVariant> |
34 | |
35 | class QMimeData; |
36 | |
37 | /** |
38 | * @brief Base class for model implementations used by KItemListView and KItemListController. |
39 | * |
40 | * An item-model consists of a variable number of items. The number of items |
41 | * is given by KItemModelBase::count(). The data of an item is accessed by a unique index |
42 | * with KItemModelBase::data(). The indexes are integer-values counting from 0 to the |
43 | * KItemModelBase::count() - 1. |
44 | * |
45 | * One item consists of a variable number of role/value-pairs. |
46 | * |
47 | * A model can optionally provide sorting- and grouping-capabilities. |
48 | * |
49 | * Also optionally it is possible to provide a tree of items by implementing the methods |
50 | * setExpanded(), isExpanded(), isExpandable() and expandedParentsCount(). |
51 | */ |
52 | class LIBDOLPHINPRIVATE_EXPORT KItemModelBase : public QObject |
53 | { |
54 | Q_OBJECT |
55 | |
56 | public: |
57 | KItemModelBase(QObject* parent = 0); |
58 | explicit KItemModelBase(const QByteArray& sortRole, QObject* parent = 0); |
59 | virtual ~KItemModelBase(); |
60 | |
61 | /** @return The number of items. */ |
62 | virtual int count() const = 0; |
63 | |
64 | virtual QHash<QByteArray, QVariant> data(int index) const = 0; |
65 | |
66 | /** |
67 | * Sets the data for the item at \a index to the given \a values. Returns true |
68 | * if the data was set on the item; returns false otherwise. |
69 | * |
70 | * The default implementation does not set the data, and will always return |
71 | * false. |
72 | */ |
73 | virtual bool setData(int index, const QHash<QByteArray, QVariant>& values); |
74 | |
75 | /** |
76 | * Enables/disables the grouped sorting. The method KItemModelBase::onGroupedSortingChanged() will be |
77 | * called so that model-implementations can react on the grouped-sorting change. Afterwards the |
78 | * signal groupedSortingChanged() will be emitted. If the grouped sorting is enabled, the method |
79 | * KItemModelBase::groups() must be implemented. |
80 | */ |
81 | void setGroupedSorting(bool grouped); |
82 | bool groupedSorting() const; |
83 | |
84 | /** |
85 | * Sets the sort-role to \a role. The method KItemModelBase::onSortRoleChanged() will be |
86 | * called so that model-implementations can react on the sort-role change. Afterwards the |
87 | * signal sortRoleChanged() will be emitted. |
88 | */ |
89 | void setSortRole(const QByteArray& role); |
90 | QByteArray sortRole() const; |
91 | |
92 | /** |
93 | * Sets the sort order to \a order. The method KItemModelBase::onSortOrderChanged() will be |
94 | * called so that model-implementations can react on the sort order change. Afterwards the |
95 | * signal sortOrderChanged() will be emitted. |
96 | */ |
97 | void setSortOrder(Qt::SortOrder order); |
98 | Qt::SortOrder sortOrder() const; |
99 | |
100 | /** |
101 | * @return Translated description for the \p role. The description is e.g. used |
102 | * for the header in KItemListView. |
103 | */ |
104 | virtual QString roleDescription(const QByteArray& role) const; |
105 | |
106 | /** |
107 | * @return List of group headers. Each list-item consists of the index of the item |
108 | * that represents the first item of a group and a value represented |
109 | * as QVariant. The value is shown by an instance of KItemListGroupHeader. |
110 | * Per default an empty list is returned. |
111 | */ |
112 | virtual QList<QPair<int, QVariant> > groups() const; |
113 | |
114 | /** |
115 | * Expands the item with the index \a index if \a expanded is true. |
116 | * If \a expanded is false the item will be collapsed. |
117 | * |
118 | * Per default no expanding of items is implemented. When implementing |
119 | * this method it is mandatory to overwrite KItemModelBase::isExpandable() |
120 | * and KItemListView::supportsExpandableItems() to return true. |
121 | * |
122 | * @return True if the operation has been successful. |
123 | */ |
124 | virtual bool setExpanded(int index, bool expanded); |
125 | |
126 | /** |
127 | * @return True if the item with the index \a index is expanded. |
128 | * Per default no expanding of items is implemented. When implementing |
129 | * this method it is mandatory to overwrite KItemModelBase::isExpandable() |
130 | * and KItemListView::supportsExpandableItems() to return true. |
131 | */ |
132 | virtual bool isExpanded(int index) const; |
133 | |
134 | /** |
135 | * @return True if expanding and collapsing of the item with the index \a index |
136 | * is supported. Per default false is returned. |
137 | */ |
138 | virtual bool isExpandable(int index) const; |
139 | |
140 | /** |
141 | * @return Number of expanded parent items for the item with the given index. |
142 | * Per default 0 is returned. |
143 | */ |
144 | virtual int expandedParentsCount(int index) const; |
145 | |
146 | /** |
147 | * @return MIME-data for the items given by \a indexes. The default implementation |
148 | * returns 0. The ownership of the returned instance is in the hand of the |
149 | * caller of this method. The method must be implemented if dragging of |
150 | * items should be possible. |
151 | */ |
152 | virtual QMimeData* createMimeData(const KItemSet& indexes) const; |
153 | |
154 | /** |
155 | * @return Reimplement this to return the index for the first item |
156 | * beginning with string typed in through the keyboard, -1 if not found. |
157 | * @param text the text which has been typed in through the keyboard |
158 | * @param startFromIndex the index from which to start searching from |
159 | */ |
160 | virtual int indexForKeyboardSearch(const QString& text, int startFromIndex = 0) const; |
161 | |
162 | /** |
163 | * @return True, if the item with the index \a index basically supports dropping. |
164 | * Per default false is returned. |
165 | * |
166 | * The information is used only to give a visual feedback during a drag operation |
167 | * and not to decide whether a drop event gets emitted. It is it is still up to |
168 | * the receiver of KItemListController::itemDropEvent() to decide how to handle |
169 | * the drop event. |
170 | */ |
171 | // TODO: Should the MIME-data be passed too so that the model can do a more specific |
172 | // decision whether it accepts the drop? |
173 | virtual bool supportsDropping(int index) const; |
174 | |
175 | signals: |
176 | /** |
177 | * Is emitted if one or more items have been inserted. Each item-range consists |
178 | * of: |
179 | * - an index where items have been inserted |
180 | * - the number of inserted items. |
181 | * The index of each item-range represents the index of the model |
182 | * before the items have been inserted. |
183 | * |
184 | * For the item-ranges it is assured that: |
185 | * - They don't overlap |
186 | * - The index of item-range n is smaller than the index of item-range n + 1. |
187 | */ |
188 | void itemsInserted(const KItemRangeList& itemRanges); |
189 | |
190 | /** |
191 | * Is emitted if one or more items have been removed. Each item-range consists |
192 | * of: |
193 | * - an index where items have been inserted |
194 | * - the number of inserted items. |
195 | * The index of each item-range represents the index of the model |
196 | * before the items have been removed. |
197 | * |
198 | * For the item-ranges it is assured that: |
199 | * - They don't overlap |
200 | * - The index of item-range n is smaller than the index of item-range n + 1. |
201 | */ |
202 | void itemsRemoved(const KItemRangeList& itemRanges); |
203 | |
204 | /** |
205 | * Is emitted if one ore more items get moved. |
206 | * @param itemRange Item-range that gets moved to a new position. |
207 | * @param movedToIndexes New positions for each element of the item-range. |
208 | * |
209 | * For example if the model has 10 items and the items 0 and 1 get exchanged |
210 | * with the items 5 and 6 then the parameters look like this: |
211 | * - itemRange: has the index 0 and a count of 7. |
212 | * - movedToIndexes: Contains the seven values 5, 6, 2, 3, 4, 0, 1 |
213 | * |
214 | * This signal implies that the groups might have changed. Therefore, |
215 | * gropusChanged() is not emitted if this signal is emitted. |
216 | */ |
217 | void itemsMoved(const KItemRange& itemRange, const QList<int>& movedToIndexes); |
218 | |
219 | void itemsChanged(const KItemRangeList& itemRanges, const QSet<QByteArray>& roles); |
220 | |
221 | /** |
222 | * Is emitted if the groups have changed, even though the order of the |
223 | * items has not been modified. |
224 | */ |
225 | void groupsChanged(); |
226 | |
227 | void groupedSortingChanged(bool current); |
228 | void sortRoleChanged(const QByteArray& current, const QByteArray& previous); |
229 | void sortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous); |
230 | |
231 | protected: |
232 | /** |
233 | * Is invoked if the grouped sorting has been changed by KItemModelBase::setGroupedSorting(). Allows |
234 | * to react on the changed grouped sorting before the signal groupedSortingChanged() will be emitted. |
235 | */ |
236 | virtual void onGroupedSortingChanged(bool current); |
237 | |
238 | /** |
239 | * Is invoked if the sort role has been changed by KItemModelBase::setSortRole(). Allows |
240 | * to react on the changed sort role before the signal sortRoleChanged() will be emitted. |
241 | * The implementation must assure that the items are sorted by the role given by \a current. |
242 | * Usually the most efficient way is to emit a |
243 | * itemsRemoved() signal for all items, reorder the items internally and to emit a |
244 | * itemsInserted() signal afterwards. |
245 | */ |
246 | virtual void onSortRoleChanged(const QByteArray& current, const QByteArray& previous); |
247 | |
248 | /** |
249 | * Is invoked if the sort order has been changed by KItemModelBase::setSortOrder(). Allows |
250 | * to react on the changed sort order before the signal sortOrderChanged() will be emitted. |
251 | * The implementation must assure that the items are sorted by the order given by \a current. |
252 | * Usually the most efficient way is to emit a |
253 | * itemsRemoved() signal for all items, reorder the items internally and to emit a |
254 | * itemsInserted() signal afterwards. |
255 | */ |
256 | virtual void onSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous); |
257 | |
258 | private: |
259 | bool m_groupedSorting; |
260 | QByteArray m_sortRole; |
261 | Qt::SortOrder m_sortOrder; |
262 | }; |
263 | |
264 | inline Qt::SortOrder KItemModelBase::sortOrder() const |
265 | { |
266 | return m_sortOrder; |
267 | } |
268 | |
269 | #endif |
270 | |
271 | |
272 | |