00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00087
00088
00089
00090
00091
00092
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
00123
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
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
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"