summaryrefslogtreecommitdiffstats
path: root/digikam/digikam/metadatahub.h
blob: decb148e2b0fe3fbb58591c9d3cd2aa144ca6ac9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
/* ============================================================
 *
 * This file is a part of digiKam project
 * http://www.digikam.org
 *
 * Date        : 2007-01-05
 * Description : Metadata handling
 *
 * Copyright (C) 2007-2009 by Marcel Wiesweg <marcel.wiesweg@gmx.de>
 * Copyright (C) 2007-2009 by Gilles Caulier <caulier dot gilles at gmail dot com>
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General
 * Public License as published by the Free Software Foundation;
 * either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * ============================================================ */

#ifndef METADATAHUB_H
#define METADATAHUB_H

// TQt includes.

#include <tqstringlist.h>
#include <tqdatetime.h>
#include <tqmap.h>
#include <tqvaluelist.h>

// KDE includes.

#include <kurl.h>

// Local includes.

#include "dmetadata.h"
#include "dimg.h"

namespace Digikam
{

class AlbumSettings;
class ImageInfo;
class TAlbum;
class MetadataHubPriv;

class MetadataWriteSettings
{
    /**
        The class MetadataWriteSettings encapsulates all metadata related settings that are available
        from the AlbumSettings.
        This allows supply changed arguments to MetadataHub without changing the global settings
    */
public:

    /**
        Constructs a MetadataWriteSettings object with all boolean values set to false,
        all TQString values set to TQString()
    */
    MetadataWriteSettings();

    /**
        Constructs a MetadataWriteSettings object from the given AlbumSettings object
    */
    MetadataWriteSettings(AlbumSettings *albumsettings);

    bool     saveComments;
    bool     saveDateTime;
    bool     saveRating;
    bool     saveIptcTags;
    bool     saveIptcPhotographerId;
    bool     saveIptcCredits;

    TQString  iptcAuthor;
    TQString  iptcAuthorTitle;
    TQString  iptcCredit;
    TQString  iptcSource;
    TQString  iptcCopyright;
};

class MetadataHub
{
public:

    /**
        The status enum describes the result of joining several metadata sets.
        If only one set has been added, the status is always MetadataAvailable.
        If no set has been added, the status is always MetadataInvalid
    */
    enum Status
    {
        MetadataInvalid,   /// not yet filled with any value
        MetadataAvailable, /// only one data set has been added, or a common value is available
        MetadataDisjoint   /// No common value is available. For rating and dates, the interval is available.
    };

    /**
        Describes the complete status of a Tag: The metadata status, and the fact if it has the tag or not.
    */
    class TagStatus
    {
        public:
            TagStatus(Status status, bool hasTag = false) : status(status), hasTag(hasTag) {};
            TagStatus() : status(MetadataInvalid), hasTag(false) {};

            Status status;
            bool   hasTag;

            bool operator==(TagStatus otherstatus)
            {
                return otherstatus.status == status &&
                        otherstatus.hasTag == hasTag;
            }
            bool operator==(Status otherstatus) { return otherstatus == status; }
    };

    enum DatabaseMode
    {
        /**
            Use this mode if
                - the album manager is not available and/or
                - metadata sets may contain tags that are not available from the AlbumManager
            This situation occurs if new tags are imported from IPTC keywords.
            This means that the album manager is not accessed, all methods depending on TAlbum*
            (tags(), tagIDs(), setTag()) shall not be used.
            The method write(ImageInfo*) will create not yet existing tags in the database.
        */
        NewTagsImport,
        /**
            Use this mode if all tags are available from the AlbumManager.
            This situation occurs if you load from ImageInfo objects.
            All methods can be used.
        */
        ManagedTags
    };

    enum WriteMode
    {
        /**
            Write all available information
        */
        FullWrite,
        /**
            Do a full write if and only if
                - metadata fields changed
                - the changed fields shall be written according to write settings
            "Changed" in this context means changed by one of the set... methods,
            the load() methods are ignored for this attribute.
            This mode allows to avoid write operations when e.g. the user does not want
            keywords to be written and only changes keywords.
        */
        FullWriteIfChanged,
        /**
            Write only the changed parts.
            Metadata fields which cannot be changed from MetadataHub (photographer ID etc.)
            will never be written
        */
        PartialWrite
    };

    /**
        Constructs a MetadataHub.
        @param dbmode Determines if the database may be accessed or not. See the enum description above.
    */
    MetadataHub(DatabaseMode dbmode = ManagedTags);
    ~MetadataHub();
    MetadataHub &operator=(const MetadataHub &);
    MetadataHub(const MetadataHub &);

    void reset();

    // --------------------------------------------------

    /**
        Add metadata information contained in the ImageInfo object.
        This method (or in combination with the other load methods)
        can be called multiple times on the same MetadataHub object.
        In this case, the metadata will be combined.
    */
    void load(ImageInfo *info);

    /**
        Add metadata information from the DMetadata object
    */
    void load(const DMetadata &metadata);

    /**
        Load metadata information from the given file.
        (Uses DMetadata, TQFileInfo)
        @returns True if the metadata could be loaded
    */
    bool load(const TQString &filePath);

    // --------------------------------------------------

    /**
        Applies the set of metadata contained in this MetadataHub
        to the given ImageInfo object.
        @return Returns true if the info object has been changed
    */
    bool write(ImageInfo *info, WriteMode writeMode = FullWrite);

    /**
        Applies the set of metadata contained in this MetadataHub
        to the given DMetadata object.
        The MetadataWriteSettings determine whether data is actually
        set or not.
        The following metadata fields may be set (depending on settings):
        - Comment
        - Date
        - Rating
        - Tags
        - Photographer ID (data from settings)
        - Credits (data from settings)

        The data fields taken from this MetadataHub object are only set if
        their status is MetadataAvailable.
        If the status is MetadataInvalid or MetadataDisjoint, the respective
        metadata field is not touched.
        @return Returns true if the metadata object has been touched
    */
    bool write(DMetadata &metadata, WriteMode writeMode = FullWrite,
               const MetadataWriteSettings &settings = defaultWriteSettings());

    /**
        Constructs a DMetadata object for given filePath,
        calls the above method, writes the changes out to the file,
        and notifies the ImageAttributesWatch.
        @return Returns if the file has been touched
    */
    bool write(const TQString &filePath, WriteMode writeMode = FullWrite,
               const MetadataWriteSettings &settings = defaultWriteSettings());

    /**
        Constructs a DMetadata object from the metadata stored in the given DImg object,
        calls the above method, and changes the stored metadata in the DImg object.
        @return Returns if the DImg object has been touched
    */
    bool write(DImg &image, WriteMode writeMode = FullWrite,
               const MetadataWriteSettings &settings = defaultWriteSettings());

    /**
        Constructs a MetadataWriteSettings object from the global AlbumSettings object.
    */
    static MetadataWriteSettings defaultWriteSettings();

    // --------------------------------------------------

    Status dateTimeStatus() const;
    Status commentStatus() const;
    Status ratingStatus() const;

    TagStatus tagStatus(TAlbum *album) const;
    TagStatus tagStatus(int albumId) const;
    TagStatus tagStatus(const TQString &tagPath) const;

    /**
        Returns if the metadata field has been changed
        with the corresponding set... method
    */
    bool dateTimeChanged() const;
    bool commentChanged() const;
    bool ratingChanged() const;
    bool tagsChanged() const;

    /**
        Returns the dateTime.
        If status is MetadataDisjoint, the earliest date is returned.
                                       (see dateTimeInterval())
        If status is MetadataInvalid, an invalid date is returned.
    */
    TQDateTime           dateTime() const;
    /**
        Returns the dateTime.
        If status is MetadataDisjoint, the first loaded comment is returned.
        If status is MetadataInvalid, TQString() is returned.
    */
    TQString             comment() const;
    /**
        Returns the rating.
        If status is MetadataDisjoint, the lowest rating is returned.
                                       (see ratingInterval())
        If status is MetadataInvalid, -1 is returned.
    */
    int                 rating() const;

    /**
        Returns the earliest and latest date.
        If status is MetadataAvailable, the values are the same.
        If status is MetadataInvalid, invalid dates are returned.
    */
    void                dateTimeInterval(TQDateTime &lowest, TQDateTime &highest) const;
    /**
        Returns the lowest and highest rating.
        If status is MetadataAvailable, the values are the same.
        If status is MetadataInvalid, -1 is returned.
    */
    void                ratingInterval(int &lowest, int &highest) const;

    /**
        Returns a TQStringList with all tags with status MetadataAvailable.
        (i.e., the intersection of tags from all loaded metadata sets)
    */
    TQStringList         keywords() const;

    /**
        Returns a map with the status for each tag.
        Tags not contained in the list are considered to have the status MetadataInvalid,
        that means no loaded metadata set contained this tag.
        If a tag in the map has the status MetadataAvailable and it has the tag,
        all loaded sets contained the tag.
        If a tag in the map has the status MetadataAvailable and it does not have the tag,
        no loaded sets contains this tag (has been explicitly set so)
        If a tag in the map has the status MetadataDisjoint, some but not all loaded
        sets contained the tag. The hasTag value is true then.
        If MapMode (set in constructor) is false, returns an empty map.
    */
    TQMap<TAlbum *, TagStatus> tags() const;
    /**
        Similar to the method above.
        This method is less efficient internally.
    */
    TQMap<int, TagStatus>   tagIDs() const;

    // --------------------------------------------------

    /**
        Set dateTime to the given value, and the dateTime status to MetadataAvailable
    */
    void setDateTime(const TQDateTime &dateTime, Status status = MetadataAvailable);
    void setComment(const TQString &comment, Status status = MetadataAvailable);
    void setRating(int rating, Status status = MetadataAvailable);
    void setTag(TAlbum *tag, bool hasTag, Status status = MetadataAvailable);
    void setTag(int albumID, bool hasTag, Status status = MetadataAvailable);

    /**
        Resets the information that metadata fields have been changed with one of the
        set... methods (see commentChanged, dateTimeChanged etc.)
    */
    void resetChanged();

private:

    void load(const TQDateTime &dateTime, const TQString &comment, int rating);
    void loadTags(const TQValueList<TAlbum *> &loadedTags);
    void loadTags(const TQStringList &loadedTagPaths);
    bool needWriteMetadata(WriteMode writeMode, const MetadataWriteSettings &settings) const;

private:

    MetadataHubPriv *d;
};

} // namespace Digikam

#endif // METADATAHUB_H