From: tsteven4 <13596209+tsteven4@users.noreply.github.com> Date: Tue, 8 Oct 2024 12:46:21 +0000 (-0600) Subject: prepare for Qt 6.8 deprecations (#1346) X-Git-Tag: archive/raspbian/1.10.0+ds-2+rpi1~1^2~12^2^2~41 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=bee3999ee9d589b7e594133427e6d535a7edc7b5;p=gpsbabel.git prepare for Qt 6.8 deprecations (#1346) * fix Qt 6.8.0 deprecation warnings. Also, the exif writer now prefers to establish a timestamp from GPS_IFD_TAG_DATESTAMP/GPS_IFD_TAG_TIMESTAMP if they exist, as the exif reader does. * avoid installing *.debug_information modules which appeared with 6.7.0 * centralize decision on lightweight time zones. * correct sort order for includes, duplicates * remove debug statement * remove const from declaration. * simplify lightweight timezone usage via qt version depependent defined constants. * fix for QTimeZone not a QLiteralType * cleanup lightweight time constants. * enhance exif offset test * add missing reference * fix test comment * revert changes to exif writer regarding gps tags. I beleive the original intent of the writer is to create the gps tags from a waypoint. * update qt modules * qt 6.8 work 1. allow builds to succeed without webengine by default. This is needed by CI until aqt catches up. 2. macos minos change for 6.8 3. add macos 6.8.0 to CI, remove macos-12 build. * avoid Wunused-const-variable * add 6.8.0 to ci for windows --- diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 7a143ac06..998c82702 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -18,11 +18,6 @@ jobs: fail-fast: false matrix: include: - - QT_VERSION: '6.2.4' - XCODE_VERSION: '13.4.1' - GENERATOR: 'Ninja' - RELEASE: false - os: macos-12 - QT_VERSION: '6.2.4' XCODE_VERSION: '14.3.1' GENERATOR: 'Ninja' @@ -38,6 +33,11 @@ jobs: GENERATOR: 'Ninja' RELEASE: true os: macos-14 + - QT_VERSION: '6.8.0' + XCODE_VERSION: '16.0' + GENERATOR: 'Ninja' + RELEASE: false + os: macos-15 steps: - name: Checkout repository diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index b37a74a0d..6b9d5d932 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -44,6 +44,14 @@ jobs: RELEASE: true GENERATOR: 'Ninja' os: windows-latest + - QT_VERSION: '6.8.0' + ARCH: 'amd64' + HOST_ARCH: 'amd64' + COMPILER: 'msvc2022_64' + METHOD: 'aqt' + RELEASE: false + GENERATOR: 'Ninja' + os: windows-latest steps: - name: Checkout repository diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a9a1df0d..c0841ee75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,9 @@ if(${Qt6Core_VERSION} VERSION_LESS 6.2) else() message(STATUS "Using Qt6 version ${Qt6Core_VERSION}") endif() +if(${Qt6Core_VERSION} VERSION_GREATER_EQUAL 6.5) + target_compile_definitions(gpsbabel PRIVATE LIGHTWEIGHT_TIMEZONES_SUPPORTED) +endif() option(GPSBABEL_ENABLE_PCH "enable precompiled headers." ON) if (GPSBABEL_ENABLE_PCH) diff --git a/defs.h b/defs.h index 316468c2e..84ecf4636 100644 --- a/defs.h +++ b/defs.h @@ -37,6 +37,9 @@ #include // for QString #include // for QStringView #include // for QTextCodec +#ifdef LIGHTWEIGHT_TIMEZONES_SUPPORTED +#include // for QTimeZone +#endif #include // for CaseInsensitive #include // for QForeachContainer, qMakeForeachContainer, foreach, qint64 @@ -1042,4 +1045,12 @@ int color_to_bbggrr(const char* cname); constexpr double unknown_alt = -99999999.0; constexpr int unknown_color = -1; +#ifdef LIGHTWEIGHT_TIMEZONES_SUPPORTED +constexpr QTimeZone::Initialization QtLocalTime = QTimeZone::LocalTime; +constexpr QTimeZone::Initialization QtUTC = QTimeZone::UTC; +#else +constexpr Qt::TimeSpec QtLocalTime = Qt::LocalTime; +constexpr Qt::TimeSpec QtUTC = Qt::UTC; +#endif + #endif // DEFS_H_INCLUDED_ diff --git a/dg-100.cc b/dg-100.cc index 53bc50fd8..3279daeae 100644 --- a/dg-100.cc +++ b/dg-100.cc @@ -109,7 +109,7 @@ Dg100Format::bintime2utc(int date, int time) date /= 100; int day = date; - return QDateTime(QDate(year, mon, day), QTime(hour, min, sec), Qt::UTC); + return QDateTime(QDate(year, mon, day), QTime(hour, min, sec), QtUTC); } void diff --git a/exif.cc b/exif.cc index c53a2db96..624f5b4ed 100644 --- a/exif.cc +++ b/exif.cc @@ -47,6 +47,9 @@ #include // for QString #include // for QTextCodec #include // for QTime +#ifdef LIGHTWEIGHT_TIMEZONES_SUPPORTED +#include // for QTimeZone +#endif #include // for QVariant #include // for QVector #include // for UTC, ISODate @@ -728,7 +731,11 @@ ExifFormat::exif_get_exif_time(ExifApp* app) const // Correct the date time by supplying the offset from UTC. int offset_hours = match.captured(1).append(match.captured(2)).toInt(); int offset_mins = match.captured(1).append(match.captured(3)).toInt(); +#ifdef LIGHTWEIGHT_TIMEZONES_SUPPORTED + res.setTimeZone(QTimeZone::fromSecondsAheadOfUtc(((offset_hours * 60) + offset_mins) * 60)); +#else res.setOffsetFromUtc(((offset_hours * 60) + offset_mins) * 60); +#endif } else if (opt_offsettime) { // Only warn for user supplied offsets. // Offset tags may indicate the offset was unknown, e.g. " : ". @@ -912,7 +919,7 @@ ExifFormat::exif_waypt_from_exif_app(ExifApp* app) const } } - gps_datetime = QDateTime(datestamp, timestamp, Qt::UTC); + gps_datetime = QDateTime(datestamp, timestamp, QtUTC); if (gps_datetime.isValid()) { if (global_opts.debug_level >= 3) { printf(MYNAME "-GPSTimeStamp = %s\n", qPrintable(gps_datetime.toString(Qt::ISODateWithMs))); diff --git a/garmin_gpi.cc b/garmin_gpi.cc index 745f68c2f..3d0ee0332 100644 --- a/garmin_gpi.cc +++ b/garmin_gpi.cc @@ -178,7 +178,7 @@ GarminGPIFormat::read_header() if (GPI_DBG) { time_t crdate = GPS_Math_Gtime_To_Utime(rdata->crdate); warning("crdate = %lld (%s)\n", (long long) rdata->crdate, - CSTR(QDateTime::fromSecsSinceEpoch(crdate, Qt::UTC).toString(Qt::ISODate))); + CSTR(QDateTime::fromSecsSinceEpoch(crdate, QtUTC).toString(Qt::ISODate))); } (void) gbfgetint16(fin); /* 0 */ diff --git a/gdb.cc b/gdb.cc index 67cd26aec..3b024e063 100644 --- a/gdb.cc +++ b/gdb.cc @@ -62,7 +62,7 @@ constexpr unsigned int GDB_DBG_TRK = 4; constexpr unsigned int GDB_DBG_WPTe = 8; constexpr unsigned int GDB_DBG_RTEe = 16; -constexpr unsigned int GDB_DBG_TRKe = 32; +//constexpr unsigned int GDB_DBG_TRKe = 32; //constexpr unsigned int GDB_DEBUG = (GDB_DBG_WPTe) /* | GDB_DBG_RTE) */; //constexpr unsigned int GDB_DEBUG = 0xff; @@ -1126,7 +1126,7 @@ GdbFormat::write_header() * This is our "Watermark" to show this file was created by GPSbabel. * The date/time used to be from CVS, and may be from git in the future. */ - static const QDateTime gdb_release_dt = QDateTime(QDate(2011, 4, 14), QTime(1, 30, 1), Qt::UTC); + static const QDateTime gdb_release_dt = QDateTime(QDate(2011, 4, 14), QTime(1, 30, 1), QtUTC); gdb_write_cstr(QStringLiteral("GPSBabel-%1").arg(gpsbabel_version)); gdb_write_cstr(gdb_release_dt.toString(u"MMM dd yyyy")); gdb_write_cstr(gdb_release_dt.toString(u"HH:mm:ss")); diff --git a/globalsat_sport.cc b/globalsat_sport.cc index 813586728..e4a69c383 100644 --- a/globalsat_sport.cc +++ b/globalsat_sport.cc @@ -529,7 +529,7 @@ GlobalsatSportFormat::track_read() if (timezn != nullptr) { gpsDateTime = gpsbabel::DateTime(QDateTime(gpsDate, gpsTime, *timezn).toUTC()); } else { - gpsDateTime = gpsbabel::DateTime(QDateTime(gpsDate, gpsTime, Qt::LocalTime).toUTC()); + gpsDateTime = gpsbabel::DateTime(QDateTime(gpsDate, gpsTime, QtLocalTime).toUTC()); } int laps_in_package = header.gh_laprec.LapIndex - header.gh_ptrec.Index + 1; diff --git a/gpx.cc b/gpx.cc index 96af32faa..080ad5659 100644 --- a/gpx.cc +++ b/gpx.cc @@ -517,7 +517,7 @@ xml_parse_time(const QString& dateTimeString) if (res > 0) { QDate date(year, mon, mday); QTime time(hour, min, sec); - dt = QDateTime(date, time, Qt::UTC); + dt = QDateTime(date, time, QtUTC); // Fractional part of time. if (fsec) { diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 04e095498..dc4e0939c 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -22,7 +22,7 @@ if(NOT UNIX OR APPLE) endif() # Find the QtCore library -find_package(Qt6 REQUIRED COMPONENTS Core Gui Network SerialPort Widgets Xml) +find_package(Qt6 REQUIRED COMPONENTS Core Gui Network SerialPort Widgets Xml OPTIONAL_COMPONENTS WebEngineWidgets WebChannel) list(APPEND QT_LIBRARIES Qt6::Core Qt6::Gui Qt6::Network Qt6::SerialPort Qt6::Widgets Qt6::Xml) if(${Qt6Core_VERSION} VERSION_LESS 6.2) message(FATAL_ERROR "Qt version ${Qt6Core_VERSION} found, but version 6.2 or newer is required.") @@ -30,11 +30,13 @@ else() message(STATUS "Using Qt6 version ${Qt6Core_VERSION}") endif() -option(GPSBABEL_MAPPREVIEW "enable map preview." ON) +cmake_dependent_option(GPSBABEL_MAPPREVIEW "enable map preview." ON "Qt6WebEngineWidgets_FOUND;Qt6WebChannel_FOUND" OFF) if (GPSBABEL_MAPPREVIEW) - find_package(Qt6 REQUIRED COMPONENTS WebEngineWidgets WebChannel) list(APPEND QT_LIBRARIES Qt6::WebEngineWidgets Qt6::WebChannel) else() + if (NOT Qt6WebEngineWidgets_FOUND OR NOT Qt6WebChannel_FOUND) + message(WARNING "Optional components Qt6 WebEngineWidgets and/or Qt6 WebChannel not found, MAPPREVIEW is not available.") + endif() target_compile_definitions(gpsbabelfe PRIVATE DISABLE_MAPPREVIEW) endif() diff --git a/gui/filterwidgets.cc b/gui/filterwidgets.cc index 39426e171..9600149a9 100644 --- a/gui/filterwidgets.cc +++ b/gui/filterwidgets.cc @@ -30,6 +30,9 @@ #include // for QEvent, QEvent::LocaleChange #include // for QLabel #include // for QRadioButton +#if (QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)) +#include // for QTimeZone +#endif #include // for LocalTime, UTC @@ -75,17 +78,27 @@ TrackWidget::TrackWidget(QWidget* parent, TrackFilterData& tfd): FilterWidget(pa ui.startEdit->setDisplayFormat("dd MMM yyyy hh:mm:ss AP"); ui.stopEdit->setDisplayFormat("dd MMM yyyy hh:mm:ss AP"); - assert(tfd.startTime.timeSpec() == tfd.stopTime.timeSpec()); - assert((tfd.startTime.timeSpec() == Qt::UTC) || (tfd.startTime.timeSpec() == Qt::LocalTime)); // Qt5 QDateTimeEdit::setDateTime ignored the passed QDateTime::timeSpec. // Qt6 QDateTimeEdit::setDateTime will convert the passed QDateTime if the passed // QDateTime::timeSpec doesn't match QDateTimeEdit::timeSpec. // If the two timeSpecs match Qt5 and Qt6 behave the same. +#if (QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)) + assert(tfd.startTime.timeZone() == tfd.stopTime.timeZone()); + assert((tfd.startTime.timeZone() == QTimeZone::UTC) || (tfd.startTime.timeZone() == QTimeZone::LocalTime)); + ui.startEdit->setTimeZone(tfd.startTime.timeZone()); + ui.stopEdit->setTimeZone(tfd.stopTime.timeZone()); + // Make sure the initial state of the localTime and utc radio buttons + // is in agreement with the startTime::timeSpec and stopTime::timeSpec. + tfd.localTime = tfd.startTime.timeZone() == QTimeZone::LocalTime; +#else + assert(tfd.startTime.timeSpec() == tfd.stopTime.timeSpec()); + assert((tfd.startTime.timeSpec() == Qt::UTC) || (tfd.startTime.timeSpec() == Qt::LocalTime)); ui.startEdit->setTimeSpec(tfd.startTime.timeSpec()); ui.stopEdit->setTimeSpec(tfd.stopTime.timeSpec()); // Make sure the initial state of the localTime and utc radio buttons // is in agreement with the startTime::timeSpec and stopTime::timeSpec. tfd.localTime = tfd.startTime.timeSpec() == Qt::LocalTime; +#endif tfd.utc = !tfd.localTime; // Collect the data fields. @@ -188,11 +201,21 @@ void TrackWidget::splitDistanceX() void TrackWidget::TZX() { if (ui.localTime->isChecked()) { +#if (QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)) + ui.startEdit->setTimeZone(QTimeZone::LocalTime); + ui.stopEdit->setTimeZone(QTimeZone::LocalTime); +#else ui.startEdit->setTimeSpec(Qt::LocalTime); ui.stopEdit->setTimeSpec(Qt::LocalTime); +#endif } else { +#if (QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)) + ui.startEdit->setTimeZone(QTimeZone::UTC); + ui.stopEdit->setTimeZone(QTimeZone::UTC); +#else ui.startEdit->setTimeSpec(Qt::UTC); ui.stopEdit->setTimeSpec(Qt::UTC); +#endif } // Force update of Edit displays, so the displayed // datetimes are in sync with the specified time spec. diff --git a/gui/upgrade.cc b/gui/upgrade.cc index 73211c4cf..3009b6a72 100644 --- a/gui/upgrade.cc +++ b/gui/upgrade.cc @@ -262,14 +262,20 @@ void UpgradeCheck::httpRequestFinished(QNetworkReply* reply) QString oresponse(reply->readAll()); QDomDocument document; - int line = -1; - QString error_text; // This shouldn't ever be seen by a user. - if (!document.setContent(oresponse, &error_text, &line)) { +#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) + if (auto result = document.setContent(oresponse); !result) { +#else + struct { + int errorLine{-1}; + QString errorMessage; + } result; + if (!document.setContent(oresponse, &result.errorMessage, &result.errorLine)) { +#endif QMessageBox::critical(nullptr, tr("Error"), tr("Invalid return data at line %1: %2.") - .arg(line) - .arg(error_text)); + .arg(result.errorLine) + .arg(result.errorMessage)); babelData_.upgradeErrors_++; replyId_ = nullptr; reply->deleteLater(); diff --git a/igc.cc b/igc.cc index 7ef925ee9..1b831a043 100644 --- a/igc.cc +++ b/igc.cc @@ -162,7 +162,7 @@ void IgcFormat::TaskRecordReader::igc_task_rec(const char* rec) } else { year += 1900; } - creation = QDateTime(QDate(year, month, day), QTime(hour, minute, second), Qt::UTC); + creation = QDateTime(QDate(year, month, day), QTime(hour, minute, second), QtUTC); if (!creation.isValid()) { fatal(MYNAME ": bad date time\n%s\n", rec); } @@ -398,7 +398,7 @@ void IgcFormat::read() pres_wpt->fs.FsChainAdd(fsdata); } - pres_wpt->SetCreationTime(QDateTime(date, tod, Qt::UTC)); + pres_wpt->SetCreationTime(QDateTime(date, tod, QtUTC)); // Add the waypoint to the pressure altitude track if (pres_alt) { diff --git a/lowranceusr.cc b/lowranceusr.cc index 8e38e6f8a..9e12d3931 100644 --- a/lowranceusr.cc +++ b/lowranceusr.cc @@ -246,7 +246,7 @@ LowranceusrFormat::lowranceusr4_writestr(const QString& buf, gbfile* file, int b gpsbabel::DateTime LowranceusrFormat::lowranceusr4_get_timestamp(unsigned int jd_number, unsigned int msecs) { - QDateTime qdt = QDateTime(QDate::fromJulianDay(jd_number), QTime(0, 0, 0), Qt::UTC).addMSecs(msecs); + QDateTime qdt = QDateTime(QDate::fromJulianDay(jd_number), QTime(0, 0, 0), QtUTC).addMSecs(msecs); return qdt; } diff --git a/mtk_logger.cc b/mtk_logger.cc index ea7fcebbf..3a2217c85 100644 --- a/mtk_logger.cc +++ b/mtk_logger.cc @@ -839,7 +839,7 @@ int MtkLoggerBase::csv_line(gbfile* csvFile, int idx, unsigned long bmask, data_ , (itm->rcr&0x0004)?"D":"", (itm->rcr&0x0008)?"B":""); if (bmask & (1U<timestamp, Qt::UTC); + QDateTime dt = QDateTime::fromSecsSinceEpoch(itm->timestamp, QtUTC); dt = dt.addMSecs(itm->timestamp_ms); QString timestamp = dt.toUTC().toString(u"yyyy/MM/dd,hh:mm:ss.zzz"); diff --git a/nmea.cc b/nmea.cc index f07d78b9f..62f906242 100644 --- a/nmea.cc +++ b/nmea.cc @@ -324,14 +324,14 @@ void NmeaFormat::nmea_set_waypoint_time(Waypoint* wpt, QDateTime* prev, const QDate& date, const QTime& time) { if (date.isValid()) { - wpt->SetCreationTime(QDateTime(date, time, Qt::UTC)); + wpt->SetCreationTime(QDateTime(date, time, QtUTC)); if (wpt->wpt_flags.fmt_use != 0) { wpt->wpt_flags.fmt_use = 0; without_date--; } *prev = wpt->GetCreationTime(); } else if (prev->date().isValid()) { - wpt->SetCreationTime(QDateTime(prev->date(), time, Qt::UTC)); + wpt->SetCreationTime(QDateTime(prev->date(), time, QtUTC)); if (*prev > wpt->creation_time) { /* go over midnight ? */ wpt->creation_time = wpt->creation_time.addDays(1); @@ -342,7 +342,7 @@ NmeaFormat::nmea_set_waypoint_time(Waypoint* wpt, QDateTime* prev, const QDate& } *prev = wpt->GetCreationTime(); } else { - wpt->SetCreationTime(QDateTime(QDate(), time, Qt::UTC)); + wpt->SetCreationTime(QDateTime(QDate(), time, QtUTC)); if (wpt->wpt_flags.fmt_use == 0) { wpt->wpt_flags.fmt_use = 1; without_date++; @@ -639,7 +639,7 @@ NmeaFormat::gpzda_parse(const QString& ibuf) // The prev_datetime data member might be used by // nmea_fix_timestamps and nmea_set_waypoint_time. - prev_datetime = QDateTime(date, time, Qt::UTC); + prev_datetime = QDateTime(date, time, QtUTC); } } @@ -839,7 +839,7 @@ NmeaFormat::nmea_fix_timestamps(route_head* track) return; } - QDateTime prev = QDateTime(opt_tm, QTime(0, 0), Qt::UTC); + QDateTime prev = QDateTime(opt_tm, QTime(0, 0), QtUTC); foreach (Waypoint* wpt, track->waypoint_list) { diff --git a/reference/ricoh-rdc5300.jpg.jpg b/reference/ricoh-rdc5300.jpg.jpg index 9aa1027cd..feda00cbd 100644 Binary files a/reference/ricoh-rdc5300.jpg.jpg and b/reference/ricoh-rdc5300.jpg.jpg differ diff --git a/reference/ricoh-rdc5300_offset.csv b/reference/ricoh-rdc5300_offset.csv new file mode 100644 index 000000000..abac49f4e --- /dev/null +++ b/reference/ricoh-rdc5300_offset.csv @@ -0,0 +1,2 @@ +No,Latitude,Longitude,Name,Speed,utc_d,utc_t +1,44.315150,15.265690,"ricoh-rdc5300",0.00,2000/05/31,22:50:40 diff --git a/reference/ricoh-rdc5300_offsettime.jpg b/reference/ricoh-rdc5300_offsettime.jpg new file mode 100644 index 000000000..dc46e1392 Binary files /dev/null and b/reference/ricoh-rdc5300_offsettime.jpg differ diff --git a/reference/ricoh-rdc5300_offsettime.jpg.jpg b/reference/ricoh-rdc5300_offsettime.jpg.jpg new file mode 100644 index 000000000..07aefa110 Binary files /dev/null and b/reference/ricoh-rdc5300_offsettime.jpg.jpg differ diff --git a/skytraq.cc b/skytraq.cc index f6df657af..2b2721367 100644 --- a/skytraq.cc +++ b/skytraq.cc @@ -534,7 +534,7 @@ SkytraqBase::gpstime_to_qdatetime(int week, int sec) const int override = xstrtoi(opt_gps_utc_offset, nullptr, 10); if (override) { gps_timet -= override; - return QDateTime::fromSecsSinceEpoch(gps_timet, Qt::UTC); + return QDateTime::fromSecsSinceEpoch(gps_timet, QtUTC); } /* leap second compensation: */ @@ -557,7 +557,7 @@ SkytraqBase::gpstime_to_qdatetime(int week, int sec) const // Future: Consult http://maia.usno.navy.mil/ser7/tai-utc.dat // use http://www.stevegs.com/utils/jd_calc/ for Julian to UNIX sec - return QDateTime::fromSecsSinceEpoch(gps_timet, Qt::UTC); + return QDateTime::fromSecsSinceEpoch(gps_timet, QtUTC); } void diff --git a/src/core/datetime.h b/src/core/datetime.h index 579c50089..30962f23b 100644 --- a/src/core/datetime.h +++ b/src/core/datetime.h @@ -29,6 +29,9 @@ #include #include #include +#ifdef LIGHTWEIGHT_TIMEZONES_SUPPORTED +#include +#endif // As this code began in C, we have several hundred places that set and // read creation_time as a time_t. Provide some operator overloads to make @@ -54,7 +57,11 @@ public: // Qt::LocalTime compared to Qt::UTC on ubuntu bionic. // Note that these conversions can be required if the Qt::TimeSpec is // set to Qt:LocalTime after construction. +#ifdef LIGHTWEIGHT_TIMEZONES_SUPPORTED + DateTime() : QDateTime(QDateTime::fromMSecsSinceEpoch(0, QTimeZone::UTC)) +#else DateTime() : QDateTime(QDateTime::fromMSecsSinceEpoch(0, Qt::UTC)) +#endif { } diff --git a/subrip.cc b/subrip.cc index ee6116b58..062e690b4 100644 --- a/subrip.cc +++ b/subrip.cc @@ -221,7 +221,7 @@ SubripFormat::wr_init(const QString& fname) fatal(FatalMsg().nospace() << MYNAME ": option gps_time value (" << opt_gpstime << ") is invalid. Expected hhmmss[.sss]"); } } - gps_datetime = QDateTime(gps_date, gps_time, Qt::UTC); + gps_datetime = QDateTime(gps_date, gps_time, QtUTC); } video_offset_ms = 0; diff --git a/testo.d/exif.test b/testo.d/exif.test index 26c39b29b..6cd71360e 100644 --- a/testo.d/exif.test +++ b/testo.d/exif.test @@ -23,6 +23,56 @@ bincompare ${REFERENCE}/kodak-dc210.jpg.jpg ${TMPDIR}/kodak-dc210.jpg.jpg # test a big endian image # image from https://github.com/ianare/exif-samples.git cp ${REFERENCE}/ricoh-rdc5300.jpg ${TMPDIR}/ricoh-rdc5300.jpg -gpsbabel -i unicsv -f ${REFERENCE}/IMG_2065_retag.csv -o exif,name=IMG_2065 -F ${TMPDIR}/ricoh-rdc5300.jpg +gpsbabel -i unicsv -f ${REFERENCE}/ricoh-rdc5300_offset.csv -o exif,name=ricoh-rdc5300 -F ${TMPDIR}/ricoh-rdc5300.jpg bincompare ${REFERENCE}/ricoh-rdc5300.jpg.jpg ${TMPDIR}/ricoh-rdc5300.jpg.jpg +# test offset option. photo has no gps info and no exif offset tags. +# the offset is only required if the current system timezone is differnt from utc. +# cat reference/ricoh-rdc5300_offset.csv +# No,Latitude,Longitude,Name,Speed,utc_d,utc_t +# 1,44.315150,15.265690,"ricoh-rdc5300",0.00,2000/05/31,22:50:40 +# $ exiftool -D -G -time:all -composite:GPSPosition -c "%+.6f" reference/ricoh-rdc5300.jpg +# [File] - File Modification Date/Time : 2024:09:27 07:18:42-06:00 +# [File] - File Access Date/Time : 2024:09:28 07:19:24-06:00 +# [File] - File Inode Change Date/Time : 2024:09:27 07:18:42-06:00 +# [EXIF] 36867 Date/Time Original : 2000:05:31 21:50:40 +# [EXIF] 36868 Create Date : 2000:05:31 21:50:40 +# $ exiftool -D -G -time:all -composite:GPSPosition -c "%+.6f" reference/ricoh-rdc5300.jpg.jpg +# [File] - File Modification Date/Time : 2024:09:29 07:04:04-06:00 +# [File] - File Access Date/Time : 2024:09:29 07:04:06-06:00 +# [File] - File Inode Change Date/Time : 2024:09:29 07:04:04-06:00 +# [EXIF] 36867 Date/Time Original : 2000:05:31 21:50:40 +# [EXIF] 36868 Create Date : 2000:05:31 21:50:40 +# [EXIF] 7 GPS Time Stamp : 22:50:40 +# [EXIF] 29 GPS Date Stamp : 2000:05:31 +# [Composite] - GPS Date/Time : 2000:05:31 22:50:40Z +# [Composite] - GPS Position : +44.315150, +15.265690 +cp ${REFERENCE}/ricoh-rdc5300.jpg ${TMPDIR}/ricoh-rdc5300_offset.jpg +gpsbabel -i unicsv -f ${REFERENCE}/ricoh-rdc5300_offset.csv -o exif,offset="-01:00" -F ${TMPDIR}/ricoh-rdc5300_offset.jpg +bincompare ${REFERENCE}/ricoh-rdc5300.jpg.jpg ${TMPDIR}/ricoh-rdc5300_offset.jpg.jpg + +# prove the option value is handled the same as the OffsetTimeOriginal tag. +# $ exiftool -D -G -time:all -composite:GPSPosition -c "%+.6f" reference/ricoh-rdc5300_offsettime.jpg +# [File] - File Modification Date/Time : 2024:09:29 06:32:54-06:00 +# [File] - File Access Date/Time : 2024:09:29 06:33:20-06:00 +# [File] - File Inode Change Date/Time : 2024:09:29 06:32:54-06:00 +# [EXIF] 36867 Date/Time Original : 2000:05:31 21:50:40 +# [EXIF] 36868 Create Date : 2000:05:31 21:50:40 +# [EXIF] 36881 Offset Time Original : -01:00 +# [Composite] - Date/Time Original : 2000:05:31 21:50:40-01:00 +# $ exiftool -D -G -time:all -composite:GPSPosition -c "%+.6f" reference/ricoh-rdc5300_offsettime.jpg.jpg +# [File] - File Modification Date/Time : 2024:09:29 07:09:20-06:00 +# [File] - File Access Date/Time : 2024:09:29 07:09:53-06:00 +# [File] - File Inode Change Date/Time : 2024:09:29 07:09:20-06:00 +# [EXIF] 36867 Date/Time Original : 2000:05:31 21:50:40 +# [EXIF] 36868 Create Date : 2000:05:31 21:50:40 +# [EXIF] 36881 Offset Time Original : -01:00 +# [EXIF] 7 GPS Time Stamp : 22:50:40 +# [EXIF] 29 GPS Date Stamp : 2000:05:31 +# [Composite] - Date/Time Original : 2000:05:31 21:50:40-01:00 +# [Composite] - GPS Date/Time : 2000:05:31 22:50:40Z +# [Composite] - GPS Position : +44.315150, +15.265690 +cp ${REFERENCE}/ricoh-rdc5300_offsettime.jpg ${TMPDIR}/ricoh-rdc5300_offsettime.jpg +gpsbabel -i unicsv -f ${REFERENCE}/ricoh-rdc5300_offset.csv -o exif -F ${TMPDIR}/ricoh-rdc5300_offsettime.jpg +bincompare ${REFERENCE}/ricoh-rdc5300_offsettime.jpg.jpg ${TMPDIR}/ricoh-rdc5300_offsettime.jpg.jpg + diff --git a/tools/ci_install_qt.sh b/tools/ci_install_qt.sh index 611aeb291..246787f56 100755 --- a/tools/ci_install_qt.sh +++ b/tools/ci_install_qt.sh @@ -19,6 +19,9 @@ remove=( \ debug_info \ qtcharts \ qtdatavis3d \ +qtgraphs \ +qtgrpc \ +qthttpserver \ qtlottie \ qtnetworkauth \ qtquick3d \ @@ -40,6 +43,9 @@ do skip=true fi done + if [[ "$a" == *".debug_information" ]]; then + skip=true + fi if [ $skip == false ]; then mods+=( "$a" ) fi diff --git a/tools/ci_install_windows.sh b/tools/ci_install_windows.sh index 1f2cad96c..7753a2b38 100755 --- a/tools/ci_install_windows.sh +++ b/tools/ci_install_windows.sh @@ -30,6 +30,8 @@ elif [ "${COMPILER}" = "msvc2019_64" ]; then PACKAGE_SUFFIX=win64_msvc2019_64 elif [ "${COMPILER}" = "msvc2019" ]; then PACKAGE_SUFFIX=win32_msvc2019 +elif [ "${COMPILER}" = "msvc2022_64" ]; then + PACKAGE_SUFFIX=win64_msvc2022_64 else echo "ERROR: unrecognized Qt compiler ${COMPILER}." >&2 exit 1 diff --git a/tools/ci_script_osx.sh b/tools/ci_script_osx.sh index 7222bc86d..a59d49890 100755 --- a/tools/ci_script_osx.sh +++ b/tools/ci_script_osx.sh @@ -17,7 +17,10 @@ if [ $# -ge 3 ]; then GENERATOR[1]=$3 fi fi -if version_ge "${QTVER}" 6.5.0; then +if version_ge "${QTVER}" 6.8.0; then + DEPLOY_TARGET="12.0" + ARCHS="x86_64;arm64" +elif version_ge "${QTVER}" 6.5.0; then DEPLOY_TARGET="11.0" ARCHS="x86_64;arm64" elif version_ge "${QTVER}" 6.0.0; then diff --git a/trackfilter.cc b/trackfilter.cc index 06f7c8bf3..835cd6099 100644 --- a/trackfilter.cc +++ b/trackfilter.cc @@ -41,6 +41,9 @@ static constexpr bool TRACKF_DBG = false; #include // for QRegularExpression, QRegularExpression::CaseInsensitiveOption, QRegularExpression::PatternOptions #include // for QRegularExpressionMatch #include // for QString +#ifdef LIGHTWEIGHT_TIMEZONES_SUPPORTED +#include // for QTimeZone +#endif #include // for UTC, CaseInsensitive #include // for foreach, qPrintable, QAddConst<>::Type, qint64 @@ -298,7 +301,7 @@ void TrackFilter::trackfilter_title() fatal(MYNAME "-title: Missing your title!\n"); } for (auto* track : std::as_const(track_list)) { - trackfilter_pack_init_rte_name(track, QDateTime::fromMSecsSinceEpoch(0, Qt::UTC)); + trackfilter_pack_init_rte_name(track, QDateTime::fromMSecsSinceEpoch(0, QtUTC)); } } @@ -676,7 +679,11 @@ QDateTime TrackFilter::trackfilter_range_check(const char* timestr) if (match.hasMatch()) { // QTime::fromString zzz expects exactly 3 digits representing milliseconds. result = QDateTime::fromString(match.captured(0), u"yyyyMMddHHmmss.zzz"); +#ifdef LIGHTWEIGHT_TIMEZONES_SUPPORTED + result.setTimeZone(QTimeZone::UTC); +#else result.setTimeSpec(Qt::UTC); +#endif if (!result.isValid()) { fatal(MYNAME "-range-check: Invalid timestamp \"%s\"!\n", timestr); } @@ -834,7 +841,11 @@ TrackFilter::faketime_t TrackFilter::trackfilter_faketime_check(const char* time QString fmtstart("00000101000000"); fmtstart.replace(0, start.size(), start); result.start = QDateTime::fromString(fmtstart, u"yyyyMMddHHmmss"); +#ifdef LIGHTWEIGHT_TIMEZONES_SUPPORTED + result.start.setTimeZone(QTimeZone::UTC); +#else result.start.setTimeSpec(Qt::UTC); +#endif if (!result.start.isValid()) { fatal(MYNAME "-faketime-check: Invalid timestamp \"%s\"!\n", qPrintable(start)); } diff --git a/util.cc b/util.cc index 53e3b983f..bf54ad498 100644 --- a/util.cc +++ b/util.cc @@ -294,6 +294,31 @@ QDateTime make_datetime(QDate date, QTime time, bool is_localtime, bool force_utc, int utc_offset) { QDateTime result; +#ifdef LIGHTWEIGHT_TIMEZONES_SUPPORTED + QTimeZone timezone; + + if (is_localtime) { + if (force_utc) { // override with passed option value + timezone = QTimeZone::fromSecondsAheadOfUtc(utc_offset); + } else { + timezone = QTimeZone::LocalTime; + } + } else { + timezone = QTimeZone::UTC; + } + + if (date.isValid() && time.isValid()) { + result = QDateTime(date, time, timezone); + } else if (time.isValid()) { + // TODO: Wouldn't it be better to return an invalid QDateTime + // that contained an invalid QDate, a valid QTime and a valid + // Qt::TimeSpec? + result = QDateTime(QDate(1970, 1, 1), time, timezone); + } else if (date.isValid()) { + // no time, use start of day in the given Qt::TimeSpec. + result = date.startOfDay(timezone); + } +#else Qt::TimeSpec timespec; int offset = 0; @@ -326,6 +351,7 @@ make_datetime(QDate date, QTime time, bool is_localtime, bool force_utc, int utc result = date.startOfDay(timespec, offset); } +#endif return result; } @@ -347,7 +373,7 @@ gpsbabel::DateTime current_time() { if (gpsbabel_testmode()) { - return QDateTime::fromMSecsSinceEpoch(0, Qt::UTC); + return QDateTime::fromMSecsSinceEpoch(0, QtUTC); } return QDateTime::currentDateTimeUtc(); @@ -361,14 +387,14 @@ current_time() */ QDateTime dotnet_time_to_qdatetime(long long dotnet) { - QDateTime epoch = QDateTime(QDate(1, 1, 1), QTime(0, 0, 0), Qt::UTC); + QDateTime epoch = QDateTime(QDate(1, 1, 1), QTime(0, 0, 0), QtUTC); qint64 millisecs = (dotnet + 5000)/ 10000; return epoch.addMSecs(millisecs); } long long qdatetime_to_dotnet_time(const QDateTime& dt) { - QDateTime epoch = QDateTime(QDate(1, 1, 1), QTime(0, 0, 0), Qt::UTC); + QDateTime epoch = QDateTime(QDate(1, 1, 1), QTime(0, 0, 0), QtUTC); qint64 millisecs = epoch.msecsTo(dt); return millisecs * 10000; } diff --git a/v900.cc b/v900.cc index 4b8fb942e..baf5a326b 100644 --- a/v900.cc +++ b/v900.cc @@ -143,7 +143,7 @@ V900Format::bintime2utc(int date, int time) { // What's left in 'date' is year. QDate dt(date + 2000, month, day); - return QDateTime(dt, tm, Qt::UTC); + return QDateTime(dt, tm, QtUTC); } void