Add a new dialog to allow to merge dive sites
From 1cd16399069a3d0b23825761cd7992d0356b2c03 Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <[email protected]>
Date: Mon, 31 Aug 2015 20:17:06 -0300
Subject: [PATCH 01/11] Widget to show other dive sites on same coordinate

Add a new widget on the dive site management view to
display all other dive sites on the same coordinate.

Signed-off-by: Tomaz Canabrava <[email protected]>
---
 qt-ui/locationInformation.ui | 65 ++++++++++++++++++++++++++++----------------
 1 file changed, 42 insertions(+), 23 deletions(-)

diff --git a/qt-ui/locationInformation.ui b/qt-ui/locationInformation.ui
index 56e8b0e..34cc2d5 100644
--- a/qt-ui/locationInformation.ui
+++ b/qt-ui/locationInformation.ui
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>556</width>
-    <height>584</height>
+    <height>707</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -30,19 +30,6 @@
      </property>
     </widget>
    </item>
-   <item row="5" column="0">
-    <spacer name="verticalSpacer">
-     <property name="orientation">
-      <enum>Qt::Vertical</enum>
-     </property>
-     <property name="sizeHint" stdset="0">
-      <size>
-       <width>20</width>
-       <height>40</height>
-      </size>
-     </property>
-    </spacer>
-   </item>
    <item row="3" column="0">
     <widget class="QLabel" name="label_3">
      <property name="text">
@@ -67,6 +54,15 @@
      </property>
     </widget>
    </item>
+   <item row="3" column="1" colspan="2">
+    <widget class="QLineEdit" name="diveSiteDescription"/>
+   </item>
+   <item row="1" column="1" colspan="2">
+    <widget class="QLineEdit" name="diveSiteName"/>
+   </item>
+   <item row="4" column="1" rowspan="2" colspan="2">
+    <widget class="QPlainTextEdit" name="diveSiteNotes"/>
+   </item>
    <item row="2" column="2">
     <widget class="QToolButton" name="geoCodeButton">
      <property name="text">
@@ -78,15 +74,6 @@
      </property>
     </widget>
    </item>
-   <item row="1" column="1" colspan="2">
-    <widget class="QLineEdit" name="diveSiteName"/>
-   </item>
-   <item row="3" column="1" colspan="2">
-    <widget class="QLineEdit" name="diveSiteDescription"/>
-   </item>
-   <item row="4" column="1" rowspan="2" colspan="2">
-    <widget class="QPlainTextEdit" name="diveSiteNotes"/>
-   </item>
    <item row="0" column="0" colspan="3">
     <widget class="KMessageWidget" name="diveSiteMessage" native="true">
      <property name="sizePolicy">
@@ -97,6 +84,38 @@
      </property>
     </widget>
    </item>
+   <item row="6" column="0" colspan="3">
+    <widget class="QGroupBox" name="diveSiteGroupBox">
+     <property name="title">
+      <string>Dive sites on same coordinates</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <widget class="QListView" name="diveSiteListView">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="5" column="0">
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
   </layout>
  </widget>
  <customwidgets>
-- 
2.5.1

From 61ffb867063773d9e9152c395adcb0545e083556 Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <[email protected]>
Date: Mon, 31 Aug 2015 20:19:06 -0300
Subject: [PATCH 02/11] Add a new Model: SsrfFilterProxyModel

Add a new Model, it's the QSortFilterProxyModel that accept
functions to filter / sort. so instead of creating a new class
for each different sorting ( overkill ), now we can just create
a function and pass to this class.  I'll rework the filtering
system of subsurface to use this - in the meantime I'v created
this to ease the creation of another filter: the Dive Sites
by gps coordinates.

Signed-off-by: Tomaz Canabrava <[email protected]>
---
 CMakeLists.txt                         |  1 +
 qt-models/ssrfsortfilterproxymodel.cpp | 39 ++++++++++++++++++++++++++++++++++
 qt-models/ssrfsortfilterproxymodel.h   | 33 ++++++++++++++++++++++++++++
 3 files changed, 73 insertions(+)
 create mode 100644 qt-models/ssrfsortfilterproxymodel.cpp
 create mode 100644 qt-models/ssrfsortfilterproxymodel.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index c0374f1..1426040 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -390,6 +390,7 @@ set(SUBSURFACE_MODELS_LIB_SRCS
 	qt-models/diveplotdatamodel.cpp
 	qt-models/divelocationmodel.cpp
 	qt-models/divesitepicturesmodel.cpp
+	qt-models/ssrfsortfilterproxymodel.cpp
 )
 source_group("Subsurface Models" FILES ${SUBSURFACE_MODELS})
 
diff --git a/qt-models/ssrfsortfilterproxymodel.cpp b/qt-models/ssrfsortfilterproxymodel.cpp
new file mode 100644
index 0000000..443f6de
--- /dev/null
+++ b/qt-models/ssrfsortfilterproxymodel.cpp
@@ -0,0 +1,39 @@
+#include "ssrfsortfilterproxymodel.h"
+
+SsrfSortFilterProxyModel::SsrfSortFilterProxyModel(QObject *parent)
+: QSortFilterProxyModel(parent), less_than(0), accepts_col(0), accepts_row(0)
+{
+}
+
+bool SsrfSortFilterProxyModel::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const
+{
+	Q_ASSERT(less_than);
+	return less_than(source_left, source_right);
+}
+
+bool SsrfSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
+{
+	Q_ASSERT(accepts_row);
+	return accepts_row(source_row, source_parent);
+}
+
+bool SsrfSortFilterProxyModel::filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const
+{
+	Q_ASSERT(accepts_col);
+	return accepts_col(source_column, source_parent);
+}
+
+void SsrfSortFilterProxyModel::setLessThan(less_than_cb func)
+{
+
+}
+
+void SsrfSortFilterProxyModel::setFilterRow(filter_accepts_row_cb func)
+{
+
+}
+
+void SsrfSortFilterProxyModel::setFilterCol(filter_accepts_col_cb func)
+{
+	
+}
\ No newline at end of file
diff --git a/qt-models/ssrfsortfilterproxymodel.h b/qt-models/ssrfsortfilterproxymodel.h
new file mode 100644
index 0000000..f2c22f0
--- /dev/null
+++ b/qt-models/ssrfsortfilterproxymodel.h
@@ -0,0 +1,33 @@
+#ifndef SSRFSORTFILTERPROXYMODEL_H
+#define SSRFSORTFILTERPROXYMODEL_H
+
+#include <QSortFilterProxyModel>
+
+typedef bool (*filter_accepts_col_cb) (int sourceRow, const QModelIndex& parent);
+typedef bool (*filter_accepts_row_cb) (int sourceRow, const QModelIndex& parent);
+typedef bool (*less_than_cb) (const QModelIndex& left, const QModelIndex& right);
+
+/* Use this class when you wanna a quick filter.
+ * instead of creating a new class, just create a new instance of this class
+ * and plug your callback.
+ */
+class SsrfSortFilterProxyModel : public QSortFilterProxyModel {
+	Q_OBJECT
+
+public:
+	SsrfSortFilterProxyModel(QObject *parent = 0);
+	virtual bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const;
+	virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
+	virtual bool filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const;
+
+	void setLessThan(less_than_cb func);
+	void setFilterRow(filter_accepts_row_cb func);
+	void setFilterCol(filter_accepts_col_cb func);
+
+private:
+	less_than_cb less_than;
+	filter_accepts_col_cb accepts_col;
+	filter_accepts_row_cb accepts_row;
+};
+
+#endif
\ No newline at end of file
-- 
2.5.1

From 2c060fb4c6a7645d26cd55a2cd0d4925ef3597ef Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <[email protected]>
Date: Mon, 31 Aug 2015 20:37:15 -0300
Subject: [PATCH 03/11] Pass the model as parameter to the callback

Forgot to add the model as a parameter to the callback
this whould made the callback useless. ;p

Signed-off-by: Tomaz Canabrava <[email protected]>
---
 qt-models/ssrfsortfilterproxymodel.cpp | 15 +++++++++------
 qt-models/ssrfsortfilterproxymodel.h   |  6 +++---
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/qt-models/ssrfsortfilterproxymodel.cpp b/qt-models/ssrfsortfilterproxymodel.cpp
index 443f6de..b3f67c1 100644
--- a/qt-models/ssrfsortfilterproxymodel.cpp
+++ b/qt-models/ssrfsortfilterproxymodel.cpp
@@ -8,32 +8,35 @@ SsrfSortFilterProxyModel::SsrfSortFilterProxyModel(QObject *parent)
 bool SsrfSortFilterProxyModel::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const
 {
 	Q_ASSERT(less_than);
-	return less_than(source_left, source_right);
+	const QAbstractItemModel *self = this;
+	return less_than(const_cast<QAbstractItemModel*>(self), source_left, source_right);
 }
 
 bool SsrfSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
 {
 	Q_ASSERT(accepts_row);
-	return accepts_row(source_row, source_parent);
+	const QAbstractItemModel *self = this;
+	return accepts_row(const_cast<QAbstractItemModel*>(self), source_row, source_parent);
 }
 
 bool SsrfSortFilterProxyModel::filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const
 {
 	Q_ASSERT(accepts_col);
-	return accepts_col(source_column, source_parent);
+	const QAbstractItemModel *self = this;
+	return accepts_col(const_cast<QAbstractItemModel*>(self), source_column, source_parent);
 }
 
 void SsrfSortFilterProxyModel::setLessThan(less_than_cb func)
 {
-
+	less_than = func;
 }
 
 void SsrfSortFilterProxyModel::setFilterRow(filter_accepts_row_cb func)
 {
-
+	accepts_row = func;
 }
 
 void SsrfSortFilterProxyModel::setFilterCol(filter_accepts_col_cb func)
 {
-	
+	accepts_col = func;
 }
\ No newline at end of file
diff --git a/qt-models/ssrfsortfilterproxymodel.h b/qt-models/ssrfsortfilterproxymodel.h
index f2c22f0..2f94a0e 100644
--- a/qt-models/ssrfsortfilterproxymodel.h
+++ b/qt-models/ssrfsortfilterproxymodel.h
@@ -3,9 +3,9 @@
 
 #include <QSortFilterProxyModel>
 
-typedef bool (*filter_accepts_col_cb) (int sourceRow, const QModelIndex& parent);
-typedef bool (*filter_accepts_row_cb) (int sourceRow, const QModelIndex& parent);
-typedef bool (*less_than_cb) (const QModelIndex& left, const QModelIndex& right);
+typedef bool (*filter_accepts_col_cb) (QAbstractItemModel *model,int sourceRow, const QModelIndex& parent);
+typedef bool (*filter_accepts_row_cb) (QAbstractItemModel *model,int sourceRow, const QModelIndex& parent);
+typedef bool (*less_than_cb) (QAbstractItemModel *model, const QModelIndex& left, const QModelIndex& right);
 
 /* Use this class when you wanna a quick filter.
  * instead of creating a new class, just create a new instance of this class
-- 
2.5.1

From 8749b15f7a13a01c0b36ea861b8f32cb6726930b Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <[email protected]>
Date: Mon, 31 Aug 2015 20:37:49 -0300
Subject: [PATCH 04/11] Add function to filter same-gps dive sites

This should be userfull to show dive sites that are
mergeable.

Signed-off-by: Tomaz Canabrava <[email protected]>
---
 qt-models/divelocationmodel.cpp | 10 ++++++++++
 qt-models/divelocationmodel.h   |  4 ++++
 2 files changed, 14 insertions(+)

diff --git a/qt-models/divelocationmodel.cpp b/qt-models/divelocationmodel.cpp
index fca322d..abdf69f 100644
--- a/qt-models/divelocationmodel.cpp
+++ b/qt-models/divelocationmodel.cpp
@@ -183,3 +183,13 @@ GeoReferencingOptionsModel::GeoReferencingOptionsModel(QObject *parent) : QStrin
 		list << taxonomy_category_names[i];
 	setStringList(list);
 }
+
+bool filter_same_gps_cb (QAbstractItemModel *model, int sourceRow, const QModelIndex& parent)
+{
+	int ref_lat = displayed_dive_site.latitude.udeg;
+	int ref_lon = displayed_dive_site.longitude.udeg;
+	QModelIndex curr = model->index(sourceRow, LocationInformationModel::UUID, parent.isValid() ? parent : QModelIndex());
+
+	struct dive_site *ds = get_dive_site_by_uuid(curr.data().toInt());
+	return (ds->latitude.udeg == ref_lat && ds->longitude.udeg == ref_lon);
+}
\ No newline at end of file
diff --git a/qt-models/divelocationmodel.h b/qt-models/divelocationmodel.h
index 3bf7161..f40bbd1 100644
--- a/qt-models/divelocationmodel.h
+++ b/qt-models/divelocationmodel.h
@@ -5,10 +5,14 @@
 #include <QStringListModel>
 #include <stdint.h>
 
+#include "ssrfsortfilterproxymodel.h"
+
 class QLineEdit;
 
 #define RECENTLY_ADDED_DIVESITE 1
 
+bool filter_same_gps_cb (int sourceRow, const QModelIndex& parent);
+
 class LocationInformationModel : public QAbstractTableModel {
 Q_OBJECT
 public:
-- 
2.5.1

From 5e0f144811d1f8e9ba68243deea120d476566889 Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <[email protected]>
Date: Mon, 31 Aug 2015 20:58:31 -0300
Subject: [PATCH 05/11] Fix recursive stack-overflow

only call this when needed, if there's no function set
as callback, always return true.

Signed-off-by: Tomaz Canabrava <[email protected]>
---
 qt-models/ssrfsortfilterproxymodel.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/qt-models/ssrfsortfilterproxymodel.cpp b/qt-models/ssrfsortfilterproxymodel.cpp
index b3f67c1..585f7b5 100644
--- a/qt-models/ssrfsortfilterproxymodel.cpp
+++ b/qt-models/ssrfsortfilterproxymodel.cpp
@@ -14,14 +14,16 @@ bool SsrfSortFilterProxyModel::lessThan(const QModelIndex& source_left, const QM
 
 bool SsrfSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
 {
-	Q_ASSERT(accepts_row);
+	if (!accepts_row)
+		return true;
 	const QAbstractItemModel *self = this;
 	return accepts_row(const_cast<QAbstractItemModel*>(self), source_row, source_parent);
 }
 
 bool SsrfSortFilterProxyModel::filterAcceptsColumn(int source_column, const QModelIndex& source_parent) const
 {
-	Q_ASSERT(accepts_col);
+	if (!accepts_col)
+		return true;
 	const QAbstractItemModel *self = this;
 	return accepts_col(const_cast<QAbstractItemModel*>(self), source_column, source_parent);
 }
-- 
2.5.1

From df39065028f286fe8781fc8c904e4bc51ffcc809 Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <[email protected]>
Date: Mon, 31 Aug 2015 20:59:13 -0300
Subject: [PATCH 06/11] Display dive sites with  same gps as the current

So we can merge them later - currently we are showing
only the ID, ugly - fixing next.

Signed-off-by: Tomaz Canabrava <[email protected]>
---
 qt-models/divelocationmodel.cpp | 9 +++++++--
 qt-models/divelocationmodel.h   | 2 +-
 qt-ui/locationinformation.cpp   | 8 ++++++++
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/qt-models/divelocationmodel.cpp b/qt-models/divelocationmodel.cpp
index abdf69f..ff733f5 100644
--- a/qt-models/divelocationmodel.cpp
+++ b/qt-models/divelocationmodel.cpp
@@ -188,8 +188,13 @@ bool filter_same_gps_cb (QAbstractItemModel *model, int sourceRow, const QModelI
 {
 	int ref_lat = displayed_dive_site.latitude.udeg;
 	int ref_lon = displayed_dive_site.longitude.udeg;
-	QModelIndex curr = model->index(sourceRow, LocationInformationModel::UUID, parent.isValid() ? parent : QModelIndex());
+	QSortFilterProxyModel *self = (QSortFilterProxyModel*) model;
+
+	int ds_uuid = self->sourceModel()->index(sourceRow, LocationInformationModel::UUID, parent).data().toInt();
+	struct dive_site *ds = get_dive_site_by_uuid(ds_uuid);
+
+	if (!ds)
+		return false;
 
-	struct dive_site *ds = get_dive_site_by_uuid(curr.data().toInt());
 	return (ds->latitude.udeg == ref_lat && ds->longitude.udeg == ref_lon);
 }
\ No newline at end of file
diff --git a/qt-models/divelocationmodel.h b/qt-models/divelocationmodel.h
index f40bbd1..83bc97e 100644
--- a/qt-models/divelocationmodel.h
+++ b/qt-models/divelocationmodel.h
@@ -11,7 +11,7 @@ class QLineEdit;
 
 #define RECENTLY_ADDED_DIVESITE 1
 
-bool filter_same_gps_cb (int sourceRow, const QModelIndex& parent);
+bool filter_same_gps_cb (QAbstractItemModel *m, int sourceRow, const QModelIndex& parent);
 
 class LocationInformationModel : public QAbstractTableModel {
 Q_OBJECT
diff --git a/qt-ui/locationinformation.cpp b/qt-ui/locationinformation.cpp
index 6006b18..4a4fff0 100644
--- a/qt-ui/locationinformation.cpp
+++ b/qt-ui/locationinformation.cpp
@@ -30,6 +30,11 @@ LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBo
 	connect(this, SIGNAL(stopFilterDiveSite()), MultiFilterSortModel::instance(), SLOT(stopFilterDiveSite()));
 	connect(ui.geoCodeButton, SIGNAL(clicked()), this, SLOT(reverseGeocode()));
 
+	SsrfSortFilterProxyModel *filter_model = new SsrfSortFilterProxyModel(this);
+	filter_model->setSourceModel(LocationInformationModel::instance());
+	filter_model->setFilterRow(filter_same_gps_cb);
+	ui.diveSiteListView->setModel(filter_model);
+
 #ifndef NO_MARBLE
 	// Globe Management Code.
 	connect(this, &LocationInformationWidget::requestCoordinates,
@@ -133,7 +138,10 @@ void LocationInformationWidget::showEvent(QShowEvent *ev)
 {
 	if (displayed_dive_site.uuid) {
 		updateLabels();
+		QSortFilterProxyModel *m = qobject_cast<QSortFilterProxyModel*>(ui.diveSiteListView->model());
 		emit startFilterDiveSite(displayed_dive_site.uuid);
+		if (m)
+			m->invalidate();
 	}
 	emit requestCoordinates();
 
-- 
2.5.1

From b7e3327be63f8d7450b8f75348ce0c0ef0519141 Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <[email protected]>
Date: Mon, 31 Aug 2015 21:03:31 -0300
Subject: [PATCH 07/11] Show the correct data on the Dive Site List

We where showing the UID, wich didn't made sense.

Signed-off-by: Tomaz Canabrava <[email protected]>
---
 qt-ui/locationInformation.ui  | 3 +++
 qt-ui/locationinformation.cpp | 1 +
 2 files changed, 4 insertions(+)

diff --git a/qt-ui/locationInformation.ui b/qt-ui/locationInformation.ui
index 34cc2d5..e7ab45c 100644
--- a/qt-ui/locationInformation.ui
+++ b/qt-ui/locationInformation.ui
@@ -98,6 +98,9 @@
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
+        <property name="modelColumn">
+         <number>0</number>
+        </property>
        </widget>
       </item>
      </layout>
diff --git a/qt-ui/locationinformation.cpp b/qt-ui/locationinformation.cpp
index 4a4fff0..616a714 100644
--- a/qt-ui/locationinformation.cpp
+++ b/qt-ui/locationinformation.cpp
@@ -34,6 +34,7 @@ LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBo
 	filter_model->setSourceModel(LocationInformationModel::instance());
 	filter_model->setFilterRow(filter_same_gps_cb);
 	ui.diveSiteListView->setModel(filter_model);
+	ui.diveSiteListView->setModelColumn(LocationInformationModel::NAME);
 
 #ifndef NO_MARBLE
 	// Globe Management Code.
-- 
2.5.1

From 259d091740a16d202ebad1fa2b914be1726a6434 Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <[email protected]>
Date: Mon, 31 Aug 2015 21:11:28 -0300
Subject: [PATCH 08/11] Offer the option to merge dive sites.

Almost finishing. :)

Signed-off-by: Tomaz Canabrava <[email protected]>
---
 qt-ui/locationInformation.ui  |  3 +++
 qt-ui/locationinformation.cpp | 15 ++++++++++++++-
 qt-ui/locationinformation.h   |  3 +++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/qt-ui/locationInformation.ui b/qt-ui/locationInformation.ui
index e7ab45c..a2fd635 100644
--- a/qt-ui/locationInformation.ui
+++ b/qt-ui/locationInformation.ui
@@ -98,6 +98,9 @@
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
+        <property name="selectionMode">
+         <enum>QAbstractItemView::MultiSelection</enum>
+        </property>
         <property name="modelColumn">
          <number>0</number>
         </property>
diff --git a/qt-ui/locationinformation.cpp b/qt-ui/locationinformation.cpp
index 616a714..b3acc66 100644
--- a/qt-ui/locationinformation.cpp
+++ b/qt-ui/locationinformation.cpp
@@ -10,6 +10,7 @@
 
 #include <QDebug>
 #include <QShowEvent>
+#include <QItemSelectionModel>
 
 LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBox(parent), modified(false)
 {
@@ -35,7 +36,7 @@ LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBo
 	filter_model->setFilterRow(filter_same_gps_cb);
 	ui.diveSiteListView->setModel(filter_model);
 	ui.diveSiteListView->setModelColumn(LocationInformationModel::NAME);
-
+	ui.diveSiteListView->installEventFilter(this);
 #ifndef NO_MARBLE
 	// Globe Management Code.
 	connect(this, &LocationInformationWidget::requestCoordinates,
@@ -49,6 +50,18 @@ LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBo
 #endif
 }
 
+bool LocationInformationWidget::eventFilter(QObject*, QEvent *ev)
+{
+	if( ev->type() == QEvent::ContextMenu ) {
+		if (ui.diveSiteListView->selectionModel()->selectedIndexes().count() >= 2) {
+			QContextMenuEvent *ctx = (QContextMenuEvent*) ev;
+			QMenu contextMenu;
+			contextMenu.addAction(tr("Merge dive Sites"), this, SLOT(merge_dive_sites()));
+			contextMenu.exec(ctx->globalPos());
+		}
+	}
+}
+
 void LocationInformationWidget::updateLabels()
 {
 	if (displayed_dive_site.name)
diff --git a/qt-ui/locationinformation.h b/qt-ui/locationinformation.h
index 445fd87..2442e16 100644
--- a/qt-ui/locationinformation.h
+++ b/qt-ui/locationinformation.h
@@ -9,6 +9,8 @@ class LocationInformationWidget : public QGroupBox {
 Q_OBJECT
 public:
 	LocationInformationWidget(QWidget *parent = 0);
+	virtual bool eventFilter(QObject*, QEvent*);
+
 protected:
 	void showEvent(QShowEvent *);
 
@@ -35,6 +37,7 @@ signals:
 	void stopFilterDiveSite();
 	void requestCoordinates();
 	void endRequestCoordinates();
+
 private:
 	Ui::LocationInformation ui;
 	bool modified;
-- 
2.5.1

From b8729896abfc864574d6fe596c3b81be8646dac1 Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <[email protected]>
Date: Mon, 31 Aug 2015 21:35:17 -0300
Subject: [PATCH 09/11] UI Code to merge dive sites

Get the Qt data structures and convert to something
that we can use on our c - core.

Signed-off-by: Tomaz Canabrava <[email protected]>
---
 divesite.c                      |  5 +++++
 divesite.h                      |  2 ++
 qt-models/divelocationmodel.cpp |  3 ++-
 qt-models/divelocationmodel.h   |  1 +
 qt-ui/locationinformation.cpp   | 14 +++++++++++++-
 qt-ui/locationinformation.h     |  1 +
 6 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/divesite.c b/divesite.c
index ec552b6..2b5c488 100644
--- a/divesite.c
+++ b/divesite.c
@@ -276,6 +276,11 @@ void clear_dive_site(struct dive_site *ds)
 	free_taxonomy(&ds->taxonomy);
 }
 
+void merge_dive_sites(uint32_t* uuids, int count)
+{
+
+}
+
 uint32_t find_or_create_dive_site_with_name(const char *name, timestamp_t divetime)
 {
 	int i;
diff --git a/divesite.h b/divesite.h
index b0d56f1..1547884 100644
--- a/divesite.h
+++ b/divesite.h
@@ -66,10 +66,12 @@ void copy_dive_site(struct dive_site *orig, struct dive_site *copy);
 void clear_dive_site(struct dive_site *ds);
 unsigned int get_distance(degrees_t lat1, degrees_t lon1, degrees_t lat2, degrees_t lon2);
 uint32_t find_or_create_dive_site_with_name(const char *name, timestamp_t divetime);
+void merge_dive_sites(uint32_t *uuids, int count);
 
 #define INVALID_DIVE_SITE_NAME "development use only - not a valid dive site name"
 
 #ifdef __cplusplus
 }
 #endif
+
 #endif // DIVESITE_H
diff --git a/qt-models/divelocationmodel.cpp b/qt-models/divelocationmodel.cpp
index ff733f5..0ddd0eb 100644
--- a/qt-models/divelocationmodel.cpp
+++ b/qt-models/divelocationmodel.cpp
@@ -109,8 +109,9 @@ QVariant LocationInformationModel::data(const QModelIndex &index, int role) cons
 		else
 			return QVariant();
 	}
+	case UUID_ROLE:
+		return ds->uuid;
 	}
-
 	return QVariant();
 }
 
diff --git a/qt-models/divelocationmodel.h b/qt-models/divelocationmodel.h
index 83bc97e..d5b8705 100644
--- a/qt-models/divelocationmodel.h
+++ b/qt-models/divelocationmodel.h
@@ -17,6 +17,7 @@ class LocationInformationModel : public QAbstractTableModel {
 Q_OBJECT
 public:
 	enum Columns { UUID, NAME, LATITUDE, LONGITUDE, COORDS, DESCRIPTION, NOTES, TAXONOMY_1, TAXONOMY_2, TAXONOMY_3, COLUMNS};
+	enum Roles { UUID_ROLE = Qt::UserRole + 1 };
 	static LocationInformationModel *instance();
 	int columnCount(const QModelIndex &parent) const;
 	int rowCount(const QModelIndex &parent = QModelIndex()) const;
diff --git a/qt-ui/locationinformation.cpp b/qt-ui/locationinformation.cpp
index b3acc66..d029dd2 100644
--- a/qt-ui/locationinformation.cpp
+++ b/qt-ui/locationinformation.cpp
@@ -11,6 +11,7 @@
 #include <QDebug>
 #include <QShowEvent>
 #include <QItemSelectionModel>
+#include <cstdlib>
 
 LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBox(parent), modified(false)
 {
@@ -56,12 +57,23 @@ bool LocationInformationWidget::eventFilter(QObject*, QEvent *ev)
 		if (ui.diveSiteListView->selectionModel()->selectedIndexes().count() >= 2) {
 			QContextMenuEvent *ctx = (QContextMenuEvent*) ev;
 			QMenu contextMenu;
-			contextMenu.addAction(tr("Merge dive Sites"), this, SLOT(merge_dive_sites()));
+			contextMenu.addAction(tr("Merge dive Sites"), this, SLOT(mergeSelectedDiveSites()));
 			contextMenu.exec(ctx->globalPos());
 		}
 	}
 }
 
+void LocationInformationWidget::mergeSelectedDiveSites() {
+	QModelIndexList selection = ui.diveSiteListView->selectionModel()->selectedIndexes();
+	uint32_t *selected_dive_sites = (uint32_t*) malloc(sizeof(u_int32_t) * selection.count());
+	int i = 0;
+	Q_FOREACH(const QModelIndex& idx, selection) {
+		selected_dive_sites[i] = (uint32_t) idx.data(LocationInformationModel::UUID_ROLE).toInt();
+	}
+	merge_dive_sites(selected_dive_sites, i);
+	free(selected_dive_sites);
+}
+
 void LocationInformationWidget::updateLabels()
 {
 	if (displayed_dive_site.name)
diff --git a/qt-ui/locationinformation.h b/qt-ui/locationinformation.h
index 2442e16..080e013 100644
--- a/qt-ui/locationinformation.h
+++ b/qt-ui/locationinformation.h
@@ -27,6 +27,7 @@ public slots:
 	void on_diveSiteName_textChanged(const QString& text);
 	void on_diveSiteNotes_textChanged();
 	void reverseGeocode();
+	void mergeSelectedDiveSites();
 private slots:
 	void updateLabels();
 signals:
-- 
2.5.1

From e88e9a15d9ffd9795a4e83bbc988c25edc0047c2 Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <[email protected]>
Date: Mon, 31 Aug 2015 21:45:31 -0300
Subject: [PATCH 10/11] Merge the dive sites selected.

Wee. :)

Signed-off-by: Tomaz Canabrava <[email protected]>
---
 divesite.c                    | 21 ++++++++++++++++++++-
 divesite.h                    |  2 +-
 qt-ui/locationinformation.cpp |  2 +-
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/divesite.c b/divesite.c
index 2b5c488..96c41d1 100644
--- a/divesite.c
+++ b/divesite.c
@@ -1,6 +1,7 @@
 /* divesite.c */
 #include "divesite.h"
 #include "dive.h"
+#include "divelist.h"
 
 #include <math.h>
 
@@ -276,9 +277,27 @@ void clear_dive_site(struct dive_site *ds)
 	free_taxonomy(&ds->taxonomy);
 }
 
-void merge_dive_sites(uint32_t* uuids, int count)
+void merge_dive_sites(uint32_t ref, uint32_t* uuids, int count)
 {
+	int curr_dive, i;
+	struct dive *d;
+	for(i = 0; i < count; i++){
+		if (uuids[i] == ref)
+			continue;
+
+		for_each_dive(curr_dive, d) {
+			if (d->dive_site_uuid != uuids[i] )
+				continue;
+			d->dive_site_uuid = ref;
+		}
+	}
 
+	for(int i = 0; i < count; i++) {
+		if (uuids[i] == ref)
+			continue;
+		delete_dive_site(uuids[i]);
+	}
+	mark_divelist_changed(true);
 }
 
 uint32_t find_or_create_dive_site_with_name(const char *name, timestamp_t divetime)
diff --git a/divesite.h b/divesite.h
index 1547884..345b504 100644
--- a/divesite.h
+++ b/divesite.h
@@ -66,7 +66,7 @@ void copy_dive_site(struct dive_site *orig, struct dive_site *copy);
 void clear_dive_site(struct dive_site *ds);
 unsigned int get_distance(degrees_t lat1, degrees_t lon1, degrees_t lat2, degrees_t lon2);
 uint32_t find_or_create_dive_site_with_name(const char *name, timestamp_t divetime);
-void merge_dive_sites(uint32_t *uuids, int count);
+void merge_dive_sites(uint32_t ref, uint32_t *uuids, int count);
 
 #define INVALID_DIVE_SITE_NAME "development use only - not a valid dive site name"
 
diff --git a/qt-ui/locationinformation.cpp b/qt-ui/locationinformation.cpp
index d029dd2..9e2821c 100644
--- a/qt-ui/locationinformation.cpp
+++ b/qt-ui/locationinformation.cpp
@@ -70,7 +70,7 @@ void LocationInformationWidget::mergeSelectedDiveSites() {
 	Q_FOREACH(const QModelIndex& idx, selection) {
 		selected_dive_sites[i] = (uint32_t) idx.data(LocationInformationModel::UUID_ROLE).toInt();
 	}
-	merge_dive_sites(selected_dive_sites, i);
+	merge_dive_sites(displayed_dive_site.uuid, selected_dive_sites, i);
 	free(selected_dive_sites);
 }
 
-- 
2.5.1

From 96340eb4297500d8c4337ab7041ef53c36f2a040 Mon Sep 17 00:00:00 2001
From: Tomaz Canabrava <[email protected]>
Date: Mon, 31 Aug 2015 22:01:25 -0300
Subject: [PATCH 11/11] Correctly refresh dive site list

And also show a warning to the user saying that that
action is non-cancelable.

Signed-off-by: Tomaz Canabrava <[email protected]>
---
 divesite.c                    |  2 +-
 qt-ui/locationinformation.cpp | 10 ++++++++++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/divesite.c b/divesite.c
index 96c41d1..a8c5ea4 100644
--- a/divesite.c
+++ b/divesite.c
@@ -292,7 +292,7 @@ void merge_dive_sites(uint32_t ref, uint32_t* uuids, int count)
 		}
 	}
 
-	for(int i = 0; i < count; i++) {
+	for(i = 0; i < count; i++) {
 		if (uuids[i] == ref)
 			continue;
 		delete_dive_site(uuids[i]);
diff --git a/qt-ui/locationinformation.cpp b/qt-ui/locationinformation.cpp
index 9e2821c..1c65015 100644
--- a/qt-ui/locationinformation.cpp
+++ b/qt-ui/locationinformation.cpp
@@ -11,6 +11,7 @@
 #include <QDebug>
 #include <QShowEvent>
 #include <QItemSelectionModel>
+#include <qmessagebox.h>
 #include <cstdlib>
 
 LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBox(parent), modified(false)
@@ -64,13 +65,22 @@ bool LocationInformationWidget::eventFilter(QObject*, QEvent *ev)
 }
 
 void LocationInformationWidget::mergeSelectedDiveSites() {
+	if (QMessageBox::warning(MainWindow::instance(), tr("Merging dive sites"),
+		tr("You are about to merge dive sites, you can't undo that action \n Are you sure you want to continue?"),
+		QMessageBox::Ok, QMessageBox::Cancel) != QMessageBox::Ok)
+		return;
+
 	QModelIndexList selection = ui.diveSiteListView->selectionModel()->selectedIndexes();
 	uint32_t *selected_dive_sites = (uint32_t*) malloc(sizeof(u_int32_t) * selection.count());
 	int i = 0;
 	Q_FOREACH(const QModelIndex& idx, selection) {
 		selected_dive_sites[i] = (uint32_t) idx.data(LocationInformationModel::UUID_ROLE).toInt();
+		i++;
 	}
 	merge_dive_sites(displayed_dive_site.uuid, selected_dive_sites, i);
+	LocationInformationModel::instance()->update();
+	QSortFilterProxyModel *m = (QSortFilterProxyModel *) ui.diveSiteListView->model();
+	m->invalidate();
 	free(selected_dive_sites);
 }
 
-- 
2.5.1

_______________________________________________
subsurface mailing list
[email protected]
http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface

Reply via email to