Hi! Here are my two commits for improving images addition. Main goal was to add some feedback when photos aren't in dives time range (they cannot be added then) as discussed with Tomaz.
During my work it appeared that some refactor in images timestamps code was needed. Miika mentioned that we can eventually need another way of getting timestamtps so I completely seperated it. Right now I can see two issues: 1) I'm not sure if the type of warning I wrote is right. It can be easily changed by anyone. 2) EXIF funtions were located in qthelper.c. I also put there code of the timestamp extraction but I'm not sure if these things should be there... It's quiet unintuitive for me. Greetings, Jan Darowski
From a66d28496ed2558b737ebb004ad2d84d3ae807bb Mon Sep 17 00:00:00 2001 From: Eltharan <[email protected]> Date: Sat, 14 Mar 2015 15:35:47 +0100 Subject: [PATCH 1/2] Refactored image timestamp checking. Seperated getting image timestamp from picture_load_exif_data() and ShiftImageTimesDialog::syncCameraClicked() into picture_get_timestamp() and seperated checking timestamp from dive_create_picture() to dive_check_picture_time(). Signed-off-by: Jan Darowski <[email protected]> --- dive.c | 43 ++++++++++++++++++++++++++++++++++--------- dive.h | 5 ++++- qt-ui/simplewidgets.cpp | 14 ++++---------- qthelper.cpp | 19 +++++++++++++++++-- 4 files changed, 59 insertions(+), 22 deletions(-) diff --git a/dive.c b/dive.c index 2fb0875..f2a3712 100644 --- a/dive.c +++ b/dive.c @@ -2884,22 +2884,47 @@ static bool new_picture_for_dive(struct dive *d, char *filename) // only add pictures that have timestamps between 30 minutes before the dive and // 30 minutes after the dive ends #define D30MIN (30 * 60) +bool dive_check_picture_time(struct dive *d, char *filename, int shift_time) +{ + timestamp_t timestamp = 0; + picture_get_timestamp(filename, ×tamp); + offset_t offset; + if (timestamp) { + offset.seconds = timestamp - d->when + shift_time; + if (offset.seconds > -D30MIN && offset.seconds < (int)d->duration.seconds + D30MIN) { + // this picture belongs to this dive + return true; + } + } + return false; +} + +bool picture_check_valid(char *filename, int shift_time) +{ + bool result = false; + int i; + struct dive *d; + + for_each_dive (i, d) + if (d->selected) + result = result || dive_check_picture_time(d, filename, shift_time); + return result; +} + void dive_create_picture(struct dive *d, char *filename, int shift_time) { timestamp_t timestamp; if (!new_picture_for_dive(d, filename)) return; + if (!dive_check_picture_time(d, filename, shift_time)) + return; + struct picture *p = alloc_picture(); p->filename = filename; - picture_load_exif_data(p, ×tamp); - if (timestamp) { - p->offset.seconds = timestamp - d->when + shift_time; - if (p->offset.seconds < -D30MIN || p->offset.seconds > (int)d->duration.seconds + D30MIN) { - // this picture doesn't belong to this dive - free(p); - return; - } - } + picture_get_timestamp(filename, ×tamp); + p->offset.seconds = timestamp - d->when + shift_time; + picture_load_exif_data(p); + dive_add_picture(d, p); dive_set_geodata_from_picture(d, p); } diff --git a/dive.h b/dive.h index 528b45a..97d8523 100644 --- a/dive.h +++ b/dive.h @@ -381,11 +381,14 @@ struct picture { for (struct picture *picture = (_divestruct).picture_list; picture; picture = picture->next) extern struct picture *alloc_picture(); +extern bool dive_check_picture_time(struct dive *d, char *filename, int shift_time); extern void dive_create_picture(struct dive *d, char *filename, int shift_time); extern void dive_add_picture(struct dive *d, struct picture *newpic); extern void dive_remove_picture(char *filename); extern unsigned int dive_get_picture_count(struct dive *d); -extern void picture_load_exif_data(struct picture *p, timestamp_t *timestamp); +extern bool picture_check_valid(char *filename, int shift_time); +extern void picture_load_exif_data(struct picture *p); +extern void picture_get_timestamp(char *filename, timestamp_t *t); extern void dive_set_geodata_from_picture(struct dive *d, struct picture *pic); extern int explicit_first_cylinder(struct dive *dive, struct divecomputer *dc); diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index ecb8a8b..8a0f2b0 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -272,9 +272,7 @@ void ShiftImageTimesDialog::buttonClicked(QAbstractButton *button) void ShiftImageTimesDialog::syncCameraClicked() { - struct memblock mem; - EXIFInfo exiv; - int retval; + timestamp_t timestamp; QPixmap picture; QDateTime dcDateTime = QDateTime(); QStringList fileNames = QFileDialog::getOpenFileNames(this, @@ -290,13 +288,9 @@ void ShiftImageTimesDialog::syncCameraClicked() scene->addPixmap(picture.scaled(ui.DCImage->size())); ui.DCImage->setScene(scene); - if (readfile(fileNames.at(0).toUtf8().data(), &mem) <= 0) - return; - retval = exiv.parseFrom((const unsigned char *)mem.buffer, (unsigned)mem.size); - free(mem.buffer); - if (retval != PARSE_EXIF_SUCCESS) - return; - dcImageEpoch = exiv.epoch(); + + picture_get_timestamp(fileNames.at(0).toUtf8().data(), ×tamp); + dcImageEpoch = timestamp; dcDateTime.setTime_t(dcImageEpoch); ui.dcTime->setDateTime(dcDateTime); connect(ui.dcTime, SIGNAL(dateTimeChanged(const QDateTime &)), this, SLOT(dcDateTimeChanged(const QDateTime &))); diff --git a/qthelper.cpp b/qthelper.cpp index 189d47e..b63eb66 100644 --- a/qthelper.cpp +++ b/qthelper.cpp @@ -334,7 +334,7 @@ extern "C" xsltStylesheetPtr get_stylesheet(const char *name) return xslt; } -extern "C" void picture_load_exif_data(struct picture *p, timestamp_t *timestamp) +extern "C" void picture_load_exif_data(struct picture *p) { EXIFInfo exif; memblock mem; @@ -343,7 +343,6 @@ extern "C" void picture_load_exif_data(struct picture *p, timestamp_t *timestamp goto picture_load_exit; if (exif.parseFrom((const unsigned char *)mem.buffer, (unsigned)mem.size) != PARSE_EXIF_SUCCESS) goto picture_load_exit; - *timestamp = exif.epoch(); p->longitude.udeg= lrint(1000000.0 * exif.GeoLocation.Longitude); p->latitude.udeg = lrint(1000000.0 * exif.GeoLocation.Latitude); @@ -352,6 +351,22 @@ picture_load_exit: return; } +extern "C" void picture_get_timestamp(char *filename, timestamp_t *t) +{ + EXIFInfo exif; + memblock mem; + int retval; + + if (readfile(filename, &mem) <= 0) + return; + retval = exif.parseFrom((const unsigned char *)mem.buffer, (unsigned)mem.size); + free(mem.buffer); + if (retval != PARSE_EXIF_SUCCESS) + return; + *t = exif.epoch(); + return; +} + extern "C" const char *system_default_directory(void) { static char filename[PATH_MAX]; -- 2.2.2
From 9a12aac00e63072ebcddca8c2180f987815811d6 Mon Sep 17 00:00:00 2001 From: Eltharan <[email protected]> Date: Sat, 14 Mar 2015 17:44:24 +0100 Subject: [PATCH 2/2] Added warning when not all images can be added. Added label in the ShiftImageTimesDialog which appears when not all of the selected images have timestamp in the checked range. Made cancel button in this widget actually work. Signed-off-by: Jan Darowski <[email protected]> --- qt-ui/divelistview.cpp | 5 +++-- qt-ui/shiftimagetimes.ui | 27 +++++++++++++++++++++------ qt-ui/simplewidgets.cpp | 24 ++++++++++++++++++++++-- qt-ui/simplewidgets.h | 5 ++++- 4 files changed, 50 insertions(+), 11 deletions(-) diff --git a/qt-ui/divelistview.cpp b/qt-ui/divelistview.cpp index e4ccb72..32679be 100644 --- a/qt-ui/divelistview.cpp +++ b/qt-ui/divelistview.cpp @@ -850,9 +850,10 @@ void DiveListView::loadImages() return; updateLastUsedImageDir(QFileInfo(fileNames[0]).dir().path()); - ShiftImageTimesDialog shiftDialog(this); + ShiftImageTimesDialog shiftDialog(this, fileNames); shiftDialog.setOffset(lastImageTimeOffset()); - shiftDialog.exec(); + if (!shiftDialog.exec()) + return; updateLastImageTimeOffset(shiftDialog.amount()); Q_FOREACH (const QString &fileName, fileNames) { diff --git a/qt-ui/shiftimagetimes.ui b/qt-ui/shiftimagetimes.ui index cce51e8..ad81923 100644 --- a/qt-ui/shiftimagetimes.ui +++ b/qt-ui/shiftimagetimes.ui @@ -48,9 +48,9 @@ <hour>23</hour> <minute>59</minute> <second>59</second> - <year>2010</year> - <month>12</month> - <day>31</day> + <year>2000</year> + <month>1</month> + <day>1</day> </datetime> </property> <property name="minimumDateTime"> @@ -65,9 +65,9 @@ </property> <property name="maximumDate"> <date> - <year>2010</year> - <month>12</month> - <day>31</day> + <year>2000</year> + <month>1</month> + <day>1</day> </date> </property> <property name="minimumDate"> @@ -117,6 +117,21 @@ </widget> </item> <item> + <widget class="QLabel" name="warningLabel"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="styleSheet"> + <string notr="true">color: red;</string> + </property> + <property name="text"> + <string>Warning! +Not all images have timestamps between +30 minutes before the dive and 30 minutes after the dive ends.</string> + </property> + </widget> + </item> + <item> <widget class="QDialogButtonBox" name="buttonBox"> <property name="orientation"> <enum>Qt::Horizontal</enum> diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index 8a0f2b0..b499095 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -289,7 +289,7 @@ void ShiftImageTimesDialog::syncCameraClicked() scene->addPixmap(picture.scaled(ui.DCImage->size())); ui.DCImage->setScene(scene); - picture_get_timestamp(fileNames.at(0).toUtf8().data(), ×tamp); + picture_get_timestamp(qstrdup(fileNames.at(0).toUtf8().data()), ×tamp); dcImageEpoch = timestamp; dcDateTime.setTime_t(dcImageEpoch); ui.dcTime->setDateTime(dcDateTime); @@ -303,11 +303,12 @@ void ShiftImageTimesDialog::dcDateTimeChanged(const QDateTime &newDateTime) setOffset(newDateTime.toTime_t() - dcImageEpoch); } -ShiftImageTimesDialog::ShiftImageTimesDialog(QWidget *parent) : QDialog(parent), m_amount(0) +ShiftImageTimesDialog::ShiftImageTimesDialog(QWidget *parent, QStringList fileNames) : QDialog(parent), m_amount(0), fileNames(fileNames) { ui.setupUi(this); connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton *)), this, SLOT(buttonClicked(QAbstractButton *))); connect(ui.syncCamera, SIGNAL(clicked()), this, SLOT(syncCameraClicked())); + connect(ui.timeEdit, SIGNAL(timeChanged(const QTime &)), this, SLOT(timeEditChanged(const QTime &))); dcImageEpoch = (time_t)0; } @@ -327,6 +328,25 @@ void ShiftImageTimesDialog::setOffset(time_t offset) ui.timeEdit->setTime(QTime(offset / 3600, (offset % 3600) / 60, offset % 60)); } +void ShiftImageTimesDialog::updateInvalid() +{ + ui.warningLabel->hide(); + bool allValid = true; + Q_FOREACH (const QString &fileName, fileNames) { + allValid = allValid && picture_check_valid(qstrdup(fileName.toUtf8().data()), m_amount); + } + if (!allValid) + ui.warningLabel->show(); +} + +void ShiftImageTimesDialog::timeEditChanged(const QTime &time) +{ + m_amount = time.hour() * 3600 + time.minute() * 60; + if (ui.backwards->isChecked()) + m_amount *= -1; + updateInvalid(); +} + bool isGnome3Session() { #if defined(QT_OS_WIW) || defined(QT_OS_MAC) diff --git a/qt-ui/simplewidgets.h b/qt-ui/simplewidgets.h index 75b1df4..5f2402a 100644 --- a/qt-ui/simplewidgets.h +++ b/qt-ui/simplewidgets.h @@ -97,7 +97,7 @@ private: class ShiftImageTimesDialog : public QDialog { Q_OBJECT public: - explicit ShiftImageTimesDialog(QWidget *parent); + explicit ShiftImageTimesDialog(QWidget *parent, QStringList fileNames); time_t amount() const; void setOffset(time_t offset); private @@ -105,8 +105,11 @@ slots: void buttonClicked(QAbstractButton *button); void syncCameraClicked(); void dcDateTimeChanged(const QDateTime &); + void timeEditChanged(const QTime &time); + void updateInvalid(); private: + QStringList fileNames; Ui::ShiftImageTimesDialog ui; time_t m_amount; time_t dcImageEpoch; -- 2.2.2
_______________________________________________ subsurface mailing list [email protected] http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface
