• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.14.3 API Reference
  • KDE Home
  • Contact Us
 

akonadi

  • home
  • ichiro
  • data
  • ssd
  • Momonga
  • trunk
  • pkgs
  • kdepimlibs
  • BUILD
  • kdepimlibs-4.14.3
  • akonadi
favoritecollectionsmodel.cpp
1 /*
2  Copyright (c) 2009 Kevin Ottens <ervin@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 "favoritecollectionsmodel.h"
21 
22 #include <QItemSelectionModel>
23 #include <QtCore/QMimeData>
24 
25 #include <kconfiggroup.h>
26 #include <klocale.h>
27 #include <klocalizedstring.h>
28 #include <KJob>
29 #include <KUrl>
30 
31 #include "entitytreemodel.h"
32 #include "mimetypechecker.h"
33 #include "pastehelper_p.h"
34 
35 using namespace Akonadi;
36 
40 class FavoriteCollectionsModel::Private
41 {
42 public:
43  Private(const KConfigGroup &group, FavoriteCollectionsModel *parent)
44  : q(parent)
45  , configGroup(group)
46  {
47  }
48 
49  QString labelForCollection(Collection::Id collectionId) const
50  {
51  if (labelMap.contains(collectionId)) {
52  return labelMap[collectionId];
53  }
54 
55  const QModelIndex collectionIdx = EntityTreeModel::modelIndexForCollection(q->sourceModel(), Collection(collectionId));
56 
57  QString accountName;
58 
59  const QString nameOfCollection = collectionIdx.data().toString();
60 
61  QModelIndex idx = collectionIdx.parent();
62  while (idx != QModelIndex()) {
63  accountName = idx.data().toString();
64  idx = idx.parent();
65  }
66 
67  if (accountName.isEmpty()) {
68  return nameOfCollection;
69  } else {
70  return nameOfCollection + QLatin1String(" (") + accountName + QLatin1Char(')');
71  }
72  }
73 
74  void insertIfAvailable(Collection::Id col)
75  {
76  if (collectionIds.contains(col)) {
77  select(col);
78  if (!referencedCollections.contains(col)) {
79  reference(col);
80  }
81  }
82  }
83 
84  void insertIfAvailable(const QModelIndex &idx)
85  {
86  insertIfAvailable(idx.data(EntityTreeModel::CollectionIdRole).value<Collection::Id>());
87  }
88 
92  void reload()
93  {
94  //don't clear the selection model here. Otherwise we mess up the users selection as collections get removed and re-inserted.
95  foreach (const Collection::Id &collectionId, collectionIds) {
96  insertIfAvailable(collectionId);
97  }
98  //TODO remove what's no longer here
99  }
100 
101  void rowsInserted(const QModelIndex &parent, int begin, int end)
102  {
103  for (int row = begin; row <= end; row++) {
104  const QModelIndex child = parent.child(row, 0);
105  if (!child.isValid()) {
106  continue;
107  }
108  insertIfAvailable(child);
109  const int childRows = q->sourceModel()->rowCount(child);
110  if (childRows > 0) {
111  rowsInserted(child, 0, childRows - 1);
112  }
113  }
114  }
115 
116  void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
117  {
118  for (int row = topLeft.row(); row <= bottomRight.row(); row++) {
119  const QModelIndex idx = topLeft.parent().child(row, 0);
120  insertIfAvailable(idx);
121  }
122  }
123 
127  void select(const Collection::Id &collectionId)
128  {
129  const QModelIndex index = EntityTreeModel::modelIndexForCollection(q->sourceModel(), Collection(collectionId));
130  if (index.isValid()) {
131  q->selectionModel()->select(index, QItemSelectionModel::Select);
132  }
133  }
134 
135  void deselect(const Collection::Id &collectionId)
136  {
137  const QModelIndex idx = EntityTreeModel::modelIndexForCollection(q->sourceModel(), Collection(collectionId));
138  if (idx.isValid()) {
139  q->selectionModel()->select(idx, QItemSelectionModel::Deselect);
140  }
141  }
142 
143  void reference(const Collection::Id &collectionId)
144  {
145  if (referencedCollections.contains(collectionId)) {
146  kWarning() << "already referenced" << collectionId;
147  return;
148  }
149  const QModelIndex index = EntityTreeModel::modelIndexForCollection(q->sourceModel(), Collection(collectionId));
150  if (index.isValid()) {
151  if (q->sourceModel()->setData(index, QVariant(), EntityTreeModel::CollectionRefRole)) {
152  referencedCollections << collectionId;
153  } else {
154  kWarning() << "failed to reference collection";
155  }
156  q->sourceModel()->fetchMore(index);
157  }
158  }
159 
160  void dereference(const Collection::Id &collectionId)
161  {
162  if (!referencedCollections.contains(collectionId)) {
163  kWarning() << "not referenced" << collectionId;
164  return;
165  }
166  const QModelIndex index = EntityTreeModel::modelIndexForCollection(q->sourceModel(), Collection(collectionId));
167  if (index.isValid()) {
168  q->sourceModel()->setData(index, QVariant(), EntityTreeModel::CollectionDerefRole);
169  }
170  referencedCollections.remove(collectionId);
171  }
172 
173  void clearReferences()
174  {
175  foreach (const Collection::Id &collectionId, referencedCollections) {
176  dereference(collectionId);
177  }
178  }
179 
183  void add(const Collection::Id &collectionId)
184  {
185  if (collectionIds.contains(collectionId)) {
186  kDebug() << "already in model " << collectionId;
187  return;
188  }
189  collectionIds << collectionId;
190  reference(collectionId);
191  select(collectionId);
192  }
193 
194  void remove(const Collection::Id &collectionId)
195  {
196  collectionIds.removeAll(collectionId);
197  labelMap.remove(collectionId);
198  dereference(collectionId);
199  deselect(collectionId);
200  }
201 
202  void set(const QList<Collection::Id> &collections)
203  {
204  QList<Collection::Id> colIds = collectionIds;
205  foreach (const Collection::Id &col, collections) {
206  const int removed = colIds.removeAll(col);
207  const bool isNewCollection = removed <= 0;
208  if (isNewCollection) {
209  add(col);
210  }
211  }
212  //Remove what's left
213  foreach (const Akonadi::Collection::Id &colId, colIds) {
214  remove(colId);
215  }
216  }
217 
218  void set(const Akonadi::Collection::List &collections)
219  {
220  QList<Akonadi::Collection::Id> colIds;
221  foreach (const Akonadi::Collection &col, collections) {
222  colIds << col.id();
223  }
224  set(colIds);
225  }
226 
227  void loadConfig()
228  {
229  const QList<Collection::Id> collections = configGroup.readEntry("FavoriteCollectionIds", QList<qint64>());
230  const QStringList labels = configGroup.readEntry("FavoriteCollectionLabels", QStringList());
231  const int numberOfLabels(labels.size());
232  for (int i = 0; i < collections.size(); ++i) {
233  if (i < numberOfLabels) {
234  labelMap[collections[i]] = labels[i];
235  }
236  add(collections[i]);
237  }
238  }
239 
240  void saveConfig()
241  {
242  QStringList labels;
243 
244  foreach (const Collection::Id &collectionId, collectionIds) {
245  labels << labelForCollection(collectionId);
246  }
247 
248  configGroup.writeEntry("FavoriteCollectionIds", collectionIds);
249  configGroup.writeEntry("FavoriteCollectionLabels", labels);
250  configGroup.config()->sync();
251  }
252 
253  FavoriteCollectionsModel *const q;
254 
255  QList<Collection::Id> collectionIds;
256  QSet<Collection::Id> referencedCollections;
257  QHash<qint64, QString> labelMap;
258  KConfigGroup configGroup;
259 };
260 
261 FavoriteCollectionsModel::FavoriteCollectionsModel(QAbstractItemModel *source, const KConfigGroup &group, QObject *parent)
262  : Akonadi::SelectionProxyModel(new QItemSelectionModel(source, parent), parent)
263  , d(new Private(group, this))
264 {
265  //This should only be a KRecursiveFilterProxyModel, but remains a SelectionProxyModel for backwards compatiblity.
266  // We therefore disable what we anyways don't want (the referencing is handled separately).
267  disconnect(this, SIGNAL(rootIndexAdded(QModelIndex)), this, SLOT(rootIndexAdded(QModelIndex)));
268  disconnect(this, SIGNAL(rootIndexAboutToBeRemoved(QModelIndex)), this, SLOT(rootIndexAboutToBeRemoved(QModelIndex)));
269 
270  setSourceModel(source);
271  setFilterBehavior(ExactSelection);
272 
273  d->loadConfig();
274  //React to various changes in the source model
275  connect(source, SIGNAL(modelReset()), this, SLOT(reload()));
276  connect(source, SIGNAL(layoutChanged()), this, SLOT(reload()));
277  connect(source, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(rowsInserted(QModelIndex,int,int)));
278  connect(source, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(dataChanged(QModelIndex,QModelIndex)));
279 }
280 
281 FavoriteCollectionsModel::~FavoriteCollectionsModel()
282 {
283  delete d;
284 }
285 
286 void FavoriteCollectionsModel::setCollections(const Collection::List &collections)
287 {
288  d->set(collections);
289  d->saveConfig();
290 }
291 
292 void FavoriteCollectionsModel::addCollection(const Collection &collection)
293 {
294  d->add(collection.id());
295  d->saveConfig();
296 }
297 
298 void FavoriteCollectionsModel::removeCollection(const Collection &collection)
299 {
300  d->remove(collection.id());
301  d->saveConfig();
302 }
303 
304 Akonadi::Collection::List FavoriteCollectionsModel::collections() const
305 {
306  Collection::List cols;
307  foreach (const Collection::Id &colId, d->collectionIds) {
308  const QModelIndex idx = EntityTreeModel::modelIndexForCollection(sourceModel(), Collection(colId));
309  const Collection collection = sourceModel()->data(idx, EntityTreeModel::CollectionRole).value<Collection>();
310  cols << collection;
311  }
312  return cols;
313 }
314 
315 QList<Collection::Id> FavoriteCollectionsModel::collectionIds() const
316 {
317  return d->collectionIds;
318 }
319 
320 void Akonadi::FavoriteCollectionsModel::setFavoriteLabel(const Collection &collection, const QString &label)
321 {
322  Q_ASSERT(d->collectionIds.contains(collection.id()));
323  d->labelMap[collection.id()] = label;
324  d->saveConfig();
325 
326  const QModelIndex idx = EntityTreeModel::modelIndexForCollection(sourceModel(), collection);
327 
328  if (!idx.isValid()) {
329  return;
330  }
331 
332  const QModelIndex index = mapFromSource(idx);
333  emit dataChanged(index, index);
334 }
335 
336 QVariant Akonadi::FavoriteCollectionsModel::data(const QModelIndex &index, int role) const
337 {
338  if (index.column() == 0 &&
339  (role == Qt::DisplayRole ||
340  role == Qt::EditRole)) {
341  const QModelIndex sourceIndex = mapToSource(index);
342  const Collection::Id collectionId = sourceModel()->data(sourceIndex, EntityTreeModel::CollectionIdRole).toLongLong();
343 
344  return d->labelForCollection(collectionId);
345  } else {
346  return KSelectionProxyModel::data(index, role);
347  }
348 }
349 
350 bool FavoriteCollectionsModel::setData(const QModelIndex &index, const QVariant &value, int role)
351 {
352  if (index.isValid() && index.column() == 0 &&
353  role == Qt::EditRole) {
354  const QString newLabel = value.toString();
355  if (newLabel.isEmpty()) {
356  return false;
357  }
358  const QModelIndex sourceIndex = mapToSource(index);
359  const Collection collection = sourceModel()->data(sourceIndex, EntityTreeModel::CollectionRole).value<Collection>();
360  setFavoriteLabel(collection, newLabel);
361  return true;
362  }
363  return Akonadi::SelectionProxyModel::setData(index, value, role);
364 }
365 
366 QString Akonadi::FavoriteCollectionsModel::favoriteLabel(const Akonadi::Collection &collection)
367 {
368  if (!collection.isValid()) {
369  return QString();
370  }
371  return d->labelForCollection(collection.id());
372 }
373 
374 QVariant FavoriteCollectionsModel::headerData(int section, Qt::Orientation orientation, int role) const
375 {
376  if (section == 0 &&
377  orientation == Qt::Horizontal &&
378  role == Qt::DisplayRole) {
379  return i18n("Favorite Folders");
380  } else {
381  return KSelectionProxyModel::headerData(section, orientation, role);
382  }
383 }
384 
385 bool FavoriteCollectionsModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
386 {
387  Q_UNUSED(action);
388  Q_UNUSED(row);
389  Q_UNUSED(column);
390  if (data->hasFormat(QLatin1String("text/uri-list"))) {
391  const KUrl::List urls = KUrl::List::fromMimeData(data);
392 
393  const QModelIndex sourceIndex = mapToSource(parent);
394  const Collection destCollection = sourceModel()->data(sourceIndex, EntityTreeModel::CollectionRole).value<Collection>();
395 
396  MimeTypeChecker mimeChecker;
397  mimeChecker.setWantedMimeTypes(destCollection.contentMimeTypes());
398 
399  foreach (const KUrl &url, urls) {
400  const Collection col = Collection::fromUrl(url);
401  if (col.isValid()) {
402  addCollection(col);
403  } else {
404  const Item item = Item::fromUrl(url);
405  if (item.isValid()) {
406  if (item.parentCollection().id() == destCollection.id() &&
407  action != Qt::CopyAction) {
408  kDebug() << "Error: source and destination of move are the same.";
409  return false;
410  }
411 #if 0
412  if (!mimeChecker.isWantedItem(item)) {
413  kDebug() << "unwanted item" << mimeChecker.wantedMimeTypes() << item.mimeType();
414  return false;
415  }
416 #endif
417  KJob *job = PasteHelper::pasteUriList(data, destCollection, action);
418  if (!job) {
419  return false;
420  }
421  connect(job, SIGNAL(result(KJob*)), SLOT(pasteJobDone(KJob*)));
422  // Accept the event so that it doesn't propagate.
423  return true;
424 
425  }
426  }
427 
428  }
429  return true;
430  }
431  return false;
432 }
433 
434 QStringList FavoriteCollectionsModel::mimeTypes() const
435 {
436  QStringList mts = Akonadi::SelectionProxyModel::mimeTypes();
437  if (!mts.contains(QLatin1String("text/uri-list"))) {
438  mts.append(QLatin1String("text/uri-list"));
439  }
440  return mts;
441 }
442 
443 Qt::ItemFlags FavoriteCollectionsModel::flags(const QModelIndex &index) const
444 {
445  Qt::ItemFlags fs = Akonadi::SelectionProxyModel::flags(index);
446  if (!index.isValid()) {
447  fs |= Qt::ItemIsDropEnabled;
448  }
449  return fs;
450 }
451 
452 void FavoriteCollectionsModel::pasteJobDone(KJob *job)
453 {
454  if (job->error()) {
455  kDebug() << job->errorString();
456  }
457 }
458 
459 #include "moc_favoritecollectionsmodel.cpp"
Akonadi::EntityTreeModel::CollectionIdRole
The collection id.
Definition: entitytreemodel.h:335
Akonadi::EntityTreeModel::CollectionRefRole
Definition: entitytreemodel.h:346
Akonadi::SelectionProxyModel
A proxy model used to reference count selected Akonadi::Collection in a view.
Definition: selectionproxymodel.h:99
Akonadi::Collection
Represents a collection of PIM items.
Definition: collection.h:75
Akonadi::FavoriteCollectionsModel::setCollections
void setCollections(const Collection::List &collections)
Sets the collections as favorite collections.
Definition: favoritecollectionsmodel.cpp:286
Akonadi::Entity::Id
qint64 Id
Describes the unique id type.
Definition: entity.h:65
Akonadi::PasteHelper::pasteUriList
KJob * pasteUriList(const QMimeData *mimeData, const Collection &collection, Qt::DropAction action, Session *session=0)
URI list paste/drop.
Definition: pastehelper.cpp:307
Akonadi::MimeTypeChecker
Helper for checking MIME types of Collections and Items.
Definition: mimetypechecker.h:109
Akonadi::FavoriteCollectionsModel::FavoriteCollectionsModel
FavoriteCollectionsModel(QAbstractItemModel *model, const KConfigGroup &group, QObject *parent=0)
Creates a new favorite collections model.
Definition: favoritecollectionsmodel.cpp:261
Akonadi::FavoriteCollectionsModel::setFavoriteLabel
void setFavoriteLabel(const Collection &collection, const QString &label)
Sets a custom label that will be used when showing the favorite collection.
Definition: favoritecollectionsmodel.cpp:320
Akonadi::FavoriteCollectionsModel::addCollection
void addCollection(const Collection &collection)
Adds a collection to the list of favorite collections.
Definition: favoritecollectionsmodel.cpp:292
Akonadi::Entity::id
Id id() const
Returns the unique identifier of the entity.
Definition: entity.cpp:72
Akonadi::EntityTreeModel::CollectionRole
The collection.
Definition: entitytreemodel.h:336
Akonadi::FavoriteCollectionsModel::collections
Collection::List collections() const
Returns the list of favorite collections.
Definition: favoritecollectionsmodel.cpp:304
Akonadi::EntityTreeModel::modelIndexForCollection
static QModelIndex modelIndexForCollection(const QAbstractItemModel *model, const Collection &collection)
Returns a QModelIndex in model which points to collection.
Definition: entitytreemodel.cpp:1235
Akonadi::FavoriteCollectionsModel::collectionIds
QList< Collection::Id > collectionIds() const
Returns the list of ids of favorite collections set on the FavoriteCollectionsModel.
Definition: favoritecollectionsmodel.cpp:315
Akonadi::FavoriteCollectionsModel::removeCollection
void removeCollection(const Collection &collection)
Removes a collection from the list of favorite collections.
Definition: favoritecollectionsmodel.cpp:298
Akonadi::MimeTypeChecker::setWantedMimeTypes
void setWantedMimeTypes(const QStringList &mimeTypes)
Sets the list of wanted MIME types this instance checks against.
Definition: mimetypechecker.cpp:57
Akonadi::FavoriteCollectionsModel::favoriteLabel
QString favoriteLabel(const Akonadi::Collection &col)
Return associate label for collection.
Definition: favoritecollectionsmodel.cpp:366
Akonadi::FavoriteCollectionsModel::~FavoriteCollectionsModel
virtual ~FavoriteCollectionsModel()
Destroys the favorite collections model.
Definition: favoritecollectionsmodel.cpp:281
Akonadi
FreeBusyManager::Singleton.
Definition: actionstatemanager_p.h:28
Akonadi::Collection::contentMimeTypes
QStringList contentMimeTypes() const
Returns a list of possible content mimetypes, e.g.
Definition: collection.cpp:115
Akonadi::Collection::fromUrl
static Collection fromUrl(const KUrl &url)
Creates a collection from the given url.
Definition: collection.cpp:172
Akonadi::Collection::List
QList< Collection > List
Describes a list of collections.
Definition: collection.h:81
Akonadi::EntityTreeModel::CollectionDerefRole
Definition: entitytreemodel.h:347
Akonadi::FavoriteCollectionsModel
A model that lists a set of favorite collections.
Definition: favoritecollectionsmodel.h:66
Akonadi::Entity::isValid
bool isValid() const
Returns whether the entity is valid.
Definition: entity.cpp:97
This file is part of the KDE documentation.
Documentation copyright © 1996-2018 The KDE developers.
Generated on Fri Oct 19 2018 17:54:58 by doxygen 1.8.13 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Modules
  • Related Pages

kdepimlibs-4.14.3 API Reference

Skip menu "kdepimlibs-4.14.3 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal