• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • 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 
00005     This library is free software; you can redistribute it and/or modify it
00006     under the terms of the GNU Library General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or (at your
00008     option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful, but WITHOUT
00011     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013     License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to the
00017     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00018     02110-1301, USA.
00019 */
00020 
00021 #include "entitytreeview.h"
00022 
00023 #include "dragdropmanager_p.h"
00024 
00025 #include <QtCore/QDebug>
00026 #include <QtCore/QTimer>
00027 #include <QtGui/QApplication>
00028 #include <QtGui/QDragMoveEvent>
00029 #include <QtGui/QHeaderView>
00030 #include <QtGui/QMenu>
00031 
00032 #include <KAction>
00033 #include <KLocale>
00034 #include <KMessageBox>
00035 #include <KUrl>
00036 #include <KXMLGUIFactory>
00037 
00038 #include <akonadi/collection.h>
00039 #include <akonadi/control.h>
00040 #include <akonadi/item.h>
00041 #include <akonadi/entitytreemodel.h>
00042 
00043 #include <kdebug.h>
00044 #include <kxmlguiclient.h>
00045 
00046 #include "progressspinnerdelegate_p.h"
00047 
00048 using namespace Akonadi;
00049 
00053 class EntityTreeView::Private
00054 {
00055 public:
00056   Private( EntityTreeView *parent )
00057       : mParent( parent )
00058 #ifndef QT_NO_DRAGANDDROP
00059       , mDragDropManager( new DragDropManager( mParent ) )
00060 #endif
00061       , mXmlGuiClient( 0 )
00062   {
00063   }
00064 
00065   void init();
00066   void itemClicked( const QModelIndex& );
00067   void itemDoubleClicked( const QModelIndex& );
00068   void itemCurrentChanged( const QModelIndex& );
00069 
00070   void slotSelectionChanged( const QItemSelection & selected, const QItemSelection & deselected );
00071 
00072   EntityTreeView *mParent;
00073   QBasicTimer mDragExpandTimer;
00074   DragDropManager *mDragDropManager;
00075   KXMLGUIClient *mXmlGuiClient;
00076 };
00077 
00078 void EntityTreeView::Private::init()
00079 {
00080   Akonadi::DelegateAnimator *animator = new Akonadi::DelegateAnimator(mParent);
00081   Akonadi::ProgressSpinnerDelegate *customDelegate = new Akonadi::ProgressSpinnerDelegate(animator, mParent);
00082   mParent->setItemDelegate(customDelegate);
00083 
00084   mParent->header()->setClickable( true );
00085   mParent->header()->setStretchLastSection( false );
00086 //   mParent->setRootIsDecorated( false );
00087 
00088   // QTreeView::autoExpandDelay has very strange behaviour. It toggles the collapse/expand state
00089   // of the item the cursor is currently over when a timer event fires.
00090   // The behaviour we want is to expand a collapsed row on drag-over, but not collapse it.
00091   // mDragExpandTimer is used to achieve this.
00092 //   mParent->setAutoExpandDelay ( QApplication::startDragTime() );
00093 
00094   mParent->setSortingEnabled( true );
00095   mParent->sortByColumn( 0, Qt::AscendingOrder );
00096   mParent->setEditTriggers( QAbstractItemView::EditKeyPressed );
00097   mParent->setAcceptDrops( true );
00098 #ifndef QT_NO_DRAGANDDROP
00099   mParent->setDropIndicatorShown( true );
00100   mParent->setDragDropMode( DragDrop );
00101   mParent->setDragEnabled( true );
00102 #endif
00103 
00104   mParent->connect( mParent, SIGNAL( clicked( const QModelIndex& ) ),
00105                     mParent, SLOT( itemClicked( const QModelIndex& ) ) );
00106   mParent->connect( mParent, SIGNAL( doubleClicked( const QModelIndex& ) ),
00107                     mParent, SLOT( itemDoubleClicked( const QModelIndex& ) ) );
00108 
00109   Control::widgetNeedsAkonadi( mParent );
00110 }
00111 
00112 void EntityTreeView::Private::slotSelectionChanged( const QItemSelection & selected, const QItemSelection& )
00113 {
00114   const int column = 0;
00115   foreach ( const QItemSelectionRange &range, selected ) {
00116     const QModelIndex index = range.topLeft();
00117 
00118     if ( index.column() > 0 )
00119       continue;
00120 
00121     for ( int row = index.row(); row <= range.bottomRight().row(); ++row ) {
00122       // Don't use canFetchMore here. We need to bypass the check in
00123       // the EntityFilterModel when it shows only collections.
00124       mParent->model()->fetchMore( index.sibling( row, column ) );
00125     }
00126   }
00127 
00128   if ( selected.size() == 1 ) {
00129     const QItemSelectionRange &range = selected.first();
00130     if ( range.topLeft().row() == range.bottomRight().row() )
00131       mParent->scrollTo( range.topLeft(), QTreeView::EnsureVisible );
00132   }
00133 }
00134 
00135 void EntityTreeView::Private::itemClicked( const QModelIndex &index )
00136 {
00137   if ( !index.isValid() )
00138     return;
00139   QModelIndex idx = index.sibling( index.row(), 0);
00140 
00141   const Collection collection = idx.model()->data( idx, EntityTreeModel::CollectionRole ).value<Collection>();
00142   if ( collection.isValid() ) {
00143     emit mParent->clicked( collection );
00144   } else {
00145     const Item item = idx.model()->data( idx, EntityTreeModel::ItemRole ).value<Item>();
00146     if ( item.isValid() )
00147       emit mParent->clicked( item );
00148   }
00149 }
00150 
00151 void EntityTreeView::Private::itemDoubleClicked( const QModelIndex &index )
00152 {
00153   if ( !index.isValid() )
00154     return;
00155   QModelIndex idx = index.sibling( index.row(), 0);
00156   const Collection collection = idx.model()->data( idx, EntityTreeModel::CollectionRole ).value<Collection>();
00157   if ( collection.isValid() ) {
00158     emit mParent->doubleClicked( collection );
00159   } else {
00160     const Item item = idx.model()->data( idx, EntityTreeModel::ItemRole ).value<Item>();
00161     if ( item.isValid() )
00162       emit mParent->doubleClicked( item );
00163   }
00164 }
00165 
00166 void EntityTreeView::Private::itemCurrentChanged( const QModelIndex &index )
00167 {
00168   if ( !index.isValid() )
00169     return;
00170   QModelIndex idx = index.sibling( index.row(), 0);
00171   const Collection collection = idx.model()->data( idx, EntityTreeModel::CollectionRole ).value<Collection>();
00172   if ( collection.isValid() ) {
00173     emit mParent->currentChanged( collection );
00174   } else {
00175     const Item item = idx.model()->data( idx, EntityTreeModel::ItemRole ).value<Item>();
00176     if ( item.isValid() )
00177       emit mParent->currentChanged( item );
00178   }
00179 }
00180 
00181 EntityTreeView::EntityTreeView( QWidget * parent )
00182   : QTreeView( parent ),
00183     d( new Private( this ) )
00184 {
00185   setSelectionMode( QAbstractItemView::SingleSelection );
00186   d->init();
00187 }
00188 
00189 EntityTreeView::EntityTreeView( KXMLGUIClient *xmlGuiClient, QWidget * parent )
00190   : QTreeView( parent ),
00191     d( new Private( this ) )
00192 {
00193   d->mXmlGuiClient = xmlGuiClient;
00194   d->init();
00195 }
00196 
00197 EntityTreeView::~EntityTreeView()
00198 {
00199   delete d->mDragDropManager;
00200   delete d;
00201 }
00202 
00203 void EntityTreeView::setModel( QAbstractItemModel * model )
00204 {
00205   if ( selectionModel() ) {
00206     disconnect( selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
00207            this, SLOT( itemCurrentChanged( const QModelIndex& ) ) );
00208 
00209     disconnect( selectionModel(), SIGNAL( selectionChanged( const QItemSelection&, const QItemSelection& ) ),
00210            this, SLOT( slotSelectionChanged( const QItemSelection&, const QItemSelection& ) ) );
00211   }
00212 
00213   QTreeView::setModel( model );
00214   header()->setStretchLastSection( true );
00215 
00216   connect( selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
00217            SLOT( itemCurrentChanged( const QModelIndex& ) ) );
00218 
00219   connect( selectionModel(), SIGNAL( selectionChanged( const QItemSelection&, const QItemSelection& ) ),
00220            SLOT( slotSelectionChanged( const QItemSelection&, const QItemSelection& ) ) );
00221 }
00222 
00223 
00224 void EntityTreeView::timerEvent( QTimerEvent *event )
00225 {
00226   if ( event->timerId() == d->mDragExpandTimer.timerId() ) {
00227     const QPoint pos = viewport()->mapFromGlobal( QCursor::pos() );
00228     if ( state() == QAbstractItemView::DraggingState && viewport()->rect().contains( pos ) )
00229       setExpanded( indexAt( pos ), true );
00230   }
00231 
00232   QTreeView::timerEvent( event );
00233 }
00234 
00235 #ifndef QT_NO_DRAGANDDROP
00236 void EntityTreeView::dragMoveEvent( QDragMoveEvent * event )
00237 {
00238   d->mDragExpandTimer.start( QApplication::startDragTime() , this );
00239 
00240   if ( d->mDragDropManager->dropAllowed( event ) ) {
00241     // All urls are supported. process the event.
00242     QTreeView::dragMoveEvent( event );
00243     return;
00244   }
00245 
00246   event->setDropAction( Qt::IgnoreAction );
00247   return;
00248 }
00249 
00250 void EntityTreeView::dropEvent( QDropEvent * event )
00251 {
00252   if ( d->mDragDropManager->processDropEvent( event ) )
00253     QTreeView::dropEvent( event );
00254 
00255   d->mDragExpandTimer.stop();
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 #include "entitytreeview.moc"

akonadi

Skip menu "akonadi"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • 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
Generated for KDE-PIM Libraries by doxygen 1.7.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal