20 #include "dragdropmanager_p.h"
21 #include "specialcollectionattribute_p.h"
22 #include "collectionutils_p.h"
24 #include <QtGui/QApplication>
25 #include <QtGui/QDropEvent>
26 #include <QtGui/QMenu>
29 #include <KDE/KLocale>
32 #include "akonadi/collection.h"
33 #include "akonadi/entitytreemodel.h"
35 using namespace Akonadi;
37 DragDropManager::DragDropManager( QAbstractItemView *view )
38 : mShowDropActionMenu( true ), mIsManualSortingActive( false ), m_view( view )
44 const QModelIndex index = m_view->indexAt( event->pos() );
45 Collection collection = m_view->model()->data( index, EntityTreeModel::CollectionRole ).value<
Collection>();
47 const Item item = m_view->model()->data( index, EntityTreeModel::ItemRole ).value<
Item>();
49 collection = m_view->model()->data( index.parent(), EntityTreeModel::CollectionRole ).value<Collection>();
55 bool DragDropManager::dropAllowed( QDragMoveEvent *event )
const
58 const Collection targetCollection = currentDropTarget( event );
59 if ( targetCollection.
isValid() ) {
60 const QStringList supportedContentTypes = targetCollection.
contentMimeTypes();
62 const QMimeData *data =
event->mimeData();
63 const KUrl::List urls = KUrl::List::fromMimeData( data );
64 foreach (
const KUrl &url, urls ) {
65 const Collection collection = Collection::fromUrl( url );
67 if ( !supportedContentTypes.contains( Collection::mimeType() ) )
71 if ( hasAncestor( m_view->indexAt( event->pos() ), collection.
id() ) )
74 const QString type = url.queryItems()[ QString::fromLatin1(
"type" ) ];
75 if ( !supportedContentTypes.contains( type ) )
86 bool DragDropManager::hasAncestor(
const QModelIndex &_index, Collection::Id parentId )
const
88 QModelIndex index( _index );
89 while ( index.isValid() ) {
90 if ( m_view->model()->data( index, EntityTreeModel::CollectionIdRole ).toLongLong() == parentId )
93 index = index.parent();
99 bool DragDropManager::processDropEvent( QDropEvent *event,
bool &menuCanceled,
bool dropOnItem )
101 const Collection targetCollection = currentDropTarget( event );
102 if ( !targetCollection.
isValid() )
105 if ( !mIsManualSortingActive && !dropOnItem )
110 const QStringList supportedContentTypes = targetCollection.
contentMimeTypes();
112 const QMimeData *data =
event->mimeData();
113 const KUrl::List urls = KUrl::List::fromMimeData( data );
114 foreach (
const KUrl &url, urls ) {
115 const Collection collection = Collection::fromUrl( url );
124 Qt::DropAction defaultAction;
127 bool moveAllowed, copyAllowed, linkAllowed;
128 moveAllowed = copyAllowed = linkAllowed =
false;
130 if ( (targetCollection.
rights() & (Collection::CanCreateCollection | Collection::CanCreateItem))
131 && (
event->possibleActions() & Qt::MoveAction) ) {
134 if ( (targetCollection.
rights() & (Collection::CanCreateCollection | Collection::CanCreateItem))
135 && (
event->possibleActions() & Qt::CopyAction) ) {
139 if ( (targetCollection.
rights() & Collection::CanLinkItem) && (event->possibleActions() & Qt::LinkAction) ) {
143 if ( mIsManualSortingActive && !dropOnItem ) {
149 if ( !moveAllowed && !copyAllowed && !linkAllowed ) {
150 kDebug() <<
"Cannot drop here:" <<
event->possibleActions() << m_view->model()->supportedDragActions() << m_view->model()->supportedDropActions();
155 if ( (QApplication::keyboardModifiers() & Qt::ControlModifier) &&
156 (QApplication::keyboardModifiers() & Qt::ShiftModifier) ) {
158 defaultAction = Qt::LinkAction;
162 }
else if ( (QApplication::keyboardModifiers() & Qt::ControlModifier) ) {
164 defaultAction = Qt::CopyAction;
168 }
else if ( (QApplication::keyboardModifiers() & Qt::ShiftModifier) ) {
170 defaultAction = Qt::MoveAction;
176 if ( actionCount == 1 ) {
177 kDebug() <<
"Selecting drop action" << defaultAction <<
", there are no other possibilities";
178 event->setDropAction( defaultAction );
182 if ( !mShowDropActionMenu ) {
184 defaultAction = Qt::MoveAction;
185 else if ( copyAllowed )
186 defaultAction = Qt::CopyAction;
187 else if ( linkAllowed )
188 defaultAction = Qt::LinkAction;
191 event->setDropAction( defaultAction );
196 QMenu popup( m_view );
197 QAction* moveDropAction = 0;
198 QAction* copyDropAction = 0;
199 QAction* linkAction = 0;
203 sequence = QKeySequence( Qt::ShiftModifier ).toString();
205 moveDropAction = popup.addAction( KIcon( QString::fromLatin1(
"go-jump" ) ), i18n(
"&Move Here" ) + QLatin1Char(
'\t' ) + sequence );
209 sequence = QKeySequence( Qt::ControlModifier ).toString();
211 copyDropAction = popup.addAction( KIcon( QString::fromLatin1(
"edit-copy" ) ), i18n(
"&Copy Here" ) + QLatin1Char(
'\t' ) + sequence );
215 sequence = QKeySequence( Qt::ControlModifier + Qt::ShiftModifier ).toString();
217 linkAction = popup.addAction( KIcon( QLatin1String(
"edit-link" ) ), i18n(
"&Link Here" ) + QLatin1Char(
'\t' ) + sequence );
220 popup.addSeparator();
221 popup.addAction( KIcon( QString::fromLatin1(
"process-stop" ) ), i18n(
"C&ancel" ) + QLatin1Char(
'\t' ) + QKeySequence( Qt::Key_Escape ).toString() );
223 QAction *activatedAction = popup.exec( QCursor::pos() );
224 if ( !activatedAction ) {
227 }
else if ( activatedAction == moveDropAction ) {
228 event->setDropAction( Qt::MoveAction );
229 }
else if ( activatedAction == copyDropAction ) {
230 event->setDropAction( Qt::CopyAction );
231 }
else if ( activatedAction == linkAction ) {
232 event->setDropAction( Qt::LinkAction );
240 void DragDropManager::startDrag( Qt::DropActions supportedActions )
242 QModelIndexList indexes;
243 bool sourceDeletable =
true;
244 foreach (
const QModelIndex &index, m_view->selectionModel()->selectedRows() ) {
245 if ( !m_view->model()->flags( index ).testFlag( Qt::ItemIsDragEnabled ) )
248 if ( sourceDeletable ) {
252 source = index.data( EntityTreeModel::ParentCollectionRole ).value<
Collection>();
253 sourceDeletable = source.
rights() & Collection::CanDeleteItem;
259 indexes.append( index );
262 if ( indexes.isEmpty() )
265 QMimeData *mimeData = m_view->model()->mimeData( indexes );
269 QDrag *drag =
new QDrag( m_view );
270 drag->setMimeData( mimeData );
271 if ( indexes.size() > 1 ) {
272 drag->setPixmap( KIcon( QLatin1String(
"document-multiple" ) ).pixmap( QSize( 22, 22 ) ) );
274 QPixmap pixmap = indexes.first().data( Qt::DecorationRole ).value<QIcon>().pixmap( QSize( 22, 22 ) );
275 if ( pixmap.isNull() )
276 pixmap = KIcon( QLatin1String(
"text-plain" ) ).pixmap( QSize( 22, 22 ) );
277 drag->setPixmap( pixmap );
280 if ( !sourceDeletable )
281 supportedActions &= ~Qt::MoveAction;
283 Qt::DropAction defaultAction = Qt::IgnoreAction;
284 if ( (QApplication::keyboardModifiers() & Qt::ControlModifier) &&
285 (QApplication::keyboardModifiers() & Qt::ShiftModifier) ) {
286 defaultAction = Qt::LinkAction;
287 }
else if ( (QApplication::keyboardModifiers() & Qt::ControlModifier) ) {
288 defaultAction = Qt::CopyAction;
289 }
else if ( (QApplication::keyboardModifiers() & Qt::ShiftModifier) ) {
290 defaultAction = Qt::MoveAction;
293 drag->exec( supportedActions, defaultAction );
296 bool DragDropManager::showDropActionMenu()
const
298 return mShowDropActionMenu;
301 void DragDropManager::setShowDropActionMenu(
bool show )
303 mShowDropActionMenu = show;
306 bool DragDropManager::isManualSortingActive()
const
308 return mIsManualSortingActive;
311 void DragDropManager::setManualSortingActive(
bool active)
313 mIsManualSortingActive = active;