1 /* ============================================================ 2 * 3 * This file is a part of digiKam project 4 * https://www.digikam.org 5 * 6 * Date : 2015-08-17 7 * Description : Helper class for Image Description Editor Tab 8 * 9 * Copyright (C) 2015 by Veaceslav Munteanu <veaceslav dot munteanu90 at gmail dot com> 10 * 11 * This program is free software; you can redistribute it 12 * and/or modify it under the terms of the GNU General 13 * Public License as published by the Free Software Foundation; 14 * either version 2, or (at your option) 15 * any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * ============================================================ */ 23 24 #ifndef DIGIKAM_DISJOINT_METADATA_H 25 #define DIGIKAM_DISJOINT_METADATA_H 26 27 // Qt includes 28 29 #include <QString> 30 #include <QMap> 31 #include <QObject> 32 #include <QDateTime> 33 34 // Local includes 35 36 #include "disjointmetadatadatafields.h" 37 #include "metaenginesettings.h" 38 39 namespace Digikam 40 { 41 42 class ItemInfo; 43 class CaptionsMap; 44 class Template; 45 46 class DisjointMetadata : public QObject 47 { 48 Q_OBJECT 49 50 public: 51 52 enum WriteMode 53 { 54 /** 55 * Write all available information 56 */ 57 FullWrite, 58 59 /** 60 * Do a full write if and only if 61 * - metadata fields changed 62 * - the changed fields shall be written according to write settings 63 * "Changed" in this context means changed by one of the set... methods, 64 * the load() methods are ignored for this attribute. 65 * This mode allows to avoid write operations when e.g. the user does not want 66 * keywords to be written and only changes keywords. 67 */ 68 FullWriteIfChanged, 69 70 /** 71 * Write only the changed parts. 72 * Metadata fields which cannot be changed from MetadataHub (photographer ID etc.) 73 * will never be written 74 */ 75 PartialWrite 76 }; 77 78 public: 79 80 DisjointMetadata(); 81 ~DisjointMetadata() override; 82 83 84 DisjointMetadataDataFields dataFields() const; 85 void setDataFields(const DisjointMetadataDataFields& data); 86 87 void reset(); 88 89 void load(const ItemInfo& info); 90 91 //@{ 92 93 /** 94 * Returnsthe metadata field Status. 95 */ 96 DisjointMetadataDataFields::Status dateTimeStatus() const; 97 DisjointMetadataDataFields::Status titlesStatus() const; 98 DisjointMetadataDataFields::Status commentsStatus() const; 99 DisjointMetadataDataFields::Status pickLabelStatus() const; 100 DisjointMetadataDataFields::Status colorLabelStatus() const; 101 DisjointMetadataDataFields::Status ratingStatus() const; 102 DisjointMetadataDataFields::Status templateStatus() const; 103 104 DisjointMetadataDataFields::Status tagStatus(int albumId) const; 105 DisjointMetadataDataFields::Status tagStatus(const QString& tagPath) const; 106 107 //@} 108 109 //@{ 110 111 /** 112 * Returns if the metadata field has been changed 113 * with the corresponding setter method. 114 */ 115 bool dateTimeChanged() const; 116 bool titlesChanged() const; 117 bool commentsChanged() const; 118 bool pickLabelChanged() const; 119 bool colorLabelChanged() const; 120 bool ratingChanged() const; 121 bool templateChanged() const; 122 bool tagsChanged() const; 123 124 //@} 125 126 //@{ 127 128 /** 129 * Set metadata field to the given value, 130 * and the metadata field status to the corresponding DisjointMetadataDataFields::MetadataAvailable. 131 */ 132 void setDateTime(const QDateTime& dateTime, 133 DisjointMetadataDataFields::Status status = DisjointMetadataDataFields::MetadataAvailable); 134 void setTitles(const CaptionsMap& titles, 135 DisjointMetadataDataFields::Status status = DisjointMetadataDataFields::MetadataAvailable); 136 void setComments(const CaptionsMap& comments, 137 DisjointMetadataDataFields::Status status = DisjointMetadataDataFields::MetadataAvailable); 138 void setPickLabel(int pickId, 139 DisjointMetadataDataFields::Status status = DisjointMetadataDataFields::MetadataAvailable); 140 void setColorLabel(int colorId, 141 DisjointMetadataDataFields::Status status = DisjointMetadataDataFields::MetadataAvailable); 142 void setRating(int rating, 143 DisjointMetadataDataFields::Status status = DisjointMetadataDataFields::MetadataAvailable); 144 void setMetadataTemplate(const Template& t, 145 DisjointMetadataDataFields::Status status = DisjointMetadataDataFields::MetadataAvailable); 146 void setTag(int albumID, 147 DisjointMetadataDataFields::Status status = DisjointMetadataDataFields::MetadataAvailable); 148 149 //@} 150 151 /** 152 * Returns the dateTime. 153 * If status is DisjointMetadataDataFields::MetadataDisjoint, the earliest date is returned. 154 * (see dateTimeInterval()) 155 * If status is DisjointMetadataDataFields::MetadataInvalid, an invalid date is returned. 156 */ 157 QDateTime dateTime() const; 158 159 /** 160 * Returns a map all alternate language titles. 161 * If status is DisjointMetadataDataFields::MetadataDisjoint, the first loaded map is returned. 162 * If status is DisjointMetadataDataFields::MetadataInvalid, CaptionMap() is returned. 163 */ 164 CaptionsMap titles() const; 165 166 /** 167 * Returns a map all alternate language omments . 168 * If status is DisjointMetadataDataFields::MetadataDisjoint, the first loaded map is returned. 169 * If status is DisjointMetadataDataFields::MetadataInvalid, CaptionMap() is returned. 170 */ 171 CaptionsMap comments() const; 172 173 /** 174 * Returns the Pick Label id (see PickLabel values in globals.h). 175 * If status is DisjointMetadataDataFields::MetadataDisjoint, the None Label is returned. 176 * (see pickLabelInterval()) 177 * If status is DisjointMetadataDataFields::MetadataInvalid, -1 is returned. 178 */ 179 int pickLabel() const; 180 181 /** 182 * Returns the Color Label id (see ColorLabel values in globals.h). 183 * If status is DisjointMetadataDataFields::MetadataDisjoint, the None Label is returned. 184 * (see colorLabelInterval()) 185 * If status is DisjointMetadataDataFields::MetadataInvalid, -1 is returned. 186 */ 187 int colorLabel() const; 188 189 /** 190 * Returns the rating. 191 * If status is DisjointMetadataDataFields::MetadataDisjoint, the lowest rating is returned. 192 * (see ratingInterval()) 193 * If status is DisjointMetadataDataFields::MetadataInvalid, -1 is returned. 194 */ 195 int rating() const; 196 197 /** 198 * Returns the metadata template. 199 * If status is DisjointMetadataDataFields::MetadataDisjoint, the first loaded template is returned. 200 * If status is DisjointMetadataDataFields::MetadataInvalid, 0 is returned. 201 */ 202 Template metadataTemplate() const; 203 204 /** 205 * Returns the earliest and latest date. 206 * If status is DisjointMetadataDataFields::MetadataAvailable, the values are the same. 207 * If status is DisjointMetadataDataFields::MetadataInvalid, invalid dates are returned. 208 */ 209 void dateTimeInterval(QDateTime& lowest, 210 QDateTime& highest) const; 211 212 /** 213 * Returns the lowest and highest Pick Label id (see PickLabel values from globals.h). 214 * If status is DisjointMetadataDataFields::MetadataAvailable, the values are the same. 215 * If status is DisjointMetadataDataFields::MetadataInvalid, -1 is returned. 216 */ 217 void pickLabelInterval(int& lowest, 218 int& highest) const; 219 220 /** 221 * Returns the lowest and highest Color Label id (see ColorLabel values from globals.h). 222 * If status is DisjointMetadataDataFields::MetadataAvailable, the values are the same. 223 * If status is DisjointMetadataDataFields::MetadataInvalid, -1 is returned. 224 */ 225 void colorLabelInterval(int& lowest, 226 int& highest) const; 227 228 /** 229 * Returns the lowest and highest rating. 230 * If status is DisjointMetadataDataFields::MetadataAvailable, the values are the same. 231 * If status is DisjointMetadataDataFields::MetadataInvalid, -1 is returned. 232 */ 233 void ratingInterval(int& lowest, 234 int& highest) const; 235 236 /** 237 * Returns a QStringList with all tags with status DisjointMetadataDataFields::MetadataAvailable. 238 * (i.e., the intersection of tags from all loaded metadata sets) 239 */ 240 QStringList keywords() const; 241 242 /** 243 * Returns a map with the status for each tag. 244 * Any tag that was set on one of the loaded images is contained in the map. 245 * (If a tag is not contained in the map, it was not set on any of the loaded images) 246 * If the tag was set on all loaded images, the status is DisjointMetadataDataFields::MetadataAvailable. 247 * If the tag was set on at least one, but not all of the loaded images, the status is DisjointMetadataDataFields::MetadataDisjoint. 248 */ 249 QMap<int, DisjointMetadataDataFields::Status> tags() const; 250 251 void resetChanged(); 252 253 /** 254 * Applies the set of metadata contained in this MetadataHub 255 * to the given ItemInfo object. 256 * @return Returns true if the info object has been changed 257 */ 258 bool write(ItemInfo info, WriteMode writeMode = FullWrite); 259 260 /** 261 * With the currently applied changes, the given writeMode and settings, 262 * returns if write(DMetadata), write(QString) or write(DImg) will actually 263 * apply any changes. 264 */ 265 bool willWriteMetadata(WriteMode writeMode, 266 const MetaEngineSettingsContainer& settings = 267 MetaEngineSettings::instance()->settings()) const; 268 269 /** 270 * @brief changedFlags - used for selective metadata write. The result will be passed to metadatahub and it will 271 * - write it to disk 272 * @return - metadatahub flags encoded as int 273 */ 274 int changedFlags(); 275 276 private Q_SLOTS: 277 278 void slotTagDeleted(int tagId); 279 void slotInvalidate(); 280 281 private: 282 283 void load(const QDateTime& dateTime, 284 const CaptionsMap& titles, 285 const CaptionsMap& comment, 286 int colorLabel, int pickLabel, 287 int rating, const Template& t); 288 289 void loadTags(const QList<int>& tagIds); 290 void notifyTagDeleted(int id); 291 void applyChangeNotifications(); 292 293 private: 294 295 // Disable 296 explicit DisjointMetadata(QObject*) = delete; 297 298 // Disable copy constructor and operator to prevent potential slicing with this class, reported by Clazy static analyzer. 299 // https://github.com/KDE/clazy/blob/master/docs/checks/README-copyable-polymorphic.md 300 // Use DisjointMetadataDataFields container setter and getter instead. 301 // TODO: remove legacy implementations for these methods later if no side effect. 302 DisjointMetadata(const DisjointMetadata& other); 303 DisjointMetadata& operator=(const DisjointMetadata& other); 304 305 private: 306 307 class Private; 308 Private* d; 309 }; 310 311 } // namespace Digikam 312 313 #endif // DIGIKAM_DISJOINT_METADATA_H 314