File indexing completed on 2024-05-05 04:33:15

0001 /*
0002     SPDX-FileCopyrightText: 2004-2018 Gilles Caulier <caulier dot gilles at gmail dot com>
0003     SPDX-FileCopyrightText: 2006-2012 Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0004     SPDX-FileCopyrightText: 2004-2005 Renchi Raju <renchi dot raju at gmail dot com>
0005     SPDX-FileCopyrightText: 2004-2005 Jesper K. Pedersen <blackie at kde dot org>
0006     SPDX-FileCopyrightText: 2004-2005 Aurelien Gateau <aurelien dot gateau at free dot fr>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #ifndef KIPI_INTERFACE_H
0012 #define KIPI_INTERFACE_H
0013 
0014 // Std includes
0015 
0016 #include <memory>
0017 
0018 // Qt includes
0019 
0020 #include <QFlags>
0021 #include <QObject>
0022 #include <QVariant>
0023 #include <QList>
0024 #include <QUrl>
0025 #include <QByteArray>
0026 #include <QImage>
0027 
0028 // Local includes
0029 
0030 #include "libkipi_export.h"
0031 
0032 class QPixmap;
0033 class QWidget;
0034 class QAbstractItemModel;
0035 
0036 /**
0037  * @namespace KIPI
0038  *
0039  * The namespace for all KIPI classes.
0040  */
0041 
0042 namespace KIPI
0043 {
0044 
0045 class ImageCollection;
0046 class ImageCollectionSelector;
0047 class ImageInfo;
0048 class ImageInfoShared;
0049 class UploadWidget;
0050 
0051 /*!
0052   @enum KIPI::Features
0053   Not all host applications support the full subset of features that KIPI
0054   allows access to. Thus before a plugin expect a decant value for the comment,
0055   it should check whether KIPI::CollectionsHaveComments are set. It does so
0056   using KIPI::Interface::hasFeature().
0057 */
0058 enum Features
0059 {
0060     CollectionsHaveComments        = 1 << 0,  /** This feature specifies that albums have descriptions associated to them.                                                          */
0061     ImagesHasComments              = 1 << 1,  /** This feature specifies that images in the host application has descriptions associated to them.                                   */
0062     ImagesHasTime                  = 1 << 2,  /** This feature specifies that images has a date associated with it, which the host application can display and set.                 */
0063     HostSupportsDateRanges         = 1 << 3,  /** This feature specifies whether the host application supports that the user can specify a date range for images, like 1998-2000.   */
0064     HostAcceptNewImages            = 1 << 4,  /** This feature specifies that the host application do accept new images. Use \ref ImageCollection::uploadUrl to find the
0065                                                   location to place the image, and \ref Interface::addImage() to tell the host application about the new image.               */
0066     ImagesHasTitlesWritable        = 1 << 5,  /** This feature specifies whether the plugin can change the title for images.                                                        */
0067     CollectionsHaveCategory        = 1 << 6,  /** This feature specifies that collections are category associated to them ('travels', 'friends', 'monuments', etc.).                */
0068     CollectionsHaveCreationDate    = 1 << 7,  /** This feature specifies that collections are a creation date associated to them.                                                   */
0069     HostSupportsProgressBar        = 1 << 8,  /** This feature specifies whether the host application has a progress manager available to report progress information from plugins. */
0070     HostSupportsTags               = 1 << 9,  /** This feature specifies whether the host application supports keywords for images.                                                 */
0071     HostSupportsRating             = 1 << 10, /** This feature specifies whether the host application supports rating values for images.                                            */
0072     HostSupportsThumbnails         = 1 << 11, /** This feature specifies that host application can provide image thumbnails.                                                        */
0073     HostSupportsReadWriteLock      = 1 << 12, /** This feature specifies that host application has mechanism to lock/unlock items to prevent concurrent operations.                 */
0074     HostSupportsPickLabel          = 1 << 13, /** This feature specifies whether the host application supports pick label values for images, used for photograph workflow.          */
0075     HostSupportsColorLabel         = 1 << 14, /** This feature specifies whether the host application supports color label values for images, used to sort item with color flag.    */
0076     HostSupportsItemReservation    = 1 << 15, /** This feature specifies whether the host application supports item reservation.                                                    */
0077     HostSupportsPreviews           = 1 << 16, /** This feature specifies that host application can provide image preview.                                                           */
0078     HostSupportsRawProcessing      = 1 << 17, /** This feature specifies that host application can process Raw files.                                                               */
0079     HostSupportsMetadataProcessing = 1 << 18, /** This feature specifies that host application can process Metadata from files.                                                     */
0080     HostSupportsSaveImages         = 1 << 19  /** This feature specifies that host application can save image files.                                                                */
0081 };
0082 
0083 // NOTE: When a new item is add to Features, please don't forget to patch Interface::hasFeature().
0084 
0085 /**
0086  * The EditHint enum.
0087  */
0088 enum EditHint
0089 {
0090     UndefinedEditHint       = 0,
0091     /** The image data (pixels) have been edited
0092      */
0093     HintPixelContentChanged = 1 << 0,
0094     /** Metadata have been edited
0095      */
0096     HintMetadataChanged     = 1 << 1,
0097     /** All changes done (typically, to the metadata) are also communicated via image attributes.
0098      *  In other words, if the host updates its internal storage from attribute changes
0099      *  and ignores changes on disk, it already has all information.
0100      */
0101     HintChangeReflectedByAttributes
0102                             = 1 << 2,
0103     /** The operation indicated as "about to be done" has been aborted / did not result in a change.
0104      */
0105     HintEditAborted         = 1 << 3,
0106 
0107     /** Short name, implies that only metadata changed, and all metadata changes are communicated via attributes.
0108      */
0109     HintMetadataOnlyChange  = HintMetadataChanged | HintChangeReflectedByAttributes
0110 };
0111 /**
0112  * Stores a combination of #EditHint values.
0113  */
0114 Q_DECLARE_FLAGS(EditHints, EditHint)
0115 
0116 // ---------------------------------------------------------------------------------------------------------------
0117 
0118 /**
0119  *  @class FileReadWriteLock interface.h <KIPI/Interface>
0120  *
0121  *  A Kipi FileReadWriteLock refers to application-wide reading/writing
0122  *  to a file on disk; it is created with Interface::createReadWriteLock() for a URL.
0123  *  All semantics are identical to a recursive QReadWriteLock.
0124  *  You must unlock as often as you locked.
0125  *
0126  *  @note Locking will incur a mutex wait if the file is not free.
0127  *  Therefore, calling the lock methods, especially lockForWrite,
0128  *  from the UI thread shall be done with care, or rather avoided.
0129  *
0130  *  Note that you must not keep a lock for a longer time, but only for the imminent
0131  *  low-level reading or writing on disk.
0132  *
0133  *  See Interface::reserveForAction() API for longer lasting reservation which
0134  *  do not incur waits.
0135  *
0136  *  It is strongly recommended to use the FileReadLocker or FileWriteLocker
0137  *  convenience locks instead of creating and locking a FileReadWriteLock directly.
0138  */
0139 class LIBKIPI_EXPORT FileReadWriteLock
0140 {
0141 public:
0142 
0143     virtual ~FileReadWriteLock() {}
0144     virtual void lockForRead()                = 0;
0145     virtual void lockForWrite()               = 0;
0146     virtual bool tryLockForRead()             = 0;
0147     virtual bool tryLockForRead(int timeout)  = 0;
0148     virtual bool tryLockForWrite()            = 0;
0149     virtual bool tryLockForWrite(int timeout) = 0;
0150     virtual void unlock()                     = 0;
0151 };
0152 
0153 // ---------------------------------------------------------------------------------------------------------------
0154 
0155 /**
0156  *  @class MetadataProcessor interface.h <KIPI/Interface>
0157  *
0158  *  A Kipi MetadataProcessor refers to application-wide to process file metadata
0159  *  about Exif/Iptc/Xmp management; it is created with Interface::createMetadataProcessor().
0160  *  You can use libkexiv2 to re-implement this class as it's implemented in tests/common/kipiinterface.cpp.
0161  */
0162 class LIBKIPI_EXPORT MetadataProcessor : public QObject
0163 {
0164 public:
0165 
0166     /** Image orientation values from Exif tag.
0167     */
0168     enum ExifOrientation
0169     {
0170         UNSPECIFIED  = 0,
0171         NORMAL       = 1,
0172         HFLIP        = 2,
0173         ROT_180      = 3,
0174         VFLIP        = 4,
0175         ROT_90_HFLIP = 5,
0176         ROT_90       = 6,
0177         ROT_90_VFLIP = 7,
0178         ROT_270      = 8
0179     };
0180 
0181 public:
0182 
0183     MetadataProcessor()          {};
0184     ~MetadataProcessor() override {};
0185 
0186     virtual bool load(const QUrl& url) = 0;
0187     virtual bool applyChanges() = 0;
0188 
0189     /** @note @p writeToFileOnly force to write metadata only in file without to manage XMP sidecar file
0190      */
0191     virtual bool save(const QUrl& url, bool writeToFileOnly=false) = 0;
0192 
0193     virtual QSize getPixelSize() = 0;
0194 
0195     virtual bool  setImageProgramId(const QString& program, const QString& version) = 0;
0196 
0197     virtual QSize getImageDimensions() = 0;
0198     virtual bool  setImageDimensions(const QSize& size) = 0;
0199 
0200     /** @note orientation is standard value from Exif orientation tag. See ExifOrientation values.
0201      */
0202     virtual int  getImageOrientation() = 0;
0203     virtual bool setImageOrientation(int orientation) = 0;
0204     virtual bool rotateExifQImage(QImage& img, int orientation) = 0;
0205 
0206     virtual QDateTime getImageDateTime() = 0;
0207     virtual bool      setImageDateTime(const QDateTime& dt) = 0;
0208 
0209     virtual bool getImagePreview(QImage& img) = 0;
0210     virtual bool setImagePreview(const QImage& img) = 0;
0211 
0212     virtual bool hasExif() = 0;
0213     virtual bool hasIptc() = 0;
0214     virtual bool hasXmp()  = 0;
0215 
0216     virtual QByteArray getExif() = 0;
0217     virtual QByteArray getIptc() = 0;
0218     virtual QByteArray getXmp()  = 0;
0219 
0220     virtual bool setExif(const QByteArray& data) = 0;
0221     virtual bool setIptc(const QByteArray& data) = 0;
0222     virtual bool setXmp(const QByteArray& data) = 0;
0223 
0224     virtual bool registerXmpNameSpace(const QString& uri, const QString& prefix) = 0;
0225 
0226     virtual bool supportXmp() = 0;
0227     virtual bool canWriteXmp(const QUrl& url) = 0;
0228 
0229     virtual bool removeExifTags(const QStringList& tagFilters) = 0;
0230     virtual bool removeIptcTags(const QStringList& tagFilters) = 0;
0231     virtual bool removeXmpTags(const QStringList& tagFilters)  = 0;
0232 
0233     virtual bool getGPSInfo(double& altitude, double& latitude, double& longitude) = 0;
0234     virtual bool setGPSInfo(const double altitude, const double latitude, const double longitude) = 0;
0235     virtual bool removeGPSInfo() = 0;
0236 
0237     virtual QString getExifTagString(const QString& tag) = 0;
0238     virtual bool    setExifTagString(const QString& tag, const QString& val) = 0;
0239 
0240     virtual bool getExifTagRational(const QString& tag, long int& num, long int& den) = 0;
0241     virtual bool setExifTagRational(const QString& tag, long int num, long int den)   = 0;
0242 
0243     virtual QString getXmpTagString(const QString& tag) = 0;
0244     virtual bool    setXmpTagString(const QString& tag, const QString& val) = 0;
0245 
0246     virtual QStringList getXmpKeywords() = 0;
0247     virtual bool        setXmpKeywords(const QStringList& keywords) = 0;
0248 
0249     virtual QVariant getXmpTagVariant(const QString& tag) = 0;
0250 };
0251 
0252 // ---------------------------------------------------------------------------------------------------------------
0253 
0254 /**
0255  * @class Interface interface.h <KIPI/Interface>
0256  *
0257  * The Interface class.
0258  */
0259 class LIBKIPI_EXPORT Interface : public QObject
0260 {
0261     Q_OBJECT
0262 
0263 public:
0264 
0265     explicit Interface(QObject* const parent, const QString& name=QString());
0266     ~Interface() override;
0267 
0268     /**
0269      * Tells whether the host application under which the plugin currently executes a given feature.
0270      * See KIPI::Features for details on the individual features.
0271      */
0272     bool hasFeature(Features feature) const;
0273 
0274     /**
0275      * Returns list of all images in current album.
0276      * If there are no current album, the returned
0277      * KIPI::ImageCollection::isValid() will return @c false.
0278      */
0279     virtual ImageCollection currentAlbum() = 0;
0280 
0281     /**
0282      * Current selection in a thumbnail view for example.
0283      * If there are no current selection, the returned
0284      * KIPI::ImageCollection::isValid() will return @c false.
0285      */
0286     virtual ImageCollection currentSelection() = 0;
0287 
0288     /**
0289      * Returns a list of albums.
0290      */
0291     virtual QList<ImageCollection> allAlbums() = 0;
0292 
0293     /**
0294      * Returns the image info container for item pointed by @p url.
0295      */
0296     virtual ImageInfo info(const QUrl& url) = 0;
0297 
0298     /**
0299      * Tells to host application that a new image has been made available to it.
0300      * Returns @c true if the host application did accept the new image, otherwise @p err will be filled with
0301      * an error description.
0302      */
0303     virtual bool addImage(const QUrl&, QString& err);
0304 
0305     /**
0306      * Tells to host application that a new image has been removed.
0307      */
0308     virtual void delImage(const QUrl&);
0309 
0310     /**
0311      * Tells to host application that the following images has changed on disk
0312      */
0313     virtual void refreshImages(const QList<QUrl>&);
0314 
0315     /**
0316      * Tells to host application to render immediatly a preview image for one item.
0317      * This method re-implemented in host application and be thread safe.
0318      */
0319     virtual QImage preview(const QUrl& url);
0320 
0321     /**
0322      * Tell to host application to save image at a URL in specific format (JPG, PNG, TIF, etc).
0323      * Pixels image data must be in ARGB, with image size (width,height).
0324      * Pixels can be in sixteen bits per color per pixels and can have an alpha channel.
0325      * If @p cancel flag is passed it permit to cancel save operation.
0326      * This method re-implemented in host application must be thread safe.
0327      */
0328     virtual bool saveImage(const QUrl& url, const QString& format,
0329                            const QByteArray& data, uint width, uint height,
0330                            bool  sixteenBit, bool hasAlpha,
0331                            bool* cancel = nullptr);
0332 
0333     /**
0334      * Tells to host application to render a preview image for one item.
0335      * A resizement to a specific size will be generated if preview is largest than.
0336      * Use a positive @p resizedTo value in this case, else -1. Aspect ratio is preserved while rendering.
0337      * This asynchronous method must be re-implemented in host application.
0338      * Use gotPreview() signal to take preview.
0339      */
0340     virtual void preview(const QUrl& url, int resizedTo);
0341 
0342     /**
0343      * Tells to host application to render a thumbnail for one item. This asynchronous method must be
0344      * re-implemented in host application. Use gotThumbnail() signal to take thumb.
0345      */
0346     virtual void thumbnail(const QUrl& url, int size);
0347 
0348     /**
0349      * Ask to Kipi host application to render thumbnails for a list of images. This asynchronous method must be
0350      * re-implemented in host application. Use gotThumbnail() signal to take thumbs.
0351      */
0352     virtual void thumbnails(const QList<QUrl>& list, int size);
0353 
0354     /**
0355       Ask to Kipi host application to prepare progress manager for a new entry. This method must return from host
0356       a string identification about progress item created. This id will be used later to change in host progress item
0357       value and text. @p title is text used to name progress item in host application.
0358       Set @p canBeCanceled to @c true if you want that progress item provide a cancel button to close process from kipi host.
0359       Use progressCanceled() signal to manage feedback from kipi host when cancel button is pressed.
0360       Set @p hasThumb to @c true if you want that progress item support small thumbnail near progress bar.
0361       Use progresssThumbnailChanged() to change thumbnail in kipi host and progressValueChanged() to advance progress
0362       bar in percent. Use progressStatusChanged() to change description string of progress item.
0363       To close progress item in kipi host, for example when all is done in plugin, use progressCompleted() method.
0364       If you Host do not re-implement this method, value returned is a null string.
0365       You must re-implement this method if your host support HostSupportsProgressBar feature.
0366     */
0367     virtual QString progressScheduled(const QString& title, bool canBeCanceled, bool hasThumb) const;
0368 
0369     /**
0370      * To manage progress state from plugin to host application.
0371      * @param id identification string of process item returned from host by progressScheduled() method.
0372      */
0373     virtual void progressValueChanged(const QString& id, float percent);
0374     virtual void progressStatusChanged(const QString& id, const QString& status);
0375     virtual void progressThumbnailChanged(const QString& id, const QPixmap& thumb);
0376     virtual void progressCompleted(const QString& id);
0377 
0378     /** Returns RAW file extensions managed by host application, separated by blank spaces, (ex: "NEF CR2 ARW PEF").
0379     */
0380     virtual QString rawFiles();
0381 
0382     virtual ImageCollectionSelector* imageCollectionSelector(QWidget* parent)=0;
0383     virtual UploadWidget*            uploadWidget(QWidget* parent)=0;
0384     virtual QAbstractItemModel*      getTagTree() const;
0385 
0386     /**
0387      * Supported if HostSupportsItemReservation
0388      *
0389      * If an item is scheduled in a plugin for an action which will edit the object,
0390      * call this method. If the user tries to subject the reserved item to another operation,
0391      * possibly conflicting, a warning message or other action may be taken.
0392      *
0393      * Give the URL of the item and a QObject which acts as the holder of the reservation.
0394      * The object must not be null, and the reservation will be cancelled when the object is deleted.
0395      *
0396      * @param descriptionOfAction a user-presentable string describing the action for which
0397      * the reservation was made
0398      *
0399      * @returns @c true if a reservation was made, or false if a reservation could not be made.
0400      */
0401     virtual bool reserveForAction(const QUrl& url, QObject* const reservingObject,
0402                                   const QString& descriptionOfAction) const;
0403     /**
0404      * Supported if HostSupportsItemReservation
0405      *
0406      * Clears a reservation made previously with reserveForAction() for the given @p reservingObject.
0407      * You must clear any reservation you made, or, alternatively, delete the reserving object.
0408      */
0409     virtual void clearReservation(const QUrl& url, QObject* const reservingObject);
0410 
0411     /**
0412      * Supported if HostSupportsItemReservation
0413      *
0414      * Returns if the item is reserved. You can pass a pointer to a QString; if the return value
0415      * is @c true, the string will be set to the @p descriptionOfAction set with reserveForAction().
0416      */
0417     virtual bool itemIsReserved(const QUrl& url, QString* const descriptionOfAction = nullptr) const;
0418 
0419     /**
0420      * Supported if HostSupportsReadWriteLock
0421      * Creates a ReadWriteLock for the given URL.
0422      * You must unlock the FileReadWriteLock as often as you locked.
0423      * Deleting the object does not unlock it.
0424      * The implementation from KIPI host application must be thread-safe.
0425      *
0426      */
0427     virtual FileReadWriteLock* createReadWriteLock(const QUrl& url) const;
0428 
0429     /**
0430      * Supported if HostSupportsMetadataProcessing.
0431      * Creates an instance of MetadataProcessor dedicated to manage file metadata.
0432      * The implementation from KIPI host application must be thread-safe.
0433      *
0434      */
0435     virtual MetadataProcessor* createMetadataProcessor() const;
0436 
0437     /**
0438      * Supported if HostSupportsEditHints
0439      *
0440      * Before an edit operation starts when it has finished, specify a hint for it.
0441      * Change hints are optional and may allow optimizations.
0442      *
0443      * When aboutToEdit() has been called, editingFinished() must be called afterwards.
0444      * It is strongly recommended to use the EditHintScope instead of these methods.
0445      */
0446     virtual void aboutToEdit(const QUrl& url, EditHints hints);
0447     virtual void editingFinished(const QUrl& url, EditHints hints);
0448 
0449     /**
0450      * Returns a string version of libkipi release ID.
0451      */
0452     static QString version();
0453 
0454     /**
0455      * Return a list of supported image MIME types by Qt image reader.
0456      * @param readWrite query Qt to list MIME types in read mode (@c false), or in write mode (@c true).
0457      */
0458     static QStringList supportedImageMimeTypes(bool readWrite=false);
0459 
0460 Q_SIGNALS:
0461 
0462     /**
0463      * Emit when item selection has changed from host application user interface.
0464      * @param hasSelection set @c true if items are select or not in collection.
0465      */
0466     void selectionChanged(bool hasSelection);
0467 
0468     /**
0469      * Emit when current album selection as changed from host application user interface.
0470      * @param hasSelection @c true if album are select or not in collection.
0471      */
0472     void currentAlbumChanged(bool hasSelection);
0473 
0474     /** Emit when host application has rendered item thumbnail. See asynchronous thumbnail() and thumbnails()
0475      *  methods for details.
0476      */
0477     void gotThumbnail(const QUrl&, const QPixmap&);
0478 
0479     /** Emit when host application has rendered item preview image. See asynchronous preview() methods for details.
0480      */
0481     void gotPreview(const QUrl&, const QImage&);
0482 
0483     /**
0484      * This signal is emit from kipi host when a progress item is canceled. id is identification string of progress item.
0485      */
0486     void progressCanceled(const QString& id);
0487 
0488     /**
0489      * Supported if HostSupportsItemReservation
0490      *
0491      * Emitted from reservedForAction() and clearReservation(), respectively.
0492      * */
0493     void reservedForAction(const QUrl& url, const QString& descriptionOfAction);
0494     void reservationCleared(const QUrl& url);
0495 
0496 protected:
0497 
0498     /**
0499      * Return a bitwise or of the KIPI::Features that thus application support.
0500      */
0501     virtual int features() const = 0;
0502 
0503 private:
0504 
0505     bool hasFeature(const QString& feature) const;
0506 
0507 private:
0508 
0509     friend class PluginLoader;
0510 };
0511 
0512 // ---------------------------------------------------------------------------------------------------------------
0513 
0514 /**
0515  * @class FileReadLocker interface.h <KIPI/Interface>
0516  *
0517  * Convenience classes creating a FileReadWriteLock and locking it for you.
0518  * It is strongly recommended to use FileReadWriteLock only through these
0519  * classes, created on the stack, as unlocking will be done automatically for you.
0520  *
0521  * The API is modelled according to the QReadLocker/QWriteLocker classes.
0522  *
0523  * @note Operations are no-ops and fileReadWriteLock() is a nullptr if not HostSupportsReadWriteLock.
0524  */
0525 class LIBKIPI_EXPORT FileReadLocker
0526 {
0527 public:
0528 
0529     FileReadLocker(Interface* const iface, const QUrl& url);
0530     FileReadLocker(ImageInfoShared* const info);
0531     ~FileReadLocker();
0532 
0533     FileReadWriteLock* fileReadWriteLock() const;
0534     void unlock();
0535     void relock();
0536 
0537 private:
0538 
0539     FileReadWriteLock* const d;
0540 };
0541 
0542 // ---------------------------------------------------------------------------------------------------------------
0543 
0544 /**
0545  * @class FileWriteLocker interface.h <KIPI/Interface>
0546  *
0547  * The FileWriteLocker class.
0548  */
0549 class LIBKIPI_EXPORT FileWriteLocker
0550 {
0551 public:
0552 
0553     FileWriteLocker(Interface* const iface, const QUrl& url);
0554     FileWriteLocker(ImageInfoShared* const info);
0555     ~FileWriteLocker();
0556 
0557     FileReadWriteLock* fileReadWriteLock() const;
0558     void unlock();
0559     void relock();
0560 
0561 private:
0562 
0563     FileReadWriteLock* const d;
0564 };
0565 
0566 // ---------------------------------------------------------------------------------------------------------------
0567 
0568 /**
0569  * @class EditHintScope interface.h <KIPI/Interface>
0570  *
0571  * The EditHintScope class.
0572  */
0573 class LIBKIPI_EXPORT EditHintScope
0574 {
0575 public:
0576 
0577     EditHintScope(Interface* const iface, const QUrl& url, EditHints hints);
0578     ~EditHintScope();
0579 
0580     void changeAborted();
0581 
0582 private:
0583 
0584     class Private;
0585     std::unique_ptr<Private> const d;
0586 };
0587 
0588 } // namespace KIPI
0589 
0590 Q_DECLARE_OPERATORS_FOR_FLAGS(KIPI::EditHints)
0591 
0592 #endif /* KIPI_INTERFACE_H */