File indexing completed on 2024-04-28 15:39:57

0001 // SPDX-FileCopyrightText: 2003-2012 Jesper K. Pedersen <jesper.pedersen@kdab.com>
0002 // SPDX-FileCopyrightText: 2005-2007 Dirk Mueller <mueller@kde.org>
0003 // SPDX-FileCopyrightText: 2006-2008 Tuomas Suutari <tuomas@nepnep.net>
0004 // SPDX-FileCopyrightText: 2007-2008 Jan Kundrát <jkt@flaska.net>
0005 // SPDX-FileCopyrightText: 2008 Henner Zeller <h.zeller@acm.org>
0006 // SPDX-FileCopyrightText: 2010 Wes Hardaker <kpa@capturedonearth.com>
0007 // SPDX-FileCopyrightText: 2012 Miika Turkia <miika.turkia@gmail.com>
0008 // SPDX-FileCopyrightText: 2013-2023 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
0009 // SPDX-FileCopyrightText: 2014-2019 Tobias Leupold <tl@stonemx.de>
0010 // SPDX-FileCopyrightText: 2017-2020 Robert Krawitz <rlk@alum.mit.edu>
0011 //
0012 // SPDX-License-Identifier: GPL-2.0-or-later
0013 
0014 #ifndef IMAGEINFO_H
0015 #define IMAGEINFO_H
0016 
0017 #include <kpabase/config-kpa-marble.h>
0018 
0019 #include "CategoryPtr.h"
0020 #include "ExifMode.h"
0021 #include "ImageDate.h"
0022 #include "MD5.h"
0023 
0024 #ifdef HAVE_MARBLE
0025 #include <Map/GeoCoordinates.h>
0026 #endif
0027 #include <kpabase/FileName.h>
0028 #include <kpabase/StringSet.h>
0029 
0030 #include <QHash>
0031 #include <QRect>
0032 #include <QSize>
0033 #include <QString>
0034 #include <QStringList>
0035 
0036 namespace Plugins
0037 {
0038 class ImageInfo;
0039 }
0040 
0041 namespace XMLDB
0042 {
0043 class Database;
0044 }
0045 
0046 namespace DB
0047 {
0048 enum RotationMode {
0049     RotateImageInfoAndAreas,
0050     RotateImageInfoOnly
0051 };
0052 
0053 using Utilities::StringSet;
0054 class ImageDB;
0055 class MemberMap;
0056 
0057 /**
0058  * @brief The FileInformation enum controls the behaviour of the ImageInfo constructor.
0059  * Depending on the value, metadata is read from the image file and optionally the Exif database is updated.
0060  */
0061 enum class FileInformation {
0062     Ignore, ///< Do not read additional information from the image file.
0063     Read, ///< Read metadata from the image file, but do not update metadata in the Exif database.
0064     ReadAndUpdateExifDB ///< Read metadata from the image file and update the Exif database.
0065 };
0066 
0067 enum MediaType { Image = 0x01,
0068                  Video = 0x02 };
0069 constexpr MediaType anyMediaType = MediaType(Image | Video);
0070 typedef unsigned int StackID;
0071 
0072 typedef QHash<QString, QRect> PositionTags;
0073 typedef QHashIterator<QString, QRect> PositionTagsIterator;
0074 typedef QHash<QString, PositionTags> TaggedAreas;
0075 typedef QHashIterator<QString, PositionTags> TaggedAreasIterator;
0076 typedef QHash<QString, StringSet> CategoryInformation;
0077 
0078 class ImageInfo : public QSharedData
0079 {
0080 
0081 public:
0082     /**
0083      * @brief ImageInfo constructs an empty ImageInfo.
0084      * An empty imageInfo can be detected by calling \c isNull().
0085      */
0086     ImageInfo();
0087     /**
0088      * @brief ImageInfo constructor to create an ImageInfo for a file.
0089      * This constructor is typically called by the new image finder.
0090      * @param fileName
0091      * @param type
0092      * @param infoMode
0093      */
0094     explicit ImageInfo(const DB::FileName &fileName, MediaType type = Image, FileInformation infoMode = FileInformation::ReadAndUpdateExifDB);
0095     /**
0096      * @brief ImageInfo constructor including all fields.
0097      * This constructor is typically called when reading ImageInfos from the database file, or when doing an import.
0098      * @param fileName
0099      * @param label
0100      * @param description
0101      * @param date
0102      * @param angle
0103      * @param md5sum
0104      * @param size
0105      * @param type
0106      * @param rating
0107      * @param stackId
0108      * @param stackOrder
0109      */
0110     ImageInfo(const DB::FileName &fileName,
0111               const QString &label,
0112               const QString &description,
0113               const ImageDate &date,
0114               int angle,
0115               const MD5 &md5sum,
0116               const QSize &size,
0117               MediaType type,
0118               short rating = -1,
0119               StackID stackId = 0,
0120               unsigned int stackOrder = 0);
0121     ImageInfo(const ImageInfo &other);
0122 
0123     FileName fileName() const;
0124     void setFileName(const DB::FileName &relativeFileName);
0125 
0126     void setLabel(const QString &);
0127     QString label() const;
0128 
0129     void setDescription(const QString &);
0130     QString description() const;
0131 
0132     void setDate(const ImageDate &);
0133     ImageDate date() const;
0134     ImageDate &date();
0135     void readExif(const DB::FileName &fullPath, DB::ExifMode mode);
0136 
0137     void rotate(int degrees, RotationMode mode = RotateImageInfoAndAreas);
0138     int angle() const;
0139     void setAngle(int angle);
0140 
0141     short rating() const;
0142     void setRating(short rating);
0143 
0144     bool isStacked() const { return m_stackId != 0; }
0145     StackID stackId() const;
0146 
0147     unsigned int stackOrder() const;
0148     void setStackOrder(const unsigned int stackOrder);
0149 
0150     void setVideoLength(int seconds);
0151     int videoLength() const;
0152 
0153     void setCategoryInfo(const QString &key, const StringSet &value);
0154     void addCategoryInfo(const QString &category, const StringSet &values);
0155     /**
0156      * Enable a tag within a category for this image.
0157      * Optionally, the tag's position can be given (for positionable categories).
0158      * @param category the category name
0159      * @param value the tag name
0160      * @param area the image region that the tag applies to.
0161      */
0162     void addCategoryInfo(const QString &category, const QString &value, const QRect &area = QRect());
0163     void clearAllCategoryInfo();
0164     void removeCategoryInfo(const QString &category, const StringSet &values);
0165     void removeCategoryInfo(const QString &category, const QString &value);
0166     /**
0167      * Set the tagged areas for the image.
0168      * It is assumed that the positioned tags have already been set to the ImageInfo
0169      * using one of the functions <code>setCategoryInfo</code> or <code>addCategoryInfo</code>.
0170      *
0171      * @param category the category name.
0172      * @param positionedTags a mapping of tag names to image areas.
0173      */
0174     void setPositionedTags(const QString &category, const PositionTags &positionedTags);
0175 
0176     bool hasCategoryInfo(const QString &key, const QString &value) const;
0177     bool hasCategoryInfo(const QString &key, const StringSet &values) const;
0178 
0179     QStringList availableCategories() const;
0180     StringSet itemsOfCategory(const QString &category) const;
0181     void renameItem(const QString &key, const QString &oldValue, const QString &newValue);
0182     void renameCategory(const QString &oldName, const QString &newName);
0183 
0184     bool operator!=(const ImageInfo &other) const;
0185     bool operator==(const ImageInfo &other) const;
0186     ImageInfo &operator=(const ImageInfo &other);
0187 
0188     static bool imageOnDisk(const DB::FileName &fileName);
0189 
0190     const MD5 &MD5Sum() const { return m_md5sum; }
0191     void setMD5Sum(const MD5 &sum, bool storeEXIF = true);
0192 
0193     void setLocked(bool);
0194     bool isLocked() const;
0195 
0196     bool isNull() const { return m_null; }
0197     QSize size() const;
0198     void setSize(const QSize &size);
0199 
0200     MediaType mediaType() const;
0201     void setMediaType(MediaType type)
0202     {
0203         if (type != m_type)
0204             m_dirty = true;
0205         m_type = type;
0206     }
0207     bool isVideo() const;
0208 
0209     void createFolderCategoryItem(DB::CategoryPtr, DB::MemberMap &memberMap);
0210 
0211     void copyExtraData(const ImageInfo &from, bool copyAngle = true);
0212     void removeExtraData();
0213     /**
0214      * Merge another ImageInfo into this one.
0215      * The other ImageInfo is not altered in any way or removed.
0216      */
0217     void merge(const ImageInfo &other);
0218 
0219     TaggedAreas taggedAreas() const;
0220     /**
0221      * Return the area associated with a tag.
0222      * @param category the category name
0223      * @param tag the tag name
0224      * @return the associated area, or <code>QRect()</code> if no association exists.
0225      */
0226     QRect areaForTag(QString category, QString tag) const;
0227     void setIsMatched(bool isMatched);
0228     bool isMatched() const;
0229     void setMatchGeneration(int matchGeneration);
0230     int matchGeneration() const;
0231 #ifdef HAVE_MARBLE
0232     Map::GeoCoordinates coordinates() const;
0233 #endif
0234 
0235 protected:
0236     void setIsNull(bool b)
0237     {
0238         m_null = b;
0239     }
0240     bool isDirty() const
0241     {
0242         return m_dirty;
0243     }
0244     void markDirty();
0245     bool updateDateInformation(int mode) const;
0246 
0247     void setStackId(const StackID stackId);
0248     friend class XMLDB::Database;
0249     friend class DB::ImageDB;
0250 
0251 private:
0252     DB::FileName m_fileName;
0253     QString m_label;
0254     QString m_description;
0255     ImageDate m_date;
0256     CategoryInformation m_categoryInfomation;
0257     TaggedAreas m_taggedAreas;
0258     int m_angle;
0259     enum OnDisk { YesOnDisk,
0260                   NoNotOnDisk,
0261                   Unchecked };
0262     mutable OnDisk m_imageOnDisk = OnDisk::Unchecked;
0263     MD5 m_md5sum;
0264     bool m_null = true;
0265     QSize m_size;
0266     MediaType m_type;
0267     short m_rating;
0268     StackID m_stackId;
0269     unsigned int m_stackOrder;
0270     int m_videoLength;
0271     bool m_isMatched = false;
0272     int m_matchGeneration;
0273 #ifdef HAVE_MARBLE
0274     mutable Map::GeoCoordinates m_coordinates;
0275     mutable bool m_coordsIsSet = false;
0276 #endif
0277 
0278     // Cache information
0279     bool m_locked = false;
0280 
0281     // Will be set to true after every change
0282     bool m_dirty = false;
0283 };
0284 }
0285 
0286 #endif /* IMAGEINFO_H */
0287 
0288 // vi:expandtab:tabstop=4 shiftwidth=4: