mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
profile: port event unhiding to QtQuick
This has UI changes: - The unhiding options are accessed by a field that appears when there are hidden events. - Only event-types of this particular dive are unhidden. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
7c7469b8ab
commit
b099e17042
14 changed files with 98 additions and 50 deletions
|
@ -334,6 +334,12 @@ struct event *get_event(struct divecomputer *dc, int idx)
|
||||||
return &dc->events[idx];
|
return &dc->events[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool divecomputer::has_individually_hidden_events() const
|
||||||
|
{
|
||||||
|
return std::any_of(events.begin(), events.end(),
|
||||||
|
[] (const event &ev) { return ev.hidden; });
|
||||||
|
}
|
||||||
|
|
||||||
void add_extra_data(struct divecomputer *dc, const std::string &key, const std::string &value)
|
void add_extra_data(struct divecomputer *dc, const std::string &key, const std::string &value)
|
||||||
{
|
{
|
||||||
if (key == "Serial") {
|
if (key == "Serial") {
|
||||||
|
|
|
@ -44,6 +44,8 @@ struct divecomputer {
|
||||||
std::vector<struct event> events;
|
std::vector<struct event> events;
|
||||||
std::vector<struct extra_data> extra_data;
|
std::vector<struct extra_data> extra_data;
|
||||||
|
|
||||||
|
bool has_individually_hidden_events() const;
|
||||||
|
|
||||||
divecomputer();
|
divecomputer();
|
||||||
~divecomputer();
|
~divecomputer();
|
||||||
divecomputer(const divecomputer &);
|
divecomputer(const divecomputer &);
|
||||||
|
|
|
@ -64,6 +64,8 @@ public:
|
||||||
const struct event *next(); // nullptr -> end
|
const struct event *next(); // nullptr -> end
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern bool has_individually_hidden_events(const struct divecomputer *dc);
|
||||||
|
|
||||||
/* Get gasmixes at increasing timestamps. */
|
/* Get gasmixes at increasing timestamps. */
|
||||||
class gasmix_loop {
|
class gasmix_loop {
|
||||||
const struct dive &dive;
|
const struct dive &dive;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
#include "eventtype.h"
|
#include "eventtype.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
#include "divecomputer.h"
|
||||||
#include "gettextfromc.h"
|
#include "gettextfromc.h"
|
||||||
#include "subsurface-string.h"
|
#include "subsurface-string.h"
|
||||||
|
|
||||||
|
@ -42,9 +43,9 @@ void remember_event_type(const struct event *ev)
|
||||||
event_types.push_back(std::move(type));
|
event_types.push_back(std::move(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_event_type_hidden(const struct event *ev)
|
bool is_event_type_hidden(const struct event &ev)
|
||||||
{
|
{
|
||||||
auto it = std::find(event_types.begin(), event_types.end(), ev);
|
auto it = std::find(event_types.begin(), event_types.end(), &ev);
|
||||||
return it != event_types.end() && !it->plot;
|
return it != event_types.end() && !it->plot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,10 +56,18 @@ void hide_event_type(const struct event *ev)
|
||||||
it->plot = false;
|
it->plot = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_all_event_types()
|
static bool has_event_type(const divecomputer &dc, const event_type &et)
|
||||||
{
|
{
|
||||||
for (event_type &e: event_types)
|
return std::any_of(dc.events.begin(), dc.events.end(), [&et] (const event &ev)
|
||||||
e.plot = true;
|
{ return ev.name == et.name && ev.get_severity() == et.severity; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_all_event_types(const divecomputer &dc)
|
||||||
|
{
|
||||||
|
for (event_type &e: event_types) {
|
||||||
|
if (!e.plot && has_event_type(dc, e))
|
||||||
|
e.plot = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_event_type(int idx)
|
void show_event_type(int idx)
|
||||||
|
@ -74,11 +83,12 @@ bool any_event_types_hidden()
|
||||||
[] (const event_type &e) { return !e.plot; });
|
[] (const event_type &e) { return !e.plot; });
|
||||||
}
|
}
|
||||||
|
|
||||||
extern std::vector<int> hidden_event_types()
|
std::vector<int> hidden_event_types(const struct divecomputer &dc)
|
||||||
{
|
{
|
||||||
std::vector<int> res;
|
std::vector<int> res;
|
||||||
for (size_t i = 0; i < event_types.size(); ++i) {
|
for (size_t i = 0; i < event_types.size(); ++i) {
|
||||||
if (!event_types[i].plot)
|
const event_type &e = event_types[i];
|
||||||
|
if (!e.plot && has_event_type(dc, e))
|
||||||
res.push_back(i);
|
res.push_back(i);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -8,12 +8,12 @@
|
||||||
|
|
||||||
extern void clear_event_types();
|
extern void clear_event_types();
|
||||||
extern void remember_event_type(const struct event *ev);
|
extern void remember_event_type(const struct event *ev);
|
||||||
extern bool is_event_type_hidden(const struct event *ev);
|
extern bool is_event_type_hidden(const struct event &ev);
|
||||||
extern void hide_event_type(const struct event *ev);
|
extern void hide_event_type(const struct event *ev);
|
||||||
extern void show_all_event_types();
|
extern void show_all_event_types(const struct divecomputer &dc);
|
||||||
extern void show_event_type(int idx);
|
extern void show_event_type(int idx);
|
||||||
extern bool any_event_types_hidden();
|
extern bool any_event_types_hidden();
|
||||||
extern std::vector<int> hidden_event_types();
|
extern std::vector<int> hidden_event_types(const struct divecomputer &dc);
|
||||||
extern QString event_type_name(const event &ev);
|
extern QString event_type_name(const event &ev);
|
||||||
extern QString event_type_name(int idx);
|
extern QString event_type_name(int idx);
|
||||||
|
|
||||||
|
|
|
@ -205,7 +205,7 @@ void DiveEventItem::recalculatePos()
|
||||||
hide();
|
hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setVisible(!ev.hidden && !is_event_type_hidden(&ev));
|
setVisible(!ev.hidden && !is_event_type_hidden(ev));
|
||||||
double x = hAxis->posAtValue(ev.time.seconds);
|
double x = hAxis->posAtValue(ev.time.seconds);
|
||||||
double y = vAxis->posAtValue(depth);
|
double y = vAxis->posAtValue(depth);
|
||||||
setPos(x, y);
|
setPos(x, y);
|
||||||
|
|
|
@ -90,6 +90,11 @@ double DiveTextItem::fontHeight(double dpr, double scale)
|
||||||
return (double)fm.height();
|
return (double)fm.height();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double DiveTextItem::width() const
|
||||||
|
{
|
||||||
|
return boundingRect().width();
|
||||||
|
}
|
||||||
|
|
||||||
double DiveTextItem::height() const
|
double DiveTextItem::height() const
|
||||||
{
|
{
|
||||||
return fontHeight(dpr, scale) + outlineSize * dpr;
|
return fontHeight(dpr, scale) + outlineSize * dpr;
|
||||||
|
|
|
@ -17,6 +17,7 @@ public:
|
||||||
const QString &text();
|
const QString &text();
|
||||||
static double fontHeight(double dpr, double scale);
|
static double fontHeight(double dpr, double scale);
|
||||||
static std::pair<double, double> getLabelSize(double dpr, double scale, const QString &label);
|
static std::pair<double, double> getLabelSize(double dpr, double scale, const QString &label);
|
||||||
|
double width() const;
|
||||||
double height() const;
|
double height() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "core/device.h"
|
#include "core/device.h"
|
||||||
#include "core/divecomputer.h"
|
#include "core/divecomputer.h"
|
||||||
#include "core/event.h"
|
#include "core/event.h"
|
||||||
|
#include "core/eventtype.h"
|
||||||
#include "core/pref.h"
|
#include "core/pref.h"
|
||||||
#include "core/profile.h"
|
#include "core/profile.h"
|
||||||
#include "core/qthelper.h" // for decoMode()
|
#include "core/qthelper.h" // for decoMode()
|
||||||
|
@ -95,6 +96,7 @@ ProfileScene::ProfileScene(double dpr, bool printMode, bool isGrayscale) :
|
||||||
[](const plot_data &item) { return 0.0; }, // unused
|
[](const plot_data &item) { return 0.0; }, // unused
|
||||||
1, dpr)),
|
1, dpr)),
|
||||||
diveComputerText(new DiveTextItem(dpr, 1.0, Qt::AlignRight | Qt::AlignTop, nullptr)),
|
diveComputerText(new DiveTextItem(dpr, 1.0, Qt::AlignRight | Qt::AlignTop, nullptr)),
|
||||||
|
eventsHiddenText(new DiveTextItem(dpr, 1.0, Qt::AlignRight | Qt::AlignTop, nullptr)),
|
||||||
reportedCeiling(createItem<DiveReportedCeiling>(*profileYAxis,
|
reportedCeiling(createItem<DiveReportedCeiling>(*profileYAxis,
|
||||||
[](const plot_data &item) { return (double)item.ceiling; },
|
[](const plot_data &item) { return (double)item.ceiling; },
|
||||||
1, dpr)),
|
1, dpr)),
|
||||||
|
@ -143,6 +145,7 @@ ProfileScene::ProfileScene(double dpr, bool printMode, bool isGrayscale) :
|
||||||
|
|
||||||
// Add items to scene
|
// Add items to scene
|
||||||
addItem(diveComputerText);
|
addItem(diveComputerText);
|
||||||
|
addItem(eventsHiddenText);
|
||||||
addItem(tankItem);
|
addItem(tankItem);
|
||||||
addItem(decoModelParameters);
|
addItem(decoModelParameters);
|
||||||
addItem(profileYAxis);
|
addItem(profileYAxis);
|
||||||
|
@ -156,6 +159,8 @@ ProfileScene::ProfileScene(double dpr, bool printMode, bool isGrayscale) :
|
||||||
|
|
||||||
for (AbstractProfilePolygonItem *item: profileItems)
|
for (AbstractProfilePolygonItem *item: profileItems)
|
||||||
addItem(item);
|
addItem(item);
|
||||||
|
|
||||||
|
eventsHiddenText->set(tr("Hidden events!"), getColor(TIME_TEXT, isGrayscale));
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfileScene::~ProfileScene()
|
ProfileScene::~ProfileScene()
|
||||||
|
@ -287,8 +292,10 @@ void ProfileScene::updateAxes(bool diveHasHeartBeat, bool simplified)
|
||||||
profileYAxis->setGridIsMultipleOfThree( qPrefDisplay::three_m_based_grid() );
|
profileYAxis->setGridIsMultipleOfThree( qPrefDisplay::three_m_based_grid() );
|
||||||
|
|
||||||
// Place the fixed dive computer text at the bottom
|
// Place the fixed dive computer text at the bottom
|
||||||
double bottomBorder = sceneRect().height() - diveComputerText->height() - 2.0 * dpr * diveComputerTextBorder;
|
double bottomTextHeight = std::max(diveComputerText->height(), eventsHiddenText->height());
|
||||||
diveComputerText->setPos(0.0, bottomBorder + dpr * diveComputerTextBorder);
|
double bottomBorder = sceneRect().height() - bottomTextHeight - 2.0 * dpr * diveComputerTextBorder;
|
||||||
|
diveComputerText->setPos(0.0, round(bottomBorder + dpr * diveComputerTextBorder));
|
||||||
|
eventsHiddenText->setPos(width - dpr * diveComputerTextBorder - eventsHiddenText->width(), bottomBorder + dpr * diveComputerTextBorder);
|
||||||
|
|
||||||
double topBorder = 0.0;
|
double topBorder = 0.0;
|
||||||
|
|
||||||
|
@ -372,6 +379,12 @@ bool ProfileScene::pointOnDiveComputerText(const QPointF &point) const
|
||||||
return diveComputerText->boundingRect().contains(point - diveComputerText->pos());
|
return diveComputerText->boundingRect().contains(point - diveComputerText->pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProfileScene::pointOnEventsHiddenText(const QPointF &point) const
|
||||||
|
{
|
||||||
|
return eventsHiddenText->isVisible() &&
|
||||||
|
eventsHiddenText->boundingRect().contains(point - eventsHiddenText->pos());
|
||||||
|
}
|
||||||
|
|
||||||
static double max_gas(const plot_info &pi, double gas_pressures::*gas)
|
static double max_gas(const plot_info &pi, double gas_pressures::*gas)
|
||||||
{
|
{
|
||||||
double ret = -1;
|
double ret = -1;
|
||||||
|
@ -525,9 +538,12 @@ void ProfileScene::plotDive(const struct dive *dIn, int dcIn, int animSpeed, boo
|
||||||
eventItems.clear();
|
eventItems.clear();
|
||||||
struct gasmix lastgasmix = d->get_gasmix_at_time(*currentdc, 1_sec);
|
struct gasmix lastgasmix = d->get_gasmix_at_time(*currentdc, 1_sec);
|
||||||
|
|
||||||
|
bool has_hidden_events = false;
|
||||||
for (auto [idx, event]: enumerated_range(currentdc->events)) {
|
for (auto [idx, event]: enumerated_range(currentdc->events)) {
|
||||||
if (event.hidden)
|
if (event.hidden || is_event_type_hidden(event)) {
|
||||||
|
has_hidden_events = true;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
// if print mode is selected only draw headings, SP change, gas events or bookmark event
|
// if print mode is selected only draw headings, SP change, gas events or bookmark event
|
||||||
if (printMode) {
|
if (printMode) {
|
||||||
if (event.name.empty() ||
|
if (event.name.empty() ||
|
||||||
|
@ -547,6 +563,7 @@ void ProfileScene::plotDive(const struct dive *dIn, int dcIn, int animSpeed, boo
|
||||||
if (event.is_gaschange())
|
if (event.is_gaschange())
|
||||||
lastgasmix = d->get_gasmix_from_event(event);
|
lastgasmix = d->get_gasmix_from_event(event);
|
||||||
}
|
}
|
||||||
|
eventsHiddenText->setVisible(has_hidden_events);
|
||||||
|
|
||||||
QString dcText = QString::fromStdString(get_dc_nickname(currentdc));
|
QString dcText = QString::fromStdString(get_dc_nickname(currentdc));
|
||||||
if (is_dc_planner(currentdc))
|
if (is_dc_planner(currentdc))
|
||||||
|
|
|
@ -38,6 +38,7 @@ public:
|
||||||
void clear();
|
void clear();
|
||||||
bool pointOnProfile(const QPointF &point) const;
|
bool pointOnProfile(const QPointF &point) const;
|
||||||
bool pointOnDiveComputerText(const QPointF &point) const;
|
bool pointOnDiveComputerText(const QPointF &point) const;
|
||||||
|
bool pointOnEventsHiddenText(const QPointF &point) const;
|
||||||
void anim(double fraction); // Called by the animation with 0.0-1.0 (start to stop).
|
void anim(double fraction); // Called by the animation with 0.0-1.0 (start to stop).
|
||||||
// Can be compared with literal 1.0 to determine "end" state.
|
// Can be compared with literal 1.0 to determine "end" state.
|
||||||
|
|
||||||
|
@ -96,6 +97,7 @@ private:
|
||||||
DiveGasPressureItem *gasPressureItem;
|
DiveGasPressureItem *gasPressureItem;
|
||||||
std::vector<std::unique_ptr<DiveEventItem>> eventItems;
|
std::vector<std::unique_ptr<DiveEventItem>> eventItems;
|
||||||
DiveTextItem *diveComputerText;
|
DiveTextItem *diveComputerText;
|
||||||
|
DiveTextItem *eventsHiddenText;
|
||||||
DiveReportedCeiling *reportedCeiling;
|
DiveReportedCeiling *reportedCeiling;
|
||||||
PartialPressureGasItem *pn2GasItem;
|
PartialPressureGasItem *pn2GasItem;
|
||||||
PartialPressureGasItem *pheGasItem;
|
PartialPressureGasItem *pheGasItem;
|
||||||
|
|
|
@ -509,6 +509,16 @@ static QString formatCylinderDescription(int i, const cylinder_t &cylinder)
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProfileView::unhideEvents()
|
||||||
|
{
|
||||||
|
if (!d)
|
||||||
|
return;
|
||||||
|
struct divecomputer *currentdc = mutable_dive()->get_dc(dc);
|
||||||
|
for (auto &ev: currentdc->events)
|
||||||
|
ev.hidden = false;
|
||||||
|
replot();
|
||||||
|
}
|
||||||
|
|
||||||
void ProfileView::mousePressEvent(QMouseEvent *event)
|
void ProfileView::mousePressEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
// Handle dragging of items
|
// Handle dragging of items
|
||||||
|
@ -541,6 +551,34 @@ void ProfileView::mousePressEvent(QMouseEvent *event)
|
||||||
return execMenu(m, event->globalPos());
|
return execMenu(m, event->globalPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open context menu for event unhiding
|
||||||
|
if (d && profileScene->pointOnEventsHiddenText(event->pos())) {
|
||||||
|
std::vector<MenuEntry> m;
|
||||||
|
const struct divecomputer *currentdc = d->get_dc(dc);
|
||||||
|
if (currentdc->has_individually_hidden_events()) {
|
||||||
|
m.emplace_back(tr("Unhide individually hidden events of this dive"), [this, ¤tdc] {
|
||||||
|
unhideEvents();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
std::vector<int> types = hidden_event_types(*currentdc);
|
||||||
|
if (!types.empty()) {
|
||||||
|
std::vector<MenuEntry> m2;
|
||||||
|
for (int i: types) {
|
||||||
|
m2.emplace_back(event_type_name(i), [this, i]() {
|
||||||
|
show_event_type(i);
|
||||||
|
replot();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (types.size() > 1) {
|
||||||
|
m2.emplace_back(tr("All types"), [this, currentdc]() {
|
||||||
|
show_all_event_types(*currentdc);
|
||||||
|
replot();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
m.emplace_back(tr("Unhide event type"), std::move(m2));
|
||||||
|
}
|
||||||
|
return execMenu(m, event->globalPos());
|
||||||
|
}
|
||||||
DiveEventItem *item = profileScene->eventAtPosition(event->pos());
|
DiveEventItem *item = profileScene->eventAtPosition(event->pos());
|
||||||
if (d && item) {
|
if (d && item) {
|
||||||
std::vector<MenuEntry> m;
|
std::vector<MenuEntry> m;
|
||||||
|
|
|
@ -142,6 +142,7 @@ private:
|
||||||
void hideEvent(DiveEventItem &item);
|
void hideEvent(DiveEventItem &item);
|
||||||
void hideEventType(DiveEventItem &item);
|
void hideEventType(DiveEventItem &item);
|
||||||
void removeEvent(DiveEventItem &item);
|
void removeEvent(DiveEventItem &item);
|
||||||
|
void unhideEvents();
|
||||||
|
|
||||||
// The list of pictures in this plot. The pictures are sorted by offset in seconds.
|
// The list of pictures in this plot. The pictures are sorted by offset in seconds.
|
||||||
// For the same offset, sort by filename.
|
// For the same offset, sort by filename.
|
||||||
|
|
|
@ -370,43 +370,9 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event)
|
||||||
changeMode->addAction(gettextFromC::tr(divemode_text_ui[PSCR]),
|
changeMode->addAction(gettextFromC::tr(divemode_text_ui[PSCR]),
|
||||||
[this, seconds](){ addDivemodeSwitch(seconds, PSCR); });
|
[this, seconds](){ addDivemodeSwitch(seconds, PSCR); });
|
||||||
|
|
||||||
if (any_event_types_hidden()) {
|
|
||||||
QMenu *m2 = m.addMenu(tr("Unhide event type"));
|
|
||||||
for (int i: hidden_event_types()) {
|
|
||||||
m2->addAction(event_type_name(i), [this, i]() {
|
|
||||||
show_event_type(i);
|
|
||||||
replot();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
m2->addAction(tr("All event types"), this, &ProfileWidget2::unhideEventTypes);
|
|
||||||
}
|
|
||||||
const struct divecomputer *currentdc = d->get_dc(dc);
|
|
||||||
if (currentdc && std::any_of(currentdc->events.begin(), currentdc->events.end(),
|
|
||||||
[] (auto &ev) { return ev.hidden; }))
|
|
||||||
m.addAction(tr("Unhide individually hidden events of this dive"), this, &ProfileWidget2::unhideEvents);
|
|
||||||
m.exec(event->globalPos());
|
m.exec(event->globalPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileWidget2::unhideEvents()
|
|
||||||
{
|
|
||||||
if (!d)
|
|
||||||
return;
|
|
||||||
struct divecomputer *currentdc = mutable_dive()->get_dc(dc);
|
|
||||||
if (!currentdc)
|
|
||||||
return;
|
|
||||||
for (auto &ev: currentdc->events)
|
|
||||||
ev.hidden = false;
|
|
||||||
for (DiveEventItem *item: profileScene->eventItems)
|
|
||||||
item->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileWidget2::unhideEventTypes()
|
|
||||||
{
|
|
||||||
show_all_event_types();
|
|
||||||
|
|
||||||
replot();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProfileWidget2::addBookmark(int seconds)
|
void ProfileWidget2::addBookmark(int seconds)
|
||||||
{
|
{
|
||||||
if (d)
|
if (d)
|
||||||
|
|
|
@ -109,8 +109,6 @@ private:
|
||||||
void addSetpointChange(int seconds);
|
void addSetpointChange(int seconds);
|
||||||
void removeEvent(DiveEventItem *item);
|
void removeEvent(DiveEventItem *item);
|
||||||
void editName(DiveEventItem *item);
|
void editName(DiveEventItem *item);
|
||||||
void unhideEvents();
|
|
||||||
void unhideEventTypes();
|
|
||||||
void makeFirstDC();
|
void makeFirstDC();
|
||||||
void deleteCurrentDC();
|
void deleteCurrentDC();
|
||||||
void splitCurrentDC();
|
void splitCurrentDC();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue