File indexing completed on 2025-01-19 03:59:24
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2012-05-22 0007 * Description : Qt model for camera entries 0008 * 0009 * SPDX-FileCopyrightText: 2012 by Islam Wazery <wazery at ubuntu dot com> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #ifndef DIGIKAM_IMPORT_IMAGE_MODEL_H 0016 #define DIGIKAM_IMPORT_IMAGE_MODEL_H 0017 0018 // Qt includes 0019 0020 #include <QAbstractListModel> 0021 #include <QUrl> 0022 0023 // Local includes 0024 0025 #include "dragdropimplementations.h" 0026 #include "camerathumbsctrl.h" 0027 #include "camiteminfo.h" 0028 0029 namespace Digikam 0030 { 0031 class AbstractItemDragDropHandler; 0032 0033 class ImportItemModel : public QAbstractListModel, public DragDropModelImplementation 0034 { 0035 Q_OBJECT 0036 0037 public: 0038 0039 enum ImportItemModelRoles 0040 { 0041 /** 0042 * An ImportItemModel* pointer to this model 0043 */ 0044 ImportItemModelPointerRole = Qt::UserRole, 0045 ImportItemModelInternalId = Qt::UserRole + 1, 0046 0047 /** 0048 * Returns a thumbnail pixmap. May be implemented by subclasses. 0049 * Returns either a valid pixmap or a null QVariant. 0050 */ 0051 ThumbnailRole = Qt::UserRole + 2, 0052 /** 0053 * Return (optional) extraData field 0054 */ 0055 ExtraDataRole = Qt::UserRole + 3, 0056 0057 /** 0058 * Returns the number of duplicate indexes for the same image id 0059 */ 0060 ExtraDataDuplicateCount = Qt::UserRole + 6, 0061 0062 FilterModelRoles = Qt::UserRole + 100 0063 }; 0064 0065 public: 0066 0067 explicit ImportItemModel(QObject* const parent = nullptr); 0068 ~ImportItemModel() override; 0069 0070 /** 0071 * Used to set the camera controller, and connect with it. 0072 */ 0073 virtual void setCameraThumbsController(CameraThumbsCtrl* const controller); 0074 0075 /** 0076 * If a cache is kept, lookup by file path is fast, 0077 * without a cache it is O(n). Default is false. 0078 */ 0079 void setKeepsFileUrlCache(bool keepCache); 0080 bool keepsFileUrlCache() const; 0081 0082 /** 0083 * Returns the CamItemInfo object, reference from the underlying data pointed to by the index. 0084 * For camItemInfo and camItemInfoId If the index is not valid they will return a null CamItemInfo, and 0 0085 * respectively, camItemInfoRef must not be called with an invalid index as it will crash. 0086 */ 0087 CamItemInfo camItemInfo(const QModelIndex& index) const; 0088 CamItemInfo& camItemInfoRef(const QModelIndex& index) const; 0089 qlonglong camItemId(const QModelIndex& index) const; 0090 CamItemInfoList camItemInfos(const QList<QModelIndex>& indexes) const; 0091 QList<qlonglong> camItemIds(const QList<QModelIndex>& indexes) const; 0092 0093 /** 0094 * Returns the CamItemInfo object, reference from the underlying data of 0095 * the given row (parent is the invalid QModelIndex, column is 0). 0096 * Note that camItemInfoRef must not be called with an invalid index as it will crash. 0097 */ 0098 CamItemInfo camItemInfo(int row) const; 0099 CamItemInfo& camItemInfoRef(int row) const; 0100 qlonglong camItemId(int row) const; 0101 0102 /** 0103 * Return the index of a given CamItemInfo, if it exists in the model. 0104 */ 0105 QModelIndex indexForCamItemInfo(const CamItemInfo& info) const; 0106 QList<QModelIndex> indexesForCamItemInfo(const CamItemInfo& info) const; 0107 QModelIndex indexForCamItemId(qlonglong id) const; 0108 QList<QModelIndex> indexesForCamItemId(qlonglong id) const; 0109 0110 /** 0111 * Returns the index or CamItemInfo object from the underlying data for 0112 * the given file url. In case of multiple occurrences of the same file, the simpler 0113 * overrides returns any one found first, use the QList methods to retrieve all occurrences. 0114 */ 0115 QModelIndex indexForUrl(const QUrl& fileUrl) const; 0116 QList<QModelIndex> indexesForUrl(const QUrl& fileUrl) const; 0117 CamItemInfo camItemInfo(const QUrl& fileUrl) const; 0118 QList<CamItemInfo> camItemInfos(const QUrl& fileUrl) const; 0119 0120 /** 0121 * Clears the CamItemInfos and resets the model. 0122 */ 0123 void clearCamItemInfos(); 0124 0125 /** 0126 * addCamItemInfo() is asynchronous if a prepocessor is set. 0127 * This method first adds the info, synchronously. 0128 * Only afterwards, the preprocessor will have the opportunity to process it. 0129 * This method also bypasses any incremental updates. 0130 */ 0131 void addCamItemInfoSynchronously(const CamItemInfo& info); 0132 void addCamItemInfosSynchronously(const Digikam::CamItemInfoList& infos); 0133 0134 /** 0135 * Clears and adds infos. 0136 */ 0137 void setCamItemInfos(const CamItemInfoList& infos); 0138 0139 QList<CamItemInfo> camItemInfos() const; 0140 QList<qlonglong> camItemIds() const; 0141 QList<CamItemInfo> uniqueCamItemInfos() const; 0142 0143 bool hasImage(qlonglong id) const; 0144 bool hasImage(const CamItemInfo& info) const; 0145 0146 bool isEmpty() const; 0147 0148 /** 0149 * Remove the given infos or indexes directly from the model. 0150 */ 0151 void removeIndex(const QModelIndex& index); 0152 void removeIndexs(const QList<QModelIndex>& indexes); 0153 void removeCamItemInfo(const CamItemInfo& info); 0154 void removeCamItemInfos(const QList<CamItemInfo>& infos); 0155 0156 int numberOfIndexesForCamItemInfo(const CamItemInfo& info) const; 0157 int numberOfIndexesForCamItemId(qlonglong id) const; 0158 0159 /** 0160 * Retrieve the CamItemInfo object from the data() function of the given index 0161 * The index may be from a QSortFilterProxyModel as long as an ImportItemModel is at the end. 0162 */ 0163 static CamItemInfo retrieveCamItemInfo(const QModelIndex& index); 0164 static qlonglong retrieveCamItemId(const QModelIndex& index); 0165 0166 /// QAbstractListModel implementation 0167 int rowCount(const QModelIndex& parent) const override; 0168 QVariant data(const QModelIndex& index, int role) const override; 0169 QVariant headerData(int section, Qt::Orientation orientation, int role) const override; 0170 Qt::ItemFlags flags(const QModelIndex& index) const override; 0171 QModelIndex index(int row, int column, const QModelIndex& parent) const override; 0172 0173 /// DragDrop methods 0174 DECLARE_MODEL_DRAG_DROP_METHODS 0175 0176 /** 0177 * Enable sending of itemInfosAboutToBeRemoved and itemsInfosRemoved signals. 0178 * Default: false 0179 */ 0180 void setSendRemovalSignals(bool send); 0181 0182 /** 0183 * Returns true if this model is currently refreshing. 0184 * For a preprocessor this means that, although the preprocessor may currently have 0185 * processed all it got, more batches are to be expected. 0186 */ 0187 bool isRefreshing() const; 0188 0189 Q_SIGNALS: 0190 0191 /** 0192 * Informs that ItemInfos will be added to the model. 0193 * This signal is sent before the model data is changed and views are informed. 0194 */ 0195 void itemInfosAboutToBeAdded(const QList<CamItemInfo>& infos); 0196 0197 /** 0198 * Informs that ItemInfos have been added to the model. 0199 * This signal is sent after the model data is changed and views are informed. 0200 */ 0201 void itemInfosAdded(const QList<CamItemInfo>& infos); 0202 0203 /** 0204 * Informs that CamItemInfos will be removed from the model. 0205 * This signal is sent before the model data is changed and views are informed. 0206 * Note: You need to explicitly enable sending of this signal. It is not sent 0207 * in clearCamItemInfos(). 0208 */ 0209 void itemInfosAboutToBeRemoved(const QList<CamItemInfo>& infos); 0210 0211 /** 0212 * Informs that CamItemInfos have been removed from the model. 0213 * This signal is sent after the model data is changed and views are informed. 0214 * Note: You need to explicitly enable sending of this signal. It is not sent 0215 * in clearCamItemInfos(). 0216 */ 0217 void itemInfosRemoved(const QList<CamItemInfo>& infos); 0218 0219 /** 0220 * Connect to this signal only if you are the current preprocessor. 0221 */ 0222 void preprocess(const QList<CamItemInfo>& infos); 0223 void processAdded(const QList<CamItemInfo>& infos); 0224 0225 /** 0226 * Signals that the model is right now ready to start an incremental refresh. 0227 * This is guaranteed only for the scope of emitting this signal. 0228 */ 0229 void readyForIncrementalRefresh(); 0230 0231 /** 0232 * Signals that the model has finished currently with all scheduled 0233 * refreshing, full or incremental, and all preprocessing. 0234 * The model is in polished, clean situation right now. 0235 */ 0236 void allRefreshingFinished(); 0237 0238 public Q_SLOTS: 0239 0240 void reAddCamItemInfos(const CamItemInfoList& infos); 0241 void reAddingFinished(); 0242 void slotFileDeleted(const QString& folder, const QString& file, bool status); 0243 void slotFileUploaded(const CamItemInfo& info); 0244 void addCamItemInfo(const CamItemInfo& info); 0245 void addCamItemInfos(const CamItemInfoList& infos); 0246 0247 protected: 0248 0249 /** 0250 * Subclasses that add CamItemInfos in batches shall call startRefresh() 0251 * when they start sending batches and finishRefresh() when they have finished. 0252 * No incremental refreshes will be started while listing. 0253 * A clearCamItemInfos() always stops listing, calling finishRefresh() is then not necessary. 0254 */ 0255 void startRefresh(); 0256 void finishRefresh(); 0257 0258 /** 0259 * As soon as the model is ready to start an incremental refresh, the signal 0260 * readyForIncrementalRefresh() will be emitted. The signal will be emitted inline 0261 * if the model is ready right now. 0262 */ 0263 void requestIncrementalRefresh(); 0264 bool hasIncrementalRefreshPending() const; 0265 0266 /** 0267 * Starts an incremental refresh operation. You shall only call this method from a slot 0268 * connected to readyForIncrementalRefresh(). To initiate an incremental refresh, 0269 * call requestIncrementalRefresh(). 0270 */ 0271 void startIncrementalRefresh(); 0272 void finishIncrementalRefresh(); 0273 0274 void emitDataChangedForAll(); 0275 void emitDataChangedForSelections(const QItemSelection& selection); 0276 0277 /** 0278 * Called when the internal storage is cleared. 0279 */ 0280 virtual void camItemInfosCleared() {}; 0281 0282 /** 0283 * Called before rowsAboutToBeRemoved 0284 */ 0285 virtual void itemInfosAboutToBeRemoved(int /*begin*/, int /*end*/) {}; 0286 0287 private: 0288 0289 void appendInfos(const CamItemInfoList& infos); 0290 void publiciseInfos(const CamItemInfoList& infos); 0291 void cleanSituationChecks(); 0292 void removeRowPairs(const QList<QPair<int, int> >& toRemove); 0293 void removeRowPairsWithCheck(const QList<QPair<int, int> >& toRemove); 0294 0295 public: 0296 0297 // NOTE: Declared public because it's used in ItemModelIncrementalUpdater class 0298 class Private; 0299 0300 private: 0301 0302 // Disable 0303 ImportItemModel(const ImportItemModel&) = delete; 0304 ImportItemModel& operator=(const ImportItemModel&) = delete; 0305 0306 private: 0307 0308 Private* const d; 0309 }; 0310 0311 } // namespace Digikam 0312 0313 Q_DECLARE_METATYPE(Digikam::ImportItemModel*) 0314 0315 #endif // DIGIKAM_IMPORT_IMAGE_MODEL_H