File indexing completed on 2025-01-19 03:57:34

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2013-07-05
0007  * Description : Qt model for Showfoto entries
0008  *
0009  * SPDX-FileCopyrightText: 2013 by Mohamed_Anwer <m_dot_anwer at gmx dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #ifndef SHOW_FOTO_ITEM_MODEL_H
0016 #define SHOW_FOTO_ITEM_MODEL_H
0017 
0018 // Qt includes
0019 
0020 #include <QAbstractListModel>
0021 #include <QUrl>
0022 
0023 // Local includes
0024 
0025 #include "dragdropimplementations.h"
0026 #include "abstractitemdragdrophandler.h"
0027 #include "showfotoiteminfo.h"
0028 
0029 using namespace Digikam;
0030 
0031 namespace ShowFoto
0032 {
0033 
0034 typedef QPair<int, int> IntPair;
0035 
0036 class ShowfotoItemModel : public QAbstractListModel,
0037                           public DragDropModelImplementation
0038 {
0039     Q_OBJECT
0040 
0041 public:
0042 
0043     enum ShowfotoItemModelRoles
0044     {
0045         /**
0046          * An ShowfotoItemModel* pointer to this model
0047          */
0048         ShowfotoItemModelPointerRole = Qt::UserRole,
0049         ShowfotoItemModelInternalId  = Qt::UserRole + 1,
0050 
0051         /**
0052          * Returns a thumbnail pixmap. May be implemented by subclasses.
0053          * Returns either a valid pixmap or a null QVariant.
0054          */
0055         ThumbnailRole                = Qt::UserRole + 2,
0056 
0057         /**
0058          * Return (optional) extraData field
0059          */
0060         ExtraDataRole                = Qt::UserRole + 3,
0061 
0062         /**
0063          * Returns the number of duplicate indexes for the same image id
0064          */
0065         ExtraDataDuplicateCount      = Qt::UserRole + 6,
0066 
0067         FilterModelRoles             = Qt::UserRole + 100
0068     };
0069 
0070 public:
0071 
0072      explicit ShowfotoItemModel(QObject* const parent);
0073     ~ShowfotoItemModel()                                                                  override;
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 
0081     /**
0082      * Returns the ShowfotoItemInfo object, reference from the underlying data pointed to by the index.
0083      * For ShowfotoItemInfo and ShowfotoItemInfoId If the index is not valid they will return a null ShowfotoItemInfo, and 0
0084      * respectively, ShowfotoItemInfoRef must not be called with an invalid index as it will crash.
0085      */
0086     ShowfotoItemInfo      showfotoItemInfo(const QModelIndex& index)                const;
0087     ShowfotoItemInfo&     showfotoItemInfoRef(const QModelIndex& index)             const;
0088     qlonglong             showfotoItemId(const QModelIndex& index)                  const;
0089     ShowfotoItemInfoList  showfotoItemInfos(const QList<QModelIndex>& indexes)      const;
0090     QList<qlonglong>      showfotoItemIds(const QList<QModelIndex>& indexes)        const;
0091 
0092     /**
0093      * Returns the ShowfotoItemInfo object, reference from the underlying data of
0094      * the given row (parent is the invalid QModelIndex, column is 0).
0095      * Note that ShowfotoItemInfoRef must not be called with an invalid index as it will crash.
0096      */
0097     ShowfotoItemInfo  showfotoItemInfo(int row)                                     const;
0098     ShowfotoItemInfo& showfotoItemInfoRef(int row)                                  const;
0099     qlonglong         showfotoItemId(int row)                                       const;
0100 
0101     /**
0102      * Return the index of a given ShowfotoItemInfo, if it exists in the model.
0103      */
0104     QModelIndex        indexForShowfotoItemInfo(const ShowfotoItemInfo& info)       const;
0105     QList<QModelIndex> indexesForShowfotoItemInfo(const ShowfotoItemInfo& info)     const;
0106     QModelIndex        indexForShowfotoItemId(qlonglong id)                         const;
0107     QList<QModelIndex> indexesForShowfotoItemId(qlonglong id)                       const;
0108 
0109     /**
0110      * Returns the index or ShowfotoItemInfo object from the underlying data for
0111      * the given file url. In case of multiple occurrences of the same file, the simpler
0112      * overrides returns any one found first, use the QList methods to retrieve all occurrences.
0113      */
0114     QModelIndex             indexForUrl(const QUrl& fileUrl)                        const;
0115     QList<QModelIndex>      indexesForUrl(const QUrl& fileUrl)                      const;
0116     ShowfotoItemInfo        showfotoItemInfo(const QUrl& fileUrl)                   const;
0117     QList<ShowfotoItemInfo> showfotoItemInfos(const QUrl& fileUrl)                  const;
0118 
0119     void addShowfotoItemInfo(const ShowfotoItemInfo& info);
0120     void addShowfotoItemInfos(const QList<ShowfotoItemInfo>& infos);
0121 
0122     /**
0123      * Clears the ShowfotoItemInfos and resets the model.
0124      */
0125     void clearShowfotoItemInfos();
0126 
0127     /**
0128      * addShowfotoItemInfo() is asynchronous if a prepocessor is set.
0129      * This method first adds the info, synchronously.
0130      * Only afterwards, the preprocessor will have the opportunity to process it.
0131      * This method also bypasses any incremental updates.
0132      */
0133     void addShowfotoItemInfoSynchronously(const ShowfotoItemInfo& info);
0134     void addShowfotoItemInfosSynchronously(const QList<ShowfotoItemInfo>& infos);
0135 
0136     /**
0137      * Clears and adds infos.
0138      */
0139     void setShowfotoItemInfos(const QList<ShowfotoItemInfo>& infos);
0140 
0141     QList<ShowfotoItemInfo> showfotoItemInfos()                                     const;
0142     QList<qlonglong>        showfotoItemIds()                                       const;
0143     QList<ShowfotoItemInfo> uniqueShowfotoItemInfos()                               const;
0144 
0145     bool hasImage(qlonglong id)                                                     const;
0146     bool hasImage(const ShowfotoItemInfo& info)                                     const;
0147 
0148     bool isEmpty()                                                                  const;
0149 
0150     /**
0151      * Remove the given infos or indexes directly from the model.
0152      */
0153     void removeIndex(const QModelIndex& index);
0154     void removeIndexs(const QList<QModelIndex>& indexes);
0155     void removeShowfotoItemInfo(const ShowfotoItemInfo& info);
0156     void removeShowfotoItemInfos(const QList<ShowfotoItemInfo>& infos);
0157 
0158     int numberOfIndexesForShowfotoItemInfo(const ShowfotoItemInfo& info)            const;
0159     int numberOfIndexesForShowfotoItemId(qlonglong id)                              const;
0160 
0161     /**
0162      * Retrieve the ShowfotoItemInfo object from the data() function of the given index
0163      * The index may be from a QSortFilterProxyModel as long as an ShowfotoItemModel is at the end.
0164      */
0165     static ShowfotoItemInfo retrieveShowfotoItemInfo(const QModelIndex& index);
0166     static qlonglong        retrieveShowfotoItemId(const QModelIndex& index);
0167 
0168     /**
0169      * QAbstractListModel implementations
0170      */
0171     int           rowCount(const QModelIndex& parent)                               const override;
0172     QVariant      data(const QModelIndex& index, int role)                          const override;
0173     QVariant      headerData(int section, Qt::Orientation orientation, int role)    const override;
0174     Qt::ItemFlags flags(const QModelIndex& index)                                   const override;
0175     QModelIndex   index(int row, int column, const QModelIndex& parent)             const override;
0176 
0177     /**
0178      * DragDrop methods
0179      */
0180     DECLARE_MODEL_DRAG_DROP_METHODS
0181 
0182     /**
0183      * Enable sending of itemInfosAboutToBeRemoved and itemsInfosRemoved signals.
0184      * Default: false
0185      */
0186     void setSendRemovalSignals(bool send);
0187 
0188 Q_SIGNALS:
0189 
0190     /**
0191      * Informs that ItemInfos will be added to the model.
0192      * This signal is sent before the model data is changed and views are informed.
0193      */
0194     void itemInfosAboutToBeAdded(const QList<ShowfotoItemInfo>& infos);
0195 
0196     /**
0197      * Informs that ItemInfos have been added to the model.
0198      * This signal is sent after the model data is changed and views are informed.
0199      */
0200     void itemInfosAdded(const QList<ShowfotoItemInfo>& infos);
0201 
0202     /**
0203      * Informs that ShowfotoItemInfos will be removed from the model.
0204      * This signal is sent before the model data is changed and views are informed.
0205      * Note: You need to explicitly enable sending of this signal. It is not sent
0206      * in clearShowfotoItemInfos().
0207      */
0208     void itemInfosAboutToBeRemoved(const QList<ShowfotoItemInfo>& infos);
0209 
0210     /**
0211      * Informs that ShowfotoItemInfos have been removed from the model.
0212      * This signal is sent after the model data is changed and views are informed.
0213      * Note: You need to explicitly enable sending of this signal. It is not sent
0214      * in clearShowfotoItemInfos().
0215      */
0216     void itemInfosRemoved(const QList<ShowfotoItemInfo>& infos);
0217 
0218     /**
0219      * Connect to this signal only if you are the current preprocessor.
0220      */
0221     void preprocess(const QList<ShowfotoItemInfo>& infos);
0222     void processAdded(const QList<ShowfotoItemInfo>& infos);
0223 
0224     /**
0225      * Signals that the model is right now ready to start an incremental refresh.
0226      * This is guaranteed only for the scope of emitting this signal.
0227      */
0228     void readyForIncrementalRefresh();
0229 
0230     /**
0231      * Signals that the model has finished currently with all scheduled
0232      * refreshing, full or incremental, and all preprocessing.
0233      * The model is in polished, clean situation right now.
0234      */
0235     void allRefreshingFinished();
0236 
0237 public Q_SLOTS:
0238 
0239     void reAddShowfotoItemInfos(const ShowfotoItemInfoList& infos);
0240     void reAddingFinished();
0241     void slotFileDeleted(const QString& folder, const QString& file, bool status);
0242     void slotFileUploaded(const ShowfotoItemInfo& info);
0243 
0244 protected:
0245 
0246     /**
0247      * As soon as the model is ready to start an incremental refresh, the signal
0248      * readyForIncrementalRefresh() will be emitted. The signal will be emitted inline
0249      * if the model is ready right now.
0250      */
0251     void requestIncrementalRefresh();
0252 
0253     /**
0254      * Starts an incremental refresh operation. You shall only call this method from a slot
0255      * connected to readyForIncrementalRefresh(). To initiate an incremental refresh,
0256      * call requestIncrementalRefresh().
0257      */
0258     void startIncrementalRefresh();
0259     void finishIncrementalRefresh();
0260 
0261     void emitDataChangedForAll();
0262     void emitDataChangedForSelections(const QItemSelection& selection);
0263 
0264     /**
0265      * Called when the internal storage is cleared.
0266      */
0267     virtual void showfotoItemInfosCleared()                                    {};
0268 
0269     /**
0270      * Called before rowsAboutToBeRemoved
0271      */
0272     virtual void showfotoItemInfosAboutToBeRemoved(int /*begin*/, int /*end*/) {};
0273 
0274 private:
0275 
0276     void appendInfos(const QList<ShowfotoItemInfo>& infos);
0277     void publiciseInfos(const QList<ShowfotoItemInfo>& infos);
0278 /*
0279     void cleanSituationChecks();
0280 */
0281     void removeRowPairs(const QList<QPair<int, int> >& toRemove);
0282 /*
0283     void removeRowPairsWithCheck(const QList<QPair<int, int> >& toRemove);
0284 */
0285     static QList<IntPair> toContiguousPairs(const QList<int>& unsorted);
0286 
0287 public:
0288 
0289     /// NOTE: Declared public because it's used in ItemModelIncrementalUpdater class
0290     class Private;
0291 
0292 private:
0293 
0294     // Disable
0295     ShowfotoItemModel(const ShowfotoItemModel&)            = delete;
0296     ShowfotoItemModel& operator=(const ShowfotoItemModel&) = delete;
0297 
0298 private:
0299 
0300     Private* const d;
0301 };
0302 
0303 } // namespace ShowFoto
0304 
0305 Q_DECLARE_METATYPE(ShowFoto::ShowfotoItemModel*)
0306 
0307 #endif // SHOW_FOTO_IMAGE_MODEL_H