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

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