• Skip to content
  • Skip to link menu
Brand

API Documentation

  1. KDE API Reference
  2. KDE PIM
  3. Akonadi
  • KDE Home
  • Contact Us

Quick Links

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

Class Picker

About

PIM Storage Framework

Maintainer
Daniel Vrátil
Supported platforms
Linux
Community
IRC: #akonadi on Freenode
Mailing list: kde-pim
Use with CMake
find_package(KF5AkonadiCore)
target_link_libraries(yourapp KF5::AkonadiCore)
Use with QMake
QT += AkonadiCore 
Clone
git clone git://anongit.kde.org/akonadi.git
Browse source
Akonadi on cgit.kde.org

Akonadi

  • kde
  • pim
  • akonadi
  • src
  • core
  • models
entityorderproxymodel.cpp
1 /*
2  Copyright (C) 2010 Klarälvdalens Datakonsult AB,
3  a KDAB Group company, [email protected],
4  author Stephen Kelly <[email protected]>
5 
6  This library is free software; you can redistribute it and/or modify it
7  under the terms of the GNU Library General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or (at your
9  option) any later version.
10 
11  This library is distributed in the hope that it will be useful, but WITHOUT
12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
14  License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to the
18  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  02110-1301, USA.
20 */
21 
22 #include "entityorderproxymodel.h"
23 
24 #include <QMimeData>
25 
26 #include <KConfigGroup>
27 #include <QUrl>
28 
29 #include "collection.h"
30 #include "item.h"
31 #include "entitytreemodel.h"
32 
33 namespace Akonadi
34 {
35 
36 class EntityOrderProxyModelPrivate
37 {
38 public:
39  EntityOrderProxyModelPrivate(EntityOrderProxyModel *qq)
40  : q_ptr(qq)
41  {
42  }
43 
44  void saveOrder(const QModelIndex &index);
45 
46  KConfigGroup m_orderConfig;
47 
48  Q_DECLARE_PUBLIC(EntityOrderProxyModel)
49  EntityOrderProxyModel *const q_ptr;
50 
51 };
52 
53 }
54 
55 using namespace Akonadi;
56 
57 EntityOrderProxyModel::EntityOrderProxyModel(QObject *parent)
58  : QSortFilterProxyModel(parent)
59  , d_ptr(new EntityOrderProxyModelPrivate(this))
60 {
61  setRecursiveFilteringEnabled(true);
62  setDynamicSortFilter(true);
63  //setSortCaseSensitivity( Qt::CaseInsensitive );
64 }
65 
66 EntityOrderProxyModel::~EntityOrderProxyModel()
67 {
68  delete d_ptr;
69 }
70 
71 void EntityOrderProxyModel::setOrderConfig(const KConfigGroup &configGroup)
72 {
73  Q_D(EntityOrderProxyModel);
74  Q_EMIT layoutAboutToBeChanged();
75  d->m_orderConfig = configGroup;
76  Q_EMIT layoutChanged();
77 }
78 
79 // reimplemented in FavoriteCollectionOrderProxyModel
80 Collection EntityOrderProxyModel::parentCollection(const QModelIndex &index) const
81 {
82  return index.data(EntityTreeModel::ParentCollectionRole).value<Collection>();
83 }
84 
85 static QString configKey(const Collection &col)
86 {
87  return !col.isValid() ? QStringLiteral("0") : QString::number(col.id());
88 }
89 
90 bool EntityOrderProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
91 {
92  Q_D(const EntityOrderProxyModel);
93 
94  if (!d->m_orderConfig.isValid()) {
95  return QSortFilterProxyModel::lessThan(left, right);
96  }
97  const Collection col = parentCollection(left);
98 
99  const QStringList list = d->m_orderConfig.readEntry(configKey(col), QStringList());
100 
101  if (list.isEmpty()) {
102  return QSortFilterProxyModel::lessThan(left, right);
103  }
104 
105  const QString leftValue = configString(left);
106  const QString rightValue = configString(right);
107 
108  const int leftPosition = list.indexOf(leftValue);
109  const int rightPosition = list.indexOf(rightValue);
110 
111  if (leftPosition < 0 || rightPosition < 0) {
112  return QSortFilterProxyModel::lessThan(left, right);
113  }
114 
115  return leftPosition < rightPosition;
116 }
117 
118 QStringList EntityOrderProxyModel::configStringsForDroppedUrls(const QList<QUrl> &urls, const Akonadi::Collection &parentCol, bool *containsMove) const
119 {
120  QStringList droppedList;
121  droppedList.reserve(urls.count());
122  for (const QUrl &url : urls) {
123  Collection col = Collection::fromUrl(url);
124 
125  if (!col.isValid()) {
126  Item item = Item::fromUrl(url);
127  if (!item.isValid()) {
128  continue;
129  }
130 
131  const QModelIndexList list = EntityTreeModel::modelIndexesForItem(this, item);
132  if (list.isEmpty()) {
133  continue;
134  }
135 
136  if (!*containsMove && parentCollection(list.first()).id() != parentCol.id()) {
137  *containsMove = true;
138  }
139 
140  droppedList << configString(list.first());
141  } else {
142  const QModelIndex idx = EntityTreeModel::modelIndexForCollection(this, col);
143  if (!idx.isValid()) {
144  continue;
145  }
146 
147  if (!*containsMove && parentCollection(idx).id() != parentCol.id()) {
148  *containsMove = true;
149  }
150 
151  droppedList << configString(idx);
152  }
153  }
154  return droppedList;
155 }
156 
157 bool EntityOrderProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
158 {
159  Q_D(EntityOrderProxyModel);
160 
161  if (!d->m_orderConfig.isValid()) {
162  return QSortFilterProxyModel::dropMimeData(data, action, row, column, parent);
163  }
164 
165  if (!data->hasFormat(QStringLiteral("text/uri-list"))) {
166  return QSortFilterProxyModel::dropMimeData(data, action, row, column, parent);
167  }
168 
169  if (row == -1) {
170  return QSortFilterProxyModel::dropMimeData(data, action, row, column, parent);
171  }
172 
173 
174  const QList<QUrl> urls = data->urls();
175  if (urls.isEmpty()) {
176  return false;
177  }
178 
179  Collection parentCol;
180 
181  if (parent.isValid()) {
182  parentCol = parent.data(EntityTreeModel::CollectionRole).value<Collection>();
183  } else {
184  if (!hasChildren(parent)) {
185  return QSortFilterProxyModel::dropMimeData(data, action, row, column, parent);
186  }
187 
188  const QModelIndex targetIndex = index(0, column, parent);
189  parentCol = parentCollection(targetIndex);
190  }
191 
192 
193  bool containsMove = false;
194  QStringList droppedList = configStringsForDroppedUrls(urls, parentCol, &containsMove);
195 
196  // Dropping new favorite folders
197  if (droppedList.isEmpty()) {
198  const bool ok = QSortFilterProxyModel::dropMimeData(data, action, row, column, parent);
199  if (ok) {
200  droppedList = configStringsForDroppedUrls(urls, parentCol, &containsMove);
201  }
202  }
203 
204  QStringList existingList;
205  if (d->m_orderConfig.hasKey(QString::number(parentCol.id()))) {
206  existingList = d->m_orderConfig.readEntry(configKey(parentCol), QStringList());
207  } else {
208  const int rowCount = this->rowCount(parent);
209  existingList.reserve(rowCount);
210  for (int row = 0; row < rowCount; ++row) {
211  static const int column = 0;
212  const QModelIndex idx = this->index(row, column, parent);
213  existingList.append(configString(idx));
214  }
215  }
216  const int numberOfDroppedElement(droppedList.size());
217  for (int i = 0; i < numberOfDroppedElement; ++i) {
218  const QString droppedItem = droppedList.at(i);
219  const int existingIndex = existingList.indexOf(droppedItem);
220  existingList.removeAt(existingIndex);
221  existingList.insert(row + i - (existingIndex > row ? 0 : 1), droppedList.at(i));
222  }
223 
224  d->m_orderConfig.writeEntry(configKey(parentCol), existingList);
225 
226  if (containsMove) {
227  bool result = QSortFilterProxyModel::dropMimeData(data, action, row, column, parent);
228  invalidate();
229  return result;
230  }
231  invalidate();
232  return true;
233 }
234 
235 QModelIndexList EntityOrderProxyModel::match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const
236 {
237  if (role < Qt::UserRole) {
238  return QSortFilterProxyModel::match(start, role, value, hits, flags);
239  }
240 
241  QModelIndexList list;
242  QModelIndex proxyIndex;
243  foreach (const QModelIndex &idx, sourceModel()->match(mapToSource(start), role, value, hits, flags)) {
244  proxyIndex = mapFromSource(idx);
245  if (proxyIndex.isValid()) {
246  list << proxyIndex;
247  }
248  }
249 
250  return list;
251 }
252 
253 void EntityOrderProxyModelPrivate::saveOrder(const QModelIndex &parent)
254 {
255  Q_Q(const EntityOrderProxyModel);
256  int rowCount = q->rowCount(parent);
257 
258  if (rowCount == 0) {
259  return;
260  }
261 
262  static const int column = 0;
263  QModelIndex childIndex = q->index(0, column, parent);
264 
265  const QString parentKey = q->parentConfigString(childIndex);
266 
267  if (parentKey.isEmpty()) {
268  return;
269  }
270 
271  QStringList list;
272 
273  list << q->configString(childIndex);
274  saveOrder(childIndex);
275  list.reserve(list.count() + rowCount);
276  for (int row = 1; row < rowCount; ++row) {
277  childIndex = q->index(row, column, parent);
278  list << q->configString(childIndex);
279  saveOrder(childIndex);
280  }
281 
282  m_orderConfig.writeEntry(parentKey, list);
283 }
284 
285 QString EntityOrderProxyModel::parentConfigString(const QModelIndex &index) const
286 {
287  const Collection col = parentCollection(index);
288 
289  Q_ASSERT(col.isValid());
290  if (!col.isValid()) {
291  return QString();
292  }
293 
294  return QString::number(col.id());
295 }
296 
297 QString EntityOrderProxyModel::configString(const QModelIndex &index) const
298 {
299  Item::Id iId = index.data(EntityTreeModel::ItemIdRole).toLongLong();
300  if (iId != -1) {
301  return QLatin1Char('i') + QString::number(iId);
302  }
303  Collection::Id cId = index.data(EntityTreeModel::CollectionIdRole).toLongLong();
304  if (cId != -1) {
305  return QLatin1Char('c') + QString::number(cId);
306  }
307  Q_ASSERT(!"Invalid entity");
308  return QString();
309 }
310 
311 void EntityOrderProxyModel::saveOrder()
312 {
313  Q_D(EntityOrderProxyModel);
314  d->saveOrder(QModelIndex());
315  d->m_orderConfig.sync();
316 }
317 
318 void EntityOrderProxyModel::clearOrder(const QModelIndex &parent)
319 {
320  Q_D(EntityOrderProxyModel);
321 
322  const QString parentKey = parentConfigString(index(0, 0, parent));
323 
324  if (parentKey.isEmpty()) {
325  return;
326  }
327 
328  d->m_orderConfig.deleteEntry(parentKey);
329  invalidate();
330 }
331 
332 void EntityOrderProxyModel::clearTreeOrder()
333 {
334  Q_D(EntityOrderProxyModel);
335  d->m_orderConfig.deleteGroup();
336  invalidate();
337 }
QVariant::toLongLong
qlonglong toLongLong(bool *ok) const
QSortFilterProxyModel::lessThan
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const
QModelIndex
Akonadi::Collection::isValid
bool isValid() const
Returns whether the collection is valid.
Definition: collection.cpp:137
Akonadi::EntityTreeModel::CollectionIdRole
The collection id.
Definition: entitytreemodel.h:333
Qt::MatchFlags
typedef MatchFlags
QMimeData::hasFormat
virtual bool hasFormat(const QString &mimeType) const
Akonadi::EntityOrderProxyModel::lessThan
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
Definition: entityorderproxymodel.cpp:90
QList::reserve
void reserve(int alloc)
Akonadi::Collection
Represents a collection of PIM items.
Definition: collection.h:76
Akonadi::Collection::Id
qint64 Id
Describes the unique id type.
Definition: collection.h:82
QSortFilterProxyModel::match
virtual QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits, QFlags< Qt::MatchFlag > flags) const
QList::at
const T & at(int i) const
QList::removeAt
void removeAt(int i)
Akonadi::EntityOrderProxyModel::setOrderConfig
void setOrderConfig(const KConfigGroup &group)
Sets the config group that will be used for storing the order.
Definition: entityorderproxymodel.cpp:71
QVariant::value
T value() const
KConfigGroup::writeEntry
void writeEntry(const QString &key, const QVariant &value, WriteConfigFlags pFlags=Normal)
QMimeData
QSortFilterProxyModel::dropMimeData
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
QList::size
int size() const
QModelIndex::isValid
bool isValid() const
QString::number
QString number(int n, int base)
QList::count
int count(const T &value) const
QList::append
void append(const T &value)
Akonadi::EntityOrderProxyModel
A model that keeps the order of entities persistent.
Definition: entityorderproxymodel.h:45
QObject
QList::isEmpty
bool isEmpty() const
QString::isEmpty
bool isEmpty() const
Akonadi::EntityTreeModel::CollectionRole
The collection.
Definition: entitytreemodel.h:334
QString
QList
Akonadi::EntityTreeModel::ParentCollectionRole
The parent collection of the entity.
Definition: entitytreemodel.h:338
Akonadi::EntityOrderProxyModel::match
QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits=1, Qt::MatchFlags flags=Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const override
Definition: entityorderproxymodel.cpp:235
QStringList
Akonadi::EntityTreeModel::modelIndexForCollection
static QModelIndex modelIndexForCollection(const QAbstractItemModel *model, const Collection &collection)
Returns a QModelIndex in model which points to collection.
Definition: entitytreemodel.cpp:1169
QUrl
QLatin1Char
QSortFilterProxyModel
KConfigGroup
Akonadi::EntityOrderProxyModel::~EntityOrderProxyModel
~EntityOrderProxyModel() override
Destroys the entity order proxy model.
Definition: entityorderproxymodel.cpp:66
Akonadi::EntityOrderProxyModel::saveOrder
void saveOrder()
Saves the order.
Definition: entityorderproxymodel.cpp:311
Akonadi::Collection::id
Id id() const
Returns the unique identifier of the collection.
Definition: collection.cpp:112
QModelIndex::data
QVariant data(int role) const
QMimeData::urls
QList< QUrl > urls() const
QList::insert
void insert(int i, const T &value)
Akonadi
QStringList::indexOf
int indexOf(const QRegExp &rx, int from) const
Akonadi::EntityTreeModel::modelIndexesForItem
static QModelIndexList modelIndexesForItem(const QAbstractItemModel *model, const Item &item)
Returns a QModelIndex in model which points to item.
Definition: entitytreemodel.cpp:1178
Akonadi::EntityOrderProxyModel::dropMimeData
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
Definition: entityorderproxymodel.cpp:157
Akonadi::Collection::fromUrl
static Collection fromUrl(const QUrl &url)
Creates a collection from the given url.
Definition: collection.cpp:284
QVariant
Akonadi::EntityTreeModel::ItemIdRole
The item id.
Definition: entitytreemodel.h:329
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Thu Dec 12 2019 02:46:56 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

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