akonadi
collectionview.cpp
00001 /* 00002 Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org> 00003 00004 This library is free software; you can redistribute it and/or modify it 00005 under the terms of the GNU Library General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or (at your 00007 option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, but WITHOUT 00010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00011 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00012 License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to the 00016 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00017 02110-1301, USA. 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(QModelIndex)), 00085 mParent, SLOT(itemClicked(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(QModelIndex,QModelIndex)), 00166 this, SLOT(itemCurrentChanged(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 // Check if the collection under the cursor accepts this data type 00181 const QStringList supportedContentTypes = model()->data( index, CollectionModel::CollectionRole ).value<Collection>().contentMimeTypes(); 00182 const QMimeData *mimeData = event->mimeData(); 00183 const KUrl::List urls = KUrl::List::fromMimeData( mimeData ); 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 // Check if we don't try to drop on one of the children 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 // open a context menu offering different drop actions (move, copy and cancel) 00220 // TODO If possible, hide non available actions ... 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"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Aug 27 2012 22:09:21 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Aug 27 2012 22:09:21 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.