File indexing completed on 2025-11-09 04:10:13
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2009-05-31 0007 * Description : Figure out camera clock delta from a clock picture. 0008 * 0009 * SPDX-FileCopyrightText: 2009 by Pieter Edelman <p dot edelman at gmx dot net> 0010 * SPDX-FileCopyrightText: 2011-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * SPDX-FileCopyrightText: 2014 by Michael G. Hansen <mike at mghansen dot de> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #include "clockphotodialog.h" 0018 0019 // Qt includes 0020 0021 #include <QDialogButtonBox> 0022 #include <QStandardPaths> 0023 #include <QDateTimeEdit> 0024 #include <QHBoxLayout> 0025 #include <QVBoxLayout> 0026 #include <QPushButton> 0027 #include <QScopedPointer> 0028 #include <QWindow> 0029 #include <QLabel> 0030 #include <QIcon> 0031 #include <QSize> 0032 #include <QDir> 0033 0034 // KDE includes 0035 0036 #include <kconfiggroup.h> 0037 #include <ksharedconfig.h> 0038 #include <klocalizedstring.h> 0039 0040 // Local includes 0041 0042 #include "dmetadata.h" 0043 #include "imagedialog.h" 0044 #include "timeadjustcontainer.h" 0045 #include "graphicsdimgview.h" 0046 #include "dimgpreviewitem.h" 0047 #include "dxmlguiwindow.h" 0048 0049 namespace Digikam 0050 { 0051 0052 class Q_DECL_HIDDEN ClockPhotoDialog::Private 0053 { 0054 0055 public: 0056 0057 explicit Private() 0058 : buttons (nullptr), 0059 calendar (nullptr), 0060 dtLabel (nullptr), 0061 previewManager(nullptr) 0062 { 0063 } 0064 0065 DeltaTime deltaValues; 0066 0067 QDialogButtonBox* buttons; 0068 QDateTimeEdit* calendar; 0069 QDateTime photoDateTime; 0070 QLabel* dtLabel; 0071 0072 GraphicsDImgView* previewManager; 0073 }; 0074 0075 ClockPhotoDialog::ClockPhotoDialog(QWidget* const parent, const QUrl& defaultUrl) 0076 : QDialog(parent), 0077 d (new Private) 0078 { 0079 // This dialog should be modal with three buttons: Ok, Cancel, and load 0080 // photo. For this third button, the User1 button from KDialog is used. 0081 // The Ok button is only enable when a photo is loaded. 0082 0083 setWindowTitle(i18nc("@title:window", "Determine Time Difference With Clock Photo")); 0084 0085 d->buttons = new QDialogButtonBox(QDialogButtonBox::Apply | QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); 0086 d->buttons->button(QDialogButtonBox::Cancel)->setDefault(true); 0087 d->buttons->button(QDialogButtonBox::Ok)->setEnabled(false); 0088 setMinimumWidth(500); 0089 setMinimumHeight(500); 0090 d->buttons->button(QDialogButtonBox::Apply)->setText(i18n("Load different photo")); 0091 d->buttons->button(QDialogButtonBox::Apply)->setIcon(QIcon::fromTheme(QLatin1String("document-open"))); 0092 0093 QWidget* const mainWidget = new QWidget(this); 0094 QVBoxLayout* const vBox = new QVBoxLayout(mainWidget); 0095 0096 // Some explanation. 0097 0098 QLabel* const explanationLabel = new QLabel(i18n("If you have a photo in your set with a clock or " 0099 "another external time source on it, you can load " 0100 "it here and set the indicator to the (date and) " 0101 "time displayed. The difference of your internal " 0102 "camera clock will be determined from this " 0103 "setting.")); 0104 explanationLabel->setWordWrap(true); 0105 vBox->addWidget(explanationLabel); 0106 0107 d->previewManager = new GraphicsDImgView(this); 0108 d->previewManager->setItem(new DImgPreviewItem()); 0109 d->previewManager->setMinimumSize(QSize(200, 200)); 0110 vBox->addWidget(d->previewManager); 0111 0112 // The date and time entry widget allows the user to enter the date and time 0113 // displayed in the image. The format is explicitly set, otherwise seconds 0114 // might not get displayed. 0115 0116 d->dtLabel = new QLabel(); 0117 d->calendar = new QDateTimeEdit(); 0118 d->calendar->setDisplayFormat(QLatin1String("d MMMM yyyy, hh:mm:ss")); 0119 d->calendar->setCalendarPopup(true); 0120 d->calendar->setEnabled(false); 0121 QHBoxLayout* const hBox2 = new QHBoxLayout(mainWidget); 0122 hBox2->addStretch(); 0123 hBox2->addWidget(d->dtLabel); 0124 hBox2->addWidget(d->calendar); 0125 vBox->addLayout(hBox2); 0126 0127 vBox->addWidget(d->buttons); 0128 setLayout(vBox); 0129 0130 // Setup the signals and slots. 0131 0132 connect(d->buttons->button(QDialogButtonBox::Ok), SIGNAL(clicked()), 0133 this, SLOT(slotOk())); 0134 0135 connect(d->buttons->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), 0136 this, SLOT(slotCancel())); 0137 0138 connect(d->buttons->button(QDialogButtonBox::Apply), SIGNAL(clicked()), 0139 this, SLOT(slotLoadPhoto())); 0140 0141 // Show the window. 0142 0143 loadSettings(); 0144 show(); 0145 0146 if (defaultUrl.isValid()) 0147 { 0148 setImage(defaultUrl); 0149 } 0150 else 0151 { 0152 // No default url was given. 0153 // Upon initialization, present the user with a photo loading dialog. This 0154 // is done before the main dialog is drawn. 0155 0156 slotLoadPhoto(); 0157 } 0158 } 0159 0160 ClockPhotoDialog::~ClockPhotoDialog() 0161 { 0162 delete d; 0163 } 0164 0165 DeltaTime ClockPhotoDialog::deltaValues() const 0166 { 0167 return d->deltaValues; 0168 } 0169 0170 bool ClockPhotoDialog::setImage(const QUrl& imageFile) 0171 { 0172 bool success = false; 0173 QString msg = i18n("<font color=\"red\"><b>Could not load<br/>" 0174 "image %1.</b></font>", 0175 imageFile.fileName()); 0176 0177 d->previewManager->previewItem()->setPath(imageFile.toLocalFile(), true); 0178 0179 // Try to read the datetime data. 0180 0181 QScopedPointer<DMetadata> meta(new DMetadata); 0182 0183 if (meta->load(imageFile.toLocalFile())) 0184 { 0185 d->photoDateTime = meta->getItemDateTime(); 0186 0187 if (d->photoDateTime.isValid()) 0188 { 0189 msg = i18n("The clock date and time:"); 0190 0191 // Set the datetime widget to the photo datetime. 0192 0193 d->calendar->setDateTime(d->photoDateTime); 0194 d->calendar->setEnabled(true); 0195 success = true; 0196 } 0197 } 0198 0199 d->dtLabel->setText(msg); 0200 0201 // Disable all the GUI elements if loading failed. 0202 0203 d->calendar->setEnabled(success); 0204 0205 // enable the ok button if loading succeeded 0206 0207 d->buttons->button(QDialogButtonBox::Ok)->setEnabled(success); 0208 0209 return success; 0210 } 0211 0212 void ClockPhotoDialog::loadSettings() 0213 { 0214 KConfigGroup group = KSharedConfig::openConfig()->group(QLatin1String("Clock Photo Dialog")); 0215 0216 winId(); 0217 DXmlGuiWindow::restoreWindowSize(windowHandle(), group); 0218 resize(windowHandle()->size()); 0219 } 0220 0221 void ClockPhotoDialog::saveSettings() 0222 { 0223 KConfigGroup group = KSharedConfig::openConfig()->group(QLatin1String("Clock Photo Dialog")); 0224 DXmlGuiWindow::saveWindowSize(windowHandle(), group); 0225 } 0226 0227 void ClockPhotoDialog::slotLoadPhoto() 0228 { 0229 QUrl place; 0230 QStringList pics = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation); 0231 0232 if (pics.isEmpty()) 0233 { 0234 place = QUrl::fromLocalFile(QDir::homePath()); 0235 } 0236 else 0237 { 0238 place = QUrl::fromLocalFile(pics.first()); 0239 } 0240 0241 ImageDialog dlg(this, place, true, i18n("Select Image to Extract Clock Photo")); 0242 0243 if (!dlg.url().isEmpty()) 0244 { 0245 // If the user selected a proper photo, try to load it. 0246 0247 setImage(dlg.url()); 0248 } 0249 } 0250 0251 void ClockPhotoDialog::slotOk() 0252 { 0253 // Called when the ok button is pressed. Calculate the time difference 0254 // between the photo and the user set datetime information, and store it in 0255 // the public variables. 0256 0257 // Determine the number of seconds between the dates. 0258 0259 int delta = d->photoDateTime.secsTo(d->calendar->dateTime()); 0260 0261 // If the photo datetime is newer than the user datetime, it results in subtraction. 0262 0263 if (delta < 0) 0264 { 0265 d->deltaValues.deltaNegative = true; 0266 delta *= -1; 0267 } 0268 else 0269 { 0270 d->deltaValues.deltaNegative = false; 0271 } 0272 0273 // Calculate the number of days, hours, minutes and seconds. 0274 0275 d->deltaValues.deltaDays = delta / 86400; 0276 delta = delta % 86400; 0277 d->deltaValues.deltaHours = delta / 3600; 0278 delta = delta % 3600; 0279 d->deltaValues.deltaMinutes = delta / 60; 0280 delta = delta % 60; 0281 d->deltaValues.deltaSeconds = delta; 0282 0283 // Accept the dialog. 0284 0285 saveSettings(); 0286 accept(); 0287 } 0288 0289 void ClockPhotoDialog::slotCancel() 0290 { 0291 saveSettings(); 0292 reject(); 0293 } 0294 0295 } // namespace Digikam 0296 0297 #include "moc_clockphotodialog.cpp"