Merge remote-tracking branch 'origin/bstoeger-divesites'

This commit is contained in:
Dirk Hohndel 2022-09-23 08:02:54 -07:00
commit 884dbc9d5e
10 changed files with 110 additions and 66 deletions

View file

@ -1,138 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include "TabDiveSite.h"
#include "core/subsurface-qt/divelistnotifier.h"
#include "core/divesite.h"
#include "core/divefilter.h"
#include "qt-models/divelocationmodel.h"
#include "desktop-widgets/mainwindow.h" // to place message box
#include "commands/command.h"
#include <QMessageBox>
TabDiveSite::TabDiveSite(QWidget *parent) : TabBase(parent)
{
ui.setupUi(this);
model = new DiveSiteSortedModel(this);
ui.diveSites->setTitle(tr("Dive sites"));
ui.diveSites->setModel(model);
// Default: sort by name
ui.diveSites->view()->sortByColumn(LocationInformationModel::NAME, Qt::AscendingOrder);
ui.diveSites->view()->setSortingEnabled(true);
ui.diveSites->view()->horizontalHeader()->setSectionResizeMode(LocationInformationModel::NAME, QHeaderView::Stretch);
ui.diveSites->view()->horizontalHeader()->setSectionResizeMode(LocationInformationModel::DESCRIPTION, QHeaderView::Stretch);
ui.diveSites->view()->setSelectionBehavior(QAbstractItemView::SelectRows);
// Show only the first few columns
for (int i = LocationInformationModel::LOCATION; i < LocationInformationModel::COLUMNS; ++i)
ui.diveSites->view()->setColumnHidden(i, true);
connect(ui.diveSites, &TableView::addButtonClicked, this, &TabDiveSite::add);
connect(ui.diveSites, &TableView::itemClicked, this, &TabDiveSite::diveSiteClicked);
connect(ui.diveSites->view()->selectionModel(), &QItemSelectionModel::selectionChanged, this, &TabDiveSite::selectionChanged);
// Subtle: We depend on this slot being executed after the slot in the model.
// This is realized because the model was constructed as a member object and connects in the constructor.
connect(&diveListNotifier, &DiveListNotifier::diveSiteChanged, this, &TabDiveSite::diveSiteChanged);
}
void TabDiveSite::updateData()
{
}
void TabDiveSite::clear()
{
}
void TabDiveSite::diveSiteClicked(const QModelIndex &index)
{
struct dive_site *ds = model->getDiveSite(index);
if (!ds)
return;
switch (index.column()) {
case LocationInformationModel::EDIT:
MainWindow::instance()->editDiveSite(ds);
break;
case LocationInformationModel::REMOVE:
if (ds->dives.nr > 0 &&
QMessageBox::warning(MainWindow::instance(), tr("Delete dive site?"),
tr("This dive site has %n dive(s). Do you really want to delete it?\n", "", ds->dives.nr),
QMessageBox::Yes|QMessageBox::No) == QMessageBox::No)
return;
Command::deleteDiveSites(QVector<dive_site *>{ds});
break;
}
}
void TabDiveSite::add()
{
// This is mighty dirty: We hook into the "dive site added" signal and
// select the name field of the added dive site when the command sends
// the signal. This works only because we know that the model added the
// connection first. Very subtle!
// After the command has finished, the signal is disconnected so that dive
// site names are not selected on regular redo / undo.
connect(&diveListNotifier, &DiveListNotifier::diveSiteAdded, this, &TabDiveSite::diveSiteAdded);
Command::addDiveSite(tr("New dive site"));
disconnect(&diveListNotifier, &DiveListNotifier::diveSiteAdded, this, &TabDiveSite::diveSiteAdded);
}
void TabDiveSite::diveSiteAdded(struct dive_site *, int idx)
{
if (idx < 0)
return;
QModelIndex globalIdx = LocationInformationModel::instance()->index(idx, LocationInformationModel::NAME);
QModelIndex localIdx = model->mapFromSource(globalIdx);
ui.diveSites->view()->setCurrentIndex(localIdx);
ui.diveSites->view()->edit(localIdx);
}
void TabDiveSite::diveSiteChanged(struct dive_site *ds, int field)
{
int idx = get_divesite_idx(ds, &dive_site_table);
if (idx < 0)
return;
QModelIndex globalIdx = LocationInformationModel::instance()->index(idx, field);
QModelIndex localIdx = model->mapFromSource(globalIdx);
ui.diveSites->view()->scrollTo(localIdx);
}
void TabDiveSite::on_purgeUnused_clicked()
{
Command::purgeUnusedDiveSites();
}
void TabDiveSite::on_filterText_textChanged(const QString &text)
{
model->setFilter(text);
}
QVector<dive_site *> TabDiveSite::selectedDiveSites()
{
const QModelIndexList indices = ui.diveSites->view()->selectionModel()->selectedRows();
QVector<dive_site *> sites;
sites.reserve(indices.size());
for (const QModelIndex &idx: indices) {
struct dive_site *ds = model->getDiveSite(idx);
sites.append(ds);
}
return sites;
}
void TabDiveSite::selectionChanged(const QItemSelection &, const QItemSelection &)
{
DiveFilter::instance()->setFilterDiveSite(selectedDiveSites());
}
void TabDiveSite::showEvent(QShowEvent *)
{
// If the user switches to the dive site tab and there was already a selection,
// filter on that selection.
DiveFilter::instance()->startFilterDiveSites(selectedDiveSites());
}
void TabDiveSite::hideEvent(QHideEvent *)
{
// If the user switches to a different tab, stop the dive site filtering
DiveFilter::instance()->stopFilterDiveSites();
}

View file

@ -1,32 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#ifndef TAB_DIVE_SITE_H
#define TAB_DIVE_SITE_H
#include "TabBase.h"
#include "ui_TabDiveSite.h"
class DiveSiteSortedModel;
class TabDiveSite : public TabBase {
Q_OBJECT
public:
TabDiveSite(QWidget *parent = 0);
void updateData() override;
void clear() override;
private slots:
void add();
void diveSiteAdded(struct dive_site *, int idx);
void diveSiteChanged(struct dive_site *ds, int field);
void diveSiteClicked(const QModelIndex &);
void on_purgeUnused_clicked();
void on_filterText_textChanged(const QString &text);
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
private:
Ui::TabDiveSite ui;
DiveSiteSortedModel *model;
QVector<dive_site *> selectedDiveSites();
void hideEvent(QHideEvent *) override;
void showEvent(QShowEvent *) override;
};
#endif

View file

@ -1,73 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TabDiveSite</class>
<widget class="QWidget" name="TabDiveSite">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dive sites</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="layout">
<item>
<widget class="QLabel" name="filterLabel">
<property name="text">
<string>Filter</string>
</property>
<property name="isHeader" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="filterText">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed"/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="purgeUnused">
<property name="text">
<string>Purge unused dive sites</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="TableView" name="diveSites" native="true"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>TableView</class>
<extends>QWidget</extends>
<header>desktop-widgets/tableview.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -13,7 +13,6 @@
#include "TabDiveNotes.h"
#include "TabDivePhotos.h"
#include "TabDiveStatistics.h"
#include "TabDiveSite.h"
#include "core/selection.h"
#include "qt-models/diveplannermodel.h"
@ -43,8 +42,6 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
addTab(extraWidgets.last(), tr("Media"));
extraWidgets << new TabDiveExtraInfo(this);
addTab(extraWidgets.last(), tr("Extra Info"));
extraWidgets << new TabDiveSite(this);
addTab(extraWidgets.last(), tr("Dive sites"));
// make sure we know if this is a light or dark mode
isDark = paletteIsDark(palette());
@ -79,39 +76,30 @@ void MainTab::updateDiveInfo()
if (DivePlannerPointsModel::instance()->isPlanner())
return;
// If there is no current dive, disable all widgets except the last one,
// which is the dive site tab
// TODO: Conceptually, this shouldn't even be a tab here!
// If there is no current dive, disable all widgets.
bool enabled = current_dive != nullptr;
for (int i = 0; i < extraWidgets.size() - 1; ++i)
extraWidgets[i]->setEnabled(enabled);
for (TabBase *widget: extraWidgets)
widget->setEnabled(enabled);
if (current_dive) {
for (TabBase *widget: extraWidgets)
widget->updateData();
// If we're on the dive-site tab, we don't want to switch tab when entering / exiting
// trip mode. The reason is that
// 1) this disrupts the user-experience and
// 2) the filter is reset, potentially erasing the current trip under our feet.
// TODO: Don't hard code tab location!
bool onDiveSiteTab = currentIndex() == 6;
if (single_selected_trip()) {
// Remember the tab selected for last dive but only if we're not on the dive site tab
if (lastSelectedDive && !onDiveSiteTab)
if (lastSelectedDive)
lastTabSelectedDive = currentIndex();
setTabText(0, tr("Trip notes"));
// Recover the tab selected for last dive trip but only if we're not on the dive site tab
if (lastSelectedDive && !onDiveSiteTab)
if (lastSelectedDive)
setCurrentIndex(lastTabSelectedDiveTrip);
lastSelectedDive = false;
} else {
// Remember the tab selected for last dive trip but only if we're not on the dive site tab
if (!lastSelectedDive && !onDiveSiteTab)
if (!lastSelectedDive)
lastTabSelectedDiveTrip = currentIndex();
setTabText(0, tr("Notes"));
// Recover the tab selected for last dive but only if we're not on the dive site tab
if (!lastSelectedDive && !onDiveSiteTab)
if (!lastSelectedDive)
setCurrentIndex(lastTabSelectedDive);
lastSelectedDive = true;
}