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;
Represents a collection of PIM items.
An Attribute that stores the special collection type of a collection.
Id id() const
Returns the unique identifier of the entity.
Rights rights() const
Returns the rights the user has on the collection.
FreeBusyManager::Singleton.
bool hasAttribute(const QByteArray &name) const
Returns true if the entity has an attribute of the given type name, false otherwise.
QStringList contentMimeTypes() const
Returns a list of possible content mimetypes, e.g.
bool isValid() const
Returns whether the entity is valid.
bool isVirtual() const
Returns whether the collection is virtual, for example a search collection.