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

akonadi

  • akonadi
entitytreeview.cpp
1/*
2 Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>
3 Copyright (c) 2008 Stephen Kelly <steveire@gmail.com>
4 Copyright (c) 2012 Laurent Montel <montel@kde.org>
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 "entitytreeview.h"
23
24#include "dragdropmanager_p.h"
25
26#include <QtCore/QDebug>
27#include <QtCore/QTimer>
28#include <QApplication>
29#include <QDragMoveEvent>
30#include <QHeaderView>
31#include <QMenu>
32
33#include <akonadi/collection.h>
34#include <akonadi/control.h>
35#include <akonadi/item.h>
36#include <akonadi/entitytreemodel.h>
37
38#include <kdebug.h>
39#include <kxmlguiclient.h>
40#include <KXMLGUIFactory>
41
42#include "progressspinnerdelegate_p.h"
43
44using namespace Akonadi;
45
49class EntityTreeView::Private
50{
51public:
52 Private(EntityTreeView *parent)
53 : mParent(parent)
54#ifndef QT_NO_DRAGANDDROP
55 , mDragDropManager(new DragDropManager(mParent))
56#endif
57 , mXmlGuiClient(0)
58 , mDefaultPopupMenu(QLatin1String("akonadi_collectionview_contextmenu"))
59 {
60 }
61
62 void init();
63 void itemClicked(const QModelIndex &index);
64 void itemDoubleClicked(const QModelIndex &index);
65 void itemCurrentChanged(const QModelIndex &index);
66
67 void slotSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
68
69 EntityTreeView *mParent;
70 QBasicTimer mDragExpandTimer;
71 DragDropManager *mDragDropManager;
72 KXMLGUIClient *mXmlGuiClient;
73 QString mDefaultPopupMenu;
74};
75
76void EntityTreeView::Private::init()
77{
78 Akonadi::DelegateAnimator *animator = new Akonadi::DelegateAnimator(mParent);
79 Akonadi::ProgressSpinnerDelegate *customDelegate = new Akonadi::ProgressSpinnerDelegate(animator, mParent);
80 mParent->setItemDelegate(customDelegate);
81
82 mParent->header()->setClickable(true);
83 mParent->header()->setStretchLastSection(false);
84// mParent->setRootIsDecorated( false );
85
86 // QTreeView::autoExpandDelay has very strange behaviour. It toggles the collapse/expand state
87 // of the item the cursor is currently over when a timer event fires.
88 // The behaviour we want is to expand a collapsed row on drag-over, but not collapse it.
89 // mDragExpandTimer is used to achieve this.
90// mParent->setAutoExpandDelay ( QApplication::startDragTime() );
91
92 mParent->setSortingEnabled(true);
93 mParent->sortByColumn(0, Qt::AscendingOrder);
94 mParent->setEditTriggers(QAbstractItemView::EditKeyPressed);
95 mParent->setAcceptDrops(true);
96#ifndef QT_NO_DRAGANDDROP
97 mParent->setDropIndicatorShown(true);
98 mParent->setDragDropMode(DragDrop);
99 mParent->setDragEnabled(true);
100#endif
101
102 mParent->connect(mParent, SIGNAL(clicked(QModelIndex)),
103 mParent, SLOT(itemClicked(QModelIndex)));
104 mParent->connect(mParent, SIGNAL(doubleClicked(QModelIndex)),
105 mParent, SLOT(itemDoubleClicked(QModelIndex)));
106
107 Control::widgetNeedsAkonadi(mParent);
108}
109
110void EntityTreeView::Private::slotSelectionChanged(const QItemSelection &selected, const QItemSelection &)
111{
112 const int column = 0;
113 foreach (const QItemSelectionRange &range, selected) {
114 const QModelIndex index = range.topLeft();
115
116 if (index.column() > 0) {
117 continue;
118 }
119
120 for (int row = index.row(); row <= range.bottomRight().row(); ++row) {
121 // Don't use canFetchMore here. We need to bypass the check in
122 // the EntityFilterModel when it shows only collections.
123 mParent->model()->fetchMore(index.sibling(row, column));
124 }
125 }
126
127 if (selected.size() == 1) {
128 const QItemSelectionRange &range = selected.first();
129 if (range.topLeft().row() == range.bottomRight().row()) {
130 mParent->scrollTo(range.topLeft(), QTreeView::EnsureVisible);
131 }
132 }
133}
134
135void EntityTreeView::Private::itemClicked(const QModelIndex &index)
136{
137 if (!index.isValid()) {
138 return;
139 }
140 QModelIndex idx = index.sibling(index.row(), 0);
141
142 const Collection collection = idx.model()->data(idx, EntityTreeModel::CollectionRole).value<Collection>();
143 if (collection.isValid()) {
144 emit mParent->clicked(collection);
145 } else {
146 const Item item = idx.model()->data(idx, EntityTreeModel::ItemRole).value<Item>();
147 if (item.isValid()) {
148 emit mParent->clicked(item);
149 }
150 }
151}
152
153void EntityTreeView::Private::itemDoubleClicked(const QModelIndex &index)
154{
155 if (!index.isValid()) {
156 return;
157 }
158 QModelIndex idx = index.sibling(index.row(), 0);
159 const Collection collection = idx.model()->data(idx, EntityTreeModel::CollectionRole).value<Collection>();
160 if (collection.isValid()) {
161 emit mParent->doubleClicked(collection);
162 } else {
163 const Item item = idx.model()->data(idx, EntityTreeModel::ItemRole).value<Item>();
164 if (item.isValid()) {
165 emit mParent->doubleClicked(item);
166 }
167 }
168}
169
170void EntityTreeView::Private::itemCurrentChanged(const QModelIndex &index)
171{
172 if (!index.isValid()) {
173 return;
174 }
175 QModelIndex idx = index.sibling(index.row(), 0);
176 const Collection collection = idx.model()->data(idx, EntityTreeModel::CollectionRole).value<Collection>();
177 if (collection.isValid()) {
178 emit mParent->currentChanged(collection);
179 } else {
180 const Item item = idx.model()->data(idx, EntityTreeModel::ItemRole).value<Item>();
181 if (item.isValid()) {
182 emit mParent->currentChanged(item);
183 }
184 }
185}
186
187EntityTreeView::EntityTreeView(QWidget *parent)
188 : QTreeView(parent)
189 , d(new Private(this))
190{
191 setSelectionMode(QAbstractItemView::SingleSelection);
192 d->init();
193}
194
195EntityTreeView::EntityTreeView(KXMLGUIClient *xmlGuiClient, QWidget *parent)
196 : QTreeView(parent)
197 , d(new Private(this))
198{
199 d->mXmlGuiClient = xmlGuiClient;
200 d->init();
201}
202
203EntityTreeView::~EntityTreeView()
204{
205 delete d->mDragDropManager;
206 delete d;
207}
208
209void EntityTreeView::setModel(QAbstractItemModel *model)
210{
211 if (selectionModel()) {
212 disconnect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
213 this, SLOT(itemCurrentChanged(QModelIndex)));
214
215 disconnect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
216 this, SLOT(slotSelectionChanged(QItemSelection,QItemSelection)));
217 }
218
219 QTreeView::setModel(model);
220 header()->setStretchLastSection(true);
221
222 connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
223 SLOT(itemCurrentChanged(QModelIndex)));
224
225 connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
226 SLOT(slotSelectionChanged(QItemSelection,QItemSelection)));
227}
228
229void EntityTreeView::timerEvent(QTimerEvent *event)
230{
231 if (event->timerId() == d->mDragExpandTimer.timerId()) {
232 const QPoint pos = viewport()->mapFromGlobal(QCursor::pos());
233 if (state() == QAbstractItemView::DraggingState && viewport()->rect().contains(pos)) {
234 setExpanded(indexAt(pos), true);
235 }
236 }
237
238 QTreeView::timerEvent(event);
239}
240
241#ifndef QT_NO_DRAGANDDROP
242void EntityTreeView::dragMoveEvent(QDragMoveEvent *event)
243{
244 d->mDragExpandTimer.start(QApplication::startDragTime() , this);
245
246 if (d->mDragDropManager->dropAllowed(event)) {
247 // All urls are supported. process the event.
248 QTreeView::dragMoveEvent(event);
249 return;
250 }
251
252 event->setDropAction(Qt::IgnoreAction);
253}
254
255void EntityTreeView::dropEvent(QDropEvent *event)
256{
257 d->mDragExpandTimer.stop();
258 bool menuCanceled = false;
259 if (d->mDragDropManager->processDropEvent(event, menuCanceled, (dropIndicatorPosition() == QAbstractItemView::OnItem))) {
260 QTreeView::dropEvent(event);
261 }
262}
263#endif
264
265#ifndef QT_NO_CONTEXTMENU
266void EntityTreeView::contextMenuEvent(QContextMenuEvent *event)
267{
268 if (!d->mXmlGuiClient || !model()) {
269 return;
270 }
271
272 const QModelIndex index = indexAt(event->pos());
273 QString popupName = d->mDefaultPopupMenu;
274
275 if (index.isValid()) { // popup not over empty space
276 // check whether the index under the cursor is a collection or item
277 const Item item = model()->data(index, EntityTreeModel::ItemRole).value<Item>();
278 popupName = (item.isValid() ? QLatin1String("akonadi_itemview_contextmenu") :
279 QLatin1String("akonadi_collectionview_contextmenu"));
280 }
281
282 QMenu *popup = static_cast<QMenu *>(d->mXmlGuiClient->factory()->container(popupName, d->mXmlGuiClient));
283 if (popup) {
284 popup->exec(event->globalPos());
285 }
286}
287#endif
288
289void EntityTreeView::setXmlGuiClient(KXMLGUIClient *xmlGuiClient)
290{
291 d->mXmlGuiClient = xmlGuiClient;
292}
293
294KXMLGUIClient *EntityTreeView::xmlGuiClient() const
295{
296 return d->mXmlGuiClient;
297}
298
299#ifndef QT_NO_DRAGANDDROP
300void EntityTreeView::startDrag(Qt::DropActions supportedActions)
301{
302 d->mDragDropManager->startDrag(supportedActions);
303}
304#endif
305
306void EntityTreeView::setDropActionMenuEnabled(bool enabled)
307{
308#ifndef QT_NO_DRAGANDDROP
309 d->mDragDropManager->setShowDropActionMenu(enabled);
310#endif
311}
312
313bool EntityTreeView::isDropActionMenuEnabled() const
314{
315#ifndef QT_NO_DRAGANDDROP
316 return d->mDragDropManager->showDropActionMenu();
317#else
318 return false;
319#endif
320}
321
322void EntityTreeView::setManualSortingActive(bool active)
323{
324#ifndef QT_NO_DRAGANDDROP
325 d->mDragDropManager->setManualSortingActive(active);
326#endif
327}
328
329bool EntityTreeView::isManualSortingActive() const
330{
331#ifndef QT_NO_DRAGANDDROP
332 return d->mDragDropManager->isManualSortingActive();
333#else
334 return false;
335#endif
336}
337
338void EntityTreeView::setDefaultPopupMenu(const QString &name)
339{
340 d->mDefaultPopupMenu = name;
341}
342
343#include "moc_entitytreeview.cpp"
Akonadi::Collection
Represents a collection of PIM items.
Definition collection.h:76
Akonadi::Control::widgetNeedsAkonadi
static void widgetNeedsAkonadi(QWidget *widget)
Disable the given widget when Akonadi is not operational and show an error overlay (given enough spac...
Definition control.cpp:264
Akonadi::EntityTreeModel::ItemRole
@ ItemRole
The Item.
Definition entitytreemodel.h:332
Akonadi::EntityTreeModel::CollectionRole
@ CollectionRole
The collection.
Definition entitytreemodel.h:336
Akonadi::EntityTreeView
A view to show an item/collection tree provided by an EntityTreeModel.
Definition entitytreeview.h:72
Akonadi::EntityTreeView::doubleClicked
void doubleClicked(const Akonadi::Collection &collection)
This signal is emitted whenever the user has double clicked a collection in the view.
Akonadi::EntityTreeView::isManualSortingActive
bool isManualSortingActive() const
Return true if we use an manual sorting Necessary to fix dnd menu We must show just move when we move...
Definition entitytreeview.cpp:329
Akonadi::EntityTreeView::xmlGuiClient
KXMLGUIClient * xmlGuiClient() const
Return the XML GUI client which the view is used in.
Definition entitytreeview.cpp:294
Akonadi::EntityTreeView::setDropActionMenuEnabled
void setDropActionMenuEnabled(bool enabled)
Sets whether the drop action menu is enabled and will be shown on drop operation.
Definition entitytreeview.cpp:306
Akonadi::EntityTreeView::clicked
void clicked(const Akonadi::Collection &collection)
This signal is emitted whenever the user has clicked a collection in the view.
Akonadi::EntityTreeView::setDefaultPopupMenu
void setDefaultPopupMenu(const QString &name)
Set the name of the default popup menu (retrieved from the application's XMLGUI file).
Definition entitytreeview.cpp:338
Akonadi::EntityTreeView::~EntityTreeView
virtual ~EntityTreeView()
Destroys the entity tree view.
Definition entitytreeview.cpp:203
Akonadi::EntityTreeView::currentChanged
void currentChanged(const Akonadi::Collection &collection)
This signal is emitted whenever the current collection in the view has changed.
Akonadi::EntityTreeView::EntityTreeView
EntityTreeView(QWidget *parent=0)
Creates a new entity tree view.
Definition entitytreeview.cpp:187
Akonadi::EntityTreeView::setModel
virtual void setModel(QAbstractItemModel *model)
Definition entitytreeview.cpp:209
Akonadi::EntityTreeView::setXmlGuiClient
void setXmlGuiClient(KXMLGUIClient *xmlGuiClient)
Sets the XML GUI client which the view is used in.
Definition entitytreeview.cpp:289
Akonadi::EntityTreeView::isDropActionMenuEnabled
bool isDropActionMenuEnabled() const
Returns whether the drop action menu is enabled and will be shown on drop operation.
Definition entitytreeview.cpp:313
Akonadi::EntityTreeView::setManualSortingActive
void setManualSortingActive(bool active)
Set true if we automatic sorting.
Definition entitytreeview.cpp:322
Akonadi
FreeBusyManager::Singleton.
Definition actionstatemanager_p.h:28
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Wed Jan 24 2024 00:00:00 by doxygen 1.10.0 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
  • Related Pages

kdepimlibs-4.14.10 API Reference

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