From 0d3c9954f4882fc46daae4751fc712355417683d Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Sun, 12 Feb 2023 15:51:39 +0100 Subject: [PATCH] profile: redo eventname handling The eventname handling code was splattered all over the place. Collect it in a single source file and use C++ idioms to avoid nasty memory management. Provide a C-only interface, however. Signed-off-by: Berthold Stoeger --- Subsurface-mobile.pro | 2 ++ core/CMakeLists.txt | 2 ++ core/divecomputer.c | 3 +- core/divelist.c | 3 +- core/event.c | 35 ------------------ core/event.h | 11 ------ core/eventname.cpp | 59 +++++++++++++++++++++++++++++++ core/eventname.h | 21 +++++++++++ profile-widget/diveeventitem.cpp | 7 ++-- profile-widget/profilewidget2.cpp | 21 +++-------- 10 files changed, 94 insertions(+), 70 deletions(-) create mode 100644 core/eventname.cpp create mode 100644 core/eventname.h diff --git a/Subsurface-mobile.pro b/Subsurface-mobile.pro index 36db76407..3d66664ce 100644 --- a/Subsurface-mobile.pro +++ b/Subsurface-mobile.pro @@ -51,6 +51,7 @@ SOURCES += subsurface-mobile-main.cpp \ core/divecomputer.c \ core/divefilter.cpp \ core/event.c \ + core/eventname.cpp \ core/filterconstraint.cpp \ core/filterpreset.cpp \ core/divelist.c \ @@ -200,6 +201,7 @@ HEADERS += \ core/dive.h \ core/divecomputer.h \ core/event.h \ + core/eventname.h \ core/extradata.h \ core/git-access.h \ core/globals.h \ diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 83ad52eb9..6c046fa61 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -79,6 +79,8 @@ set(SUBSURFACE_CORE_LIB_SRCS downloadfromdcthread.h event.c event.h + eventname.cpp + eventname.h equipment.c equipment.h errorhelper.c diff --git a/core/divecomputer.c b/core/divecomputer.c index 94de56f66..e7c5e783a 100644 --- a/core/divecomputer.c +++ b/core/divecomputer.c @@ -2,6 +2,7 @@ #include "divecomputer.h" #include "event.h" +#include "eventname.h" #include "extradata.h" #include "pref.h" #include "sample.h" @@ -442,7 +443,7 @@ struct event *add_event(struct divecomputer *dc, unsigned int time, int type, in add_event_to_dc(dc, ev); - remember_event(name); + remember_event_name(name); return ev; } diff --git a/core/divelist.c b/core/divelist.c index c3385920d..d0e7cabf4 100644 --- a/core/divelist.c +++ b/core/divelist.c @@ -8,6 +8,7 @@ #include "divesite.h" #include "dive.h" #include "event.h" +#include "eventname.h" #include "filterpreset.h" #include "fulltext.h" #include "interpolate.h" @@ -1375,7 +1376,7 @@ void clear_dive_file_data() clear_dive(&displayed_dive); clear_device_table(&device_table); - clear_events(); + clear_event_names(); clear_filter_presets(); reset_min_datafile_version(); diff --git a/core/event.c b/core/event.c index 8f73aefd8..fe38bbebb 100644 --- a/core/event.c +++ b/core/event.c @@ -99,38 +99,3 @@ bool same_event(const struct event *a, const struct event *b) return 0; return !strcmp(a->name, b->name); } - -/* collect all event names and whether we display them */ -struct ev_select *ev_namelist = NULL; -int evn_used = 0; -static int evn_allocated = 0; - -void clear_events(void) -{ - for (int i = 0; i < evn_used; i++) - free(ev_namelist[i].ev_name); - evn_used = 0; -} - -void remember_event(const char *eventname) -{ - int i = 0, len; - - if (!eventname || (len = strlen(eventname)) == 0) - return; - while (i < evn_used) { - if (!strncmp(eventname, ev_namelist[i].ev_name, len)) - return; - i++; - } - if (evn_used == evn_allocated) { - evn_allocated += 10; - ev_namelist = realloc(ev_namelist, evn_allocated * sizeof(struct ev_select)); - if (!ev_namelist) - /* we are screwed, but let's just bail out */ - return; - } - ev_namelist[evn_used].ev_name = strdup(eventname); - ev_namelist[evn_used].plot_ev = true; - evn_used++; -} diff --git a/core/event.h b/core/event.h index 4c729e3f3..90f36fe54 100644 --- a/core/event.h +++ b/core/event.h @@ -39,15 +39,6 @@ struct event { char name[]; }; -struct ev_select { - char *ev_name; - bool plot_ev; -}; - -/* collect all event names and whether we display them */ -extern struct ev_select *ev_namelist; -extern int evn_used; - extern int event_is_gaschange(const struct event *ev); extern bool event_is_divemodechange(const struct event *ev); extern struct event *clone_event(const struct event *src_ev); @@ -55,8 +46,6 @@ 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 *clone_event_rename(const struct event *ev, const char *name); extern bool same_event(const struct event *a, const struct event *b); -extern void remember_event(const char *eventname); -extern void clear_events(void); /* 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); diff --git a/core/eventname.cpp b/core/eventname.cpp new file mode 100644 index 000000000..4b890ddac --- /dev/null +++ b/core/eventname.cpp @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "eventname.h" +#include "subsurface-string.h" + +#include +#include +#include + +struct event_name { + std::string name; + bool plot; +}; + +static std::vector event_names; + +// Small helper so that we can compare events to C-strings +static bool operator==(const event_name &en, const char *s) +{ + return en.name == s; +} + +extern "C" void clear_event_names() +{ + event_names.clear(); +} + +extern "C" void remember_event_name(const char *eventname) +{ + if (empty_string(eventname)) + return; + if (std::find(event_names.begin(), event_names.end(), eventname) != event_names.end()) + return; + event_names.push_back({ eventname, true }); +} + +extern "C" bool is_event_hidden(const char *eventname) +{ + auto it = std::find(event_names.begin(), event_names.end(), eventname); + return it != event_names.end() && !it->plot; +} + +extern "C" void hide_event(const char *eventname) +{ + auto it = std::find(event_names.begin(), event_names.end(), eventname); + 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; }); +} diff --git a/core/eventname.h b/core/eventname.h new file mode 100644 index 000000000..596711c7c --- /dev/null +++ b/core/eventname.h @@ -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_names(void); +extern void remember_event_name(const char *eventname); +extern bool is_event_hidden(const char *eventname); +extern void hide_event(const char *eventname); +extern void show_all_events(); +extern bool any_events_hidden(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/profile-widget/diveeventitem.cpp b/profile-widget/diveeventitem.cpp index 6e864b069..9b701286d 100644 --- a/profile-widget/diveeventitem.cpp +++ b/profile-widget/diveeventitem.cpp @@ -4,6 +4,7 @@ #include "profile-widget/divepixmapcache.h" #include "profile-widget/animationfunctions.h" #include "core/event.h" +#include "core/eventname.h" #include "core/format.h" #include "core/profile.h" #include "core/gettextfromc.h" @@ -225,11 +226,7 @@ bool DiveEventItem::isInteresting(const struct dive *d, const struct divecompute bool DiveEventItem::shouldBeHidden() { - for (int i = 0; i < evn_used; i++) { - if (!strcmp(ev->name, ev_namelist[i].ev_name) && ev_namelist[i].plot_ev == false) - return true; - } - return false; + return is_event_hidden(ev->name); } void DiveEventItem::recalculatePos() diff --git a/profile-widget/profilewidget2.cpp b/profile-widget/profilewidget2.cpp index 65ccb64a7..88002af15 100644 --- a/profile-widget/profilewidget2.cpp +++ b/profile-widget/profilewidget2.cpp @@ -3,6 +3,7 @@ #include "profile-widget/profilescene.h" #include "core/device.h" #include "core/event.h" +#include "core/eventname.h" #include "core/subsurface-string.h" #include "core/qthelper.h" #include "core/range.h" @@ -643,14 +644,7 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event) } #endif } - bool some_hidden = false; - for (int i = 0; i < evn_used; i++) { - if (ev_namelist[i].plot_ev == false) { - some_hidden = true; - break; - } - } - if (some_hidden) + if (any_events_hidden()) m.addAction(tr("Unhide all events"), this, &ProfileWidget2::unhideEvents); m.exec(event->globalPos()); } @@ -694,12 +688,7 @@ void ProfileWidget2::hideEvents(DiveEventItem *item) TITLE_OR_TEXT(tr("Hide events"), tr("Hide all %1 events?").arg(event->name)), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) { if (!empty_string(event->name)) { - for (int i = 0; i < evn_used; i++) { - if (same_string(event->name, ev_namelist[i].ev_name)) { - ev_namelist[i].plot_ev = false; - break; - } - } + hide_event(event->name); Q_FOREACH (DiveEventItem *evItem, profileScene->eventItems) { if (same_string(evItem->getEvent()->name, event->name)) evItem->hide(); @@ -712,9 +701,7 @@ void ProfileWidget2::hideEvents(DiveEventItem *item) void ProfileWidget2::unhideEvents() { - for (int i = 0; i < evn_used; i++) { - ev_namelist[i].plot_ev = true; - } + show_all_events(); Q_FOREACH (DiveEventItem *item, profileScene->eventItems) item->show(); }