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 xmlGuiClient( 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 KXMLGUIClient *xmlGuiClient;
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 collection = index.model()->data( index, CollectionModel::CollectionRole ).value<Collection>();
00114 if ( !collection.isValid() )
00115 return;
00116
00117 emit mParent->clicked( collection );
00118 }
00119
00120 void CollectionView::Private::itemCurrentChanged( const QModelIndex &index )
00121 {
00122 if ( !index.isValid() )
00123 return;
00124
00125 const Collection collection = index.model()->data( index, CollectionModel::CollectionRole ).value<Collection>();
00126 if ( !collection.isValid() )
00127 return;
00128
00129 emit mParent->currentChanged( collection );
00130 }
00131
00132 CollectionView::CollectionView( QWidget * parent )
00133 : QTreeView( parent ),
00134 d( new Private( this ) )
00135 {
00136 d->init();
00137 }
00138
00139 CollectionView::CollectionView( KXMLGUIClient *xmlGuiClient, QWidget * parent )
00140 : QTreeView( parent ),
00141 d( new Private( this ) )
00142 {
00143 d->xmlGuiClient = xmlGuiClient;
00144 d->init();
00145 }
00146
00147 CollectionView::CollectionView( KXmlGuiWindow *xmlGuiWindow, QWidget * parent )
00148 : QTreeView( parent ),
00149 d( new Private( this ) )
00150 {
00151 d->xmlGuiClient = static_cast<KXMLGUIClient*>( xmlGuiWindow );
00152 d->init();
00153 }
00154
00155 CollectionView::~CollectionView()
00156 {
00157 delete d;
00158 }
00159
00160 void CollectionView::setModel( QAbstractItemModel * model )
00161 {
00162 QTreeView::setModel( model );
00163 header()->setStretchLastSection( true );
00164
00165 connect( selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
00166 this, SLOT( itemCurrentChanged( const QModelIndex& ) ) );
00167 }
00168
00169 void CollectionView::dragMoveEvent( QDragMoveEvent * event )
00170 {
00171 QModelIndex index = indexAt( event->pos() );
00172 if ( d->dragOverIndex != index ) {
00173 d->dragExpandTimer.stop();
00174 if ( index.isValid() && !isExpanded( index ) && itemsExpandable() ) {
00175 d->dragExpandTimer.start( QApplication::startDragTime() );
00176 d->dragOverIndex = index;
00177 }
00178 }
00179
00180
00181 const QStringList supportedContentTypes = model()->data( index, CollectionModel::CollectionRole ).value<Collection>().contentMimeTypes();
00182 const QMimeData *data = event->mimeData();
00183 const KUrl::List urls = KUrl::List::fromMimeData( data );
00184 foreach( const KUrl &url, urls ) {
00185
00186 const Collection collection = Collection::fromUrl( url );
00187 if ( collection.isValid() ) {
00188 if ( !supportedContentTypes.contains( QString::fromLatin1( "inode/directory" ) ) )
00189 break;
00190
00191
00192 if ( d->hasParent( index, collection.id() ) )
00193 break;
00194 } else {
00195 const QString type = url.queryItems()[ QString::fromLatin1( "type" ) ];
00196 if ( !supportedContentTypes.contains( type ) )
00197 break;
00198 }
00199
00200 QTreeView::dragMoveEvent( event );
00201 return;
00202 }
00203
00204 event->setDropAction( Qt::IgnoreAction );
00205 }
00206
00207 void CollectionView::dragLeaveEvent( QDragLeaveEvent * event )
00208 {
00209 d->dragExpandTimer.stop();
00210 d->dragOverIndex = QModelIndex();
00211 QTreeView::dragLeaveEvent( event );
00212 }
00213
00214 void CollectionView::dropEvent( QDropEvent * event )
00215 {
00216 d->dragExpandTimer.stop();
00217 d->dragOverIndex = QModelIndex();
00218
00219
00220
00221 QMenu popup( this );
00222 QAction* moveDropAction = popup.addAction( KIcon( QString::fromLatin1( "edit-rename" ) ), i18n( "&Move here" ) );
00223 QAction* copyDropAction = popup.addAction( KIcon( QString::fromLatin1( "edit-copy" ) ), i18n( "&Copy here" ) );
00224 popup.addSeparator();
00225 popup.addAction( KIcon( QString::fromLatin1( "process-stop" ) ), i18n( "Cancel" ) );
00226
00227 QAction *activatedAction = popup.exec( QCursor::pos() );
00228 if ( activatedAction == moveDropAction ) {
00229 event->setDropAction( Qt::MoveAction );
00230 } else if ( activatedAction == copyDropAction ) {
00231 event->setDropAction( Qt::CopyAction );
00232 } else {
00233 return;
00234 }
00235
00236 QTreeView::dropEvent( event );
00237 }
00238
00239 void CollectionView::contextMenuEvent( QContextMenuEvent * event )
00240 {
00241 if ( !d->xmlGuiClient )
00242 return;
00243 QMenu *popup = static_cast<QMenu*>( d->xmlGuiClient->factory()->container(
00244 QLatin1String( "akonadi_collectionview_contextmenu" ), d->xmlGuiClient ) );
00245 if ( popup )
00246 popup->exec( event->globalPos() );
00247 }
00248
00249 void CollectionView::setXmlGuiClient( KXMLGUIClient * xmlGuiClient )
00250 {
00251 d->xmlGuiClient = xmlGuiClient;
00252 }
00253
00254 void CollectionView::setXmlGuiWindow( KXmlGuiWindow * xmlGuiWindow )
00255 {
00256 d->xmlGuiClient = static_cast<KXMLGUIClient*>( xmlGuiWindow );
00257 }
00258
00259 #include "collectionview.moc"