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
00129 void EntityTreeView::Private::itemClicked( const QModelIndex &index )
00130 {
00131 if ( !index.isValid() )
00132 return;
00133 QModelIndex idx = index.sibling( index.row(), 0);
00134
00135 const Collection collection = idx.model()->data( idx, EntityTreeModel::CollectionRole ).value<Collection>();
00136 if ( collection.isValid() ) {
00137 emit mParent->clicked( collection );
00138 } else {
00139 const Item item = idx.model()->data( idx, EntityTreeModel::ItemRole ).value<Item>();
00140 if ( item.isValid() )
00141 emit mParent->clicked( item );
00142 }
00143 }
00144
00145 void EntityTreeView::Private::itemDoubleClicked( const QModelIndex &index )
00146 {
00147 if ( !index.isValid() )
00148 return;
00149 QModelIndex idx = index.sibling( index.row(), 0);
00150 const Collection collection = idx.model()->data( idx, EntityTreeModel::CollectionRole ).value<Collection>();
00151 if ( collection.isValid() ) {
00152 emit mParent->doubleClicked( collection );
00153 } else {
00154 const Item item = idx.model()->data( idx, EntityTreeModel::ItemRole ).value<Item>();
00155 if ( item.isValid() )
00156 emit mParent->doubleClicked( item );
00157 }
00158 }
00159
00160 void EntityTreeView::Private::itemCurrentChanged( const QModelIndex &index )
00161 {
00162 if ( !index.isValid() )
00163 return;
00164 QModelIndex idx = index.sibling( index.row(), 0);
00165 const Collection collection = idx.model()->data( idx, EntityTreeModel::CollectionRole ).value<Collection>();
00166 if ( collection.isValid() ) {
00167 emit mParent->currentChanged( collection );
00168 } else {
00169 const Item item = idx.model()->data( idx, EntityTreeModel::ItemRole ).value<Item>();
00170 if ( item.isValid() )
00171 emit mParent->currentChanged( item );
00172 }
00173 }
00174
00175 EntityTreeView::EntityTreeView( QWidget * parent )
00176 : QTreeView( parent ),
00177 d( new Private( this ) )
00178 {
00179 setSelectionMode( QAbstractItemView::SingleSelection );
00180 d->init();
00181 }
00182
00183 EntityTreeView::EntityTreeView( KXMLGUIClient *xmlGuiClient, QWidget * parent )
00184 : QTreeView( parent ),
00185 d( new Private( this ) )
00186 {
00187 d->mXmlGuiClient = xmlGuiClient;
00188 d->init();
00189 }
00190
00191 EntityTreeView::~EntityTreeView()
00192 {
00193 delete d->mDragDropManager;
00194 delete d;
00195 }
00196
00197 void EntityTreeView::setModel( QAbstractItemModel * model )
00198 {
00199 if ( selectionModel() ) {
00200 disconnect( selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
00201 this, SLOT( itemCurrentChanged( const QModelIndex& ) ) );
00202
00203 disconnect( selectionModel(), SIGNAL( selectionChanged( const QItemSelection&, const QItemSelection& ) ),
00204 this, SLOT( slotSelectionChanged( const QItemSelection&, const QItemSelection& ) ) );
00205 }
00206
00207 QTreeView::setModel( model );
00208 header()->setStretchLastSection( true );
00209
00210 connect( selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
00211 SLOT( itemCurrentChanged( const QModelIndex& ) ) );
00212
00213 connect( selectionModel(), SIGNAL( selectionChanged( const QItemSelection&, const QItemSelection& ) ),
00214 SLOT( slotSelectionChanged( const QItemSelection&, const QItemSelection& ) ) );
00215 }
00216
00217
00218 void EntityTreeView::timerEvent( QTimerEvent *event )
00219 {
00220 if ( event->timerId() == d->mDragExpandTimer.timerId() ) {
00221 const QPoint pos = viewport()->mapFromGlobal( QCursor::pos() );
00222 if ( state() == QAbstractItemView::DraggingState && viewport()->rect().contains( pos ) )
00223 setExpanded( indexAt( pos ), true );
00224 }
00225
00226 QTreeView::timerEvent( event );
00227 }
00228
00229 #ifndef QT_NO_DRAGANDDROP
00230 void EntityTreeView::dragMoveEvent( QDragMoveEvent * event )
00231 {
00232 d->mDragExpandTimer.start( QApplication::startDragTime() , this );
00233
00234 if ( d->mDragDropManager->dropAllowed( event ) ) {
00235
00236 QTreeView::dragMoveEvent( event );
00237 return;
00238 }
00239
00240 event->setDropAction( Qt::IgnoreAction );
00241 return;
00242 }
00243
00244 void EntityTreeView::dropEvent( QDropEvent * event )
00245 {
00246 if ( d->mDragDropManager->processDropEvent( event ) )
00247 QTreeView::dropEvent( event );
00248
00249 d->mDragExpandTimer.stop();
00250 }
00251 #endif
00252
00253 #ifndef QT_NO_CONTEXTMENU
00254 void EntityTreeView::contextMenuEvent( QContextMenuEvent * event )
00255 {
00256 if ( !d->mXmlGuiClient || !model())
00257 return;
00258
00259 const QModelIndex index = indexAt( event->pos() );
00260
00261 QMenu *popup = 0;
00262
00263
00264 const Item item = model()->data( index, EntityTreeModel::ItemRole ).value<Item>();
00265 if ( item.isValid() )
00266 popup = static_cast<QMenu*>( d->mXmlGuiClient->factory()->container(
00267 QLatin1String( "akonadi_itemview_contextmenu" ), d->mXmlGuiClient ) );
00268 else
00269 popup = static_cast<QMenu*>( d->mXmlGuiClient->factory()->container(
00270 QLatin1String( "akonadi_collectionview_contextmenu" ), d->mXmlGuiClient ) );
00271 if ( popup )
00272 popup->exec( event->globalPos() );
00273 }
00274 #endif
00275
00276 void EntityTreeView::setXmlGuiClient( KXMLGUIClient * xmlGuiClient )
00277 {
00278 d->mXmlGuiClient = xmlGuiClient;
00279 }
00280
00281 #ifndef QT_NO_DRAGANDDROP
00282 void EntityTreeView::startDrag( Qt::DropActions supportedActions )
00283 {
00284 d->mDragDropManager->startDrag( supportedActions );
00285 }
00286 #endif
00287
00288
00289 void EntityTreeView::setDropActionMenuEnabled( bool enabled )
00290 {
00291 #ifndef QT_NO_DRAGANDDROP
00292 d->mDragDropManager->setShowDropActionMenu( enabled );
00293 #endif
00294 }
00295
00296 bool EntityTreeView::isDropActionMenuEnabled() const
00297 {
00298 #ifndef QT_NO_DRAGANDDROP
00299 return d->mDragDropManager->showDropActionMenu();
00300 #else
00301 return false;
00302 #endif
00303 }
00304
00305 #include "entitytreeview.moc"