20 #include "dragdropmanager_p.h"
21 #include "specialcollectionattribute_p.h"
22 #include "collectionutils_p.h"
24 #include <QApplication>
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>();
56 bool DragDropManager::dropAllowed( QDragMoveEvent *event )
const
59 const Collection targetCollection = currentDropTarget( event );
60 if ( targetCollection.
isValid() ) {
61 const QStringList supportedContentTypes = targetCollection.
contentMimeTypes();
63 const QMimeData *data =
event->mimeData();
64 const KUrl::List urls = KUrl::List::fromMimeData( data );
65 foreach (
const KUrl &url, urls ) {
66 const Collection collection = Collection::fromUrl( url );
68 if ( !supportedContentTypes.contains( Collection::mimeType() ) ) {
73 if ( hasAncestor( m_view->indexAt( event->pos() ), collection.
id() ) ) {
77 const QString type = url.queryItems()[ QString::fromLatin1(
"type" ) ];
78 if ( !supportedContentTypes.contains( type ) ) {
90 bool DragDropManager::hasAncestor(
const QModelIndex &_index, Collection::Id parentId )
const
92 QModelIndex index( _index );
93 while ( index.isValid() ) {
94 if ( m_view->model()->data( index, EntityTreeModel::CollectionIdRole ).toLongLong() == parentId ) {
98 index = index.parent();
104 bool DragDropManager::processDropEvent( QDropEvent *event,
bool &menuCanceled,
bool dropOnItem )
106 const Collection targetCollection = currentDropTarget( event );
107 if ( !targetCollection.
isValid() ) {
111 if ( !mIsManualSortingActive && !dropOnItem ) {
115 const QStringList supportedContentTypes = targetCollection.
contentMimeTypes();
117 const QMimeData *data =
event->mimeData();
118 const KUrl::List urls = KUrl::List::fromMimeData( data );
119 foreach (
const KUrl &url, urls ) {
120 const Collection collection = Collection::fromUrl( url );
129 Qt::DropAction defaultAction;
132 bool moveAllowed, copyAllowed, linkAllowed;
133 moveAllowed = copyAllowed = linkAllowed =
false;
135 if ( ( targetCollection.
rights() & ( Collection::CanCreateCollection | Collection::CanCreateItem ) ) &&
136 (
event->possibleActions() & Qt::MoveAction ) ) {
139 if ( ( targetCollection.
rights() & ( Collection::CanCreateCollection | Collection::CanCreateItem ) ) &&
140 (
event->possibleActions() & Qt::CopyAction ) ) {
144 if ( ( targetCollection.
rights() & Collection::CanLinkItem ) && ( event->possibleActions() & Qt::LinkAction ) ) {
148 if ( mIsManualSortingActive && !dropOnItem ) {
154 if ( !moveAllowed && !copyAllowed && !linkAllowed ) {
155 kDebug() <<
"Cannot drop here:" <<
event->possibleActions() << m_view->model()->supportedDragActions() << m_view->model()->supportedDropActions();
160 if ( ( QApplication::keyboardModifiers() & Qt::ControlModifier ) &&
161 ( QApplication::keyboardModifiers() & Qt::ShiftModifier ) ) {
163 defaultAction = Qt::LinkAction;
168 }
else if ( ( QApplication::keyboardModifiers() & Qt::ControlModifier ) ) {
170 defaultAction = Qt::CopyAction;
175 }
else if ( ( QApplication::keyboardModifiers() & Qt::ShiftModifier ) ) {
177 defaultAction = Qt::MoveAction;
184 if ( actionCount == 1 ) {
185 kDebug() <<
"Selecting drop action" << defaultAction <<
", there are no other possibilities";
186 event->setDropAction( defaultAction );
190 if ( !mShowDropActionMenu ) {
192 defaultAction = Qt::MoveAction;
193 }
else if ( copyAllowed ) {
194 defaultAction = Qt::CopyAction;
195 }
else if ( linkAllowed ) {
196 defaultAction = Qt::LinkAction;
200 event->setDropAction( defaultAction );
205 QMenu popup( m_view );
206 QAction* moveDropAction = 0;
207 QAction* copyDropAction = 0;
208 QAction* linkAction = 0;
212 sequence = QKeySequence( Qt::ShiftModifier ).toString();
214 moveDropAction = popup.addAction( KIcon( QString::fromLatin1(
"go-jump" ) ), i18n(
"&Move Here" ) + QLatin1Char(
'\t' ) + sequence );
218 sequence = QKeySequence( Qt::ControlModifier ).toString();
220 copyDropAction = popup.addAction( KIcon( QString::fromLatin1(
"edit-copy" ) ), i18n(
"&Copy Here" ) + QLatin1Char(
'\t' ) + sequence );
224 sequence = QKeySequence( Qt::ControlModifier + Qt::ShiftModifier ).toString();
226 linkAction = popup.addAction( KIcon( QLatin1String(
"edit-link" ) ), i18n(
"&Link Here" ) + QLatin1Char(
'\t' ) + sequence );
229 popup.addSeparator();
230 popup.addAction( KIcon( QString::fromLatin1(
"process-stop" ) ), i18n(
"C&ancel" ) + QLatin1Char(
'\t' ) + QKeySequence( Qt::Key_Escape ).toString() );
232 QAction *activatedAction = popup.exec( QCursor::pos() );
233 if ( !activatedAction ) {
236 }
else if ( activatedAction == moveDropAction ) {
237 event->setDropAction( Qt::MoveAction );
238 }
else if ( activatedAction == copyDropAction ) {
239 event->setDropAction( Qt::CopyAction );
240 }
else if ( activatedAction == linkAction ) {
241 event->setDropAction( Qt::LinkAction );
249 void DragDropManager::startDrag( Qt::DropActions supportedActions )
251 QModelIndexList indexes;
252 bool sourceDeletable =
true;
253 foreach (
const QModelIndex &index, m_view->selectionModel()->selectedRows() ) {
254 if ( !m_view->model()->flags( index ).testFlag( Qt::ItemIsDragEnabled ) ) {
258 if ( sourceDeletable ) {
262 source = index.data( EntityTreeModel::ParentCollectionRole ).value<
Collection>();
263 sourceDeletable = source.
rights() & Collection::CanDeleteItem;
269 indexes.append( index );
272 if ( indexes.isEmpty() ) {
276 QMimeData *mimeData = m_view->model()->mimeData( indexes );
281 QDrag *drag =
new QDrag( m_view );
282 drag->setMimeData( mimeData );
283 if ( indexes.size() > 1 ) {
284 drag->setPixmap( KIcon( QLatin1String(
"document-multiple" ) ).pixmap( QSize( 22, 22 ) ) );
286 QPixmap pixmap = indexes.first().data( Qt::DecorationRole ).value<QIcon>().pixmap( QSize( 22, 22 ) );
287 if ( pixmap.isNull() ) {
288 pixmap = KIcon( QLatin1String(
"text-plain" ) ).pixmap( QSize( 22, 22 ) );
290 drag->setPixmap( pixmap );
293 if ( !sourceDeletable ) {
294 supportedActions &= ~Qt::MoveAction;
297 Qt::DropAction defaultAction = Qt::IgnoreAction;
298 if ( ( QApplication::keyboardModifiers() & Qt::ControlModifier ) &&
299 ( QApplication::keyboardModifiers() & Qt::ShiftModifier ) ) {
300 defaultAction = Qt::LinkAction;
301 }
else if ( ( QApplication::keyboardModifiers() & Qt::ControlModifier ) ) {
302 defaultAction = Qt::CopyAction;
303 }
else if ( ( QApplication::keyboardModifiers() & Qt::ShiftModifier ) ) {
304 defaultAction = Qt::MoveAction;
307 drag->exec( supportedActions, defaultAction );
310 bool DragDropManager::showDropActionMenu()
const
312 return mShowDropActionMenu;
315 void DragDropManager::setShowDropActionMenu(
bool show )
317 mShowDropActionMenu = show;
320 bool DragDropManager::isManualSortingActive()
const
322 return mIsManualSortingActive;
325 void DragDropManager::setManualSortingActive(
bool active)
327 mIsManualSortingActive = active;