File indexing completed on 2025-01-19 03:50:35

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2012-09-07
0007  * Description : Qt Model for ImportUI - drag and drop handling
0008  *
0009  * SPDX-FileCopyrightText: 2012      by Islam Wazery <wazery at ubuntu dot com>
0010  * SPDX-FileCopyrightText: 2013-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "importdragdrop.h"
0017 
0018 // Qt includes
0019 
0020 #include <QDropEvent>
0021 #include <QIcon>
0022 
0023 // KDE includes
0024 
0025 #include <klocalizedstring.h>
0026 
0027 // Local includes
0028 
0029 #include "digikam_debug.h"
0030 #include "importiconview.h"
0031 #include "importui.h"
0032 #include "ddragobjects.h"
0033 #include "importcategorizedview.h"
0034 #include "camiteminfo.h"
0035 #include "albummanager.h"
0036 #include "digikamapp.h"
0037 #include "itemiconview.h"
0038 
0039 namespace Digikam
0040 {
0041 
0042 ImportDragDropHandler::ImportDragDropHandler(ImportItemModel* const model)
0043     : AbstractItemDragDropHandler(model)
0044 {
0045 }
0046 
0047 QAction* ImportDragDropHandler::addGroupAction(QMenu* const menu)
0048 {
0049     return menu->addAction(QIcon::fromTheme(QLatin1String("go-bottom")),
0050                            i18nc("@action:inmenu Group images with this image", "Group here"));
0051 }
0052 
0053 QAction* ImportDragDropHandler::addCancelAction(QMenu* const menu)
0054 {
0055     return menu->addAction(QIcon::fromTheme(QLatin1String("dialog-cancel")), i18n("C&ancel"));
0056 }
0057 
0058 ImportDragDropHandler::DropAction ImportDragDropHandler::copyOrMove(const QDropEvent* e,
0059                                                                     QWidget* const view,
0060                                                                     bool allowMove,
0061                                                                     bool askForGrouping)
0062 {
0063 
0064 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0065 
0066     if      (e->modifiers() & Qt::ControlModifier)
0067 
0068 #else
0069 
0070     if      (e->keyboardModifiers() & Qt::ControlModifier)
0071 
0072 #endif
0073 
0074     {
0075         return CopyAction;
0076     }
0077 
0078 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0079 
0080     else if (e->modifiers() & Qt::ShiftModifier)
0081 
0082 #else
0083 
0084     else if (e->keyboardModifiers() & Qt::ShiftModifier)
0085 
0086 #endif
0087 
0088     {
0089         return MoveAction;
0090     }
0091 
0092     if (!allowMove && !askForGrouping)
0093     {
0094         switch (e->proposedAction())
0095         {
0096             case Qt::CopyAction:
0097             {
0098                 return CopyAction;
0099             }
0100 
0101             case Qt::MoveAction:
0102             {
0103                 return MoveAction;
0104             }
0105 
0106             default:
0107             {
0108                 return NoAction;
0109             }
0110         }
0111     }
0112 
0113     QMenu popMenu(view);
0114 
0115     QAction* moveAction       = nullptr;
0116 
0117     if (allowMove)
0118     {
0119         moveAction = popMenu.addAction(QIcon::fromTheme(QLatin1String("go-jump")), i18n("&Move Here"));
0120     }
0121 
0122     QAction* const copyAction = popMenu.addAction(QIcon::fromTheme(QLatin1String("edit-copy")), i18n("&Copy Here"));
0123     popMenu.addSeparator();
0124 
0125     QAction* groupAction      = nullptr;
0126 
0127     if (askForGrouping)
0128     {
0129         groupAction = addGroupAction(&popMenu);
0130         popMenu.addSeparator();
0131     }
0132 
0133     addCancelAction(&popMenu);
0134 
0135     popMenu.setMouseTracking(true);
0136     QAction* const choice = popMenu.exec(QCursor::pos());
0137 
0138     if      (moveAction && (choice == moveAction))
0139     {
0140         return MoveAction;
0141     }
0142     else if (choice == copyAction)
0143     {
0144         return CopyAction;
0145     }
0146     else if (groupAction && (choice == groupAction))
0147     {
0148         return GroupAction;
0149     }
0150 
0151     return NoAction;
0152 }
0153 
0154 /*
0155 static DropAction tagAction(const QDropEvent*, QWidget* view, bool askForGrouping)
0156 {
0157 }
0158 
0159 static DropAction groupAction(const QDropEvent*, QWidget* view)
0160 {
0161 }
0162 */
0163 
0164 bool ImportDragDropHandler::dropEvent(QAbstractItemView* abstractview,
0165                                       const QDropEvent* e,
0166                                       const QModelIndex& droppedOn)
0167 {
0168     ImportCategorizedView* const view = static_cast<ImportCategorizedView*>(abstractview);
0169 
0170     if (accepts(e, droppedOn) == Qt::IgnoreAction)
0171     {
0172         return false;
0173     }
0174 
0175     if (DItemDrag::canDecode(e->mimeData()))
0176     {
0177         QList<QUrl> lst         = DigikamApp::instance()->view()->selectedUrls();
0178 
0179         QMenu popMenu(view);
0180         popMenu.addSection(QIcon::fromTheme(QLatin1String("digikam")), i18n("Exporting"));
0181         QAction* const upAction = popMenu.addAction(QIcon::fromTheme(QLatin1String("media-flash-sd-mmc")),
0182                                                     i18n("Upload to Camera"));
0183         popMenu.addSeparator();
0184         popMenu.addAction(QIcon::fromTheme(QLatin1String("dialog-cancel")), i18n("C&ancel"));
0185         popMenu.setMouseTracking(true);
0186 
0187 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0188 
0189         QAction* const choice   = popMenu.exec(view->mapToGlobal(e->position().toPoint()));
0190 
0191 #else
0192 
0193         QAction* const choice   = popMenu.exec(view->mapToGlobal(e->pos()));
0194 
0195 #endif
0196 
0197         if (choice)
0198         {
0199             if (choice == upAction)
0200             {
0201                 ImportUI::instance()->slotUploadItems(lst);
0202             }
0203         }
0204 
0205         return true;
0206     }
0207 /*
0208     TODO: Implement tag dropping in import tool.
0209     else if (DTagListDrag::canDecode(e->mimeData()))
0210     {
0211     }
0212 */
0213     return false;
0214 }
0215 
0216 Qt::DropAction ImportDragDropHandler::accepts(const QDropEvent* e, const QModelIndex& /*dropIndex*/)
0217 {
0218     if (DItemDrag::canDecode(e->mimeData()) || e->mimeData()->hasUrls())
0219     {
0220 
0221 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0222 
0223         if      (e->modifiers() & Qt::ControlModifier)
0224 
0225 #else
0226 
0227         if      (e->keyboardModifiers() & Qt::ControlModifier)
0228 
0229 #endif
0230 
0231         {
0232             return Qt::CopyAction;
0233         }
0234 
0235 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0236 
0237         else if (e->modifiers() & Qt::ShiftModifier)
0238 
0239 #else
0240 
0241         else if (e->keyboardModifiers() & Qt::ShiftModifier)
0242 
0243 #endif
0244         {
0245             return Qt::MoveAction;
0246         }
0247 
0248         return Qt::MoveAction;
0249     }
0250 
0251     if (DTagListDrag::canDecode(e->mimeData())        ||
0252         DCameraItemListDrag::canDecode(e->mimeData()) ||
0253         DCameraDragObject::canDecode(e->mimeData()))
0254     {
0255         return Qt::MoveAction;
0256     }
0257 
0258     return Qt::IgnoreAction;
0259 }
0260 
0261 QStringList ImportDragDropHandler::mimeTypes() const
0262 {
0263     QStringList mimeTypes;
0264     mimeTypes << DItemDrag::mimeTypes()
0265               << DTagListDrag::mimeTypes()
0266               << DCameraItemListDrag::mimeTypes()
0267               << DCameraDragObject::mimeTypes()
0268               << QLatin1String("text/uri-list");
0269 
0270     return mimeTypes;
0271 }
0272 
0273 QMimeData* ImportDragDropHandler::createMimeData(const QList<QModelIndex>& indexes)
0274 {
0275     QList<CamItemInfo> infos = model()->camItemInfos(indexes);
0276 
0277     QStringList lst;
0278 
0279     Q_FOREACH (const CamItemInfo& info, infos)
0280     {
0281         lst.append(info.folder + info.name);
0282     }
0283 
0284     if (lst.isEmpty())
0285     {
0286         return nullptr;
0287     }
0288 
0289     return (new DCameraItemListDrag(lst));
0290 }
0291 
0292 ImportItemModel* ImportDragDropHandler::model() const
0293 {
0294     return static_cast<ImportItemModel*>(m_model);
0295 }
0296 
0297 } // namespace Digikam
0298 
0299 #include "moc_importdragdrop.cpp"