File indexing completed on 2025-01-19 03:55:35

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2017-05-06
0007  * Description : interface to item information for shared tools
0008  *               based on DMetadata. This interface is used in all cases
0009  *               where no database is available (aka Showfoto).
0010  *
0011  * SPDX-FileCopyrightText: 2017-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0012  * SPDX-FileCopyrightText: 2019-2020 by Minh Nghia Duong <minhnghiaduong997 at gmail dot com>
0013  *
0014  * SPDX-License-Identifier: GPL-2.0-or-later
0015  *
0016  * ============================================================ */
0017 
0018 #include "dmetainfoiface.h"
0019 
0020 // Qt includes
0021 
0022 #include <QFileInfo>
0023 #include <QStandardPaths>
0024 #include <QScopedPointer>
0025 
0026 // KDE includes
0027 
0028 #include <klocalizedstring.h>
0029 
0030 // Local includes
0031 
0032 #include "dmetadata.h"
0033 #include "photoinfocontainer.h"
0034 #include "videoinfocontainer.h"
0035 #include "template.h"
0036 #include "dfileselector.h"
0037 #include "digikam_debug.h"
0038 
0039 namespace Digikam
0040 {
0041 
0042 class Q_DECL_HIDDEN DMetaInfoIface::Private
0043 {
0044 public:
0045 
0046     explicit Private()
0047       : dirSelector(nullptr)
0048     {
0049     }
0050 
0051     DFileSelector* dirSelector;
0052     QList<QUrl>    urls;
0053 };
0054 
0055 DMetaInfoIface::DMetaInfoIface(QObject* const parent, const QList<QUrl>& lst)
0056     : DInfoInterface(parent),
0057       d             (new Private)
0058 {
0059     d->urls = lst;
0060 }
0061 
0062 DMetaInfoIface::~DMetaInfoIface()
0063 {
0064     delete d;
0065 }
0066 
0067 void DMetaInfoIface::slotDateTimeForUrl(const QUrl& url, const QDateTime& /*dt*/, bool /*updModDate*/)
0068 {
0069     Q_EMIT signalItemChanged(url);
0070 }
0071 
0072 void DMetaInfoIface::slotMetadataChangedForUrl(const QUrl& url)
0073 {
0074     Q_EMIT signalItemChanged(url);
0075 }
0076 
0077 void DMetaInfoIface::parseAlbumItemsRecursive()
0078 {
0079     Q_EMIT signalAlbumItemsRecursiveCompleted(d->urls);
0080 }
0081 
0082 QList<QUrl> DMetaInfoIface::currentAlbumItems() const
0083 {
0084     return d->urls;
0085 }
0086 
0087 QList<QUrl> DMetaInfoIface::currentSelectedItems() const
0088 {
0089     // No multiple items selection is available in this interface.
0090 
0091     return currentAlbumItems();
0092 }
0093 
0094 QList<QUrl> DMetaInfoIface::allAlbumItems() const
0095 {
0096     // No album management is available in this interface.
0097 
0098     return currentAlbumItems();
0099 }
0100 
0101 DMetaInfoIface::DInfoMap DMetaInfoIface::itemInfo(const QUrl& url) const
0102 {
0103     DInfoMap map;
0104 
0105     if (d->urls.contains(url))
0106     {
0107         QScopedPointer<DMetadata> meta(new DMetadata(url.toLocalFile()));
0108         QString   def = QLatin1String("x-default");
0109         QFileInfo info(url.toLocalFile());
0110 
0111         map.insert(QLatin1String("name"),               info.fileName());
0112         map.insert(QLatin1String("title"),              meta->getItemTitles()[def].caption);
0113         map.insert(QLatin1String("comment"),            meta->getItemComments()[def].caption);
0114         map.insert(QLatin1String("orientation"),        (int)meta->getItemOrientation());
0115         map.insert(QLatin1String("datetime"),           meta->getItemDateTime());
0116         map.insert(QLatin1String("rating"),             meta->getItemRating());
0117         map.insert(QLatin1String("colorlabel"),         meta->getItemColorLabel());
0118         map.insert(QLatin1String("picklabel"),          meta->getItemPickLabel());
0119         map.insert(QLatin1String("filesize"),           (qlonglong)info.size());
0120         map.insert(QLatin1String("dimensions"),         meta->getItemDimensions());
0121 
0122         // Get digiKam Tags Path list of picture from metadata.
0123         // Ex.: "City/Paris/Monuments/Notre Dame"
0124 
0125         QStringList tagsPath;
0126         meta->getItemTagsPath(tagsPath);
0127         map.insert(QLatin1String("tagspath"),           tagsPath);
0128 
0129         // Get digiKam Tags name (keywords) list of picture from metadata.
0130         // Ex.: "Notre Dame"
0131 
0132         QStringList keywords = meta->getMetadataField(MetadataInfo::Keywords).toStringList();
0133         map.insert(QLatin1String("keywords"),           keywords);
0134 
0135         // Get GPS location of picture from metadata.
0136 
0137         double lat = 0.0;
0138         double lng = 0.0;
0139         double alt = 0.0;
0140 
0141         if (meta->getGPSInfo(lat, lng, alt))
0142         {
0143             map.insert(QLatin1String("latitude"),       lat);
0144             map.insert(QLatin1String("longitude"),      lng);
0145             map.insert(QLatin1String("altitude"),       alt);
0146         }
0147 
0148         // Get Copyright information of picture from metadata.
0149 
0150         Template temp;
0151         meta->getCopyrightInformation(temp);
0152 
0153         map.insert(QLatin1String("creators"),           temp.authors());
0154         map.insert(QLatin1String("credit"),             temp.credit());
0155         map.insert(QLatin1String("rights"),             temp.copyright().value(def));
0156         map.insert(QLatin1String("source"),             temp.source());
0157 
0158         PhotoInfoContainer photoInfo = meta->getPhotographInformation();
0159         map.insert(QLatin1String("lens"),               photoInfo.lens);
0160         map.insert(QLatin1String("make"),               photoInfo.make);
0161         map.insert(QLatin1String("model"),              photoInfo.model);
0162         map.insert(QLatin1String("exposuretime"),       photoInfo.exposureTime);
0163         map.insert(QLatin1String("sensitivity"),        photoInfo.sensitivity);
0164         map.insert(QLatin1String("aperture"),           photoInfo.aperture);
0165         map.insert(QLatin1String("focallength"),        photoInfo.focalLength);
0166         map.insert(QLatin1String("focalLength35mm"),    photoInfo.focalLength35mm);
0167 
0168         // Get Video information from metadata
0169 
0170         VideoInfoContainer videoInfo = meta->getVideoInformation();
0171         map.insert(QLatin1String("videocodec"),         videoInfo.videoCodec);
0172 
0173         // TODO: add more video metadata as needed
0174 
0175         // Get complex text containers.
0176 
0177         CaptionsMap titles   = meta->getItemTitles();
0178         map.insert(QLatin1String("titles"),             QVariant::fromValue(titles));
0179         CaptionsMap captions = meta->getItemComments();
0180         map.insert(QLatin1String("captions"),           QVariant::fromValue(captions));
0181 
0182         Template tpl                     = meta->getMetadataTemplate();
0183         DMetadata::AltLangMap copyrights = tpl.copyright();
0184         map.insert(QLatin1String("copyrights"),         QVariant::fromValue(copyrights));
0185         DMetadata::AltLangMap notices    = tpl.rightUsageTerms();
0186         map.insert(QLatin1String("copyrightnotices"),   QVariant::fromValue(notices));
0187     }
0188 
0189     return map;
0190 }
0191 
0192 void DMetaInfoIface::setItemInfo(const QUrl& url, const DInfoMap& map)
0193 {
0194     QScopedPointer<DMetadata> meta(new DMetadata(url.toLocalFile()));
0195     QStringList keys = map.keys();
0196 
0197     if (map.contains(QLatin1String("orientation")))
0198     {
0199         meta->setItemOrientation((DMetadata::ImageOrientation)map[QLatin1String("orientation")].toInt());
0200         keys.removeAll(QLatin1String("orientation"));
0201     }
0202 
0203     if (map.contains(QLatin1String("rating")))
0204     {
0205         meta->setItemRating(map[QLatin1String("rating")].toInt());
0206         keys.removeAll(QLatin1String("rating"));
0207     }
0208 
0209     if (map.contains(QLatin1String("colorlabel")))
0210     {
0211         meta->setItemColorLabel(map[QLatin1String("colorlabel")].toInt());
0212         keys.removeAll(QLatin1String("colorlabel"));
0213     }
0214 
0215     if (map.contains(QLatin1String("picklabel")))
0216     {
0217         meta->setItemPickLabel(map[QLatin1String("picklabel")].toInt());
0218         keys.removeAll(QLatin1String("picklabel"));
0219     }
0220 
0221     if (map.contains(QLatin1String("titles")))
0222     {
0223         meta->setItemTitles(qvariant_cast<CaptionsMap>(map[QLatin1String("titles")]));
0224         keys.removeAll(QLatin1String("titles"));
0225     }
0226 
0227     if (map.contains(QLatin1String("captions")))
0228     {
0229         meta->setItemComments(qvariant_cast<CaptionsMap>(map[QLatin1String("captions")]));
0230         keys.removeAll(QLatin1String("captions"));
0231     }
0232 
0233     if (map.contains(QLatin1String("copyrights")))
0234     {
0235         Template tpl = meta->getMetadataTemplate();
0236         tpl.setCopyright(qvariant_cast<DMetadata::AltLangMap>(map[QLatin1String("copyrights")]));
0237         meta->setMetadataTemplate(tpl);
0238         keys.removeAll(QLatin1String("copyrights"));
0239     }
0240 
0241     if (map.contains(QLatin1String("copyrightnotices")))
0242     {
0243         Template tpl = meta->getMetadataTemplate();
0244         tpl.setRightUsageTerms(qvariant_cast<DMetadata::AltLangMap>(map[QLatin1String("copyrightnotices")]));
0245         meta->setMetadataTemplate(tpl);
0246         keys.removeAll(QLatin1String("copyrightnotices"));
0247     }
0248 
0249     if (!keys.isEmpty())
0250     {
0251         qCWarning(DIGIKAM_GENERAL_LOG) << "Keys not yet supported in DMetaInfoIface::setItemInfo():" << keys;
0252     }
0253 
0254     Q_EMIT signalItemChanged(url);
0255 }
0256 
0257 bool DMetaInfoIface::supportAlbums() const
0258 {
0259     return false;
0260 }
0261 
0262 QWidget* DMetaInfoIface::uploadWidget(QWidget* const parent) const
0263 {
0264     if (!d->dirSelector)
0265     {
0266         d->dirSelector = new DFileSelector(parent);
0267         d->dirSelector->setFileDlgMode(QFileDialog::Directory);
0268         d->dirSelector->setFileDlgOptions(QFileDialog::ShowDirsOnly);
0269         d->dirSelector->setFileDlgTitle(i18nc("@title:window", "Destination Folder"));
0270         d->dirSelector->lineEdit()->setPlaceholderText(i18n("Output Destination Path"));
0271 
0272         connect(d->dirSelector, SIGNAL(signalUrlSelected(QUrl)),
0273                 this, SIGNAL(signalUploadUrlChanged()));
0274     }
0275 
0276     QFileInfo info(!d->urls.isEmpty() ? d->urls[0].toLocalFile() : QString());
0277     d->dirSelector->setFileDlgPath(info.absolutePath());
0278 
0279     return d->dirSelector;
0280 }
0281 
0282 QUrl DMetaInfoIface::uploadUrl() const
0283 {
0284     return QUrl::fromLocalFile(d->dirSelector->fileDlgPath());
0285 }
0286 
0287 QUrl DMetaInfoIface::defaultUploadUrl() const
0288 {
0289     QUrl place       = QUrl::fromLocalFile(QDir::homePath());
0290     QStringList pics = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
0291 
0292     if (!pics.isEmpty())
0293     {
0294         place = QUrl::fromLocalFile(pics.first());
0295     }
0296 
0297     QList<QUrl> lst = currentAlbumItems();
0298 
0299     if (!lst.isEmpty())
0300     {
0301         QUrl trg = lst.first().adjusted(QUrl::RemoveFilename);
0302 
0303         if (!trg.isEmpty())
0304         {
0305             place = trg;
0306         }
0307     }
0308 
0309     return place;
0310 }
0311 
0312 void DMetaInfoIface::deleteImage(const QUrl& url)
0313 {
0314 
0315 #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
0316 
0317     QFile::moveToTrash(url.toLocalFile());
0318 
0319 #else
0320 
0321     QFile::remove(url.toLocalFile());
0322 
0323 #endif
0324 
0325     Q_EMIT signalRemoveImageFromAlbum(url);
0326 }
0327 
0328 #ifdef HAVE_GEOLOCATION
0329 
0330 QList<GPSItemContainer*> DMetaInfoIface::currentGPSItems() const
0331 {
0332     QList<GPSItemContainer*> items;
0333 
0334     Q_FOREACH (const QUrl& url, currentSelectedItems())
0335     {
0336         items << new GPSItemContainer(url);
0337     }
0338 
0339     return items;
0340 }
0341 
0342 #endif
0343 
0344 } // namespace Digikam
0345 
0346 #include "moc_dmetainfoiface.cpp"