From c173fc567db339330bffa3e51769d63c8d18a6de Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava Date: Wed, 11 Feb 2015 13:00:10 -0200 Subject: [PATCH 01/58] Add the ui file for the location information Just the xml file for the Ui location information. Signed-off-by: Tomaz Canabrava Signed-off-by: Dirk Hohndel --- qt-ui/locationInformation.ui | 75 ++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 qt-ui/locationInformation.ui diff --git a/qt-ui/locationInformation.ui b/qt-ui/locationInformation.ui new file mode 100644 index 000000000..41e8ad0bc --- /dev/null +++ b/qt-ui/locationInformation.ui @@ -0,0 +1,75 @@ + + + GroupBox + + + + 0 + 0 + 400 + 300 + + + + GroupBox + + + Dive Site + + + + + + + + + Name + + + + + + + + + + Coordinates + + + + + + + + + + Description + + + + + + + + + + Notes + + + + + + + + + + + KMessageWidget + QWidget +
kmessagewidget.h
+ 1 +
+
+ + +
From 63e998b4bdeeea6d4a79533845761ef0368552de Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava Date: Wed, 11 Feb 2015 13:04:29 -0200 Subject: [PATCH 02/58] More meaningfull names for the ui elements. Signed-off-by: Tomaz Canabrava Signed-off-by: Dirk Hohndel --- qt-ui/locationInformation.ui | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qt-ui/locationInformation.ui b/qt-ui/locationInformation.ui index 41e8ad0bc..1d7afa77d 100644 --- a/qt-ui/locationInformation.ui +++ b/qt-ui/locationInformation.ui @@ -28,7 +28,7 @@ - + @@ -38,7 +38,7 @@ - + @@ -48,7 +48,7 @@ - + @@ -58,7 +58,7 @@ - + From 3516ff2ab27905bc7698d5b052084b162042427f Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava Date: Wed, 11 Feb 2015 13:13:52 -0200 Subject: [PATCH 03/58] Create simple class to hold the location management. Signed-off-by: Tomaz Canabrava Signed-off-by: Dirk Hohndel --- qt-ui/locationInformation.ui | 4 ++-- qt-ui/simplewidgets.cpp | 4 ++++ qt-ui/simplewidgets.h | 11 +++++++++++ subsurface.pro | 3 ++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/qt-ui/locationInformation.ui b/qt-ui/locationInformation.ui index 1d7afa77d..658395b35 100644 --- a/qt-ui/locationInformation.ui +++ b/qt-ui/locationInformation.ui @@ -1,7 +1,7 @@ - GroupBox - + LocationInformation + 0 diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index 5c08a3f7e..98d9bcf9f 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -646,3 +646,7 @@ void MultiFilter::closeFilter() MultiFilterSortModel::instance()->clearFilter(); hide(); } + +LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBox(parent) { + ui.setupUi(this); +} diff --git a/qt-ui/simplewidgets.h b/qt-ui/simplewidgets.h index 8d5b4f73c..cfa9e0423 100644 --- a/qt-ui/simplewidgets.h +++ b/qt-ui/simplewidgets.h @@ -6,6 +6,7 @@ class QAbstractButton; class QNetworkReply; #include +#include #include #include @@ -214,6 +215,16 @@ private: Ui::FilterWidget ui; }; +#include "ui_locationInformation.h" + +class LocationInformationWidget : public QGroupBox { +Q_OBJECT +public: + LocationInformationWidget(QWidget *parent = 0); +private: + Ui::LocationInformation ui; +}; + bool isGnome3Session(); QImage grayImage(const QImage &coloredImg); diff --git a/subsurface.pro b/subsurface.pro index d65c94f50..2469b8aa9 100644 --- a/subsurface.pro +++ b/subsurface.pro @@ -238,7 +238,8 @@ FORMS = \ qt-ui/listfilter.ui \ qt-ui/diveshareexportdialog.ui \ qt-ui/filterwidget.ui \ - qt-ui/plannerDetails.ui + qt-ui/plannerDetails.ui \ + qt-ui/locationInformation.ui # Nether usermanual or printing is supported on android right now android: FORMS -= qt-ui/printoptions.ui From e3d800885f9b5814f88235f49982635f7644da8e Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava Date: Wed, 11 Feb 2015 13:19:35 -0200 Subject: [PATCH 04/58] Create a new state for the MainWindow: EditDiveSite Signed-off-by: Tomaz Canabrava Signed-off-by: Dirk Hohndel --- qt-ui/mainwindow.cpp | 7 +++++++ qt-ui/mainwindow.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 257f394d6..c763f8e58 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -67,12 +67,15 @@ MainWindow::MainWindow() : QMainWindow(), PlannerSettingsWidget *plannerSettings = new PlannerSettingsWidget(); DivePlannerWidget *plannerWidget = new DivePlannerWidget(); PlannerDetails *plannerDetails = new PlannerDetails(); + LocationInformationWidget *locationInformation = new LocationInformationWidget(); registerApplicationState("Default", mainTab, profileWidget, diveListView, globeGps ); registerApplicationState("AddDive", mainTab, profileWidget, diveListView, globeGps ); registerApplicationState("EditDive", mainTab, profileWidget, diveListView, globeGps ); registerApplicationState("PlanDive", plannerWidget, profileWidget, plannerSettings, plannerDetails ); registerApplicationState("EditPlannedDive", plannerWidget, profileWidget, diveListView, globeGps ); + registerApplicationState("EditDiveSite",locationInformation, profileWidget, diveListView, globeGps ); + setApplicationState("Default"); ui.multiFilter->hide(); @@ -205,6 +208,10 @@ PlannerSettingsWidget *MainWindow::divePlannerSettingsWidget() { return qobject_cast(applicationState["PlanDive"].bottomLeft); } +LocationInformationWidget *MainWindow::locationInformationWidget() { + return qobject_cast(applicationState["EditDiveSite"].topLeft); +} + void MainWindow::setLoadedWithFiles(bool f) { filesAsArguments = f; diff --git a/qt-ui/mainwindow.h b/qt-ui/mainwindow.h index 25771d650..6d4c05acc 100644 --- a/qt-ui/mainwindow.h +++ b/qt-ui/mainwindow.h @@ -68,7 +68,7 @@ public: GlobeGPS *globe(); DivePlannerWidget *divePlannerWidget(); PlannerSettingsWidget *divePlannerSettingsWidget(); - + LocationInformationWidget *locationInformationWidget(); void showError(QString message); void setTitle(enum MainWindowTitleFormat format); From 7d66dcd12d42db7c9e3f18be21615204588a66e3 Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava Date: Wed, 11 Feb 2015 13:32:29 -0200 Subject: [PATCH 05/58] Enable the location edit widget on mainwindow Clicking on the 'Manage' button now brings you to the widget to manage it. Nothing has been added on it yet. Signed-off-by: Tomaz Canabrava Signed-off-by: Dirk Hohndel --- qt-ui/maintab.cpp | 2 ++ qt-ui/maintab.h | 2 +- qt-ui/maintab.ui | 8 ++++---- qt-ui/mainwindow.cpp | 5 +++++ qt-ui/mainwindow.h | 1 + 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index e0da97a2d..385b0e2e2 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -49,6 +49,8 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent), ui.extraData->setModel(extraDataModel); closeMessage(); + connect(ui.manageDiveSite, SIGNAL(clicked()), this, SIGNAL(requestDiveSiteEdit())); + QAction *action = new QAction(tr("Apply changes"), this); connect(action, SIGNAL(triggered(bool)), this, SLOT(acceptChanges())); addMessageAction(action); diff --git a/qt-ui/maintab.h b/qt-ui/maintab.h index a279baf7a..acbb8f14f 100644 --- a/qt-ui/maintab.h +++ b/qt-ui/maintab.h @@ -55,7 +55,7 @@ public: signals: void addDiveFinished(); void dateTimeChanged(); - + void requestDiveSiteEdit(); public slots: void addCylinder_clicked(); diff --git a/qt-ui/maintab.ui b/qt-ui/maintab.ui index 48bad01aa..cdaab8386 100644 --- a/qt-ui/maintab.ui +++ b/qt-ui/maintab.ui @@ -131,7 +131,7 @@ - + manage @@ -400,7 +400,7 @@ 0 0 - 454 + 443 752 @@ -456,7 +456,7 @@ 0 0 - 454 + 443 752 @@ -773,7 +773,7 @@ 0 0 - 454 + 443 752 diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index c763f8e58..c3226c0d0 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -111,6 +111,7 @@ MainWindow::MainWindow() : QMainWindow(), connect(DivePlannerPointsModel::instance(), SIGNAL(planCreated()), this, SLOT(planCreated())); connect(DivePlannerPointsModel::instance(), SIGNAL(planCanceled()), this, SLOT(planCanceled())); connect(plannerDetails->printPlan(), SIGNAL(pressed()), divePlannerWidget(), SLOT(printDecoPlan())); + connect(mainTab, SIGNAL(requestDiveSiteEdit()), this, SLOT(enableDiveSiteEdit())); #ifdef NO_PRINTING ui.printPlan->hide(); ui.menuFile->removeAction(ui.actionPrint); @@ -212,6 +213,10 @@ LocationInformationWidget *MainWindow::locationInformationWidget() { return qobject_cast(applicationState["EditDiveSite"].topLeft); } +void MainWindow::enableDiveSiteEdit() { + setApplicationState("EditDiveSite"); +} + void MainWindow::setLoadedWithFiles(bool f) { filesAsArguments = f; diff --git a/qt-ui/mainwindow.h b/qt-ui/mainwindow.h index 6d4c05acc..69ee44217 100644 --- a/qt-ui/mainwindow.h +++ b/qt-ui/mainwindow.h @@ -159,6 +159,7 @@ slots: void on_paste_triggered(); void on_actionFilterTags_triggered(); void on_actionConfigure_Dive_Computer_triggered(); + void enableDiveSiteEdit(); protected: void closeEvent(QCloseEvent *); From 68691c9d6d05ba28c8e0e8c837dcd32bb2eec42c Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava Date: Wed, 11 Feb 2015 13:58:23 -0200 Subject: [PATCH 06/58] Accept / Cancel location edit Make it possible to cancel or accept the location edit and get back to the mainwindow default state. Signed-off-by: Tomaz Canabrava Signed-off-by: Dirk Hohndel --- qt-ui/maintab.cpp | 3 +-- qt-ui/mainwindow.cpp | 5 +++++ qt-ui/mainwindow.h | 1 + qt-ui/simplewidgets.cpp | 30 +++++++++++++++++++++++++++++- qt-ui/simplewidgets.h | 9 +++++++++ 5 files changed, 45 insertions(+), 3 deletions(-) diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index 385b0e2e2..2f39c17db 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -57,12 +57,11 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent), action = new QAction(tr("Discard changes"), this); connect(action, SIGNAL(triggered(bool)), this, SLOT(rejectChanges())); + addMessageAction(action); QShortcut *closeKey = new QShortcut(QKeySequence(Qt::Key_Escape), this); connect(closeKey, SIGNAL(activated()), this, SLOT(escDetected())); - addMessageAction(action); - if (qApp->style()->objectName() == "oxygen") setDocumentMode(true); else diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index c3226c0d0..51b0353be 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -112,6 +112,7 @@ MainWindow::MainWindow() : QMainWindow(), connect(DivePlannerPointsModel::instance(), SIGNAL(planCanceled()), this, SLOT(planCanceled())); connect(plannerDetails->printPlan(), SIGNAL(pressed()), divePlannerWidget(), SLOT(printDecoPlan())); connect(mainTab, SIGNAL(requestDiveSiteEdit()), this, SLOT(enableDiveSiteEdit())); + connect(locationInformation, SIGNAL(informationManagementEnded()), this, SLOT(setDefaultState())); #ifdef NO_PRINTING ui.printPlan->hide(); ui.menuFile->removeAction(ui.actionPrint); @@ -217,6 +218,10 @@ void MainWindow::enableDiveSiteEdit() { setApplicationState("EditDiveSite"); } +void MainWindow::setDefaultState() { + setApplicationState("Default"); +} + void MainWindow::setLoadedWithFiles(bool f) { filesAsArguments = f; diff --git a/qt-ui/mainwindow.h b/qt-ui/mainwindow.h index 69ee44217..300748371 100644 --- a/qt-ui/mainwindow.h +++ b/qt-ui/mainwindow.h @@ -160,6 +160,7 @@ slots: void on_actionFilterTags_triggered(); void on_actionConfigure_Dive_Computer_triggered(); void enableDiveSiteEdit(); + void setDefaultState(); protected: void closeEvent(QCloseEvent *); diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index 98d9bcf9f..63ec4b4fa 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "file.h" #include "mainwindow.h" @@ -646,7 +647,34 @@ void MultiFilter::closeFilter() MultiFilterSortModel::instance()->clearFilter(); hide(); } +#include +#include -LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBox(parent) { +LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBox(parent) +{ ui.setupUi(this); + ui.diveSiteMessage->setText("You are editing the Dive Site"); + ui.diveSiteMessage->setCloseButtonVisible(false); + + QAction *action = new QAction(tr("Apply changes"), this); + connect(action, SIGNAL(triggered(bool)), this, SLOT(acceptChanges())); + ui.diveSiteMessage->addAction(action); + + action = new QAction(tr("Discard changes"), this); + connect(action, SIGNAL(triggered(bool)), this, SLOT(rejectChanges())); + ui.diveSiteMessage->addAction(action); +} + +void LocationInformationWidget::acceptChanges() +{ + emit informationManagementEnded(); +} + +void LocationInformationWidget::rejectChanges() +{ + emit informationManagementEnded(); +} + +void LocationInformationWidget::showEvent(QShowEvent *ev) { + ui.diveSiteMessage->setCloseButtonVisible(false); } diff --git a/qt-ui/simplewidgets.h b/qt-ui/simplewidgets.h index cfa9e0423..16ed0478c 100644 --- a/qt-ui/simplewidgets.h +++ b/qt-ui/simplewidgets.h @@ -221,6 +221,15 @@ class LocationInformationWidget : public QGroupBox { Q_OBJECT public: LocationInformationWidget(QWidget *parent = 0); + +public slots: + void acceptChanges(); + void rejectChanges(); + + void showEvent(QShowEvent *); +signals: + void informationManagementEnded(); + private: Ui::LocationInformation ui; }; From d769c6016fb9fd484cfee90aa58eaac67f0d536a Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava Date: Wed, 11 Feb 2015 14:53:02 -0200 Subject: [PATCH 07/58] Copy the name and the coords when entering the EditDiveSite state Name and coords of the current dive are copied to the edit dive site screen. Signed-off-by: Tomaz Canabrava Signed-off-by: Dirk Hohndel --- qt-ui/mainwindow.cpp | 2 ++ qt-ui/simplewidgets.cpp | 10 ++++++++++ qt-ui/simplewidgets.h | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 51b0353be..a83d0903a 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -215,6 +215,8 @@ LocationInformationWidget *MainWindow::locationInformationWidget() { } void MainWindow::enableDiveSiteEdit() { + locationInformationWidget()->setLocationName(current_dive->location); + locationInformationWidget()->setLocationCoords(printGPSCoords(current_dive->latitude.udeg, current_dive->longitude.udeg)); setApplicationState("EditDiveSite"); } diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index 63ec4b4fa..c7dd47c6d 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -665,6 +665,16 @@ LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBo ui.diveSiteMessage->addAction(action); } +void LocationInformationWidget::setLocationName(const QString& name) +{ + ui.diveSiteName->setText(name); +} + +void LocationInformationWidget::setLocationCoords(const QString& coords) +{ + ui.diveSiteCoordinates->setText(coords); +} + void LocationInformationWidget::acceptChanges() { emit informationManagementEnded(); diff --git a/qt-ui/simplewidgets.h b/qt-ui/simplewidgets.h index 16ed0478c..24af171a7 100644 --- a/qt-ui/simplewidgets.h +++ b/qt-ui/simplewidgets.h @@ -227,6 +227,11 @@ public slots: void rejectChanges(); void showEvent(QShowEvent *); + + /* change that to setLocationSite(QUuid diveSiteUid or something later */ + void setLocationName(const QString& name); + void setLocationCoords(const QString& coords); + signals: void informationManagementEnded(); From 42afb4972ad2928f7f93dd9806234154c62f42cd Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava Date: Wed, 11 Feb 2015 10:14:45 -0800 Subject: [PATCH 08/58] Pass a fake dive site UUID to the callback. This is the start of the preparations to edit the dive site, passing a uuid so we can retrieve it later. Signed-off-by: Tomaz Canabrava Signed-off-by: Dirk Hohndel --- qt-ui/maintab.cpp | 7 ++++++- qt-ui/maintab.h | 5 +++-- qt-ui/mainwindow.cpp | 4 ++-- qt-ui/mainwindow.h | 3 ++- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index 2f39c17db..571d38b9d 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -49,7 +49,7 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent), ui.extraData->setModel(extraDataModel); closeMessage(); - connect(ui.manageDiveSite, SIGNAL(clicked()), this, SIGNAL(requestDiveSiteEdit())); + connect(ui.manageDiveSite, SIGNAL(clicked()), this, SLOT(prepareDiveSiteEdit())); QAction *action = new QAction(tr("Apply changes"), this); connect(action, SIGNAL(triggered(bool)), this, SLOT(acceptChanges())); @@ -213,6 +213,11 @@ MainTab::~MainTab() } } +void MainTab::prepareDiveSiteEdit() { + //TODO: GET THE CORRECT DIVESITE UUID HERE + QUuid id = QUuid::createUuid(); + emit requestDiveSiteEdit(id); +} void MainTab::toggleTriggeredColumn() { QAction *action = qobject_cast(sender()); diff --git a/qt-ui/maintab.h b/qt-ui/maintab.h index acbb8f14f..c90b0fb09 100644 --- a/qt-ui/maintab.h +++ b/qt-ui/maintab.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "ui_maintab.h" #include "completionmodels.h" @@ -55,7 +56,7 @@ public: signals: void addDiveFinished(); void dateTimeChanged(); - void requestDiveSiteEdit(); + void requestDiveSiteEdit(QUuid diveSiteId); public slots: void addCylinder_clicked(); @@ -93,7 +94,7 @@ slots: void photoDoubleClicked(const QString filePath); void removeSelectedPhotos(); void updateGpsCoordinates(); - + void prepareDiveSiteEdit(); private: Ui::MainTab ui; WeightModel *weightModel; diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index a83d0903a..eca4c08f8 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -111,7 +111,7 @@ MainWindow::MainWindow() : QMainWindow(), connect(DivePlannerPointsModel::instance(), SIGNAL(planCreated()), this, SLOT(planCreated())); connect(DivePlannerPointsModel::instance(), SIGNAL(planCanceled()), this, SLOT(planCanceled())); connect(plannerDetails->printPlan(), SIGNAL(pressed()), divePlannerWidget(), SLOT(printDecoPlan())); - connect(mainTab, SIGNAL(requestDiveSiteEdit()), this, SLOT(enableDiveSiteEdit())); + connect(mainTab, SIGNAL(requestDiveSiteEdit(QUuid)), this, SLOT(enableDiveSiteEdit(QUuid))); connect(locationInformation, SIGNAL(informationManagementEnded()), this, SLOT(setDefaultState())); #ifdef NO_PRINTING ui.printPlan->hide(); @@ -214,7 +214,7 @@ LocationInformationWidget *MainWindow::locationInformationWidget() { return qobject_cast(applicationState["EditDiveSite"].topLeft); } -void MainWindow::enableDiveSiteEdit() { +void MainWindow::enableDiveSiteEdit(QUuid id) { locationInformationWidget()->setLocationName(current_dive->location); locationInformationWidget()->setLocationCoords(printGPSCoords(current_dive->latitude.udeg, current_dive->longitude.udeg)); setApplicationState("EditDiveSite"); diff --git a/qt-ui/mainwindow.h b/qt-ui/mainwindow.h index 300748371..ef3e8fa18 100644 --- a/qt-ui/mainwindow.h +++ b/qt-ui/mainwindow.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "ui_mainwindow.h" @@ -159,7 +160,7 @@ slots: void on_paste_triggered(); void on_actionFilterTags_triggered(); void on_actionConfigure_Dive_Computer_triggered(); - void enableDiveSiteEdit(); + void enableDiveSiteEdit(QUuid id); void setDefaultState(); protected: From 9edb7811ef3366cf5ee378a07adb7121fab8630a Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Wed, 11 Feb 2015 10:33:36 -0800 Subject: [PATCH 09/58] Remove redundant function We had two functions doing exactly the same thing. Let's drop the one with the highly confusing name. Signed-off-by: Dirk Hohndel --- dive.h | 7 ------- qt-ui/subsurfacewebservices.cpp | 4 ++-- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/dive.h b/dive.h index b350527a7..a5d0e8712 100644 --- a/dive.h +++ b/dive.h @@ -494,13 +494,6 @@ extern unsigned int dc_number; #define current_dive (get_dive(selected_dive)) #define current_dc (get_dive_dc(current_dive, dc_number)) -static inline struct dive *get_gps_location(int nr, struct dive_table *table) -{ - if (nr >= table->nr || nr < 0) - return NULL; - return table->dives[nr]; -} - static inline struct dive *get_dive(int nr) { if (nr >= dive_table.nr || nr < 0) diff --git a/qt-ui/subsurfacewebservices.cpp b/qt-ui/subsurfacewebservices.cpp index 72e7e3d27..a247888a2 100644 --- a/qt-ui/subsurfacewebservices.cpp +++ b/qt-ui/subsurfacewebservices.cpp @@ -42,7 +42,7 @@ static bool merge_locations_into_dives(void) for_each_dive (i, dive) { if (!dive_has_gps_location(dive)) { - for (j = tracer; (gpsfix = get_gps_location(j, &gps_location_table)) !=NULL; j++) { + for (j = tracer; (gpsfix = get_dive_from_table(j, &gps_location_table)) !=NULL; j++) { if (dive_within_time_range (dive, gpsfix->when, SAME_GROUP)) { /* * If position is fixed during dive. This is the good one. @@ -57,7 +57,7 @@ static bool merge_locations_into_dives(void) /* * If it is not, check if there are more position fixes in SAME_GROUP range */ - if ((nextgpsfix = get_gps_location(j+1,&gps_location_table)) && + if ((nextgpsfix = get_dive_from_table(j+1,&gps_location_table)) && dive_within_time_range (dive, nextgpsfix->when, SAME_GROUP)) { /* * If distance from gpsfix to end of dive is shorter than distance between From dcfda29da6d5539c602935f3518749942dad2153 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Wed, 11 Feb 2015 11:22:00 -0800 Subject: [PATCH 10/58] Add dive site data structure This leaves location and gps coordinates in the struct dive to allow a step by step migration. Signed-off-by: Dirk Hohndel --- dive.h | 1 + divesite.c | 2 ++ divesite.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ subsurface.pro | 2 ++ 4 files changed, 52 insertions(+) create mode 100644 divesite.c create mode 100644 divesite.h diff --git a/dive.h b/dive.h index a5d0e8712..2c9ef3336 100644 --- a/dive.h +++ b/dive.h @@ -319,6 +319,7 @@ struct dive { bool downloaded; timestamp_t when; char *location; + uint32_t dive_site_uuid; char *notes; char *divemaster, *buddy; int rating; diff --git a/divesite.c b/divesite.c new file mode 100644 index 000000000..1d3bb1c0d --- /dev/null +++ b/divesite.c @@ -0,0 +1,2 @@ +/* divesite.c */ +#include "divesite.h" diff --git a/divesite.h b/divesite.h new file mode 100644 index 000000000..e11a10738 --- /dev/null +++ b/divesite.h @@ -0,0 +1,47 @@ +#ifndef DIVESITE_H +#define DIVESITE_H + +#include "units.h" +#include + +struct dive_site +{ + uint32_t uuid; + char *name; + degrees_t latitude, longitude; + char *description; + char *notes; +}; + +struct dive_site_table { + int nr, allocated; + struct dive_site **dive_sites; +}; + +extern struct dive_site_table dive_site_table; + +static inline struct dive_site *get_dive_site(int nr) +{ + if (nr >= dive_site_table.nr || nr < 0) + return NULL; + return dive_site_table.dive_sites[nr]; +} + +static inline struct dive_site *get_dive_site_by_uuid(uint32_t uuid) +{ + for (int i = 0; i < dive_site_table.nr; i++) + if (get_dive_site(i)->uuid == uuid) + return get_dive_site(i); + return NULL; +} + +/* there could be multiple sites of the same name - return the first one */ +static inline struct dive_site *get_dive_site_by_name(const char *name) +{ + for (int i = 0; i < dive_site_table.nr; i++) + if (get_dive_site(i)->name == name) + return get_dive_site(i); + return NULL; +} + +#endif // DIVESITE_H diff --git a/subsurface.pro b/subsurface.pro index 2469b8aa9..4853796c0 100644 --- a/subsurface.pro +++ b/subsurface.pro @@ -29,6 +29,7 @@ HEADERS = \ display.h \ dive.h \ divelist.h \ + divesite.h \ file.h \ gettextfromc.h \ gettext.h \ @@ -119,6 +120,7 @@ SOURCES = \ device.c \ dive.c \ divelist.c \ + divesite.c \ equipment.c \ file.c \ gettextfromc.cpp \ From e720c82aa1abac491ee48f39a69fe88620115bfc Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 11:19:05 -0800 Subject: [PATCH 11/58] Some dive site helper functions Signed-off-by: Dirk Hohndel --- divesite.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ divesite.h | 10 +++++++--- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/divesite.c b/divesite.c index 1d3bb1c0d..21efaf2e6 100644 --- a/divesite.c +++ b/divesite.c @@ -1,2 +1,59 @@ /* divesite.c */ #include "divesite.h" +#include "dive.h" + +struct dive_site_table dive_site_table; + +/* try to create a uniqe ID - fingers crossed */ +static uint32_t dive_site_getUniqId() +{ + uint32_t id = 0; + + while (id == 0 || get_dive_site_by_uuid(id)) + id = random() + random(); + + return id; +} + +struct dive_site *alloc_dive_site() +{ + int nr = dive_site_table.nr, allocated = dive_site_table.allocated; + struct dive_site **sites = dive_site_table.dive_sites; + + if (nr >= allocated) { + allocated = (nr + 32) * 3 / 2; + sites = realloc(sites, allocated * sizeof(struct dive_site *)); + if (!sites) + exit(1); + dive_site_table.dive_sites = sites; + dive_site_table.allocated = allocated; + } + struct dive_site *ds = calloc(1, sizeof(*ds)); + if (!ds) + exit(1); + sites[nr] = ds; + dive_site_table.nr = nr + 1; + return ds; +} + +/* allocate a new site and add it to the table */ +uint32_t create_dive_site(const char *name, degrees_t latitude, degrees_t longitude) +{ + struct dive_site *ds = alloc_dive_site(); + ds->uuid = dive_site_getUniqId(); + ds->name = copy_string(name); + ds->latitude = latitude; + ds->longitude = longitude; + + return ds->uuid; +} + +/* this either returns the uuid for a site with that name or creates an entry */ +uint32_t dive_site_uuid_by_name(const char *name) +{ + uint32_t id = get_dive_site_uuid_by_name(name); + if (id == 0) + id = create_dive_site(name, (degrees_t){0}, (degrees_t){0}); + + return id; +} diff --git a/divesite.h b/divesite.h index e11a10738..da0a78983 100644 --- a/divesite.h +++ b/divesite.h @@ -36,12 +36,16 @@ static inline struct dive_site *get_dive_site_by_uuid(uint32_t uuid) } /* there could be multiple sites of the same name - return the first one */ -static inline struct dive_site *get_dive_site_by_name(const char *name) +static inline uint32_t get_dive_site_uuid_by_name(const char *name) { for (int i = 0; i < dive_site_table.nr; i++) if (get_dive_site(i)->name == name) - return get_dive_site(i); - return NULL; + return get_dive_site(i)->uuid; + return 0; } +struct dive_site *alloc_dive_site(); +uint32_t create_dive_site(const char *name, degrees_t latitude, degrees_t longitude); +uint32_t dive_site_uuid_by_name(const char *name); + #endif // DIVESITE_H From 4b15b9dfe910fd0df63bdc8024a919a566c380be Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Wed, 11 Feb 2015 21:46:02 -0800 Subject: [PATCH 12/58] Save and parse dive site structures to XML Read and write divesite sections in the XML file. Read divelogs of version 2 and create dive site structures on the fly. Read version 3 files that have divesiteid instead of location / gps. Saves version 3 files where dives no longer have location and gps but instead refer to a divesiteid The commit contains quite a few fprintf(stderr,...) in order to allow better monitoring of the parsing / transforming of locations and gps to dive sites. This will need to be removed later. Signed-off-by: Dirk Hohndel --- dive.h | 16 +++-- parse-xml.c | 166 ++++++++++++++++++++++++++++++++++++++++++---------- save-xml.c | 52 ++++++---------- 3 files changed, 166 insertions(+), 68 deletions(-) diff --git a/dive.h b/dive.h index 2c9ef3336..c38016bb5 100644 --- a/dive.h +++ b/dive.h @@ -8,6 +8,7 @@ #include #include #include +#include "divesite.h" /* Windows has no MIN/MAX macros - so let's just roll our own */ #define MIN(x, y) ({ \ @@ -387,11 +388,6 @@ extern void dive_set_geodata_from_picture(struct dive *d, struct picture *pic); extern int explicit_first_cylinder(struct dive *dive, struct divecomputer *dc); -static inline int dive_has_gps_location(struct dive *dive) -{ - return dive->latitude.udeg || dive->longitude.udeg; -} - static inline void copy_gps_location(struct dive *from, struct dive *to) { if (from && to) { @@ -607,6 +603,16 @@ static inline int get_idx_by_uniq_id(int id) return i; } +static inline bool dive_site_has_gps_location(struct dive_site *ds) +{ + return ds && (ds->latitude.udeg || ds->longitude.udeg); +} + +static inline int dive_has_gps_location(struct dive *dive) +{ + return dive_site_has_gps_location(get_dive_site_by_uuid(dive->dive_site_uuid)); +} + #ifdef __cplusplus extern "C" { #endif diff --git a/parse-xml.c b/parse-xml.c index 5baa40394..4377a32cb 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -128,6 +128,7 @@ const struct units IMPERIAL_units = IMPERIAL_UNITS; #define MAX_EVENT_NAME 128 static struct divecomputer *cur_dc; static struct dive *cur_dive; +static struct dive_site *cur_dive_site; static dive_trip_t *cur_trip = NULL; static struct sample *cur_sample; static struct picture *cur_picture; @@ -968,22 +969,21 @@ void try_to_fill_userid(const char *name, char *buf) static const char *country, *city; -static void divinglog_place(char *place, char **location) +static void divinglog_place(char *place, uint32_t *uuid) { char buffer[1024], *p; int len; - len = snprintf(buffer, sizeof(buffer), - "%s%s%s%s%s", - place, - city ? ", " : "", - city ? city : "", - country ? ", " : "", - country ? country : ""); - - p = malloc(len + 1); - memcpy(p, buffer, len + 1); - *location = p; + snprintf(buffer, sizeof(buffer), + "%s%s%s%s%s", + place, + city ? ", " : "", + city ? city : "", + country ? ", " : "", + country ? country : ""); + *uuid = get_dive_site_uuid_by_name(buffer); + if (*uuid == 0) + *uuid = create_dive_site(buffer, (degrees_t){0}, (degrees_t){0}); city = NULL; country = NULL; @@ -1005,7 +1005,7 @@ static int divinglog_dive_match(struct dive *dive, const char *name, char *buf) MATCH("names.buddy", utf8_string, &dive->buddy) || MATCH("name.country", utf8_string, &country) || MATCH("name.city", utf8_string, &city) || - MATCH("name.place", divinglog_place, &dive->location) || + MATCH("name.place", divinglog_place, &dive->dive_site_uuid) || 0; } @@ -1138,12 +1138,64 @@ static void gps_long(char *buffer, struct dive *dive) dive->longitude = parse_degrees(buffer, &end); } -static void gps_location(char *buffer, struct dive *dive) +static void gps_location(char *buffer, struct dive_site *ds) { char *end; - dive->latitude = parse_degrees(buffer, &end); - dive->longitude = parse_degrees(end, &end); + ds->latitude = parse_degrees(buffer, &end); + ds->longitude = parse_degrees(end, &end); +} + +static void gps_in_dive(char *buffer, struct dive *dive) +{ + char *end; + fprintf(stderr, "called gps_in_dive with buffer |%s|\n", buffer); + degrees_t latitude = parse_degrees(buffer, &end); + degrees_t longitude = parse_degrees(end, &end); + fprintf(stderr, "got lat %f lon %f\n", latitude.udeg / 1000000.0, longitude.udeg / 1000000.0); + uint32_t uuid = dive->dive_site_uuid; + if (uuid == 0) { + fprintf(stderr, "found no uuid in dive, creating a divesite without name and above GPS\n"); + dive->dive_site_uuid = create_dive_site("", latitude, longitude); + } else { + fprintf(stderr, "found uuid in dive, checking to see if we should add GPS\n"); + struct dive_site *ds = get_dive_site_by_uuid(uuid); + if (dive_site_has_gps_location(ds) && + (latitude.udeg != 0 || longitude.udeg != 0) && + (ds->latitude.udeg != latitude.udeg || ds->longitude.udeg != longitude.udeg)) { + // Houston, we have a problem + fprintf(stderr, "dive site uuid in dive, but gps location (%10.6f/%10.6f) different from dive location (%10.6f/%10.6f)\n", + ds->latitude.udeg / 1000000.0, ds->longitude.udeg / 1000000.0, + latitude.udeg / 1000000.0, longitude.udeg / 1000000.0); + } else { + fprintf(stderr, "let's add the gps coordinates to divesite with uuid %8x and name %s\n", ds->uuid, ds->name ?: "(none)"); + ds->latitude = latitude; + ds->longitude = longitude; + } + } +} + +static void add_dive_site(char *buffer, struct dive *dive) +{ + fprintf(stderr, "add_dive_site with name %s\n", buffer); + int size; + size = trimspace(buffer); + if(size) { + if (dive->dive_site_uuid) { + // we have a uuid, let's hope there's no name + struct dive_site *ds = get_dive_site_by_uuid(dive->dive_site_uuid); + if (!ds) { + fprintf(stderr, "dive contains a non-existing dive site uuid %x\n", dive->dive_site_uuid); + exit(1); + } + if (!same_string(ds->name, buffer)) { + fprintf(stderr, "dive links to dive site of different name %s / %s\n", ds->name, buffer); + exit(1); + } + } else { + dive->dive_site_uuid = create_dive_site(buffer, (degrees_t){0}, (degrees_t){0}); + } + } } static void gps_picture_location(char *buffer, struct picture *pic) @@ -1173,7 +1225,8 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) default: break; } - + if (MATCH("divesiteid", hex_value, &dive->dive_site_uuid)) + return; if (MATCH("number", get_index, &dive->number)) return; if (MATCH("tags", divetags, &dive->tag_list)) @@ -1203,9 +1256,9 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) return; if (MATCH("cylinderendpressure", pressure, &dive->cylinder[0].end)) return; - if (MATCH("gps", gps_location, dive)) + if (MATCH("gps", gps_in_dive, dive)) return; - if (MATCH("Place", gps_location, dive)) + if (MATCH("Place", gps_in_dive, dive)) return; if (MATCH("latitude", gps_lat, dive)) return; @@ -1219,9 +1272,9 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) return; if (MATCH("lon", gps_long, dive)) return; - if (MATCH("location", utf8_string, &dive->location)) + if (MATCH("location", add_dive_site, dive)) return; - if (MATCH("name.dive", utf8_string, &dive->location)) + if (MATCH("name.dive", add_dive_site, dive)) return; if (MATCH("suit", utf8_string, &dive->suit)) return; @@ -1290,6 +1343,27 @@ static void try_to_fill_trip(dive_trip_t **dive_trip_p, const char *name, char * nonmatch("trip", name, buf); } +/* We're processing a divesite entry - try to fill the components */ +static void try_to_fill_dive_site(struct dive_site **ds_p, const char *name, char *buf) +{ + start_match("divesite", name, buf); + + struct dive_site *ds = *ds_p; + + if (MATCH("uuid", hex_value, &ds->uuid)) + return; + if (MATCH("name", utf8_string, &ds->name)) + return; + if (MATCH("description", utf8_string, &ds->description)) + return; + if (MATCH("notes", utf8_string, &ds->notes)) + return; + if (MATCH("gps", gps_location, ds)) + return; + + nonmatch("divesite", name, buf); +} + /* * While in some formats file boundaries are dive boundaries, in many * others (as for example in our native format) there are @@ -1305,7 +1379,7 @@ static void try_to_fill_trip(dive_trip_t **dive_trip_p, const char *name, char * static bool is_dive(void) { return (cur_dive && - (cur_dive->location || cur_dive->when || cur_dive->dc.samples)); + (cur_dive->dive_site_uuid || cur_dive->when || cur_dive->dc.samples)); } static void reset_dc_info(struct divecomputer *dc) @@ -1349,6 +1423,32 @@ static void dc_settings_end(void) reset_dc_settings(); } +static void dive_site_start(void) +{ + if (cur_dive_site) + return; + cur_dive_site = calloc(1, sizeof(struct dive_site)); + fprintf(stderr, "allocated cur_dive_site\n"); +} + +static void dive_site_end(void) +{ + fprintf(stderr, "done with dive_site\n"); + if (!cur_dive_site) + return; + if (cur_dive_site->uuid) { + uint32_t tmp = create_dive_site(cur_dive_site->name, cur_dive_site->latitude, cur_dive_site->longitude); + struct dive_site *ds = get_dive_site_by_uuid(tmp); + ds->uuid = cur_dive_site->uuid; + ds->notes = cur_dive_site->notes; + ds->description = cur_dive_site->description; + } + free(cur_dive_site); + cur_dive_site = NULL; +} + +// now we need to add the code to parse the parts of the divesite enry + static void dive_start(void) { if (cur_dive) @@ -1538,6 +1638,10 @@ static void entry(const char *name, char *buf) try_to_match_autogroup(name, buf); return; } + if (cur_dive_site) { + try_to_fill_dive_site(&cur_dive_site, name, buf); + return; + } if (!cur_event.deleted) { try_to_fill_event(name, buf); return; @@ -1666,6 +1770,7 @@ static struct nesting { } nesting[] = { { "divecomputerid", dc_settings_start, dc_settings_end }, { "settings", settings_start, settings_end }, + { "site", dive_site_start, dive_site_end }, { "dive", dive_start, dive_end }, { "Dive", dive_start, dive_end }, { "trip", trip_start, trip_end }, @@ -2291,7 +2396,7 @@ extern int shearwater_dive(void *param, int columns, char **data, char **column) cur_dive->when = (time_t)(atol(data[1])); if (data[2]) - utf8_string(data[2], &cur_dive->location); + add_dive_site(data[2], cur_dive); if (data[3]) utf8_string(data[3], &cur_dive->buddy); if (data[4]) @@ -2388,19 +2493,20 @@ extern int cobalt_visibility(void *handle, int columns, char **data, char **colu extern int cobalt_location(void *handle, int columns, char **data, char **column) { + static char *location = NULL; if (data[0]) { - if (cur_dive->location) { - char *tmp = malloc(strlen(cur_dive->location) + strlen(data[0]) + 4); + if (location) { + char *tmp = malloc(strlen(location) + strlen(data[0]) + 4); if (!tmp) return -1; - sprintf(tmp, "%s / %s", cur_dive->location, data[0]); - free(cur_dive->location); - cur_dive->location = tmp; + sprintf(tmp, "%s / %s", location, data[0]); + free(location); + location = NULL; + cur_dive->dive_site_uuid = create_dive_site(tmp, (degrees_t){0}, (degrees_t){0}); } else { - utf8_string(data[0], &cur_dive->location); + location = strdup(data[0]); } } - return 0; } diff --git a/save-xml.c b/save-xml.c index 053b8fc96..dad57dc9b 100644 --- a/save-xml.c +++ b/save-xml.c @@ -110,38 +110,8 @@ static void save_salinity(struct membuffer *b, struct divecomputer *dc) put_string(b, " />\n"); } -static void show_location(struct membuffer *b, struct dive *dive) -{ - degrees_t latitude = dive->latitude; - degrees_t longitude = dive->longitude; - - /* Should we write a location tag at all? */ - if (!(latitude.udeg || longitude.udeg) && !dive->location) - return; - - put_string(b, " location && dive->location[0] != '\0') - show_utf8(b, dive->location, ">", "\n", 0); - else - put_string(b, "/>\n"); -} - static void save_overview(struct membuffer *b, struct dive *dive) { - show_location(b, dive); show_utf8(b, dive->divemaster, " ", "\n", 0); show_utf8(b, dive->buddy, " ", "\n", 0); show_utf8(b, dive->notes, " ", "\n", 0); @@ -424,7 +394,8 @@ void save_one_dive(struct membuffer *b, struct dive *dive) if (dive->visibility) put_format(b, " visibility='%d'", dive->visibility); save_tags(b, dive->tag_list); - + if (dive->dive_site_uuid) + put_format(b, " divesiteid='%8x'", dive->dive_site_uuid); show_date(b, dive->when); put_format(b, " duration='%u:%02u min'>\n", FRACTION(dive->dc.duration.seconds, 60)); @@ -507,7 +478,7 @@ static void save_one_device(void *_f, const char *model, uint32_t deviceid, put_format(b, "/>\n"); } -#define VERSION 2 +#define VERSION 3 int save_dives(const char *filename) { @@ -529,8 +500,23 @@ void save_dives_buffer(struct membuffer *b, const bool select_only) call_for_each_dc(b, save_one_device); if (autogroup) put_format(b, " \n"); - put_format(b, "\n\n"); + put_format(b, "\n"); + /* save the dive sites */ + put_format(b, "\n"); + for (i = 0; i < dive_site_table.nr; i++) { + struct dive_site *ds = get_dive_site(i); + put_format(b, "uuid); + show_utf8(b, ds->name, " name='", "'", 1); + if (ds->latitude.udeg || ds->longitude.udeg) { + put_degrees(b, ds->latitude, " gps='", " "); + put_degrees(b, ds->longitude, "", "'"); + } + show_utf8(b, ds->description, " description='", "'", 1); + show_utf8(b, ds->notes, " notes='", "'", 1); + put_format(b, "/>\n"); + } + put_format(b, "\n\n"); for (trip = dive_trip_list; trip != NULL; trip = trip->next) trip->index = 0; From 05948530e94096c47a517f709cee0e74794530ab Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 00:14:50 -0800 Subject: [PATCH 13/58] Save and load dive sites in git format Update the version to 3. Continue to read version 2 files and create dive sites on the fly. Signed-off-by: Dirk Hohndel --- load-git.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++--- save-git.c | 28 +++++++++++++++++++++++--- 2 files changed, 80 insertions(+), 6 deletions(-) diff --git a/load-git.c b/load-git.c index 1cdb44cff..7bd020bd5 100644 --- a/load-git.c +++ b/load-git.c @@ -160,6 +160,9 @@ static void parse_dive_suit(char *line, struct membuffer *str, void *_dive) static void parse_dive_notes(char *line, struct membuffer *str, void *_dive) { struct dive *dive = _dive; dive->notes = get_utf8(str); } +static void parse_dive_divesiteid(char *line, struct membuffer *str, void *_dive) +{ struct dive *dive = _dive; dive->dive_site_uuid = get_hex(line); } + /* * We can have multiple tags in the membuffer. They are separated by * NUL bytes. @@ -205,6 +208,24 @@ static void parse_dive_visibility(char *line, struct membuffer *str, void *_dive static void parse_dive_notrip(char *line, struct membuffer *str, void *_dive) { struct dive *dive = _dive; dive->tripflag = NO_TRIP; } +static void parse_site_description(char *line, struct membuffer *str, void *_ds) +{ struct dive_site *ds = _ds; ds->description = strdup(mb_cstring(str)); } + +static void parse_site_name(char *line, struct membuffer *str, void *_ds) +{ struct dive_site *ds = _ds; ds->name = strdup(mb_cstring(str)); } + +static void parse_site_notes(char *line, struct membuffer *str, void *_ds) +{ struct dive_site *ds = _ds; ds->notes = strdup(mb_cstring(str)); } + +extern degrees_t parse_degrees(char *buf, char **end); +static void parse_site_gps(char *line, struct membuffer *str, void *_ds) +{ + struct dive_site *ds = _ds; + + ds->latitude = parse_degrees(line, &line); + ds->longitude = parse_degrees(line, &line); +} + /* Parse key=val parts of samples and cylinders etc */ static char *parse_keyvalue_entry(void (*fn)(void *, const char *, const char *), void *fndata, char *line) { @@ -672,7 +693,7 @@ static void parse_settings_userid(char *line, struct membuffer *str, void *_unus * *can* do some day. And if we do change the version, this warning will show if * you read with a version of subsurface that doesn't know about it. */ -#define VERSION 2 +#define VERSION 3 static void parse_settings_version(char *line, struct membuffer *str, void *_unused) { int version = atoi(line); @@ -783,7 +804,7 @@ static void divecomputer_parser(char *line, struct membuffer *str, void *_dc) struct keyword_action dive_action[] = { #undef D #define D(x) { #x, parse_dive_ ## x } - D(airtemp), D(buddy), D(cylinder), D(divemaster), D(duration), + D(airtemp), D(buddy), D(cylinder), D(divemaster), D(divesiteid), D(duration), D(gps), D(location), D(notes), D(notrip), D(rating), D(suit), D(tags), D(visibility), D(watertemp), D(weightsystem) }; @@ -793,6 +814,18 @@ static void dive_parser(char *line, struct membuffer *str, void *_dive) match_action(line, str, _dive, dive_action, ARRAY_SIZE(dive_action)); } +/* These need to be sorted! */ +struct keyword_action site_action[] = { +#undef D +#define D(x) { #x, parse_site_ ## x } + D(description), D(gps), D(name), D(notes) +}; + +static void site_parser(char *line, struct membuffer *str, void *_ds) +{ + match_action(line, str, _ds, site_action, ARRAY_SIZE(site_action)); +} + /* These need to be sorted! */ struct keyword_action trip_action[] = { #undef D @@ -1190,6 +1223,9 @@ static int walk_tree_directory(const char *root, const git_tree_entry *entry) if (!strcmp(name, "Pictures")) return picture_directory(root, name); + if (!strcmp(name, "01-Divesites")) + return GIT_WALK_OK; + while (isdigit(c = name[digits])) digits++; @@ -1284,6 +1320,20 @@ static int parse_dive_entry(git_repository *repo, const git_tree_entry *entry, c return 0; } +static int parse_site_entry(git_repository *repo, const git_tree_entry *entry, const char *suffix) +{ + if (*suffix == '\0') + return report_error("Dive site without uuid"); + struct dive_site *ds = alloc_dive_site(); + ds->uuid = strtol(suffix, NULL, 16); + git_blob *blob = git_tree_entry_blob(repo, entry); + if (!blob) + return report_error("Unable to read dive site file"); + for_each_line(blob, site_parser, ds); + git_blob_free(blob); + return 0; +} + static int parse_trip_entry(git_repository *repo, const git_tree_entry *entry) { git_blob *blob = git_tree_entry_blob(repo, entry); @@ -1343,7 +1393,6 @@ static int walk_tree_file(const char *root, const git_tree_entry *entry, git_rep struct dive *dive = active_dive; dive_trip_t *trip = active_trip; const char *name = git_tree_entry_name(entry); - switch (*name) { /* Picture file? They are saved as time offsets in the dive */ case '-': case '+': @@ -1356,6 +1405,9 @@ static int walk_tree_file(const char *root, const git_tree_entry *entry, git_rep if (dive && !strncmp(name, "Dive", 4)) return parse_dive_entry(repo, entry, name+4); break; + case 'S': + if (!strncmp(name, "Site", 4)) + return parse_site_entry(repo, entry, name + 5); case '0': if (trip && !strcmp(name, "00-Trip")) return parse_trip_entry(repo, entry); diff --git a/save-git.c b/save-git.c index 6c2587bf8..764805d03 100644 --- a/save-git.c +++ b/save-git.c @@ -104,8 +104,6 @@ static void show_utf8(struct membuffer *b, const char *prefix, const char *value static void save_overview(struct membuffer *b, struct dive *dive) { - show_gps(b, dive->latitude, dive->longitude); - show_utf8(b, "location ", dive->location, "\n"); show_utf8(b, "divemaster ", dive->divemaster, "\n"); show_utf8(b, "buddy ", dive->buddy, "\n"); show_utf8(b, "suit ", dive->suit, "\n"); @@ -390,6 +388,7 @@ static void create_dive_buffer(struct dive *dive, struct membuffer *b) SAVE("visibility", visibility); cond_put_format(dive->tripflag == NO_TRIP, b, "notrip\n"); save_tags(b, dive->tag_list); + cond_put_format(dive->dive_site_uuid, b, "divesiteid %8x\n", dive->dive_site_uuid); save_overview(b, dive); save_cylinder_info(b, dive); @@ -804,7 +803,7 @@ static void save_one_device(void *_b, const char *model, uint32_t deviceid, put_string(b, "\n"); } -#define VERSION 2 +#define VERSION 3 static void save_settings(git_repository *repo, struct dir *tree) { @@ -818,6 +817,27 @@ static void save_settings(git_repository *repo, struct dir *tree) blob_insert(repo, tree, &b, "00-Subsurface"); } +static void save_divesites(git_repository *repo, struct dir *tree) +{ + struct dir *subdir; + struct membuffer dirname = { 0 }; + put_format(&dirname, "01-Divesites"); + subdir = new_directory(repo, tree, &dirname); + + for (int i = 0; i < dive_site_table.nr; i++) { + struct membuffer b = { 0 }; + struct dive_site *ds = get_dive_site(i); + int size = sizeof("Site-012345678"); + char name[size]; + snprintf(name, size, "Site-%8x", ds->uuid); + show_utf8(&b, "name ", ds->name, "\n"); + show_utf8(&b, "description ", ds->description, "\n"); + show_utf8(&b, "notes ", ds->notes, "\n"); + show_gps(&b, ds->latitude, ds->longitude); + blob_insert(repo, subdir, &b, name); + } +} + static int create_git_tree(git_repository *repo, struct dir *root, bool select_only) { int i; @@ -826,6 +846,8 @@ static int create_git_tree(git_repository *repo, struct dir *root, bool select_o save_settings(repo, root); + save_divesites(repo, root); + for (trip = dive_trip_list; trip != NULL; trip = trip->next) trip->index = 0; From 6a812c6b6dfffca3c99f4076005de6ee9f11d614 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 12:46:21 -0800 Subject: [PATCH 14/58] Show location based on dive site on MainTab Signed-off-by: Dirk Hohndel --- qt-ui/maintab.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index 571d38b9d..48d2a0034 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -430,9 +430,7 @@ void MainTab::updateDiveInfo(bool clear) else ui.notes->setPlainText(tmp); } - UPDATE_TEXT(displayed_dive, notes); - UPDATE_TEXT(displayed_dive, location); UPDATE_TEXT(displayed_dive, suit); UPDATE_TEXT(displayed_dive, divemaster); UPDATE_TEXT(displayed_dive, buddy); @@ -441,6 +439,9 @@ void MainTab::updateDiveInfo(bool clear) ui.DiveType->setCurrentIndex(displayed_dive.dc.divemode); if (!clear) { + struct dive_site *ds = get_dive_site_by_uuid(displayed_dive.dive_site_uuid); + if (ds) + ui.location->setText(ds->name); updateGpsCoordinates(); // Subsurface always uses "local time" as in "whatever was the local time at the location" // so all time stamps have no time zone information and are in UTC @@ -655,6 +656,7 @@ void MainTab::updateDiveInfo(bool clear) ui.rating->setCurrentStars(0); ui.coordinates->clear(); ui.visibility->setCurrentStars(0); + ui.location->clear(); } editMode = NONE; ui.cylinders->view()->hideColumn(CylindersModel::DEPTH); From 9ef81d3ed38bd2e7498242095e1655d568c61f7e Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 12:57:58 -0800 Subject: [PATCH 15/58] Show GPS coordinates based on dive site on MainTab Signed-off-by: Dirk Hohndel --- qt-ui/maintab.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index 48d2a0034..363ab3c43 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -1286,8 +1286,14 @@ void MainTab::updateGpsCoordinates() if (editMode == NONE) enableEdition(); - ui.coordinates->setText(printGPSCoords(displayed_dive.latitude.udeg, displayed_dive.longitude.udeg)); - ui.coordinates->setModified(displayed_dive.latitude.udeg || displayed_dive.longitude.udeg); + struct dive_site *ds = get_dive_site_by_uuid(displayed_dive.dive_site_uuid); + if (ds && dive_site_has_gps_location(ds)) { + ui.coordinates->setText(printGPSCoords(ds->latitude.udeg, ds->longitude.udeg)); + ui.coordinates->setModified(true); + } else if (!ui.coordinates->text().isEmpty()) { + ui.coordinates->setModified(true); + ui.coordinates->clear(); + } } void MainTab::escDetected() From d488c37cc11a6051f94715465264a38bf7cf4dc2 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 01:19:07 -0800 Subject: [PATCH 16/58] Show dive coordinates on map based on dive site Signed-off-by: Dirk Hohndel --- dive.h | 7 +++++++ qt-ui/globe.cpp | 42 ++++++++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/dive.h b/dive.h index c38016bb5..42cec6224 100644 --- a/dive.h +++ b/dive.h @@ -505,6 +505,13 @@ static inline struct dive *get_dive_from_table(int nr, struct dive_table *dt) return dt->dives[nr]; } +static inline struct dive_site *get_dive_site_for_dive(struct dive *dive) +{ + if (dive) + return get_dive_site_by_uuid(dive->dive_site_uuid); + return NULL; +} + static inline unsigned int number_of_computers(struct dive *dive) { unsigned int total_number = 0; diff --git a/qt-ui/globe.cpp b/qt-ui/globe.cpp index cda408ddc..58e7dc620 100644 --- a/qt-ui/globe.cpp +++ b/qt-ui/globe.cpp @@ -164,10 +164,11 @@ void GlobeGPS::mouseClicked(qreal lon, qreal lat, GeoDataCoordinates::Unit unit) QList selectedDiveIds; for_each_dive (idx, dive) { long lat_diff, lon_diff; - if (!dive_has_gps_location(dive)) + struct dive_site *ds = get_dive_site_for_dive(dive); + if (!dive_site_has_gps_location(ds)) continue; - lat_diff = labs(dive->latitude.udeg - lat_udeg); - lon_diff = labs(dive->longitude.udeg - lon_udeg); + lat_diff = labs(ds->latitude.udeg - lat_udeg); + lon_diff = labs(ds->longitude.udeg - lon_udeg); if (lat_diff > 180000000) lat_diff = 360000000 - lat_diff; if (lon_diff > 180000000) @@ -186,6 +187,7 @@ void GlobeGPS::mouseClicked(qreal lon, qreal lat, GeoDataCoordinates::Unit unit) void GlobeGPS::repopulateLabels() { + struct dive_site *ds; if (loadedDives) { model()->treeModel()->removeDocument(loadedDives); delete loadedDives; @@ -204,12 +206,13 @@ void GlobeGPS::repopulateLabels() // don't show that flag, it's either already shown as displayed_dive // or it's the one that we are moving right now... continue; - if (dive_has_gps_location(dive)) { - GeoDataPlacemark *place = new GeoDataPlacemark(dive->location); - place->setCoordinate(dive->longitude.udeg / 1000000.0, dive->latitude.udeg / 1000000.0, 0, GeoDataCoordinates::Degree); + ds = get_dive_site_for_dive(dive); + if (dive_site_has_gps_location(ds)) { + GeoDataPlacemark *place = new GeoDataPlacemark(ds->name); + place->setCoordinate(ds->longitude.udeg / 1000000.0, ds->latitude.udeg / 1000000.0, 0, GeoDataCoordinates::Degree); // don't add dive locations twice, unless they are at least 50m apart - if (locationMap[QString(dive->location)]) { - GeoDataCoordinates existingLocation = locationMap[QString(dive->location)]->coordinate(); + if (locationMap[QString(ds->name)]) { + GeoDataCoordinates existingLocation = locationMap[QString(ds->name)]->coordinate(); GeoDataLineString segment = GeoDataLineString(); segment.append(existingLocation); GeoDataCoordinates newLocation = place->coordinate(); @@ -220,7 +223,7 @@ void GlobeGPS::repopulateLabels() if (dist < 0.05) continue; } - locationMap[QString(dive->location)] = place; + locationMap[QString(ds->name)] = place; loadedDives->append(place); } } @@ -236,23 +239,23 @@ void GlobeGPS::reload() void GlobeGPS::centerOnCurrentDive() { - struct dive *dive = current_dive; + struct dive_site *ds = get_dive_site_for_dive(current_dive); // dive has changed, if we had the 'editingDive', hide it. - if (messageWidget->isVisible() && (!dive || dive_has_gps_location(dive) || amount_selected != 1)) + if (messageWidget->isVisible() && (!ds || dive_site_has_gps_location(ds) || amount_selected != 1)) messageWidget->hide(); editingDiveLocation = false; - if (!dive) + if (!ds) return; - qreal longitude = dive->longitude.udeg / 1000000.0; - qreal latitude = dive->latitude.udeg / 1000000.0; + qreal longitude = ds->longitude.udeg / 1000000.0; + qreal latitude = ds->latitude.udeg / 1000000.0; - if ((!dive_has_gps_location(dive) || MainWindow::instance()->information()->isEditing()) && amount_selected == 1) { + if ((!dive_site_has_gps_location(ds) || MainWindow::instance()->information()->isEditing()) && amount_selected == 1) { prepareForGetDiveCoordinates(); return; } - if (!dive_has_gps_location(dive)) { + if (!dive_site_has_gps_location(ds)) { zoomOutForNoGPS(); return; } @@ -309,8 +312,10 @@ void GlobeGPS::prepareForGetDiveCoordinates() } } +// This needs to update the dive site, not just this dive void GlobeGPS::changeDiveGeoPosition(qreal lon, qreal lat, GeoDataCoordinates::Unit unit) { + struct dive_site *ds; messageWidget->hide(); if (MainWindow::instance()->dive_list()->selectionModel()->selection().isEmpty()) @@ -324,8 +329,9 @@ void GlobeGPS::changeDiveGeoPosition(qreal lon, qreal lat, GeoDataCoordinates::U centerOn(lon, lat, true); // change the location of the displayed_dive and put the UI in edit mode - displayed_dive.latitude.udeg = lrint(lat * 1000000.0); - displayed_dive.longitude.udeg = lrint(lon * 1000000.0); + ds = get_dive_site_for_dive(&displayed_dive); + ds->latitude.udeg = lrint(lat * 1000000.0); + ds->longitude.udeg = lrint(lon * 1000000.0); emit(coordinatesChanged()); repopulateLabels(); editingDiveLocation = false; From 801e584029688eca38d35542e8ab3d644833231b Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 01:26:57 -0800 Subject: [PATCH 17/58] Another helper: for_each_dive_site() This doesn't make the code necessarily more compact, but easier to read and is consistent with our other patterns. Signed-off-by: Dirk Hohndel --- divesite.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/divesite.h b/divesite.h index da0a78983..2a4d8c616 100644 --- a/divesite.h +++ b/divesite.h @@ -27,10 +27,16 @@ static inline struct dive_site *get_dive_site(int nr) return dive_site_table.dive_sites[nr]; } +/* iterate over each dive site */ +#define for_each_dive_site(_i, _x) \ + for ((_i) = 0; ((_x) = get_dive_site(_i)) != NULL; (_i)++) + static inline struct dive_site *get_dive_site_by_uuid(uint32_t uuid) { - for (int i = 0; i < dive_site_table.nr; i++) - if (get_dive_site(i)->uuid == uuid) + int i; + struct dive_site *ds; + for_each_dive_site (i, ds) + if (ds->uuid == uuid) return get_dive_site(i); return NULL; } @@ -38,9 +44,11 @@ static inline struct dive_site *get_dive_site_by_uuid(uint32_t uuid) /* there could be multiple sites of the same name - return the first one */ static inline uint32_t get_dive_site_uuid_by_name(const char *name) { - for (int i = 0; i < dive_site_table.nr; i++) - if (get_dive_site(i)->name == name) - return get_dive_site(i)->uuid; + int i; + struct dive_site *ds; + for_each_dive_site (i, ds) + if (ds->name == name) + return ds->uuid; return 0; } From f8b63e1bb6e282cd0e7368bbfcf2c572a4ba507e Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 01:28:41 -0800 Subject: [PATCH 18/58] Update completion model for dive site names This way the drop down works again. Signed-off-by: Dirk Hohndel --- qt-ui/completionmodels.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/qt-ui/completionmodels.cpp b/qt-ui/completionmodels.cpp index fd3cc7504..f2e70afd1 100644 --- a/qt-ui/completionmodels.cpp +++ b/qt-ui/completionmodels.cpp @@ -40,9 +40,21 @@ CREATE_CSV_UPDATE_METHOD(BuddyCompletionModel, buddy); CREATE_CSV_UPDATE_METHOD(DiveMasterCompletionModel, divemaster); -CREATE_UPDATE_METHOD(LocationCompletionModel, location); CREATE_UPDATE_METHOD(SuitCompletionModel, suit); +void LocationCompletionModel::updateModel() +{ + QStringList list; + struct dive_site *ds; + int i = 0; + for_each_dive_site(i, ds) { + if (!list.contains(ds->name)) + list.append(ds->name); + } + std::sort(list.begin(), list.end()); + setStringList(list); +} + void TagCompletionModel::updateModel() { if (g_tag_list == NULL) From ccf833b45cf7cc9f0bc1ddd3220148835062593d Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 01:34:00 -0800 Subject: [PATCH 19/58] Clear the location if we have no dive site Signed-off-by: Dirk Hohndel --- qt-ui/maintab.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index 363ab3c43..d2990b194 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -442,6 +442,8 @@ void MainTab::updateDiveInfo(bool clear) struct dive_site *ds = get_dive_site_by_uuid(displayed_dive.dive_site_uuid); if (ds) ui.location->setText(ds->name); + else + ui.location->clear(); updateGpsCoordinates(); // Subsurface always uses "local time" as in "whatever was the local time at the location" // so all time stamps have no time zone information and are in UTC From cd28e88bee085b1f12561764b87a9b8ffc0a8212 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 01:59:16 -0800 Subject: [PATCH 20/58] Improve helper functions Sometimes we want to create a dive site just based on a name, sometimes we have both a name and GPS coordinates. Let's make a helper for either case. Signed-off-by: Dirk Hohndel --- divesite.c | 14 ++++++++++++-- divesite.h | 10 +++++++++- parse-xml.c | 10 +++++----- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/divesite.c b/divesite.c index 21efaf2e6..c3bb45950 100644 --- a/divesite.c +++ b/divesite.c @@ -37,7 +37,17 @@ struct dive_site *alloc_dive_site() } /* allocate a new site and add it to the table */ -uint32_t create_dive_site(const char *name, degrees_t latitude, degrees_t longitude) +uint32_t create_dive_site(const char *name) +{ + struct dive_site *ds = alloc_dive_site(); + ds->uuid = dive_site_getUniqId(); + ds->name = copy_string(name); + + return ds->uuid; +} + +/* same as before, but with GPS data */ +uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees_t longitude) { struct dive_site *ds = alloc_dive_site(); ds->uuid = dive_site_getUniqId(); @@ -53,7 +63,7 @@ uint32_t dive_site_uuid_by_name(const char *name) { uint32_t id = get_dive_site_uuid_by_name(name); if (id == 0) - id = create_dive_site(name, (degrees_t){0}, (degrees_t){0}); + id = create_dive_site(name); return id; } diff --git a/divesite.h b/divesite.h index 2a4d8c616..b3487c341 100644 --- a/divesite.h +++ b/divesite.h @@ -4,6 +4,10 @@ #include "units.h" #include +#ifdef __cplusplus +extern "C" { +#endif + struct dive_site { uint32_t uuid; @@ -53,7 +57,11 @@ static inline uint32_t get_dive_site_uuid_by_name(const char *name) } struct dive_site *alloc_dive_site(); -uint32_t create_dive_site(const char *name, degrees_t latitude, degrees_t longitude); +uint32_t create_dive_site(const char *name); +uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees_t longitude); uint32_t dive_site_uuid_by_name(const char *name); +#ifdef __cplusplus +} +#endif #endif // DIVESITE_H diff --git a/parse-xml.c b/parse-xml.c index 4377a32cb..54e74b953 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -983,7 +983,7 @@ static void divinglog_place(char *place, uint32_t *uuid) country ? country : ""); *uuid = get_dive_site_uuid_by_name(buffer); if (*uuid == 0) - *uuid = create_dive_site(buffer, (degrees_t){0}, (degrees_t){0}); + *uuid = create_dive_site(buffer); city = NULL; country = NULL; @@ -1156,7 +1156,7 @@ static void gps_in_dive(char *buffer, struct dive *dive) uint32_t uuid = dive->dive_site_uuid; if (uuid == 0) { fprintf(stderr, "found no uuid in dive, creating a divesite without name and above GPS\n"); - dive->dive_site_uuid = create_dive_site("", latitude, longitude); + dive->dive_site_uuid = create_dive_site_with_gps("", latitude, longitude); } else { fprintf(stderr, "found uuid in dive, checking to see if we should add GPS\n"); struct dive_site *ds = get_dive_site_by_uuid(uuid); @@ -1193,7 +1193,7 @@ static void add_dive_site(char *buffer, struct dive *dive) exit(1); } } else { - dive->dive_site_uuid = create_dive_site(buffer, (degrees_t){0}, (degrees_t){0}); + dive->dive_site_uuid = create_dive_site(buffer); } } } @@ -1437,7 +1437,7 @@ static void dive_site_end(void) if (!cur_dive_site) return; if (cur_dive_site->uuid) { - uint32_t tmp = create_dive_site(cur_dive_site->name, cur_dive_site->latitude, cur_dive_site->longitude); + uint32_t tmp = create_dive_site_with_gps(cur_dive_site->name, cur_dive_site->latitude, cur_dive_site->longitude); struct dive_site *ds = get_dive_site_by_uuid(tmp); ds->uuid = cur_dive_site->uuid; ds->notes = cur_dive_site->notes; @@ -2502,7 +2502,7 @@ extern int cobalt_location(void *handle, int columns, char **data, char **column sprintf(tmp, "%s / %s", location, data[0]); free(location); location = NULL; - cur_dive->dive_site_uuid = create_dive_site(tmp, (degrees_t){0}, (degrees_t){0}); + cur_dive->dive_site_uuid = create_dive_site(tmp); } else { location = strdup(data[0]); } From 5c4d2660604af8925b757025571a8dcc36da1cdc Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 02:04:20 -0800 Subject: [PATCH 21/58] Make editing a location work with dive sites Not sure if this is the final implementation, but at least for simple cases it works now. Signed-off-by: Dirk Hohndel --- qt-ui/maintab.cpp | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index d2990b194..ab691a4b4 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -1158,25 +1158,12 @@ void MainTab::on_location_textChanged(const QString &text) // If we have GPS data for the location entered, add it. void MainTab::on_location_editingFinished() { - // if we have a location and no GPS data, look up the GPS data; - // but if the GPS data was intentionally cleared then don't - if (!currentTrip && - !same_string(displayed_dive.location, "") && - ui.coordinates->text().trimmed().isEmpty() && - !(editMode == DIVE && dive_has_gps_location(current_dive))) { - struct dive *dive; - int i = 0; - for_each_dive (i, dive) { - if (same_string(displayed_dive.location, dive->location) && - (dive->latitude.udeg || dive->longitude.udeg)) { - displayed_dive.latitude = dive->latitude; - displayed_dive.longitude = dive->longitude; - MainWindow::instance()->globe()->reload(); - updateGpsCoordinates(); - break; - } - } - } + // find the dive site or create it + const char *name = ui.location->text().toUtf8().data(); + uint32_t uuid = get_dive_site_uuid_by_name(name); + if (!uuid) + uuid = create_dive_site(name); + displayed_dive.dive_site_uuid = uuid; } void MainTab::on_suit_textChanged(const QString &text) From 0e6345f65b041b5005c75b83792ca98d8ef4f766 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 02:04:20 -0800 Subject: [PATCH 22/58] Correctly connect the maintab to dive site management We now have a working uuid - use it. And populate the fields accordingly. Signed-off-by: Dirk Hohndel --- qt-ui/maintab.cpp | 5 ++--- qt-ui/maintab.h | 2 +- qt-ui/mainwindow.cpp | 7 +++---- qt-ui/mainwindow.h | 2 +- qt-ui/simplewidgets.cpp | 13 ++++++------- qt-ui/simplewidgets.h | 5 ++--- 6 files changed, 15 insertions(+), 19 deletions(-) diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index ab691a4b4..b0c2009d3 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -214,10 +214,9 @@ MainTab::~MainTab() } void MainTab::prepareDiveSiteEdit() { - //TODO: GET THE CORRECT DIVESITE UUID HERE - QUuid id = QUuid::createUuid(); - emit requestDiveSiteEdit(id); + emit requestDiveSiteEdit(displayed_dive.dive_site_uuid); } + void MainTab::toggleTriggeredColumn() { QAction *action = qobject_cast(sender()); diff --git a/qt-ui/maintab.h b/qt-ui/maintab.h index c90b0fb09..505fa6f21 100644 --- a/qt-ui/maintab.h +++ b/qt-ui/maintab.h @@ -56,7 +56,7 @@ public: signals: void addDiveFinished(); void dateTimeChanged(); - void requestDiveSiteEdit(QUuid diveSiteId); + void requestDiveSiteEdit(uint32_t uuid); public slots: void addCylinder_clicked(); diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index eca4c08f8..30ab5e5df 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -111,7 +111,7 @@ MainWindow::MainWindow() : QMainWindow(), connect(DivePlannerPointsModel::instance(), SIGNAL(planCreated()), this, SLOT(planCreated())); connect(DivePlannerPointsModel::instance(), SIGNAL(planCanceled()), this, SLOT(planCanceled())); connect(plannerDetails->printPlan(), SIGNAL(pressed()), divePlannerWidget(), SLOT(printDecoPlan())); - connect(mainTab, SIGNAL(requestDiveSiteEdit(QUuid)), this, SLOT(enableDiveSiteEdit(QUuid))); + connect(mainTab, SIGNAL(requestDiveSiteEdit(uint32_t)), this, SLOT(enableDiveSiteEdit(uint32_t))); connect(locationInformation, SIGNAL(informationManagementEnded()), this, SLOT(setDefaultState())); #ifdef NO_PRINTING ui.printPlan->hide(); @@ -214,9 +214,8 @@ LocationInformationWidget *MainWindow::locationInformationWidget() { return qobject_cast(applicationState["EditDiveSite"].topLeft); } -void MainWindow::enableDiveSiteEdit(QUuid id) { - locationInformationWidget()->setLocationName(current_dive->location); - locationInformationWidget()->setLocationCoords(printGPSCoords(current_dive->latitude.udeg, current_dive->longitude.udeg)); +void MainWindow::enableDiveSiteEdit(uint32_t id) { + locationInformationWidget()->setLocationId(id); setApplicationState("EditDiveSite"); } diff --git a/qt-ui/mainwindow.h b/qt-ui/mainwindow.h index ef3e8fa18..85a63123b 100644 --- a/qt-ui/mainwindow.h +++ b/qt-ui/mainwindow.h @@ -160,7 +160,7 @@ slots: void on_paste_triggered(); void on_actionFilterTags_triggered(); void on_actionConfigure_Dive_Computer_triggered(); - void enableDiveSiteEdit(QUuid id); + void enableDiveSiteEdit(uint32_t id); void setDefaultState(); protected: diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index c7dd47c6d..756251b51 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -665,14 +665,13 @@ LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBo ui.diveSiteMessage->addAction(action); } -void LocationInformationWidget::setLocationName(const QString& name) +void LocationInformationWidget::setLocationId(uint32_t uuid) { - ui.diveSiteName->setText(name); -} - -void LocationInformationWidget::setLocationCoords(const QString& coords) -{ - ui.diveSiteCoordinates->setText(coords); + currentDs = get_dive_site_by_uuid(uuid); + ui.diveSiteName->setText(currentDs->name); + ui.diveSiteDescription->setText(currentDs->description); + ui.diveSiteNotes->setPlainText(currentDs->notes); + ui.diveSiteCoordinates->setText(printGPSCoords(currentDs->latitude.udeg, currentDs->longitude.udeg)); } void LocationInformationWidget::acceptChanges() diff --git a/qt-ui/simplewidgets.h b/qt-ui/simplewidgets.h index 24af171a7..9cedb8ad5 100644 --- a/qt-ui/simplewidgets.h +++ b/qt-ui/simplewidgets.h @@ -228,14 +228,13 @@ public slots: void showEvent(QShowEvent *); - /* change that to setLocationSite(QUuid diveSiteUid or something later */ - void setLocationName(const QString& name); - void setLocationCoords(const QString& coords); + void setLocationId(uint32_t uuid); signals: void informationManagementEnded(); private: + struct dive_site *currentDs; Ui::LocationInformation ui; }; From a6336d13b302d071bc94cc15b4a865f0ba2492f7 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 12:27:55 -0800 Subject: [PATCH 23/58] Don't ever create a dive site without valid uuid If you want a specific one, you can always overwrite it, but a dive site with a uuid of 0 breaks some of our assumptions. Signed-off-by: Dirk Hohndel --- divesite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/divesite.c b/divesite.c index c3bb45950..c9dbb095a 100644 --- a/divesite.c +++ b/divesite.c @@ -33,6 +33,7 @@ struct dive_site *alloc_dive_site() exit(1); sites[nr] = ds; dive_site_table.nr = nr + 1; + ds->uuid = dive_site_getUniqId(); return ds; } @@ -40,7 +41,6 @@ struct dive_site *alloc_dive_site() uint32_t create_dive_site(const char *name) { struct dive_site *ds = alloc_dive_site(); - ds->uuid = dive_site_getUniqId(); ds->name = copy_string(name); return ds->uuid; From 0ce215e0d90e8d7612917b75f73bb703b9ada9ae Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 12:28:54 -0800 Subject: [PATCH 24/58] Fix dive site creation from v2 git storage Clearly didn't test that part well enough. Signed-off-by: Dirk Hohndel --- divesite.c | 14 ++++++++++++++ divesite.h | 1 + load-git.c | 23 +++++++++++++++-------- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/divesite.c b/divesite.c index c9dbb095a..d9351e1af 100644 --- a/divesite.c +++ b/divesite.c @@ -67,3 +67,17 @@ uint32_t dive_site_uuid_by_name(const char *name) return id; } + +/* if the uuid is valid, just get the site, otherwise create it first; + * so you can call this with dive->dive_site_uuid and you'll either get the existing + * dive site or it will create a new one - so make sure you assign the uuid back to + * dive->dive_site_uuid when using this function! */ +struct dive_site *get_or_create_dive_site_by_uuid(uint32_t uuid) +{ + struct dive_site *ds = get_dive_site_by_uuid(uuid); + + if (!ds) + ds = alloc_dive_site(); + + return ds; +} diff --git a/divesite.h b/divesite.h index b3487c341..f0cf08067 100644 --- a/divesite.h +++ b/divesite.h @@ -60,6 +60,7 @@ struct dive_site *alloc_dive_site(); uint32_t create_dive_site(const char *name); uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees_t longitude); uint32_t dive_site_uuid_by_name(const char *name); +struct dive_site *get_or_create_dive_site_by_uuid(uint32_t uuid); #ifdef __cplusplus } diff --git a/load-git.c b/load-git.c index 7bd020bd5..4fcf1f600 100644 --- a/load-git.c +++ b/load-git.c @@ -23,13 +23,6 @@ struct keyword_action { #define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0])) extern degrees_t parse_degrees(char *buf, char **end); -static void parse_dive_gps(char *line, struct membuffer *str, void *_dive) -{ - struct dive *dive = _dive; - - dive->latitude = parse_degrees(line, &line); - dive->longitude = parse_degrees(line, &line); -} static char *get_utf8(struct membuffer *b) { @@ -145,8 +138,22 @@ static int get_index(const char *line) static int get_hex(const char *line) { return strtoul(line, NULL, 16); } +static void parse_dive_gps(char *line, struct membuffer *str, void *_dive) +{ + struct dive *dive = _dive; + struct dive_site *ds = get_or_create_dive_site_by_uuid(dive->dive_site_uuid); + dive->dive_site_uuid = ds->uuid; + ds->latitude = parse_degrees(line, &line); + ds->longitude = parse_degrees(line, &line); +} + static void parse_dive_location(char *line, struct membuffer *str, void *_dive) -{ struct dive *dive = _dive; dive->location = get_utf8(str); } +{ + struct dive *dive = _dive; + struct dive_site *ds = get_or_create_dive_site_by_uuid(dive->dive_site_uuid); + dive->dive_site_uuid = ds->uuid; + ds->name = get_utf8(str); +} static void parse_dive_divemaster(char *line, struct membuffer *str, void *_dive) { struct dive *dive = _dive; dive->divemaster = get_utf8(str); } From 7fb35c98d3657407287e6674e7d20ff2525ef152 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 12:49:25 -0800 Subject: [PATCH 25/58] Get trip location from dive's dive site This adds another useful helper function as well. Signed-off-by: Dirk Hohndel --- dive.h | 8 ++++++++ divelist.c | 7 +++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/dive.h b/dive.h index 42cec6224..76ea4b597 100644 --- a/dive.h +++ b/dive.h @@ -512,6 +512,14 @@ static inline struct dive_site *get_dive_site_for_dive(struct dive *dive) return NULL; } +static inline char *get_dive_location(struct dive *dive) +{ + struct dive_site *ds = get_dive_site_by_uuid(dive->dive_site_uuid); + if (ds && ds->name) + return ds->name; + return NULL; +} + static inline unsigned int number_of_computers(struct dive *dive) { unsigned int total_number = 0; diff --git a/divelist.c b/divelist.c index f1dd7006c..a6f6332e1 100644 --- a/divelist.c +++ b/divelist.c @@ -678,9 +678,9 @@ void add_dive_to_trip(struct dive *dive, dive_trip_t *trip) dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive) { dive_trip_t *dive_trip = calloc(1, sizeof(dive_trip_t)); + dive_trip->when = dive->when; - if (dive->location) - dive_trip->location = strdup(dive->location); + dive_trip->location = copy_string(get_dive_location(dive)); insert_trip(&dive_trip); dive->tripflag = IN_TRIP; @@ -714,7 +714,7 @@ void autogroup_dives(void) dive_trip_t *trip = lastdive->divetrip; add_dive_to_trip(dive, trip); if (dive->location && !trip->location) - trip->location = strdup(dive->location); + trip->location = copy_string(get_dive_location(dive)); lastdive = dive; continue; } @@ -745,7 +745,6 @@ void delete_single_dive(int idx) dive_table.dives[--dive_table.nr] = NULL; /* free all allocations */ free(dive->dc.sample); - free((void *)dive->location); free((void *)dive->notes); free((void *)dive->divemaster); free((void *)dive->buddy); From 8bea7cbdc7225496de5817340a9199801a4a6c49 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 12:54:20 -0800 Subject: [PATCH 26/58] Show dive site name in dive list Signed-off-by: Dirk Hohndel --- qt-ui/models.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qt-ui/models.cpp b/qt-ui/models.cpp index ac2f7d899..19f0d12c0 100644 --- a/qt-ui/models.cpp +++ b/qt-ui/models.cpp @@ -1191,7 +1191,7 @@ QVariant DiveItem::data(int column, int role) const retVal = dive->maxcns; break; case LOCATION: - retVal = QString(dive->location); + retVal = QString(get_dive_location(dive)); break; } break; @@ -1232,7 +1232,7 @@ QVariant DiveItem::data(int column, int role) const retVal = dive->maxcns; break; case LOCATION: - retVal = QString(dive->location); + retVal = QString(get_dive_location(dive)); break; case GAS: const char *gas_string = get_dive_gas_string(dive); @@ -2110,7 +2110,7 @@ QVariant ProfilePrintModel::data(const QModelIndex &index, int role) const } if (row == 1) { if (col == 0) - return QString(dive->location); + return QString(get_dive_location(dive)); if (col == 3) return QString(tr("Duration: %1 min")).arg(di.displayDuration()); } From 99ba2f068779248f47c2613e6ce31653adf47553 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 18:52:54 -0800 Subject: [PATCH 27/58] Switch from locations to dive sites in dive.c Signed-off-by: Dirk Hohndel --- dive.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/dive.c b/dive.c index fe7807c5e..3b682ee5f 100644 --- a/dive.c +++ b/dive.c @@ -437,7 +437,6 @@ void clear_dive(struct dive *d) /* free the strings */ free(d->buddy); free(d->divemaster); - free(d->location); free(d->notes); free(d->suit); /* free tags, additional dive computers, and pictures */ @@ -463,7 +462,6 @@ void copy_dive(struct dive *s, struct dive *d) *d = *s; d->buddy = copy_string(s->buddy); d->divemaster = copy_string(s->divemaster); - d->location = copy_string(s->location); d->notes = copy_string(s->notes); d->suit = copy_string(s->suit); for (int i = 0; i < MAX_CYLINDERS; i++) @@ -500,7 +498,6 @@ void selective_copy_dive(struct dive *s, struct dive *d, struct dive_components { if (clear) clear_dive(d); - CONDITIONAL_COPY_STRING(location); CONDITIONAL_COPY_STRING(notes); CONDITIONAL_COPY_STRING(divemaster); CONDITIONAL_COPY_STRING(buddy); @@ -509,10 +506,8 @@ void selective_copy_dive(struct dive *s, struct dive *d, struct dive_components d->rating = s->rating; if (what.visibility) d->visibility = s->visibility; - if (what.gps) { - d->longitude = s->longitude; - d->latitude = s->latitude; - } + if (what.divesite) + d->dive_site_uuid = s->dive_site_uuid; if (what.tags) STRUCTURED_LIST_COPY(struct tag_entry, s->tag_list, d->tag_list, copy_tl); if (what.cylinders) @@ -2699,7 +2694,7 @@ int count_dives_with_location(const char *location) struct dive *d; for_each_dive (i, d) { - if (same_string(d->location, location)) + if (same_string(get_dive_location(d), location)) counter++; } return counter; @@ -2744,9 +2739,6 @@ struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer res->when = dl ? dl->when : a->when; res->selected = a->selected || b->selected; merge_trip(res, a, b); - MERGE_NONZERO(res, a, b, latitude.udeg); - MERGE_NONZERO(res, a, b, longitude.udeg); - MERGE_TXT(res, a, b, location); MERGE_TXT(res, a, b, notes); MERGE_TXT(res, a, b, buddy); MERGE_TXT(res, a, b, divemaster); @@ -2766,7 +2758,7 @@ struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer interleave_dive_computers(&res->dc, &a->dc, &b->dc, offset); else join_dive_computers(&res->dc, &a->dc, &b->dc, 0); - + res->dive_site_uuid = a->dive_site_uuid ?: b->dive_site_uuid; fixup_dive(res); return res; } @@ -2931,9 +2923,10 @@ unsigned int dive_get_picture_count(struct dive *d) void dive_set_geodata_from_picture(struct dive *d, struct picture *pic) { - if (!d->latitude.udeg && pic->latitude.udeg) { - d->latitude = pic->latitude; - d->longitude = pic->longitude; + struct dive_site *ds = get_dive_site_by_uuid(d->dive_site_uuid); + if (!dive_site_has_gps_location(ds) && (pic->latitude.udeg || pic->longitude.udeg)) { + ds->latitude = pic->latitude; + ds->longitude = pic->longitude; } } From 32da12664dd1055befdb7385176ff9eb8a3b9379 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 20:58:03 -0800 Subject: [PATCH 28/58] Switch components for cut/paste dive to dive site logic Signed-off-by: Dirk Hohndel --- dive.h | 3 +- qt-ui/divecomponentselection.ui | 57 +++++++++++++++------------------ qt-ui/maintab.cpp | 5 ++- qt-ui/simplewidgets.cpp | 6 ++-- 4 files changed, 30 insertions(+), 41 deletions(-) diff --git a/dive.h b/dive.h index 76ea4b597..09c831e43 100644 --- a/dive.h +++ b/dive.h @@ -349,14 +349,13 @@ extern int get_cylinder_idx_by_use(struct dive *dive, enum cylinderuse cylinder_ /* when selectively copying dive information, which parts should be copied? */ struct dive_components { - unsigned int location : 1; + unsigned int divesite : 1; unsigned int notes : 1; unsigned int divemaster : 1; unsigned int buddy : 1; unsigned int suit : 1; unsigned int rating : 1; unsigned int visibility : 1; - unsigned int gps : 1; unsigned int tags : 1; unsigned int cylinders : 1; unsigned int weights : 1; diff --git a/qt-ui/divecomponentselection.ui b/qt-ui/divecomponentselection.ui index dbd0839ba..7eade039b 100644 --- a/qt-ui/divecomponentselection.ui +++ b/qt-ui/divecomponentselection.ui @@ -9,8 +9,8 @@ 0 0 - 308 - 263 + 401 + 317 @@ -41,9 +41,9 @@ - + - Location + Dive site @@ -54,34 +54,6 @@ - - - - GPS coordinates - - - - - - - Divemaster - - - - - - - Buddy - - - - - - - Rating - - - @@ -117,6 +89,27 @@ + + + + Divemaster + + + + + + + Buddy + + + + + + + Rating + + + diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index b0c2009d3..e2ccd44de 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -1314,7 +1314,6 @@ void MainTab::showAndTriggerEditSelective(struct dive_components what) // take the data in our copyPasteDive and apply it to selected dives enableEdition(); copyPaste = true; - SHOW_SELECTIVE(location); SHOW_SELECTIVE(buddy); SHOW_SELECTIVE(divemaster); SHOW_SELECTIVE(suit); @@ -1329,8 +1328,8 @@ void MainTab::showAndTriggerEditSelective(struct dive_components what) ui.rating->setCurrentStars(displayed_dive.rating); if (what.visibility) ui.visibility->setCurrentStars(displayed_dive.visibility); - if (what.gps) - updateGpsCoordinates(); + if (what.divesite) + ui.location->setText(get_dive_location(&displayed_dive)); if (what.tags) { char buf[1024]; taglist_get_tagstring(displayed_dive.tag_list, buf, 1024); diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index 756251b51..97b39ee61 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -457,8 +457,7 @@ DiveComponentSelection::DiveComponentSelection(QWidget *parent, struct dive *tar { ui.setupUi(this); what = _what; - UI_FROM_COMPONENT(location); - UI_FROM_COMPONENT(gps); + UI_FROM_COMPONENT(divesite); UI_FROM_COMPONENT(divemaster); UI_FROM_COMPONENT(buddy); UI_FROM_COMPONENT(rating); @@ -478,8 +477,7 @@ DiveComponentSelection::DiveComponentSelection(QWidget *parent, struct dive *tar void DiveComponentSelection::buttonClicked(QAbstractButton *button) { if (ui.buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) { - COMPONENT_FROM_UI(location); - COMPONENT_FROM_UI(gps); + COMPONENT_FROM_UI(divesite); COMPONENT_FROM_UI(divemaster); COMPONENT_FROM_UI(buddy); COMPONENT_FROM_UI(rating); From 4c87ccf952de33a0e62a4fbaf56457ce7359ed84 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 18:55:56 -0800 Subject: [PATCH 29/58] Switch from locations to dive sites in liquivision code Signed-off-by: Dirk Hohndel --- liquivision.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/liquivision.c b/liquivision.c index a42c35aab..7126c9b79 100644 --- a/liquivision.c +++ b/liquivision.c @@ -121,21 +121,24 @@ static void parse_dives (int log_version, const unsigned char *buf, unsigned int // Dive location, assemble Location and Place unsigned int len, place_len; + char *location; len = array_uint32_le(buf + ptr); ptr += 4; place_len = array_uint32_le(buf + ptr + len); if (len && place_len) { - dive->location = malloc(len + place_len + 4); - memset(dive->location, 0, len + place_len + 4); - memcpy(dive->location, buf + ptr, len); - memcpy(dive->location + len, ", ", 2); - memcpy(dive->location + len + 2, buf + ptr + len + 4, place_len); + location = malloc(len + place_len + 4); + memset(location, 0, len + place_len + 4); + memcpy(location, buf + ptr, len); + memcpy(location + len, ", ", 2); + memcpy(location + len + 2, buf + ptr + len + 4, place_len); } else if (len) { - dive->location = strndup(buf + ptr, len); + location = strndup(buf + ptr, len); } else if (place_len) { - dive->location = strndup(buf + ptr + len + 4, place_len); + location = strndup(buf + ptr + len + 4, place_len); } + dive->dive_site_uuid = create_dive_site(location); + free(location); ptr += len + 4 + place_len; From b7e53aaee6703c27061037dfadd657f5fc301559 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 19:01:27 -0800 Subject: [PATCH 30/58] Change from locations to dive sites in save-html and worldmap Signed-off-by: Dirk Hohndel --- save-html.c | 9 ++++++--- worldmap-save.c | 10 +++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/save-html.c b/save-html.c index d67931d8f..13d2fd559 100644 --- a/save-html.c +++ b/save-html.c @@ -172,8 +172,11 @@ void put_HTML_samples(struct membuffer *b, struct dive *dive) void put_HTML_coordinates(struct membuffer *b, struct dive *dive) { - degrees_t latitude = dive->latitude; - degrees_t longitude = dive->longitude; + struct dive_site *ds = get_dive_site_for_dive(dive); + if (!ds) + return; + degrees_t latitude = ds->latitude; + degrees_t longitude = ds->longitude; //don't put coordinates if in (0,0) if (!latitude.udeg && !longitude.udeg) @@ -304,7 +307,7 @@ void write_one_dive(struct membuffer *b, struct dive *dive, const char *photos_d put_format(b, "\"subsurface_number\":%d,", dive->number); put_HTML_date(b, dive, "\"date\":\"", "\","); put_HTML_time(b, dive, "\"time\":\"", "\","); - write_attribute(b, "location", dive->location, ", "); + write_attribute(b, "location", get_dive_location(dive), ", "); put_HTML_coordinates(b, dive); put_format(b, "\"rating\":%d,", dive->rating); put_format(b, "\"visibility\":%d,", dive->visibility); diff --git a/worldmap-save.c b/worldmap-save.c index a7e9d82c2..22bfe583e 100644 --- a/worldmap-save.c +++ b/worldmap-save.c @@ -27,11 +27,11 @@ void writeMarkers(struct membuffer *b, const bool selected_only) if (!dive->selected) continue; } - if (dive->latitude.udeg == 0 && dive->longitude.udeg == 0) + struct dive_site *ds = get_dive_site_for_dive(dive); + if (!ds || !dive_site_has_gps_location(ds)) continue; - - put_degrees(b, dive->latitude, "temp = new google.maps.Marker({position: new google.maps.LatLng(", ""); - put_degrees(b, dive->longitude, ",", ")});\n"); + put_degrees(b, ds->latitude, "temp = new google.maps.Marker({position: new google.maps.LatLng(", ""); + put_degrees(b, ds->longitude, ",", ")});\n"); put_string(b, "markers.push(temp);\ntempinfowindow = new google.maps.InfoWindow({content: '
'+'
'+'
'+'
"); snprintf(pre, sizeof(pre), "

%s ", translate("gettextFromC", "Date:")); put_HTML_date(b, dive, pre, "

"); @@ -49,7 +49,7 @@ void writeMarkers(struct membuffer *b, const bool selected_only) put_HTML_watertemp(b, dive, pre, "

"); snprintf(pre, sizeof(pre), "

%s ", translate("gettextFromC", "Location:")); put_string(b, pre); - put_HTML_quoted(b, dive->location); + put_HTML_quoted(b, get_dive_location(dive)); put_string(b, "

"); snprintf(pre, sizeof(pre), "

%s ", translate("gettextFromC", "Notes:")); put_HTML_notes(b, dive, pre, "

"); From c109b98f198eb3ea98190d720dfd3fc26c571b69 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 19:02:06 -0800 Subject: [PATCH 31/58] Change one more spot in divelist.c from locations to dive sites Signed-off-by: Dirk Hohndel --- divelist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/divelist.c b/divelist.c index a6f6332e1..d57188a68 100644 --- a/divelist.c +++ b/divelist.c @@ -713,7 +713,7 @@ void autogroup_dives(void) if (lastdive && dive->when < lastdive->when + TRIP_THRESHOLD) { dive_trip_t *trip = lastdive->divetrip; add_dive_to_trip(dive, trip); - if (dive->location && !trip->location) + if (get_dive_location(dive) && !trip->location) trip->location = copy_string(get_dive_location(dive)); lastdive = dive; continue; From 9ca600e114cd5f12a17c6a2d39d445f76eb67b0a Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 21:26:43 -0800 Subject: [PATCH 32/58] Fix remaining gps references when parsing XML files Clearly I didn't run into these before in my testing. Signed-off-by: Dirk Hohndel --- parse-xml.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/parse-xml.c b/parse-xml.c index 54e74b953..c93d25453 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -1127,15 +1127,30 @@ degrees_t parse_degrees(char *buf, char **end) static void gps_lat(char *buffer, struct dive *dive) { char *end; - - dive->latitude = parse_degrees(buffer, &end); + degrees_t latitude = parse_degrees(buffer, &end); + struct dive_site *ds = get_dive_site_for_dive(dive); + if (!ds) { + dive->dive_site_uuid = create_dive_site_with_gps(NULL, latitude, (degrees_t){0}); + } else { + if (ds->latitude.udeg && ds->latitude.udeg != latitude.udeg) + fprintf(stderr, "Oops, changing the latitude of existing dive site id %8x name %s; not good\n", ds->uuid, ds->name ?: "(unknown)"); + ds->latitude = latitude; + } } static void gps_long(char *buffer, struct dive *dive) { char *end; + degrees_t longitude = parse_degrees(buffer, &end); + struct dive_site *ds = get_dive_site_for_dive(dive); + if (!ds) { + dive->dive_site_uuid = create_dive_site_with_gps(NULL, (degrees_t){0}, longitude); + } else { + if (ds->longitude.udeg && ds->longitude.udeg != longitude.udeg) + fprintf(stderr, "Oops, changing the longitude of existing dive site id %8x name %s; not good\n", ds->uuid, ds->name ?: "(unknown)"); + ds->longitude = longitude; + } - dive->longitude = parse_degrees(buffer, &end); } static void gps_location(char *buffer, struct dive_site *ds) From d032c2a5c53820a3abec983ba9d61366c1f346fd Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 22:08:43 -0800 Subject: [PATCH 33/58] Change UEMIS infrastructure to use dive sites Which is actually much more natural to the way the UEMIS stores things... Signed-off-by: Dirk Hohndel --- uemis-downloader.c | 7 ++++--- uemis.c | 23 ++++++++--------------- uemis.h | 2 +- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/uemis-downloader.c b/uemis-downloader.c index 7ce25cd57..b9ea57b62 100644 --- a/uemis-downloader.c +++ b/uemis-downloader.c @@ -638,12 +638,12 @@ static void parse_divespot(char *buf) uemis_set_divelocation(divespot, locationstring, latitude, longitude); } -static void track_divespot(char *val, int diveid, char **location, degrees_t *latitude, degrees_t *longitude) +static void track_divespot(char *val, int diveid, uint32_t dive_site_uuid) { int id = atoi(val); if (id >= 0 && id > nr_divespots) nr_divespots = id; - uemis_mark_divelocation(diveid, id, location, latitude, longitude); + uemis_mark_divelocation(diveid, id, dive_site_uuid); return; } @@ -783,7 +783,8 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, char * if (for_dive) *for_dive = atoi(val); } else if (!log && dive && !strcmp(tag, "divespot_id")) { - track_divespot(val, dive->dc.diveid, &dive->location, &dive->latitude, &dive->longitude); + dive->dive_site_uuid = create_dive_site("from Uemis"); + track_divespot(val, dive->dc.diveid, dive->dive_site_uuid); } else if (dive) { parse_tag(dive, tag, val); } diff --git a/uemis.c b/uemis.c index b6cadb848..1f4db09cf 100644 --- a/uemis.c +++ b/uemis.c @@ -103,9 +103,7 @@ struct uemis_helper { int diveid; int lbs; int divespot; - char **location; - degrees_t *latitude; - degrees_t *longitude; + int dive_site_uuid; struct uemis_helper *next; }; static struct uemis_helper *uemis_helper = NULL; @@ -150,27 +148,22 @@ int uemis_get_weight_unit(int diveid) return 0; } -void uemis_mark_divelocation(int diveid, int divespot, char **location, degrees_t *latitude, degrees_t *longitude) +void uemis_mark_divelocation(int diveid, int divespot, uint32_t dive_site_uuid) { struct uemis_helper *hp = uemis_get_helper(diveid); hp->divespot = divespot; - hp->location = location; - hp->longitude = longitude; - hp->latitude = latitude; + hp->dive_site_uuid = dive_site_uuid; } void uemis_set_divelocation(int divespot, char *text, double longitude, double latitude) { struct uemis_helper *hp = uemis_helper; -#if 0 /* seems overkill */ - if (!g_utf8_validate(text, -1, NULL)) - return; -#endif while (hp) { - if (hp->divespot == divespot && hp->location) { - *hp->location = strdup(text); - hp->longitude->udeg = round(longitude * 1000000); - hp->latitude->udeg = round(latitude * 1000000); + if (hp->divespot == divespot) { + struct dive_site *ds = get_dive_site_by_uuid(hp->dive_site_uuid); + ds->name = strdup(text); + ds->longitude.udeg = round(longitude * 1000000); + ds->latitude.udeg = round(latitude * 1000000); } hp = hp->next; } diff --git a/uemis.h b/uemis.h index 32c4bdc24..ad4fa10de 100644 --- a/uemis.h +++ b/uemis.h @@ -14,7 +14,7 @@ extern "C" { void uemis_parse_divelog_binary(char *base64, void *divep); int uemis_get_weight_unit(int diveid); -void uemis_mark_divelocation(int diveid, int divespot, char **location, degrees_t *latitude, degrees_t *longitude); +void uemis_mark_divelocation(int diveid, int divespot, uint32_t dive_site_uuid); void uemis_set_divelocation(int divespot, char *text, double longitude, double latitude); typedef struct From 616cb18b2919d8131c1520975d7c5eb7e8e4aaec Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 22:20:35 -0800 Subject: [PATCH 34/58] Make filters work with dive sites This simply tracks the names - if we have multiple dives sites with the same name but different other data (e.g. different GPS), we could easily get this right (well, somewhat easily, it's a UI question), but for that we'd have to filter for dive site uuid instead of for dive location name. Signed-off-by: Dirk Hohndel --- qt-ui/filtermodels.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qt-ui/filtermodels.cpp b/qt-ui/filtermodels.cpp index 378f46735..f44ab7cf8 100644 --- a/qt-ui/filtermodels.cpp +++ b/qt-ui/filtermodels.cpp @@ -249,7 +249,7 @@ bool LocationFilterModel::doFilter(struct dive *d, QModelIndex &index0, QAbstrac return true; } // Checked means 'Show', Unchecked means 'Hide'. - QString location(d->location); + QString location(get_dive_location(d)); // only show empty location dives if the user checked that. if (location.isEmpty()) { if (rowCount() > 0) @@ -277,7 +277,7 @@ void LocationFilterModel::repopulate() struct dive *dive; int i = 0; for_each_dive (i, dive) { - QString location(dive->location); + QString location(get_dive_location(dive)); if (!location.isEmpty() && !list.contains(location)) { list.append(location); } From 4e95beabc2fd7cdd2efcceb226417f84a903861f Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 22:24:12 -0800 Subject: [PATCH 35/58] Remove coordinates from main tab It seems to make sense to only have them on the dive site screen. For the main UI they were redundant (we have the map) and not all that useful. The only time people would want them is if they wanted to manually add GPS coordinates for a dive, but that should now be done via the dive site UI. There are a couple of FIXMEs in the code and a few code blocks that have been commented out as they will be needed in one form or another once this GPS handling is done on the dive site UI, which right now it is NOT. Signed-off-by: Dirk Hohndel --- qt-ui/globe.cpp | 7 ++- qt-ui/maintab.cpp | 38 +++++-------- qt-ui/maintab.h | 2 - qt-ui/maintab.ui | 130 +++++++++++++++++++------------------------ qt-ui/mainwindow.cpp | 5 +- qthelper.cpp | 2 + 6 files changed, 83 insertions(+), 101 deletions(-) diff --git a/qt-ui/globe.cpp b/qt-ui/globe.cpp index 58e7dc620..256eff175 100644 --- a/qt-ui/globe.cpp +++ b/qt-ui/globe.cpp @@ -347,7 +347,12 @@ void GlobeGPS::mousePressEvent(QMouseEvent *event) // there could be two scenarios that got us here; let's check if we are editing a dive if (MainWindow::instance()->information()->isEditing() && clickOnGlobe) { - MainWindow::instance()->information()->updateCoordinatesText(lat, lon); + // + // FIXME + // TODO + // + // this needs to do this on the dive site screen + // MainWindow::instance()->information()->updateCoordinatesText(lat, lon); repopulateLabels(); } else if (clickOnGlobe) { changeDiveGeoPosition(lon, lat, GeoDataCoordinates::Degree); diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index e2ccd44de..1fbb32fa8 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -72,7 +72,6 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent), setEnabled(false); ui.location->installEventFilter(this); - ui.coordinates->installEventFilter(this); ui.divemaster->installEventFilter(this); ui.buddy->installEventFilter(this); ui.suit->installEventFilter(this); @@ -443,7 +442,6 @@ void MainTab::updateDiveInfo(bool clear) ui.location->setText(ds->name); else ui.location->clear(); - updateGpsCoordinates(); // Subsurface always uses "local time" as in "whatever was the local time at the location" // so all time stamps have no time zone information and are in UTC QDateTime localTime = QDateTime::fromTime_t(displayed_dive.when - gettimezoneoffset(displayed_dive.when)); @@ -454,8 +452,6 @@ void MainTab::updateDiveInfo(bool clear) setTabText(0, tr("Trip notes")); currentTrip = *MainWindow::instance()->dive_list()->selectedTrips().begin(); // only use trip relevant fields - ui.coordinates->setVisible(false); - ui.CoordinatedLabel->setVisible(false); ui.divemaster->setVisible(false); ui.DivemasterLabel->setVisible(false); ui.buddy->setVisible(false); @@ -485,8 +481,6 @@ void MainTab::updateDiveInfo(bool clear) setTabText(0, tr("Dive notes")); currentTrip = NULL; // make all the fields visible writeable - ui.coordinates->setVisible(true); - ui.CoordinatedLabel->setVisible(true); ui.divemaster->setVisible(true); ui.buddy->setVisible(true); ui.suit->setVisible(true); @@ -655,7 +649,6 @@ void MainTab::updateDiveInfo(bool clear) clearStats(); clearEquipment(); ui.rating->setCurrentStars(0); - ui.coordinates->clear(); ui.visibility->setCurrentStars(0); ui.location->clear(); } @@ -765,8 +758,6 @@ void MainTab::acceptChanges() copy_samples(&displayed_dive.dc, ¤t_dive->dc); } struct dive *cd = current_dive; - //Reset coordinates field, in case it contains garbage. - updateGpsCoordinates(); // now check if something has changed and if yes, edit the selected dives that // were identical with the master dive shown (and mark the divelist as changed) if (!same_string(displayed_dive.buddy, cd->buddy)) @@ -794,17 +785,6 @@ void MainTab::acceptChanges() time_t offset = cd->when - displayed_dive.when; MODIFY_SELECTED_DIVES(mydive->when -= offset;); } - if (displayed_dive.latitude.udeg != cd->latitude.udeg || - displayed_dive.longitude.udeg != cd->longitude.udeg) - MODIFY_SELECTED_DIVES( - if (copyPaste || - (same_string(mydive->location, cd->location) && - mydive->latitude.udeg == cd->latitude.udeg && - mydive->longitude.udeg == cd->longitude.udeg)) - gpsHasChanged(mydive, cd, ui.coordinates->text(), 0); - ); - if (!same_string(displayed_dive.location, cd->location)) - MODIFY_SELECTED_DIVES(EDIT_TEXT(location)); saveTags(); @@ -910,7 +890,6 @@ void MainTab::resetPallete() ui.buddy->setPalette(p); ui.notes->setPalette(p); ui.location->setPalette(p); - ui.coordinates->setPalette(p); ui.divemaster->setPalette(p); ui.suit->setPalette(p); ui.airtemp->setPalette(p); @@ -1148,8 +1127,17 @@ void MainTab::on_location_textChanged(const QString &text) free(displayedTrip.location); displayedTrip.location = strdup(ui.location->text().toUtf8().data()); } else { - free(displayed_dive.location); - displayed_dive.location = strdup(ui.location->text().toUtf8().data()); + // this means we switched dive sites... this requires a lot more thinking + // + // + // FIXME + // + // TODO + // + // + // + // free(displayed_dive.location); + // displayed_dive.location = strdup(ui.location->text().toUtf8().data()); } markChangedWidget(ui.location); } @@ -1195,6 +1183,7 @@ void MainTab::on_notes_textChanged() markChangedWidget(ui.notes); } +#if 0 // we'll need something like this for the dive site management void MainTab::on_coordinates_textChanged(const QString &text) { if (editMode == IGNORE || acceptingEdit == true) @@ -1211,6 +1200,7 @@ void MainTab::on_coordinates_textChanged(const QString &text) ui.coordinates->setPalette(p); // marks things red } } +#endif void MainTab::on_rating_valueChanged(int value) { @@ -1262,6 +1252,7 @@ void MainTab::editWeightWidget(const QModelIndex &index) ui.weights->edit(index); } +#if 0 // we'll need this for dive sites void MainTab::updateCoordinatesText(qreal lat, qreal lon) { int ulat = rint(lat * 1000000); @@ -1283,6 +1274,7 @@ void MainTab::updateGpsCoordinates() ui.coordinates->clear(); } } +#endif void MainTab::escDetected() { diff --git a/qt-ui/maintab.h b/qt-ui/maintab.h index 505fa6f21..aebd51073 100644 --- a/qt-ui/maintab.h +++ b/qt-ui/maintab.h @@ -66,7 +66,6 @@ slots: void rejectChanges(); void on_location_textChanged(const QString &text); void on_location_editingFinished(); - void on_coordinates_textChanged(const QString &text); void on_divemaster_textChanged(); void on_buddy_textChanged(); void on_suit_textChanged(const QString &text); @@ -93,7 +92,6 @@ slots: void escDetected(void); void photoDoubleClicked(const QString filePath); void removeSelectedPhotos(); - void updateGpsCoordinates(); void prepareDiveSiteEdit(); private: Ui::MainTab ui; diff --git a/qt-ui/maintab.ui b/qt-ui/maintab.ui index cdaab8386..659e790ef 100644 --- a/qt-ui/maintab.ui +++ b/qt-ui/maintab.ui @@ -22,7 +22,9 @@ 0 - + + scrollArea + @@ -40,8 +42,8 @@ 0 0 - 443 - 758 + 441 + 753 @@ -139,40 +141,6 @@ - - - - - - - 0 - 0 - - - - Coordinates - - - - - - - Dive mode - - - - - - - false - - - - - - - - @@ -251,6 +219,7 @@ Qt::StrongFocus + tagWidget @@ -276,36 +245,50 @@ - - - Tags - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - Qt::ScrollBarAlwaysOff - - - Qt::ScrollBarAlwaysOff - - - QPlainTextEdit::NoWrap - - + + + + + + + + Tags + + + + + + + Dive mode + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + QPlainTextEdit::NoWrap + + + + @@ -400,8 +383,8 @@ 0 0 - 443 - 752 + 68 + 40 @@ -456,8 +439,8 @@ 0 0 - 443 - 752 + 441 + 363 @@ -773,8 +756,8 @@ 0 0 - 443 - 752 + 446 + 215 @@ -1036,7 +1019,6 @@ rating visibility suit - tagWidget notes diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 30ab5e5df..7776f312e 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -133,7 +133,10 @@ MainWindow::MainWindow() : QMainWindow(), #ifdef NO_MARBLE ui.menuView->removeAction(ui.actionViewGlobe); #else - connect(globe(), SIGNAL(coordinatesChanged()), information(), SLOT(updateGpsCoordinates())); + // FIXME + // TODO + // we need this on the dive sites + //connect(globe(), SIGNAL(coordinatesChanged()), information(), SLOT(updateGpsCoordinates())); #endif #ifdef NO_USERMANUAL ui.menuHelp->removeAction(ui.actionUserManual); diff --git a/qthelper.cpp b/qthelper.cpp index acb1e103a..902dc5e6d 100644 --- a/qthelper.cpp +++ b/qthelper.cpp @@ -165,6 +165,7 @@ bool parseGpsText(const QString &gps_text, double *latitude, double *longitude) pos == gps_text.size(); } +#if 0 // we'll need something like this for the dive site management, eventually bool gpsHasChanged(struct dive *dive, struct dive *master, const QString &gps_text, bool *parsed_out) { double latitude, longitude; @@ -193,6 +194,7 @@ bool gpsHasChanged(struct dive *dive, struct dive *master, const QString &gps_te dive->longitude.udeg = longudeg; return true; } +#endif QList getDivesInTrip(dive_trip_t *trip) { From 253a137cc7fa14caa4db165ce8529a898be06406 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 22:39:54 -0800 Subject: [PATCH 36/58] Get location from dive site for printing Signed-off-by: Dirk Hohndel --- qt-ui/printlayout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qt-ui/printlayout.cpp b/qt-ui/printlayout.cpp index d9752d235..4be5fef73 100644 --- a/qt-ui/printlayout.cpp +++ b/qt-ui/printlayout.cpp @@ -462,7 +462,7 @@ void PrintLayout::addTablePrintDataRow(TablePrintModel *model, int row, struct d model->setData(model->index(row, 3), di.displayDuration(), Qt::DisplayRole); model->setData(model->index(row, 4), dive->divemaster, Qt::DisplayRole); model->setData(model->index(row, 5), dive->buddy, Qt::DisplayRole); - model->setData(model->index(row, 6), dive->location, Qt::DisplayRole); + model->setData(model->index(row, 6), get_dive_location(dive), Qt::DisplayRole); } void PrintLayout::addTablePrintHeadingRow(TablePrintModel *model, int row) const From b2f0d21d43fb42918041e492cd5cb18253505960 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 22:40:30 -0800 Subject: [PATCH 37/58] Get location for Facebook from dive site Signed-off-by: Dirk Hohndel --- qt-ui/socialnetworks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qt-ui/socialnetworks.cpp b/qt-ui/socialnetworks.cpp index 21ccf9354..6a81d5db7 100644 --- a/qt-ui/socialnetworks.cpp +++ b/qt-ui/socialnetworks.cpp @@ -302,7 +302,7 @@ void SocialNetworkDialog::selectionChanged() tr("min", "abbreviation for minutes"))); } if (ui->Location->isChecked()) { - fullText += tr("Dive location: %1 \n").arg(d->location); + fullText += tr("Dive location: %1 \n").arg(get_dive_location(d)); } if (ui->Buddy->isChecked()) { fullText += tr("Buddy: %1 \n").arg(d->buddy); From ae49a8a4f7c277644a62b096585ee467f3cad5c7 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 22:54:39 -0800 Subject: [PATCH 38/58] Get location from dive site for git commit message Signed-off-by: Dirk Hohndel --- save-git.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/save-git.c b/save-git.c index 764805d03..2069b4c29 100644 --- a/save-git.c +++ b/save-git.c @@ -960,7 +960,7 @@ static void create_commit_message(struct membuffer *msg) if (dive) { dive_trip_t *trip = dive->divetrip; - const char *location = dive->location ? : "no location"; + const char *location = get_dive_location(dive) ? : "no location"; struct divecomputer *dc = &dive->dc; const char *sep = "\n"; From d4f2b7214863b2a40ebcf69e7add113412f795b8 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 23:35:52 -0800 Subject: [PATCH 39/58] Make special backup when switching XML versions Since the last few dozen commits change the format in irreversible ways and could therefore be destructive and lose data for testers of the development version, let's try to be extra careful and create "special" backup files that aren't overwritten by subsequent backups. At least this way people can go back to the previous state. Of course people using the git backend don't have to worry about this as they always can go back to any earlier save. Signed-off-by: Dirk Hohndel --- dive.h | 2 ++ parse-xml.c | 4 ++++ save-xml.c | 10 +++++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/dive.h b/dive.h index 09c831e43..9de3423ad 100644 --- a/dive.h +++ b/dive.h @@ -48,6 +48,8 @@ extern "C" { #include #endif +extern int last_xml_version; + enum dive_comp_type {OC, CCR, PSCR, FREEDIVE, NUM_DC_TYPE}; // Flags (Open-circuit and Closed-circuit-rebreather) for setting dive computer type enum cylinderuse {OC_GAS, DILUENT, OXYGEN, NUM_GAS_USE}; // The different uses for cylinders diff --git a/parse-xml.c b/parse-xml.c index c93d25453..6cc2d881a 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -21,6 +21,7 @@ int verbose, quit; int metric = 1; +int last_xml_version = -1; static xmlDoc *test_xslt_transforms(xmlDoc *doc, const char **params); @@ -1644,6 +1645,9 @@ static void userid_stop(void) static void entry(const char *name, char *buf) { + if (!strncmp(name, "version.program", sizeof("version.program") - 1) || + !strncmp(name, "version.divelog", sizeof("version.divelog") - 1)) + last_xml_version = atoi(buf); if (in_userid) { try_to_fill_userid(name, buf); return; diff --git a/save-xml.c b/save-xml.c index dad57dc9b..5a0c6976c 100644 --- a/save-xml.c +++ b/save-xml.c @@ -591,7 +591,15 @@ static void try_to_backup(const char *filename) while (extension[i][0] != '\0') { int elen = strlen(extension[i]); if (strcasecmp(filename + flen - elen, extension[i]) == 0) { - save_backup(filename, extension[i], "bak"); + if (last_xml_version < VERSION) { + int se_len = strlen(extension[i]) + 5; + char *special_ext = malloc(se_len); + snprintf(special_ext, se_len, "%s.v%d", extension[i], last_xml_version); + save_backup(filename, extension[i], special_ext); + free(special_ext); + } else { + save_backup(filename, extension[i], "bak"); + } break; } i++; From 8c3efd2a22959f684b7604a405d66abc0831a9e1 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 00:04:14 -0800 Subject: [PATCH 40/58] Improve parsing of older XML files in order to auto create dive sites While the existing code worked with a couple of hand crafted examples it turns out it did a poor job with most of my files. Oops. Depending on whether we find name or coordinates first, we need to identify existing sites in either case and do the right thing. The challeng here are multiple dives at the same site with slightly different GPS coordinates. If the name is read first, these all get merged into one (and we warn about the different GPS data). But if GPS gets read first, we create separate dive sites with the same name. We need a sane UI to consolidate these - but we can't completely automate this... it's possible that these ARE the same site and the GPS data is just imprecise (for example, multiple dives at the same time with GPS locations from the Subsurface companion app). The user should be able to either pick one of the GPS locations, or keep multiple (for example, different buoyes for the same site and you want to keep the different markers). Signed-off-by: Dirk Hohndel --- divesite.c | 10 ---------- divesite.h | 26 ++++++++++++++++++++++---- parse-xml.c | 54 +++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 60 insertions(+), 30 deletions(-) diff --git a/divesite.c b/divesite.c index d9351e1af..bccbe37e2 100644 --- a/divesite.c +++ b/divesite.c @@ -58,16 +58,6 @@ uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees return ds->uuid; } -/* this either returns the uuid for a site with that name or creates an entry */ -uint32_t dive_site_uuid_by_name(const char *name) -{ - uint32_t id = get_dive_site_uuid_by_name(name); - if (id == 0) - id = create_dive_site(name); - - return id; -} - /* if the uuid is valid, just get the site, otherwise create it first; * so you can call this with dive->dive_site_uuid and you'll either get the existing * dive site or it will create a new one - so make sure you assign the uuid back to diff --git a/divesite.h b/divesite.h index f0cf08067..5b1d1959d 100644 --- a/divesite.h +++ b/divesite.h @@ -46,20 +46,38 @@ static inline struct dive_site *get_dive_site_by_uuid(uint32_t uuid) } /* there could be multiple sites of the same name - return the first one */ -static inline uint32_t get_dive_site_uuid_by_name(const char *name) +static inline uint32_t get_dive_site_uuid_by_name(const char *name, struct dive_site **dsp) { int i; struct dive_site *ds; - for_each_dive_site (i, ds) - if (ds->name == name) + for_each_dive_site (i, ds) { + if (ds->name == name) { + if (dsp) + *dsp = ds; return ds->uuid; + } + } + return 0; +} + +/* there could be multiple sites at the same GPS fix - return the first one */ +static inline uint32_t get_dive_site_uuid_by_gps(degrees_t latitude, degrees_t longitude, struct dive_site **dsp) +{ + int i; + struct dive_site *ds; + for_each_dive_site (i, ds) { + if (ds->latitude.udeg == latitude.udeg && ds->longitude.udeg == longitude.udeg) { + if (dsp) + *dsp = ds; + return ds->uuid; + } + } return 0; } struct dive_site *alloc_dive_site(); uint32_t create_dive_site(const char *name); uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees_t longitude); -uint32_t dive_site_uuid_by_name(const char *name); struct dive_site *get_or_create_dive_site_by_uuid(uint32_t uuid); #ifdef __cplusplus diff --git a/parse-xml.c b/parse-xml.c index 6cc2d881a..55744d275 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -982,7 +982,7 @@ static void divinglog_place(char *place, uint32_t *uuid) city ? city : "", country ? ", " : "", country ? country : ""); - *uuid = get_dive_site_uuid_by_name(buffer); + *uuid = get_dive_site_uuid_by_name(buffer, NULL); if (*uuid == 0) *uuid = create_dive_site(buffer); @@ -1165,14 +1165,20 @@ static void gps_location(char *buffer, struct dive_site *ds) static void gps_in_dive(char *buffer, struct dive *dive) { char *end; - fprintf(stderr, "called gps_in_dive with buffer |%s|\n", buffer); + struct dive_site *ds = NULL; degrees_t latitude = parse_degrees(buffer, &end); degrees_t longitude = parse_degrees(end, &end); fprintf(stderr, "got lat %f lon %f\n", latitude.udeg / 1000000.0, longitude.udeg / 1000000.0); uint32_t uuid = dive->dive_site_uuid; if (uuid == 0) { - fprintf(stderr, "found no uuid in dive, creating a divesite without name and above GPS\n"); - dive->dive_site_uuid = create_dive_site_with_gps("", latitude, longitude); + uuid = get_dive_site_uuid_by_gps(latitude, longitude, &ds); + if (ds) { + fprintf(stderr, "found dive site {%s} with these coordinates\n", ds->name); + dive->dive_site_uuid = uuid; + } else { + fprintf(stderr, "found no uuid in dive, no existing dive site with these coordinates, creating a new divesite without name and above GPS\n"); + dive->dive_site_uuid = create_dive_site_with_gps("", latitude, longitude); + } } else { fprintf(stderr, "found uuid in dive, checking to see if we should add GPS\n"); struct dive_site *ds = get_dive_site_by_uuid(uuid); @@ -1183,6 +1189,13 @@ static void gps_in_dive(char *buffer, struct dive *dive) fprintf(stderr, "dive site uuid in dive, but gps location (%10.6f/%10.6f) different from dive location (%10.6f/%10.6f)\n", ds->latitude.udeg / 1000000.0, ds->longitude.udeg / 1000000.0, latitude.udeg / 1000000.0, longitude.udeg / 1000000.0); + int len = ds->notes ? strlen(ds->notes) : 0; + len += sizeof("\nalternative coordinates") + 24; + char *notes = malloc(len); + snprintf(notes, len, "%s\nalternative coordinates %11.6f/%11.6f", + ds->notes ?: "", latitude.udeg / 1000000.0, longitude.udeg / 1000000.0); + free(ds->notes); + ds->notes = notes; } else { fprintf(stderr, "let's add the gps coordinates to divesite with uuid %8x and name %s\n", ds->uuid, ds->name ?: "(none)"); ds->latitude = latitude; @@ -1194,21 +1207,30 @@ static void gps_in_dive(char *buffer, struct dive *dive) static void add_dive_site(char *buffer, struct dive *dive) { fprintf(stderr, "add_dive_site with name %s\n", buffer); - int size; - size = trimspace(buffer); + int size = trimspace(buffer); if(size) { - if (dive->dive_site_uuid) { - // we have a uuid, let's hope there's no name - struct dive_site *ds = get_dive_site_by_uuid(dive->dive_site_uuid); - if (!ds) { - fprintf(stderr, "dive contains a non-existing dive site uuid %x\n", dive->dive_site_uuid); - exit(1); - } - if (!same_string(ds->name, buffer)) { - fprintf(stderr, "dive links to dive site of different name %s / %s\n", ds->name, buffer); - exit(1); + uint32_t uuid = dive->dive_site_uuid; + struct dive_site *ds = get_dive_site_by_uuid(uuid); + if (uuid && !ds) { + // that's strange - we have a uuid but it doesn't exist - let's just ignore it + fprintf(stderr, "dive contains a non-existing dive site uuid %x\n", dive->dive_site_uuid); + uuid = 0; + } + if (!uuid) + // if the dive doesn't have a uuid, check if there's already a dive site by this name + uuid = get_dive_site_uuid_by_name(buffer, &ds); + if (ds) { + // we have a uuid, let's hope there isn't a different name + fprintf(stderr, "have existing site with name {%s} gps %f/%f ", ds->name, ds->latitude.udeg / 1000000.0, ds->longitude.udeg / 1000000.0); + if (same_string(ds->name, "")) { + fprintf(stderr, "so now add name {%s}\n", buffer); + ds->name = copy_string(buffer); + } else if (!same_string(ds->name, buffer)) { + // coin toss, let's just keep the first name we found + fprintf(stderr, "which means the dive already links to dive site of different name {%s} / {%s}\n", ds->name, buffer); } } else { + fprintf(stderr, "no uuid, create new dive site with name {%s}\n", buffer); dive->dive_site_uuid = create_dive_site(buffer); } } From d2baa3631270f8b9bcd612f971d269f5d06fca79 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 01:14:33 -0800 Subject: [PATCH 41/58] Improve dive site creation from v2 git storage Fix broken helper function, move helper functions into the .c file (there really wasn't a good reason for these to be inline), fix the logic that decides if we want to create a new dive site or use an existing one. Signed-off-by: Dirk Hohndel --- divesite.c | 44 ++++++++++++++++++++++++++++++-------------- divesite.h | 33 ++------------------------------- load-git.c | 35 ++++++++++++++++++++++++++++------- 3 files changed, 60 insertions(+), 52 deletions(-) diff --git a/divesite.c b/divesite.c index bccbe37e2..4339a658a 100644 --- a/divesite.c +++ b/divesite.c @@ -4,6 +4,36 @@ struct dive_site_table dive_site_table; +/* there could be multiple sites of the same name - return the first one */ +uint32_t get_dive_site_uuid_by_name(const char *name, struct dive_site **dsp) +{ + int i; + struct dive_site *ds; + for_each_dive_site (i, ds) { + if (same_string(ds->name, name)) { + if (dsp) + *dsp = ds; + return ds->uuid; + } + } + return 0; +} + +/* there could be multiple sites at the same GPS fix - return the first one */ +uint32_t get_dive_site_uuid_by_gps(degrees_t latitude, degrees_t longitude, struct dive_site **dsp) +{ + int i; + struct dive_site *ds; + for_each_dive_site (i, ds) { + if (ds->latitude.udeg == latitude.udeg && ds->longitude.udeg == longitude.udeg) { + if (dsp) + *dsp = ds; + return ds->uuid; + } + } + return 0; +} + /* try to create a uniqe ID - fingers crossed */ static uint32_t dive_site_getUniqId() { @@ -57,17 +87,3 @@ uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees return ds->uuid; } - -/* if the uuid is valid, just get the site, otherwise create it first; - * so you can call this with dive->dive_site_uuid and you'll either get the existing - * dive site or it will create a new one - so make sure you assign the uuid back to - * dive->dive_site_uuid when using this function! */ -struct dive_site *get_or_create_dive_site_by_uuid(uint32_t uuid) -{ - struct dive_site *ds = get_dive_site_by_uuid(uuid); - - if (!ds) - ds = alloc_dive_site(); - - return ds; -} diff --git a/divesite.h b/divesite.h index 5b1d1959d..4dca3ee9d 100644 --- a/divesite.h +++ b/divesite.h @@ -45,40 +45,11 @@ static inline struct dive_site *get_dive_site_by_uuid(uint32_t uuid) return NULL; } -/* there could be multiple sites of the same name - return the first one */ -static inline uint32_t get_dive_site_uuid_by_name(const char *name, struct dive_site **dsp) -{ - int i; - struct dive_site *ds; - for_each_dive_site (i, ds) { - if (ds->name == name) { - if (dsp) - *dsp = ds; - return ds->uuid; - } - } - return 0; -} - -/* there could be multiple sites at the same GPS fix - return the first one */ -static inline uint32_t get_dive_site_uuid_by_gps(degrees_t latitude, degrees_t longitude, struct dive_site **dsp) -{ - int i; - struct dive_site *ds; - for_each_dive_site (i, ds) { - if (ds->latitude.udeg == latitude.udeg && ds->longitude.udeg == longitude.udeg) { - if (dsp) - *dsp = ds; - return ds->uuid; - } - } - return 0; -} - struct dive_site *alloc_dive_site(); uint32_t create_dive_site(const char *name); uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees_t longitude); -struct dive_site *get_or_create_dive_site_by_uuid(uint32_t uuid); +uint32_t get_dive_site_uuid_by_name(const char *name, struct dive_site **dsp); +uint32_t get_dive_site_uuid_by_gps(degrees_t latitude, degrees_t longitude, struct dive_site **dsp); #ifdef __cplusplus } diff --git a/load-git.c b/load-git.c index 4fcf1f600..7cebb038a 100644 --- a/load-git.c +++ b/load-git.c @@ -140,19 +140,40 @@ static int get_hex(const char *line) static void parse_dive_gps(char *line, struct membuffer *str, void *_dive) { + uint32_t uuid; + degrees_t latitude = parse_degrees(line, &line); + degrees_t longitude = parse_degrees(line, &line); struct dive *dive = _dive; - struct dive_site *ds = get_or_create_dive_site_by_uuid(dive->dive_site_uuid); - dive->dive_site_uuid = ds->uuid; - ds->latitude = parse_degrees(line, &line); - ds->longitude = parse_degrees(line, &line); + struct dive_site *ds = get_dive_site_for_dive(dive); + if (!ds) { + uuid = get_dive_site_uuid_by_gps(latitude, longitude, NULL); + if (!uuid) + uuid = create_dive_site_with_gps("", latitude, longitude); + dive->dive_site_uuid = uuid; + } else { + ds->latitude = latitude; + ds->longitude = longitude; + } + } static void parse_dive_location(char *line, struct membuffer *str, void *_dive) { + uint32_t uuid; + char *name = get_utf8(str); struct dive *dive = _dive; - struct dive_site *ds = get_or_create_dive_site_by_uuid(dive->dive_site_uuid); - dive->dive_site_uuid = ds->uuid; - ds->name = get_utf8(str); + struct dive_site *ds = get_dive_site_for_dive(dive); + fprintf(stderr, "looking for a site named {%s} ", name); + if (!ds) { + uuid = get_dive_site_uuid_by_name(name, NULL); + if (!uuid) { fprintf(stderr, "found none, creating\n"); + uuid = create_dive_site(name); + } else { fprintf(stderr, "found one with uuid %8x\n", uuid); } + dive->dive_site_uuid = uuid; + } else { + fprintf(stderr, "dive had site with uuid %8x and name {%s}\n", ds->uuid, ds->name); + ds->name = name; + } } static void parse_dive_divemaster(char *line, struct membuffer *str, void *_dive) From d8146445fcf962e456af91c592536481fdc2753f Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 07:02:26 -0800 Subject: [PATCH 42/58] Add another helper funtion We need to be able to get rid of dive sites as well. Signed-off-by: Dirk Hohndel --- divesite.c | 19 +++++++++++++++++++ divesite.h | 1 + 2 files changed, 20 insertions(+) diff --git a/divesite.c b/divesite.c index 4339a658a..492ba9d82 100644 --- a/divesite.c +++ b/divesite.c @@ -67,6 +67,25 @@ struct dive_site *alloc_dive_site() return ds; } +void delete_dive_site(uint32_t id) +{ + int nr = dive_site_table.nr; + for (int i = 0; i < nr; i++) { + struct dive_site *ds = get_dive_site(i); + if (ds->uuid == id) { + free(ds->name); + free(ds->notes); + free(ds); + if (nr - 1 > i) + memmove(&dive_site_table.dive_sites[i], + &dive_site_table.dive_sites[i+1], + (nr - 1 - i) * sizeof(dive_site_table.dive_sites[0])); + dive_site_table.nr = nr - 1; + break; + } + } +} + /* allocate a new site and add it to the table */ uint32_t create_dive_site(const char *name) { diff --git a/divesite.h b/divesite.h index 4dca3ee9d..4702913aa 100644 --- a/divesite.h +++ b/divesite.h @@ -46,6 +46,7 @@ static inline struct dive_site *get_dive_site_by_uuid(uint32_t uuid) } struct dive_site *alloc_dive_site(); +void delete_dive_site(uint32_t id); uint32_t create_dive_site(const char *name); uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees_t longitude); uint32_t get_dive_site_uuid_by_name(const char *name, struct dive_site **dsp); From be1b6c67c1ec0be77dfa65a1199bf8fc6d6101cf Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 07:08:08 -0800 Subject: [PATCH 43/58] maintab change for get_dive_site_uuid_by_name Signed-off-by: Dirk Hohndel --- qt-ui/maintab.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index 1fbb32fa8..86a8965f5 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -1147,7 +1147,7 @@ void MainTab::on_location_editingFinished() { // find the dive site or create it const char *name = ui.location->text().toUtf8().data(); - uint32_t uuid = get_dive_site_uuid_by_name(name); + uint32_t uuid = get_dive_site_uuid_by_name(name, NULL); if (!uuid) uuid = create_dive_site(name); displayed_dive.dive_site_uuid = uuid; From 6708e06872b395c5a0d22d4f5cf17f8ec19bdaf3 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 07:14:30 -0800 Subject: [PATCH 44/58] Adapt GPS coordinate download from our companion app to dive sites This is a bit awkward now. We are downloading what looks like fake dives in the v2 format. So we create a dive site for every single fix. After we merge those new dive sites into the existing dives we need to throw away all the dive sites that weren't used. Signed-off-by: Dirk Hohndel --- dive.h | 11 -------- qt-ui/subsurfacewebservices.cpp | 47 +++++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/dive.h b/dive.h index 9de3423ad..105d5d8c5 100644 --- a/dive.h +++ b/dive.h @@ -389,17 +389,6 @@ extern void dive_set_geodata_from_picture(struct dive *d, struct picture *pic); extern int explicit_first_cylinder(struct dive *dive, struct divecomputer *dc); -static inline void copy_gps_location(struct dive *from, struct dive *to) -{ - if (from && to) { - to->latitude.udeg = from->latitude.udeg; - to->longitude.udeg = from->longitude.udeg; - if (!to->location) { - to->location = strdup(from->location); - } - } -} - static inline int get_surface_pressure_in_mbar(const struct dive *dive, bool non_null) { int mbar = dive->surface_pressure.mbar; diff --git a/qt-ui/subsurfacewebservices.cpp b/qt-ui/subsurfacewebservices.cpp index a247888a2..17c15583f 100644 --- a/qt-ui/subsurfacewebservices.cpp +++ b/qt-ui/subsurfacewebservices.cpp @@ -29,7 +29,25 @@ #endif struct dive_table gps_location_table; -static bool merge_locations_into_dives(void); + +// we don't overwrite any existing GPS info in the dive +// so get the dive site and if there is none or there is one without GPS fix, add it +static void copy_gps_location(struct dive *from, struct dive *to) +{ + struct dive_site *ds = get_dive_site_for_dive(to); + if (!ds || !dive_site_has_gps_location(ds)) { + struct dive_site *gds = get_dive_site_for_dive(from); + if (!ds) { + // simply link to the one created for the fake dive + to->dive_site_uuid = gds->uuid; + } else { + ds->latitude = gds->latitude; + ds->longitude = gds->longitude; + if (same_string(ds->name, "")) + ds->name = copy_string(gds->name); + } + } +} #define SAME_GROUP 6 * 3600 // six hours //TODO: C Code. static functions are not good if we plan to have a test for them. @@ -49,7 +67,7 @@ static bool merge_locations_into_dives(void) * Asign and mark position, and end gps_location loop */ if ((dive->when <= gpsfix->when && gpsfix->when <= dive->when + dive->duration.seconds)) { - copy_gps_location(gpsfix,dive); + copy_gps_location(gpsfix, dive); changed++; tracer = j; break; @@ -65,7 +83,7 @@ static bool merge_locations_into_dives(void) * If not, simply fail and nextgpsfix will be evaluated in next iteration. */ if ((dive->when + dive->duration.seconds - gpsfix->when) < (nextgpsfix->when - gpsfix->when)) { - copy_gps_location(gpsfix,dive); + copy_gps_location(gpsfix, dive); tracer = j; break; } @@ -73,7 +91,7 @@ static bool merge_locations_into_dives(void) * If no more positions in range, the actual is the one. Asign, mark and end loop. */ } else { - copy_gps_location(gpsfix,dive); + copy_gps_location(gpsfix, dive); changed++; tracer = j; break; @@ -329,10 +347,19 @@ void SubsurfaceWebServices::buttonClicked(QAbstractButton *button) ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); switch (ui.buttonBox->buttonRole(button)) { case QDialogButtonBox::ApplyRole: { + int i; + struct dive *d; + struct dive_site *ds; clear_table(&gps_location_table); QByteArray url = tr("Webservice").toLocal8Bit(); parse_xml_buffer(url.data(), downloadedData.data(), downloadedData.length(), &gps_location_table, NULL); - + // make sure we mark all the dive sites that were created + for (i = 0; i < gps_location_table.nr; i++) { + d = get_dive_from_table(i, &gps_location_table); + ds = get_dive_site_by_uuid(d->dive_site_uuid); + if (ds) + ds->notes = strdup("SubsurfaceWebservice"); + } /* now merge the data in the gps_location table into the dive_table */ if (merge_locations_into_dives()) { mark_divelist_changed(true); @@ -361,6 +388,16 @@ void SubsurfaceWebServices::buttonClicked(QAbstractButton *button) hide(); close(); resetState(); + /* and now clean up and remove all the extra dive sites that were created */ + QSet usedUuids; + for_each_dive(i, d) { + if (d->dive_site_uuid) + usedUuids.insert(d->dive_site_uuid); + } + for_each_dive_site(i, ds) { + if (!usedUuids.contains(ds->uuid) && same_string(ds->notes, "SubsurfaceWebservice")) + delete_dive_site(ds->uuid); + } } break; case QDialogButtonBox::RejectRole: if (reply != NULL && reply->isOpen()) { From 06e578424e272b1c500c2a9e79b4367465fb4ac8 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 12:14:24 -0800 Subject: [PATCH 45/58] Finally remove location, latitude and longitude from struct dive With this all references to these members should be gone and all the code should be switched over to the dive site infrastructure. Signed-off-by: Dirk Hohndel --- dive.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/dive.h b/dive.h index 105d5d8c5..533a193b6 100644 --- a/dive.h +++ b/dive.h @@ -321,12 +321,10 @@ struct dive { bool hidden_by_filter; bool downloaded; timestamp_t when; - char *location; uint32_t dive_site_uuid; char *notes; char *divemaster, *buddy; int rating; - degrees_t latitude, longitude; int visibility; /* 0 - 5 star rating */ cylinder_t cylinder[MAX_CYLINDERS]; weightsystem_t weightsystem[MAX_WEIGHTSYSTEMS]; From 32ad046f5681ad02e3f9842075447e880145267d Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 12:38:56 -0800 Subject: [PATCH 46/58] Allow editing of dive sites And hook things up when double clicking the globe. The user experience isn't consistent with what we do on the main tab (i.e., no coloring of fields that are changed), but it seems to work. Signed-off-by: Dirk Hohndel --- dive.c | 1 + dive.h | 1 + qt-ui/globe.cpp | 10 ++++++---- qt-ui/mainwindow.cpp | 9 ++++----- qt-ui/simplewidgets.cpp | 35 +++++++++++++++++++++++++++++++---- qt-ui/simplewidgets.h | 1 + 6 files changed, 44 insertions(+), 13 deletions(-) diff --git a/dive.c b/dive.c index 3b682ee5f..758368615 100644 --- a/dive.c +++ b/dive.c @@ -13,6 +13,7 @@ * it's used in the UI, but it seems to make the most sense to have it * here */ struct dive displayed_dive; +struct dive_site displayed_dive_site; struct tag_entry *g_tag_list = NULL; diff --git a/dive.h b/dive.h index 533a193b6..8247a5f50 100644 --- a/dive.h +++ b/dive.h @@ -474,6 +474,7 @@ struct dive_table { extern struct dive_table dive_table; extern struct dive displayed_dive; +extern struct dive_site displayed_dive_site; extern int selected_dive; extern unsigned int dc_number; #define current_dive (get_dive(selected_dive)) diff --git a/qt-ui/globe.cpp b/qt-ui/globe.cpp index 256eff175..91bb4e858 100644 --- a/qt-ui/globe.cpp +++ b/qt-ui/globe.cpp @@ -206,7 +206,10 @@ void GlobeGPS::repopulateLabels() // don't show that flag, it's either already shown as displayed_dive // or it's the one that we are moving right now... continue; - ds = get_dive_site_for_dive(dive); + if (idx == -1) + ds = &displayed_dive_site; + else + ds = get_dive_site_for_dive(dive); if (dive_site_has_gps_location(ds)) { GeoDataPlacemark *place = new GeoDataPlacemark(ds->name); place->setCoordinate(ds->longitude.udeg / 1000000.0, ds->latitude.udeg / 1000000.0, 0, GeoDataCoordinates::Degree); @@ -329,9 +332,8 @@ void GlobeGPS::changeDiveGeoPosition(qreal lon, qreal lat, GeoDataCoordinates::U centerOn(lon, lat, true); // change the location of the displayed_dive and put the UI in edit mode - ds = get_dive_site_for_dive(&displayed_dive); - ds->latitude.udeg = lrint(lat * 1000000.0); - ds->longitude.udeg = lrint(lon * 1000000.0); + displayed_dive_site.latitude.udeg = lrint(lat * 1000000.0); + displayed_dive_site.longitude.udeg = lrint(lon * 1000000.0); emit(coordinatesChanged()); repopulateLabels(); editingDiveLocation = false; diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 7776f312e..6a67befa1 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -113,6 +113,8 @@ MainWindow::MainWindow() : QMainWindow(), connect(plannerDetails->printPlan(), SIGNAL(pressed()), divePlannerWidget(), SLOT(printDecoPlan())); connect(mainTab, SIGNAL(requestDiveSiteEdit(uint32_t)), this, SLOT(enableDiveSiteEdit(uint32_t))); connect(locationInformation, SIGNAL(informationManagementEnded()), this, SLOT(setDefaultState())); + connect(locationInformation, SIGNAL(informationManagementEnded()), this, SLOT(refreshDisplay())); + #ifdef NO_PRINTING ui.printPlan->hide(); ui.menuFile->removeAction(ui.actionPrint); @@ -133,10 +135,7 @@ MainWindow::MainWindow() : QMainWindow(), #ifdef NO_MARBLE ui.menuView->removeAction(ui.actionViewGlobe); #else - // FIXME - // TODO - // we need this on the dive sites - //connect(globe(), SIGNAL(coordinatesChanged()), information(), SLOT(updateGpsCoordinates())); + connect(globe(), SIGNAL(coordinatesChanged()), locationInformation, SLOT(updateGpsCoordinates())); #endif #ifdef NO_USERMANUAL ui.menuHelp->removeAction(ui.actionUserManual); @@ -218,7 +217,6 @@ LocationInformationWidget *MainWindow::locationInformationWidget() { } void MainWindow::enableDiveSiteEdit(uint32_t id) { - locationInformationWidget()->setLocationId(id); setApplicationState("EditDiveSite"); } @@ -276,6 +274,7 @@ void MainWindow::current_dive_changed(int divenr) } graphics()->plotDive(); information()->updateDiveInfo(); + locationInformationWidget()->setLocationId(displayed_dive.dive_site_uuid); } void MainWindow::on_actionNew_triggered() diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index 97b39ee61..00f749780 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -666,19 +666,46 @@ LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBo void LocationInformationWidget::setLocationId(uint32_t uuid) { currentDs = get_dive_site_by_uuid(uuid); - ui.diveSiteName->setText(currentDs->name); - ui.diveSiteDescription->setText(currentDs->description); - ui.diveSiteNotes->setPlainText(currentDs->notes); - ui.diveSiteCoordinates->setText(printGPSCoords(currentDs->latitude.udeg, currentDs->longitude.udeg)); + displayed_dive_site = *currentDs; + ui.diveSiteName->setText(displayed_dive_site.name); + ui.diveSiteDescription->setText(displayed_dive_site.description); + ui.diveSiteNotes->setPlainText(displayed_dive_site.notes); + ui.diveSiteCoordinates->setText(printGPSCoords(displayed_dive_site.latitude.udeg, displayed_dive_site.longitude.udeg)); +} + +void LocationInformationWidget::updateGpsCoordinates() +{ + ui.diveSiteCoordinates->setText(printGPSCoords(displayed_dive_site.latitude.udeg, displayed_dive_site.longitude.udeg)); + MainWindow::instance()->setApplicationState("EditDiveSite"); } void LocationInformationWidget::acceptChanges() { + char *uiString; + currentDs->latitude = displayed_dive_site.latitude; + currentDs->longitude = displayed_dive_site.longitude; + uiString = ui.diveSiteName->text().toUtf8().data(); + if (!same_string(uiString, currentDs->name)) { + free(currentDs->name); + currentDs->name = copy_string(uiString); + } + uiString = ui.diveSiteDescription->text().toUtf8().data(); + if (!same_string(uiString, currentDs->description)) { + free(currentDs->description); + currentDs->description = copy_string(uiString); + } + uiString = ui.diveSiteNotes->document()->toPlainText().toUtf8().data(); + if (!same_string(uiString, currentDs->notes)) { + free(currentDs->notes); + currentDs->notes = copy_string(uiString); + } + mark_divelist_changed(true); emit informationManagementEnded(); } void LocationInformationWidget::rejectChanges() { + setLocationId(currentDs->uuid); emit informationManagementEnded(); } diff --git a/qt-ui/simplewidgets.h b/qt-ui/simplewidgets.h index 9cedb8ad5..d0cb60508 100644 --- a/qt-ui/simplewidgets.h +++ b/qt-ui/simplewidgets.h @@ -229,6 +229,7 @@ public slots: void showEvent(QShowEvent *); void setLocationId(uint32_t uuid); + void updateGpsCoordinates(void); signals: void informationManagementEnded(); From 2607fea2de9f3158c7f292c4195746b9becee615 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 12:32:11 -0800 Subject: [PATCH 47/58] Fix compile time warning No idea why designer sometimes adds these zorder items. Signed-off-by: Dirk Hohndel --- qt-ui/maintab.ui | 2 -- 1 file changed, 2 deletions(-) diff --git a/qt-ui/maintab.ui b/qt-ui/maintab.ui index 659e790ef..5267863ff 100644 --- a/qt-ui/maintab.ui +++ b/qt-ui/maintab.ui @@ -23,7 +23,6 @@ - scrollArea @@ -219,7 +218,6 @@ Qt::StrongFocus - tagWidget From 1527cd0d05f01dda47bf3634e872580a40000702 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 12:44:42 -0800 Subject: [PATCH 48/58] More useful debug prints Signed-off-by: Dirk Hohndel --- parse-xml.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parse-xml.c b/parse-xml.c index 55744d275..5c5346c09 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -1466,12 +1466,10 @@ static void dive_site_start(void) if (cur_dive_site) return; cur_dive_site = calloc(1, sizeof(struct dive_site)); - fprintf(stderr, "allocated cur_dive_site\n"); } static void dive_site_end(void) { - fprintf(stderr, "done with dive_site\n"); if (!cur_dive_site) return; if (cur_dive_site->uuid) { @@ -1480,6 +1478,8 @@ static void dive_site_end(void) ds->uuid = cur_dive_site->uuid; ds->notes = cur_dive_site->notes; ds->description = cur_dive_site->description; + if (verbose > 3) + printf("completed dive site uuid %x8 name {%s}\n", ds->uuid, ds->name); } free(cur_dive_site); cur_dive_site = NULL; From 6dd6e9068452dc12666aa45cf464031c8a8b0d57 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 21:07:22 -0800 Subject: [PATCH 49/58] Don't force the first divecomputer to CCR just because there's po2 value The existing code was bogus as it used cur_dive->dc instead of cur_dc (i.e., it always changed the first dive computer, even if the po2 was found in a different one). But fundamentally I consider this bogus. We are not doing the right thing here - some dive computer send us pO2 values that are just the calculated pO2 at a depth and NOT a setpoint, yet we pretend those are setpoints and then turn these dives into CCR dives. This needs to done differently. Signed-off-by: Dirk Hohndel --- parse-xml.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/parse-xml.c b/parse-xml.c index 5c5346c09..cfe3459ed 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -935,10 +935,8 @@ static void try_to_fill_sample(struct sample *sample, const char *name, char *bu return; if (MATCH("sensor3.sample", double_to_o2pressure, &sample->o2sensor[2])) // up to 3 CCR sensors return; - if (MATCH("po2.sample", double_to_o2pressure, &sample->setpoint)) { - cur_dive->dc.divemode = CCR; + if (MATCH("po2.sample", double_to_o2pressure, &sample->setpoint)) return; - } if (MATCH("heartbeat", get_uint8, &sample->heartbeat)) return; if (MATCH("bearing", get_bearing, &sample->bearing)) From da60867ae3765dce3fbbfe85682e6157f9fd5ed7 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 22:06:57 -0800 Subject: [PATCH 50/58] Always print dive site uuids as 8 digits / leading 0s in git format Otherwise there are ugly spaces in the file names. This didn't break anything, per se, it's mostly cosmetic. Signed-off-by: Dirk Hohndel --- save-git.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/save-git.c b/save-git.c index 2069b4c29..cf6bd37e9 100644 --- a/save-git.c +++ b/save-git.c @@ -388,7 +388,7 @@ static void create_dive_buffer(struct dive *dive, struct membuffer *b) SAVE("visibility", visibility); cond_put_format(dive->tripflag == NO_TRIP, b, "notrip\n"); save_tags(b, dive->tag_list); - cond_put_format(dive->dive_site_uuid, b, "divesiteid %8x\n", dive->dive_site_uuid); + cond_put_format(dive->dive_site_uuid, b, "divesiteid %08x\n", dive->dive_site_uuid); save_overview(b, dive); save_cylinder_info(b, dive); @@ -829,7 +829,7 @@ static void save_divesites(git_repository *repo, struct dir *tree) struct dive_site *ds = get_dive_site(i); int size = sizeof("Site-012345678"); char name[size]; - snprintf(name, size, "Site-%8x", ds->uuid); + snprintf(name, size, "Site-%08x", ds->uuid); show_utf8(&b, "name ", ds->name, "\n"); show_utf8(&b, "description ", ds->description, "\n"); show_utf8(&b, "notes ", ds->notes, "\n"); From b60b4ef69d1ae81ace1d4f8ccccdd13aeee01f5a Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 22:08:08 -0800 Subject: [PATCH 51/58] Fix crash when adding a dive If a dive has no dive_site_uuid we would dereference a NULL pointer and crash. Oops. Signed-off-by: Dirk Hohndel --- qt-ui/simplewidgets.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index 00f749780..4f050063c 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -666,7 +666,10 @@ LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBo void LocationInformationWidget::setLocationId(uint32_t uuid) { currentDs = get_dive_site_by_uuid(uuid); - displayed_dive_site = *currentDs; + if (currentDs) + displayed_dive_site = *currentDs; + else + memset(&displayed_dive, 0, sizeof(displayed_dive)); ui.diveSiteName->setText(displayed_dive_site.name); ui.diveSiteDescription->setText(displayed_dive_site.description); ui.diveSiteNotes->setPlainText(displayed_dive_site.notes); From e32459d3139e5f9815550fe3ebbc6bfff96d5d97 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 22:42:57 -0800 Subject: [PATCH 52/58] When adding / planning a dive, reset the dive site manage screen Otherwise old data is still shown if the user clicks manage. Signed-off-by: Dirk Hohndel --- qt-ui/mainwindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 6a67befa1..0991a98e1 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -552,6 +552,7 @@ void MainWindow::setupForAddAndPlan(const char *model) // setup the dive cylinders DivePlannerPointsModel::instance()->clear(); DivePlannerPointsModel::instance()->setupCylinders(); + locationInformationWidget()->setLocationId(0); } void MainWindow::on_actionReplanDive_triggered() From cd77e2e700da92fe0292320d5d4a82361104adfe Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 22:44:05 -0800 Subject: [PATCH 53/58] Make sure there is a dive site if you try to edit it If the user clicks on manage (or double clicks on the globe) and the displayed_dive doesn't actually have a dive site associated with it (e.g. because we are adding a dive or because it was imported or downloaded without dive site information, then we need to make sure that there is an empty dive site that we can make changes to. Signed-off-by: Dirk Hohndel --- qt-ui/simplewidgets.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index 4f050063c..f32ce9b19 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -666,10 +666,16 @@ LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBo void LocationInformationWidget::setLocationId(uint32_t uuid) { currentDs = get_dive_site_by_uuid(uuid); - if (currentDs) - displayed_dive_site = *currentDs; - else - memset(&displayed_dive, 0, sizeof(displayed_dive)); + + if (!currentDs) { + currentDs = get_dive_site_by_uuid(create_dive_site("")); + displayed_dive.dive_site_uuid = currentDs->uuid; + ui.diveSiteName->clear(); + ui.diveSiteDescription->clear(); + ui.diveSiteNotes->clear(); + ui.diveSiteCoordinates->clear(); + } + displayed_dive_site = *currentDs; ui.diveSiteName->setText(displayed_dive_site.name); ui.diveSiteDescription->setText(displayed_dive_site.description); ui.diveSiteNotes->setPlainText(displayed_dive_site.notes); @@ -708,6 +714,7 @@ void LocationInformationWidget::acceptChanges() void LocationInformationWidget::rejectChanges() { + Q_ASSERT(currentDs != NULL); setLocationId(currentDs->uuid); emit informationManagementEnded(); } From 7ca3d859dc304674fe9e48c3ab3925303615a1c2 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 22:53:03 -0800 Subject: [PATCH 54/58] Add helper function to detect empty dive sites No point in keeping those. Signed-off-by: Dirk Hohndel --- divesite.c | 10 ++++++++++ divesite.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/divesite.c b/divesite.c index 492ba9d82..4f236017f 100644 --- a/divesite.c +++ b/divesite.c @@ -106,3 +106,13 @@ uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees return ds->uuid; } + +/* a uuid is always present - but if all the other fields are empty, the dive site is pointless */ +bool dive_site_is_empty(struct dive_site *ds) +{ + return same_string(ds->name, "") && + same_string(ds->description, "") && + same_string(ds->notes, "") && + ds->latitude.udeg == 0 && + ds->longitude.udeg == 0; +} diff --git a/divesite.h b/divesite.h index 4702913aa..ca650259a 100644 --- a/divesite.h +++ b/divesite.h @@ -6,6 +6,8 @@ #ifdef __cplusplus extern "C" { +#else +#include #endif struct dive_site @@ -51,6 +53,7 @@ uint32_t create_dive_site(const char *name); uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees_t longitude); uint32_t get_dive_site_uuid_by_name(const char *name, struct dive_site **dsp); uint32_t get_dive_site_uuid_by_gps(degrees_t latitude, degrees_t longitude, struct dive_site **dsp); +bool dive_site_is_empty(struct dive_site *ds); #ifdef __cplusplus } From 3ea2e15bd2f20e0f84bf02a468c3273a347ac554 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 23:08:33 -0800 Subject: [PATCH 55/58] Don't add empty dive sites It makes no sense to keep them around, it makes no sense to have dives refer to them. Signed-off-by: Dirk Hohndel --- qt-ui/simplewidgets.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index f32ce9b19..27050f6e2 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -708,6 +708,13 @@ void LocationInformationWidget::acceptChanges() free(currentDs->notes); currentDs->notes = copy_string(uiString); } + if (dive_site_is_empty(currentDs)) { + delete_dive_site(currentDs->uuid); + displayed_dive.dive_site_uuid = 0; + setLocationId(0); + } else { + setLocationId(currentDs->uuid); + } mark_divelist_changed(true); emit informationManagementEnded(); } @@ -715,7 +722,13 @@ void LocationInformationWidget::acceptChanges() void LocationInformationWidget::rejectChanges() { Q_ASSERT(currentDs != NULL); - setLocationId(currentDs->uuid); + if (dive_site_is_empty(currentDs)) { + delete_dive_site(currentDs->uuid); + displayed_dive.dive_site_uuid = 0; + setLocationId(0); + } else { + setLocationId(currentDs->uuid); + } emit informationManagementEnded(); } From ca72ab574904bc7fe8083bb692f58d4647e2ff61 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 23:11:36 -0800 Subject: [PATCH 56/58] When closing a dive, delete all the dive sites Signed-off-by: Dirk Hohndel --- qt-ui/mainwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 0991a98e1..1f4c2d7de 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -354,6 +354,8 @@ void MainWindow::closeCurrentFile() clear_git_id(); while (dive_table.nr) delete_single_dive(0); + while (dive_site_table.nr) + delete_dive_site(get_dive_site(0)->uuid); free((void *)existing_filename); existing_filename = NULL; From 6820b13bd58ee382a21215e84427dfd690857dd6 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 23:22:40 -0800 Subject: [PATCH 57/58] Don't store empty dive sites And remove references to them from the dives. Signed-off-by: Dirk Hohndel --- save-git.c | 11 +++++++++++ save-xml.c | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/save-git.c b/save-git.c index cf6bd37e9..84eb1a316 100644 --- a/save-git.c +++ b/save-git.c @@ -827,6 +827,17 @@ static void save_divesites(git_repository *repo, struct dir *tree) for (int i = 0; i < dive_site_table.nr; i++) { struct membuffer b = { 0 }; struct dive_site *ds = get_dive_site(i); + if (dive_site_is_empty(ds)) { + int j; + struct dive *d; + for_each_dive(j, d) { + if (d->dive_site_uuid == ds->uuid) + d->dive_site_uuid = 0; + } + delete_dive_site(get_dive_site(i)->uuid); + i--; // since we just deleted that one + continue; + } int size = sizeof("Site-012345678"); char name[size]; snprintf(name, size, "Site-%08x", ds->uuid); diff --git a/save-xml.c b/save-xml.c index 5a0c6976c..c09b90812 100644 --- a/save-xml.c +++ b/save-xml.c @@ -506,6 +506,17 @@ void save_dives_buffer(struct membuffer *b, const bool select_only) put_format(b, "\n"); for (i = 0; i < dive_site_table.nr; i++) { struct dive_site *ds = get_dive_site(i); + if (dive_site_is_empty(ds)) { + int j; + struct dive *d; + for_each_dive(j, d) { + if (d->dive_site_uuid == ds->uuid) + d->dive_site_uuid = 0; + } + delete_dive_site(get_dive_site(i)->uuid); + i--; // since we just deleted that one + continue; + } put_format(b, "uuid); show_utf8(b, ds->name, " name='", "'", 1); if (ds->latitude.udeg || ds->longitude.udeg) { From f81e2c111d9c563a78e62c3bae64bec07c052ec0 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 23:49:05 -0800 Subject: [PATCH 58/58] When updating the dive site name, show this on the maintab If we accept a change on the dive site management screen, it needs to be reflected on the Dive notes tab right away. Signed-off-by: Dirk Hohndel --- qt-ui/maintab.cpp | 5 +++++ qt-ui/maintab.h | 2 ++ qt-ui/mainwindow.cpp | 1 + 3 files changed, 8 insertions(+) diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index 86a8965f5..b78280d7a 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -395,6 +395,11 @@ bool MainTab::isEditing() return editMode != NONE; } +void MainTab::showLocation() +{ + ui.location->setText(get_dive_location(&displayed_dive)); +} + void MainTab::updateDiveInfo(bool clear) { // don't execute this while adding / planning a dive diff --git a/qt-ui/maintab.h b/qt-ui/maintab.h index aebd51073..8869b068e 100644 --- a/qt-ui/maintab.h +++ b/qt-ui/maintab.h @@ -93,6 +93,8 @@ slots: void photoDoubleClicked(const QString filePath); void removeSelectedPhotos(); void prepareDiveSiteEdit(); + void showLocation(); + private: Ui::MainTab ui; WeightModel *weightModel; diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 1f4c2d7de..56f885409 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -114,6 +114,7 @@ MainWindow::MainWindow() : QMainWindow(), connect(mainTab, SIGNAL(requestDiveSiteEdit(uint32_t)), this, SLOT(enableDiveSiteEdit(uint32_t))); connect(locationInformation, SIGNAL(informationManagementEnded()), this, SLOT(setDefaultState())); connect(locationInformation, SIGNAL(informationManagementEnded()), this, SLOT(refreshDisplay())); + connect(locationInformation, SIGNAL(informationManagementEnded()), information(), SLOT(showLocation())); #ifdef NO_PRINTING ui.printPlan->hide();