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