1 /* SPDX-FileCopyrightText: 2003-2020 The KPhotoAlbum Development Team 2 3 SPDX-License-Identifier: GPL-2.0-or-later 4 */ 5 6 #ifndef IMAGEINFO_H 7 #define IMAGEINFO_H 8 9 #include <kpabase/config-kpa-marble.h> 10 11 #include "CategoryPtr.h" 12 #include "ExifMode.h" 13 #include "ImageDate.h" 14 #include "MD5.h" 15 16 #ifdef HAVE_MARBLE 17 #include <Map/GeoCoordinates.h> 18 #endif 19 #include <kpabase/FileName.h> 20 #include <kpabase/StringSet.h> 21 22 #include <QHash> 23 #include <QRect> 24 #include <QSize> 25 #include <QString> 26 #include <QStringList> 27 28 namespace Plugins 29 { 30 class ImageInfo; 31 } 32 33 namespace XMLDB 34 { 35 class Database; 36 } 37 38 namespace DB 39 { 40 enum RotationMode { 41 RotateImageInfoAndAreas, 42 RotateImageInfoOnly 43 }; 44 45 using Utilities::StringSet; 46 class MemberMap; 47 48 /** 49 * @brief The FileInformation enum controls the behaviour of the ImageInfo constructor. 50 * Depending on the value, metadata is read from the image file and optionally the Exif database is updated. 51 */ 52 enum class FileInformation { 53 Ignore, ///< Do not read additional information from the image file. 54 Read, ///< Read metadata from the image file, but do not update metadata in the Exif database. 55 ReadAndUpdateExifDB ///< Read metadata from the image file and update the Exif database. 56 }; 57 58 enum MediaType { Image = 0x01, 59 Video = 0x02 }; 60 const MediaType anyMediaType = MediaType(Image | Video); 61 typedef unsigned int StackID; 62 63 typedef QHash<QString, QRect> PositionTags; 64 typedef QHashIterator<QString, QRect> PositionTagsIterator; 65 typedef QHash<QString, PositionTags> TaggedAreas; 66 typedef QHashIterator<QString, PositionTags> TaggedAreasIterator; 67 typedef QHash<QString, StringSet> CategoryInformation; 68 69 class ImageInfo : public QSharedData 70 { 71 72 public: 73 /** 74 * @brief ImageInfo constructs an empty ImageInfo. 75 * An empty imageInfo can be detected by calling \c isNull(). 76 */ 77 ImageInfo(); 78 /** 79 * @brief ImageInfo constructor to create an ImageInfo for a file. 80 * This constructor is typically called by the new image finder. 81 * @param fileName 82 * @param type 83 * @param infoMode 84 */ 85 explicit ImageInfo(const DB::FileName &fileName, MediaType type = Image, FileInformation infoMode = FileInformation::ReadAndUpdateExifDB); 86 /** 87 * @brief ImageInfo constructor including all fields. 88 * This constructor is typically called when reading ImageInfos from the database file, or when doing an import. 89 * @param fileName 90 * @param label 91 * @param description 92 * @param date 93 * @param angle 94 * @param md5sum 95 * @param size 96 * @param type 97 * @param rating 98 * @param stackId 99 * @param stackOrder 100 */ 101 ImageInfo(const DB::FileName &fileName, 102 const QString &label, 103 const QString &description, 104 const ImageDate &date, 105 int angle, 106 const MD5 &md5sum, 107 const QSize &size, 108 MediaType type, 109 short rating = -1, 110 StackID stackId = 0, 111 unsigned int stackOrder = 0); 112 ImageInfo(const ImageInfo &other); 113 114 FileName fileName() const; 115 void setFileName(const DB::FileName &relativeFileName); 116 117 void setLabel(const QString &); 118 QString label() const; 119 120 void setDescription(const QString &); 121 QString description() const; 122 123 void setDate(const ImageDate &); 124 ImageDate date() const; 125 ImageDate &date(); 126 void readExif(const DB::FileName &fullPath, DB::ExifMode mode); 127 128 void rotate(int degrees, RotationMode mode = RotateImageInfoAndAreas); 129 int angle() const; 130 void setAngle(int angle); 131 132 short rating() const; 133 void setRating(short rating); 134 isStacked()135 bool isStacked() const { return m_stackId != 0; } 136 StackID stackId() const; 137 138 unsigned int stackOrder() const; 139 void setStackOrder(const unsigned int stackOrder); 140 141 void setVideoLength(int seconds); 142 int videoLength() const; 143 144 void setCategoryInfo(const QString &key, const StringSet &value); 145 void addCategoryInfo(const QString &category, const StringSet &values); 146 /** 147 * Enable a tag within a category for this image. 148 * Optionally, the tag's position can be given (for positionable categories). 149 * @param category the category name 150 * @param value the tag name 151 * @param area the image region that the tag applies to. 152 */ 153 void addCategoryInfo(const QString &category, const QString &value, const QRect &area = QRect()); 154 void clearAllCategoryInfo(); 155 void removeCategoryInfo(const QString &category, const StringSet &values); 156 void removeCategoryInfo(const QString &category, const QString &value); 157 /** 158 * Set the tagged areas for the image. 159 * It is assumed that the positioned tags have already been set to the ImageInfo 160 * using one of the functions <code>setCategoryInfo</code> or <code>addCategoryInfo</code>. 161 * 162 * @param category the category name. 163 * @param positionedTags a mapping of tag names to image areas. 164 */ 165 void setPositionedTags(const QString &category, const PositionTags &positionedTags); 166 167 bool hasCategoryInfo(const QString &key, const QString &value) const; 168 bool hasCategoryInfo(const QString &key, const StringSet &values) const; 169 170 QStringList availableCategories() const; 171 StringSet itemsOfCategory(const QString &category) const; 172 void renameItem(const QString &key, const QString &oldValue, const QString &newValue); 173 void renameCategory(const QString &oldName, const QString &newName); 174 175 bool operator!=(const ImageInfo &other) const; 176 bool operator==(const ImageInfo &other) const; 177 ImageInfo &operator=(const ImageInfo &other); 178 179 static bool imageOnDisk(const DB::FileName &fileName); 180 MD5Sum()181 const MD5 &MD5Sum() const { return m_md5sum; } 182 void setMD5Sum(const MD5 &sum, bool storeEXIF = true); 183 184 void setLocked(bool); 185 bool isLocked() const; 186 isNull()187 bool isNull() const { return m_null; } 188 QSize size() const; 189 void setSize(const QSize &size); 190 191 MediaType mediaType() const; setMediaType(MediaType type)192 void setMediaType(MediaType type) 193 { 194 if (type != m_type) 195 m_dirty = true; 196 m_type = type; 197 } 198 bool isVideo() const; 199 200 void createFolderCategoryItem(DB::CategoryPtr, DB::MemberMap &memberMap); 201 202 void copyExtraData(const ImageInfo &from, bool copyAngle = true); 203 void removeExtraData(); 204 /** 205 * Merge another ImageInfo into this one. 206 * The other ImageInfo is not altered in any way or removed. 207 */ 208 void merge(const ImageInfo &other); 209 210 TaggedAreas taggedAreas() const; 211 /** 212 * Return the area associated with a tag. 213 * @param category the category name 214 * @param tag the tag name 215 * @return the associated area, or <code>QRect()</code> if no association exists. 216 */ 217 QRect areaForTag(QString category, QString tag) const; 218 void setIsMatched(bool isMatched); 219 bool isMatched() const; 220 void setMatchGeneration(int matchGeneration); 221 int matchGeneration() const; 222 #ifdef HAVE_MARBLE 223 Map::GeoCoordinates coordinates() const; 224 #endif 225 226 protected: setIsNull(bool b)227 void setIsNull(bool b) { m_null = b; } isDirty()228 bool isDirty() const { return m_dirty; } 229 void markDirty(); 230 bool updateDateInformation(int mode) const; 231 232 void setStackId(const StackID stackId); 233 friend class XMLDB::Database; 234 235 private: 236 DB::FileName m_fileName; 237 QString m_label; 238 QString m_description; 239 ImageDate m_date; 240 CategoryInformation m_categoryInfomation; 241 TaggedAreas m_taggedAreas; 242 int m_angle; 243 enum OnDisk { YesOnDisk, 244 NoNotOnDisk, 245 Unchecked }; 246 mutable OnDisk m_imageOnDisk; 247 MD5 m_md5sum; 248 bool m_null; 249 QSize m_size; 250 MediaType m_type; 251 short m_rating; 252 StackID m_stackId; 253 unsigned int m_stackOrder; 254 int m_videoLength; 255 bool m_isMatched; 256 int m_matchGeneration; 257 #ifdef HAVE_MARBLE 258 mutable Map::GeoCoordinates m_coordinates; 259 mutable bool m_coordsIsSet = false; 260 #endif 261 262 // Cache information 263 bool m_locked; 264 265 // Will be set to true after every change 266 bool m_dirty; 267 }; 268 } 269 270 #endif /* IMAGEINFO_H */ 271 272 // vi:expandtab:tabstop=4 shiftwidth=4: 273