This commit is contained in:
bstoeger 2024-02-20 20:14:51 +00:00 committed by GitHub
commit 2424de3cd2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 179 additions and 120 deletions

View file

@ -51,7 +51,7 @@ SOURCES += subsurface-mobile-main.cpp \
core/divecomputer.c \ core/divecomputer.c \
core/divefilter.cpp \ core/divefilter.cpp \
core/event.c \ core/event.c \
core/eventname.cpp \ core/eventtype.cpp \
core/filterconstraint.cpp \ core/filterconstraint.cpp \
core/filterpreset.cpp \ core/filterpreset.cpp \
core/divelist.c \ core/divelist.c \
@ -202,7 +202,7 @@ HEADERS += \
core/dive.h \ core/dive.h \
core/divecomputer.h \ core/divecomputer.h \
core/event.h \ core/event.h \
core/eventname.h \ core/eventtype.h \
core/extradata.h \ core/extradata.h \
core/git-access.h \ core/git-access.h \
core/globals.h \ core/globals.h \

View file

@ -81,8 +81,8 @@ set(SUBSURFACE_CORE_LIB_SRCS
downloadfromdcthread.h downloadfromdcthread.h
event.c event.c
event.h event.h
eventname.cpp eventtype.cpp
eventname.h eventtype.h
equipment.c equipment.c
equipment.h equipment.h
errorhelper.c errorhelper.c

View file

@ -9,7 +9,7 @@
#include "divelog.h" #include "divelog.h"
#include "divesite.h" #include "divesite.h"
#include "event.h" #include "event.h"
#include "eventname.h" #include "eventtype.h"
#include "filterpreset.h" #include "filterpreset.h"
#include "fulltext.h" #include "fulltext.h"
#include "interpolate.h" #include "interpolate.h"
@ -1319,7 +1319,7 @@ void clear_dive_file_data()
current_dive = NULL; current_dive = NULL;
clear_divelog(&divelog); clear_divelog(&divelog);
clear_event_names(); clear_event_types();
reset_min_datafile_version(); reset_min_datafile_version();
clear_git_id(); clear_git_id();

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include "event.h" #include "event.h"
#include "eventname.h" #include "eventtype.h"
#include "subsurface-string.h" #include "subsurface-string.h"
#include <string.h> #include <string.h>
@ -80,7 +80,7 @@ struct event *create_event(unsigned int time, int type, int flags, int value, co
break; break;
} }
remember_event_name(name, flags); remember_event_type(ev);
return ev; return ev;
} }
@ -102,3 +102,17 @@ bool same_event(const struct event *a, const struct event *b)
return 0; return 0;
return !strcmp(a->name, b->name); return !strcmp(a->name, b->name);
} }
extern enum event_severity get_event_severity(const struct event *ev)
{
switch (ev->flags & SAMPLE_FLAGS_SEVERITY_MASK) {
case SAMPLE_FLAGS_SEVERITY_INFO:
return EVENT_SEVERITY_INFO;
case SAMPLE_FLAGS_SEVERITY_WARN:
return EVENT_SEVERITY_WARN;
case SAMPLE_FLAGS_SEVERITY_ALARM:
return EVENT_SEVERITY_ALARM;
default:
return EVENT_SEVERITY_NONE;
}
}

View file

@ -12,6 +12,13 @@
extern "C" { extern "C" {
#endif #endif
enum event_severity {
EVENT_SEVERITY_NONE = 0,
EVENT_SEVERITY_INFO,
EVENT_SEVERITY_WARN,
EVENT_SEVERITY_ALARM
};
/* /*
* Events are currently based straight on what libdivecomputer gives us. * Events are currently based straight on what libdivecomputer gives us.
* We need to wrap these into our own events at some point to remove some of the limitations. * We need to wrap these into our own events at some point to remove some of the limitations.
@ -35,7 +42,8 @@ struct event {
struct gasmix mix; struct gasmix mix;
} gas; } gas;
}; };
bool deleted; bool deleted; // used internally in the parser and in fixup_dive().
bool hidden;
char name[]; char name[];
}; };
@ -46,12 +54,12 @@ extern void free_events(struct event *ev);
extern struct event *create_event(unsigned int time, int type, int flags, int value, const char *name); extern struct event *create_event(unsigned int time, int type, int flags, int value, const char *name);
extern struct event *clone_event_rename(const struct event *ev, const char *name); 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 bool same_event(const struct event *a, const struct event *b);
extern enum event_severity get_event_severity(const struct event *ev);
/* Since C doesn't have parameter-based overloading, two versions of get_next_event. */ /* 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); extern const struct event *get_next_event(const struct event *event, const char *name);
extern struct event *get_next_event_mutable(struct event *event, const char *name); extern struct event *get_next_event_mutable(struct event *event, const char *name);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -1,60 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include "eventname.h"
#include "subsurface-string.h"
#include <string>
#include <vector>
#include <algorithm>
struct event_name {
std::string name;
int flags;
bool plot;
};
static std::vector<event_name> event_names;
// Small helper so that we can compare events to C-strings
static bool operator==(const event_name &en1, const event_name &en2)
{
return en1.name == en2.name && en1.flags == en2.flags;
}
extern "C" void clear_event_names()
{
event_names.clear();
}
extern "C" void remember_event_name(const char *eventname, const int flags)
{
if (empty_string(eventname))
return;
if (std::find(event_names.begin(), event_names.end(), event_name{ eventname, flags }) != event_names.end())
return;
event_names.push_back({ eventname, flags, true });
}
extern "C" bool is_event_hidden(const char *eventname, const int flags)
{
auto it = std::find(event_names.begin(), event_names.end(), event_name{ eventname, flags });
return it != event_names.end() && !it->plot;
}
extern "C" void hide_similar_events(const char *eventname, const int flags)
{
auto it = std::find(event_names.begin(), event_names.end(), event_name{ eventname, flags });
if (it != event_names.end())
it->plot = false;
}
extern "C" void show_all_events()
{
for (event_name &en: event_names)
en.plot = true;
}
extern "C" bool any_events_hidden()
{
return std::any_of(event_names.begin(), event_names.end(),
[] (const event_name &en) { return !en.plot; });
}

View file

@ -1,21 +0,0 @@
// collect all event names and whether we display events of that type
// SPDX-License-Identifier: GPL-2.0
#ifndef EVENTNAME_H
#define EVENTNAME_H
#ifdef __cplusplus
extern "C" {
#endif
extern void clear_event_names(void);
extern void remember_event_name(const char *eventname, const int flags);
extern bool is_event_hidden(const char *eventname, const int flags);
extern void hide_similar_events(const char *eventname, const int flags);
extern void show_all_events();
extern bool any_events_hidden();
#ifdef __cplusplus
}
#endif
#endif

67
core/eventtype.cpp Normal file
View file

@ -0,0 +1,67 @@
// SPDX-License-Identifier: GPL-2.0
#include "eventtype.h"
#include "event.h"
#include "subsurface-string.h"
#include <string>
#include <vector>
#include <algorithm>
struct event_type {
std::string name;
event_severity severity;
bool plot;
event_type(const struct event *ev) :
name(ev->name),
severity(get_event_severity(ev)),
plot(true)
{
}
};
static std::vector<event_type> event_types;
static bool operator==(const event_type &en1, const event_type &en2)
{
return en1.name == en2.name && en1.severity == en2.severity;
}
extern "C" void clear_event_types()
{
event_types.clear();
}
extern "C" void remember_event_type(const struct event *ev)
{
if (empty_string(ev->name))
return;
event_type type(ev);
if (std::find(event_types.begin(), event_types.end(), type) != event_types.end())
return;
event_types.push_back(std::move(type));
}
extern "C" bool is_event_type_hidden(const struct event *ev)
{
auto it = std::find(event_types.begin(), event_types.end(), ev);
return it != event_types.end() && !it->plot;
}
extern "C" void hide_event_type(const struct event *ev)
{
auto it = std::find(event_types.begin(), event_types.end(), ev);
if (it != event_types.end())
it->plot = false;
}
extern "C" void show_all_event_types()
{
for (event_type &e: event_types)
e.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; });
}

21
core/eventtype.h Normal file
View file

@ -0,0 +1,21 @@
// collect all event names and whether we display events of that type
// SPDX-License-Identifier: GPL-2.0
#ifndef EVENTNAME_H
#define EVENTNAME_H
#ifdef __cplusplus
extern "C" {
#endif
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 bool any_event_types_hidden();
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,6 +1,7 @@
#include "string-format.h" #include "string-format.h"
#include "dive.h" #include "dive.h"
#include "divesite.h" #include "divesite.h"
#include "event.h"
#include "format.h" #include "format.h"
#include "qthelper.h" #include "qthelper.h"
#include "subsurface-string.h" #include "subsurface-string.h"
@ -327,3 +328,26 @@ QString formatTripTitleWithDives(const dive_trip *trip)
return formatTripTitle(trip) + " " + return formatTripTitle(trip) + " " +
gettextFromC::tr("(%n dive(s))", "", nr); gettextFromC::tr("(%n dive(s))", "", nr);
} }
static QString formatEventSeverity(const event *ev)
{
switch(get_event_severity(ev)) {
case EVENT_SEVERITY_INFO: return gettextFromC::tr("info");
case EVENT_SEVERITY_WARN: return gettextFromC::tr("warn");
case EVENT_SEVERITY_ALARM: return gettextFromC::tr("alarm");
default: return QString();
}
}
QString formatEventType(const event *ev)
{
if (!ev || empty_string(ev->name))
return QString();
QString eventName = QString::fromUtf8(ev->name);
QString severity = formatEventSeverity(ev);
if (severity.isEmpty())
return eventName;
return QStringLiteral("%1 (%2)").arg(eventName, severity);
}

View file

@ -7,6 +7,7 @@
struct dive; struct dive;
struct dive_trip; struct dive_trip;
struct event;
QString formatSac(const dive *d); QString formatSac(const dive *d);
QString formatNotes(const dive *d); QString formatNotes(const dive *d);
@ -31,5 +32,6 @@ QString formatDayOfWeek(int day);
QString formatMinutes(int seconds); QString formatMinutes(int seconds);
QString formatTripTitle(const dive_trip *trip); QString formatTripTitle(const dive_trip *trip);
QString formatTripTitleWithDives(const dive_trip *trip); QString formatTripTitleWithDives(const dive_trip *trip);
QString formatEventType(const event *ev);
#endif #endif

View file

@ -4,7 +4,7 @@
#include "profile-widget/divepixmapcache.h" #include "profile-widget/divepixmapcache.h"
#include "profile-widget/animationfunctions.h" #include "profile-widget/animationfunctions.h"
#include "core/event.h" #include "core/event.h"
#include "core/eventname.h" #include "core/eventtype.h"
#include "core/format.h" #include "core/format.h"
#include "core/profile.h" #include "core/profile.h"
#include "core/gettextfromc.h" #include "core/gettextfromc.h"
@ -47,6 +47,7 @@ struct event *DiveEventItem::getEventMutable()
void DiveEventItem::setupPixmap(struct gasmix lastgasmix, const DivePixmaps &pixmaps) void DiveEventItem::setupPixmap(struct gasmix lastgasmix, const DivePixmaps &pixmaps)
{ {
event_severity severity = get_event_severity(ev);
if (empty_string(ev->name)) { if (empty_string(ev->name)) {
setPixmap(pixmaps.warning); setPixmap(pixmaps.warning);
} else if (same_string_caseinsensitive(ev->name, "modechange")) { } else if (same_string_caseinsensitive(ev->name, "modechange")) {
@ -82,12 +83,8 @@ void DiveEventItem::setupPixmap(struct gasmix lastgasmix, const DivePixmaps &pix
else else
setPixmap(pixmaps.gaschangeEAN); setPixmap(pixmaps.gaschangeEAN);
} }
#ifdef SAMPLE_FLAGS_SEVERITY_SHIFT
} else if ((((ev->flags & SAMPLE_FLAGS_SEVERITY_MASK) >> SAMPLE_FLAGS_SEVERITY_SHIFT) == 1) || } else if ((((ev->flags & SAMPLE_FLAGS_SEVERITY_MASK) >> SAMPLE_FLAGS_SEVERITY_SHIFT) == 1) ||
// those are useless internals of the dive computer // those are useless internals of the dive computer
#else
} else if (
#endif
same_string_caseinsensitive(ev->name, "heading") || same_string_caseinsensitive(ev->name, "heading") ||
(same_string_caseinsensitive(ev->name, "SP change") && ev->time.seconds == 0)) { (same_string_caseinsensitive(ev->name, "SP change") && ev->time.seconds == 0)) {
// 2 cases: // 2 cases:
@ -98,14 +95,12 @@ void DiveEventItem::setupPixmap(struct gasmix lastgasmix, const DivePixmaps &pix
// that allows tooltips to work when we don't want to show a specific // that allows tooltips to work when we don't want to show a specific
// pixmap for an event, but want to show the event value in the tooltip // pixmap for an event, but want to show the event value in the tooltip
setPixmap(pixmaps.transparent); setPixmap(pixmaps.transparent);
#ifdef SAMPLE_FLAGS_SEVERITY_SHIFT } else if (severity == EVENT_SEVERITY_INFO) {
} else if (((ev->flags & SAMPLE_FLAGS_SEVERITY_MASK) >> SAMPLE_FLAGS_SEVERITY_SHIFT) == 2) {
setPixmap(pixmaps.info); setPixmap(pixmaps.info);
} else if (((ev->flags & SAMPLE_FLAGS_SEVERITY_MASK) >> SAMPLE_FLAGS_SEVERITY_SHIFT) == 3) { } else if (severity == EVENT_SEVERITY_WARN) {
setPixmap(pixmaps.warning); setPixmap(pixmaps.warning);
} else if (((ev->flags & SAMPLE_FLAGS_SEVERITY_MASK) >> SAMPLE_FLAGS_SEVERITY_SHIFT) == 4) { } else if (severity == EVENT_SEVERITY_ALARM) {
setPixmap(pixmaps.violation); setPixmap(pixmaps.violation);
#endif
} else if (same_string_caseinsensitive(ev->name, "violation") || // generic libdivecomputer } else if (same_string_caseinsensitive(ev->name, "violation") || // generic libdivecomputer
same_string_caseinsensitive(ev->name, "Safety stop violation") || // the rest are from the Uemis downloader same_string_caseinsensitive(ev->name, "Safety stop violation") || // the rest are from the Uemis downloader
same_string_caseinsensitive(ev->name, "pO₂ ascend alarm") || same_string_caseinsensitive(ev->name, "pO₂ ascend alarm") ||
@ -224,11 +219,6 @@ bool DiveEventItem::isInteresting(const struct dive *d, const struct divecompute
return true; return true;
} }
bool DiveEventItem::shouldBeHidden()
{
return is_event_hidden(ev->name, ev->flags);
}
void DiveEventItem::recalculatePos() void DiveEventItem::recalculatePos()
{ {
if (!ev) if (!ev)
@ -238,7 +228,7 @@ void DiveEventItem::recalculatePos()
hide(); hide();
return; return;
} }
setVisible(!shouldBeHidden()); 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);

View file

@ -21,7 +21,6 @@ public:
void eventVisibilityChanged(const QString &eventName, bool visible); void eventVisibilityChanged(const QString &eventName, bool visible);
void setVerticalAxis(DiveCartesianAxis *axis, int speed); void setVerticalAxis(DiveCartesianAxis *axis, int speed);
void setHorizontalAxis(DiveCartesianAxis *axis); void setHorizontalAxis(DiveCartesianAxis *axis);
bool shouldBeHidden();
static bool isInteresting(const struct dive *d, const struct divecomputer *dc, static bool isInteresting(const struct dive *d, const struct divecomputer *dc,
const struct event *ev, const struct plot_info &pi, const struct event *ev, const struct plot_info &pi,
int firstSecond, int lastSecond); int firstSecond, int lastSecond);

View file

@ -40,7 +40,7 @@ DivePixmaps::DivePixmaps(int dpr) : dpr(dpr)
gaschangeEANICD = createPixmap(":gaschange-ean-ICD-icon", sz_bigger); gaschangeEANICD = createPixmap(":gaschange-ean-ICD-icon", sz_bigger);
gaschangeEAN = createPixmap(":gaschange-ean-icon", sz_bigger); gaschangeEAN = createPixmap(":gaschange-ean-icon", sz_bigger);
// The transparen pixmap is a very obscure feature to enable tooltips without showing a pixmap. // The transparent pixmap is a very obscure feature to enable tooltips without showing a pixmap.
// See code in diveeventitem.cpp. This should probably be replaced by a different mechanism. // See code in diveeventitem.cpp. This should probably be replaced by a different mechanism.
QPixmap transparentPixmap(lrint(4 * dprf), lrint(20 * dprf)); QPixmap transparentPixmap(lrint(4 * dprf), lrint(20 * dprf));
transparentPixmap.fill(makeColor(1.0, 1.0, 1.0, 0.01)); transparentPixmap.fill(makeColor(1.0, 1.0, 1.0, 0.01));
@ -52,7 +52,7 @@ static std::vector<std::shared_ptr<const DivePixmaps>> cache;
// Note that the idiomatic way would be to store std::weak_ptr<>s. // Note that the idiomatic way would be to store std::weak_ptr<>s.
// That would mean that the pixmaps are destroyed when the last user uses // That would mean that the pixmaps are destroyed when the last user uses
// them. We want to keep them around at least until the next caller! // them. We want to keep them around at least until the next caller!
// Therefore we also std::shared_ptr<>s. // Therefore we also store std::shared_ptr<>s.
std::shared_ptr<const DivePixmaps> getDivePixmaps(double dprIn) std::shared_ptr<const DivePixmaps> getDivePixmaps(double dprIn)
{ {
using ptr = std::shared_ptr<const DivePixmaps>; using ptr = std::shared_ptr<const DivePixmaps>;

View file

@ -3,10 +3,11 @@
#include "profile-widget/profilescene.h" #include "profile-widget/profilescene.h"
#include "core/device.h" #include "core/device.h"
#include "core/event.h" #include "core/event.h"
#include "core/eventname.h" #include "core/eventtype.h"
#include "core/subsurface-string.h" #include "core/subsurface-string.h"
#include "core/qthelper.h" #include "core/qthelper.h"
#include "core/range.h" #include "core/range.h"
#include "core/string-format.h"
#include "core/settings/qPrefTechnicalDetails.h" #include "core/settings/qPrefTechnicalDetails.h"
#include "core/settings/qPrefPartialPressureGas.h" #include "core/settings/qPrefPartialPressureGas.h"
#include "profile-widget/diveeventitem.h" #include "profile-widget/diveeventitem.h"
@ -608,10 +609,11 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event)
[this, seconds](){ addDivemodeSwitch(seconds, PSCR); }); [this, seconds](){ addDivemodeSwitch(seconds, PSCR); });
if (DiveEventItem *item = dynamic_cast<DiveEventItem *>(sceneItem)) { if (DiveEventItem *item = dynamic_cast<DiveEventItem *>(sceneItem)) {
const struct event *dcEvent = item->getEvent();
m.addAction(tr("Remove event"), [this,item] { removeEvent(item); }); m.addAction(tr("Remove event"), [this,item] { removeEvent(item); });
m.addAction(tr("Hide event"), [this, item] { hideEvent(item); }); m.addAction(tr("Hide event"), [this, item] { hideEvent(item); });
m.addAction(tr("Hide similar events"), [this, item] { hideSimilarEvents(item); }); m.addAction(tr("Hide events of type '%1'").arg(formatEventType(dcEvent)),
const struct event *dcEvent = item->getEvent(); [this, item] { hideEventType(item); });
if (dcEvent->type == SAMPLE_EVENT_BOOKMARK) if (dcEvent->type == SAMPLE_EVENT_BOOKMARK)
m.addAction(tr("Edit name"), [this, item] { editName(item); }); m.addAction(tr("Edit name"), [this, item] { editName(item); });
#if 0 // TODO::: FINISH OR DISABLE #if 0 // TODO::: FINISH OR DISABLE
@ -656,8 +658,11 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event)
} }
#endif #endif
} }
if (any_events_hidden() || std::any_of(profileScene->eventItems.begin(), profileScene->eventItems.end(), [] (const DiveEventItem *item) { return !item->isVisible(); })) if (any_event_types_hidden())
m.addAction(tr("Unhide all events"), this, &ProfileWidget2::unhideEvents); m.addAction(tr("Unhide 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()); m.exec(event->globalPos());
} }
@ -694,15 +699,16 @@ void ProfileWidget2::renameCurrentDC()
void ProfileWidget2::hideEvent(DiveEventItem *item) void ProfileWidget2::hideEvent(DiveEventItem *item)
{ {
item->getEventMutable()->hidden = true;
item->hide(); item->hide();
} }
void ProfileWidget2::hideSimilarEvents(DiveEventItem *item) void ProfileWidget2::hideEventType(DiveEventItem *item)
{ {
const struct event *event = item->getEvent(); const struct event *event = item->getEvent();
if (!empty_string(event->name)) { if (!empty_string(event->name)) {
hide_similar_events(event->name, event->flags); hide_event_type(event);
replot(); replot();
} }
@ -710,10 +716,18 @@ void ProfileWidget2::hideSimilarEvents(DiveEventItem *item)
void ProfileWidget2::unhideEvents() void ProfileWidget2::unhideEvents()
{ {
show_all_events(); for (DiveEventItem *item: profileScene->eventItems) {
for (DiveEventItem *item: profileScene->eventItems) item->getEventMutable()->hidden = false;
item->show(); item->show();
} }
}
void ProfileWidget2::unhideEventTypes()
{
show_all_event_types();
replot();
}
void ProfileWidget2::removeEvent(DiveEventItem *item) void ProfileWidget2::removeEvent(DiveEventItem *item)
{ {

View file

@ -126,9 +126,10 @@ private:
void addSetpointChange(int seconds); void addSetpointChange(int seconds);
void removeEvent(DiveEventItem *item); void removeEvent(DiveEventItem *item);
void hideEvent(DiveEventItem *item); void hideEvent(DiveEventItem *item);
void hideSimilarEvents(DiveEventItem *item); void hideEventType(DiveEventItem *item);
void editName(DiveEventItem *item); void editName(DiveEventItem *item);
void unhideEvents(); void unhideEvents();
void unhideEventTypes();
void makeFirstDC(); void makeFirstDC();
void deleteCurrentDC(); void deleteCurrentDC();
void splitCurrentDC(); void splitCurrentDC();