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

akonadi

  • sources
  • kde-4.14
  • kdepimlibs
  • akonadi
collectiondialog_desktop.cpp
1 /*
2  Copyright 2008 Ingo Klöcker <kloecker@kde.org>
3  Copyright 2010 Laurent Montel <montel@kde.org>
4 
5  This library is free software; you can redistribute it and/or modify it
6  under the terms of the GNU Library General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or (at your
8  option) any later version.
9 
10  This library is distributed in the hope that it will be useful, but WITHOUT
11  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13  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 the
17  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  02110-1301, USA.
19 */
20 
21 #include "collectiondialog.h"
22 
23 #include "asyncselectionhandler_p.h"
24 
25 #include <akonadi/changerecorder.h>
26 #include <akonadi/collectionfetchscope.h>
27 #include <akonadi/collectionfilterproxymodel.h>
28 #include <akonadi/entityrightsfiltermodel.h>
29 #include <akonadi/entitytreemodel.h>
30 #include <akonadi/entitytreeview.h>
31 #include <akonadi/session.h>
32 #include <akonadi/collectioncreatejob.h>
33 #include <akonadi/collectionutils_p.h>
34 
35 #include <QHeaderView>
36 #include <QLabel>
37 #include <QVBoxLayout>
38 #include <QCheckBox>
39 
40 #include <KLineEdit>
41 #include <KLocalizedString>
42 #include <KInputDialog>
43 #include <KMessageBox>
44 
45 using namespace Akonadi;
46 
47 class CollectionDialog::Private
48 {
49 public:
50  Private(QAbstractItemModel *customModel, CollectionDialog *parent, CollectionDialogOptions options)
51  : mParent(parent)
52  , mMonitor(0)
53  {
54  // setup GUI
55  QWidget *widget = mParent->mainWidget();
56  QVBoxLayout *layout = new QVBoxLayout(widget);
57  layout->setContentsMargins(0, 0, 0, 0);
58 
59  mTextLabel = new QLabel;
60  layout->addWidget(mTextLabel);
61  mTextLabel->hide();
62 
63  KLineEdit *filterCollectionLineEdit = new KLineEdit(widget);
64  filterCollectionLineEdit->setClearButtonShown(true);
65  filterCollectionLineEdit->setClickMessage(i18nc("@info/plain Displayed grayed-out inside the "
66  "textbox, verb to search", "Search"));
67  layout->addWidget(filterCollectionLineEdit);
68 
69  mView = new EntityTreeView;
70  mView->setDragDropMode(QAbstractItemView::NoDragDrop);
71  mView->header()->hide();
72  layout->addWidget(mView);
73 
74  mUseByDefault = new QCheckBox(i18n("Use folder by default"));
75  mUseByDefault->hide();
76  layout->addWidget(mUseByDefault);
77 
78  mParent->enableButton(KDialog::Ok, false);
79 
80  // setup models
81  QAbstractItemModel *baseModel;
82 
83  if (customModel) {
84  baseModel = customModel;
85  } else {
86  mMonitor = new Akonadi::ChangeRecorder(mParent);
87  mMonitor->fetchCollection(true);
88  mMonitor->setCollectionMonitored(Akonadi::Collection::root());
89 
90  EntityTreeModel *model = new EntityTreeModel(mMonitor, mParent);
91  model->setItemPopulationStrategy(EntityTreeModel::NoItemPopulation);
92  baseModel = model;
93  }
94 
95  mMimeTypeFilterModel = new CollectionFilterProxyModel(mParent);
96  mMimeTypeFilterModel->setSourceModel(baseModel);
97  mMimeTypeFilterModel->setExcludeVirtualCollections(true);
98 
99  mRightsFilterModel = new EntityRightsFilterModel(mParent);
100  mRightsFilterModel->setSourceModel(mMimeTypeFilterModel);
101 
102  mFilterCollection = new KRecursiveFilterProxyModel(mParent);
103  mFilterCollection->setDynamicSortFilter(true);
104  mFilterCollection->setSourceModel(mRightsFilterModel);
105  mFilterCollection->setFilterCaseSensitivity(Qt::CaseInsensitive);
106  mView->setModel(mFilterCollection);
107 
108  changeCollectionDialogOptions(options);
109  mParent->connect(filterCollectionLineEdit, SIGNAL(textChanged(QString)),
110  mParent, SLOT(slotFilterFixedString(QString)));
111 
112  mParent->connect(mView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
113  mParent, SLOT(slotSelectionChanged()));
114 
115  mParent->connect(mView, SIGNAL(doubleClicked(QModelIndex)),
116  mParent, SLOT(slotDoubleClicked()));
117 
118  mSelectionHandler = new AsyncSelectionHandler(mFilterCollection, mParent);
119  mParent->connect(mSelectionHandler, SIGNAL(collectionAvailable(QModelIndex)),
120  mParent, SLOT(slotCollectionAvailable(QModelIndex)));
121  readConfig();
122  }
123 
124  ~Private()
125  {
126  writeConfig();
127  }
128 
129  void slotCollectionAvailable(const QModelIndex &index)
130  {
131  mView->expandAll();
132  mView->setCurrentIndex(index);
133  }
134 
135  void slotFilterFixedString(const QString &filter)
136  {
137  mFilterCollection->setFilterFixedString(filter);
138  if (mKeepTreeExpanded) {
139  mView->expandAll();
140  }
141  }
142 
143  void readConfig()
144  {
145  KConfig config( QLatin1String( "akonadi_contactrc" ) );
146  KConfigGroup group( &config, QLatin1String( "CollectionDialog" ) );
147  const QSize size = group.readEntry( "Size", QSize(800, 500) );
148  if ( size.isValid() ) {
149  mParent->resize( size );
150  }
151  }
152 
153  void writeConfig()
154  {
155  KConfig config( QLatin1String( "akonadi_contactrc" ) );
156  KConfigGroup group( &config, QLatin1String( "CollectionDialog" ) );
157  group.writeEntry( "Size", mParent->size() );
158  group.sync();
159  }
160 
161  CollectionDialog *mParent;
162 
163  ChangeRecorder *mMonitor;
164  CollectionFilterProxyModel *mMimeTypeFilterModel;
165  EntityRightsFilterModel *mRightsFilterModel;
166  EntityTreeView *mView;
167  AsyncSelectionHandler *mSelectionHandler;
168  QLabel *mTextLabel;
169  bool mAllowToCreateNewChildCollection;
170  bool mKeepTreeExpanded;
171  KRecursiveFilterProxyModel *mFilterCollection;
172  QCheckBox *mUseByDefault;
173  QStringList mContentMimeTypes;
174 
175  void slotDoubleClicked();
176  void slotSelectionChanged();
177  void slotAddChildCollection();
178  void slotCollectionCreationResult(KJob *job);
179  bool canCreateCollection(const Akonadi::Collection &parentCollection) const;
180  void changeCollectionDialogOptions(CollectionDialogOptions options);
181  bool canSelectCollection() const;
182 };
183 
184 void CollectionDialog::Private::slotDoubleClicked()
185 {
186  if (canSelectCollection()) {
187  mParent->accept();
188  }
189 }
190 
191 bool CollectionDialog::Private::canSelectCollection() const
192 {
193  bool result = (mView->selectionModel()->selectedIndexes().count() > 0);
194  if (mAllowToCreateNewChildCollection) {
195  const Akonadi::Collection parentCollection = mParent->selectedCollection();
196 
197  if (parentCollection.isValid()) {
198  result = (parentCollection.rights() & Akonadi::Collection::CanCreateItem);
199  }
200  }
201  return result;
202 }
203 
204 void CollectionDialog::Private::slotSelectionChanged()
205 {
206  mParent->enableButton(KDialog::Ok, mView->selectionModel()->selectedIndexes().count() > 0);
207  if (mAllowToCreateNewChildCollection) {
208  const Akonadi::Collection parentCollection = mParent->selectedCollection();
209  const bool canCreateChildCollections = canCreateCollection(parentCollection);
210 
211  mParent->enableButton(KDialog::User1, (canCreateChildCollections && !parentCollection.isVirtual()));
212  if (parentCollection.isValid()) {
213  const bool canCreateItems = (parentCollection.rights() & Akonadi::Collection::CanCreateItem);
214  mParent->enableButton(KDialog::Ok, canCreateItems);
215  }
216  }
217 }
218 
219 void CollectionDialog::Private::changeCollectionDialogOptions(CollectionDialogOptions options)
220 {
221  mAllowToCreateNewChildCollection = (options & AllowToCreateNewChildCollection);
222  if (mAllowToCreateNewChildCollection) {
223  mParent->setButtons(Ok | Cancel | User1);
224  mParent->setButtonGuiItem(User1, KGuiItem(i18n("&New Subfolder..."), QLatin1String("folder-new"),
225  i18n("Create a new subfolder under the currently selected folder")));
226  mParent->enableButton(KDialog::User1, false);
227  connect(mParent, SIGNAL(user1Clicked()), mParent, SLOT(slotAddChildCollection()));
228  }
229  mKeepTreeExpanded = (options & KeepTreeExpanded);
230  if (mKeepTreeExpanded) {
231  mParent->connect(mRightsFilterModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
232  mView, SLOT(expandAll()), Qt::UniqueConnection);
233  mView->expandAll();
234  }
235 }
236 
237 bool CollectionDialog::Private::canCreateCollection(const Akonadi::Collection &parentCollection) const
238 {
239  if (!parentCollection.isValid()) {
240  return false;
241  }
242 
243  if ((parentCollection.rights() & Akonadi::Collection::CanCreateCollection)) {
244  const QStringList dialogMimeTypeFilter = mParent->mimeTypeFilter();
245  const QStringList parentCollectionMimeTypes = parentCollection.contentMimeTypes();
246  Q_FOREACH (const QString &mimetype, dialogMimeTypeFilter) {
247  if (parentCollectionMimeTypes.contains(mimetype)) {
248  return true;
249  }
250  }
251  return true;
252  }
253  return false;
254 }
255 
256 void CollectionDialog::Private::slotAddChildCollection()
257 {
258  const Akonadi::Collection parentCollection = mParent->selectedCollection();
259  if (canCreateCollection(parentCollection)) {
260  const QString name = KInputDialog::getText(i18nc("@title:window", "New Folder"),
261  i18nc("@label:textbox, name of a thing", "Name"),
262  QString(), 0, mParent);
263  if (name.isEmpty()) {
264  return;
265  }
266 
267  Akonadi::Collection collection;
268  collection.setName(name);
269  collection.setParentCollection(parentCollection);
270  if (!mContentMimeTypes.isEmpty()) {
271  collection.setContentMimeTypes(mContentMimeTypes);
272  }
273  Akonadi::CollectionCreateJob *job = new Akonadi::CollectionCreateJob(collection);
274  connect(job, SIGNAL(result(KJob*)), mParent, SLOT(slotCollectionCreationResult(KJob*)));
275  }
276 }
277 
278 void CollectionDialog::Private::slotCollectionCreationResult(KJob *job)
279 {
280  if (job->error()) {
281  KMessageBox::error(mParent, i18n("Could not create folder: %1", job->errorString()),
282  i18n("Folder creation failed"));
283  }
284 }
285 
286 CollectionDialog::CollectionDialog(QWidget *parent)
287  : KDialog(parent)
288  , d(new Private(0, this, CollectionDialog::None))
289 {
290 }
291 
292 CollectionDialog::CollectionDialog(QAbstractItemModel *model, QWidget *parent)
293  : KDialog(parent)
294  , d(new Private(model, this, CollectionDialog::None))
295 {
296 }
297 
298 CollectionDialog::CollectionDialog(CollectionDialogOptions options, QAbstractItemModel *model, QWidget *parent)
299  : KDialog(parent)
300  , d(new Private(model, this, options))
301 {
302 }
303 
304 CollectionDialog::~CollectionDialog()
305 {
306  delete d;
307 }
308 
309 Akonadi::Collection CollectionDialog::selectedCollection() const
310 {
311  if (selectionMode() == QAbstractItemView::SingleSelection) {
312  const QModelIndex index = d->mView->currentIndex();
313  if (index.isValid()) {
314  return index.model()->data(index, EntityTreeModel::CollectionRole).value<Collection>();
315  }
316  }
317 
318  return Collection();
319 }
320 
321 Akonadi::Collection::List CollectionDialog::selectedCollections() const
322 {
323  Collection::List collections;
324  const QItemSelectionModel *selectionModel = d->mView->selectionModel();
325  const QModelIndexList selectedIndexes = selectionModel->selectedIndexes();
326  foreach (const QModelIndex &index, selectedIndexes) {
327  if (index.isValid()) {
328  const Collection collection = index.model()->data(index, EntityTreeModel::CollectionRole).value<Collection>();
329  if (collection.isValid()) {
330  collections.append(collection);
331  }
332  }
333  }
334 
335  return collections;
336 }
337 
338 void CollectionDialog::setMimeTypeFilter(const QStringList &mimeTypes)
339 {
340  if (mimeTypeFilter() == mimeTypes) {
341  return;
342  }
343 
344  d->mMimeTypeFilterModel->clearFilters();
345  d->mMimeTypeFilterModel->addMimeTypeFilters(mimeTypes);
346 
347  if (d->mMonitor) {
348  foreach (const QString &mimetype, mimeTypes) {
349  d->mMonitor->setMimeTypeMonitored(mimetype);
350  }
351  }
352 }
353 
354 QStringList CollectionDialog::mimeTypeFilter() const
355 {
356  return d->mMimeTypeFilterModel->mimeTypeFilters();
357 }
358 
359 void CollectionDialog::setAccessRightsFilter(Collection::Rights rights)
360 {
361  if (accessRightsFilter() == rights) {
362  return;
363  }
364  d->mRightsFilterModel->setAccessRights(rights);
365 }
366 
367 Akonadi::Collection::Rights CollectionDialog::accessRightsFilter() const
368 {
369  return d->mRightsFilterModel->accessRights();
370 }
371 
372 void CollectionDialog::setDescription(const QString &text)
373 {
374  d->mTextLabel->setText(text);
375  d->mTextLabel->show();
376 }
377 
378 void CollectionDialog::setDefaultCollection(const Collection &collection)
379 {
380  d->mSelectionHandler->waitForCollection(collection);
381 }
382 
383 void CollectionDialog::setSelectionMode(QAbstractItemView::SelectionMode mode)
384 {
385  d->mView->setSelectionMode(mode);
386 }
387 
388 QAbstractItemView::SelectionMode CollectionDialog::selectionMode() const
389 {
390  return d->mView->selectionMode();
391 }
392 
393 void CollectionDialog::changeCollectionDialogOptions(CollectionDialogOptions options)
394 {
395  d->changeCollectionDialogOptions(options);
396 }
397 
398 void CollectionDialog::setUseFolderByDefault(bool b)
399 {
400  d->mUseByDefault->setChecked(b);
401  d->mUseByDefault->show();
402 }
403 
404 bool CollectionDialog::useFolderByDefault() const
405 {
406  return d->mUseByDefault->isChecked();
407 }
408 
409 void CollectionDialog::setContentMimeTypes(const QStringList &mimetypes)
410 {
411  d->mContentMimeTypes = mimetypes;
412 }
413 
414 
415 #include "moc_collectiondialog.cpp"
Akonadi::CollectionDialog::setAccessRightsFilter
void setAccessRightsFilter(Collection::Rights rights)
Sets the access rights that the listed collections shall match with.
Definition: collectiondialog_desktop.cpp:359
Akonadi::CollectionDialog::CollectionDialog
CollectionDialog(QWidget *parent=0)
Creates a new collection dialog.
Definition: collectiondialog_desktop.cpp:286
Akonadi::CollectionDialog::selectedCollection
Akonadi::Collection selectedCollection() const
Returns the selected collection if the selection mode is QAbstractItemView::SingleSelection.
Definition: collectiondialog_desktop.cpp:309
QModelIndex
Akonadi::CollectionDialog::setSelectionMode
void setSelectionMode(QAbstractItemView::SelectionMode mode)
Sets the selection mode.
Definition: collectiondialog_desktop.cpp:383
Akonadi::CollectionDialog::useFolderByDefault
bool useFolderByDefault() const
Definition: collectiondialog_desktop.cpp:404
QWidget
QSize::isValid
bool isValid() const
QLayout::setContentsMargins
void setContentsMargins(int left, int top, int right, int bottom)
Akonadi::CollectionDialog::setMimeTypeFilter
void setMimeTypeFilter(const QStringList &mimeTypes)
Sets the mime types any of which the selected collection(s) shall support.
Definition: collectiondialog_desktop.cpp:338
Akonadi::CollectionFilterProxyModel
A proxy model that filters collections by mime type.
Definition: collectionfilterproxymodel.h:54
Akonadi::AsyncSelectionHandler
Definition: asyncselectionhandler_p.h:42
Akonadi::CollectionDialog
A collection selection dialog.
Definition: collectiondialog.h:67
Akonadi::CollectionDialog::selectedCollections
Akonadi::Collection::List selectedCollections() const
Returns the list of selected collections.
Definition: collectiondialog_desktop.cpp:321
Akonadi::Collection
Represents a collection of PIM items.
Definition: collection.h:75
Akonadi::EntityTreeModel::NoItemPopulation
Do not include items in the model.
Definition: entitytreemodel.h:409
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
QAbstractItemView::setDragDropMode
void setDragDropMode(DragDropMode behavior)
QVariant::value
T value() const
Akonadi::Collection::CanCreateCollection
Can create new subcollections in this collection.
Definition: collection.h:92
Akonadi::EntityRightsFilterModel
A proxy model that filters entities by access rights.
Definition: entityrightsfiltermodel.h:60
Akonadi::Entity::setParentCollection
void setParentCollection(const Collection &parent)
Set the parent collection of this object.
Definition: entity.cpp:194
Akonadi::Collection::setName
void setName(const QString &name)
Sets the i18n'ed name of the collection.
Definition: collection.cpp:93
Akonadi::CollectionDialog::setUseFolderByDefault
void setUseFolderByDefault(bool b)
Definition: collectiondialog_desktop.cpp:398
QModelIndex::isValid
bool isValid() const
QBoxLayout::addWidget
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
Akonadi::CollectionDialog::selectionMode
QAbstractItemView::SelectionMode selectionMode() const
Returns the selection mode.
Definition: collectiondialog_desktop.cpp:388
QList::append
void append(const T &value)
Akonadi::CollectionDialog::setContentMimeTypes
void setContentMimeTypes(const QStringList &mimetypes)
Allow to specify collection content mimetype when we create new one.
Definition: collectiondialog_desktop.cpp:409
Akonadi::EntityTreeView
A view to show an item/collection tree provided by an EntityTreeModel.
Definition: entitytreeview.h:71
QCheckBox
QString::isEmpty
bool isEmpty() const
QItemSelectionModel::selectedIndexes
QModelIndexList selectedIndexes() const
Akonadi::Collection::CanCreateItem
Can create new items in this collection.
Definition: collection.h:89
QVBoxLayout
Akonadi::Collection::root
static Collection root()
Returns the root collection.
Definition: collection.cpp:192
QAbstractItemModel::data
virtual QVariant data(const QModelIndex &index, int role) const =0
Akonadi::EntityTreeModel::CollectionRole
The collection.
Definition: entitytreemodel.h:336
Akonadi::CollectionDialog::setDefaultCollection
void setDefaultCollection(const Collection &collection)
Sets the collection that shall be selected by default.
Definition: collectiondialog_desktop.cpp:378
QString
QList
Akonadi::CollectionDialog::changeCollectionDialogOptions
void changeCollectionDialogOptions(CollectionDialogOptions options)
Change collection dialog options.
Definition: collectiondialog_desktop.cpp:393
QStringList
Akonadi::Collection::rights
Rights rights() const
Returns the rights the user has on the collection.
Definition: collection.cpp:99
Akonadi::CollectionDialog::mimeTypeFilter
QStringList mimeTypeFilter() const
Returns the mime types any of which the selected collection(s) shall support.
Definition: collectiondialog_desktop.cpp:354
Akonadi::CollectionDialog::accessRightsFilter
Collection::Rights accessRightsFilter() const
Sets the access rights that the listed collections shall match with.
Definition: collectiondialog_desktop.cpp:367
QSize
Akonadi::EntityTreeModel::setItemPopulationStrategy
void setItemPopulationStrategy(ItemPopulationStrategy strategy)
Sets the item population strategy of the model.
Definition: entitytreemodel.cpp:1121
Akonadi::CollectionDialog::setDescription
void setDescription(const QString &text)
Sets the text that will be shown in the dialog.
Definition: collectiondialog_desktop.cpp:372
QItemSelection
QModelIndex::model
const QAbstractItemModel * model() const
QLatin1String
Akonadi::EntityTreeModel
A model for collections and items together.
Definition: entitytreemodel.h:318
Akonadi::Collection::contentMimeTypes
QStringList contentMimeTypes() const
Returns a list of possible content mimetypes, e.g.
Definition: collection.cpp:115
QAbstractItemModel
Akonadi::CollectionDialog::~CollectionDialog
~CollectionDialog()
Destroys the collection dialog.
Definition: collectiondialog_desktop.cpp:304
Akonadi::CollectionCreateJob
Job that creates a new collection in the Akonadi storage.
Definition: collectioncreatejob.h:52
Akonadi::Entity::isValid
bool isValid() const
Returns whether the entity is valid.
Definition: entity.cpp:97
QItemSelectionModel
QLabel
Akonadi::Collection::setContentMimeTypes
void setContentMimeTypes(const QStringList &types)
Sets the list of possible content mime types.
Definition: collection.cpp:120
Akonadi::Collection::isVirtual
bool isVirtual() const
Returns whether the collection is virtual, for example a search collection.
Definition: collection.cpp:261
Akonadi::ChangeRecorder
Records and replays change notification.
Definition: changerecorder.h:47
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:38:02 by doxygen 1.8.7 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 API Reference

Skip menu "kdepimlibs 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

Search



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