1 /* SPDX-FileCopyrightText: 2020 Tobias Leupold <tobias.leupold@gmx.de>
2 
3    SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-KDE-Accepted-GPL
4 */
5 
6 // Local includes
7 #include "ImagesListFilter.h"
8 #include "Coordinates.h"
9 #include "ImagesModel.h"
10 #include "MimeHelper.h"
11 
12 // Qt includes
13 #include <QDebug>
14 #include <QMimeData>
15 #include <QUrl>
16 
ImagesListFilter(QObject * parent,KGeoTag::ImagesListType type)17 ImagesListFilter::ImagesListFilter(QObject *parent, KGeoTag::ImagesListType type)
18     : QSortFilterProxyModel(parent),
19       m_listType(type)
20 {
21 }
22 
setListType(KGeoTag::ImagesListType type)23 void ImagesListFilter::setListType(KGeoTag::ImagesListType type)
24 {
25     m_listType = type;
26     invalidateFilter();
27 }
28 
setSourceModel(QAbstractItemModel * sourceModel)29 void ImagesListFilter::setSourceModel(QAbstractItemModel *sourceModel)
30 {
31     QSortFilterProxyModel::setSourceModel(sourceModel);
32     m_imagesModel = qobject_cast<ImagesModel *>(sourceModel);
33 }
34 
filterAcceptsRow(int sourceRow,const QModelIndex &) const35 bool ImagesListFilter::filterAcceptsRow(int sourceRow, const QModelIndex &) const
36 {
37     if (m_listType == KGeoTag::AllImages) {
38         return true;
39     }
40 
41     const bool coordinatesSet = sourceModel()->index(sourceRow, 0).data(
42                                     KGeoTag::CoordinatesRole).value<Coordinates>().isSet();
43 
44     return    (m_listType == KGeoTag::AssignedImages   &&   coordinatesSet)
45            || (m_listType == KGeoTag::UnAssignedImages && ! coordinatesSet);
46 }
47 
supportedDropActions() const48 Qt::DropActions ImagesListFilter::supportedDropActions() const
49 {
50     return Qt::CopyAction | Qt::MoveAction;
51 }
52 
flags(const QModelIndex & index) const53 Qt::ItemFlags ImagesListFilter::flags(const QModelIndex &index) const
54 {
55     auto defaultFlags = QSortFilterProxyModel::flags(index);
56 
57     if (index.isValid()) {
58         return defaultFlags;
59     } else {
60         return Qt::ItemIsDropEnabled | defaultFlags;
61     }
62 }
63 
canDropMimeData(const QMimeData * data,Qt::DropAction action,int,int,const QModelIndex &) const64 bool ImagesListFilter::canDropMimeData(const QMimeData *data, Qt::DropAction action, int, int,
65                                        const QModelIndex &) const
66 {
67     if (! (action & (Qt::CopyAction | Qt::MoveAction)) || ! data->hasUrls()) {
68         return false;
69     }
70 
71     // Check if the drag's origin is an image list
72     const auto source = data->data(KGeoTag::SourceImagesListMimeType);
73     if (! source.isEmpty()) {
74         // Don't allow drops on the "assigned" images list
75         if (m_listType == KGeoTag::AssignedImages) {
76             return false;
77         }
78         // Don't allow drops on the origin list
79         if (source == KGeoTag::SourceImagesList.value(m_listType)) {
80             return false;
81         }
82 
83     } else {
84         // The user wants to drop files from an external source
85         if (MimeHelper::getUsablePaths(KGeoTag::DroppedOnImageList, data).isEmpty()) {
86             return false;
87         }
88     }
89 
90     return true;
91 }
92 
dropMimeData(const QMimeData * data,Qt::DropAction action,int,int,const QModelIndex &)93 bool ImagesListFilter::dropMimeData(const QMimeData *data, Qt::DropAction action, int, int,
94                                     const QModelIndex &)
95 {
96     if (! (action & (Qt::CopyAction | Qt::MoveAction)) || ! data->hasUrls()) {
97         return false;
98     }
99 
100     QVector<QString> paths;
101     QVector<QString> removeCoordinates;
102 
103     const auto usablePaths = MimeHelper::getUsablePaths(KGeoTag::DroppedOnImageList, data);
104     for (const auto &path : usablePaths) {
105         if (! m_imagesModel->contains(path)) {
106             paths.append(path);
107         } else {
108             if (m_listType == KGeoTag::UnAssignedImages
109                 && m_imagesModel->coordinates(path).isSet()) {
110 
111                 removeCoordinates.append(path);
112             }
113         }
114     }
115 
116     if (! removeCoordinates.isEmpty()) {
117         emit requestRemoveCoordinates(removeCoordinates);
118     }
119 
120     if (! paths.isEmpty()) {
121         emit requestAddingImages(paths);
122     }
123 
124     return true;
125 }
126