diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/CMakeLists.txt | 2 | ||||
-rw-r--r-- | core/divelist.c | 2 | ||||
-rw-r--r-- | core/filterpreset.cpp | 144 | ||||
-rw-r--r-- | core/filterpreset.h | 73 |
4 files changed, 221 insertions, 0 deletions
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 2e84112da..caaa2b74c 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -86,6 +86,8 @@ set(SUBSURFACE_CORE_LIB_SRCS file.h filterconstraint.cpp filterconstraint.h + filterpreset.cpp + filterpreset.h format.cpp format.h fulltext.cpp diff --git a/core/divelist.c b/core/divelist.c index a5eaffe06..b1e670e31 100644 --- a/core/divelist.c +++ b/core/divelist.c @@ -7,6 +7,7 @@ #include "device.h" #include "divesite.h" #include "dive.h" +#include "filterpreset.h" #include "fulltext.h" #include "planner.h" #include "qthelper.h" @@ -1376,6 +1377,7 @@ void clear_dive_file_data() clear_dive(&displayed_dive); clear_device_nodes(); clear_events(); + clear_filter_presets(); reset_min_datafile_version(); clear_git_id(); diff --git a/core/filterpreset.cpp b/core/filterpreset.cpp new file mode 100644 index 000000000..b21306502 --- /dev/null +++ b/core/filterpreset.cpp @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "filterpreset.h" +#include "qthelper.h" +#include "subsurface-string.h" + +std::vector<filter_preset> filter_preset_table; + +extern "C" void clear_filter_presets(void) +{ + filter_preset_table.clear(); +} + +extern "C" int filter_presets_count(void) +{ + return (int)filter_preset_table.size(); +} + +extern "C" char *filter_preset_name(int preset) +{ + return copy_qstring(filter_preset_name_qstring(preset)); +} + +extern "C" char *filter_preset_fulltext_query(int preset) +{ + return copy_qstring(filter_preset_table[preset].data.fullText.originalQuery); +} + +extern "C" const char *filter_preset_fulltext_mode(int preset) +{ + switch (filter_preset_table[preset].data.fulltextStringMode) { + default: + case StringFilterMode::SUBSTRING: + return "substring"; + case StringFilterMode::STARTSWITH: + return "startswith"; + case StringFilterMode::EXACT: + return "exact"; + } +} + +extern "C" void filter_preset_set_fulltext(struct filter_preset *preset, const char *fulltext, const char *fulltext_string_mode) +{ + if (same_string(fulltext_string_mode, "substring")) + preset->data.fulltextStringMode = StringFilterMode::SUBSTRING; + else if (same_string(fulltext_string_mode, "startswith")) + preset->data.fulltextStringMode = StringFilterMode::STARTSWITH; + else // if (same_string(fulltext_string_mode, "exact")) + preset->data.fulltextStringMode = StringFilterMode::EXACT; + preset->data.fullText = fulltext; +} + +extern "C" int filter_preset_constraint_count(int preset) +{ + return (int)filter_preset_table[preset].data.constraints.size(); +} + +extern "C" const filter_constraint *filter_preset_constraint(int preset, int constraint) +{ + return &filter_preset_table[preset].data.constraints[constraint]; +} + +extern "C" struct filter_preset *alloc_filter_preset() +{ + return new filter_preset; +} + +extern "C" void free_filter_preset(const struct filter_preset *preset) +{ + delete preset; +} + +extern "C" void filter_preset_set_name(struct filter_preset *preset, const char *name) +{ + preset->name = name; +} + +static int filter_preset_add_to_table(const QString &name, const FilterData &d, filter_preset_table_t &table) +{ + // std::lower_bound does a binary search - the vector must be sorted. + filter_preset newEntry { name, d }; + auto it = std::lower_bound(table.begin(), table.end(), newEntry, + [](const filter_preset &p1, const filter_preset &p2) + { return p1.name < p2.name; }); + it = table.insert(it, newEntry); + return it - table.begin(); +} + +// Take care that the name doesn't already exist by adding numbers +static QString get_unique_preset_name(const QString &orig, const filter_preset_table_t &table) +{ + QString res = orig; + int count = 2; + while (std::find_if(table.begin(), table.end(), + [&res](const filter_preset &preset) + { return preset.name == res; }) != table.end()) { + res = orig + "#" + QString::number(count); + ++count; + } + return res; +} + +extern "C" void add_filter_preset_to_table(const struct filter_preset *preset, filter_preset_table_t *table) +{ + QString name = get_unique_preset_name(preset->name, *table); + filter_preset_add_to_table(name, preset->data, *table); +} + +extern "C" void filter_preset_add_constraint(struct filter_preset *preset, const char *type, const char *string_mode, + const char *range_mode, bool negate, const char *data) +{ + preset->data.constraints.emplace_back(type, string_mode, range_mode, negate, data); +} + +int filter_preset_id(const QString &name) +{ + auto it = std::find_if(filter_preset_table.begin(), filter_preset_table.end(), + [&name] (filter_preset &p) { return p.name == name; }); + return it != filter_preset_table.end() ? it - filter_preset_table.begin() : -1; +} + +QString filter_preset_name_qstring(int preset) +{ + return filter_preset_table[preset].name; +} + +void filter_preset_set(int preset, const FilterData &data) +{ + filter_preset_table[preset].data = data; +} + +FilterData filter_preset_get(int preset) +{ + return filter_preset_table[preset].data; +} + +int filter_preset_add(const QString &name, const FilterData &d) +{ + return filter_preset_add_to_table(name, d, filter_preset_table); +} + +void filter_preset_delete(int preset) +{ + filter_preset_table.erase(filter_preset_table.begin() + preset); +} diff --git a/core/filterpreset.h b/core/filterpreset.h new file mode 100644 index 000000000..d10f1a06e --- /dev/null +++ b/core/filterpreset.h @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0 +// A list of filter settings with names. Every name is unique, which +// means that saving to an old name will overwrite the old preset. +// +// Even though the filter data itself is a C++/Qt class to simplify +// string manipulation and memory management, the data is accessible +// via pure C functions so that it can be written to the log (git or xml). +#ifndef FILTER_PRESETS_H +#define FILTER_PRESETS_H + +struct dive; +struct filter_constraint; + +// So that we can pass filter preset table between C and C++ we define +// it as an opaque type in C. Thus we can easily create the table in C++ +// without having to do our own memory management and pass pointers to +// void through C. +#ifdef __cplusplus +#include "divefilter.h" +#include <vector> +#include <QStringList> +struct filter_preset { + QString name; + FilterData data; +}; + +using filter_preset_table_t = std::vector<filter_preset>; +extern filter_preset_table_t filter_preset_table; +#else +struct filter_preset; +typedef void filter_preset_table_t; +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +// The C IO code accesses the filter presets via integer indices. +extern void clear_filter_presets(void); +extern int filter_presets_count(void); +extern char *filter_preset_name(int preset); // name of filter preset - caller must free the result. +extern char *filter_preset_fulltext_query(int preset); // fulltext query of filter preset - caller must free the result. +extern const char *filter_preset_fulltext_mode(int preset); // string mode of fulltext query. ownership is *not* passed to caller. +extern int filter_preset_constraint_count(int preset); // number of constraints in the filter preset. +extern const struct filter_constraint *filter_preset_constraint(int preset, int constraint); // get constraint. ownership is *not* passed to caller. +extern struct filter_preset *alloc_filter_preset(); +extern void free_filter_preset(const struct filter_preset *preset); +extern void filter_preset_set_name(struct filter_preset *preset, const char *name); +extern void filter_preset_set_fulltext(struct filter_preset *preset, const char *fulltext, const char *fulltext_string_mode); +extern void add_filter_preset_to_table(const struct filter_preset *preset, filter_preset_table_t *table); +extern void filter_preset_add_constraint(struct filter_preset *preset, const char *type, const char *string_mode, + const char *range_mode, bool negate, const char *data); // called by the parser, therefore data passed as strings. + +#ifdef __cplusplus +} +#endif + +// C++ only functions +#ifdef __cplusplus + +struct FilterData; + +int filter_preset_id(const QString &s); // for now, we assume that names are unique. returns -1 if no preset with that name. +QString filter_preset_name_qstring(int preset); +void filter_preset_set(int preset, const FilterData &d); // this will override a preset if the name already exists. +FilterData filter_preset_get(int preset); +int filter_preset_add(const QString &name, const FilterData &d); // returns point of insertion +void filter_preset_delete(int preset); + +#endif + +#endif |