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"