1 | /* |
2 | Copyright (c) 2006 - 2008 Volker Krause <vkrause@kde.org> |
3 | |
4 | This library is free software; you can redistribute it and/or modify it |
5 | under the terms of the GNU Library General Public License as published by |
6 | the Free Software Foundation; either version 2 of the License, or (at your |
7 | option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, but WITHOUT |
10 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
12 | 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 the |
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
17 | 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "collectionmodel.h" |
21 | #include "collectionmodel_p.h" |
22 | |
23 | #include "collectionutils_p.h" |
24 | #include "collectionmodifyjob.h" |
25 | #include "entitydisplayattribute.h" |
26 | #include "monitor.h" |
27 | #include "pastehelper_p.h" |
28 | #include "session.h" |
29 | |
30 | #include <kdebug.h> |
31 | #include <kurl.h> |
32 | #include <kicon.h> |
33 | |
34 | #include <QtCore/QMimeData> |
35 | |
36 | using namespace Akonadi; |
37 | |
38 | CollectionModel::CollectionModel(QObject *parent) |
39 | : QAbstractItemModel(parent) |
40 | , d_ptr(new CollectionModelPrivate(this)) |
41 | { |
42 | Q_D(CollectionModel); |
43 | d->init(); |
44 | } |
45 | |
46 | //@cond PRIVATE |
47 | CollectionModel::CollectionModel(CollectionModelPrivate *d, QObject *parent) |
48 | : QAbstractItemModel(parent) |
49 | , d_ptr(d) |
50 | { |
51 | d->init(); |
52 | } |
53 | //@endcond |
54 | |
55 | CollectionModel::~CollectionModel() |
56 | { |
57 | Q_D(CollectionModel); |
58 | d->childCollections.clear(); |
59 | d->collections.clear(); |
60 | |
61 | delete d->monitor; |
62 | d->monitor = 0; |
63 | |
64 | delete d; |
65 | } |
66 | |
67 | int CollectionModel::columnCount(const QModelIndex &parent) const |
68 | { |
69 | if (parent.isValid() && parent.column() != 0) { |
70 | return 0; |
71 | } |
72 | return 1; |
73 | } |
74 | |
75 | QVariant CollectionModel::data(const QModelIndex &index, int role) const |
76 | { |
77 | Q_D(const CollectionModel); |
78 | if (!index.isValid()) { |
79 | return QVariant(); |
80 | } |
81 | |
82 | const Collection col = d->collections.value(index.internalId()); |
83 | if (!col.isValid()) { |
84 | return QVariant(); |
85 | } |
86 | |
87 | if (index.column() == 0 && (role == Qt::DisplayRole || role == Qt::EditRole)) { |
88 | return col.displayName(); |
89 | } |
90 | |
91 | switch (role) { |
92 | case Qt::DecorationRole: |
93 | if (index.column() == 0) { |
94 | if (col.hasAttribute<EntityDisplayAttribute>() && |
95 | !col.attribute<EntityDisplayAttribute>()->iconName().isEmpty()) { |
96 | return col.attribute<EntityDisplayAttribute>()->icon(); |
97 | } |
98 | return KIcon(CollectionUtils::defaultIconName(col)); |
99 | } |
100 | break; |
101 | case OldCollectionIdRole: // fall-through |
102 | case CollectionIdRole: |
103 | return col.id(); |
104 | case OldCollectionRole: // fall-through |
105 | case CollectionRole: |
106 | return QVariant::fromValue(col); |
107 | } |
108 | return QVariant(); |
109 | } |
110 | |
111 | QModelIndex CollectionModel::index(int row, int column, const QModelIndex &parent) const |
112 | { |
113 | Q_D(const CollectionModel); |
114 | if (column >= columnCount() || column < 0) { |
115 | return QModelIndex(); |
116 | } |
117 | |
118 | QVector<Collection::Id> list; |
119 | if (!parent.isValid()) { |
120 | list = d->childCollections.value(Collection::root().id()); |
121 | } else { |
122 | if (parent.column() > 0) { |
123 | return QModelIndex(); |
124 | } |
125 | list = d->childCollections.value(parent.internalId()); |
126 | } |
127 | |
128 | if (row < 0 || row >= list.size()) { |
129 | return QModelIndex(); |
130 | } |
131 | if (!d->collections.contains(list.at(row))) { |
132 | return QModelIndex(); |
133 | } |
134 | return createIndex(row, column, reinterpret_cast<void *>(d->collections.value(list.at(row)).id())); |
135 | } |
136 | |
137 | QModelIndex CollectionModel::parent(const QModelIndex &index) const |
138 | { |
139 | Q_D(const CollectionModel); |
140 | if (!index.isValid()) { |
141 | return QModelIndex(); |
142 | } |
143 | |
144 | const Collection col = d->collections.value(index.internalId()); |
145 | if (!col.isValid()) { |
146 | return QModelIndex(); |
147 | } |
148 | |
149 | const Collection parentCol = d->collections.value(col.parentCollection().id()); |
150 | if (!parentCol.isValid()) { |
151 | return QModelIndex(); |
152 | } |
153 | QVector<Collection::Id> list; |
154 | list = d->childCollections.value(parentCol.parentCollection().id()); |
155 | |
156 | int parentRow = list.indexOf(parentCol.id()); |
157 | if (parentRow < 0) { |
158 | return QModelIndex(); |
159 | } |
160 | |
161 | return createIndex(parentRow, 0, reinterpret_cast<void *>(parentCol.id())); |
162 | } |
163 | |
164 | int CollectionModel::rowCount(const QModelIndex &parent) const |
165 | { |
166 | const Q_D(CollectionModel); |
167 | QVector<Collection::Id> list; |
168 | if (parent.isValid()) { |
169 | list = d->childCollections.value(parent.internalId()); |
170 | } else { |
171 | list = d->childCollections.value(Collection::root().id()); |
172 | } |
173 | |
174 | return list.size(); |
175 | } |
176 | |
177 | QVariant CollectionModel::(int section, Qt::Orientation orientation, int role) const |
178 | { |
179 | const Q_D(CollectionModel); |
180 | |
181 | if (section == 0 && orientation == Qt::Horizontal && role == Qt::DisplayRole) { |
182 | return d->headerContent; |
183 | } |
184 | return QAbstractItemModel::headerData(section, orientation, role); |
185 | } |
186 | |
187 | bool CollectionModel::(int section, Qt::Orientation orientation, const QVariant &value, int role) |
188 | { |
189 | Q_D(CollectionModel); |
190 | |
191 | if (section == 0 && orientation == Qt::Horizontal && role == Qt::EditRole) { |
192 | d->headerContent = value.toString(); |
193 | return true; |
194 | } |
195 | |
196 | return false; |
197 | } |
198 | |
199 | bool CollectionModel::setData(const QModelIndex &index, const QVariant &value, int role) |
200 | { |
201 | Q_D(CollectionModel); |
202 | if (index.column() == 0 && role == Qt::EditRole) { |
203 | // rename collection |
204 | Collection col = d->collections.value(index.internalId()); |
205 | if (!col.isValid() || value.toString().isEmpty()) { |
206 | return false; |
207 | } |
208 | col.setName(value.toString()); |
209 | CollectionModifyJob *job = new CollectionModifyJob(col, d->session); |
210 | connect(job, SIGNAL(result(KJob*)), SLOT(editDone(KJob*))); |
211 | return true; |
212 | } |
213 | return QAbstractItemModel::setData(index, value, role); |
214 | } |
215 | |
216 | Qt::ItemFlags CollectionModel::flags(const QModelIndex &index) const |
217 | { |
218 | Q_D(const CollectionModel); |
219 | |
220 | // Pass modeltest. |
221 | if (!index.isValid()) { |
222 | return 0; |
223 | } |
224 | |
225 | Qt::ItemFlags flags = QAbstractItemModel::flags(index); |
226 | |
227 | flags = flags | Qt::ItemIsDragEnabled; |
228 | |
229 | Collection col; |
230 | if (index.isValid()) { |
231 | col = d->collections.value(index.internalId()); |
232 | Q_ASSERT(col.isValid()); |
233 | } else { |
234 | return flags | Qt::ItemIsDropEnabled; // HACK Workaround for a probable bug in Qt |
235 | } |
236 | |
237 | if (col.isValid()) { |
238 | if (col.rights() & (Collection::CanChangeCollection | |
239 | Collection::CanCreateCollection | |
240 | Collection::CanDeleteCollection | |
241 | Collection::CanCreateItem)) { |
242 | if (index.column() == 0) { |
243 | flags = flags | Qt::ItemIsEditable; |
244 | } |
245 | flags = flags | Qt::ItemIsDropEnabled; |
246 | } |
247 | } |
248 | |
249 | return flags; |
250 | } |
251 | |
252 | Qt::DropActions CollectionModel::supportedDropActions() const |
253 | { |
254 | return Qt::CopyAction | Qt::MoveAction; |
255 | } |
256 | |
257 | QStringList CollectionModel::mimeTypes() const |
258 | { |
259 | return QStringList() << QLatin1String("text/uri-list" ); |
260 | } |
261 | |
262 | QMimeData *CollectionModel::mimeData(const QModelIndexList &indexes) const |
263 | { |
264 | QMimeData *data = new QMimeData(); |
265 | KUrl::List urls; |
266 | foreach (const QModelIndex &index, indexes) { |
267 | if (index.column() != 0) { |
268 | continue; |
269 | } |
270 | |
271 | urls << Collection(index.internalId()).url(); |
272 | } |
273 | urls.populateMimeData(data); |
274 | |
275 | return data; |
276 | } |
277 | |
278 | bool CollectionModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) |
279 | { |
280 | Q_D(CollectionModel); |
281 | if (!(action & supportedDropActions())) { |
282 | return false; |
283 | } |
284 | |
285 | // handle drops onto items as well as drops between items |
286 | QModelIndex idx; |
287 | if (row >= 0 && column >= 0) { |
288 | idx = index(row, column, parent); |
289 | } else { |
290 | idx = parent; |
291 | } |
292 | |
293 | if (!idx.isValid()) { |
294 | return false; |
295 | } |
296 | |
297 | const Collection parentCol = d->collections.value(idx.internalId()); |
298 | if (!parentCol.isValid()) { |
299 | return false; |
300 | } |
301 | |
302 | KJob *job = PasteHelper::paste(data, parentCol, action != Qt::MoveAction); |
303 | connect(job, SIGNAL(result(KJob*)), SLOT(dropResult(KJob*))); |
304 | return true; |
305 | } |
306 | |
307 | Collection CollectionModel::collectionForId(Collection::Id id) const |
308 | { |
309 | Q_D(const CollectionModel); |
310 | return d->collections.value(id); |
311 | } |
312 | |
313 | void CollectionModel::fetchCollectionStatistics(bool enable) |
314 | { |
315 | Q_D(CollectionModel); |
316 | d->fetchStatistics = enable; |
317 | d->monitor->fetchCollectionStatistics(enable); |
318 | } |
319 | |
320 | void CollectionModel::includeUnsubscribed(bool include) |
321 | { |
322 | Q_D(CollectionModel); |
323 | d->unsubscribed = include; |
324 | } |
325 | |
326 | #include "moc_collectionmodel.cpp" |
327 | |