diff --git a/core/utilities/timeadjust/detbyclockphotobutton.h b/core/utilities/timeadjust/detbyclockphotobutton.h index 849b297d62..8e9610dbf6 100644 --- a/core/utilities/timeadjust/detbyclockphotobutton.h +++ b/core/utilities/timeadjust/detbyclockphotobutton.h @@ -1,57 +1,56 @@ /* ============================================================ * * This file is a part of the digikam project * http://www.digikam.org * * Date : 2017-01-01 * Description : button for choosing time difference photo which accepts drag & drop * * Copyright (C) 2017 by Markus Leuthold * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_DET_BY_CLOCK_PHOTO_BUTTON_H #define DIGIKAM_DET_BY_CLOCK_PHOTO_BUTTON_H // Qt includes -#include #include #include namespace Digikam { class DetByClockPhotoButton : public QPushButton { Q_OBJECT public: explicit DetByClockPhotoButton(const QString& text) : QPushButton(text) { setAcceptDrops(true); }; void dragEnterEvent(QDragEnterEvent* event); void dropEvent(QDropEvent* event); Q_SIGNALS: void signalClockPhotoDropped(const QUrl&); }; } // namespace Digikam #endif // DIGIKAM_DET_BY_CLOCK_PHOTO_BUTTON_H diff --git a/core/utilities/timeadjust/timeadjustcontainer.h b/core/utilities/timeadjust/timeadjustcontainer.h index ee6593fcc4..59b143a32e 100644 --- a/core/utilities/timeadjust/timeadjustcontainer.h +++ b/core/utilities/timeadjust/timeadjustcontainer.h @@ -1,137 +1,136 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2012-04-19 * Description : time adjust settings container. * * Copyright (C) 2012-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_TIME_ADJUST_CONTAINER_H #define DIGIKAM_TIME_ADJUST_CONTAINER_H // Qt includes #include -#include // Local includes #include "digikam_export.h" namespace Digikam { /** Container that store all timestamp adjustments. */ class DIGIKAM_EXPORT TimeAdjustContainer { public: enum UseDateSource { APPDATE = 0, FILEDATE, METADATADATE, CUSTOMDATE }; enum UseMetaDateType { EXIFIPTCXMP = 0, EXIFCREATED, EXIFORIGINAL, EXIFDIGITIZED, IPTCCREATED, XMPCREATED }; enum UseFileDateType { FILELASTMOD = 0, FILECREATED }; enum AdjType { COPYVALUE = 0, ADDVALUE, SUBVALUE }; public: TimeAdjustContainer(); ~TimeAdjustContainer(); /// Check if at least one option is selected bool atLeastOneUpdateToProcess() const; QDateTime calculateAdjustedDate(const QDateTime& originalTime) const; public: QDateTime customDate; QDateTime customTime; QDateTime adjustmentTime; bool updIfAvailable; bool updEXIFModDate; bool updEXIFOriDate; bool updEXIFDigDate; bool updEXIFThmDate; bool updIPTCDate; bool updXMPVideo; bool updXMPDate; bool updFileModDate; int dateSource; int metadataSource; int fileDateSource; int adjustmentType; int adjustmentDays; }; // ------------------------------------------------------------------- /** Container that hold the time difference for clock photo dialog. */ class DeltaTime { public: explicit DeltaTime(); ~DeltaTime(); /// Check if at least one option is selected bool isNull() const; public: bool deltaNegative; int deltaDays; int deltaHours; int deltaMinutes; int deltaSeconds; }; } // namespace Digikam #endif // DIGIKAM_TIME_ADJUST_CONTAINER_H diff --git a/core/utilities/timeadjust/timeadjustdialog.cpp b/core/utilities/timeadjust/timeadjustdialog.cpp index 7af8500fdf..c4806a0d8b 100644 --- a/core/utilities/timeadjust/timeadjustdialog.cpp +++ b/core/utilities/timeadjust/timeadjustdialog.cpp @@ -1,486 +1,487 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2004-05-16 * Description : dialog to set time stamp of picture files. * * Copyright (C) 2012 by Smit Mehta * Copyright (C) 2003-2005 by Jesper Pedersen * Copyright (C) 2006-2018 by Gilles Caulier * Copyright (c) 2018 by Maik Qualmann * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "timeadjustdialog.h" // Qt includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include #include // KDE includes #include #include #include // Local includes #include "dmetadata.h" #include "dprogresswdg.h" #include "digikam_debug.h" #include "dxmlguiwindow.h" #include "dinfointerface.h" #include "timeadjustlist.h" #include "digikam_version.h" #include "timeadjustthread.h" #include "timeadjustsettings.h" namespace Digikam { class Q_DECL_HIDDEN TimeAdjustDialog::Private { public: explicit Private() { settingsView = 0; progressBar = 0; listView = 0; thread = 0; iface = 0; } TimeAdjustSettings* settingsView; QMap itemsUsedMap; // Map of item urls and Used Timestamps. QMap itemsUpdatedMap; // Map of item urls and Updated Timestamps. QMap itemsStatusMap; // Map of item urls and status flag. DProgressWdg* progressBar; TimeAdjustList* listView; TimeAdjustThread* thread; DInfoInterface* iface; }; TimeAdjustDialog::TimeAdjustDialog(QWidget* const parent, DInfoInterface* const iface) : WSToolDialog(parent), d(new Private) { setWindowTitle(i18n("Adjust Time & Date")); setMinimumSize(900, 500); setModal(true); d->iface = iface; startButton()->setText(i18nc("@action:button", "&Apply")); startButton()->setToolTip(i18nc("@info:tooltip", "Write the corrected date and time for each image")); startButton()->setIcon(QIcon::fromTheme(QLatin1String("dialog-ok-apply"))); QWidget* const mainWidget = new QWidget(this); setMainWidget(mainWidget); QGridLayout* const mainLayout = new QGridLayout(mainWidget); d->listView = new TimeAdjustList(mainWidget); d->settingsView = new TimeAdjustSettings(mainWidget); d->progressBar = new DProgressWdg(mainWidget); d->progressBar->reset(); d->progressBar->hide(); // ---------------------------------------------------------------------------- mainLayout->addWidget(d->listView, 0, 0, 2, 1); mainLayout->addWidget(d->settingsView, 0, 1, 1, 1); mainLayout->addWidget(d->progressBar, 1, 1, 1, 1); mainLayout->setColumnStretch(0, 10); mainLayout->setRowStretch(0, 10); mainLayout->setContentsMargins(QMargins()); // -- Thread Slots/Signals ---------------------------------------------- d->thread = new TimeAdjustThread(this); connect(d->thread, SIGNAL(finished()), this, SLOT(slotThreadFinished())); connect(d->thread, SIGNAL(signalProcessStarted(QUrl)), this, SLOT(slotProcessStarted(QUrl))); connect(d->thread, SIGNAL(signalProcessEnded(QUrl,int)), this, SLOT(slotProcessEnded(QUrl,int))); connect(d->progressBar, SIGNAL(signalProgressCanceled()), this, SLOT(slotCancelThread())); // -- Dialog Slots/Signals ----------------------------------------------- connect(startButton(), &QPushButton::clicked, this, &TimeAdjustDialog::slotApplyClicked); connect(this, &WSToolDialog::cancelClicked, this, &TimeAdjustDialog::slotCancelThread); connect(this, &QDialog::finished, this, &TimeAdjustDialog::slotDialogFinished); connect(d->settingsView, SIGNAL(signalSettingsChanged()), this, SLOT(slotReadTimestamps())); connect(d->settingsView, SIGNAL(signalSettingsChangedTool()), this, SLOT(slotReadTimestamps())); // ----------------------------------------------------------------------- setBusy(false); readSettings(); foreach (const QUrl& url, d->iface->currentSelectedItems()) { d->itemsUsedMap.insert(url, QDateTime()); } d->listView->setIface(d->iface); d->listView->loadImagesFromCurrentSelection(); slotReadTimestamps(); } TimeAdjustDialog::~TimeAdjustDialog() { delete d; } void TimeAdjustDialog::closeEvent(QCloseEvent* e) { if (!e) { return; } slotDialogFinished(); e->accept(); } void TimeAdjustDialog::slotDialogFinished() { saveSettings(); } void TimeAdjustDialog::readSettings() { TimeAdjustContainer prm; KSharedConfig::Ptr config = KSharedConfig::openConfig(); KConfigGroup group = config->group(QLatin1String("Time Adjust Settings")); prm.customDate = group.readEntry(QLatin1String("Custom Date"), QDateTime()); prm.customTime = group.readEntry(QLatin1String("Custom Time"), QDateTime()); prm.adjustmentType = group.readEntry(QLatin1String("Adjustment Type"), 0); prm.adjustmentDays = group.readEntry(QLatin1String("Adjustment Days"), 0); prm.adjustmentTime = group.readEntry(QLatin1String("Adjustment Time"), QDateTime()); prm.updIfAvailable = group.readEntry(QLatin1String("Update Only If Available Time"), true); prm.updFileModDate = group.readEntry(QLatin1String("Update File Modification Time"), true); prm.updEXIFModDate = group.readEntry(QLatin1String("Update EXIF Modification Time"), true); prm.updEXIFOriDate = group.readEntry(QLatin1String("Update EXIF Original Time"), true); prm.updEXIFDigDate = group.readEntry(QLatin1String("Update EXIF Digitization Time"), true); prm.updEXIFThmDate = group.readEntry(QLatin1String("Update EXIF Thumbnail Time"), true); prm.updIPTCDate = group.readEntry(QLatin1String("Update IPTC Time"), false); prm.updXMPVideo = group.readEntry(QLatin1String("Update XMP Video Time"), false); prm.updXMPDate = group.readEntry(QLatin1String("Update XMP Creation Time"), false); prm.dateSource = group.readEntry(QLatin1String("Use Timestamp Type"), 0); prm.metadataSource = group.readEntry(QLatin1String("Meta Timestamp Type"), 0); prm.fileDateSource = group.readEntry(QLatin1String("File Timestamp Type"), 0); d->settingsView->setSettings(prm); winId(); KConfigGroup group2 = config->group(QLatin1String("Time Adjust Dialog")); DXmlGuiWindow::restoreWindowSize(windowHandle(), group2); resize(windowHandle()->size()); } void TimeAdjustDialog::saveSettings() { TimeAdjustContainer prm = d->settingsView->settings(); KSharedConfig::Ptr config = KSharedConfig::openConfig(); KConfigGroup group = config->group(QLatin1String("Time Adjust Settings")); group.writeEntry(QLatin1String("Custom Date"), prm.customDate); group.writeEntry(QLatin1String("Custom Time"), prm.customTime); group.writeEntry(QLatin1String("Adjustment Type"), prm.adjustmentType); group.writeEntry(QLatin1String("Adjustment Days"), prm.adjustmentDays); group.writeEntry(QLatin1String("Adjustment Time"), prm.adjustmentTime); group.writeEntry(QLatin1String("Update Only If Available Time"), prm.updIfAvailable); group.writeEntry(QLatin1String("Update File Modification Time"), prm.updFileModDate); group.writeEntry(QLatin1String("Update EXIF Modification Time"), prm.updEXIFModDate); group.writeEntry(QLatin1String("Update EXIF Original Time"), prm.updEXIFOriDate); group.writeEntry(QLatin1String("Update EXIF Digitization Time"), prm.updEXIFDigDate); group.writeEntry(QLatin1String("Update EXIF Thumbnail Time"), prm.updEXIFThmDate); group.writeEntry(QLatin1String("Update IPTC Time"), prm.updIPTCDate); group.writeEntry(QLatin1String("Update XMP Video Time"), prm.updXMPVideo); group.writeEntry(QLatin1String("Update XMP Creation Time"), prm.updXMPDate); group.writeEntry(QLatin1String("Use Timestamp Type"), prm.dateSource); group.writeEntry(QLatin1String("Meta Timestamp Type"), prm.metadataSource); group.writeEntry(QLatin1String("File Timestamp Type"), prm.fileDateSource); KConfigGroup group2 = config->group(QLatin1String("Time Adjust Dialog")); DXmlGuiWindow::saveWindowSize(windowHandle(), group2); } void TimeAdjustDialog::slotReadTimestamps() { foreach (const QUrl& url, d->itemsUsedMap.keys()) { d->itemsUsedMap.insert(url, QDateTime()); } TimeAdjustContainer prm = d->settingsView->settings(); switch (prm.dateSource) { case TimeAdjustContainer::APPDATE: { readApplicationTimestamps(); break; } case TimeAdjustContainer::FILEDATE: { readFileTimestamps(); break; } case TimeAdjustContainer::METADATADATE: { readMetadataTimestamps(); break; } default: // CUSTOMDATE { QDateTime dateTime(d->settingsView->settings().customDate.date(), d->settingsView->settings().customTime.time()); foreach (const QUrl& url, d->itemsUsedMap.keys()) { d->itemsUsedMap.insert(url, dateTime); } break; } } updateListView(); } void TimeAdjustDialog::readApplicationTimestamps() { QList floatingDateItems; foreach (const QUrl& url, d->itemsUsedMap.keys()) { DItemInfo info(d->iface->itemInfo(url)); if (info.dateTime().isValid()) { d->itemsUsedMap.insert(url, info.dateTime()); } else { floatingDateItems.append(url); d->itemsUsedMap.insert(url, QDateTime()); } } // TODO (blackie): handle all items in listview with inexact timestamp through floatingDateItems. } void TimeAdjustDialog::readFileTimestamps() { foreach (const QUrl& url, d->itemsUsedMap.keys()) { QFileInfo fileInfo(url.toLocalFile()); d->itemsUsedMap.insert(url, fileInfo.lastModified()); } } void TimeAdjustDialog::readMetadataTimestamps() { foreach (const QUrl& url, d->itemsUsedMap.keys()) { DMetadata meta; if (!meta.load(url.toLocalFile())) { d->itemsUsedMap.insert(url, QDateTime()); continue; } QDateTime curImageDateTime; TimeAdjustContainer prm = d->settingsView->settings(); switch (prm.metadataSource) { case TimeAdjustContainer::EXIFIPTCXMP: curImageDateTime = meta.getImageDateTime(); break; case TimeAdjustContainer::EXIFCREATED: curImageDateTime = QDateTime::fromString(meta.getExifTagString("Exif.Image.DateTime"), QLatin1String("yyyy:MM:dd hh:mm:ss")); break; case TimeAdjustContainer::EXIFORIGINAL: curImageDateTime = QDateTime::fromString(meta.getExifTagString("Exif.Photo.DateTimeOriginal"), QLatin1String("yyyy:MM:dd hh:mm:ss")); break; case TimeAdjustContainer::EXIFDIGITIZED: curImageDateTime = QDateTime::fromString(meta.getExifTagString("Exif.Photo.DateTimeDigitized"), QLatin1String("yyyy:MM:dd hh:mm:ss")); break; case TimeAdjustContainer::IPTCCREATED: // we have to truncate the timezone from the time, otherwise it cannot be converted to a QTime curImageDateTime = QDateTime(QDate::fromString(meta.getIptcTagString("Iptc.Application2.DateCreated"), Qt::ISODate), QTime::fromString(meta.getIptcTagString("Iptc.Application2.TimeCreated").left(8), Qt::ISODate)); break; case TimeAdjustContainer::XMPCREATED: curImageDateTime = QDateTime::fromString(meta.getXmpTagString("Xmp.xmp.CreateDate"), QLatin1String("yyyy:MM:ddThh:mm:ss")); break; default: // curImageDateTime stays invalid break; }; d->itemsUsedMap.insert(url, curImageDateTime); } } void TimeAdjustDialog::slotApplyClicked() { d->itemsStatusMap.clear(); TimeAdjustContainer prm = d->settingsView->settings(); if (prm.atLeastOneUpdateToProcess()) { d->progressBar->show(); d->progressBar->progressScheduled(i18n("Adjust Time and Date"), true, true); d->progressBar->progressThumbnailChanged(QIcon::fromTheme(QLatin1String("appointment-new")).pixmap(22, 22)); d->progressBar->setMaximum(d->itemsUsedMap.keys().size()); d->thread->setSettings(prm); d->thread->setUpdatedDates(d->itemsUpdatedMap); if (!d->thread->isRunning()) { d->thread->start(); } setBusy(true); } else { QMessageBox::critical(QApplication::activeWindow(), i18n("Adjust Time & Date"), i18n("Select at least one option")); } } void TimeAdjustDialog::slotCancelThread() { if (d->thread->isRunning()) { d->thread->cancel(); } } void TimeAdjustDialog::setBusy(bool busy) { setRejectButtonMode(busy ? QDialogButtonBox::Cancel : QDialogButtonBox::Close); startButton()->setEnabled(!busy); } void TimeAdjustDialog::slotProcessStarted(const QUrl& url) { d->listView->processing(url); } void TimeAdjustDialog::slotProcessEnded(const QUrl& url, int status) { d->listView->processed(url, (status == TimeAdjustList::NOPROCESS_ERROR)); d->itemsStatusMap.insert(url, status); d->progressBar->setValue(d->progressBar->value()+1); } void TimeAdjustDialog::slotThreadFinished() { d->listView->setStatus(d->itemsStatusMap); setBusy(false); d->progressBar->hide(); d->progressBar->progressCompleted(); saveSettings(); } void TimeAdjustDialog::updateListView() { QApplication::setOverrideCursor(Qt::WaitCursor); TimeAdjustContainer prm = d->settingsView->settings(); d->listView->setItemDates(d->itemsUsedMap, TimeAdjustList::TIMESTAMP_USED); // TODO : this loop can take a while, especially when items mist is huge. // Moving this loop code to ActionThread is the right way for the future. foreach (const QUrl& url, d->itemsUsedMap.keys()) { d->itemsUpdatedMap.insert(url, prm.calculateAdjustedDate(d->itemsUsedMap.value(url))); } d->listView->setItemDates(d->itemsUpdatedMap, TimeAdjustList::TIMESTAMP_UPDATED); QApplication::restoreOverrideCursor(); } } // namespace Digikam diff --git a/core/utilities/timeadjust/timeadjustdialog.h b/core/utilities/timeadjust/timeadjustdialog.h index 20db89947a..537d04a73c 100644 --- a/core/utilities/timeadjust/timeadjustdialog.h +++ b/core/utilities/timeadjust/timeadjustdialog.h @@ -1,106 +1,105 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2004-05-16 * Description : dialog to set time stamp of picture files. * * Copyright (C) 2012 by Smit Mehta * Copyright (C) 2003-2005 by Jesper Pedersen * Copyright (C) 2006-2018 by Gilles Caulier * Copyright (c) 2018 by Maik Qualmann * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_TIME_ADJUST_DIALOG_H #define DIGIKAM_TIME_ADJUST_DIALOG_H // Qt includes #include -#include // Local includes #include "wstooldialog.h" #include "digikam_export.h" #include "timeadjustsettings.h" namespace Digikam { class DInfoInterface; class DIGIKAM_EXPORT TimeAdjustDialog : public WSToolDialog { Q_OBJECT public: explicit TimeAdjustDialog(QWidget* const parent, DInfoInterface* const iface); ~TimeAdjustDialog(); Q_SIGNALS: void signalMyCloseClicked(); private Q_SLOTS: void slotApplyClicked(); void slotDialogFinished(); void slotThreadFinished(); void slotCancelThread(); void slotProcessStarted(const QUrl&); void slotProcessEnded(const QUrl&, int); void setBusy(bool); /** Read the Used Timestamps for all selected files * (according to the newly selected source timestamp type), * this will also implicitly update listview info. */ void slotReadTimestamps(); private: /** Called by readTimestamps() to get host timestamps */ void readApplicationTimestamps(); /** Called by readTimestamps() to get file timestamps */ void readFileTimestamps(); /** Called by readTimestamps() to get file metadata timestamps */ void readMetadataTimestamps(); void readSettings(); void saveSettings(); void updateListView(); protected: void closeEvent(QCloseEvent*); private: class Private; Private* const d; }; } // namespace Digikam #endif // DIGIKAM_TIME_ADJUST_DIALOG_H diff --git a/core/utilities/timeadjust/timeadjustlist.h b/core/utilities/timeadjust/timeadjustlist.h index 6c1f04a4e8..e9fbfe58ef 100644 --- a/core/utilities/timeadjust/timeadjustlist.h +++ b/core/utilities/timeadjust/timeadjustlist.h @@ -1,74 +1,74 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2012-17-04 * Description : time adjust images list. * * Copyright (C) 2012 by Smit Mehta * Copyright (C) 2012-2015 by Gilles Caulier * Copyright (c) 2018 by Maik Qualmann * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_TIME_ADJUST_LIST_H #define DIGIKAM_TIME_ADJUST_LIST_H // Qt includes -#include #include +#include #include // Local includes #include "dimageslist.h" #include "timeadjustsettings.h" namespace Digikam { class TimeAdjustList : public DImagesList { Q_OBJECT public: /* The different columns in a list. */ enum FieldType { TIMESTAMP_USED = DImagesListView::User1, TIMESTAMP_UPDATED = DImagesListView::User2, STATUS = DImagesListView::User3 }; enum ProcessingStatus { NOPROCESS_ERROR = 1 << 0, META_TIME_ERROR = 1 << 1, FILE_TIME_ERROR = 1 << 2 }; public: explicit TimeAdjustList(QWidget* const parent); ~TimeAdjustList(); void setItemDates(const QMap& map, FieldType type); void setStatus(const QMap& status); }; } // namespace Digikam #endif // DIGIKAM_TIME_ADJUST_LIST_H diff --git a/core/utilities/timeadjust/timeadjustsettings.cpp b/core/utilities/timeadjust/timeadjustsettings.cpp index 32a4da2538..74787a9545 100644 --- a/core/utilities/timeadjust/timeadjustsettings.cpp +++ b/core/utilities/timeadjust/timeadjustsettings.cpp @@ -1,524 +1,525 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2004-05-16 * Description : time adjust settings widget. * * Copyright (C) 2012 by Smit Mehta * Copyright (C) 2006-2018 by Gilles Caulier * Copyright (c) 2018 by Maik Qualmann * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "timeadjustsettings.h" // Qt includes #include #include #include #include #include #include #include #include #include +#include #include #include #include #include // KDE includes #include // Local includes #include "dexpanderbox.h" #include "clockphotodialog.h" #include "dmetadata.h" #include "detbyclockphotobutton.h" namespace Digikam { class Q_DECL_HIDDEN TimeAdjustSettings::Private { public: explicit Private() { useSettingsBox = 0; adjustSettingsBox = 0; updateSettingsBox = 0; useButtonGroup = 0; useApplDateBtn = 0; useFileDateBtn = 0; useMetaDateBtn = 0; useCustomDateBtn = 0; updIfAvailableCheck = 0; updFileModDateCheck = 0; updEXIFModDateCheck = 0; updEXIFOriDateCheck = 0; updEXIFDigDateCheck = 0; updEXIFThmDateCheck = 0; updIPTCDateCheck = 0; updXMPVideoCheck = 0; updXMPDateCheck = 0; useFileDateTypeChooser = 0; useMetaDateTypeChooser = 0; adjTypeChooser = 0; useApplDateLbl = 0; adjDaysLabel = 0; adjDaysInput = 0; adjDetByClockPhotoBtn = 0; useCustDateInput = 0; useCustTimeInput = 0; adjTimeInput = 0; useCustomDateTodayBtn = 0; settingsExpander = 0; } QWidget* useSettingsBox; QWidget* adjustSettingsBox; QWidget* updateSettingsBox; QButtonGroup* useButtonGroup; QRadioButton* useApplDateBtn; QRadioButton* useFileDateBtn; QRadioButton* useMetaDateBtn; QRadioButton* useCustomDateBtn; QCheckBox* updIfAvailableCheck; QCheckBox* updFileModDateCheck; QCheckBox* updEXIFModDateCheck; QCheckBox* updEXIFOriDateCheck; QCheckBox* updEXIFDigDateCheck; QCheckBox* updEXIFThmDateCheck; QCheckBox* updIPTCDateCheck; QCheckBox* updXMPVideoCheck; QCheckBox* updXMPDateCheck; QComboBox* useFileDateTypeChooser; QComboBox* useMetaDateTypeChooser; QComboBox* adjTypeChooser; QLabel* useApplDateLbl; QLabel* adjDaysLabel; QSpinBox* adjDaysInput; DetByClockPhotoButton* adjDetByClockPhotoBtn; QDateEdit* useCustDateInput; QTimeEdit* useCustTimeInput; QTimeEdit* adjTimeInput; QToolButton* useCustomDateTodayBtn; DExpanderBox* settingsExpander; }; TimeAdjustSettings::TimeAdjustSettings(QWidget* const parent) : QScrollArea(parent), d(new Private) { QWidget* const panel = new QWidget(viewport()); setWidget(panel); setWidgetResizable(true); d->settingsExpander = new DExpanderBox(panel); d->settingsExpander->setObjectName(QLatin1String("Time Adjust Settings Expander")); QVBoxLayout* const vlay = new QVBoxLayout(panel); vlay->addWidget(d->settingsExpander); const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing); // -- Settings View Used Timestamps --------------------------------------------------------- d->useSettingsBox = new QWidget(d->settingsExpander); QGridLayout* const useGBLayout = new QGridLayout(d->useSettingsBox); d->useButtonGroup = new QButtonGroup(d->useSettingsBox); d->useButtonGroup->setExclusive(true); QString applDateLabelString = i18n("%1 timestamp", QApplication::applicationName()); d->useApplDateBtn = new QRadioButton(QString(), d->useSettingsBox); d->useApplDateLbl = new QLabel(applDateLabelString); d->useApplDateLbl->setIndent(5); d->useFileDateBtn = new QRadioButton(d->useSettingsBox); d->useFileDateTypeChooser = new QComboBox(d->useSettingsBox); d->useFileDateTypeChooser->insertItem(TimeAdjustContainer::FILELASTMOD, i18n("File last modified")); /* // NOTE: not supported by Linux, although supported by Qt (read-only) d->useFileDateTypeChooser->insertItem(TimeAdjustContainer::FILECREATED, i18n("File created")); */ d->useMetaDateBtn = new QRadioButton(QString(), d->useSettingsBox); d->useMetaDateTypeChooser = new QComboBox(d->useSettingsBox); d->useMetaDateTypeChooser->insertItem(TimeAdjustContainer::EXIFIPTCXMP, i18n("EXIF/IPTC/XMP")); d->useMetaDateTypeChooser->insertItem(TimeAdjustContainer::EXIFCREATED, i18n("EXIF: created")); d->useMetaDateTypeChooser->insertItem(TimeAdjustContainer::EXIFORIGINAL, i18n("EXIF: original")); d->useMetaDateTypeChooser->insertItem(TimeAdjustContainer::EXIFDIGITIZED, i18n("EXIF: digitized")); d->useMetaDateTypeChooser->insertItem(TimeAdjustContainer::IPTCCREATED, i18n("IPTC: created")); d->useMetaDateTypeChooser->insertItem(TimeAdjustContainer::XMPCREATED, i18n("XMP: created")); d->useCustomDateBtn = new QRadioButton(d->useSettingsBox); d->useCustDateInput = new QDateEdit(d->useSettingsBox); d->useCustDateInput->setDisplayFormat(QLatin1String("dd MMMM yyyy")); d->useCustDateInput->setCalendarPopup(true); d->useCustTimeInput = new QTimeEdit(d->useSettingsBox); d->useCustTimeInput->setDisplayFormat(QLatin1String("hh:mm:ss")); d->useCustomDateTodayBtn = new QToolButton(d->useSettingsBox); d->useCustomDateTodayBtn->setIcon(QIcon::fromTheme(QLatin1String("go-jump-today"))); d->useCustomDateTodayBtn->setToolTip(i18n("Reset to current date")); useGBLayout->addWidget(d->useApplDateBtn, 0, 0, 1, 1); useGBLayout->addWidget(d->useApplDateLbl, 0, 1, 1, 1); useGBLayout->addWidget(d->useFileDateBtn, 1, 0, 1, 1); useGBLayout->addWidget(d->useFileDateTypeChooser, 1, 1, 1, 1); useGBLayout->addWidget(d->useMetaDateBtn, 2, 0, 1, 1); useGBLayout->addWidget(d->useMetaDateTypeChooser, 2, 1, 1, 1); useGBLayout->addWidget(d->useCustomDateBtn, 3, 0, 1, 1); useGBLayout->addWidget(d->useCustDateInput, 3, 1, 1, 1); useGBLayout->addWidget(d->useCustTimeInput, 3, 2, 1, 1); useGBLayout->addWidget(d->useCustomDateTodayBtn, 3, 3, 1, 1); useGBLayout->setContentsMargins(spacing, spacing, spacing, spacing); useGBLayout->setSpacing(spacing); useGBLayout->setColumnStretch(1, 1); useGBLayout->setColumnStretch(2, 1); d->useButtonGroup->addButton(d->useApplDateBtn, 0); d->useButtonGroup->addButton(d->useFileDateBtn, 1); d->useButtonGroup->addButton(d->useMetaDateBtn, 2); d->useButtonGroup->addButton(d->useCustomDateBtn, 3); d->useApplDateBtn->setChecked(true); // -- Settings View TimesStamp Adjustments --------------------------------------------------- d->adjustSettingsBox = new QWidget(d->settingsExpander); QGridLayout* const adjustGBLayout = new QGridLayout(d->adjustSettingsBox); d->adjTypeChooser = new QComboBox(d->adjustSettingsBox); d->adjTypeChooser->insertItem(TimeAdjustContainer::COPYVALUE, i18nc("copy timestamp as well", "Copy value")); d->adjTypeChooser->insertItem(TimeAdjustContainer::ADDVALUE, i18nc("add a fixed timestamp to date", "Add")); d->adjTypeChooser->insertItem(TimeAdjustContainer::SUBVALUE, i18nc("subtract a fixed timestamp to date", "Subtract")); d->adjDaysInput = new QSpinBox(d->adjustSettingsBox); d->adjDaysInput->setRange(0, 9999); d->adjDaysInput->setSingleStep(1); d->adjDaysLabel = new QLabel(i18nc("time adjust offset, days value label", "days"), d->adjustSettingsBox); d->adjTimeInput = new QTimeEdit(d->adjustSettingsBox); d->adjTimeInput->setDisplayFormat(QLatin1String("hh:mm:ss")); d->adjDetByClockPhotoBtn = new DetByClockPhotoButton(i18n("Determine difference from clock photo")); d->adjDetByClockPhotoBtn->setToolTip(i18n("Either click or drag'n drop a photo on the button to choose a clock photo")); adjustGBLayout->addWidget(d->adjTypeChooser, 0, 0, 1, 1); adjustGBLayout->addWidget(d->adjDaysInput, 0, 1, 1, 1); adjustGBLayout->addWidget(d->adjDaysLabel, 0, 2, 1, 1); adjustGBLayout->addWidget(d->adjTimeInput, 0, 3, 1, 1); adjustGBLayout->addWidget(d->adjDetByClockPhotoBtn, 1, 0, 1, 4); adjustGBLayout->setContentsMargins(spacing, spacing, spacing, spacing); adjustGBLayout->setSpacing(spacing); adjustGBLayout->setColumnStretch(0, 1); adjustGBLayout->setColumnStretch(1, 1); adjustGBLayout->setColumnStretch(3, 1); // -- Settings View Updated Timestamps ------------------------------------------------------- d->updateSettingsBox = new QWidget(d->settingsExpander); QGridLayout* const updateGBLayout = new QGridLayout(d->updateSettingsBox); d->updIfAvailableCheck = new QCheckBox(i18n("Update only existing timestamps"), d->updateSettingsBox); d->updFileModDateCheck = new QCheckBox(i18n("File last modified"), d->updateSettingsBox); d->updEXIFModDateCheck = new QCheckBox(i18n("EXIF: created"), d->updateSettingsBox); d->updEXIFOriDateCheck = new QCheckBox(i18n("EXIF: original"), d->updateSettingsBox); d->updEXIFDigDateCheck = new QCheckBox(i18n("EXIF: digitized"), d->updateSettingsBox); d->updEXIFThmDateCheck = new QCheckBox(i18n("EXIF: Thumbnail"), d->updateSettingsBox); d->updIPTCDateCheck = new QCheckBox(i18n("IPTC: created"), d->updateSettingsBox); d->updXMPVideoCheck = new QCheckBox(i18n("XMP: Video"), d->updateSettingsBox); d->updXMPDateCheck = new QCheckBox(i18n("XMP"), d->updateSettingsBox); updateGBLayout->addWidget(d->updIfAvailableCheck, 0, 0, 1, 2); updateGBLayout->addWidget(d->updEXIFOriDateCheck, 1, 0, 1, 1); updateGBLayout->addWidget(d->updEXIFModDateCheck, 1, 1, 1, 1); updateGBLayout->addWidget(d->updEXIFDigDateCheck, 2, 0, 1, 1); updateGBLayout->addWidget(d->updEXIFThmDateCheck, 2, 1, 1, 1); updateGBLayout->addWidget(d->updXMPDateCheck, 3, 0, 1, 1); updateGBLayout->addWidget(d->updXMPVideoCheck, 3, 1, 1, 1); updateGBLayout->addWidget(d->updIPTCDateCheck, 4, 0, 1, 1); updateGBLayout->addWidget(d->updFileModDateCheck, 4, 1, 1, 1); updateGBLayout->setContentsMargins(spacing, spacing, spacing, spacing); updateGBLayout->setSpacing(spacing); updateGBLayout->setColumnStretch(0, 1); updateGBLayout->setColumnStretch(1, 1); if (!DMetadata::supportXmp()) { d->updXMPVideoCheck->setEnabled(false); d->updXMPDateCheck->setEnabled(false); } // ----------------------------------------------------------------------- d->settingsExpander->addItem(d->useSettingsBox, i18n("Timestamp Used"), QLatin1String("timestampused"), true); d->settingsExpander->addItem(d->adjustSettingsBox, i18n("Timestamp Adjustments"), QLatin1String("timestampadjustments"), true); d->settingsExpander->addItem(d->updateSettingsBox, i18n("Timestamp Updated"), QLatin1String("timestampupdated"), true); d->settingsExpander->addStretch(); d->settingsExpander->setItemIcon(0, QIcon::fromTheme(QLatin1String("document-import"))); d->settingsExpander->setItemIcon(1, QIcon::fromTheme(QLatin1String("document-edit"))); d->settingsExpander->setItemIcon(2, QIcon::fromTheme(QLatin1String("document-export"))); // -- Settings View Slots/Signals ---------------------------------------- connect(d->useButtonGroup, SIGNAL(buttonReleased(int)), this, SLOT(slotSrcTimestampChanged())); connect(d->useFileDateTypeChooser, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSrcTimestampChanged())); connect(d->useMetaDateTypeChooser, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSrcTimestampChanged())); connect(d->adjTypeChooser, SIGNAL(currentIndexChanged(int)), this, SLOT(slotAdjustmentTypeChanged())); connect(d->useCustomDateTodayBtn, SIGNAL(clicked()), this, SLOT(slotResetDateToCurrent())); connect(d->adjDetByClockPhotoBtn, SIGNAL(clicked()), this, SLOT(slotDetAdjustmentByClockPhotoDialog())); connect(d->adjDetByClockPhotoBtn, SIGNAL(signalClockPhotoDropped(QUrl)), this, SLOT(slotDetAdjustmentByClockPhotoUrl(QUrl))); connect(d->useCustDateInput, SIGNAL(editingFinished()), this, SIGNAL(signalSettingsChanged())); connect(d->useCustDateInput, SIGNAL(dateChanged(QDate)), this, SIGNAL(signalSettingsChangedTool())); connect(d->useCustTimeInput, SIGNAL(editingFinished()), this, SIGNAL(signalSettingsChanged())); connect(d->useCustTimeInput, SIGNAL(timeChanged(QTime)), this, SIGNAL(signalSettingsChangedTool())); connect(d->adjDaysInput, SIGNAL(valueChanged(int)), this, SIGNAL(signalSettingsChanged())); connect(d->adjTimeInput, SIGNAL(editingFinished()), this, SIGNAL(signalSettingsChanged())); connect(d->adjTimeInput, SIGNAL(timeChanged(QTime)), this, SIGNAL(signalSettingsChangedTool())); connect(d->updEXIFModDateCheck, SIGNAL(toggled(bool)), this, SIGNAL(signalSettingsChanged())); connect(d->updEXIFOriDateCheck, SIGNAL(toggled(bool)), this, SIGNAL(signalSettingsChanged())); connect(d->updEXIFDigDateCheck, SIGNAL(toggled(bool)), this, SIGNAL(signalSettingsChanged())); connect(d->updEXIFThmDateCheck, SIGNAL(toggled(bool)), this, SIGNAL(signalSettingsChanged())); connect(d->updXMPVideoCheck, SIGNAL(toggled(bool)), this, SIGNAL(signalSettingsChanged())); connect(d->updXMPDateCheck, SIGNAL(toggled(bool)), this, SIGNAL(signalSettingsChanged())); connect(d->updIPTCDateCheck, SIGNAL(toggled(bool)), this, SIGNAL(signalSettingsChanged())); connect(d->updFileModDateCheck, SIGNAL(toggled(bool)), this, SIGNAL(signalSettingsChanged())); connect(d->updIfAvailableCheck, SIGNAL(toggled(bool)), this, SIGNAL(signalSettingsChanged())); } TimeAdjustSettings::~TimeAdjustSettings() { delete d; } void TimeAdjustSettings::setSettings(const TimeAdjustContainer& settings) { //d->settingsExpander->readSettings(group); int useTimestampType = settings.dateSource; if (useTimestampType == TimeAdjustContainer::APPDATE) d->useApplDateBtn->setChecked(true); else if (useTimestampType == TimeAdjustContainer::FILEDATE) d->useFileDateBtn->setChecked(true); else if (useTimestampType == TimeAdjustContainer::METADATADATE) d->useMetaDateBtn->setChecked(true); else if (useTimestampType == TimeAdjustContainer::CUSTOMDATE) d->useCustomDateBtn->setChecked(true); d->useFileDateTypeChooser->setCurrentIndex(settings.fileDateSource); d->useMetaDateTypeChooser->setCurrentIndex(settings.metadataSource); d->useCustDateInput->setDateTime(settings.customDate); d->useCustTimeInput->setDateTime(settings.customTime); d->adjTypeChooser->setCurrentIndex(settings.adjustmentType); d->adjDaysInput->setValue(settings.adjustmentDays); d->adjTimeInput->setDateTime(settings.adjustmentTime); d->updIfAvailableCheck->setChecked(settings.updIfAvailable); d->updFileModDateCheck->setChecked(settings.updFileModDate); d->updEXIFModDateCheck->setChecked(settings.updEXIFModDate); d->updEXIFOriDateCheck->setChecked(settings.updEXIFOriDate); d->updEXIFDigDateCheck->setChecked(settings.updEXIFDigDate); d->updEXIFThmDateCheck->setChecked(settings.updEXIFThmDate); d->updIPTCDateCheck->setChecked(settings.updIPTCDate); d->updXMPVideoCheck->setChecked(settings.updXMPVideo); d->updXMPDateCheck->setChecked(settings.updXMPDate); slotSrcTimestampChanged(); slotAdjustmentTypeChanged(); } TimeAdjustContainer TimeAdjustSettings::settings() const { TimeAdjustContainer settings; settings.customDate = d->useCustDateInput->dateTime(); settings.customTime = d->useCustTimeInput->dateTime(); settings.adjustmentType = d->adjTypeChooser->currentIndex(); settings.adjustmentDays = d->adjDaysInput->value(); settings.adjustmentTime = d->adjTimeInput->dateTime(); settings.updIfAvailable = d->updIfAvailableCheck->isChecked(); settings.updFileModDate = d->updFileModDateCheck->isChecked(); settings.updEXIFModDate = d->updEXIFModDateCheck->isChecked(); settings.updEXIFOriDate = d->updEXIFOriDateCheck->isChecked(); settings.updEXIFDigDate = d->updEXIFDigDateCheck->isChecked(); settings.updEXIFThmDate = d->updEXIFThmDateCheck->isChecked(); settings.updIPTCDate = d->updIPTCDateCheck->isChecked(); settings.updXMPVideo = d->updXMPVideoCheck->isChecked(); settings.updXMPDate = d->updXMPDateCheck->isChecked(); settings.dateSource = TimeAdjustContainer::APPDATE; if (d->useFileDateBtn->isChecked()) settings.dateSource = TimeAdjustContainer::FILEDATE; if (d->useMetaDateBtn->isChecked()) settings.dateSource = TimeAdjustContainer::METADATADATE; if (d->useCustomDateBtn->isChecked()) settings.dateSource = TimeAdjustContainer::CUSTOMDATE; settings.metadataSource = d->useMetaDateTypeChooser->currentIndex(); settings.fileDateSource = d->useFileDateTypeChooser->currentIndex(); return settings; } void TimeAdjustSettings::detAdjustmentByClockPhotoUrl(const QUrl& url) { /* When user press the clock photo button, a dialog is displayed and set the * results to the proper widgets. */ QPointer dlg = new ClockPhotoDialog(this, url); const int result = dlg->exec(); if (result == QDialog::Accepted) { DeltaTime dvalues = dlg->deltaValues(); if (dvalues.isNull()) { d->adjTypeChooser->setCurrentIndex(TimeAdjustContainer::COPYVALUE); } else if (dvalues.deltaNegative) { d->adjTypeChooser->setCurrentIndex(TimeAdjustContainer::SUBVALUE); } else { d->adjTypeChooser->setCurrentIndex(TimeAdjustContainer::ADDVALUE); } d->adjDaysInput->setValue(dvalues.deltaDays); QTime deltaTime; deltaTime.setHMS(dvalues.deltaHours, dvalues.deltaMinutes, dvalues.deltaSeconds); d->adjTimeInput->setTime(deltaTime); emit signalSettingsChanged(); } delete dlg; } void TimeAdjustSettings::slotSrcTimestampChanged() { d->useFileDateTypeChooser->setEnabled(false); d->useMetaDateTypeChooser->setEnabled(false); d->useCustDateInput->setEnabled(false); d->useCustTimeInput->setEnabled(false); d->useCustomDateTodayBtn->setEnabled(false); if (d->useFileDateBtn->isChecked()) { d->useFileDateTypeChooser->setEnabled(true); } else if (d->useMetaDateBtn->isChecked()) { d->useMetaDateTypeChooser->setEnabled(true); } else if (d->useCustomDateBtn->isChecked()) { d->useCustDateInput->setEnabled(true); d->useCustTimeInput->setEnabled(true); d->useCustomDateTodayBtn->setEnabled(true); } emit signalSettingsChanged(); } void TimeAdjustSettings::slotResetDateToCurrent() { QDateTime currentDateTime(QDateTime::currentDateTime()); d->useCustDateInput->setDateTime(currentDateTime); d->useCustTimeInput->setDateTime(currentDateTime); emit signalSettingsChanged(); } void TimeAdjustSettings::slotAdjustmentTypeChanged() { // If the addition or subtraction has been selected, enable the edit boxes to enter the adjustment length bool isAdjustment = (d->adjTypeChooser->currentIndex() > TimeAdjustContainer::COPYVALUE); d->adjDaysInput->setEnabled(isAdjustment); d->adjDaysLabel->setEnabled(isAdjustment); d->adjTimeInput->setEnabled(isAdjustment); emit signalSettingsChanged(); } void TimeAdjustSettings::slotDetAdjustmentByClockPhotoUrl(const QUrl& url) { //usually called when a photo is dropped onto the push button detAdjustmentByClockPhotoUrl(url); } void TimeAdjustSettings::slotDetAdjustmentByClockPhotoDialog() { // Determine the currently selected item and preselect it as clock photo QUrl emptyUrl; detAdjustmentByClockPhotoUrl(emptyUrl); } } // namespace Digikam diff --git a/core/utilities/timeadjust/timeadjustsettings.h b/core/utilities/timeadjust/timeadjustsettings.h index c28016add6..884e468e23 100644 --- a/core/utilities/timeadjust/timeadjustsettings.h +++ b/core/utilities/timeadjust/timeadjustsettings.h @@ -1,78 +1,77 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2004-05-16 * Description : time adjust settings widget. * * Copyright (C) 2012 by Smit Mehta * Copyright (C) 2006-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_TIME_ADJUST_SETTINGS_H #define DIGIKAM_TIME_ADJUST_SETTINGS_H // Qt includes -#include #include // Local includes #include "digikam_export.h" #include "timeadjustcontainer.h" namespace Digikam { class TimeAdjustContainer; class DIGIKAM_EXPORT TimeAdjustSettings : public QScrollArea { Q_OBJECT public: explicit TimeAdjustSettings(QWidget* const parent = 0); ~TimeAdjustSettings(); public: void setSettings(const TimeAdjustContainer& settings); TimeAdjustContainer settings() const; void detAdjustmentByClockPhotoUrl(const QUrl& url); Q_SIGNALS: void signalSettingsChanged(); void signalSettingsChangedTool(); private Q_SLOTS: void slotSrcTimestampChanged(); void slotResetDateToCurrent(); void slotAdjustmentTypeChanged(); void slotDetAdjustmentByClockPhotoDialog(); void slotDetAdjustmentByClockPhotoUrl(const QUrl& url); private: class Private; Private* const d; }; } // namespace Digikam #endif // DIGIKAM_TIME_ADJUST_SETTINGS_H diff --git a/core/utilities/timeadjust/timeadjusttask.cpp b/core/utilities/timeadjust/timeadjusttask.cpp index c43fcb1656..9761226df4 100644 --- a/core/utilities/timeadjust/timeadjusttask.cpp +++ b/core/utilities/timeadjust/timeadjusttask.cpp @@ -1,330 +1,331 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2012-12-31 * Description : time adjust actions using threads. * * Copyright (C) 2012 by Smit Mehta * Copyright (C) 2006-2018 by Gilles Caulier * Copyright (c) 2018 by Maik Qualmann * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "timeadjusttask.h" // C ANSI includes extern "C" { #include #include } // Qt includes #include // Local includes #include "dmetadata.h" #include "digikam_debug.h" #include "dinfointerface.h" #include "timeadjustlist.h" #include "timeadjustthread.h" namespace Digikam { class Q_DECL_HIDDEN TimeAdjustTask::Private { public: explicit Private() { } QUrl url; // Settings from GUI. TimeAdjustContainer settings; // Map of item urls and Updated Timestamps. QMap itemsMap; }; TimeAdjustTask::TimeAdjustTask(const QUrl& url) : ActionJob(), d(new Private) { d->url = url; } TimeAdjustTask::~TimeAdjustTask() { cancel(); delete d; } void TimeAdjustTask::setSettings(const TimeAdjustContainer& settings) { d->settings = settings; } void TimeAdjustTask::setItemsMap(const QMap& itemsMap) { d->itemsMap = itemsMap; } void TimeAdjustTask::run() { if (m_cancel) return; QDateTime dt = d->itemsMap.value(d->url); - if (!dt.isValid()) return; + if (!dt.isValid()) + return; emit signalProcessStarted(d->url); bool metadataChanged = d->settings.updEXIFModDate || d->settings.updEXIFOriDate || d->settings.updEXIFDigDate || d->settings.updEXIFThmDate || d->settings.updIPTCDate || d->settings.updXMPDate; int status = TimeAdjustList::NOPROCESS_ERROR; if (metadataChanged) { bool ret = true; DMetadata meta; ret &= meta.load(d->url.path()); if (ret) { QString exifDateTimeFormat = QLatin1String("yyyy:MM:dd hh:mm:ss"); QString xmpDateTimeFormat = QLatin1String("yyyy:MM:ddThh:mm:ss"); if (meta.canWriteExif(d->url.path())) { if (d->settings.updEXIFModDate) { if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getExifTagString("Exif.Image.DateTime").isEmpty())) { ret &= meta.setExifTagString("Exif.Image.DateTime", dt.toString(exifDateTimeFormat)); } } if (d->settings.updEXIFOriDate) { if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getExifTagString("Exif.Photo.DateTimeOriginal").isEmpty())) { ret &= meta.setExifTagString("Exif.Photo.DateTimeOriginal", dt.toString(exifDateTimeFormat)); } } if (d->settings.updEXIFDigDate) { if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getExifTagString("Exif.Photo.DateTimeDigitized").isEmpty())) { ret &= meta.setExifTagString("Exif.Photo.DateTimeDigitized", dt.toString(exifDateTimeFormat)); } } if (d->settings.updEXIFThmDate) { if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getExifTagString("Exif.Image.PreviewDateTime").isEmpty())) { ret &= meta.setExifTagString("Exif.Image.PreviewDateTime", dt.toString(exifDateTimeFormat)); } } } else if (d->settings.updEXIFModDate || d->settings.updEXIFOriDate || d->settings.updEXIFDigDate || d->settings.updEXIFThmDate) { ret = false; } if (d->settings.updIPTCDate) { if (meta.canWriteIptc(d->url.path())) { if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getIptcTagString("Iptc.Application2.DateCreated").isEmpty())) { ret &= meta.setIptcTagString("Iptc.Application2.DateCreated", dt.date().toString(Qt::ISODate)); } if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getIptcTagString("Iptc.Application2.TimeCreated").isEmpty())) { ret &= meta.setIptcTagString("Iptc.Application2.TimeCreated", dt.time().toString(Qt::ISODate)); } } else { ret = false; } } if (d->settings.updXMPDate) { if (meta.supportXmp() && meta.canWriteXmp(d->url.path())) { if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getXmpTagString("Xmp.exif.DateTimeOriginal").isEmpty())) { ret &= meta.setXmpTagString("Xmp.exif.DateTimeOriginal", dt.toString(xmpDateTimeFormat)); } if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getXmpTagString("Xmp.photoshop.DateCreated").isEmpty())) { ret &= meta.setXmpTagString("Xmp.photoshop.DateCreated", dt.toString(xmpDateTimeFormat)); } if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getXmpTagString("Xmp.tiff.DateTime").isEmpty())) { ret &= meta.setXmpTagString("Xmp.tiff.DateTime", dt.toString(xmpDateTimeFormat)); } if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getXmpTagString("Xmp.xmp.CreateDate").isEmpty())) { ret &= meta.setXmpTagString("Xmp.xmp.CreateDate", dt.toString(xmpDateTimeFormat)); } if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getXmpTagString("Xmp.xmp.MetadataDate").isEmpty())) { ret &= meta.setXmpTagString("Xmp.xmp.MetadataDate", dt.toString(xmpDateTimeFormat)); } if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getXmpTagString("Xmp.xmp.ModifyDate").isEmpty())) { ret &= meta.setXmpTagString("Xmp.xmp.ModifyDate", dt.toString(xmpDateTimeFormat)); } } else { ret = false; } } if (d->settings.updXMPVideo) { if (meta.supportXmp() && meta.canWriteXmp(d->url.path())) { if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getXmpTagString("Xmp.video.DateTimeOriginal").isEmpty())) { ret &= meta.setXmpTagString("Xmp.video.DateTimeOriginal", dt.toString(xmpDateTimeFormat)); } if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getXmpTagString("Xmp.video.DateTimeDigitized").isEmpty())) { ret &= meta.setXmpTagString("Xmp.video.DateTimeDigitized", dt.toString(xmpDateTimeFormat)); } if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getXmpTagString("Xmp.video.ModificationDate").isEmpty())) { ret &= meta.setXmpTagString("Xmp.video.ModificationDate", dt.toString(xmpDateTimeFormat)); } if (!d->settings.updIfAvailable || (d->settings.updIfAvailable && !meta.getXmpTagString("Xmp.video.DateUTC").isEmpty())) { ret &= meta.setXmpTagString("Xmp.video.DateUTC", dt.toUTC().toString(xmpDateTimeFormat)); } } else { ret = false; } } ret &= meta.save(d->url.path()); if (!ret) { qCDebug(DIGIKAM_GENERAL_LOG) << "Failed to update metadata in file " << d->url.fileName(); } } else { qCDebug(DIGIKAM_GENERAL_LOG) << "Failed to load metadata from file " << d->url.fileName(); } if (!ret) { status |= TimeAdjustList::META_TIME_ERROR; } } if (d->settings.updFileModDate) { // Since QFileInfo does not support timestamp updates, see Qt suggestion #79427 at // http://www.qtsoftware.com/developer/task-tracker/index_html?id=79427&method=entry // we have to use the utime() system call. int modtime; QDateTime unixDate; unixDate.setDate(QDate(1970, 1, 1)); unixDate.setTime(QTime(0, 0, 0, 0)); if (dt < unixDate) modtime = -(dt.secsTo(unixDate) + (60 * 60)); else modtime = dt.toTime_t(); utimbuf times; times.actime = QDateTime::currentDateTime().toTime_t(); times.modtime = modtime; if (utime(QFile::encodeName(d->url.toLocalFile()).constData(), ×) != 0) { status |= TimeAdjustList::FILE_TIME_ERROR; } } emit signalProcessEnded(d->url, status); emit signalDone(); } } // namespace Digikam diff --git a/core/utilities/timeadjust/timeadjustthread.cpp b/core/utilities/timeadjust/timeadjustthread.cpp index 7e5372af42..d7ddebcd66 100644 --- a/core/utilities/timeadjust/timeadjustthread.cpp +++ b/core/utilities/timeadjust/timeadjustthread.cpp @@ -1,112 +1,107 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2004-05-16 * Description : time adjust thread. * * Copyright (C) 2012 by Smit Mehta * Copyright (C) 2012-2018 by Gilles Caulier * Copyright (c) 2018 by Maik Qualmann * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "timeadjustthread.h" -// Qt Includes - -#include - // Local includes -#include "digikam_debug.h" #include "dinfointerface.h" #include "timeadjusttask.h" namespace Digikam { class Q_DECL_HIDDEN TimeAdjustThread::Private { public: explicit Private() { } // Settings from GUI. TimeAdjustContainer settings; // Map of item urls and Updated Timestamps. QMap itemsMap; }; TimeAdjustThread::TimeAdjustThread(QObject* const parent) : ActionThreadBase(parent), d(new Private) { } TimeAdjustThread::~TimeAdjustThread() { // cancel the thread cancel(); // wait for the thread to finish wait(); delete d; } void TimeAdjustThread::setUpdatedDates(const QMap& itemsMap) { d->itemsMap = itemsMap; ActionJobCollection collection; foreach (const QUrl& url, d->itemsMap.keys()) { TimeAdjustTask* const t = new TimeAdjustTask(url); t->setSettings(d->settings); t->setItemsMap(d->itemsMap); connect(t, SIGNAL(signalProcessStarted(QUrl)), this, SIGNAL(signalProcessStarted(QUrl))); connect(t, SIGNAL(signalProcessEnded(QUrl,int)), this, SIGNAL(signalProcessEnded(QUrl,int))); connect(this, SIGNAL(signalCancelTask()), t, SLOT(cancel()), Qt::QueuedConnection); collection.insert(t, 0); } appendJobs(collection); } void TimeAdjustThread::setSettings(const TimeAdjustContainer& settings) { d->settings = settings; } void TimeAdjustThread::cancel() { if (isRunning()) emit signalCancelTask(); ActionThreadBase::cancel(); } } // namespace Digikam diff --git a/core/utilities/timeadjust/timeadjustthread.h b/core/utilities/timeadjust/timeadjustthread.h index 999f932b39..36f424263b 100644 --- a/core/utilities/timeadjust/timeadjustthread.h +++ b/core/utilities/timeadjust/timeadjustthread.h @@ -1,74 +1,72 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2004-05-16 * Description : time adjust thread. * * Copyright (C) 2012 by Smit Mehta * Copyright (C) 2012-2018 by Gilles Caulier * Copyright (c) 2018 by Maik Qualmann * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_TIME_ADJUST_THREAD_H #define DIGIKAM_TIME_ADJUST_THREAD_H // Qt includes -#include #include -#include #include #include // Local includes #include "actionthreadbase.h" #include "timeadjustcontainer.h" namespace Digikam { class TimeAdjustThread : public ActionThreadBase { Q_OBJECT public: explicit TimeAdjustThread(QObject* const parent); ~TimeAdjustThread(); void setUpdatedDates(const QMap& itemsMap); void setSettings(const TimeAdjustContainer& settings); void cancel(); Q_SIGNALS: void signalProcessStarted(const QUrl&); void signalProcessEnded(const QUrl&, int); void signalCancelTask(); public: class Private; private: Private* const d; }; } // namespace Digikam #endif // DIGIKAM_TIME_ADJUST_THREAD_H