20 #include "dragdropmanager_p.h" 21 #include "specialcollectionattribute_p.h" 22 #include "collectionutils_p.h" 24 #include <QApplication> 30 #include <KDE/KLocalizedString> 33 #include "akonadi/collection.h" 34 #include "akonadi/entitytreemodel.h" 38 DragDropManager::DragDropManager(QAbstractItemView *view)
39 : mShowDropActionMenu(true)
40 , mIsManualSortingActive(false)
47 const QModelIndex index = m_view->indexAt(event->pos());
48 Collection collection = m_view->model()->data(index, EntityTreeModel::CollectionRole).value<
Collection>();
50 const Item item = m_view->model()->data(index, EntityTreeModel::ItemRole).value<Item>();
52 collection = m_view->model()->data(index.parent(), EntityTreeModel::CollectionRole).value<Collection>();
59 bool DragDropManager::dropAllowed(QDragMoveEvent *event)
const 62 const Collection targetCollection = currentDropTarget(event);
63 if (targetCollection.
isValid()) {
64 const QStringList supportedContentTypes = targetCollection.
contentMimeTypes();
66 const QMimeData *data =
event->mimeData();
67 const KUrl::List urls = KUrl::List::fromMimeData(data);
68 foreach (
const KUrl &url, urls) {
69 const Collection collection = Collection::fromUrl(url);
71 if (!supportedContentTypes.contains(Collection::mimeType()) &&
72 !supportedContentTypes.contains(Collection::virtualMimeType())) {
77 if (hasAncestor(m_view->indexAt(event->pos()), collection.
id())) {
81 const QString type = url.queryItems()[QString::fromLatin1(
"type")];
82 if (!supportedContentTypes.contains(type)) {
94 bool DragDropManager::hasAncestor(
const QModelIndex &_index, Collection::Id parentId)
const 96 QModelIndex index(_index);
97 while (index.isValid()) {
98 if (m_view->model()->data(index, EntityTreeModel::CollectionIdRole).toLongLong() == parentId) {
102 index = index.parent();
108 bool DragDropManager::processDropEvent(QDropEvent *event,
bool &menuCanceled,
bool dropOnItem)
110 const Collection targetCollection = currentDropTarget(event);
111 if (!targetCollection.
isValid()) {
115 if (!mIsManualSortingActive && !dropOnItem) {
119 const QStringList supportedContentTypes = targetCollection.
contentMimeTypes();
121 const QMimeData *data =
event->mimeData();
122 const KUrl::List urls = KUrl::List::fromMimeData(data);
123 foreach (
const KUrl &url, urls) {
124 const Collection collection = Collection::fromUrl(url);
133 Qt::DropAction defaultAction;
136 bool moveAllowed, copyAllowed, linkAllowed;
137 moveAllowed = copyAllowed = linkAllowed =
false;
139 if ((targetCollection.
rights() & (Collection::CanCreateCollection | Collection::CanCreateItem)) &&
140 (
event->possibleActions() & Qt::MoveAction)) {
143 if ((targetCollection.
rights() & (Collection::CanCreateCollection | Collection::CanCreateItem)) &&
144 (
event->possibleActions() & Qt::CopyAction)) {
148 if ((targetCollection.
rights() & Collection::CanLinkItem) &&
149 (event->possibleActions() & Qt::LinkAction)) {
153 if (mIsManualSortingActive && !dropOnItem) {
159 if (!moveAllowed && !copyAllowed && !linkAllowed) {
160 kDebug() <<
"Cannot drop here:" <<
event->possibleActions() << m_view->model()->supportedDragActions() << m_view->model()->supportedDropActions();
165 if ((QApplication::keyboardModifiers() & Qt::ControlModifier) &&
166 (QApplication::keyboardModifiers() & Qt::ShiftModifier)) {
168 defaultAction = Qt::LinkAction;
173 }
else if ((QApplication::keyboardModifiers() & Qt::ControlModifier)) {
175 defaultAction = Qt::CopyAction;
180 }
else if ((QApplication::keyboardModifiers() & Qt::ShiftModifier)) {
182 defaultAction = Qt::MoveAction;
189 if (actionCount == 1) {
190 kDebug() <<
"Selecting drop action" << defaultAction <<
", there are no other possibilities";
191 event->setDropAction(defaultAction);
195 if (!mShowDropActionMenu) {
197 defaultAction = Qt::MoveAction;
198 }
else if (copyAllowed) {
199 defaultAction = Qt::CopyAction;
200 }
else if (linkAllowed) {
201 defaultAction = Qt::LinkAction;
205 event->setDropAction(defaultAction);
211 QAction *moveDropAction = 0;
212 QAction *copyDropAction = 0;
213 QAction *linkAction = 0;
217 sequence = QKeySequence(Qt::ShiftModifier).toString();
219 moveDropAction = popup.addAction(KIcon(QString::fromLatin1(
"go-jump")), i18n(
"&Move Here") + QLatin1Char(
'\t') + sequence);
223 sequence = QKeySequence(Qt::ControlModifier).toString();
225 copyDropAction = popup.addAction(KIcon(QString::fromLatin1(
"edit-copy")), i18n(
"&Copy Here") + QLatin1Char(
'\t') + sequence);
229 sequence = QKeySequence(Qt::ControlModifier + Qt::ShiftModifier).toString();
231 linkAction = popup.addAction(KIcon(QLatin1String(
"edit-link")), i18n(
"&Link Here") + QLatin1Char(
'\t') + sequence);
234 popup.addSeparator();
235 popup.addAction(KIcon(QString::fromLatin1(
"process-stop")), i18n(
"C&ancel") + QLatin1Char(
'\t') + QKeySequence(Qt::Key_Escape).toString());
237 QAction *activatedAction = popup.exec(QCursor::pos());
238 if (!activatedAction) {
241 }
else if (activatedAction == moveDropAction) {
242 event->setDropAction(Qt::MoveAction);
243 }
else if (activatedAction == copyDropAction) {
244 event->setDropAction(Qt::CopyAction);
245 }
else if (activatedAction == linkAction) {
246 event->setDropAction(Qt::LinkAction);
254 void DragDropManager::startDrag(Qt::DropActions supportedActions)
256 QModelIndexList indexes;
257 bool sourceDeletable =
true;
258 foreach (
const QModelIndex &index, m_view->selectionModel()->selectedRows()) {
259 if (!m_view->model()->flags(index).testFlag(Qt::ItemIsDragEnabled)) {
263 if (sourceDeletable) {
267 source = index.data(EntityTreeModel::ParentCollectionRole).value<
Collection>();
268 sourceDeletable = source.
rights() & Collection::CanDeleteItem;
274 indexes.append(index);
277 if (indexes.isEmpty()) {
281 QMimeData *mimeData = m_view->model()->mimeData(indexes);
286 QDrag *drag =
new QDrag(m_view);
287 drag->setMimeData(mimeData);
288 if (indexes.size() > 1) {
289 drag->setPixmap(KIcon(QLatin1String(
"document-multiple")).pixmap(QSize(22, 22)));
291 QPixmap pixmap = indexes.first().data(Qt::DecorationRole).value<QIcon>().pixmap(QSize(22, 22));
292 if (pixmap.isNull()) {
293 pixmap = KIcon(QLatin1String(
"text-plain")).pixmap(QSize(22, 22));
295 drag->setPixmap(pixmap);
298 if (!sourceDeletable) {
299 supportedActions &= ~Qt::MoveAction;
302 Qt::DropAction defaultAction = Qt::IgnoreAction;
303 if ((QApplication::keyboardModifiers() & Qt::ControlModifier) &&
304 (QApplication::keyboardModifiers() & Qt::ShiftModifier)) {
305 defaultAction = Qt::LinkAction;
306 }
else if ((QApplication::keyboardModifiers() & Qt::ControlModifier)) {
307 defaultAction = Qt::CopyAction;
308 }
else if ((QApplication::keyboardModifiers() & Qt::ShiftModifier)) {
309 defaultAction = Qt::MoveAction;
312 drag->exec(supportedActions, defaultAction);
315 bool DragDropManager::showDropActionMenu()
const 317 return mShowDropActionMenu;
320 void DragDropManager::setShowDropActionMenu(
bool show)
322 mShowDropActionMenu = show;
325 bool DragDropManager::isManualSortingActive()
const 327 return mIsManualSortingActive;
330 void DragDropManager::setManualSortingActive(
bool active)
332 mIsManualSortingActive = active;
Rights rights() const
Returns the rights the user has on the collection.
Represents a collection of PIM items.
An Attribute that stores the special collection type of a collection.
bool hasAttribute(const QByteArray &name) const
Returns true if the entity has an attribute of the given type name, false otherwise.
Id id() const
Returns the unique identifier of the entity.
bool isVirtual() const
Returns whether the collection is virtual, for example a search collection.
FreeBusyManager::Singleton.
QStringList contentMimeTypes() const
Returns a list of possible content mimetypes, e.g.
bool isValid() const
Returns whether the entity is valid.