File indexing completed on 2024-06-02 04:14:53

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2007-01-05
0007  * Description : Metadata handling
0008  *
0009  * SPDX-FileCopyrightText: 2007-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0010  * SPDX-FileCopyrightText: 2007-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 #ifndef DIGIKAM_METADATA_HUB_H
0017 #define DIGIKAM_METADATA_HUB_H
0018 
0019 // Qt includes
0020 
0021 #include <QList>
0022 #include <QStringList>
0023 #include <QDateTime>
0024 #include <QMap>
0025 
0026 // Local includes
0027 
0028 #include "metaenginesettings.h"
0029 #include "captionvalues.h"
0030 #include "dmetadata.h"
0031 #include "dimg.h"
0032 
0033 namespace Digikam
0034 {
0035 
0036 class ApplicationSettings;
0037 class ItemInfo;
0038 class Template;
0039 
0040 class MetadataHub
0041 {
0042 public:
0043 
0044     /**
0045      * The status enum describes the result of joining several metadata sets.
0046      * If only one set has been added, the status is always MetadataAvailable.
0047      * If no set has been added, the status is always MetadataInvalid
0048      */
0049     enum Status
0050     {
0051         MetadataInvalid,   ///< not yet filled with any value
0052         MetadataAvailable  ///< only one data set has been added, or a common value is available
0053     };
0054 
0055     enum WriteMode
0056     {
0057         /**
0058          * Write all available information
0059          */
0060         FullWrite,
0061 
0062         /**
0063          * Do a full write if and only if
0064          *     - metadata fields changed
0065          *     - the changed fields shall be written according to write settings
0066          * "Changed" in this context means changed by one of the set... methods,
0067          * the load() methods are ignored for this attribute.
0068          * This mode allows to avoid write operations when e.g. the user does not want
0069          * keywords to be written and only changes keywords.
0070          */
0071         FullWriteIfChanged,
0072 
0073         /**
0074          * Write only the changed parts.
0075          * Metadata fields which cannot be changed from MetadataHub (photographer ID etc.)
0076          * will never be written
0077          */
0078         PartialWrite
0079     };
0080 
0081     enum WriteComponents
0082     {
0083         WRITE_DATETIME  = 1,
0084         WRITE_TITLE     = 2,
0085         WRITE_COMMENTS  = 4,
0086         WRITE_PICKLABEL = 8,
0087         WRITE_COLORLABEL= 16,
0088         WRITE_RATING    = 32,
0089         WRITE_TEMPLATE  = 64,
0090         WRITE_TAGS      = 128,
0091         WRITE_POSITION  = 256,
0092         WRITE_ALL       = 511
0093     };
0094     Q_DECLARE_FLAGS(WriteComponent, WriteComponents)
0095 
0096 public:
0097 
0098     /**
0099      * Constructs a MetadataHub.
0100      */
0101     MetadataHub();
0102     ~MetadataHub();
0103 
0104     void reset();
0105 
0106     // --------------------------------------------------
0107 
0108     /**
0109      * Add metadata information contained in the ItemInfo object.
0110      * This method (or in combination with the other load methods)
0111      * can be called multiple times on the same MetadataHub object.
0112      * In this case, the metadata will be combined.
0113      */
0114     void load(const ItemInfo& info);
0115 
0116 //    /**
0117 //     * Add metadata information from the meta engine object
0118 //     */
0119 //    void load(const DMetadata& metadata);
0120 
0121 //    /**
0122 //     * Load metadata information from the given file.
0123 //     * (Uses DMetadata, QFileInfo)
0124 //     * @returns True if the metadata could be loaded
0125 //     */
0126 //    bool load(const QString& filePath, const MetaEngineSettingsContainer& settings = MetaEngineSettings::instance()->settings());
0127 
0128     // --------------------------------------------------
0129 
0130     /**
0131      * @brief writeToMetadata - write to metadata using image info to retrieve tags and filepath
0132      *                          use this method when multiple image infos are loaded in hub
0133      * @param info - image info to retrieve current tags
0134      * @param writeMode
0135      * @param settings
0136      * @return true           - if everything is successful
0137      */
0138     bool writeToMetadata(const ItemInfo& info,
0139                          WriteComponent writeMode = WRITE_ALL,
0140                          bool ignoreLazySync = false,
0141                          const MetaEngineSettingsContainer& settings = MetaEngineSettings::instance()->settings());
0142 
0143 
0144     /**
0145      * Constructs a meta engine object for given filePath,
0146      * calls the above method, writes the changes out to the file,
0147      * and notifies the ItemAttributesWatch.
0148      * WARNING: Do not use this method when multiple image infos are loaded
0149      *          It will result in disjoint tags not being written
0150      *          Use writeToMetadata(Image info ...) instead
0151      * @return Returns if the file has been touched
0152      */
0153     bool write(const QString& filePath,
0154                WriteComponent writeMode = WRITE_ALL,
0155                bool ignoreLazySync = false,
0156                const MetaEngineSettingsContainer& settings = MetaEngineSettings::instance()->settings());
0157 
0158     /**
0159      * Constructs a meta engine object from the metadata stored in the given DImg object,
0160      * calls the above method, and changes the stored metadata in the DImg object.
0161      * @return Returns if the DImg object has been touched
0162      */
0163     bool write(const DImg& image,
0164                WriteComponent writeMode = WRITE_ALL,
0165                bool ignoreLazySync = false,
0166                const MetaEngineSettingsContainer& settings = MetaEngineSettings::instance()->settings());
0167 
0168     /**
0169      * Will write only Tags to image. Used by TagsManager to write tags to image
0170      * Other metadata are not updated.
0171      * @return if tags were successfully written.
0172      */
0173     bool writeTags(const QString& filePath,
0174                    WriteComponent writeMode = WRITE_ALL,
0175                    const MetaEngineSettingsContainer& settings = MetaEngineSettings::instance()->settings());
0176 
0177     /**
0178      * @brief writeTags - used to deduplicate code from writeTags and usual write, all write to tags
0179      *                    operations must be done here
0180      * @param metadata  - meta engine object that apply changes
0181      * @param saveTags  - save switch
0182      * @return          - if tags were successfully set
0183      */
0184     bool writeTags(const DMetadata& metadata, bool saveTags);
0185 
0186     /**
0187      * @brief cleanupTags - remove duplicates and obsolete tags before setting metadata
0188      * @param toClean     - tag list to be cleared and de-duplicated
0189      * @return            - clean tag list
0190      */
0191     QStringList cleanupTags(const QStringList& toClean);
0192 
0193     /**
0194      * With the currently applied changes, the given writeMode and settings,
0195      * returns if write(DMetadata), write(QString) or write(DImg) will actually
0196      * apply any changes.
0197      */
0198     bool willWriteMetadata(Digikam::MetadataHub::WriteComponent writeMode = WRITE_ALL,
0199                            const MetaEngineSettingsContainer& settings = MetaEngineSettings::instance()->settings()) const;
0200 
0201     /**
0202      * @brief writeToBaloo - write tags, comments and rating to KDE Nepomuk replacement: Baloo
0203      * @param filePath     - path to file to add comments, tags and rating
0204      * @param settings     - metadata settings to be set
0205      */
0206     void writeToBaloo(const QString& filePath,
0207                       const MetaEngineSettingsContainer& settings = MetaEngineSettings::instance()->settings());
0208 
0209 protected:
0210 
0211     /**
0212      * Applies the set of metadata contained in this MetadataHub
0213      * to the given meta engine object.
0214      * The MetaEngineSettingsContainer determine whether data is actually
0215      * set or not.
0216      * The following metadata fields may be set (depending on settings):
0217      * - Comment
0218      * - Date
0219      * - Rating
0220      * - Tags
0221      * - Photographer ID (data from settings)
0222      * - Credits (data from settings)
0223      *
0224      * The data fields taken from this MetadataHub object are only set if
0225      * their status is MetadataAvailable.
0226      * If the status is MetadataInvalid or MetadataDisjoint, the respective
0227      * metadata field is not touched.
0228      * @return Returns true if the metadata object has been touched
0229      */
0230     bool write(DMetadata& metadata,
0231                WriteComponent writeMode = WRITE_ALL,
0232                const MetaEngineSettingsContainer& settings = MetaEngineSettings::instance()->settings());
0233 
0234     void load(const QDateTime& dateTime,
0235               const CaptionsMap& titles,
0236               const CaptionsMap& comment,
0237               int colorLabel, int pickLabel,
0238               int rating, const Template& t);
0239 
0240     void loadTags(const QList<int>& loadedTagIds);
0241     void loadFaceTags(const ItemInfo& info);
0242 
0243     void notifyTagDeleted(int id);
0244 
0245     void applyChangeNotifications();
0246 
0247 private:
0248 
0249     bool writeFaceTagsMap(const DMetadata& metadata, bool saveFaces);
0250 
0251 private:
0252 
0253     class Private;
0254     Private* const d;
0255 
0256 private:
0257 
0258     Q_DISABLE_COPY(MetadataHub)
0259 };
0260 
0261 } // namespace Digikam
0262 
0263 Q_DECLARE_OPERATORS_FOR_FLAGS(Digikam::MetadataHub::WriteComponent)
0264 
0265 #endif // DIGIKAM_METADATA_HUB_H