Dive site: add proximity field to dive site list

Merging dive sites is currently only possible if dive sites are at
the exact same position.

Introduce a field where the user can enter a distance up to which all
dive sites should be listed. These can then be merged.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2019-03-25 22:18:32 +01:00 committed by Dirk Hohndel
parent 22fe0c14e8
commit 8287d86d2b
5 changed files with 63 additions and 5 deletions

View file

@ -11,6 +11,7 @@
#include "core/subsurface-qt/DiveListNotifier.h" #include "core/subsurface-qt/DiveListNotifier.h"
#include "command.h" #include "command.h"
#include "core/taxonomy.h" #include "core/taxonomy.h"
#include "core/settings/qPrefUnit.h"
#include <QDebug> #include <QDebug>
#include <QShowEvent> #include <QShowEvent>
@ -20,7 +21,7 @@
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QScrollBar> #include <QScrollBar>
LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBox(parent), diveSite(nullptr) LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBox(parent), diveSite(nullptr), closeDistance(0)
{ {
ui.setupUi(this); ui.setupUi(this);
ui.diveSiteMessage->setCloseButtonVisible(false); ui.diveSiteMessage->setCloseButtonVisible(false);
@ -35,6 +36,8 @@ LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBo
ui.diveSiteCoordinates->installEventFilter(this); ui.diveSiteCoordinates->installEventFilter(this);
connect(&diveListNotifier, &DiveListNotifier::diveSiteChanged, this, &LocationInformationWidget::diveSiteChanged); connect(&diveListNotifier, &DiveListNotifier::diveSiteChanged, this, &LocationInformationWidget::diveSiteChanged);
connect(qPrefUnits::instance(), &qPrefUnits::unit_systemChanged, this, &LocationInformationWidget::unitsChanged);
unitsChanged();
ui.diveSiteListView->setModel(&filter_model); ui.diveSiteListView->setModel(&filter_model);
ui.diveSiteListView->setModelColumn(LocationInformationModel::NAME); ui.diveSiteListView->setModelColumn(LocationInformationModel::NAME);
@ -112,6 +115,17 @@ void LocationInformationWidget::updateLabels()
ui.locationTags->setText(constructLocationTags(&diveSite->taxonomy, false)); ui.locationTags->setText(constructLocationTags(&diveSite->taxonomy, false));
} }
void LocationInformationWidget::unitsChanged()
{
if (prefs.units.length == units::METERS) {
ui.diveSiteDistanceUnits->setText("m");
ui.diveSiteDistance->setText(QString::number(lrint(closeDistance / 1000.0)));
} else {
ui.diveSiteDistanceUnits->setText("ft");
ui.diveSiteDistance->setText(QString::number(lrint(mm_to_feet(closeDistance))));
}
}
void LocationInformationWidget::diveSiteChanged(struct dive_site *ds, int field) void LocationInformationWidget::diveSiteChanged(struct dive_site *ds, int field)
{ {
if (diveSite != ds) if (diveSite != ds)
@ -222,6 +236,16 @@ void LocationInformationWidget::on_diveSiteNotes_editingFinished()
Command::editDiveSiteNotes(diveSite, ui.diveSiteNotes->toPlainText()); Command::editDiveSiteNotes(diveSite, ui.diveSiteNotes->toPlainText());
} }
void LocationInformationWidget::on_diveSiteDistance_textChanged(const QString &s)
{
bool ok;
uint64_t d = s.toLongLong(&ok);
if (!ok)
d = 0;
closeDistance = prefs.units.length == units::METERS ? d * 1000 : feet_to_mm(d);
filter_model.setDistance(closeDistance);
}
void LocationInformationWidget::reverseGeocode() void LocationInformationWidget::reverseGeocode()
{ {
location_t location = parseGpsText(ui.diveSiteCoordinates->text()); location_t location = parseGpsText(ui.diveSiteCoordinates->text());

View file

@ -27,17 +27,20 @@ public slots:
void on_diveSiteDescription_editingFinished(); void on_diveSiteDescription_editingFinished();
void on_diveSiteName_editingFinished(); void on_diveSiteName_editingFinished();
void on_diveSiteNotes_editingFinished(); void on_diveSiteNotes_editingFinished();
void on_diveSiteDistance_textChanged(const QString &s);
void reverseGeocode(); void reverseGeocode();
void mergeSelectedDiveSites(); void mergeSelectedDiveSites();
private slots: private slots:
void updateLabels(); void updateLabels();
void diveSiteChanged(struct dive_site *ds, int field); void diveSiteChanged(struct dive_site *ds, int field);
void unitsChanged();
private: private:
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
void clearLabels(); void clearLabels();
Ui::LocationInformation ui; Ui::LocationInformation ui;
GPSLocationInformationModel filter_model; GPSLocationInformationModel filter_model;
dive_site *diveSite; dive_site *diveSite;
int64_t closeDistance; // Distance of "close" dive sites in mm
}; };
class DiveLocationFilterProxyModel : public QSortFilterProxyModel { class DiveLocationFilterProxyModel : public QSortFilterProxyModel {

View file

@ -94,9 +94,30 @@
<item row="9" column="0" colspan="5"> <item row="9" column="0" colspan="5">
<widget class="QGroupBox" name="diveSiteGroupBox"> <widget class="QGroupBox" name="diveSiteGroupBox">
<property name="title"> <property name="title">
<string>Dive sites on same coordinates</string> <string>Near dive sites</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>Show dive sites in the range of:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="diveSiteDistance"/>
</item>
<item>
<widget class="QLabel" name="diveSiteDistanceUnits">
<property name="text">
<string></string>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="QListView" name="diveSiteListView"> <widget class="QListView" name="diveSiteListView">
<property name="sizePolicy"> <property name="sizePolicy">

View file

@ -302,15 +302,17 @@ GeoReferencingOptionsModel::GeoReferencingOptionsModel(QObject *parent) : QStrin
bool GPSLocationInformationModel::filterAcceptsRow(int sourceRow, const QModelIndex &parent) const bool GPSLocationInformationModel::filterAcceptsRow(int sourceRow, const QModelIndex &parent) const
{ {
struct dive_site *ds = sourceModel()->index(sourceRow, LocationInformationModel::DIVESITE, parent).data().value<dive_site *>(); struct dive_site *ds = sourceModel()->index(sourceRow, LocationInformationModel::DIVESITE, parent).data().value<dive_site *>();
if (ds == ignoreDs || ds == RECENTLY_ADDED_DIVESITE) if (!ds || ds == ignoreDs || ds == RECENTLY_ADDED_DIVESITE)
return false; return false;
return ds && same_location(&ds->location, &location); return distance <= 0 ? same_location(&ds->location, &location)
: (int64_t)get_distance(&ds->location, &location) * 1000 <= distance; // We need 64 bit to represent distances in mm
} }
GPSLocationInformationModel::GPSLocationInformationModel(QObject *parent) : QSortFilterProxyModel(parent), GPSLocationInformationModel::GPSLocationInformationModel(QObject *parent) : QSortFilterProxyModel(parent),
ignoreDs(nullptr), ignoreDs(nullptr),
location({{0},{0}}) location({{0},{0}}),
distance(0)
{ {
setSourceModel(LocationInformationModel::instance()); setSourceModel(LocationInformationModel::instance());
} }
@ -327,3 +329,9 @@ void GPSLocationInformationModel::setCoordinates(const location_t &locationIn)
location = locationIn; location = locationIn;
invalidate(); invalidate();
} }
void GPSLocationInformationModel::setDistance(int64_t dist)
{
distance = dist;
invalidate();
}

View file

@ -62,11 +62,13 @@ class GPSLocationInformationModel : public QSortFilterProxyModel {
private: private:
const struct dive_site *ignoreDs; const struct dive_site *ignoreDs;
location_t location; location_t location;
int64_t distance;
bool filterAcceptsRow(int sourceRow, const QModelIndex &source_parent) const override; bool filterAcceptsRow(int sourceRow, const QModelIndex &source_parent) const override;
public: public:
GPSLocationInformationModel(QObject *parent = nullptr); GPSLocationInformationModel(QObject *parent = nullptr);
void set(const struct dive_site *ignoreDs, const location_t &); void set(const struct dive_site *ignoreDs, const location_t &);
void setCoordinates(const location_t &); void setCoordinates(const location_t &);
void setDistance(int64_t dist); // Distance from coordinates in mm
}; };
class GeoReferencingOptionsModel : public QStringListModel { class GeoReferencingOptionsModel : public QStringListModel {