File indexing completed on 2025-01-19 03:51:27

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2004-05-16
0007  * Description : time adjust thread.
0008  *
0009  * SPDX-FileCopyrightText: 2012      by Smit Mehta <smit dot meh at gmail dot com>
0010  * SPDX-FileCopyrightText: 2012-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  * SPDX-FileCopyrightText: 2018-2021 by Maik Qualmann <metzpinguin at gmail dot com>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #include "timeadjustthread.h"
0018 
0019 // Qt includes
0020 
0021 #include <QFileInfo>
0022 
0023 // Local includes
0024 
0025 #include "dmetadata.h"
0026 #include "timeadjusttask.h"
0027 
0028 namespace DigikamGenericTimeAdjustPlugin
0029 {
0030 
0031 class Q_DECL_HIDDEN TimeAdjustThread::Private
0032 {
0033 
0034 public:
0035 
0036     explicit Private()
0037       : iface(nullptr)
0038     {
0039     }
0040 
0041     // Settings from GUI.
0042 
0043     TimeAdjustContainer settings;
0044 
0045     QMap<QUrl, int>     itemsMap;
0046 
0047     DInfoInterface*     iface;
0048 };
0049 
0050 
0051 TimeAdjustThread::TimeAdjustThread(QObject* const parent, DInfoInterface* const iface)
0052     : ActionThreadBase(parent),
0053       d(new Private)
0054 {
0055     d->iface = iface;
0056 }
0057 
0058 TimeAdjustThread::~TimeAdjustThread()
0059 {
0060     // cancel the thread
0061 
0062     cancel();
0063 
0064     // wait for the thread to finish
0065 
0066     wait();
0067 
0068     delete d;
0069 }
0070 
0071 void TimeAdjustThread::setUpdatedDates(const QMap<QUrl, int>& itemsMap)
0072 {
0073     d->itemsMap = itemsMap;
0074 
0075     ActionJobCollection collection;
0076 
0077     Q_FOREACH (const QUrl& url, itemsMap.keys())
0078     {
0079         TimeAdjustTask* const t = new TimeAdjustTask(url, this);
0080         t->setSettings(d->settings);
0081 
0082         connect(t, SIGNAL(signalProcessStarted(QUrl)),
0083                 this, SIGNAL(signalProcessStarted(QUrl)));
0084 
0085         connect(t, SIGNAL(signalProcessEnded(QUrl,QDateTime,QDateTime,int)),
0086                 this, SIGNAL(signalProcessEnded(QUrl,QDateTime,QDateTime,int)));
0087 
0088         connect(t, SIGNAL(signalDateTimeForUrl(QUrl,QDateTime,bool)),
0089                 this, SIGNAL(signalDateTimeForUrl(QUrl,QDateTime,bool)));
0090 
0091         collection.insert(t, 0);
0092      }
0093 
0094     appendJobs(collection);
0095 }
0096 
0097 void TimeAdjustThread::setPreviewDates(const QMap<QUrl, int>& itemsMap)
0098 {
0099     d->itemsMap = itemsMap;
0100 
0101     ActionJobCollection collection;
0102 
0103     Q_FOREACH (const QUrl& url, itemsMap.keys())
0104     {
0105         TimePreviewTask* const t = new TimePreviewTask(url, this);
0106         t->setSettings(d->settings);
0107 
0108         connect(t, SIGNAL(signalPreviewReady(QUrl,QDateTime,QDateTime)),
0109                 this, SIGNAL(signalPreviewReady(QUrl,QDateTime,QDateTime)));
0110 
0111         collection.insert(t, 0);
0112      }
0113 
0114     appendJobs(collection);
0115 }
0116 
0117 void TimeAdjustThread::setSettings(const TimeAdjustContainer& settings)
0118 {
0119     d->settings = settings;
0120 }
0121 
0122 QDateTime TimeAdjustThread::readTimestamp(const QUrl& url) const
0123 {
0124     QDateTime dateTime;
0125 
0126     switch (d->settings.dateSource)
0127     {
0128         case TimeAdjustContainer::APPDATE:
0129         {
0130             dateTime = readApplicationTimestamp(url);
0131             break;
0132         }
0133 
0134         case TimeAdjustContainer::FILENAME:
0135         {
0136             dateTime = readFileNameTimestamp(url);
0137             break;
0138         }
0139 
0140         case TimeAdjustContainer::FILEDATE:
0141         {
0142             dateTime = readFileTimestamp(url);
0143             break;
0144         }
0145 
0146         case TimeAdjustContainer::METADATADATE:
0147         {
0148             dateTime = readMetadataTimestamp(url);
0149             break;
0150         }
0151 
0152         default:  // CUSTOMDATE
0153         {
0154             dateTime = QDateTime(d->settings.customDate.date(),
0155                                  d->settings.customTime.time());
0156 
0157             break;
0158         }
0159     }
0160 
0161     return dateTime;
0162 }
0163 
0164 QDateTime TimeAdjustThread::readApplicationTimestamp(const QUrl& url) const
0165 {
0166     DItemInfo info(d->iface->itemInfo(url));
0167 
0168     if (info.dateTime().isValid())
0169     {
0170         return info.dateTime();
0171     }
0172 
0173     return QDateTime();
0174 }
0175 
0176 QDateTime TimeAdjustThread::readFileNameTimestamp(const QUrl& url) const
0177 {
0178     return d->settings.getDateTimeFromString(url.fileName());
0179 }
0180 
0181 QDateTime TimeAdjustThread::readFileTimestamp(const QUrl& url) const
0182 {
0183     QFileInfo fileInfo(url.toLocalFile());
0184 
0185     return fileInfo.lastModified();
0186 }
0187 
0188 QDateTime TimeAdjustThread::readMetadataTimestamp(const QUrl& url) const
0189 {
0190     QScopedPointer<DMetadata> meta(new DMetadata);
0191 
0192     if (!meta->load(url.toLocalFile()))
0193     {
0194         return QDateTime();
0195     }
0196 
0197     QDateTime dateTime;
0198     QString exifDateTimeFormat = QLatin1String("yyyy:MM:dd hh:mm:ss");
0199     QString xmpDateTimeFormat  = QLatin1String("yyyy-MM-ddThh:mm:ss");
0200 
0201     switch (d->settings.metadataSource)
0202     {
0203         case TimeAdjustContainer::EXIFIPTCXMP:
0204         {
0205             dateTime = meta->getItemDateTime();
0206             break;
0207         }
0208 
0209         case TimeAdjustContainer::EXIFCREATED:
0210         {
0211             dateTime = QDateTime::fromString(meta->getExifTagString("Exif.Image.DateTime"),
0212                                              exifDateTimeFormat);
0213             break;
0214         }
0215 
0216         case TimeAdjustContainer::EXIFORIGINAL:
0217         {
0218             dateTime = QDateTime::fromString(meta->getExifTagString("Exif.Photo.DateTimeOriginal"),
0219                                              exifDateTimeFormat);
0220             break;
0221         }
0222 
0223         case TimeAdjustContainer::EXIFDIGITIZED:
0224         {
0225             dateTime = QDateTime::fromString(meta->getExifTagString("Exif.Photo.DateTimeDigitized"),
0226                                              exifDateTimeFormat);
0227             break;
0228         }
0229 
0230         case TimeAdjustContainer::IPTCCREATED:
0231         {
0232             // we have to truncate the timezone from the time, otherwise it cannot be converted to a QTime
0233 
0234             dateTime = QDateTime(QDate::fromString(meta->getIptcTagString("Iptc.Application2.DateCreated"),
0235                                                    Qt::ISODate),
0236                                  QTime::fromString(meta->getIptcTagString("Iptc.Application2.TimeCreated").left(8),
0237                                                    Qt::ISODate));
0238             break;
0239         }
0240 
0241         case TimeAdjustContainer::XMPCREATED:
0242         {
0243             dateTime = QDateTime::fromString(meta->getXmpTagString("Xmp.xmp.CreateDate"),
0244                                              xmpDateTimeFormat);
0245             break;
0246         }
0247 
0248         case TimeAdjustContainer::FUZZYCREATED:
0249         {
0250             dateTime = d->settings.getDateTimeFromString(meta->getExifTagString("Exif.Image.DateTime"));
0251             break;
0252         }
0253 
0254         case TimeAdjustContainer::FUZZYORIGINAL:
0255         {
0256             dateTime = d->settings.getDateTimeFromString(meta->getExifTagString("Exif.Photo.DateTimeOriginal"));
0257             break;
0258         }
0259 
0260         case TimeAdjustContainer::FUZZYDIGITIZED:
0261         {
0262             dateTime = d->settings.getDateTimeFromString(meta->getExifTagString("Exif.Photo.DateTimeDigitized"));
0263             break;
0264         }
0265 
0266         default:
0267         {
0268             // dateTime stays invalid
0269 
0270             break;
0271         }
0272     };
0273 
0274     return dateTime;
0275 }
0276 
0277 int TimeAdjustThread::indexForUrl(const QUrl& url) const
0278 {
0279     return d->itemsMap.value(url);
0280 }
0281 
0282 } // namespace DigikamGenericTimeAdjustPlugin
0283 
0284 #include "moc_timeadjustthread.cpp"