File indexing completed on 2025-01-19 03:56:00

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2006-09-15
0007  * Description : Exiv2 library interface
0008  *               Exiv2: https://www.exiv2.org
0009  *               Exif : https://www.exif.org/Exif2-2.PDF
0010  *               Iptc : https://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf
0011  *               Xmp  : https://www.adobe.com/devnet/xmp/pdfs/xmp_specification.pdf
0012  *                      https://www.iptc.org/std/Iptc4xmpCore/1.0/specification/Iptc4xmpCore_1.0-spec-XMPSchema_8.pdf
0013  *               Paper: www.metadataworkinggroup.com/pdf/mwg_guidance.pdf
0014  *
0015  * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0016  * SPDX-FileCopyrightText: 2006-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0017  *
0018  * SPDX-License-Identifier: GPL-2.0-or-later
0019  *
0020  * ============================================================ */
0021 
0022 #ifndef DIGIKAM_META_ENGINE_H
0023 #define DIGIKAM_META_ENGINE_H
0024 
0025 // QT includes
0026 
0027 #include <QByteArray>
0028 #include <QString>
0029 #include <QDateTime>
0030 #include <QMap>
0031 #include <QSharedDataPointer>
0032 #include <QStringList>
0033 #include <QVariant>
0034 #include <QRegularExpression>
0035 #include <QUrl>
0036 #include <QImage>
0037 
0038 // Local includes
0039 
0040 #include "metaengine_data.h"
0041 #include "digikam_export.h"
0042 
0043 namespace Digikam
0044 {
0045 
0046 // TODO: merge with DMetadata class.
0047 
0048 class DIGIKAM_EXPORT MetaEngine
0049 {
0050 
0051 public:
0052 
0053     /**
0054      * The item metadata writing mode, between item file metadata and XMP sidecar file, depending on the context.
0055      * @sa MetadataWritingMode(), metadataWritingMode()
0056      */
0057     enum MetadataWritingMode
0058     {
0059         /// Write metadata to item file only.
0060         WRITE_TO_FILE_ONLY                        = 0,
0061 
0062         /// Write metadata to sidecar file only.
0063         WRITE_TO_SIDECAR_ONLY                     = 1,
0064 
0065         /// Write metadata to item and sidecar files.
0066         WRITE_TO_SIDECAR_AND_FILE                 = 2,
0067 
0068         /// Write metadata to sidecar file only for read only items such as RAW files for example.
0069         WRITE_TO_SIDECAR_ONLY_FOR_READ_ONLY_FILES = 3
0070     };
0071 
0072     /**
0073      * The item color workspace values given by Exif metadata.
0074      */
0075     enum ImageColorWorkSpace
0076     {
0077         WORKSPACE_UNSPECIFIED  = 0,
0078         WORKSPACE_SRGB         = 1,
0079         WORKSPACE_ADOBERGB     = 2,
0080         WORKSPACE_UNCALIBRATED = 65535
0081     };
0082 
0083     /**
0084      * The item orientation values given by Exif metadata.
0085      */
0086     enum ImageOrientation
0087     {
0088         ORIENTATION_UNSPECIFIED  = 0,
0089         ORIENTATION_NORMAL       = 1,
0090         ORIENTATION_HFLIP        = 2,
0091         ORIENTATION_ROT_180      = 3,
0092         ORIENTATION_VFLIP        = 4,
0093         ORIENTATION_ROT_90_HFLIP = 5,
0094         ORIENTATION_ROT_90       = 6,
0095         ORIENTATION_ROT_90_VFLIP = 7,
0096         ORIENTATION_ROT_270      = 8
0097     };
0098 
0099     /**
0100      * Xmp tag types, used by setXmpTag, only first three types are used
0101      */
0102     enum XmpTagType
0103     {
0104         NormalTag    = 0,
0105         ArrayBagTag  = 1,
0106         StructureTag = 2,
0107         ArrayLangTag = 3,
0108         ArraySeqTag  = 4
0109     };
0110 
0111     /**
0112      * Metadata Backend used to populate information.
0113      */
0114     enum Backend
0115     {
0116         Exiv2Backend       = 0,   ///< Default backend used by MetaEngine.
0117         LibRawBackend,            ///< DMetadata only.
0118         LibHeifBackend,           ///< DMetadata only.
0119         ImageMagickBackend,       ///< DMetadata only.
0120         FFMpegBackend,            ///< DMetadata only.
0121         ExifToolBackend,          ///< DMetadata only.
0122         VideoMergeBackend,        ///< DMetadata only.
0123         NoBackend                 ///< No backend used (aka file cannot be read).
0124     };
0125 
0126     /**
0127      * A map used to store Tags Key and Tags Value.
0128      */
0129     typedef QMap<QString, QString> MetaDataMap;
0130 
0131     /**
0132      * A map used to store a list of Alternative Language values.
0133      * The map key is the language code following RFC3066 notation
0134      * (like "fr-FR" for French), and the map value the text.
0135      */
0136     typedef QMap<QString, QString> AltLangMap;
0137 
0138     /**
0139      * A map used to store Tags Key and a list of Tags properties :
0140      *  - name,
0141      *  - title,
0142      *  - description.
0143      */
0144     typedef QMap<QString, QStringList> TagsMap;
0145 
0146 public:
0147 
0148     /**
0149      * Standard constructor.
0150      */
0151     MetaEngine();
0152 
0153     /**
0154      * Constructor to load from parsed data.
0155      */
0156     explicit MetaEngine(const MetaEngineData& data);
0157 
0158     /**
0159      * Constructor to Load Metadata from item file.
0160      */
0161     explicit MetaEngine(const QString& filePath);
0162 
0163     /**
0164      * Standard destructor
0165      */
0166     virtual ~MetaEngine();
0167 
0168 public:
0169 
0170     //-----------------------------------------------------------------
0171     /// @name Static methods
0172     //@{
0173 
0174     /**
0175      * Return true if Exiv2 library initialization is done properly.
0176      * This method must be called before using libMetaEngine with multithreading.
0177      * It initialize several non re-entrancy code from Adobe XMP SDK, and register
0178      * a function to cleanup automatically all XMP SDK memory allocation.
0179      * See Bug #166424 for details.
0180      */
0181     static bool initializeExiv2();
0182 
0183     /**
0184      * Return true if Exiv2 library is compiled with Xmp metadata support.
0185      */
0186     static bool supportXmp();
0187 
0188     /**
0189      * Return true if Exiv2 library is compiled with JpegXL metadata support.
0190      */
0191     static bool supportJpegXL();
0192 
0193     /**
0194      * Return true if library support Base Media File Format (aka CR3, HEIF, HEIC, and AVIF).
0195      * Note: use this function only after to call initializeExiv2(), else false will always returned.
0196      * The function return true only if Exiv2 >= 0.27.4 compiled with BMFF support.
0197      */
0198     static bool supportBmff();
0199 
0200     /**
0201      * Return true if library can write metadata to typeMime file format.
0202      */
0203     static bool supportMetadataWriting(const QString& typeMime);
0204 
0205     /**
0206      * Return a string version of Exiv2 release in format "major.minor.patch"
0207      */
0208     static QString Exiv2Version();
0209 
0210     //@}
0211 
0212     //-----------------------------------------------------------------
0213     /// @name General methods
0214     //@{
0215 
0216     MetaEngineData data() const;
0217     void setData(const MetaEngineData& data);
0218 
0219     /**
0220      * Load all metadata (Exif, Iptc, Xmp, and JFIF Comments) from a byte array.
0221      * Return true if metadata have been loaded successfully from item data.
0222      */
0223     bool loadFromData(const QByteArray& imgData);
0224 
0225     /**
0226      * Load and merge metadata (Exif, Iptc and Xmp) from a byte array.
0227      * Use 'exclude' to remove Exif tags from the 'imgData' that will not be merged.
0228      * Return true if metadata have been loaded and merged successfully from item data.
0229      */
0230     bool loadFromDataAndMerge(const QByteArray& imgData, const QStringList& exclude = QStringList());
0231 
0232     /**
0233      * Return 'true' if metadata container in memory as no Comments, Exif, Iptc, and Xmp.
0234      */
0235     bool isEmpty() const;
0236 
0237     /**
0238      * Returns the pixel size of the current item. This information is read from the file,
0239      * not from the metadata. The returned QSize is valid if the MetaEngine object was _constructed_
0240      * by reading a file or item data; the information is not available when the object
0241      * was created from MetaEngineData.
0242      * Note that in the Exif or XMP metadata, there may be fields describing the item size.
0243      * These fields are not accessed by this method.
0244      * When replacing the metadata with setData(), the metadata may change; this information
0245      * always keeps referring to the file it was initially read from.
0246      */
0247     QSize getPixelSize() const;
0248 
0249     /**
0250      * Returns the mime type of this item. The information is read from the file;
0251      * see the docs for getPixelSize() to know when it is available.
0252      */
0253     QString getMimeType() const;
0254 
0255     /**
0256      * Enable or disable writing metadata operations with ExifTool.
0257      */
0258     void setWriteWithExifTool(const bool on);
0259 
0260     /**
0261      * Return true if writing metadata operations with ExifTool is enabled.
0262      */
0263     bool writeWithExifTool() const;
0264 
0265     /**
0266      * Enable or disable writing metadata operations to RAW files.
0267      * By default RAW files are untouched.
0268      */
0269     void setWriteRawFiles(const bool on);
0270 
0271     /**
0272      * Return true if writing metadata operations on RAW files is enabled.
0273      */
0274     bool writeRawFiles() const;
0275 
0276     /**
0277      * Enable or disable writing metadata operations to DNG files.
0278      */
0279     void setWriteDngFiles(const bool on);
0280 
0281     /**
0282      * Return true if writing metadata operations on DNG files is enabled.
0283      */
0284     bool writeDngFiles() const;
0285 
0286     /**
0287      * Enable or disable using XMP sidecar for reading metadata.
0288      */
0289     void setUseXMPSidecar4Reading(const bool on);
0290 
0291     /**
0292      * Return true if using XMP sidecar for reading metadata is enabled.
0293      */
0294     bool useXMPSidecar4Reading() const;
0295 
0296     /**
0297      * Enable or disable using compatible file name for sidecar files.
0298      */
0299     void setUseCompatibleFileName(const bool on);
0300 
0301     /**
0302      * Return true if using compatible file name for sidecar files.
0303      */
0304     bool useCompatibleFileName() const;
0305 
0306     /**
0307      * Set metadata writing mode.
0308      * @param mode Metadata writing mode as defined by the #MetadataWritingMode enum.
0309      * @sa MetadataWritingMode, metadataWritingMode()
0310      */
0311     void setMetadataWritingMode(const int mode);
0312 
0313     /**
0314      * Return the metadata writing mode.
0315      * @returns Metadata writing mode as defined by the #MetadataWritingMode enum.
0316      * @sa MetadataWritingMode, setMetadataWritingMode()
0317      */
0318     int metadataWritingMode() const;
0319 
0320     /**
0321      * Enable or disable file timestamp updating when metadata are saved.
0322      * By default files timestamp are untouched.
0323      */
0324     void setUpdateFileTimeStamp(bool on);
0325 
0326     /**
0327      * Return true if file timestamp is updated when metadata are saved.
0328      */
0329     bool updateFileTimeStamp() const;
0330 
0331     //@}
0332 
0333     //-------------------------------------------------------------------
0334     /// @name File I/O methods
0335     //@{
0336 
0337     /**
0338      * Set the file path of current item.
0339      */
0340     void setFilePath(const QString& path);
0341 
0342     /**
0343      * Return the file path of current item.
0344      */
0345     QString getFilePath() const;
0346 
0347     /**
0348      * Return the XMP Sidecar file path for a item file path.
0349      * If item file path do not include a file name or is empty, this function return a null string.
0350      */
0351     static QString sidecarFilePathForFile(const QString& path);
0352 
0353     /**
0354      * Like sidecarFilePathForFile(), but works for local file path.
0355      */
0356     static QString sidecarPath(const QString& path);
0357 
0358     /**
0359      * Like sidecarFilePathForFile(), but works for remote URLs.
0360      */
0361     static QUrl sidecarUrl(const QUrl& url);
0362 
0363     /**
0364      * Gives a file url for a local path.
0365      */
0366     static QUrl sidecarUrl(const QString& path);
0367 
0368     /**
0369      * Performs a QFileInfo based check if the given local file has a sidecar.
0370      */
0371     static bool hasSidecar(const QString& path);
0372 
0373     /**
0374      * Return a string of backend name used to parse metadata from file.
0375      * See Backend enum for details.
0376      */
0377     static QString backendName(Backend t);
0378 
0379     /**
0380      * Load all metadata (Exif, Iptc, Xmp, and JFIF Comments) from a picture (JPEG, RAW, TIFF, PNG,
0381      * DNG, etc...). Return true if metadata have been loaded successfully from file.
0382      * If backend is non null, return the backend used to populate metadata (Exiv2).
0383      * See Backend enum for details.
0384      */
0385     bool load(const QString& filePath, Backend* backend = nullptr);
0386 
0387     /**
0388      * Load metadata from a sidecar file and merge.
0389      * Return true if metadata have been loaded successfully from file.
0390      */
0391     bool loadFromSidecarAndMerge(const QString& filePath);
0392 
0393     /**
0394      * Save all metadata to a file. This one can be different than original picture to perform
0395      * transfer operation Return true if metadata have been saved into file.
0396      */
0397     bool save(const QString& filePath, bool setVersion = false) const;
0398 
0399     /**
0400      * The same than save() method, but it apply on current item. Return true if metadata
0401      * have been saved into file.
0402      */
0403     bool applyChanges(bool setVersion = false) const;
0404 
0405     /**
0406      *  Export metadata to a temporary EXV file container.
0407      * 'exvTmpFile' is the path to the temporary EXV container to create.
0408      */
0409     bool exportChanges(const QString& exvTmpFile) const;
0410 
0411     //@}
0412 
0413     //-------------------------------------------------------------------
0414     /// @name Metadata item information manipulation methods
0415     //@{
0416 
0417     /**
0418      * Set Program name and program version in Exif and Iptc Metadata. Return true if information
0419      * have been changed in metadata.
0420      */
0421     bool setItemProgramId(const QString& program, const QString& version) const;
0422 
0423     /**
0424      * Return the size of item in pixels using Exif tags. Return a null dimension if size cannot
0425      * be found.
0426      */
0427     QSize getItemDimensions() const;
0428 
0429     /**
0430      * Set the size of item in pixels in Exif tags. Return true if size have been changed
0431      * in metadata.
0432      */
0433     bool setItemDimensions(const QSize& size) const;
0434 
0435     /**
0436      * Return the item orientation set in Exif metadata. The makernotes of item are also parsed to
0437      * get this information. See ImageOrientation values for details.
0438      */
0439     MetaEngine::ImageOrientation getItemOrientation() const;
0440 
0441     /**
0442      * Set the Exif orientation tag of item. See ImageOrientation values for details
0443      * Return true if orientation have been changed in metadata.
0444      */
0445     bool setItemOrientation(ImageOrientation orientation) const;
0446 
0447     /**
0448      * Return the item color-space set in Exif metadata. The makernotes of item are also parsed to
0449      * get this information. See ImageColorWorkSpace values for details.
0450      */
0451     MetaEngine::ImageColorWorkSpace getItemColorWorkSpace() const;
0452 
0453     /**
0454      * Set the Exif color-space tag of item. See ImageColorWorkSpace values for details
0455      * Return true if work-space have been changed in metadata.
0456      */
0457     bool setItemColorWorkSpace(ImageColorWorkSpace workspace) const;
0458 
0459     /**
0460      * Return the time stamp of item. Exif information are check in first, IPTC in second
0461      * if item don't have Exif information. If no time stamp is found, a null date is returned.
0462      */
0463     QDateTime getItemDateTime() const;
0464 
0465     /**
0466      * Set the Exif and Iptc time stamp. If 'setDateTimeDigitized' parameter is true, the 'Digitalized'
0467      * time stamp is set, else only 'Created' time stamp is set.
0468      */
0469     bool setImageDateTime(const QDateTime& dateTime, bool setDateTimeDigitized = false) const;
0470 
0471     /**
0472      * Return the digitization time stamp of the item. First Exif information is checked, then IPTC.
0473      * If no digitization time stamp is found, getItemDateTime() is called if fallbackToCreationTime
0474      * is true, or a null QDateTime is returned if fallbackToCreationTime is false.
0475      */
0476     QDateTime getDigitizationDateTime(bool fallbackToCreationTime = false) const;
0477 
0478     /**
0479      * Return a QImage copy of Iptc preview image. Return a null item if preview cannot
0480      * be found.
0481      */
0482     bool getItemPreview(QImage& preview) const;
0483 
0484     /**
0485      * Set the Iptc preview image. The thumbnail item must have the right size before (64Kb max
0486      * with JPEG file, else 256Kb). Look Iptc specification for details. Return true if preview
0487      * have been changed in metadata.
0488      * Re-implement this method if you want to use another item file format than JPEG to
0489      * save preview.
0490      */
0491     bool setItemPreview(const QImage& preview) const;
0492 
0493     //@}
0494 
0495     //-----------------------------------------------------------------
0496     /// @name Comments manipulation methods
0497     //@{
0498 
0499     /**
0500      * Return 'true' if Comments can be written in file.
0501      */
0502     static bool canWriteComment(const QString& filePath);
0503 
0504     /**
0505      * Return 'true' if metadata container in memory as Comments.
0506      */
0507     bool hasComments() const;
0508 
0509     /**
0510      * Clear the Comments metadata container in memory.
0511      */
0512     bool clearComments() const;
0513 
0514     /**
0515      * Return a Qt byte array copy of Comments container get from current item.
0516      * Comments are JFIF section of JPEG images. Look Exiv2 API for more information.
0517      * Return a null Qt byte array if there is no Comments metadata in memory.
0518      */
0519     QByteArray getComments() const;
0520 
0521     /**
0522      * Return a Qt string object of Comments from current item decoded using
0523      * the 'detectEncodingAndDecode()' method. Return a null string if there is no
0524      * Comments metadata available.
0525      */
0526     QString getCommentsDecoded() const;
0527 
0528     /**
0529      * Set the Comments data using a Qt byte array. Return true if Comments metadata
0530      * have been changed in memory.
0531      */
0532     bool setComments(const QByteArray& data) const;
0533 
0534     /**
0535      * Language Alternative autodetection. Return a QString without language alternative
0536      * header. Header is saved into 'lang'. If no language alternative is founf, value is returned
0537      * as well and 'lang' is set to a null string.
0538      */
0539     static QString detectLanguageAlt(const QString& value, QString& lang);
0540 
0541     //@}
0542 
0543     //-----------------------------------------------------------------
0544     /// @name Exif manipulation methods
0545     //@{
0546 
0547     /**
0548      * Return a map of all standard Exif tags supported by Exiv2.
0549      */
0550     TagsMap getStdExifTagsList() const;
0551 
0552     /**
0553      * Return a map of all non-standard Exif tags (makernotes) supported by Exiv2.
0554      */
0555     TagsMap getMakernoteTagsList() const;
0556 
0557     /**
0558      * Return 'true' if Exif can be written in file.
0559      */
0560     static bool canWriteExif(const QString& filePath);
0561 
0562     /**
0563      * Return 'true' if metadata container in memory as Exif.
0564      */
0565     bool hasExif() const;
0566 
0567     /**
0568      * Clear the Exif metadata container in memory.
0569      */
0570     bool clearExif() const;
0571 
0572     /**
0573      * Returns the exif data encoded to a QByteArray in a form suitable
0574      * for storage in a JPEG image.
0575      * Note that this encoding is a lossy operation.
0576      *
0577      * Set true 'addExifHeader' parameter to add an Exif header to Exif metadata.
0578      * Returns a null Qt byte array if there is no Exif metadata in memory.
0579      */
0580     QByteArray getExifEncoded(bool addExifHeader = false) const;
0581 
0582     /**
0583      * Set the Exif data using a Qt byte array. Return true if Exif metadata
0584      * have been changed in memory.
0585      */
0586     bool setExif(const QByteArray& data) const;
0587 
0588     /**
0589      * Return a QImage copy of Exif thumbnail image. Return a null image if thumbnail cannot
0590      * be found. The 'fixOrientation' parameter will rotate automatically the thumbnail if Exif
0591      * orientation tags information are attached with thumbnail.
0592      */
0593     QImage getExifThumbnail(bool fixOrientation) const;
0594 
0595     /**
0596      * Fix orientation of a QImage image accordingly with Exif orientation tag.
0597      * Return true if image is rotated, else false.
0598      */
0599     bool rotateExifQImage(QImage& image, ImageOrientation orientation) const;
0600 
0601     /**
0602      * Set the Exif Thumbnail image. The thumbnail image must have the right dimensions before.
0603      * Look Exif specification for details. Return true if thumbnail have been changed in metadata.
0604      */
0605     bool setExifThumbnail(const QImage& thumb) const;
0606 
0607     /**
0608      * Remove the Exif Thumbnail from the item
0609      */
0610     bool removeExifThumbnail() const;
0611 
0612     /**
0613      * Adds a JPEG thumbnail to a TIFF images. Use this instead of setExifThumbnail for TIFF images.
0614      */
0615     bool setTiffThumbnail(const QImage& thumb) const;
0616 
0617     /**
0618      * Return a QString copy of Exif user comments. Return a null string if user comments cannot
0619      * be found.
0620      */
0621     QString getExifComment(bool readDescription = true) const;
0622 
0623     /**
0624      * Return a Exif tag comment like a string. Return a null string if user comments cannot
0625      * be found.
0626      */
0627     QString getExifTagComment(const char* exifTagName) const;
0628 
0629     /**
0630      * Set the Exif user comments from item. Look Exif specification for more details about this tag.
0631      * Return true if Exif user comments have been changed in metadata.
0632      */
0633     bool setExifComment(const QString& comment, bool writeDescription = true) const;
0634 
0635     /**
0636      * Get an Exif tags content like a string. If 'escapeCR' parameter is true, the CR characters
0637      * will be removed. If Exif tag cannot be found a null string is returned.
0638      */
0639     QString getExifTagString(const char* exifTagName, bool escapeCR = true) const;
0640 
0641     /**
0642      * Set an Exif tag content using a string. Return true if tag is set successfully.
0643      */
0644     bool setExifTagString(const char* exifTagName, const QString& value) const;
0645 
0646     /**
0647      * Get an Exif tag content like a long value. Return true if Exif tag be found.
0648      */
0649     bool getExifTagLong(const char* exifTagName, long &val) const;
0650 
0651     /**
0652      * Get an Exif tag content like a long value. Return true if Exif tag be found.
0653      */
0654     bool getExifTagLong(const char* exifTagName, long &val, int component) const;
0655 
0656     /**
0657      * Set an Exif tag content using a long value. Return true if tag is set successfully.
0658      */
0659     bool setExifTagLong(const char* exifTagName, long val) const;
0660 
0661     /**
0662      * Get the 'component' index of an Exif tags content like a rational value.
0663      * 'num' and 'den' are the numerator and the denominator of the rational value.
0664      * Return true if Exif tag be found.
0665      */
0666     bool getExifTagRational(const char* exifTagName, long int& num, long int& den, int component = 0) const;
0667 
0668     /**
0669      * Set an Exif tag content using a rational value.
0670      * 'num' and 'den' are the numerator and the denominator of the rational value.
0671      * Return true if tag is set successfully.
0672      */
0673     bool setExifTagRational(const char* exifTagName, long int num, long int den) const;
0674 
0675     /**
0676      * Get an Exif tag content like a bytes array. Return an empty bytes array if Exif
0677      * tag cannot be found.
0678      */
0679     QByteArray getExifTagData(const char* exifTagName) const;
0680 
0681     /**
0682      * Set an Exif tag content using a bytes array. Return true if tag is set successfully.
0683      */
0684     bool setExifTagData(const char* exifTagName, const QByteArray& data) const;
0685 
0686     /**
0687      * Get an Exif tags content as a QVariant. Returns a null QVariant if the Exif
0688      * tag cannot be found.
0689      * For string and integer values the matching QVariant types will be used,
0690      * for date and time values QVariant::DateTime.
0691      * Rationals will be returned as QVariant::List with two integer QVariants (numerator, denominator)
0692      * if rationalAsListOfInts is true, as double if rationalAsListOfInts is false.
0693      * An exif tag of numerical type may contain more than one value; set component to the desired index.
0694      */
0695     QVariant getExifTagVariant(const char* exifTagName, bool rationalAsListOfInts = true,
0696                                bool escapeCR = true, int component = 0) const;
0697 
0698     /**
0699      * Set an Exif tag content using a QVariant. Returns true if tag is set successfully.
0700      * All types described for the getExifTagVariant() method are supported.
0701      * Calling with a QVariant of type ByteArray is equivalent to calling setExifTagData.
0702      * For the meaning of rationalWantSmallDenominator, see the documentation of the convertToRational methods.
0703      * Setting a value with multiple components is currently not supported.
0704      */
0705     bool setExifTagVariant(const char* exifTagName, const QVariant& data,
0706                            bool rationalWantSmallDenominator = true) const;
0707 
0708     /**
0709      * Remove the Exif tag 'exifTagName' from Exif metadata. Return true if tag is
0710      * removed successfully or if no tag was present.
0711      */
0712     bool removeExifTag(const char* exifTagName) const;
0713 
0714     /**
0715      * Return the Exif Tag title or a null string.
0716      */
0717     QString getExifTagTitle(const char* exifTagName);
0718 
0719     /**
0720      * Return the Exif Tag description or a null string.
0721      */
0722     QString getExifTagDescription(const char* exifTagName);
0723 
0724     /**
0725      * Takes a QVariant value as it could have been retrieved by getExifTagVariant with the given exifTagName,
0726      * and returns its value properly converted to a string (including translations from Exiv2).
0727      * This is equivalent to calling getExifTagString directly.
0728      * If escapeCR is true CR characters will be removed from the result.
0729      */
0730     QString createExifUserStringFromValue(const char* exifTagName, const QVariant& val, bool escapeCR = true);
0731 
0732     /**
0733      * Return a map of Exif tags name/value found in metadata sorted by
0734      * Exif keys given by 'exifKeysFilter'.
0735      *
0736      * 'exifKeysFilter' is a QStringList of Exif keys.
0737      * For example, if you use the string list given below:
0738      *
0739      * "Iop"
0740      * "Thumbnail"
0741      * "Image"
0742      * "Photo"
0743      *
0744      * List can be empty to not filter output.
0745      *
0746      * ... this method will return a map of all Exif tags which :
0747      *
0748      * - include "Iop", or "Thumbnail", or "Image", or "Photo" in the Exif tag keys
0749      *   if 'inverSelection' is false.
0750      * - not include "Iop", or "Thumbnail", or "Image", or "Photo" in the Exif tag keys
0751      * if 'inverSelection' is true.
0752      * if 'extractBinary" is true, tags with undefined types of data are extracted (default),
0753      * else contents is replaced by "Binary data ... bytes". Take a care as large binary data as
0754      * original RAW data from DNG container can be huge and listing Exif tags from GUI can take a while.
0755      */
0756     MetaEngine::MetaDataMap getExifTagsDataList(const QStringList& exifKeysFilter = QStringList(),
0757                                                 bool invertSelection = false,
0758                                                 bool extractBinary = true) const;
0759 
0760     //@}
0761 
0762     //-------------------------------------------------------------
0763     /// @name IPTC manipulation methods
0764     //@{
0765 
0766     /**
0767      * Return a map of all standard Iptc tags supported by Exiv2.
0768      */
0769     MetaEngine::TagsMap getIptcTagsList() const;
0770 
0771     /**
0772      * Return 'true' if Iptc can be written in file.
0773      */
0774     static bool canWriteIptc(const QString& filePath);
0775 
0776     /**
0777      * Return 'true' if metadata container in memory as Iptc.
0778      */
0779     bool hasIptc() const;
0780 
0781     /**
0782      * Clear the Iptc metadata container in memory.
0783      */
0784     bool clearIptc() const;
0785 
0786     /**
0787      * Return a Qt byte array copy of Iptc container get from current item.
0788      * Set true 'addIrbHeader' parameter to add an Irb header to Iptc metadata.
0789      * Return a null Qt byte array if there is no Iptc metadata in memory.
0790      */
0791     QByteArray  getIptc(bool addIrbHeader = false) const;
0792 
0793     /**
0794      * Set the Iptc data using a Qt byte array. Return true if Iptc metadata
0795      * have been changed in memory.
0796      */
0797     bool setIptc(const QByteArray& data) const;
0798 
0799     /**
0800      * Get an Iptc tag content like a string. If 'escapeCR' parameter is true, the CR characters
0801      * will be removed. If Iptc tag cannot be found a null string is returned.
0802      */
0803     QString getIptcTagString(const char* iptcTagName, bool escapeCR = true) const;
0804 
0805     /**
0806      * Set an Iptc tag content using a string. Return true if tag is set successfully.
0807      */
0808     bool setIptcTagString(const char* iptcTagName, const QString& value) const;
0809 
0810     /**
0811      * Returns a strings list with of multiple Iptc tags from the item. Return an empty list if no tag is found.
0812      * Get the values of all IPTC tags with the given tag name in a string list.
0813      * (In Iptc, there can be multiple tags with the same name)
0814      * If the 'escapeCR' parameter is true, the CR characters
0815      * will be removed.
0816      * If no tag can be found an empty list is returned.
0817      */
0818     QStringList getIptcTagsStringList(const char* iptcTagName, bool escapeCR = true) const;
0819 
0820     /**
0821      * Set multiple Iptc tags contents using a strings list. 'maxSize' is the max characters size
0822      * of one entry. Return true if all tags have been set successfully.
0823      */
0824     bool setIptcTagsStringList(const char* iptcTagName, int maxSize,
0825                                const QStringList& oldValues, const QStringList& newValues) const;
0826 
0827     /**
0828      * Get an Iptc tag content as a bytes array. Return an empty bytes array if Iptc
0829      * tag cannot be found.
0830      */
0831     QByteArray getIptcTagData(const char* iptcTagName) const;
0832 
0833     /**
0834      * Set an Iptc tag content using a bytes array. Return true if tag is set successfully.
0835      */
0836     bool setIptcTagData(const char* iptcTagName, const QByteArray& data) const;
0837 
0838     /**
0839      * Remove the all instance of Iptc tags 'iptcTagName' from Iptc metadata. Return true if all
0840      * tags have been removed successfully (or none were present).
0841      */
0842     bool removeIptcTag(const char* iptcTagName) const;
0843 
0844     /**
0845      * Return the Iptc Tag title or a null string.
0846      */
0847     QString getIptcTagTitle(const char* iptcTagName);
0848 
0849     /**
0850      * Return the Iptc Tag description or a null string.
0851      */
0852     QString getIptcTagDescription(const char* iptcTagName);
0853 
0854     /**
0855      * Return a map of Iptc tags name/value found in metadata sorted by
0856      * Iptc keys given by 'iptcKeysFilter'.
0857      *
0858      * 'iptcKeysFilter' is a QStringList of Iptc keys.
0859      * For example, if you use the string list given below:
0860      *
0861      * "Envelope"
0862      * "Application2"
0863      *
0864      * List can be empty to not filter output.
0865      *
0866      * ... this method will return a map of all Iptc tags which :
0867      *
0868      * - include "Envelope", or "Application2" in the Iptc tag keys
0869      *   if 'inverSelection' is false.
0870      * - not include "Envelope", or "Application2" in the Iptc tag keys
0871      *   if 'inverSelection' is true.
0872      */
0873     MetaEngine::MetaDataMap getIptcTagsDataList(const QStringList& iptcKeysFilter = QStringList(),
0874                                                 bool invertSelection = false) const;
0875 
0876     /**
0877      * Return a strings list of Iptc keywords from item. Return an empty list if no keyword are set.
0878      */
0879     QStringList getIptcKeywords() const;
0880 
0881     /**
0882      * Set Iptc keywords using a list of strings defined by 'newKeywords' parameter. Use 'getImageKeywords()'
0883      * method to set 'oldKeywords' parameter with existing keywords from item. The method will compare
0884      * all new keywords with all old keywords to prevent duplicate entries in item. Return true if keywords
0885      * have been changed in metadata.
0886      */
0887     bool setIptcKeywords(const QStringList& oldKeywords, const QStringList& newKeywords) const;
0888 
0889     /**
0890      * Return a strings list of Iptc subjects from item. Return an empty list if no subject are set.
0891      */
0892     QStringList getIptcSubjects() const;
0893 
0894     /**
0895      * Set Iptc subjects using a list of strings defined by 'newSubjects' parameter. Use 'getImageSubjects()'
0896      * method to set 'oldSubjects' parameter with existing subjects from item. The method will compare
0897      * all new subjects with all old subjects to prevent duplicate entries in item. Return true if subjects
0898      * have been changed in metadata.
0899      */
0900     bool setIptcSubjects(const QStringList& oldSubjects, const QStringList& newSubjects) const;
0901 
0902     /**
0903      * Return a strings list of Iptc sub-categories from item. Return an empty list if no sub-category
0904      * are set.
0905      */
0906     QStringList getIptcSubCategories() const;
0907 
0908     /**
0909      * Set Iptc sub-categories using a list of strings defined by 'newSubCategories' parameter. Use
0910      * 'getImageSubCategories()' method to set 'oldSubCategories' parameter with existing sub-categories
0911      * from item. The method will compare all new sub-categories with all old sub-categories to prevent
0912      * duplicate entries in item. Return true if sub-categories have been changed in metadata.
0913      */
0914     bool setIptcSubCategories(const QStringList& oldSubCategories, const QStringList& newSubCategories) const;
0915 
0916     //@}
0917 
0918     //------------------------------------------------------------
0919     /// @name XMP manipulation methods
0920     //@{
0921 
0922     /**
0923      * Return a map of all standard Xmp tags supported by Exiv2.
0924      */
0925     MetaEngine::TagsMap getXmpTagsList() const;
0926 
0927     /**
0928      * Return 'true' if Xmp can be written in file.
0929      */
0930     static bool canWriteXmp(const QString& filePath);
0931 
0932     /**
0933      * Return 'true' if metadata container in memory as Xmp.
0934      */
0935     bool hasXmp() const;
0936 
0937     /**
0938      * Clear the Xmp metadata container in memory.
0939      */
0940     bool clearXmp() const;
0941 
0942     /**
0943      * Return a Qt byte array copy of XMp container get from current item.
0944      * Return a null Qt byte array if there is no Xmp metadata in memory.
0945      */
0946     QByteArray getXmp() const;
0947 
0948     /**
0949      * Set the Xmp data using a Qt byte array. Return true if Xmp metadata
0950      * have been changed in memory.
0951      */
0952     bool setXmp(const QByteArray& data) const;
0953 
0954     /**
0955      * Get a Xmp tag content like a string. If 'escapeCR' parameter is true, the CR characters
0956      * will be removed. If Xmp tag cannot be found a null string is returned.
0957      */
0958     QString getXmpTagString(const char* xmpTagName, bool escapeCR = true) const;
0959 
0960     /**
0961      * Set a Xmp tag content using a string. Return true if tag is set successfully.
0962      */
0963     bool setXmpTagString(const char* xmpTagName, const QString& value) const;
0964 
0965     /**
0966      * Set a Xmp tag with a specific type. Return true if tag is set successfully.
0967      * This method only accept NormalTag, ArrayBagTag and StructureTag.
0968      * Other XmpTagTypes do nothing
0969      */
0970     bool setXmpTagString(const char* xmpTagName, const QString& value,
0971                          XmpTagType type) const;
0972 
0973     /**
0974      * Return the Xmp Tag title or a null string.
0975      */
0976     QString getXmpTagTitle(const char* xmpTagName);
0977 
0978     /**
0979      * Return the Xmp Tag description or a null string.
0980      */
0981     QString getXmpTagDescription(const char* xmpTagName);
0982 
0983     /**
0984      * Return a map of Xmp tags name/value found in metadata sorted by
0985      * Xmp keys given by 'xmpKeysFilter'.
0986      *
0987      * 'xmpKeysFilter' is a QStringList of Xmp keys.
0988      * For example, if you use the string list given below:
0989      *
0990      * "dc"           // Dubling Core schema.
0991      * "xmp"          // Standard Xmp schema.
0992      *
0993      * List can be empty to not filter output.
0994      *
0995      * ... this method will return a map of all Xmp tags which :
0996      *
0997      * - include "dc", or "xmp" in the Xmp tag keys
0998      *   if 'inverSelection' is false.
0999      * - not include "dc", or "xmp" in the Xmp tag keys
1000      *   if 'inverSelection' is true.
1001      */
1002     MetaEngine::MetaDataMap getXmpTagsDataList(const QStringList& xmpKeysFilter = QStringList(),
1003                                                bool invertSelection = false) const;
1004 
1005     /**
1006      * Get all redondant Alternative Language Xmp tags content like a map.
1007      * See AltLangMap class description for details.
1008      * If 'escapeCR' parameter is true, the CR characters will be removed from strings.
1009      * If Xmp tag cannot be found a null string list is returned.
1010      */
1011     MetaEngine::AltLangMap getXmpTagStringListLangAlt(const char* xmpTagName,
1012                                                       bool escapeCR = true) const;
1013 
1014     /**
1015      * Set an Alternative Language Xmp tag content using a map. See AltLangMap class
1016      * description for details. If tag already exist, it will be removed before.
1017      * Return true if tag is set successfully.
1018      */
1019     bool setXmpTagStringListLangAlt(const char* xmpTagName, const MetaEngine::AltLangMap& values) const;
1020 
1021     /**
1022      * Get a Xmp tag content like a string set with an alternative language
1023      * header 'langAlt' (like "fr-FR" for French - RFC3066 notation)
1024      * If 'escapeCR' parameter is true, the CR characters will be removed.
1025      * If Xmp tag cannot be found a null string is returned.
1026      */
1027     QString getXmpTagStringLangAlt(const char* xmpTagName, const QString& langAlt, bool escapeCR) const;
1028 
1029     /**
1030      * Set a Xmp tag content using a string with an alternative language header. 'langAlt' contain the
1031      * language alternative information (like "fr-FR" for French - RFC3066 notation) or is null to
1032      * set alternative language to default settings ("x-default").
1033      * Return true if tag is set successfully.
1034      */
1035     bool setXmpTagStringLangAlt(const char* xmpTagName, const QString& value,
1036                                 const QString& langAlt) const;
1037 
1038     /**
1039      * Get a Xmp tag content like a sequence of strings. If 'escapeCR' parameter is true, the CR characters
1040      * will be removed from strings. If Xmp tag cannot be found a null string list is returned.
1041      */
1042     QStringList getXmpTagStringSeq(const char* xmpTagName, bool escapeCR = true) const;
1043 
1044     /**
1045      * Set a Xmp tag content using the sequence of strings 'seq'.
1046      * Return true if tag is set successfully.
1047      */
1048     bool setXmpTagStringSeq(const char* xmpTagName, const QStringList& seq) const;
1049 
1050     /**
1051      * Get a Xmp tag content like a bag of strings. If 'escapeCR' parameter is true, the CR characters
1052      * will be removed from strings. If Xmp tag cannot be found a null string list is returned.
1053      */
1054     QStringList getXmpTagStringBag(const char* xmpTagName, bool escapeCR) const;
1055 
1056     /**
1057      * Set a Xmp tag content using the bag of strings 'bag'.
1058      * Return true if tag is set successfully.
1059      */
1060     bool setXmpTagStringBag(const char* xmpTagName, const QStringList& bag) const;
1061 
1062     /**
1063      * Set an Xmp tag content using a list of strings defined by the 'entriesToAdd' parameter.
1064      * The existing entries are preserved. The method will compare
1065      * all new with all already existing entries to prevent duplicates in the item.
1066      * Return true if the entries have been added to metadata.
1067      */
1068     bool addToXmpTagStringBag(const char* xmpTagName, const QStringList& entriesToAdd) const;
1069 
1070     /**
1071      * Remove those Xmp tag entries that are listed in entriesToRemove from the entries in metadata.
1072      * Return true if tag entries are no longer contained in metadata.
1073      * All other entries are preserved.
1074      */
1075     bool removeFromXmpTagStringBag(const char* xmpTagName, const QStringList& entriesToRemove) const;
1076 
1077     /**
1078      * Get an Xmp tag content as a QVariant. Returns a null QVariant if the Xmp
1079      * tag cannot be found.
1080      * For string and integer values the matching QVariant types will be used,
1081      * for date and time values QVariant::DateTime.
1082      * Rationals will be returned as QVariant::List with two integer QVariants (numerator, denominator)
1083      * if rationalAsListOfInts is true, as double if rationalAsListOfInts is false.
1084      * Arrays (ordered, unordered, alternative) are returned as type StringList.
1085      * LangAlt values will have type Map (QMap<QString, QVariant>) with the language
1086      * code as key and the contents as value, of type String.
1087      */
1088     QVariant getXmpTagVariant(const char* xmpTagName, bool rationalAsListOfInts = true, bool stringEscapeCR = true) const;
1089 
1090     /**
1091      * Return a strings list of Xmp keywords from item. Return an empty list if no keyword are set.
1092      */
1093     QStringList getXmpKeywords() const;
1094 
1095     /**
1096      * Set Xmp keywords using a list of strings defined by 'newKeywords' parameter.
1097      * The existing keywords from item are preserved. The method will compare
1098      * all new keywords with all already existing keywords to prevent duplicate entries in item.
1099      * Return true if keywords have been changed in metadata.
1100      */
1101     bool setXmpKeywords(const QStringList& newKeywords) const;
1102 
1103     /**
1104      * Remove those Xmp keywords that are listed in keywordsToRemove from the keywords in metadata.
1105      * Return true if keywords are no longer contained in metadata.
1106      */
1107     bool removeXmpKeywords(const QStringList& keywordsToRemove);
1108 
1109     /**
1110      * Return a strings list of Xmp subjects from item. Return an empty list if no subject are set.
1111      */
1112     QStringList getXmpSubjects() const;
1113 
1114     /**
1115      * Set Xmp subjects using a list of strings defined by 'newSubjects' parameter.
1116      * The existing subjects from item are preserved. The method will compare
1117      * all new subject with all already existing subject to prevent duplicate entries in item.
1118      * Return true if subjects have been changed in metadata.
1119      */
1120     bool setXmpSubjects(const QStringList& newSubjects) const;
1121 
1122     /**
1123      * Remove those Xmp subjects that are listed in subjectsToRemove from the subjects in metadata.
1124      * Return true if subjects are no longer contained in metadata.
1125      */
1126     bool removeXmpSubjects(const QStringList& subjectsToRemove);
1127 
1128     /**
1129      * Return a strings list of Xmp sub-categories from item. Return an empty list if no sub-category
1130      * are set.
1131      */
1132     QStringList getXmpSubCategories() const;
1133 
1134     /**
1135      * Set Xmp sub-categories using a list of strings defined by 'newSubCategories' parameter.
1136      * The existing sub-categories from item are preserved. The method will compare
1137      * all new sub-categories with all already existing sub-categories to prevent duplicate entries in item.
1138      * Return true if sub-categories have been changed in metadata.
1139      */
1140     bool setXmpSubCategories(const QStringList& newSubCategories) const;
1141 
1142     /**
1143      * Remove those Xmp sub-categories that are listed in categoriesToRemove from the sub-categories in metadata.
1144      * Return true if subjects are no longer contained in metadata.
1145      */
1146     bool removeXmpSubCategories(const QStringList& categoriesToRemove);
1147 
1148     /**
1149      * Remove the Xmp tag 'xmpTagName' from Xmp metadata. Return true if tag is
1150      * removed successfully or if no tag was present.
1151      */
1152     bool removeXmpTag(const char* xmpTagName, bool family = false) const;
1153 
1154     /**
1155      * Register a namespace which Exiv2 doesn't know yet. This is only needed
1156      * when new Xmp properties are added manually. 'uri' is the namespace url and 'prefix' the
1157      * string used to construct new Xmp key (ex. "Xmp.digiKam.tagList").
1158      * NOTE: If the Xmp metadata is read from an item, namespaces are decoded and registered
1159      * by Exiv2 at the same time.
1160      */
1161     static bool registerXmpNameSpace(const QString& uri, const QString& prefix);
1162 
1163     /**
1164      * Unregister a previously registered custom namespace
1165      */
1166     static bool unregisterXmpNameSpace(const QString& uri);
1167 
1168     //@}
1169 
1170     //------------------------------------------------------------
1171     /// @name GPS manipulation methods
1172     //@{
1173 
1174     /**
1175      * Make sure all static required GPS EXIF and XMP tags exist
1176      */
1177     bool initializeGPSInfo();
1178 
1179     /**
1180      * Get all GPS location information set in item. Return true if all information can be found.
1181      */
1182     bool getGPSInfo(double& altitude, double& latitude, double& longitude) const;
1183 
1184     /**
1185      * Get GPS location information set in the item, in the GPSCoordinate format
1186      * as described in the XMP specification. Returns a null string in the information cannot be found.
1187      */
1188     QString getGPSLatitudeString()  const;
1189     QString getGPSLongitudeString() const;
1190 
1191     /**
1192      * Get GPS location information set in the item, as a double floating point number as in degrees
1193      * where the sign determines the direction ref (North + / South - ; East + / West -).
1194      * Returns true if the information is available.
1195      */
1196     bool getGPSLatitudeNumber(double* const latitude)   const;
1197     bool getGPSLongitudeNumber(double* const longitude) const;
1198 
1199     /**
1200      * Get GPS altitude information, in meters, relative to sea level (positive sign above sea level)
1201      */
1202     bool getGPSAltitude(double* const altitude) const;
1203 
1204     /**
1205      * Set all GPS location information into item. Return true if all information have been
1206      * changed in metadata.
1207      */
1208     bool setGPSInfo(const double altitude, const double latitude, const double longitude);
1209 
1210     /**
1211      * Set all GPS location information into item. Return true if all information have been
1212      * changed in metadata. If you do not want altitude to be set, pass a null pointer.
1213      */
1214     bool setGPSInfo(const double* const altitude, const double latitude, const double longitude);
1215 
1216     /**
1217      * Set all GPS location information into item. Return true if all information have been
1218      * changed in metadata.
1219      */
1220     bool setGPSInfo(const double altitude, const QString& latitude, const QString& longitude);
1221 
1222     /**
1223      * Remove all Exif tags relevant of GPS location information. Return true if all tags have been
1224      * removed successfully in metadata.
1225      */
1226     bool removeGPSInfo();
1227 
1228     /**
1229      * This method converts 'number' to a rational value, returned in the 'numerator' and
1230      * 'denominator' parameters. Set the precision using 'rounding' parameter.
1231      * Use this method if you want to retrieve a most exact rational for a number
1232      * without further properties, without any requirements to the denominator.
1233      */
1234     static void convertToRational(const double number,
1235                                   long int* const numerator,
1236                                   long int* const denominator,
1237                                   const int rounding);
1238 
1239     /**
1240      * This method convert a 'number' to a rational value, returned in 'numerator' and
1241      * 'denominator' parameters.
1242      * This method will be able to retrieve a rational number from a double - if you
1243      * constructed your double with 1.0 / 4786.0, this method will retrieve 1 / 4786.
1244      * If your number is not expected to be rational, use the method above which is just as
1245      * exact with rounding = 4 and more exact with rounding > 4.
1246      */
1247     static void convertToRationalSmallDenominator(const double number,
1248                                                   long int* const numerator,
1249                                                   long int* const denominator);
1250 
1251     /**
1252      * Converts degrees values as a double representation. This code take a care about hemisphere position.
1253      */
1254     static double convertDegreeAngleToDouble(double degrees, double minutes, double seconds);
1255 
1256 
1257     /**
1258      * Converts a GPS position stored as rationals in Exif to the form described
1259      * as GPSCoordinate in the XMP specification, either in the from "256,45,34N" or "256,45.566667N"
1260      */
1261     static QString convertToGPSCoordinateString(const long int numeratorDegrees,
1262                                                 const long int denominatorDegrees,
1263                                                 const long int numeratorMinutes,
1264                                                 const long int denominatorMinutes,
1265                                                 const long int numeratorSeconds,
1266                                                 const long int denominatorSeconds,
1267                                                 const char directionReference);
1268 
1269     /**
1270      * Converts a GPS position stored as double floating point number in degrees to the form described
1271      * as GPSCoordinate in the XMP specification.
1272      */
1273     static QString convertToGPSCoordinateString(const bool isLatitude,
1274                                                 double coordinate);
1275 
1276     /**
1277      * Converts a GPSCoordinate string as defined by XMP to three rationals and the direction reference.
1278      * Returns true if the conversion was successful.
1279      * If minutes is given in the fractional form, a denominator of 1000000 for the minutes will be used.
1280      */
1281     static bool convertFromGPSCoordinateString(const QString& coordinate,
1282                                                long int* const numeratorDegrees,
1283                                                long int* const denominatorDegrees,
1284                                                long int* const numeratorMinutes,
1285                                                long int* const denominatorMinutes,
1286                                                long int* const numeratorSeconds,
1287                                                long int* const denominatorSeconds,
1288                                                char* const directionReference);
1289 
1290     /**
1291      * Convert a GPSCoordinate string as defined by XMP to a double floating point number in degrees
1292      * where the sign determines the direction ref (North + / South - ; East + / West -).
1293      * Returns true if the conversion was successful.
1294      */
1295     static bool convertFromGPSCoordinateString(const QString& gpsString,
1296                                                double* const coordinate);
1297 
1298     /**
1299      * Converts a GPSCoordinate string to user presentable numbers, integer degrees and minutes and
1300      * double floating point seconds, and a direction reference ('N' or 'S', 'E' or 'W')
1301      */
1302     static bool convertToUserPresentableNumbers(const QString& coordinate,
1303                                                 int* const degrees,
1304                                                 int* const minutes,
1305                                                 double* const seconds,
1306                                                 char* const directionReference);
1307 
1308     /**
1309      * Converts a double floating point number to user presentable numbers, integer degrees and minutes and
1310      * double floating point seconds, and a direction reference ('N' or 'S', 'E' or 'W').
1311      * The method needs to know for the direction reference
1312      * if the latitude or the longitude is meant by the double parameter.
1313      */
1314     static void convertToUserPresentableNumbers(const bool isLatitude,
1315                                                 double coordinate,
1316                                                 int* const degrees,
1317                                                 int* const minutes,
1318                                                 double* const seconds,
1319                                                 char* const directionReference);
1320 
1321     //@}
1322 
1323 protected:
1324 
1325     /**
1326      * Set the Program Name and Program Version
1327      * information in Exif and Iptc metadata
1328      */
1329     bool setProgramId() const;
1330 
1331 private:
1332 
1333     // Disable copy constructor and operator to prevent potential slicing with this class, reported by Clazy static analyzer.
1334     // https://github.com/KDE/clazy/blob/master/docs/checks/README-copyable-polymorphic.md
1335     // This methods was implemented to be able to pass this class or a derived version to signals and slots. This is very
1336     // Dangerous as virtual methods are present in this polymorphic class and is copyable.
1337     // Instead to use this class in signals and slots, use MetaEngineData container.
1338     // TODO: remove legacy implementations for these methods later if no side effect.
1339     MetaEngine(const MetaEngine& metadata);
1340     MetaEngine& operator=(const MetaEngine& metadata);
1341 
1342 private:
1343 
1344     /**
1345      * Internal container to store private members. Used to improve binary compatibility
1346      */
1347     class Private;
1348     Private* const d;
1349 
1350     friend class MetaEnginePreviews;
1351 };
1352 
1353 } // namespace Digikam
1354 
1355 #endif // DIGIKAM_META_ENGINE_H