File indexing completed on 2024-05-12 04:33:18

0001 /*
0002     SPDX-FileCopyrightText: 2009-2010 Michael G. Hansen <mike at mghansen dot de>
0003     SPDX-FileCopyrightText: 2011-2018 Gilles Caulier <caulier dot gilles at gmail dot com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "kipiinterface.h"
0009 
0010 // Qt includes
0011 
0012 #include <QTextStream>
0013 #include <QDebug>
0014 #include <QIcon>
0015 #include <QFileInfo>
0016 
0017 // Libkipi includes
0018 
0019 #include "libkipi_version.h"
0020 #include "imagecollection.h"
0021 
0022 // KF includes
0023 
0024 #ifdef HAVE_KEXIV2
0025 #   include <kexiv2/kexiv2.h>
0026 #endif
0027 
0028 // Local includes
0029 
0030 #include "kipiimageinfoshared.h"
0031 #include "kipiimagecollectionselector.h"
0032 #include "kipiuploadwidget.h"
0033 #include "kipiimagecollectionshared.h"
0034 #include "kipiwriteimage.h"
0035 
0036 namespace KXMLKipiCmd
0037 {
0038 
0039 KipiInterface::KipiInterface(QObject* const parent, const QString& name)
0040     : Interface(parent, name),
0041       m_selectedImages(),
0042       m_selectedAlbums(),
0043       m_albums()
0044 {
0045 }
0046 
0047 KipiInterface::~KipiInterface()
0048 {
0049 }
0050 
0051 ImageCollection KipiInterface::currentAlbum()
0052 {
0053     qDebug() << "Called by plugins";
0054 
0055     QUrl currentAlbumUrl;
0056 
0057     if (!m_selectedAlbums.isEmpty())
0058     {
0059         currentAlbumUrl = m_selectedAlbums.at(0);
0060     }
0061 
0062     return (ImageCollection(new KipiImageCollectionShared(currentAlbumUrl)));
0063 }
0064 
0065 ImageCollection KipiInterface::currentSelection()
0066 {
0067     qDebug() << "Called by plugins";
0068 
0069     return (ImageCollection(new KipiImageCollectionShared(m_selectedImages)));
0070 }
0071 
0072 QList<ImageCollection> KipiInterface::allAlbums()
0073 {
0074     QList<ImageCollection> listAllAlbums;
0075 
0076     for (QList<QUrl>::const_iterator it = m_albums.constBegin(); it!=m_albums.constEnd(); ++it)
0077     {
0078         listAllAlbums.append(ImageCollection(new KipiImageCollectionShared(*it)));
0079     }
0080 
0081     // make sure albums which have been specified as selectedalbums are also in the allAlbums list:
0082     for (QList<QUrl>::const_iterator it = m_selectedAlbums.constBegin(); it!=m_selectedAlbums.constEnd(); ++it)
0083     {
0084         if (!m_albums.contains(*it))
0085         {
0086             listAllAlbums.append(ImageCollection(new KipiImageCollectionShared(*it)));
0087         }
0088     }
0089 
0090     return listAllAlbums;
0091 }
0092 
0093 ImageInfo KipiInterface::info(const QUrl& url)
0094 {
0095     qDebug() << QString::fromLatin1( "Plugin wants information about image \"%1\"").arg( url.url() );
0096 
0097     return (ImageInfo(new KipiImageInfoShared(this, url)));
0098 }
0099 
0100 bool KipiInterface::addImage(const QUrl& url, QString& errmsg)
0101 {
0102     Q_UNUSED(errmsg);
0103     qDebug() << QString::fromLatin1( "Plugin added an image: \"%1\"").arg( url.url() );
0104 
0105     return true;
0106 }
0107 
0108 void KipiInterface::delImage(const QUrl& url)
0109 {
0110     qDebug() << QString::fromLatin1( "Plugin deleted an image: \"%1\"").arg( url.url() );
0111 }
0112 
0113 void KipiInterface::refreshImages(const QList<QUrl>& urls)
0114 {
0115     qDebug() << QString::fromLatin1( "Plugin asks to refresh %1 images:").arg( urls.size() );
0116 
0117     for (QList<QUrl>::ConstIterator it = urls.constBegin(); it!=urls.constEnd(); ++it)
0118     {
0119         qDebug() << QString::fromLatin1("  ") + (*it).url();
0120     }
0121 }
0122 
0123 int KipiInterface::features() const
0124 {
0125     qDebug() << "Called by plugins";
0126 
0127     return   ImagesHasTime
0128 #ifdef HAVE_KEXIV2
0129            | HostSupportsMetadataProcessing
0130 #endif
0131 
0132     ;
0133 }
0134 
0135 ImageCollectionSelector* KipiInterface::imageCollectionSelector(QWidget* parent)
0136 {
0137     qDebug() << "Called by plugins";
0138 
0139     return (new KipiImageCollectionSelector(this, parent));
0140 }
0141 
0142 UploadWidget* KipiInterface::uploadWidget(QWidget* parent)
0143 {
0144     qDebug() << "Called by plugins";
0145 
0146     return (new KipiUploadWidget(this, parent));
0147 }
0148 
0149 void KipiInterface::addSelectedImages(const QList<QUrl>& images)
0150 {
0151     m_selectedImages.append(images);
0152 }
0153 
0154 void KipiInterface::addSelectedImage(const QUrl& image)
0155 {
0156     m_selectedImages.append(image);
0157 }
0158 
0159 void KipiInterface::addAlbums(const QList<QUrl>& albums)
0160 {
0161     for (QList<QUrl>::const_iterator it = albums.constBegin(); it!=albums.constEnd(); ++it)
0162     {
0163         addAlbum(*it);
0164     }
0165 }
0166 
0167 void KipiInterface::addAlbum(const QUrl& album)
0168 {
0169     m_albums.append(album);
0170 
0171     // TODO: recurse through sub-directories?
0172 }
0173 
0174 void KipiInterface::addSelectedAlbums(const QList<QUrl>& albums)
0175 {
0176     for (QList<QUrl>::const_iterator it = albums.constBegin(); it!=albums.constEnd(); ++it)
0177     {
0178         addSelectedAlbum(*it);
0179     }
0180 }
0181 
0182 void KipiInterface::addSelectedAlbum(const QUrl& album)
0183 {
0184     m_selectedAlbums.append(album);
0185 
0186     // TODO: recurse through sub-directories?
0187 }
0188 
0189 QVariant KipiInterface::hostSetting(const QString& settingName)
0190 {
0191     Q_UNUSED(settingName);
0192     return QVariant();
0193 }
0194 
0195 void KipiInterface::thumbnails(const QList<QUrl>& list, int)
0196 {
0197     for (const QUrl& url : list)
0198     {
0199         QIcon icon(url.url());
0200         Q_EMIT gotThumbnail(url, icon.pixmap(256));
0201     }
0202 }
0203 
0204 bool KipiInterface::saveImage(const QUrl& url, const QString& format,
0205                               const QByteArray& data, uint width, uint height,
0206                               bool  sixteenBit, bool hasAlpha, bool* cancel)
0207 {
0208     KIPIWriteImage writer;
0209     writer.setImageData(data, width, height, sixteenBit, hasAlpha);
0210     writer.setCancel(cancel);
0211 
0212     if (format.toUpper() == QLatin1String("JPG") ||
0213         format.toUpper() == QLatin1String("JPEG"))
0214     {
0215         return writer.write2JPEG(url.toLocalFile());
0216     }
0217 
0218     if (format.toUpper() == QLatin1String("TIF") ||
0219         format.toUpper() == QLatin1String("TIFF"))
0220     {
0221         return writer.write2TIFF(url.toLocalFile());
0222     }
0223 
0224     if (format.toUpper() == QLatin1String("PNG"))
0225     {
0226         return writer.write2PNG(url.toLocalFile());
0227     }
0228 
0229     if (format.toUpper() == QLatin1String("PPM"))
0230     {
0231         return writer.write2PPM(url.toLocalFile());
0232     }
0233 
0234     return false;
0235 }
0236 
0237 // ---------------------------------------------------------------------------------------
0238 
0239 #ifdef HAVE_KEXIV2
0240 
0241 class KipiMetadataProcessor : public KIPI::MetadataProcessor
0242 {
0243 public:
0244 
0245     KipiMetadataProcessor()  {};
0246     ~KipiMetadataProcessor() override {};
0247 
0248     bool load(const QUrl& url) override
0249     {
0250         return m_meta.load(url.toLocalFile());
0251     }
0252 
0253     bool save(const QUrl& url, bool writeToFileOnly) override
0254     {
0255         if (writeToFileOnly)
0256             m_meta.setMetadataWritingMode((int) KExiv2Iface::KExiv2::WRITETOIMAGEONLY);
0257 
0258         return m_meta.save(url.toLocalFile());
0259     }
0260 
0261     bool applyChanges() override
0262     {
0263         return m_meta.applyChanges();
0264     }
0265 
0266     QSize getPixelSize() override
0267     {
0268         return m_meta.getPixelSize();
0269     }
0270 
0271     bool setImageProgramId(const QString& program, const QString& version) override
0272     {
0273         return m_meta.setImageProgramId(program, version);
0274     }
0275 
0276     QSize getImageDimensions() override
0277     {
0278         return m_meta.getImageDimensions();
0279     }
0280 
0281     bool setImageDimensions(const QSize& size) override
0282     {
0283         return m_meta.setImageDimensions(size);
0284     }
0285 
0286     int getImageOrientation() override
0287     {
0288         return m_meta.getImageOrientation();
0289     }
0290 
0291     bool setImageOrientation(int orientation) override
0292     {
0293         return m_meta.setImageOrientation((KExiv2Iface::KExiv2::ImageOrientation)orientation);
0294     }
0295 
0296     bool rotateExifQImage(QImage& img, int orientation) override
0297     {
0298         return m_meta.rotateExifQImage(img, (KExiv2Iface::KExiv2::ImageOrientation)orientation);
0299     }
0300 
0301     QDateTime getImageDateTime() override
0302     {
0303         return m_meta.getImageDateTime();
0304     }
0305 
0306     bool setImageDateTime(const QDateTime& dt) override
0307     {
0308         return m_meta.setImageDateTime(dt);
0309     }
0310 
0311     bool getImagePreview(QImage& img) override
0312     {
0313         return m_meta.getImagePreview(img);
0314     }
0315 
0316     bool setImagePreview(const QImage& img) override
0317     {
0318         return m_meta.setImagePreview(img);
0319     }
0320 
0321     bool hasExif() override
0322     {
0323         return m_meta.hasExif();
0324     }
0325 
0326     bool hasIptc() override
0327     {
0328         return m_meta.hasIptc();
0329     }
0330 
0331     bool hasXmp() override
0332     {
0333         return m_meta.hasXmp();
0334     }
0335 
0336     QByteArray getExif() override
0337     {
0338         return m_meta.getExifEncoded();
0339     }
0340 
0341     QByteArray getIptc() override
0342     {
0343         return m_meta.getIptc();
0344     }
0345 
0346     QByteArray getXmp() override
0347     {
0348         return m_meta.getXmp();
0349     }
0350 
0351     bool setExif(const QByteArray& data) override
0352     {
0353         return m_meta.setExif(data);
0354     }
0355 
0356     bool setIptc(const QByteArray& data) override
0357     {
0358         return m_meta.setIptc(data);
0359     }
0360 
0361     bool setXmp(const QByteArray& data) override
0362     {
0363         return m_meta.setXmp(data);
0364     }
0365 
0366     bool registerXmpNameSpace(const QString& uri, const QString& prefix) override
0367     {
0368         return m_meta.registerXmpNameSpace(uri, prefix);
0369     }
0370 
0371     bool supportXmp() override
0372     {
0373         return m_meta.supportXmp();
0374     }
0375 
0376     bool canWriteXmp(const QUrl& url) override
0377     {
0378         return m_meta.canWriteXmp(url.toLocalFile());
0379     }
0380 
0381     bool removeExifTags(const QStringList& tagFilters) override
0382     {
0383         KExiv2Iface::KExiv2::MetaDataMap m = m_meta.getExifTagsDataList(tagFilters);
0384 
0385         if (m.isEmpty())
0386             return false;
0387 
0388         for (KExiv2Iface::KExiv2::MetaDataMap::iterator it = m.begin(); it != m.end(); ++it)
0389         {
0390             m_meta.removeExifTag(it.key().toLatin1().constData());
0391         }
0392 
0393         return true;
0394     }
0395 
0396     bool removeIptcTags(const QStringList& tagFilters) override
0397     {
0398         KExiv2Iface::KExiv2::MetaDataMap m = m_meta.getIptcTagsDataList(tagFilters);
0399 
0400         if (m.isEmpty())
0401             return false;
0402 
0403         for (KExiv2Iface::KExiv2::MetaDataMap::iterator it = m.begin(); it != m.end(); ++it)
0404         {
0405             m_meta.removeIptcTag(it.key().toLatin1().constData());
0406         }
0407 
0408         return true;
0409     }
0410 
0411     bool removeXmpTags(const QStringList& tagFilters) override
0412     {
0413         KExiv2Iface::KExiv2::MetaDataMap m = m_meta.getXmpTagsDataList(tagFilters);
0414 
0415         if (m.isEmpty())
0416             return false;
0417 
0418         for (KExiv2Iface::KExiv2::MetaDataMap::iterator it = m.begin(); it != m.end(); ++it)
0419         {
0420             m_meta.removeXmpTag(it.key().toLatin1().constData());
0421         }
0422 
0423         return true;
0424     }
0425 
0426     bool getGPSInfo(double& alt, double& lat, double& lon) override
0427     {
0428         return m_meta.getGPSInfo(alt, lat, lon);
0429     }
0430 
0431     bool setGPSInfo(const double alt, const double lat, const double lon) override
0432     {
0433         return m_meta.setGPSInfo(alt, lat, lon);
0434     }
0435 
0436     bool removeGPSInfo() override
0437     {
0438         return m_meta.removeGPSInfo();
0439     }
0440 
0441     QString getExifTagString(const QString& tag) override
0442     {
0443         return m_meta.getExifTagString(tag.toLatin1().constData());
0444     }
0445 
0446     bool setExifTagString(const QString& tag, const QString& val) override
0447     {
0448         return m_meta.setExifTagString(tag.toLatin1().constData(), val);
0449     }
0450 
0451     bool getExifTagRational(const QString& tag, long int& num, long int& den) override
0452     {
0453         return m_meta.getExifTagRational(tag.toLatin1().constData(), num, den);
0454     }
0455 
0456     bool setExifTagRational(const QString& tag, long int num, long int den) override
0457     {
0458         return m_meta.setExifTagRational(tag.toLatin1().constData(), num, den);
0459     }
0460 
0461     QString getXmpTagString(const QString& tag) override
0462     {
0463         return m_meta.getXmpTagString(tag.toLatin1().constData());
0464     }
0465 
0466     bool setXmpTagString(const QString& tag, const QString& val) override
0467     {
0468         return m_meta.setXmpTagString(tag.toLatin1().constData(), val);
0469     }
0470 
0471     QStringList getXmpKeywords() override
0472     {
0473         return m_meta.getXmpKeywords();
0474     }
0475 
0476     bool  setXmpKeywords(const QStringList& keywords) override
0477     {
0478         return m_meta.setXmpKeywords(keywords);
0479     }
0480 
0481     QVariant getXmpTagVariant(const QString& tag) override
0482     {
0483         return m_meta.getXmpTagVariant(tag.toLatin1().constData());
0484     }
0485 
0486 private:
0487 
0488     KExiv2Iface::KExiv2 m_meta;
0489 };
0490 
0491 MetadataProcessor* KipiInterface::createMetadataProcessor() const
0492 {
0493     return (new KipiMetadataProcessor);
0494 }
0495 
0496 #else // HAVE_KEXIV2
0497 
0498 MetadataProcessor* KipiInterface::createMetadataProcessor() const
0499 {
0500     qDebug() << "This interface was not compiled with libkexiv2 to support Metadata processing";
0501     return 0;
0502 }
0503 
0504 #endif // HAVE_KEXIV2
0505 
0506 // ---------------------------------------------------------------------------------------
0507 
0508 FileReadWriteLock* KipiInterface::createReadWriteLock(const QUrl&) const
0509 {
0510     return nullptr;  // TODO
0511 }
0512 
0513 } // namespace KXMLKipiCmd
0514 
0515 #include "moc_kipiinterface.cpp"