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

akonadi

entitytreeview.cpp
00001 /*
00002     Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>
00003     Copyright (c) 2008 Stephen Kelly <steveire@gmail.com>
00004     Copyright (c) 2012 Laurent Montel <montel@kde.org>
00005 
00006     This library is free software; you can redistribute it and/or modify it
00007     under the terms of the GNU Library General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or (at your
00009     option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful, but WITHOUT
00012     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00013     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00014     License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to the
00018     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00019     02110-1301, USA.
00020 */
00021 
00022 #include "entitytreeview.h"
00023 
00024 #include "dragdropmanager_p.h"
00025 
00026 #include <QtCore/QDebug>
00027 #include <QtCore/QTimer>
00028 #include <QtGui/QApplication>
00029 #include <QtGui/QDragMoveEvent>
00030 #include <QtGui/QHeaderView>
00031 #include <QtGui/QMenu>
00032 
00033 #include <KAction>
00034 #include <KLocale>
00035 #include <KMessageBox>
00036 #include <KUrl>
00037 #include <KXMLGUIFactory>
00038 
00039 #include <akonadi/collection.h>
00040 #include <akonadi/control.h>
00041 #include <akonadi/item.h>
00042 #include <akonadi/entitytreemodel.h>
00043 
00044 #include <kdebug.h>
00045 #include <kxmlguiclient.h>
00046 
00047 #include "progressspinnerdelegate_p.h"
00048 
00049 using namespace Akonadi;
00050 
00054 class EntityTreeView::Private
00055 {
00056 public:
00057   Private( EntityTreeView *parent )
00058       : mParent( parent )
00059 #ifndef QT_NO_DRAGANDDROP
00060       , mDragDropManager( new DragDropManager( mParent ) )
00061 #endif
00062       , mXmlGuiClient( 0 )
00063   {
00064   }
00065 
00066   void init();
00067   void itemClicked( const QModelIndex& );
00068   void itemDoubleClicked( const QModelIndex& );
00069   void itemCurrentChanged( const QModelIndex& );
00070 
00071   void slotSelectionChanged( const QItemSelection & selected, const QItemSelection & deselected );
00072 
00073   EntityTreeView *mParent;
00074   QBasicTimer mDragExpandTimer;
00075   DragDropManager *mDragDropManager;
00076   KXMLGUIClient *mXmlGuiClient;
00077 };
00078 
00079 void EntityTreeView::Private::init()
00080 {
00081   Akonadi::DelegateAnimator *animator = new Akonadi::DelegateAnimator(mParent);
00082   Akonadi::ProgressSpinnerDelegate *customDelegate = new Akonadi::ProgressSpinnerDelegate(animator, mParent);
00083   mParent->setItemDelegate(customDelegate);
00084 
00085   mParent->header()->setClickable( true );
00086   mParent->header()->setStretchLastSection( false );
00087 //   mParent->setRootIsDecorated( false );
00088 
00089   // QTreeView::autoExpandDelay has very strange behaviour. It toggles the collapse/expand state
00090   // of the item the cursor is currently over when a timer event fires.
00091   // The behaviour we want is to expand a collapsed row on drag-over, but not collapse it.
00092   // mDragExpandTimer is used to achieve this.
00093 //   mParent->setAutoExpandDelay ( QApplication::startDragTime() );
00094 
00095   mParent->setSortingEnabled( true );
00096   mParent->sortByColumn( 0, Qt::AscendingOrder );
00097   mParent->setEditTriggers( QAbstractItemView::EditKeyPressed );
00098   mParent->setAcceptDrops( true );
00099 #ifndef QT_NO_DRAGANDDROP
00100   mParent->setDropIndicatorShown( true );
00101   mParent->setDragDropMode( DragDrop );
00102   mParent->setDragEnabled( true );
00103 #endif
00104 
00105   mParent->connect( mParent, SIGNAL(clicked(QModelIndex)),
00106                     mParent, SLOT(itemClicked(QModelIndex)) );
00107   mParent->connect( mParent, SIGNAL(doubleClicked(QModelIndex)),
00108                     mParent, SLOT(itemDoubleClicked(QModelIndex)) );
00109 
00110   Control::widgetNeedsAkonadi( mParent );
00111 }
00112 
00113 void EntityTreeView::Private::slotSelectionChanged( const QItemSelection & selected, const QItemSelection& )
00114 {
00115   const int column = 0;
00116   foreach ( const QItemSelectionRange &range, selected ) {
00117     const QModelIndex index = range.topLeft();
00118 
00119     if ( index.column() > 0 )
00120       continue;
00121 
00122     for ( int row = index.row(); row <= range.bottomRight().row(); ++row ) {
00123       // Don't use canFetchMore here. We need to bypass the check in
00124       // the EntityFilterModel when it shows only collections.
00125       mParent->model()->fetchMore( index.sibling( row, column ) );
00126     }
00127   }
00128 
00129   if ( selected.size() == 1 ) {
00130     const QItemSelectionRange &range = selected.first();
00131     if ( range.topLeft().row() == range.bottomRight().row() )
00132       mParent->scrollTo( range.topLeft(), QTreeView::EnsureVisible );
00133   }
00134 }
00135 
00136 void EntityTreeView::Private::itemClicked( const QModelIndex &index )
00137 {
00138   if ( !index.isValid() )
00139     return;
00140   QModelIndex idx = index.sibling( index.row(), 0);
00141 
00142   const Collection collection = idx.model()->data( idx, EntityTreeModel::CollectionRole ).value<Collection>();
00143   if ( collection.isValid() ) {
00144     emit mParent->clicked( collection );
00145   } else {
00146     const Item item = idx.model()->data( idx, EntityTreeModel::ItemRole ).value<Item>();
00147     if ( item.isValid() )
00148       emit mParent->clicked( item );
00149   }
00150 }
00151 
00152 void EntityTreeView::Private::itemDoubleClicked( const QModelIndex &index )
00153 {
00154   if ( !index.isValid() )
00155     return;
00156   QModelIndex idx = index.sibling( index.row(), 0);
00157   const Collection collection = idx.model()->data( idx, EntityTreeModel::CollectionRole ).value<Collection>();
00158   if ( collection.isValid() ) {
00159     emit mParent->doubleClicked( collection );
00160   } else {
00161     const Item item = idx.model()->data( idx, EntityTreeModel::ItemRole ).value<Item>();
00162     if ( item.isValid() )
00163       emit mParent->doubleClicked( item );
00164   }
00165 }
00166 
00167 void EntityTreeView::Private::itemCurrentChanged( const QModelIndex &index )
00168 {
00169   if ( !index.isValid() )
00170     return;
00171   QModelIndex idx = index.sibling( index.row(), 0);
00172   const Collection collection = idx.model()->data( idx, EntityTreeModel::CollectionRole ).value<Collection>();
00173   if ( collection.isValid() ) {
00174     emit mParent->currentChanged( collection );
00175   } else {
00176     const Item item = idx.model()->data( idx, EntityTreeModel::ItemRole ).value<Item>();
00177     if ( item.isValid() )
00178       emit mParent->currentChanged( item );
00179   }
00180 }
00181 
00182 EntityTreeView::EntityTreeView( QWidget * parent )
00183   : QTreeView( parent ),
00184     d( new Private( this ) )
00185 {
00186   setSelectionMode( QAbstractItemView::SingleSelection );
00187   d->init();
00188 }
00189 
00190 EntityTreeView::EntityTreeView( KXMLGUIClient *xmlGuiClient, QWidget * parent )
00191   : QTreeView( parent ),
00192     d( new Private( this ) )
00193 {
00194   d->mXmlGuiClient = xmlGuiClient;
00195   d->init();
00196 }
00197 
00198 EntityTreeView::~EntityTreeView()
00199 {
00200   delete d->mDragDropManager;
00201   delete d;
00202 }
00203 
00204 void EntityTreeView::setModel( QAbstractItemModel * model )
00205 {
00206   if ( selectionModel() ) {
00207     disconnect( selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
00208            this, SLOT(itemCurrentChanged(QModelIndex)) );
00209 
00210     disconnect( selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
00211            this, SLOT(slotSelectionChanged(QItemSelection,QItemSelection)) );
00212   }
00213 
00214   QTreeView::setModel( model );
00215   header()->setStretchLastSection( true );
00216 
00217   connect( selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
00218            SLOT(itemCurrentChanged(QModelIndex)) );
00219 
00220   connect( selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
00221            SLOT(slotSelectionChanged(QItemSelection,QItemSelection)) );
00222 }
00223 
00224 
00225 void EntityTreeView::timerEvent( QTimerEvent *event )
00226 {
00227   if ( event->timerId() == d->mDragExpandTimer.timerId() ) {
00228     const QPoint pos = viewport()->mapFromGlobal( QCursor::pos() );
00229     if ( state() == QAbstractItemView::DraggingState && viewport()->rect().contains( pos ) )
00230       setExpanded( indexAt( pos ), true );
00231   }
00232 
00233   QTreeView::timerEvent( event );
00234 }
00235 
00236 #ifndef QT_NO_DRAGANDDROP
00237 void EntityTreeView::dragMoveEvent( QDragMoveEvent * event )
00238 {
00239   d->mDragExpandTimer.start( QApplication::startDragTime() , this );
00240 
00241   if ( d->mDragDropManager->dropAllowed( event ) ) {
00242     // All urls are supported. process the event.
00243     QTreeView::dragMoveEvent( event );
00244     return;
00245   }
00246 
00247   event->setDropAction( Qt::IgnoreAction );
00248 }
00249 
00250 void EntityTreeView::dropEvent( QDropEvent * event )
00251 {
00252   d->mDragExpandTimer.stop();
00253   bool menuCanceled = false;
00254   if ( d->mDragDropManager->processDropEvent( event, menuCanceled, ( dropIndicatorPosition () == QAbstractItemView::OnItem ) ) )
00255     QTreeView::dropEvent( event );
00256 }
00257 #endif
00258 
00259 #ifndef QT_NO_CONTEXTMENU
00260 void EntityTreeView::contextMenuEvent( QContextMenuEvent * event )
00261 {
00262   if ( !d->mXmlGuiClient || !model())
00263     return;
00264 
00265   const QModelIndex index = indexAt( event->pos() );
00266 
00267   QMenu *popup = 0;
00268 
00269   // check if the index under the cursor is a collection or item
00270   const Item item = model()->data( index, EntityTreeModel::ItemRole ).value<Item>();
00271   if ( item.isValid() )
00272     popup = static_cast<QMenu*>( d->mXmlGuiClient->factory()->container(
00273                                  QLatin1String( "akonadi_itemview_contextmenu" ), d->mXmlGuiClient ) );
00274   else
00275     popup = static_cast<QMenu*>( d->mXmlGuiClient->factory()->container(
00276                                  QLatin1String( "akonadi_collectionview_contextmenu" ), d->mXmlGuiClient ) );
00277   if ( popup )
00278     popup->exec( event->globalPos() );
00279 }
00280 #endif
00281 
00282 void EntityTreeView::setXmlGuiClient( KXMLGUIClient * xmlGuiClient )
00283 {
00284   d->mXmlGuiClient = xmlGuiClient;
00285 }
00286 
00287 #ifndef QT_NO_DRAGANDDROP
00288 void EntityTreeView::startDrag( Qt::DropActions supportedActions )
00289 {
00290   d->mDragDropManager->startDrag( supportedActions );
00291 }
00292 #endif
00293 
00294 
00295 void EntityTreeView::setDropActionMenuEnabled( bool enabled )
00296 {
00297 #ifndef QT_NO_DRAGANDDROP
00298   d->mDragDropManager->setShowDropActionMenu( enabled );
00299 #endif
00300 }
00301 
00302 bool EntityTreeView::isDropActionMenuEnabled() const
00303 {
00304 #ifndef QT_NO_DRAGANDDROP
00305   return d->mDragDropManager->showDropActionMenu();
00306 #else
00307   return false;
00308 #endif
00309 }
00310 
00311 void EntityTreeView::setManualSortingActive(bool active)
00312 {
00313 #ifndef QT_NO_DRAGANDDROP
00314   d->mDragDropManager->setManualSortingActive( active );
00315 #endif 
00316 }
00317 
00318 bool EntityTreeView::isManualSortingActive() const
00319 {
00320 #ifndef QT_NO_DRAGANDDROP
00321   return d->mDragDropManager->isManualSortingActive();
00322 #else
00323   return false;
00324 #endif 
00325 }
00326 
00327 
00328 #include "entitytreeview.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Apr 30 2012 21:49:15 by doxygen 1.8.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
  • Modules
  • Related Pages

kdepimlibs-4.8.3 API Reference

Skip menu "kdepimlibs-4.8.3 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • 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