akonadi
collectionview.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "collectionview.h"
00021
00022 #include "collection.h"
00023 #include "collectionmodel.h"
00024
00025 #include <kaction.h>
00026 #include <kdebug.h>
00027 #include <klocale.h>
00028 #include <kmessagebox.h>
00029 #include <kurl.h>
00030 #include <kxmlguifactory.h>
00031 #include <kxmlguiwindow.h>
00032
00033 #include <QtCore/QDebug>
00034 #include <QtCore/QTimer>
00035 #include <QtGui/QApplication>
00036 #include <QtGui/QDragMoveEvent>
00037 #include <QtGui/QHeaderView>
00038 #include <QtGui/QMenu>
00039
00040 using namespace Akonadi;
00041
00045 class CollectionView::Private
00046 {
00047 public:
00048 Private( CollectionView *parent )
00049 : mParent( parent ),
00050 xmlGuiWindow( 0 )
00051 {
00052 }
00053
00054 void init();
00055 void dragExpand();
00056 void itemClicked( const QModelIndex& );
00057 void itemCurrentChanged( const QModelIndex& );
00058 bool hasParent( const QModelIndex& idx, Collection::Id parentId );
00059
00060 CollectionView *mParent;
00061 QModelIndex dragOverIndex;
00062 QTimer dragExpandTimer;
00063
00064 KXmlGuiWindow *xmlGuiWindow;
00065 };
00066
00067 void CollectionView::Private::init()
00068 {
00069 mParent->header()->setClickable( true );
00070 mParent->header()->setStretchLastSection( false );
00071
00072 mParent->setSortingEnabled( true );
00073 mParent->sortByColumn( 0, Qt::AscendingOrder );
00074 mParent->setEditTriggers( QAbstractItemView::EditKeyPressed );
00075 mParent->setAcceptDrops( true );
00076 mParent->setDropIndicatorShown( true );
00077 mParent->setDragDropMode( DragDrop );
00078 mParent->setDragEnabled( true );
00079
00080 dragExpandTimer.setSingleShot( true );
00081 mParent->connect( &dragExpandTimer, SIGNAL(timeout()), SLOT(dragExpand()) );
00082
00083 mParent->connect( mParent, SIGNAL( clicked( const QModelIndex& ) ),
00084 mParent, SLOT( itemClicked( const QModelIndex& ) ) );
00085 }
00086
00087 bool CollectionView::Private::hasParent( const QModelIndex& idx, Collection::Id parentId )
00088 {
00089 QModelIndex idx2 = idx;
00090 while( idx2.isValid() ) {
00091 if ( mParent->model()->data( idx2, CollectionModel::CollectionIdRole).toLongLong() == parentId )
00092 return true;
00093
00094 idx2 = idx2.parent();
00095 }
00096 return false;
00097 }
00098
00099 void CollectionView::Private::dragExpand()
00100 {
00101 mParent->setExpanded( dragOverIndex, true );
00102 dragOverIndex = QModelIndex();
00103 }
00104
00105 void CollectionView::Private::itemClicked( const QModelIndex &index )
00106 {
00107 if ( !index.isValid() )
00108 return;
00109
00110 const Collection col = index.model()->data( index, CollectionModel::CollectionRole ).value<Collection>();
00111 if ( !col.isValid() )
00112 return;
00113
00114 emit mParent->clicked( col );
00115 }
00116
00117 void CollectionView::Private::itemCurrentChanged( const QModelIndex &index )
00118 {
00119 if ( !index.isValid() )
00120 return;
00121
00122 const Collection col = index.model()->data( index, CollectionModel::CollectionRole ).value<Collection>();
00123 if ( !col.isValid() )
00124 return;
00125
00126 emit mParent->currentChanged( col );
00127 }
00128
00129 CollectionView::CollectionView(QWidget * parent) :
00130 QTreeView( parent ),
00131 d( new Private( this ) )
00132 {
00133 d->init();
00134 }
00135
00136 CollectionView::CollectionView( KXmlGuiWindow *xmlGuiWindow, QWidget * parent ) :
00137 QTreeView( parent ),
00138 d( new Private( this ) )
00139 {
00140 d->xmlGuiWindow = xmlGuiWindow;
00141 d->init();
00142 }
00143
00144 CollectionView::~CollectionView()
00145 {
00146 delete d;
00147 }
00148
00149 void CollectionView::setModel( QAbstractItemModel * model )
00150 {
00151 QTreeView::setModel( model );
00152 header()->setStretchLastSection( true );
00153
00154 connect( selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
00155 this, SLOT( itemCurrentChanged( const QModelIndex& ) ) );
00156 }
00157
00158 void CollectionView::dragMoveEvent(QDragMoveEvent * event)
00159 {
00160 QModelIndex index = indexAt( event->pos() );
00161 if ( d->dragOverIndex != index ) {
00162 d->dragExpandTimer.stop();
00163 if ( index.isValid() && !isExpanded( index ) && itemsExpandable() ) {
00164 d->dragExpandTimer.start( QApplication::startDragTime() );
00165 d->dragOverIndex = index;
00166 }
00167 }
00168
00169
00170 QStringList supportedContentTypes = model()->data( index, CollectionModel::CollectionRole ).value<Collection>().contentMimeTypes();
00171 const QMimeData *data = event->mimeData();
00172 KUrl::List urls = KUrl::List::fromMimeData( data );
00173 foreach( const KUrl &url, urls ) {
00174
00175 const Collection collection = Collection::fromUrl( url );
00176 if ( collection.isValid() )
00177 {
00178 if ( !supportedContentTypes.contains( QString::fromLatin1( "inode/directory" ) ) )
00179 break;
00180
00181
00182 if ( d->hasParent( index, collection.id() ) )
00183 break;
00184 }
00185 else
00186 {
00187 QString type = url.queryItems()[ QString::fromLatin1("type") ];
00188 if ( !supportedContentTypes.contains( type ) )
00189 break;
00190 }
00191
00192 QTreeView::dragMoveEvent( event );
00193 return;
00194 }
00195
00196 event->setDropAction( Qt::IgnoreAction );
00197 return;
00198 }
00199
00200 void CollectionView::dragLeaveEvent(QDragLeaveEvent * event)
00201 {
00202 d->dragExpandTimer.stop();
00203 d->dragOverIndex = QModelIndex();
00204 QTreeView::dragLeaveEvent( event );
00205 }
00206
00207
00208 void CollectionView::dropEvent(QDropEvent * event)
00209 {
00210 d->dragExpandTimer.stop();
00211 d->dragOverIndex = QModelIndex();
00212
00213
00214
00215 QMenu popup( this );
00216 QAction* moveDropAction = popup.addAction( KIcon( QString::fromLatin1("edit-rename") ), i18n("&Move here") );
00217 QAction* copyDropAction = popup.addAction( KIcon( QString::fromLatin1("edit-copy") ), i18n("&Copy here") );
00218 popup.addSeparator();
00219 popup.addAction( KIcon( QString::fromLatin1("process-stop") ), i18n("Cancel"));
00220
00221 QAction *activatedAction = popup.exec( QCursor::pos() );
00222 if (activatedAction == moveDropAction) {
00223 event->setDropAction( Qt::MoveAction );
00224 }
00225 else if (activatedAction == copyDropAction) {
00226 event->setDropAction( Qt::CopyAction );
00227 }
00228 else return;
00229
00230 QTreeView::dropEvent( event );
00231 }
00232
00233 void CollectionView::contextMenuEvent(QContextMenuEvent * event)
00234 {
00235 if ( !d->xmlGuiWindow )
00236 return;
00237 QMenu *popup = static_cast<QMenu*>( d->xmlGuiWindow->guiFactory()->container(
00238 QLatin1String("akonadi_collectionview_contextmenu"), d->xmlGuiWindow ) );
00239 if ( popup )
00240 popup->exec( event->globalPos() );
00241 }
00242
00243 void CollectionView::setXmlGuiWindow(KXmlGuiWindow * xmlGuiWindow)
00244 {
00245 d->xmlGuiWindow = xmlGuiWindow;
00246 }
00247
00248 #include "collectionview.moc"