• 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
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 
44 using namespace Akonadi;
45 
49 class EntityTreeView::Private
50 {
51 public:
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 
76 void 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 
110 void 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 
135 void 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 
153 void 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 
170 void 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 
187 EntityTreeView::EntityTreeView(QWidget *parent)
188  : QTreeView(parent)
189  , d(new Private(this))
190 {
191  setSelectionMode(QAbstractItemView::SingleSelection);
192  d->init();
193 }
194 
195 EntityTreeView::EntityTreeView(KXMLGUIClient *xmlGuiClient, QWidget *parent)
196  : QTreeView(parent)
197  , d(new Private(this))
198 {
199  d->mXmlGuiClient = xmlGuiClient;
200  d->init();
201 }
202 
203 EntityTreeView::~EntityTreeView()
204 {
205  delete d->mDragDropManager;
206  delete d;
207 }
208 
209 void 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 
229 void 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
242 void 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 
255 void 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
266 void 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 
289 void EntityTreeView::setXmlGuiClient(KXMLGUIClient *xmlGuiClient)
290 {
291  d->mXmlGuiClient = xmlGuiClient;
292 }
293 
294 KXMLGUIClient *EntityTreeView::xmlGuiClient() const
295 {
296  return d->mXmlGuiClient;
297 }
298 
299 #ifndef QT_NO_DRAGANDDROP
300 void EntityTreeView::startDrag(Qt::DropActions supportedActions)
301 {
302  d->mDragDropManager->startDrag(supportedActions);
303 }
304 #endif
305 
306 void EntityTreeView::setDropActionMenuEnabled(bool enabled)
307 {
308 #ifndef QT_NO_DRAGANDDROP
309  d->mDragDropManager->setShowDropActionMenu(enabled);
310 #endif
311 }
312 
313 bool EntityTreeView::isDropActionMenuEnabled() const
314 {
315 #ifndef QT_NO_DRAGANDDROP
316  return d->mDragDropManager->showDropActionMenu();
317 #else
318  return false;
319 #endif
320 }
321 
322 void EntityTreeView::setManualSortingActive(bool active)
323 {
324 #ifndef QT_NO_DRAGANDDROP
325  d->mDragDropManager->setManualSortingActive(active);
326 #endif
327 }
328 
329 bool EntityTreeView::isManualSortingActive() const
330 {
331 #ifndef QT_NO_DRAGANDDROP
332  return d->mDragDropManager->isManualSortingActive();
333 #else
334  return false;
335 #endif
336 }
337 
338 void EntityTreeView::setDefaultPopupMenu(const QString &name)
339 {
340  d->mDefaultPopupMenu = name;
341 }
342 
343 #include "moc_entitytreeview.cpp"
QModelIndex
QWidget
QTreeView::dragMoveEvent
virtual void dragMoveEvent(QDragMoveEvent *event)
Akonadi::EntityTreeView::~EntityTreeView
virtual ~EntityTreeView()
Destroys the entity tree view.
Definition: entitytreeview.cpp:203
QItemSelectionRange
QAbstractItemView::dropIndicatorPosition
DropIndicatorPosition dropIndicatorPosition() const
QAbstractItemView::setSelectionMode
void setSelectionMode(QAbstractItemView::SelectionMode mode)
QBasicTimer
QAbstractItemView::selectionModel
QItemSelectionModel * selectionModel() const
QDragMoveEvent
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::Collection
Represents a collection of PIM items.
Definition: collection.h:75
QItemSelectionRange::bottomRight
QModelIndex bottomRight() const
QVariant::value
T value() const
QAbstractScrollArea::viewport
QWidget * viewport() const
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::setManualSortingActive
void setManualSortingActive(bool active)
Set true if we automatic sorting.
Definition: entitytreeview.cpp:322
QPoint
QObject::disconnect
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QContextMenuEvent::globalPos
const QPoint & globalPos() const
QList::size
int size() const
QTreeView::setExpanded
void setExpanded(const QModelIndex &index, bool expanded)
QTimerEvent
QObject::name
const char * name() const
QModelIndex::isValid
bool isValid() const
Akonadi::EntityTreeView::xmlGuiClient
KXMLGUIClient * xmlGuiClient() const
Return the XML GUI client which the view is used in.
Definition: entitytreeview.cpp:294
QTreeView::timerEvent
virtual void timerEvent(QTimerEvent *event)
QContextMenuEvent
Akonadi::EntityTreeView
A view to show an item/collection tree provided by an EntityTreeModel.
Definition: entitytreeview.h:71
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::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
QDropEvent
QModelIndex::row
int row() const
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
QWidget::pos
QPoint pos() const
QAbstractItemModel::data
virtual QVariant data(const QModelIndex &index, int role) const =0
QList::first
T & first()
Akonadi::EntityTreeModel::CollectionRole
The collection.
Definition: entitytreemodel.h:336
QString
QMenu::exec
QAction * exec()
QWidget::rect
QRect rect() const
Akonadi::EntityTreeView::EntityTreeView
EntityTreeView(QWidget *parent=0)
Creates a new entity tree view.
Definition: entitytreeview.cpp:187
QMenu
QAbstractItemView::state
State state() const
QItemSelection
QApplication::startDragTime
int startDragTime()
QContextMenuEvent::pos
const QPoint & pos() const
QModelIndex::model
const QAbstractItemModel * model() const
QCursor::pos
QPoint pos()
Akonadi::EntityTreeModel::ItemRole
The Item.
Definition: entitytreemodel.h:332
QLatin1String
QTreeView
Qt::DropActions
typedef DropActions
QModelIndex::sibling
QModelIndex sibling(int row, int column) const
QTreeView::setModel
virtual void setModel(QAbstractItemModel *model)
QTreeView::selectionChanged
virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
QAbstractItemView::dropEvent
virtual void dropEvent(QDropEvent *event)
QWidget::mapFromGlobal
QPoint mapFromGlobal(const QPoint &pos) const
QModelIndex::column
int column() const
QAbstractItemModel::fetchMore
virtual void fetchMore(const QModelIndex &parent)
QTimerEvent::timerId
int timerId() const
QAbstractItemModel
Akonadi::EntityTreeView::setModel
virtual void setModel(QAbstractItemModel *model)
Definition: entitytreeview.cpp:209
QTreeView::header
QHeaderView * header() const
QAbstractItemView::model
QAbstractItemModel * model() const
Akonadi::Entity::isValid
bool isValid() const
Returns whether the entity is valid.
Definition: entity.cpp:97
QHeaderView::setStretchLastSection
void setStretchLastSection(bool stretch)
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Akonadi::EntityTreeView::setXmlGuiClient
void setXmlGuiClient(KXMLGUIClient *xmlGuiClient)
Sets the XML GUI client which the view is used in.
Definition: entitytreeview.cpp:289
QObject::parent
QObject * parent() const
Akonadi::EntityTreeView::currentChanged
void currentChanged(const Akonadi::Collection &collection)
This signal is emitted whenever the current collection in the view has changed.
QTreeView::indexAt
virtual QModelIndex indexAt(const QPoint &point) const
QItemSelectionRange::topLeft
QModelIndex topLeft() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:38:03 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