diff --git a/CMakeLists.txt b/CMakeLists.txt index eb5c9a6..caef769 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,8 @@ set(LINUX_GL_LIBS -lGL) find_package(SDL2 REQUIRED) find_package(Freetype 2 REQUIRED) -set(LIBS -lpcre2-8 -lpcre2-posix SDL2 imgui) +find_package(nlohmann_json REQUIRED) +set(LIBS -lpcre2-8 -lpcre2-posix SDL2 nlohmann_json::nlohmann_json imgui) set(IMGUI_LIBS SDL2 Freetype::Freetype) set(INCLUDES imgui imgui/backends imgui/misc/cpp imgui/freetype /usr/include/SDL2) diff --git a/config.cpp b/config.cpp index fb9446d..a5e1f06 100644 --- a/config.cpp +++ b/config.cpp @@ -1,11 +1,8 @@ -#include #include #include -#include -#include #include #include -#include +#include #include "log.h" #include "misc.h" @@ -26,49 +23,6 @@ static void fclose_and_log(FILE* file) { log(std::string("Failed to close a file: fclose(): ") + strerror(errno)); } -static bool write(const std::string& ptr, FILE* file) { - return fwrite(ptr.data(), sizeof(char), ptr.size(), file) == ptr.size() * sizeof(char); -} -static bool write(const char* ptr, FILE* file) { - return fwrite(ptr, 1, strlen(ptr), file) == strlen(ptr); -} - -static inline float to_float(const char* str) { - char* endptr; - - while (isspace(str[0])) { - str++; - } - if (str[0] == '\0') { - throw std::invalid_argument("float string is empty"); - } - - errno = 0; - float res = strtof(str, &endptr); - if (res == HUGE_VALF && errno == ERANGE) { - throw std::overflow_error(std::string(str) + " is bigger than HUGE_VALF"); - } else if (res == FLT_MIN && errno == ERANGE) { - throw std::underflow_error(std::string(str) + " is smaller than FLT_MIN"); - } else if (endptr[0] != '\0') { - throw std::invalid_argument(std::string(str) + " has trailing text"); - } - return res; -} - -static bool validate_font_size_or_log(float size) { - if (size <= 0.0f) { - log(std::string("Font size ") + std::to_string(size) + " is lower or equal to 0"); - return false; - } else if (std::isnan(size)) { - log(std::string("Font size ") + std::to_string(size) + " is NaN"); - return false; - } else if (std::isinf(size)) { - log(std::string("Font size ") + std::to_string(size) + " is infinity or negative infinity"); - return false; - } - return true; -} - std::string get_config_folder() { const char* path; @@ -86,7 +40,7 @@ std::string get_config_folder() { } std::string get_config_file_path() { - return get_config_folder() + "/config"; + return get_config_folder() + "/config.json"; } // tries to create a directory with an empty string if it's just "/" but who cares @@ -112,59 +66,11 @@ void create_config_folders_if_necessary() { } -static inline void parse_config_line(Config& config, char* line) { - if (strncmp(line, "logcat_command=", 15 * sizeof(char)) == 0) { - config.logcat_command = &line[15]; - } else if (strncmp(line, "normal_font_size=", 17 * sizeof(char)) == 0) { - float size = to_float(&line[17]); - if (validate_font_size_or_log(size)) { - config.normal_font_size = size; - } - } else if (strncmp(line, "monospace_font_size=", 20 * sizeof(char)) == 0) { - float size = to_float(&line[20]); - if (validate_font_size_or_log(size)) { - config.monospace_font_size = size; - } - } else if (line[0] != '\0') { - throw std::invalid_argument(std::string("unknown config line: ") + line); - } -} - -static inline Config load_config(FILE* file) { - size_t line_capacity_size = 128 * sizeof(char); - char* line = static_cast(malloc(line_capacity_size)); - if (line == nullptr) { - throw std::bad_alloc(); - } - Config config; - - while (true) { - errno = 0; - if (getline(&line, &line_capacity_size, file) < 0) { - // https://stackoverflow.com/questions/30569981/does-free-set-errno - int errsv = errno; - free(line); - if (errsv) { - throw_system_error(errsv, "getline()"); - } - break; - } - if (line_capacity_size == 0 || line[0] == '\0' || line[0] == '#') { - continue; - } - if (char* newline = strchr(line, '\n')) { - *newline = '\0'; - } - - try { - parse_config_line(config, line); - } catch (const std::exception& e) { - free(line); - throw; - } - } - - return config; +void from_json(const nlohmann::json& j, Config& config) { + j.at("logcat_command").get_to(config.logcat_command); + j.at("normal_font_size").get_to(config.normal_font_size); + j.at("monospace_font_size").get_to(config.monospace_font_size); + j.at("filters").get_to(config.filters); } Config load_config() { @@ -175,37 +81,15 @@ Config load_config() { return Config(); } - return load_config(config_file.get()); + return nlohmann::json::parse(config_file.get()).get(); } -static inline void write_config(FILE* file, const Config& config) { - if (!write("# This is an auto-generated file, modifications will be lost\n" - "# This is a poor man's config file \"format\", there are only three legal lines:\n" - "# # a comment, only available at the start of a line\n" - "# (an empty line, no whitespace)\n" - "# key=value pairs, no spaces around the delimiter, and no unknown keys\n\n", file)) { - throw std::runtime_error("Failed to write info comment"); - } - if (!write("logcat_command=", file)) { - throw std::runtime_error("Failed to write logcat command key"); - } - if (!write(config.logcat_command, file)) { - throw std::runtime_error("Failed to write logcat command value"); - } - - if (!write("\nnormal_font_size=", file)) { - throw std::runtime_error("Failed to write normal font size key"); - } - if (!write(std::to_string(config.normal_font_size), file)) { - throw std::runtime_error("Failed to write normal font size value"); - } - if (!write("\nmonospace_font_size=", file)) { - throw std::runtime_error("Failed to write monospace font size key"); - } - if (!write(std::to_string(config.monospace_font_size), file)) { - throw std::runtime_error("Failed to write monospace font size value"); - } +void to_json(nlohmann::json& j, const Config& config) { + j["logcat_command"] = config.logcat_command; + j["normal_font_size"] = config.normal_font_size; + j["monospace_font_size"] = config.monospace_font_size; + j["filters"] = config.filters; } void write_config(const Config& config) { @@ -213,7 +97,9 @@ void write_config(const Config& config) { std::string tmp_config_file_path = config_file_path + ".tmp"; std::unique_ptr config_file(fopen_or_raise(tmp_config_file_path.c_str(), "w", false), fclose_and_log); - write_config(config_file.get(), config); + nlohmann::json json_config = config; + std::string str_config = json_config.dump(); + fwrite(str_config.data(), sizeof(char), str_config.size(), config_file.get()); config_file.reset(); if (!rename(tmp_config_file_path.c_str(), config_file_path.c_str())) { diff --git a/config.h b/config.h index 0b8f545..1f6fa5c 100644 --- a/config.h +++ b/config.h @@ -1,14 +1,20 @@ #pragma once #include +#include +#include "filters.h" struct Config { std::string logcat_command; float normal_font_size = 13.0f; float monospace_font_size = 13.0f; + + Filters filters; }; std::string get_config_folder(); void create_config_folders_if_necessary(); +void from_json(const nlohmann::json& j, Config& config); Config load_config(); +void to_json(nlohmann::json& j, const Config& config); void write_config(const Config& config); diff --git a/event_loop.cpp b/event_loop.cpp index c899cca..2d3783a 100644 --- a/event_loop.cpp +++ b/event_loop.cpp @@ -33,9 +33,8 @@ static inline void check_for_logcat_items(LogcatThread& logcat_thread, const Fil } -void event_loop(ImFont* monospace_font, Config& active_config, Filters& active_filters, LogcatThread& logcat_thread, bool* run_event_loop) { +void event_loop(ImFont* monospace_font, Config& active_config, LogcatThread& logcat_thread, bool* run_event_loop) { static Config inactive_config; - static Filters inactive_filters; static bool show_settings_window = false; static bool show_filters_window = false; static bool show_logs_window = false; @@ -43,7 +42,7 @@ void event_loop(ImFont* monospace_font, Config& active_config, Filters& active_f static std::vector logcat_entries; static std::vector filtered_logcat_entry_offsets; - check_for_logcat_items(logcat_thread, active_filters, logcat_entries, filtered_logcat_entry_offsets); + check_for_logcat_items(logcat_thread, active_config.filters, logcat_entries, filtered_logcat_entry_offsets); #ifndef NDEBUG debug_window(logcat_thread); @@ -54,7 +53,7 @@ void event_loop(ImFont* monospace_font, Config& active_config, Filters& active_f } if (show_filters_window) { - filters_window(active_filters, inactive_filters, logcat_entries, filtered_logcat_entry_offsets, &show_filters_window); + filters_window(active_config, inactive_config, logcat_entries, filtered_logcat_entry_offsets, &show_filters_window); } if (show_logs_window) { @@ -69,6 +68,5 @@ void event_loop(ImFont* monospace_font, Config& active_config, Filters& active_f main_window(log_entries_read == log_entries.size(), monospace_font, logcat_entries, filtered_logcat_entry_offsets, active_config, inactive_config, - active_filters, inactive_filters, &show_settings_window, &show_filters_window, &show_logs_window, run_event_loop); } diff --git a/event_loop.h b/event_loop.h index 2bbf0fd..683a7f3 100644 --- a/event_loop.h +++ b/event_loop.h @@ -3,7 +3,6 @@ #include #include "config.h" -#include "filters.h" #include "logcat_thread.h" -void event_loop(ImFont* monospace_font, Config& active_config, Filters& active_filters, LogcatThread& logcat_thread, bool* run_event_loop); +void event_loop(ImFont* monospace_font, Config& active_config, LogcatThread& logcat_thread, bool* run_event_loop); diff --git a/filters.cpp b/filters.cpp index e5c8b1e..3bc0f77 100644 --- a/filters.cpp +++ b/filters.cpp @@ -289,3 +289,158 @@ bool matches(const Filters& filters, const LogcatEntry& entry) { return !ok_filter_exists; } + + +void from_json(const nlohmann::json& j, FilterKey& key) { + const std::string& str = j.get_ref(); + + if (str == "BUFFER") key = FilterKey::Buffer; + else if (str == "USER") key = FilterKey::User; + else if (str == "PID") key = FilterKey::PID; + else if (str == "TID") key = FilterKey::TID; + else if (str == "PRIORITY") key = FilterKey::Priority; + else if (str == "TAG") key = FilterKey::Tag; + else if (str == "MESSAGE") key = FilterKey::Message; + else throw std::invalid_argument(std::string("Unknown filter key: ") + str); +} + +void to_json(nlohmann::json& j, const FilterKey& key) { + switch (key) { + case FilterKey::Buffer: j = "BUFFER"; break; + case FilterKey::User: j = "USER"; break; + case FilterKey::PID: j = "PID"; break; + case FilterKey::TID: j = "TID"; break; + case FilterKey::Priority: j = "PRIORITY"; break; + case FilterKey::Tag: j = "TAG"; break; + case FilterKey::Message: j = "MESSAGE"; break; + } +} + +void from_json(const nlohmann::json& j, GroupFilter::Type& type) { + const std::string& str = j.get_ref(); + + if (str == "ALL") type = GroupFilter::Type::All; + else if (str == "ANY") type = GroupFilter::Type::Any; + else if (str == "ONE") type = GroupFilter::Type::One; + else if (str == "NONE") type = GroupFilter::Type::None; + else throw std::invalid_argument(std::string("Unknown group filter type: ") + str); +} + +void to_json(nlohmann::json& j, const GroupFilter::Type& type) { + switch (type) { + case GroupFilter::Type::All: j = "ALL"; break; + case GroupFilter::Type::Any: j = "ANY"; break; + case GroupFilter::Type::One: j = "ONE"; break; + case GroupFilter::Type::None: j = "NONE"; break; + } +} + +void from_json(const nlohmann::json& j, std::unique_ptr& filter) { + const std::string& filter_type = j.at("type").get_ref(); + bool disabled = j.at("disabled").get(); + + if (filter_type == "INTEGER") { + filter = std::make_unique(j.at("key").get(), j.at("other").get(), j.at("inverted").get(), disabled); + } else if (filter_type == "STRING") { + filter = std::make_unique( + j.at("key").get(), j.at("other").get(), j.at("inverted").get(), j.at("exact_match").get(), disabled); + } else if (filter_type == "BUFFER") { + unsigned int wanted = 0; + nlohmann::json wanted_json = j.at("wanted"); + if (!wanted_json.is_array()) { + throw std::invalid_argument("Wanted buffer items is not an array"); + } + for (nlohmann::json::const_iterator it = wanted_json.cbegin(); it != wanted_json.cend(); it++) { + wanted |= static_cast(it->get()); + } + + filter = std::make_unique(wanted, disabled); + } else if (filter_type == "PRIORITY") { + unsigned int wanted = 0; + nlohmann::json wanted_json = j.at("wanted"); + if (!wanted_json.is_array()) { + throw std::invalid_argument("Wanted priority items is not an array"); + } + for (nlohmann::json::const_iterator it = wanted_json.cbegin(); it != wanted_json.cend(); it++) { + wanted |= static_cast(it->get()); + } + + filter = std::make_unique(wanted, disabled); + } else if (filter_type == "GROUP") { + filter = std::make_unique( + j.at("filters").get>>(), j.at("group_type").get(), disabled); + } else { + throw std::invalid_argument(std::string("Unknown filter type: ") + filter_type); + } +} + +void to_json(nlohmann::json& j, const std::unique_ptr& filter) { + j["disabled"] = filter->disabled(); + + if (const IntegerFilter* ifilter = dynamic_cast(filter.get())) { + j["type"] = "INTEGER"; + j["key"] = ifilter->key; + j["other"] = ifilter->other; + j["inverted"] = ifilter->inverted; + } else if (const StringFilter* sfilter = dynamic_cast(filter.get())) { + j["type"] = "STRING"; + j["key"] = sfilter->key; + j["other"] = sfilter->other; + j["inverted"] = sfilter->inverted; + j["exact_match"] = sfilter->exact_match; + } else if (const BufferFilter* bfilter = dynamic_cast(filter.get())) { + j["type"] = "BUFFER"; + j["wanted"] = nlohmann::json::array(); + if (bfilter->wanted & static_cast(Buffer::Unknown)) { + j["wanted"].emplace_back(Buffer::Unknown); + } + if (bfilter->wanted & static_cast(Buffer::Main)) { + j["wanted"].emplace_back(Buffer::Main); + } + if (bfilter->wanted & static_cast(Buffer::System)) { + j["wanted"].emplace_back(Buffer::System); + } + if (bfilter->wanted & static_cast(Buffer::Radio)) { + j["wanted"].emplace_back(Buffer::Radio); + } + if (bfilter->wanted & static_cast(Buffer::Events)) { + j["wanted"].emplace_back(Buffer::Events); + } + if (bfilter->wanted & static_cast(Buffer::Crash)) { + j["wanted"].emplace_back(Buffer::Crash); + } + } else if (const PriorityFilter* pfilter = dynamic_cast(filter.get())) { + j["type"] = "PRIORITY"; + j["wanted"] = nlohmann::json::array(); + if (pfilter->wanted & static_cast(Priority::Unknown)) { + j["wanted"].emplace_back(Priority::Unknown); + } + if (pfilter->wanted & static_cast(Priority::Verbose)) { + j["wanted"].emplace_back(Priority::Verbose); + } + if (pfilter->wanted & static_cast(Priority::Debug)) { + j["wanted"].emplace_back(Priority::Debug); + } + if (pfilter->wanted & static_cast(Priority::Info)) { + j["wanted"].emplace_back(Priority::Info); + } + if (pfilter->wanted & static_cast(Priority::Warn)) { + j["wanted"].emplace_back(Priority::Warn); + } + if (pfilter->wanted & static_cast(Priority::Error)) { + j["wanted"].emplace_back(Priority::Error); + } + if (pfilter->wanted & static_cast(Priority::Fatal)) { + j["wanted"].emplace_back(Priority::Fatal); + } + } else if (const GroupFilter* gfilter = dynamic_cast(filter.get())) { + j["type"] = "GROUP"; + j["group_type"] = gfilter->type; + j["filters"] = nlohmann::json::array(); + for (const std::unique_ptr& i : gfilter->filters) { + j["filters"].emplace_back(i); + } + } else { + throw std::invalid_argument("Cannot serialize unknown filter"); + } +} diff --git a/filters.h b/filters.h index 5f9bf19..076e541 100644 --- a/filters.h +++ b/filters.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "logcat_entry.h" #include "pcre2_wrapper.h" @@ -34,7 +35,7 @@ public: class IntegerFilter : public Filter { public: - IntegerFilter(FilterKey key_, size_t other_, bool inverted_ = false, bool disabled = false); + IntegerFilter(FilterKey key_, size_t other_, bool inverted_, bool disabled); void updated() override; bool disabled() const override; @@ -57,7 +58,7 @@ public: StringFilter(const StringFilter&) = delete; StringFilter& operator=(const StringFilter&) = delete; - StringFilter(FilterKey key_, std::string other_, bool inverted_ = false, bool exact_match_ = true, bool disabled = false); + StringFilter(FilterKey key_, std::string other_, bool inverted_, bool exact_match_, bool disabled); void updated() override; bool disabled() const override; @@ -81,7 +82,7 @@ private: class BufferFilter : public Filter { public: - BufferFilter(unsigned int wanted_, bool disabled = false); + BufferFilter(unsigned int wanted_, bool disabled); void updated() override; bool disabled() const override; @@ -122,7 +123,7 @@ public: None = 3, }; - GroupFilter(std::vector> filters_, Type type_, bool disabled = false); + GroupFilter(std::vector> filters_, Type type_, bool disabled); void updated() override; bool disabled() const override; @@ -141,3 +142,10 @@ private: typedef std::vector>> Filters; void copy_filters(Filters& filters, const Filters& other); bool matches(const Filters& filters, const LogcatEntry& entry); + +void from_json(const nlohmann::json& j, FilterKey& key); +void to_json(nlohmann::json& j, const FilterKey& key); +void from_json(const nlohmann::json& j, GroupFilter::Type& type); +void to_json(nlohmann::json& j, const GroupFilter::Type& type); +void from_json(const nlohmann::json& j, std::unique_ptr& filter); +void to_json(nlohmann::json& j, const std::unique_ptr& filter); diff --git a/logcat_entry.cpp b/logcat_entry.cpp index 119967b..edcde21 100644 --- a/logcat_entry.cpp +++ b/logcat_entry.cpp @@ -122,3 +122,52 @@ std::optional try_parse_buffer(char* buf, size_t length) { if (!strncmp(buffer_str, "crash", 5)) return Buffer::Crash; return Buffer::Unknown; } + + +void from_json(const nlohmann::json& j, Buffer& buffer) { + const std::string& str = j.get_ref(); + + if (str == "UNKNOWN") buffer = Buffer::Unknown; + else if (str == "MAIN") buffer = Buffer::Main; + else if (str == "SYSTEM") buffer = Buffer::System; + else if (str == "RADIO") buffer = Buffer::Radio; + else if (str == "EVENTS") buffer = Buffer::Events; + else if (str == "CRASH") buffer = Buffer::Crash; + else throw std::invalid_argument(std::string("Unknown buffer value: ") + str); +} + +void to_json(nlohmann::json& j, const Buffer& buffer) { + switch (buffer) { + case Buffer::Unknown: j = "UNKNOWN"; break; + case Buffer::Main: j = "MAIN"; break; + case Buffer::System: j = "SYSTEM"; break; + case Buffer::Radio: j = "RADIO"; break; + case Buffer::Events: j = "EVENTS"; break; + case Buffer::Crash: j = "CRASH"; break; + } +} + +void from_json(const nlohmann::json& j, Priority& priority) { + const std::string& str = j.get_ref(); + + if (str == "UNKNOWN") priority = Priority::Unknown; + else if (str == "VERBOSE") priority = Priority::Verbose; + else if (str == "DEBUG") priority = Priority::Debug; + else if (str == "INFO") priority = Priority::Info; + else if (str == "WARN") priority = Priority::Warn; + else if (str == "ERROR") priority = Priority::Error; + else if (str == "FATAL") priority = Priority::Fatal; + else throw std::invalid_argument(std::string("Unknown priority value: ") + str); +} + +void to_json(nlohmann::json& j, const Priority& priority) { + switch (priority) { + case Priority::Unknown: j = "UNKNOWN"; break; + case Priority::Verbose: j = "VERBOSE"; break; + case Priority::Debug: j = "DEBUG"; break; + case Priority::Info: j = "INFO"; break; + case Priority::Warn: j = "WARN"; break; + case Priority::Error: j = "ERROR"; break; + case Priority::Fatal: j = "FATAL"; break; + } +} diff --git a/logcat_entry.h b/logcat_entry.h index dc53313..bb3c517 100644 --- a/logcat_entry.h +++ b/logcat_entry.h @@ -2,6 +2,7 @@ #include #include +#include enum class Buffer { Unknown = 0b1, @@ -38,3 +39,8 @@ const char* priority_to(Priority priority); const char* buffer_to(Buffer buffer); std::optional try_parse_logcat_entry(char* buf, size_t length, Buffer buffer); std::optional try_parse_buffer(char* buf, size_t length); + +void from_json(const nlohmann::json& j, Buffer& buffer); +void to_json(nlohmann::json& j, const Buffer& buffer); +void from_json(const nlohmann::json& j, Priority& priority); +void to_json(nlohmann::json& j, const Priority& priority); diff --git a/main.cpp b/main.cpp index c311bb9..e96550c 100644 --- a/main.cpp +++ b/main.cpp @@ -23,8 +23,6 @@ int main(int, char**) { setlocale(LC_TIME, ""); - // TODO add saving - Filters filters; Config config; try { config = load_config(); @@ -164,7 +162,7 @@ int main(int, char**) { ImGui_ImplSDL2_NewFrame(); ImGui::NewFrame(); - event_loop(monospace_font, config, filters, logcat_thread, &run_event_loop); + event_loop(monospace_font, config, logcat_thread, &run_event_loop); // Rendering ImGui::Render(); diff --git a/windows/filters.cpp b/windows/filters.cpp index fbffd15..5b63183 100644 --- a/windows/filters.cpp +++ b/windows/filters.cpp @@ -3,6 +3,7 @@ #include "../group_panel.h" #include "../filters.h" +#include "../config.h" #include "filters.h" static inline void render_integer_filter(IntegerFilter* filter); @@ -13,6 +14,7 @@ static inline void render_group_filter(GroupFilter* filter); static std::unique_ptr render_add_filter_popup(); static void update_logcat_entries(const Filters& filters, const std::vector& logcat_entries, std::vector& filtered_logcat_entry_offsets); +static void try_write_config(const Config& config); static void render_filter(Filter* filter, std::string* title, bool* request_removal) { ImGui::PushID(filter); @@ -182,21 +184,21 @@ static inline void render_group_filter(GroupFilter* filter) { static std::unique_ptr render_add_filter_popup() { if (ImGui::Selectable("Buffer")) { - return std::make_unique(0); + return std::make_unique(0, false); } else if (ImGui::Selectable("User")) { - return std::make_unique(FilterKey::User, ""); + return std::make_unique(FilterKey::User, "", false, true, false); } else if (ImGui::Selectable("PID")) { - return std::make_unique(FilterKey::PID, 0); + return std::make_unique(FilterKey::PID, 0, false, false); } else if (ImGui::Selectable("TID")) { - return std::make_unique(FilterKey::TID, 0); + return std::make_unique(FilterKey::TID, 0, false, false); } else if (ImGui::Selectable("Priority")) { - return std::make_unique(0); + return std::make_unique(0, false); } else if (ImGui::Selectable("Tag")) { - return std::make_unique(FilterKey::Tag, ""); + return std::make_unique(FilterKey::Tag, "", false, true, false); } else if (ImGui::Selectable("Message")) { - return std::make_unique(FilterKey::Message, ""); + return std::make_unique(FilterKey::Message, "", false, true, false); } else if (ImGui::Selectable("Group of filters")) { - return std::make_unique(std::vector>(), GroupFilter::Type::All); + return std::make_unique(std::vector>(), GroupFilter::Type::All, false); } return std::unique_ptr(); @@ -212,7 +214,15 @@ static void update_logcat_entries(const Filters& filters, } } -void filters_window(Filters& active_filters, Filters& inactive_filters, +static void try_write_config(const Config& config) { + try { + write_config(config); + } catch (const std::exception& e) { + log(std::string("Failed to write config: ") + e.what()); + } +} + +void filters_window(Config& active_config, Config& inactive_config, const std::vector& logcat_entries, std::vector& filtered_logcat_entry_offsets, bool* p_open) { if (!ImGui::Begin("Filters", p_open)) { @@ -222,11 +232,11 @@ void filters_window(Filters& active_filters, Filters& inactive_filters, ImGui::TextUnformatted("You can use regex for strings by prepending \"regex:\""); - for (Filters::iterator it = inactive_filters.begin(); it != inactive_filters.end();) { + for (Filters::iterator it = inactive_config.filters.begin(); it != inactive_config.filters.end();) { bool removal_requested = false; render_filter(it->second.get(), &it->first, &removal_requested); if (removal_requested) { - inactive_filters.erase(it); + inactive_config.filters.erase(it); } else { it++; } @@ -238,7 +248,7 @@ void filters_window(Filters& active_filters, Filters& inactive_filters, if (ImGui::BeginPopup("addfilter_root")) { std::unique_ptr added_filter = render_add_filter_popup(); if (added_filter) { - inactive_filters.push_back(std::make_pair("", std::move(added_filter))); + inactive_config.filters.push_back(std::make_pair("", std::move(added_filter))); } ImGui::EndPopup(); } @@ -246,8 +256,9 @@ void filters_window(Filters& active_filters, Filters& inactive_filters, ImGui::Separator(); ImVec2 button_size(4 * ImGui::GetFontSize(), 0); if (ImGui::Button("OK", button_size)) { - active_filters = std::move(inactive_filters); - update_logcat_entries(active_filters, logcat_entries, filtered_logcat_entry_offsets); + active_config.filters = std::move(inactive_config.filters); + try_write_config(active_config); + update_logcat_entries(active_config.filters, logcat_entries, filtered_logcat_entry_offsets); *p_open = false; } ImGui::SameLine(); @@ -256,8 +267,9 @@ void filters_window(Filters& active_filters, Filters& inactive_filters, } ImGui::SameLine(); if (ImGui::Button("Apply", button_size)) { - copy_filters(active_filters, inactive_filters); - update_logcat_entries(active_filters, logcat_entries, filtered_logcat_entry_offsets); + copy_filters(active_config.filters, inactive_config.filters); + try_write_config(active_config); + update_logcat_entries(active_config.filters, logcat_entries, filtered_logcat_entry_offsets); } ImGui::End(); } diff --git a/windows/filters.h b/windows/filters.h index 2183699..823597c 100644 --- a/windows/filters.h +++ b/windows/filters.h @@ -3,8 +3,8 @@ #include #include "../logcat_entry.h" -#include "../filters.h" +#include "../config.h" -void filters_window(Filters& active_filters, Filters& inactive_filters, +void filters_window(Config& active_config, Config& inactive_config, const std::vector& logcat_entries, std::vector& filtered_logcat_entry_offsets, bool* p_open); diff --git a/windows/main.cpp b/windows/main.cpp index de0408f..64dea2d 100644 --- a/windows/main.cpp +++ b/windows/main.cpp @@ -55,7 +55,6 @@ static inline void render_table(ImFont* monospace_font, std::vector void main_window(bool latest_log_entries_read, ImFont* monospace_font, std::vector& logcat_entries, std::vector& filtered_logcat_entry_offsets, const Config& active_config, Config& inactive_config, - const Filters& active_filters, Filters& inactive_filters, bool* show_settings_window, bool* show_filters_window, bool* show_logs_window, bool* run_event_loop) { ImGui::SetNextWindowPos(ImGui::GetMainViewport()->WorkPos); @@ -67,13 +66,15 @@ void main_window(bool latest_log_entries_read, ImFont* monospace_font, } if (ImGui::Button("Settings") && !*show_settings_window) { - inactive_config = active_config; + inactive_config.logcat_command = active_config.logcat_command; + inactive_config.normal_font_size = active_config.normal_font_size; + inactive_config.monospace_font_size = active_config.monospace_font_size; *show_settings_window = true; } ImGui::SameLine(); if (ImGui::Button("Filters") && !*show_filters_window) { - copy_filters(inactive_filters, active_filters); + copy_filters(inactive_config.filters, active_config.filters); *show_filters_window = true; } diff --git a/windows/main.h b/windows/main.h index 18f168f..e9750e4 100644 --- a/windows/main.h +++ b/windows/main.h @@ -4,11 +4,9 @@ #include #include "../config.h" -#include "../filters.h" #include "../logcat_entry.h" void main_window(bool latest_log_entries_read, ImFont* monospace_font, std::vector& logcat_entries, std::vector& filtered_logcat_entry_offsets, const Config& active_config, Config& inactive_config, - const Filters& active_filters, Filters& inactive_filters, bool* show_settings_window, bool* show_filters_window, bool* show_logs_window, bool* run_event_loop); diff --git a/windows/settings.cpp b/windows/settings.cpp index c1f6d9e..d982914 100644 --- a/windows/settings.cpp +++ b/windows/settings.cpp @@ -4,12 +4,11 @@ #include "../config.h" #include "settings.h" -static void write_config_and_update_structures(const Config& config) { +static void try_write_config(const Config& config) { try { write_config(config); } catch (const std::exception& e) { log(std::string("Failed to write config: ") + e.what()); - return; } } @@ -31,8 +30,10 @@ void settings_window(Config& active_config, Config& inactive_config, bool* p_ope ImGui::Separator(); ImVec2 button_size(4 * ImGui::GetFontSize(), 0); if (ImGui::Button("OK", button_size)) { - active_config = std::move(inactive_config); - write_config_and_update_structures(active_config); + active_config.logcat_command = std::move(inactive_config.logcat_command); + active_config.normal_font_size = inactive_config.normal_font_size; + active_config.monospace_font_size = inactive_config.monospace_font_size; + try_write_config(active_config); *p_open = false; } ImGui::SameLine(); @@ -41,8 +42,10 @@ void settings_window(Config& active_config, Config& inactive_config, bool* p_ope } ImGui::SameLine(); if (ImGui::Button("Apply", button_size)) { - active_config = inactive_config; - write_config_and_update_structures(active_config); + active_config.logcat_command = inactive_config.logcat_command; + active_config.normal_font_size = inactive_config.normal_font_size; + active_config.monospace_font_size = inactive_config.monospace_font_size; + try_write_config(active_config); } ImGui::End(); }