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

akonadi

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

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