File indexing completed on 2025-01-19 03:53:19

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2004-06-15
0007  * Description : Albums manager interface.
0008  *
0009  * SPDX-FileCopyrightText: 2004      by Renchi Raju <renchi dot raju at gmail dot com>
0010  * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  * SPDX-FileCopyrightText: 2006-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #ifndef DIGIKAM_ALBUM_MANAGER_H
0018 #define DIGIKAM_ALBUM_MANAGER_H
0019 
0020 // Qt includes
0021 
0022 #include <QList>
0023 #include <QObject>
0024 #include <QString>
0025 #include <QMap>
0026 #include <QUrl>
0027 #include <QDate>
0028 #include <QFileInfo>
0029 
0030 // Local includes
0031 
0032 #include "album.h"
0033 #include "coredbalbuminfo.h"
0034 #include "dbengineparameters.h"
0035 #include "digikam_export.h"
0036 #include "itemlisterrecord.h"
0037 
0038 namespace Digikam
0039 {
0040 
0041 class FAlbum;
0042 class CollectionLocation;
0043 class AlbumChangeset;
0044 class TagChangeset;
0045 class SearchChangeset;
0046 class CollectionImageChangeset;
0047 class ImageTagChangeset;
0048 
0049 /**
0050  * \class AlbumManager
0051  *
0052  * AlbumManager manages albums: does listing of albums and controls the lifetime of it.
0053  * For PAlbums and TAlbums, the listing is done by reading the db directly and
0054  * building the hierarchy of the albums. For DAlbums, since the listing takes
0055  * time, the work is delegated to a dbjob. Interested frontend entities can
0056  * connect to the albummanager to receive notifications of new Albums, when
0057  * Albums are deleted and when the current album is changed.
0058  *
0059  * Additional operations are provided for: creating/deleting/rename Albums,
0060  * updating icons and moving Albums.
0061  *
0062  */
0063 class DIGIKAM_GUI_EXPORT AlbumManager : public QObject
0064 {
0065     Q_OBJECT
0066 
0067 public:
0068 
0069     /**
0070      * A convenience function to get the instance of the AlbumManager
0071      */
0072     static AlbumManager* instance();
0073 
0074     /**
0075      * starts scanning the libraryPath and listing the albums. If the
0076      * libraryPath has not changed since the last scan, then nothing happens
0077      * @see setLibraryPath
0078      * @see refresh
0079      */
0080     void startScan();
0081 
0082     /**
0083      * Stop ongoing operations, prepare for application shutdown
0084      */
0085     void cleanUp();
0086 
0087     /**
0088      * This is similar to startScan, except that it assumes you have run
0089      * startScan at least once. It checks the database to see if any new albums
0090      * have been added and updates them accordingly. Use this when a change in the
0091      * filesystem is detected (but the album library path hasn't changed)
0092      * @see startScan
0093      */
0094     void refresh();
0095 
0096     /**
0097      * Ensures that valid item counts for physical and tag albums are available
0098      */
0099     void prepareItemCounts();
0100 
0101     bool isShowingOnlyAvailableAlbums() const;
0102     void setShowOnlyAvailableAlbums(bool onlyAvailable);
0103 
0104 private Q_SLOTS:
0105 
0106     void slotImagesDeleted(const QList<qlonglong>& imageIds);
0107 
0108     // -----------------------------------------------------------------------------
0109 
0110     /**
0111      * @name Operations with database
0112      */
0113 
0114     //@{
0115 
0116 public:
0117 
0118     /**
0119      * Initialize. Informs the user about failures.
0120      * Returns true on success, false on failure.
0121      * A return value of false during startup indicates termination of the program
0122      * (user is informed)
0123      *
0124      * ignoreDisappearedLocations is intended to be used in tests, because the path of the collection is hardcoded
0125      * but when executing the test on different computers the collection might not be available at that path
0126      */
0127     bool setDatabase(const DbEngineParameters& params, bool priority,
0128                      const QString& suggestedAlbumRoot = QString(), bool ignoreDisappearedLocations = false);
0129 
0130     /**
0131      * Sets new database when chosen by the user in setup.
0132      * Handles user notification about problems.
0133      * Call this instead of setDatabase when digiKam is up and running.
0134      */
0135     void changeDatabase(const DbEngineParameters& params);
0136 
0137     /**
0138      * Checks if the given database path is equal to the current one
0139      */
0140     bool databaseEqual(const DbEngineParameters& parameters) const;
0141 
0142     /**
0143      * Some checks for settings done in first run wizard in case of QSlite Database.
0144      */
0145     static void checkDatabaseDirsAfterFirstRun(const QString& dbPath, const QString& albumPath);
0146 
0147 private:
0148 
0149     static bool moveToBackup(const QFileInfo& info);
0150     static bool copyToNewLocation(const QFileInfo& oldFile,
0151                                   const QFileInfo& newFile,
0152                                   const QString& otherMessage = QString());
0153 
0154     //@}
0155 
0156     // -----------------------------------------------------------------------------
0157 
0158     /**
0159      * @name Operations with collections
0160      */
0161 
0162     //@{
0163 
0164 private:
0165 
0166     /**
0167      * Returns true if it added or removed an album.
0168      */
0169     bool handleCollectionStatusChange(const CollectionLocation& location, int oldStatus);
0170 
0171     void addAlbumRoot(const CollectionLocation& location);
0172     void removeAlbumRoot(const CollectionLocation& location);
0173 
0174 private Q_SLOTS:
0175 
0176     void slotCollectionLocationStatusChanged(const CollectionLocation&, int);
0177     void slotCollectionLocationPropertiesChanged(const CollectionLocation& location);
0178     void slotCollectionImageChange(const CollectionImageChangeset& changeset);
0179 
0180     //@}
0181 
0182     // -----------------------------------------------------------------------------
0183 
0184     /**
0185      * @name Operations on generic Album
0186      */
0187 
0188     //@{
0189 
0190 public:
0191 
0192     /**
0193      * set current album to @p albums.
0194      */
0195     void setCurrentAlbums(const QList<Album*>& albums);
0196 
0197     /**
0198      * @returns current albums, previously set up by setCurrentAlbums
0199      */
0200     AlbumList currentAlbums()                       const;
0201 
0202     /**
0203      * clear current albums.
0204      */
0205     void clearCurrentAlbums();
0206 
0207     /**
0208      * @return a Album with the given globalID
0209      * @param gid the global id for the album
0210      */
0211     Album*    findAlbum(int gid)                    const;
0212 
0213     /**
0214      * @return a Album with the given type and id
0215      * @param id the id for the album (not the global id)
0216      */
0217     Album*    findAlbum(Album::Type type, int id)   const;
0218 
0219     /**
0220      * @return A hash with the titles for all album IDs.
0221      */
0222     QHash<int, QString> albumTitles()               const;
0223 
0224     /**
0225      * Returns if the given album is currently being moved, that is,
0226      * if this album is in between signalAlbumAboutToBeMoved and
0227      * signalAlbumMoved. In this case, you can preserve state of such an album
0228      * because the object is guaranteed not to be deleted, even if
0229      * signalAlbumAboutToBeDeleted is emitted.
0230      */
0231     bool isMovingAlbum(Album* album) const;
0232 
0233     /**
0234      * Returns the id of the item with the given filename in
0235      * the given Album.
0236      * @param album The album in which we search the item.
0237      * @param fileName The name of the item file.
0238      * @return The item id or -1 if not existent.
0239      */
0240     qlonglong getItemFromAlbum(Album* const album, const QString& fileName);
0241 
0242 private:
0243 
0244     bool hasDirectChildAlbumWithTitle(Album* parent, const QString& title);
0245     void notifyAlbumDeletion(Album* album);
0246     void updateAlbumPathHash();
0247     void addGuardedPointer(Album* a, Album** pointer);
0248     void removeGuardedPointer(Album* a, Album** pointer);
0249     void changeGuardedPointer(Album* oldAlbum, Album* a, Album** pointer);
0250     void invalidateGuardedPointers(Album* album);
0251 
0252 private Q_SLOTS:
0253 
0254     void slotAlbumsJobResult();
0255     void slotAlbumsJobData(const QHash<int, int>& albumsStatHash);
0256     void slotAlbumChange(const AlbumChangeset& changeset);
0257     void getAlbumItemsCount();
0258 
0259 Q_SIGNALS:
0260 
0261     /**
0262      * Emitted when an album is about to be added to the given parent (0 if album is root)
0263      * after the item given by prev (prev is 0 if parent has no children yet).
0264      */
0265     void signalAlbumAboutToBeAdded(Album* album, Album* parent, Album* prev);
0266 
0267     /**
0268      * Emitted when the album has been added.
0269      */
0270     void signalAlbumAdded(Album* album);
0271 
0272     /**
0273      * Emitted when the album is about to be deleted, but is still fully valid.
0274      */
0275     void signalAlbumAboutToBeDeleted(Album* album);
0276 
0277     /**
0278      * Emitted when the album is deleted, but the object can still be accessed.
0279      */
0280     void signalAlbumDeleted(Album* album);
0281 
0282     /**
0283      * Emitted when the album is deleted, the object can no longer be accessed.
0284      * For identification purposes, the former album pointer is passed.
0285      */
0286     void signalAlbumHasBeenDeleted(quintptr);
0287 
0288     void signalAlbumsCleared();
0289     void signalAlbumCurrentChanged(const QList<Album*>& albums);
0290     void signalAllAlbumsLoaded();
0291 
0292     void signalAlbumIconChanged(Album* album);
0293     void signalAlbumRenamed(Album* album);
0294     void signalAlbumNewPath(Album* album);
0295 
0296     /**
0297      * Emittedd when an album is about to be moved. Signals for deleting and adding will be
0298      * sent afterwards, but the album object is guaranteed not to be deleted until after signalAlbumMoved.
0299      */
0300     void signalAlbumAboutToBeMoved(Album* album);
0301 
0302     /**
0303      * Emitted when the album is moved to its new parent. After signalAlbumAboutToBeMoved,
0304      * all four signals for first deleting and then adding will have been sent.
0305      */
0306     void signalAlbumMoved(Album* album);
0307     void signalAlbumsUpdated(int type);
0308 
0309     /**
0310      * Emitted when a change is done on available Albums.
0311      * Please note that affected albums may appear or disappear after this signal has been emitted.
0312      */
0313     void signalShowOnlyAvailableAlbumsChanged(bool showsOnlyAvailableAlbums);
0314 
0315     //@}
0316 
0317     // -----------------------------------------------------------------------------
0318 
0319     /**
0320      * @name Operations on Date Album
0321      */
0322 
0323     //@{
0324 
0325 public:
0326 
0327     /**
0328      * @return a list of all DAlbums
0329      */
0330     AlbumList allDAlbums()                  const;
0331 
0332     /**
0333      * @return a DAlbum with given ID
0334      * @param id the id for the DAlbum
0335      */
0336     DAlbum*   findDAlbum(int id)            const;
0337 
0338     /**
0339      * Returns the latest count for DAlbums as also emitted via
0340      * signalDAlbumsDirty.
0341      *
0342      * @return count map for DAlbums
0343      */
0344     QMap<YearMonth, int> getDAlbumsCount()  const;
0345 
0346 private Q_SLOTS:
0347 
0348     void slotDatesJobResult();
0349     void slotDatesJobData(const QHash<QDateTime, int>& datesStatHash);
0350 
0351     /**
0352      * Scan dates from the database and updates the DAlbums.
0353      */
0354     void scanDAlbumsScheduled();
0355     void scanDAlbums();
0356 
0357 Q_SIGNALS:
0358 
0359     void signalDAlbumsDirty(const QMap<YearMonth, int>&);
0360     void signalDatesHashDirty(const QHash<QDateTime, int>&);
0361     void signalAllDAlbumsLoaded();
0362 
0363     //@}
0364 
0365     // -----------------------------------------------------------------------------
0366 
0367     /**
0368      * @name Operations on Physical Album
0369      */
0370 
0371     //@{
0372 
0373 public:
0374 
0375     /**
0376      * @return a list of all PAlbums
0377      */
0378     AlbumList allPAlbums()                  const;
0379 
0380     /**
0381      * @returns the current PAlbum or null if no one is selected
0382      */
0383     PAlbum* currentPAlbum()                 const;
0384 
0385     /**
0386      * Given a complete file url (kde url with file protocol), it will try to find
0387      * a PAlbum corresponding to it.
0388      * \warning This should not be used, unless really necessary
0389      * @return PAlbum corresponding to supplied @p url
0390      * @param url the url we need to check
0391      */
0392     PAlbum*   findPAlbum(const QUrl& url)   const;
0393 
0394     /**
0395      * @return a PAlbum with given ID
0396      * @param id the id for the PAlbum
0397      */
0398     PAlbum*   findPAlbum(int id)            const;
0399 
0400     /**
0401      * Returns the latest count for PAlbums as also emitted via
0402      * signalPAlbumsDirty.
0403      *
0404      * @return count map for PAlbums
0405      */
0406     QHash<int, int> getPAlbumsCount()        const;
0407 
0408     void removeWatchedPAlbums(const PAlbum* const album);
0409 
0410     /**
0411      * Create a new PAlbum with supplied properties as a child of the parent
0412      * This is equivalent to creating a new folder on the disk with supplied
0413      * name in the parent's folder path. Also the supplied attributes are written
0414      * out to the database
0415      * \note the signalAlbumAdded will be fired before this function returns. Its
0416      * recommended to connect to that signal to get notification of new album added
0417      * @return the newly created PAlbum or 0 if it fails
0418      * @param parent  The parent album under which to create the new Album.
0419      *                Parent must not be root. Otherwise, use the other variants of this method.
0420      *                If parent is root, the albumRootPath must be supplied.
0421      * @param name    the name of the new album
0422      * @param caption the caption for the new album
0423      * @param date    the date for the new album
0424      * @param errMsg  this will contain the error message describing why the
0425      * operation failed
0426      */
0427     PAlbum* createPAlbum(PAlbum* parent, const QString& name,
0428                          const QString& caption, const QDate& date,
0429                          const QString& category,
0430                          QString& errMsg);
0431 
0432     /**
0433      * Overloaded method. Here you can supply an albumRootPath which must
0434      * correspond to an available collection location.
0435      */
0436     PAlbum* createPAlbum(const QString& albumRootPath, const QString& name,
0437                          const QString& caption, const QDate& date,
0438                          const QString& category,
0439                          QString& errMsg);
0440 
0441     /**
0442      * Overloaded method. Here you can supply a collection location (which
0443      * must be available).
0444      *
0445      * @param location the collection for the new album
0446      */
0447     PAlbum* createPAlbum(const CollectionLocation& location, const QString& name,
0448                          const QString& caption, const QDate& date,
0449                          const QString& category,
0450                          QString& errMsg);
0451 
0452     /**
0453      * Renames a PAlbum. This is equivalent to actually renaming the corresponding
0454      * folder on the disk.
0455      * @return true if the operation succeeds, false otherwise
0456      * @param album the Album which should be renamed
0457      * @param newName the new name for the album
0458      * @param errMsg this will contain the error message describing why the
0459      * operation failed
0460      */
0461     bool renamePAlbum(PAlbum* album, const QString& newName,
0462                       QString& errMsg);
0463 
0464     /**
0465      * Update the icon for an album. The @p icon is the name (and not full path)
0466      * of the file in the album
0467      * @return true if the operation succeeds, false otherwise
0468      * @param album  the album for which icon should be changed
0469      * @param iconID the filename of the new icon
0470      * @param errMsg if the operation fails, this will contain the error message
0471      * describing why the operation failed
0472      */
0473     bool updatePAlbumIcon(PAlbum* album, qlonglong iconID, QString& errMsg);
0474 
0475 private:
0476 
0477     bool showDatabaseSetupPage(const QString& error, bool priority, const QString& suggestedAlbumRoot);
0478     void insertPAlbum(PAlbum* album, PAlbum* parent);
0479     void removePAlbum(PAlbum* album);
0480 
0481 private Q_SLOTS:
0482 
0483     /**
0484      * Scan albums directly from database and creates new PAlbums
0485      * It only creates those PAlbums which haven't already been
0486      * created.
0487      */
0488     void scanPAlbums();
0489     void updateChangedPAlbums();
0490 
0491 Q_SIGNALS:
0492 
0493     void signalPAlbumsDirty(const QHash<int, int>&);
0494     void signalEmptyTrash();
0495 
0496     //@}
0497 
0498     // -----------------------------------------------------------------------------
0499 
0500     /**
0501      * @name Operations on Tag Album
0502      */
0503 
0504     //@{
0505 
0506 public:
0507 
0508     /**
0509      * @return a list of all TAlbums
0510      */
0511     AlbumList allTAlbums()                       const;
0512 
0513     /**
0514      * @returns the current TAlbum or null if no one is selected
0515      */
0516     QList<TAlbum*> currentTAlbums()              const;
0517 
0518     /**
0519      * @return a TAlbum with given ID
0520      * @param id the id for the TAlbum
0521      */
0522     TAlbum*   findTAlbum(int id)                 const;
0523 
0524     /**
0525      * @return a TAlbum with given tag path, or 0 if not found
0526      * @param tagPath the tag path ("People/Friend/John")
0527      */
0528     TAlbum*   findTAlbum(const QString& tagPath) const;
0529 
0530     /**
0531      * Returns the latest count for TAlbums as also emitted via
0532      * signalTAlbumsDirty.
0533      *
0534      * @return count map for TAlbums
0535      */
0536     QHash<int, int> getTAlbumsCount()             const;
0537 
0538     /**
0539      * Create a new TAlbum with supplied properties as a child of the parent
0540      * The tag is added to the database
0541      * \note the signalAlbumAdded will be fired before this function returns. Its
0542      * recommended to connect to that signal to get notification of new album added
0543      * @return the newly created TAlbum or 0 if it fails
0544      * @param parent  the parent album under which to create the new Album
0545      * @param name    the name of the new album
0546      * @param iconkde the iconkde for the new album (this is a filename which
0547      * kde iconloader can load up
0548      * @param errMsg  this will contain the error message describing why the
0549      * operation failed
0550      */
0551     TAlbum* createTAlbum(TAlbum* parent, const QString& name,
0552                          const QString& iconkde, QString& errMsg);
0553 
0554     /**
0555      * A list of tag paths is supplied.
0556      * If no corresponding TAlbum exists, a new one will be created.
0557      * @param tagPaths A list of tag paths
0558      * @returns A list of all TAlbums for the list (already existing or newly created)
0559      */
0560     AlbumList findOrCreateTAlbums(const QStringList& tagPaths);
0561 
0562     /**
0563      * Delete a TAlbum.
0564      * The tag is removed from the database
0565      * \note the signalAlbumDeleted will be fired before this function returns. Its
0566      * recommended to connect to that signal to get notification of album deletes
0567      * @return true if the operation succeeds or false otherwise
0568      * @param album   the TAlbum to delete
0569      * @param errMsg  this will contain the error message describing why the
0570      * @param askUser ask user to write metadata to images
0571      * operation failed
0572      */
0573     bool deleteTAlbum(TAlbum* album, QString& errMsg, QList<qlonglong>* imageIds = nullptr);
0574 
0575     /**
0576      * Renames a TAlbum.
0577      * This updates the tag name in the database
0578      * @return true if the operation succeeds, false otherwise
0579      * @param album the Album which should be renamed
0580      * @param name the new name for the album
0581      * @param errMsg this will contain the error message describing why the
0582      * operation failed
0583      */
0584     bool renameTAlbum(TAlbum* album, const QString& name, QString& errMsg);
0585 
0586     /**
0587      * Move a TAlbum to a new parent.
0588      * This updates the tag parent ID in the database
0589      * @return true if the operation succeeds, false otherwise
0590      * @param album the Album which should be moved
0591      * @param newParent the Parent Album to which album should be moved
0592      * @param errMsg this will contain the error message describing why the
0593      * operation failed
0594      */
0595     bool moveTAlbum(TAlbum* album, TAlbum* newParent, QString& errMsg);
0596 
0597     /**
0598      * Merge a TAlbum to a TAlbum.
0599      * This updates the image tags in the database
0600      * @return true if the operation succeeds, false otherwise
0601      * @param album the Album which should be merged
0602      * @param destAlbum the Album to which album should be merged
0603      * @param dialog show dialog to ask the user if he wants to merge
0604      * @param errMsg this will contain the error message describing why the
0605      * operation failed
0606      */
0607 
0608     bool mergeTAlbum(TAlbum* album, TAlbum* destAlbum, bool dialog, QString& errMsg);
0609 
0610     /**
0611      * Update the icon for a TAlbum.
0612      * @return true if the operation succeeds, false otherwise
0613      * @param album the album for which icon should be changed
0614      * @param iconKDE  a simple filename which can be loaded by KIconLoader
0615      * @param iconID   id of the icon image file
0616      * @param errMsg this will contain the error message describing why the
0617      * operation failed
0618      * \note if iconKDE is not empty then iconID is used. So if you want to set
0619      * the icon to a file which can be loaded by QIcon, pass it in as
0620      * iconKDE. otherwise pass a null QString to iconKDE and set iconID
0621      */
0622     bool updateTAlbumIcon(TAlbum* album, const QString& iconKDE,
0623                           qlonglong iconID, QString& errMsg);
0624 
0625     /**
0626      * Get a list of recently assigned tags (only last 6 tags are listed)
0627      * @return the list of recently assigned TAlbums
0628      * @param includeInternal include internal tags in the returned list, or skip them
0629      */
0630     AlbumList getRecentlyAssignedTags(bool includeInternal = false)                                      const;
0631 
0632     /**
0633      * @return A list with the tag paths for a list of tag IDs.
0634      * @param tagIDs list of tag album IDs
0635      * @param leadingSlash if <code>true</code> return tags with a leading slash
0636      * @param includeInternal include internal tags in the returned list, or skip them
0637      */
0638     QStringList tagPaths(const QList<int>& tagIDs, bool leadingSlash=true, bool includeInternal = false) const;
0639 
0640     /**
0641      * @return A list with the tag names for a list of tag IDs.
0642      * @param tagIDs list of tag album IDs
0643      */
0644     QStringList tagNames(const QList<int>& tagIDs, bool includeInternal = false)                         const;
0645 
0646     /**
0647      * @return A hash with the tag paths for all tag IDs.
0648      */
0649     QHash<int, QString> tagPaths(bool leadingSlash=true, bool includeInternal = false)                   const;
0650 
0651     /**
0652      * @return A hash with the tag names for all tag IDs.
0653      */
0654     QHash<int, QString> tagNames(bool includeInternal = false)                                           const;
0655 
0656     /**
0657      * Returns a list of TAlbums which have the given property,
0658      * or the given property/value combination.
0659      */
0660     AlbumList findTagsWithProperty(const QString& property);
0661     AlbumList findTagsWithProperty(const QString& property, const QString& value);
0662 
0663     /**
0664      * TODO
0665      */
0666     QList<int> subTags(int tagId, bool recursive = false)                                                const;
0667     int findTopId(int tagId)                                                                             const;
0668 
0669     void askUserForWriteChangedTAlbumToFiles(TAlbum* const album);
0670     void askUserForWriteChangedTAlbumToFiles(const QList<qlonglong>& imageIds);
0671 
0672 private:
0673 
0674     /**
0675      * Checks whether an Album has a direct child with the given name.
0676      *
0677      * @param parent album to check children for
0678      * @param title the title to search for
0679      * @return <code>true</code> if there is a child with name, else
0680      *         <code>false</code>
0681      */
0682     void insertTAlbum(TAlbum* album, TAlbum* parent);
0683     void removeTAlbum(TAlbum* album);
0684 
0685 private Q_SLOTS:
0686 
0687     /**
0688      * Scan tags directly from database and creates new TAlbums
0689      * It only creates those TAlbums which haven't already been
0690      * created.
0691      */
0692     void scanTAlbums();
0693 
0694     void slotTagsJobResult();
0695     void slotTagsJobData(const QHash<int, int>& tagsStatHash);
0696     void slotTagChange(const TagChangeset& changeset);
0697     void slotImageTagChange(const ImageTagChangeset& changeset);
0698 
0699     void getTagItemsCount();
0700     void tagItemsCount();
0701 
0702 Q_SIGNALS:
0703 
0704     void signalTAlbumsDirty(const QHash<int, int>&);
0705     void signalTagPropertiesChanged(TAlbum* album);
0706 
0707     //@}
0708 
0709     // -----------------------------------------------------------------------------
0710 
0711     /**
0712      * @name Operations on Search Album
0713      */
0714 
0715     //@{
0716 
0717 public:
0718 
0719     /**
0720      * @return a list of all SAlbums
0721      */
0722     AlbumList allSAlbums()                                  const;
0723 
0724     /**
0725      * @return a SAlbum with given ID
0726      * @param id the id for the SAlbum
0727      */
0728     SAlbum*   findSAlbum(int id)                            const;
0729 
0730     /**
0731      * @return a SAlbum with given name, or 0 if not found
0732      * @param name the name of the search
0733      */
0734     SAlbum*   findSAlbum(const QString& name)               const;
0735 
0736     /**
0737      * @return SAlbums with given type, empty list if not found
0738      * @param searchType the type of the search
0739      */
0740     QList<SAlbum*> findSAlbumsBySearchType(int searchType)  const;
0741 
0742     /**
0743      * Create a new SAlbum with supplied url. If an existing SAlbum with same name
0744      * exists this function will return a pointer to that album, instead of creating
0745      * a new one. A newly created search album is added to the database. For an
0746      * existing SAlbum, the url is updated and written out to the database
0747      * \note the signalAlbumAdded will be fired before this function returns. Its
0748      * recommended to connect to that signal to get notification of new album added
0749      * @return the newly created SAlbum or an existing SAlbum with same name
0750      * @param name  name for the new search
0751      * @param type  the type of the search
0752      * @param query search query to use
0753      */
0754     SAlbum* createSAlbum(const QString& name,
0755                          DatabaseSearch::Type type,
0756                          const QString& query);
0757 
0758     /**
0759      * Update the url for a SAlbum
0760      * @return true if the operation succeeds, false otherwise
0761      * @param album the album to update
0762      * @param changedQuery the new query data of the album
0763      * @param changedName a new name, or null to keep the current name
0764      * @param type a new type, or UndefinedType to keep the current type
0765      */
0766     bool updateSAlbum(SAlbum* album,
0767                       const QString& changedQuery,
0768                       const QString& changedName = QString(),
0769                       DatabaseSearch::Type type = DatabaseSearch::UndefinedType);
0770 
0771     /**
0772      * Delete a SAlbum from the database
0773      * \note the signalAlbumDeleted will be fired before this function returns. Its
0774      * recommended to connect to that signal to get notification of album deletes
0775      * @return true if the operation succeeds, false otherwise
0776      * @param album the album to delete
0777      */
0778     bool deleteSAlbum(SAlbum* album);
0779 
0780 private Q_SLOTS:
0781 
0782     /**
0783      * Scan searches directly from database and creates new SAlbums
0784      * It only creates those SAlbums which haven't already been
0785      * created.
0786      */
0787     void scanSAlbums();
0788 
0789     void slotSearchChange(const SearchChangeset& changeset);
0790 
0791 Q_SIGNALS:
0792 
0793     void signalUpdateDuplicatesAlbums(const QList<SAlbum*>& modifiedAlbums,
0794                                       const QList<qlonglong>& deletedImages);
0795     void signalSearchUpdated(SAlbum* album);
0796 
0797     //@}
0798 
0799     // -----------------------------------------------------------------------------
0800 
0801     /**
0802      * @name Operations on Face Album
0803      */
0804 
0805     //@{
0806 
0807 public:
0808 
0809     /**
0810      * Returns the latest count for faces as also emitted via
0811      * signalFaceCountsDirty.
0812      *
0813      * @return count map for faces (confirmed and unconfirmed combined)
0814      */
0815     QHash<int, int> getFaceCount()            const;
0816 
0817     /**
0818      * Returns the latest count for unconfirmed faces only
0819      * as also emitted via signalFaceCountsDirty.
0820      *
0821      * @return count map for unconfirmed faces only
0822      */
0823     QHash<int, int> getUnconfirmedFaceCount() const;
0824 
0825 private Q_SLOTS:
0826 
0827     void slotPeopleJobResult();
0828     void slotPeopleJobData(const QMap<QString,
0829                            QHash<int, int> >& facesStatHash);
0830     void personItemsCount();
0831 
0832 Q_SIGNALS:
0833 
0834     void signalFaceCountsDirty(const QHash<int, int>& faceCount,
0835                                const QHash<int, int>& uFaceCount,
0836                                const QList<int>& toUpdatedFaces);
0837 
0838     //@}
0839 
0840 private:
0841 
0842     // Disable
0843     AlbumManager();
0844     explicit AlbumManager(QObject*) = delete;
0845     ~AlbumManager() override;
0846 
0847     friend class AlbumManagerCreator;
0848 
0849     static AlbumManager* internalInstance;
0850 
0851 public:
0852 
0853     // Declared public because it used in ChangingDB class.
0854     class Private;
0855 
0856 private:
0857 
0858     Private* const d;
0859 
0860     template <class T> friend class AlbumPointer;
0861     friend class Album;
0862 };
0863 
0864 } // namespace Digikam
0865 
0866 #endif // DIGIKAM_ALBUM_MANAGER_H