mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-30 22:20:21 +00:00
23cf85e89c
During edit mode, we could get spurious reload() requests owing to tabs being hidden. This led to undefined behavior: In some cases entering dive site edit mode would show all dive sites, in some only the dive site of the currently edited dive. Therefore, refuse to reload the map while in edit mode. The corresponding flag already exists. Partially fixes #2076 Reported-by: Doug Junkins <junkins@foghead.com> Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
143 lines
3.8 KiB
C++
143 lines
3.8 KiB
C++
// SPDX-License-Identifier: GPL-2.0
|
|
#include <QQmlContext>
|
|
#include <QDebug>
|
|
#include <QQuickItem>
|
|
#include <QModelIndex>
|
|
|
|
#include "mapwidget.h"
|
|
#include "core/divesite.h"
|
|
#include "core/subsurface-qt/DiveListNotifier.h"
|
|
#include "map-widget/qmlmapwidgethelper.h"
|
|
#include "qt-models/maplocationmodel.h"
|
|
#include "qt-models/divelocationmodel.h"
|
|
#include "mainwindow.h"
|
|
#include "divelistview.h"
|
|
#include "command.h"
|
|
|
|
static const QUrl urlMapWidget = QUrl(QStringLiteral("qrc:/qml/MapWidget.qml"));
|
|
static const QUrl urlMapWidgetError = QUrl(QStringLiteral("qrc:/qml/MapWidgetError.qml"));
|
|
static bool isReady = false;
|
|
static bool skipReload = false;
|
|
|
|
#define CHECK_IS_READY_RETURN_VOID() \
|
|
if (!isReady) return
|
|
|
|
MapWidget *MapWidget::m_instance = NULL;
|
|
|
|
MapWidget::MapWidget(QWidget *parent) : QQuickWidget(parent)
|
|
{
|
|
m_rootItem = nullptr;
|
|
m_mapHelper = nullptr;
|
|
setResizeMode(QQuickWidget::SizeRootObjectToView);
|
|
connect(this, &QQuickWidget::statusChanged, this, &MapWidget::doneLoading);
|
|
connect(&diveListNotifier, &DiveListNotifier::diveSiteChanged, this, &MapWidget::diveSiteChanged);
|
|
setSource(urlMapWidget);
|
|
}
|
|
|
|
void MapWidget::doneLoading(QQuickWidget::Status status)
|
|
{
|
|
// the default map widget QML failed; load the error QML.
|
|
if (source() == urlMapWidget && status != QQuickWidget::Ready) {
|
|
qDebug() << urlMapWidget << "failed to load with status:" << status;
|
|
setSource(urlMapWidgetError);
|
|
return;
|
|
} else if (source() == urlMapWidgetError) { // the error QML finished loading.
|
|
return;
|
|
}
|
|
|
|
isReady = true;
|
|
m_rootItem = qobject_cast<QQuickItem *>(rootObject());
|
|
m_mapHelper = rootObject()->findChild<MapWidgetHelper *>();
|
|
connect(m_mapHelper, SIGNAL(selectedDivesChanged(QList<int>)),
|
|
this, SLOT(selectedDivesChanged(QList<int>)));
|
|
connect(m_mapHelper, &MapWidgetHelper::coordinatesChanged, this, &MapWidget::coordinatesChanged);
|
|
}
|
|
|
|
void MapWidget::centerOnSelectedDiveSite()
|
|
{
|
|
CHECK_IS_READY_RETURN_VOID();
|
|
if (!skipReload)
|
|
m_mapHelper->centerOnSelectedDiveSite();
|
|
}
|
|
|
|
void MapWidget::centerOnDiveSite(struct dive_site *ds)
|
|
{
|
|
CHECK_IS_READY_RETURN_VOID();
|
|
if (!skipReload)
|
|
m_mapHelper->centerOnDiveSite(ds);
|
|
}
|
|
|
|
void MapWidget::centerOnIndex(const QModelIndex& idx)
|
|
{
|
|
CHECK_IS_READY_RETURN_VOID();
|
|
dive_site *ds = idx.model()->index(idx.row(), LocationInformationModel::DIVESITE).data().value<dive_site *>();
|
|
if (!ds || ds == RECENTLY_ADDED_DIVESITE || !dive_site_has_gps_location(ds))
|
|
centerOnSelectedDiveSite();
|
|
else
|
|
centerOnDiveSite(ds);
|
|
}
|
|
|
|
void MapWidget::repopulateLabels()
|
|
{
|
|
CHECK_IS_READY_RETURN_VOID();
|
|
m_mapHelper->reloadMapLocations();
|
|
}
|
|
|
|
void MapWidget::reload()
|
|
{
|
|
CHECK_IS_READY_RETURN_VOID();
|
|
if (!skipReload)
|
|
m_mapHelper->reloadMapLocations();
|
|
}
|
|
|
|
void MapWidget::endGetDiveCoordinates()
|
|
{
|
|
CHECK_IS_READY_RETURN_VOID();
|
|
|
|
skipReload = false;
|
|
m_mapHelper->exitEditMode();
|
|
}
|
|
|
|
void MapWidget::prepareForGetDiveCoordinates(struct dive_site *ds)
|
|
{
|
|
CHECK_IS_READY_RETURN_VOID();
|
|
m_mapHelper->enterEditMode(ds);
|
|
|
|
// Ignore any reload signals during edit mode to avoid showing all flags when in edit mode.
|
|
// This can happen for example when the filter is reset.
|
|
skipReload = true;
|
|
}
|
|
|
|
void MapWidget::selectedDivesChanged(QList<int> list)
|
|
{
|
|
CHECK_IS_READY_RETURN_VOID();
|
|
skipReload = true;
|
|
MainWindow::instance()->diveList->unselectDives();
|
|
if (!list.empty())
|
|
MainWindow::instance()->diveList->selectDives(list);
|
|
skipReload = false;
|
|
}
|
|
|
|
void MapWidget::coordinatesChanged(struct dive_site *ds, const location_t &location)
|
|
{
|
|
Command::editDiveSiteLocation(ds, location);
|
|
}
|
|
|
|
void MapWidget::diveSiteChanged(struct dive_site *ds, int field)
|
|
{
|
|
CHECK_IS_READY_RETURN_VOID();
|
|
if (field == LocationInformationModel::LOCATION)
|
|
m_mapHelper->updateDiveSiteCoordinates(ds, ds->location);
|
|
}
|
|
|
|
MapWidget::~MapWidget()
|
|
{
|
|
m_instance = NULL;
|
|
}
|
|
|
|
MapWidget *MapWidget::instance()
|
|
{
|
|
if (m_instance == NULL)
|
|
m_instance = new MapWidget();
|
|
return m_instance;
|
|
}
|