• Skip to content
  • Skip to link menu
KDE 4.5 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • 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 ), mDragDropManager( new DragDropManager( mParent ) ), mXmlGuiClient( 0 )
00058   {
00059   }
00060 
00061   void init();
00062   void itemClicked( const QModelIndex& );
00063   void itemDoubleClicked( const QModelIndex& );
00064   void itemCurrentChanged( const QModelIndex& );
00065 
00066   void slotSelectionChanged( const QItemSelection & selected, const QItemSelection & deselected );
00067 
00068   EntityTreeView *mParent;
00069   QBasicTimer mDragExpandTimer;
00070   DragDropManager *mDragDropManager;
00071   KXMLGUIClient *mXmlGuiClient;
00072 };
00073 
00074 void EntityTreeView::Private::init()
00075 {
00076   Akonadi::DelegateAnimator *animator = new Akonadi::DelegateAnimator(mParent);
00077   Akonadi::ProgressSpinnerDelegate *customDelegate = new Akonadi::ProgressSpinnerDelegate(animator, mParent);
00078   mParent->setItemDelegate(customDelegate);
00079 
00080   mParent->header()->setClickable( true );
00081   mParent->header()->setStretchLastSection( false );
00082 //   mParent->setRootIsDecorated( false );
00083 
00084   // QTreeView::autoExpandDelay has very strange behaviour. It toggles the collapse/expand state
00085   // of the item the cursor is currently over when a timer event fires.
00086   // The behaviour we want is to expand a collapsed row on drag-over, but not collapse it.
00087   // mDragExpandTimer is used to achieve this.
00088 //   mParent->setAutoExpandDelay ( QApplication::startDragTime() );
00089 
00090   mParent->setSortingEnabled( true );
00091   mParent->sortByColumn( 0, Qt::AscendingOrder );
00092   mParent->setEditTriggers( QAbstractItemView::EditKeyPressed );
00093   mParent->setAcceptDrops( true );
00094   mParent->setDropIndicatorShown( true );
00095   mParent->setDragDropMode( DragDrop );
00096   mParent->setDragEnabled( true );
00097 
00098   mParent->connect( mParent, SIGNAL( clicked( const QModelIndex& ) ),
00099                     mParent, SLOT( itemClicked( const QModelIndex& ) ) );
00100   mParent->connect( mParent, SIGNAL( doubleClicked( const QModelIndex& ) ),
00101                     mParent, SLOT( itemDoubleClicked( const QModelIndex& ) ) );
00102 
00103   Control::widgetNeedsAkonadi( mParent );
00104 }
00105 
00106 void EntityTreeView::Private::slotSelectionChanged( const QItemSelection & selected, const QItemSelection& )
00107 {
00108   const int column = 0;
00109   foreach ( const QItemSelectionRange &range, selected ) {
00110     const QModelIndex index = range.topLeft();
00111 
00112     if ( index.column() > 0 )
00113       continue;
00114 
00115     for ( int row = index.row(); row <= range.bottomRight().row(); ++row ) {
00116       // Don't use canFetchMore here. We need to bypass the check in
00117       // the EntityFilterModel when it shows only collections.
00118       mParent->model()->fetchMore( index.sibling( row, column ) );
00119     }
00120   }
00121 }
00122 
00123 void EntityTreeView::Private::itemClicked( const QModelIndex &index )
00124 {
00125   if ( !index.isValid() )
00126     return;
00127 
00128   const Collection collection = index.model()->data( index, EntityTreeModel::CollectionRole ).value<Collection>();
00129   if ( collection.isValid() ) {
00130     emit mParent->clicked( collection );
00131   } else {
00132     const Item item = index.model()->data( index, EntityTreeModel::ItemRole ).value<Item>();
00133     if ( item.isValid() )
00134       emit mParent->clicked( item );
00135   }
00136 }
00137 
00138 void EntityTreeView::Private::itemDoubleClicked( const QModelIndex &index )
00139 {
00140   if ( !index.isValid() )
00141     return;
00142 
00143   const Collection collection = index.model()->data( index, EntityTreeModel::CollectionRole ).value<Collection>();
00144   if ( collection.isValid() ) {
00145     emit mParent->doubleClicked( collection );
00146   } else {
00147     const Item item = index.model()->data( index, EntityTreeModel::ItemRole ).value<Item>();
00148     if ( item.isValid() )
00149       emit mParent->doubleClicked( item );
00150   }
00151 }
00152 
00153 void EntityTreeView::Private::itemCurrentChanged( const QModelIndex &index )
00154 {
00155   if ( !index.isValid() )
00156     return;
00157 
00158   const Collection collection = index.model()->data( index, EntityTreeModel::CollectionRole ).value<Collection>();
00159   if ( collection.isValid() ) {
00160     emit mParent->currentChanged( collection );
00161   } else {
00162     const Item item = index.model()->data( index, EntityTreeModel::ItemRole ).value<Item>();
00163     if ( item.isValid() )
00164       emit mParent->currentChanged( item );
00165   }
00166 }
00167 
00168 EntityTreeView::EntityTreeView( QWidget * parent )
00169   : QTreeView( parent ),
00170     d( new Private( this ) )
00171 {
00172   setSelectionMode( QAbstractItemView::SingleSelection );
00173   d->init();
00174 }
00175 
00176 EntityTreeView::EntityTreeView( KXMLGUIClient *xmlGuiClient, QWidget * parent )
00177   : QTreeView( parent ),
00178     d( new Private( this ) )
00179 {
00180   d->mXmlGuiClient = xmlGuiClient;
00181   d->init();
00182 }
00183 
00184 EntityTreeView::~EntityTreeView()
00185 {
00186   delete d->mDragDropManager;
00187   delete d;
00188 }
00189 
00190 void EntityTreeView::setModel( QAbstractItemModel * model )
00191 {
00192   if ( selectionModel() ) {
00193     disconnect( selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
00194            this, SLOT( itemCurrentChanged( const QModelIndex& ) ) );
00195 
00196     disconnect( selectionModel(), SIGNAL( selectionChanged( const QItemSelection&, const QItemSelection& ) ),
00197            this, SLOT( slotSelectionChanged( const QItemSelection&, const QItemSelection& ) ) );
00198   }
00199 
00200   QTreeView::setModel( model );
00201   header()->setStretchLastSection( true );
00202 
00203   connect( selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
00204            SLOT( itemCurrentChanged( const QModelIndex& ) ) );
00205 
00206   connect( selectionModel(), SIGNAL( selectionChanged( const QItemSelection&, const QItemSelection& ) ),
00207            SLOT( slotSelectionChanged( const QItemSelection&, const QItemSelection& ) ) );
00208 }
00209 
00210 
00211 void EntityTreeView::timerEvent( QTimerEvent *event )
00212 {
00213   if ( event->timerId() == d->mDragExpandTimer.timerId() ) {
00214     const QPoint pos = viewport()->mapFromGlobal( QCursor::pos() );
00215     if ( state() == QAbstractItemView::DraggingState && viewport()->rect().contains( pos ) )
00216       setExpanded( indexAt( pos ), true );
00217   }
00218 
00219   QTreeView::timerEvent( event );
00220 }
00221 
00222 void EntityTreeView::dragMoveEvent( QDragMoveEvent * event )
00223 {
00224   d->mDragExpandTimer.start( QApplication::startDragTime() , this );
00225 
00226   if ( d->mDragDropManager->dropAllowed( event ) ) {
00227     // All urls are supported. process the event.
00228     QTreeView::dragMoveEvent( event );
00229     return;
00230   }
00231 
00232   event->setDropAction( Qt::IgnoreAction );
00233   return;
00234 }
00235 
00236 void EntityTreeView::dropEvent( QDropEvent * event )
00237 {
00238   if ( d->mDragDropManager->processDropEvent( event ) )
00239     QTreeView::dropEvent( event );
00240 
00241   d->mDragExpandTimer.stop();
00242 }
00243 
00244 void EntityTreeView::contextMenuEvent( QContextMenuEvent * event )
00245 {
00246   if ( !d->mXmlGuiClient || !model())
00247     return;
00248 
00249   const QModelIndex index = indexAt( event->pos() );
00250 
00251   QMenu *popup = 0;
00252 
00253   // check if the index under the cursor is a collection or item
00254   const Item item = model()->data( index, EntityTreeModel::ItemRole ).value<Item>();
00255   if ( item.isValid() )
00256     popup = static_cast<QMenu*>( d->mXmlGuiClient->factory()->container(
00257                                  QLatin1String( "akonadi_itemview_contextmenu" ), d->mXmlGuiClient ) );
00258   else
00259     popup = static_cast<QMenu*>( d->mXmlGuiClient->factory()->container(
00260                                  QLatin1String( "akonadi_collectionview_contextmenu" ), d->mXmlGuiClient ) );
00261   if ( popup )
00262     popup->exec( event->globalPos() );
00263 }
00264 
00265 void EntityTreeView::setXmlGuiClient( KXMLGUIClient * xmlGuiClient )
00266 {
00267   d->mXmlGuiClient = xmlGuiClient;
00268 }
00269 
00270 void EntityTreeView::startDrag( Qt::DropActions supportedActions )
00271 {
00272   d->mDragDropManager->startDrag( supportedActions );
00273 }
00274 
00275 
00276 void EntityTreeView::setDropActionMenuEnabled( bool enabled )
00277 {
00278   d->mDragDropManager->setShowDropActionMenu( enabled );
00279 }
00280 
00281 bool EntityTreeView::isDropActionMenuEnabled() const
00282 {
00283   return d->mDragDropManager->showDropActionMenu();
00284 }
00285 
00286 #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
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • 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.1
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