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:
Berthold Stoeger 2024-03-01 13:02:35 +01:00
parent bd089f3556
commit 0bf1d35a4b
13 changed files with 103 additions and 49 deletions

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include "event.h"
#include "eventtype.h"
#include "divecomputer.h"
#include "subsurface-string.h"
#include <string.h>
@ -116,3 +117,12 @@ extern enum event_severity get_event_severity(const struct event *ev)
return EVENT_SEVERITY_NONE;
}
}
extern bool has_individually_hidden_events(const struct divecomputer *dc)
{
for (const struct event *ev = dc->events; ev; ev = ev->next) {
if (ev->hidden)
return true;
}
return false;
}

View File

@ -8,6 +8,8 @@
#include <libdivecomputer/parser.h>
struct divecomputer;
#ifdef __cplusplus
extern "C" {
#endif
@ -55,6 +57,7 @@ extern struct event *create_event(unsigned int time, int type, int flags, int va
extern struct event *clone_event_rename(const struct event *ev, const char *name);
extern bool same_event(const struct event *a, const struct event *b);
extern enum event_severity get_event_severity(const struct event *ev);
extern bool has_individually_hidden_events(const struct divecomputer *dc);
/* Since C doesn't have parameter-based overloading, two versions of get_next_event. */
extern const struct event *get_next_event(const struct event *event, const char *name);

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include "eventtype.h"
#include "event.h"
#include "divecomputer.h"
#include "gettextfromc.h"
#include "subsurface-string.h"
@ -55,10 +56,22 @@ extern "C" void hide_event_type(const struct event *ev)
it->plot = false;
}
extern "C" void show_all_event_types()
static bool has_event_type(const divecomputer *dc, const event_type et)
{
for (event_type &e: event_types)
e.plot = true;
for (const event *ev = dc->events; ev; ev = ev->next) {
if (ev->name == et.name &&
get_event_severity(ev) == et.severity)
return true;
}
return false;
}
extern "C" 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;
}
}
extern "C" void show_event_type(int idx)
@ -68,17 +81,12 @@ extern "C" void show_event_type(int idx)
event_types[idx].plot = true;
}
extern "C" bool any_event_types_hidden()
{
return std::any_of(event_types.begin(), event_types.end(),
[] (const event_type &e) { return !e.plot; });
}
extern std::vector<int> hidden_event_types()
extern std::vector<int> hidden_event_types(const divecomputer *dc)
{
std::vector<int> res;
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);
}
return res;

View File

@ -3,6 +3,8 @@
#ifndef EVENTNAME_H
#define EVENTNAME_H
struct divecomputer;
#ifdef __cplusplus
extern "C" {
#endif
@ -11,9 +13,8 @@ extern void clear_event_types(void);
extern void remember_event_type(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 show_all_event_types();
extern void show_all_event_types(const struct divecomputer *dc);
extern void show_event_type(int idx);
extern bool any_event_types_hidden();
#ifdef __cplusplus
}
@ -22,7 +23,7 @@ extern bool any_event_types_hidden();
#include <vector>
#include <QString>
extern std::vector<int> hidden_event_types();
extern std::vector<int> hidden_event_types(const divecomputer *dc);
QString event_type_name(const event *ev);
QString event_type_name(int idx);

View File

@ -4,7 +4,6 @@
#include "profile-widget/divepixmapcache.h"
#include "profile-widget/animationfunctions.h"
#include "core/event.h"
#include "core/eventtype.h"
#include "core/format.h"
#include "core/profile.h"
#include "core/gettextfromc.h"
@ -217,7 +216,6 @@ void DiveEventItem::recalculatePos()
hide();
return;
}
setVisible(!ev->hidden && !is_event_type_hidden(ev));
double x = hAxis->posAtValue(ev->time.seconds);
double y = vAxis->posAtValue(depth);
setPos(x, y);

View File

@ -90,6 +90,11 @@ double DiveTextItem::fontHeight(double dpr, double scale)
return (double)fm.height();
}
double DiveTextItem::width() const
{
return boundingRect().width();
}
double DiveTextItem::height() const
{
return fontHeight(dpr, scale) + outlineSize * dpr;

View File

@ -17,6 +17,7 @@ public:
const QString &text();
static double fontHeight(double dpr, double scale);
static std::pair<double, double> getLabelSize(double dpr, double scale, const QString &label);
double width() const;
double height() const;
private:

View File

@ -9,6 +9,7 @@
#include "tankitem.h"
#include "core/device.h"
#include "core/event.h"
#include "core/eventtype.h"
#include "core/pref.h"
#include "core/profile.h"
#include "core/qthelper.h" // for decoMode()
@ -92,6 +93,7 @@ ProfileScene::ProfileScene(double dpr, bool printMode, bool isGrayscale) :
[](const plot_data &item) { return 0.0; }, // unused
1, dpr)),
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,
[](const plot_data &item) { return (double)item.ceiling; },
1, dpr)),
@ -142,6 +144,7 @@ ProfileScene::ProfileScene(double dpr, bool printMode, bool isGrayscale) :
// Add items to scene
addItem(diveComputerText);
addItem(eventsHiddenText);
addItem(tankItem);
addItem(decoModelParameters);
addItem(profileYAxis);
@ -155,6 +158,8 @@ ProfileScene::ProfileScene(double dpr, bool printMode, bool isGrayscale) :
for (AbstractProfilePolygonItem *item: profileItems)
addItem(item);
eventsHiddenText->set(tr("Hidden events!"), getColor(TIME_TEXT, isGrayscale));
}
ProfileScene::~ProfileScene()
@ -287,8 +292,10 @@ void ProfileScene::updateAxes(bool diveHasHeartBeat, bool simplified)
profileYAxis->setGridIsMultipleOfThree( qPrefDisplay::three_m_based_grid() );
// Place the fixed dive computer text at the bottom
double bottomBorder = sceneRect().height() - diveComputerText->height() - 2.0 * dpr * diveComputerTextBorder;
diveComputerText->setPos(0.0, bottomBorder + dpr * diveComputerTextBorder);
double bottomTextHeight = std::max(diveComputerText->height(), eventsHiddenText->height());
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;
@ -372,6 +379,12 @@ bool ProfileScene::pointOnDiveComputerText(const QPointF &point) const
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)
{
double ret = -1;
@ -525,9 +538,12 @@ void ProfileScene::plotDive(const struct dive *dIn, int dcIn, int animSpeed, boo
eventItems.clear();
struct gasmix lastgasmix = get_gasmix_at_time(d, currentdc, duration_t{1});
bool has_hidden_events = false;
for (struct event *event = currentdc->events; event; event = event->next) {
if (event->hidden)
if (event->hidden || is_event_type_hidden(event)) {
has_hidden_events = true;
continue;
}
// if print mode is selected only draw headings, SP change, gas events or bookmark event
if (printMode) {
if (empty_string(event->name) ||
@ -548,6 +564,7 @@ void ProfileScene::plotDive(const struct dive *dIn, int dcIn, int animSpeed, boo
if (event_is_gaschange(event))
lastgasmix = get_gasmix_from_event(d, event);
}
eventsHiddenText->setVisible(has_hidden_events);
QString dcText = get_dc_nickname(currentdc);
if (dcText == "planned dive")

View File

@ -38,6 +38,7 @@ public:
void clear();
bool pointOnProfile(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).
// Can be compared with literal 1.0 to determine "end" state.
@ -96,6 +97,7 @@ private:
DiveGasPressureItem *gasPressureItem;
std::vector<std::unique_ptr<DiveEventItem>> eventItems;
DiveTextItem *diveComputerText;
DiveTextItem *eventsHiddenText;
DiveReportedCeiling *reportedCeiling;
PartialPressureGasItem *pn2GasItem;
PartialPressureGasItem *pheGasItem;

View File

@ -474,6 +474,16 @@ static QString formatCylinderDescription(int i, const cylinder_t *cylinder)
return label;
}
void ProfileView::unhideEvents()
{
if (!d)
return;
const struct divecomputer *currentdc = get_dive_dc_const(d, dc);
for (struct event *ev = currentdc->events; ev; ev = ev->next)
ev->hidden = false;
replot();
}
void ProfileView::mousePressEvent(QMouseEvent *event)
{
// Handle dragging of items
@ -506,6 +516,34 @@ void ProfileView::mousePressEvent(QMouseEvent *event)
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 = get_dive_dc_const(d, dc);
if (has_individually_hidden_events(currentdc)) {
m.emplace_back(tr("Unhide individually hidden events of this dive"), [this, &currentdc] {
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());
if (d && item) {
std::vector<MenuEntry> m;

View File

@ -138,6 +138,7 @@ private:
// Event related
void editEventName(struct event *event);
void unhideEvents();
// The list of pictures in this plot. The pictures are sorted by offset in seconds.
// For the same offset, sort by filename.

View File

@ -365,37 +365,9 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event)
changeMode->addAction(gettextFromC::tr(divemode_text_ui[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);
}
if (std::any_of(profileScene->eventItems.begin(), profileScene->eventItems.end(),
[] (const DiveEventItem *item) { return item->getEvent()->hidden; }))
m.addAction(tr("Unhide individually hidden events of this dive"), this, &ProfileWidget2::unhideEvents);
m.exec(event->globalPos());
}
void ProfileWidget2::unhideEvents()
{
for (DiveEventItem *item: profileScene->eventItems) {
item->getEventMutable()->hidden = false;
item->show();
}
}
void ProfileWidget2::unhideEventTypes()
{
show_all_event_types();
replot();
}
void ProfileWidget2::addBookmark(int seconds)
{
if (d)

View File

@ -107,8 +107,6 @@ private:
void addSetpointChange(int seconds);
void removeEvent(DiveEventItem *item);
void editName(DiveEventItem *item);
void unhideEvents();
void unhideEventTypes();
void makeFirstDC();
void deleteCurrentDC();
void splitCurrentDC();