From d62822640cf5322c46038722533de56e6baa17e2 Mon Sep 17 00:00:00 2001 From: blankie Date: Wed, 1 Feb 2023 22:22:08 +0700 Subject: [PATCH] Add exclusions --- CMakeLists.txt | 2 +- config.cpp | 2 + config.h | 1 + event_loop.cpp | 13 +- filters.cpp | 14 ++- filters.h | 2 +- fragments/filters.cpp | 269 +++++++++++++++++++++++++++++++++++++++++ fragments/filters.h | 9 ++ windows/exclusions.cpp | 19 +++ windows/exclusions.h | 10 ++ windows/filters.cpp | 260 +-------------------------------------- windows/main.cpp | 8 +- windows/main.h | 2 +- 13 files changed, 339 insertions(+), 272 deletions(-) create mode 100644 fragments/filters.cpp create mode 100644 fragments/filters.h create mode 100644 windows/exclusions.cpp create mode 100644 windows/exclusions.h diff --git a/CMakeLists.txt b/CMakeLists.txt index caef769..b4e22a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ set(IMGUI_LIBS SDL2 Freetype::Freetype) set(INCLUDES imgui imgui/backends imgui/misc/cpp imgui/freetype /usr/include/SDL2) set(SOURCES main.cpp event_loop.cpp logcat_thread.cpp logcat_entry.cpp log.cpp config.cpp filters.cpp misc.cpp pcre2_wrapper.cpp - group_panel.cpp windows/logs.cpp windows/settings.cpp windows/filters.cpp windows/main.cpp) + group_panel.cpp fragments/filters.cpp windows/logs.cpp windows/settings.cpp windows/filters.cpp windows/exclusions.cpp windows/main.cpp) set(IMGUI_SOURCES imgui/imgui.cpp imgui/imgui_draw.cpp imgui/imgui_widgets.cpp imgui/imgui_tables.cpp imgui/misc/cpp/imgui_stdlib.cpp imgui/misc/freetype/imgui_freetype.cpp imgui/backends/imgui_impl_sdl.cpp imgui/backends/imgui_impl_opengl3.cpp) diff --git a/config.cpp b/config.cpp index a5e1f06..10446f2 100644 --- a/config.cpp +++ b/config.cpp @@ -71,6 +71,7 @@ void from_json(const nlohmann::json& j, Config& config) { 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); + j.at("exclusions").get_to(config.exclusions); } Config load_config() { @@ -90,6 +91,7 @@ void to_json(nlohmann::json& j, const Config& config) { j["normal_font_size"] = config.normal_font_size; j["monospace_font_size"] = config.monospace_font_size; j["filters"] = config.filters; + j["exclusions"] = config.exclusions; } void write_config(const Config& config) { diff --git a/config.h b/config.h index 1f6fa5c..5555ff4 100644 --- a/config.h +++ b/config.h @@ -10,6 +10,7 @@ struct Config { float monospace_font_size = 13.0f; Filters filters; + Filters exclusions; }; std::string get_config_folder(); diff --git a/event_loop.cpp b/event_loop.cpp index 2d3783a..db6d030 100644 --- a/event_loop.cpp +++ b/event_loop.cpp @@ -7,13 +7,14 @@ #include "windows/logs.h" #include "windows/filters.h" +#include "windows/exclusions.h" #include "windows/settings.h" #include "windows/main.h" #ifndef NDEBUG #include "windows/debug.h" #endif -static inline void check_for_logcat_items(LogcatThread& logcat_thread, const Filters& filters, +static inline void check_for_logcat_items(LogcatThread& logcat_thread, const Config& active_config, std::vector& logcat_entries, std::vector& filtered_logcat_entry_offsets) { LogcatThreadItem* logcat_thread_item; @@ -22,7 +23,7 @@ static inline void check_for_logcat_items(LogcatThread& logcat_thread, const Fil log(std::move(std::get(*logcat_thread_item)), false); } else if (std::holds_alternative(*logcat_thread_item)) { logcat_entries.push_back(std::move(std::get(*logcat_thread_item))); - if (matches(filters, logcat_entries.back())) { + if (matches(logcat_entries.back(), active_config.filters, active_config.exclusions)) { filtered_logcat_entry_offsets.push_back(logcat_entries.size() - 1); } } else { @@ -37,12 +38,13 @@ void event_loop(ImFont* monospace_font, Config& active_config, LogcatThread& log static Config inactive_config; static bool show_settings_window = false; static bool show_filters_window = false; + static bool show_exclusions_window = false; static bool show_logs_window = false; static size_t log_entries_read = 0; static std::vector logcat_entries; static std::vector filtered_logcat_entry_offsets; - check_for_logcat_items(logcat_thread, active_config.filters, logcat_entries, filtered_logcat_entry_offsets); + check_for_logcat_items(logcat_thread, active_config, logcat_entries, filtered_logcat_entry_offsets); #ifndef NDEBUG debug_window(logcat_thread); @@ -55,6 +57,9 @@ void event_loop(ImFont* monospace_font, Config& active_config, LogcatThread& log if (show_filters_window) { filters_window(active_config, inactive_config, logcat_entries, filtered_logcat_entry_offsets, &show_filters_window); } + if (show_exclusions_window) { + exclusions_window(active_config, inactive_config, logcat_entries, filtered_logcat_entry_offsets, &show_exclusions_window); + } if (show_logs_window) { bool autoscrolling = false; @@ -68,5 +73,5 @@ void event_loop(ImFont* monospace_font, Config& active_config, LogcatThread& log main_window(log_entries_read == log_entries.size(), monospace_font, logcat_entries, filtered_logcat_entry_offsets, active_config, inactive_config, - &show_settings_window, &show_filters_window, &show_logs_window, run_event_loop); + &show_settings_window, &show_filters_window, &show_exclusions_window, &show_logs_window, run_event_loop); } diff --git a/filters.cpp b/filters.cpp index 3bc0f77..d8b378f 100644 --- a/filters.cpp +++ b/filters.cpp @@ -274,20 +274,22 @@ void copy_filters(Filters& filters, const Filters& other) { } } -bool matches(const Filters& filters, const LogcatEntry& entry) { - bool ok_filter_exists = false; - - for (const auto &[title, filter] : filters) { +static bool matches(const LogcatEntry& entry, const Filters& filters, bool return_true_if_empty) { + for (const auto &[_, filter] : filters) { if (filter->disabled() || filter->error()) { continue; } - ok_filter_exists = true; if (filter->match(entry)) { return true; } + return_true_if_empty = false; } - return !ok_filter_exists; + return return_true_if_empty; +} + +bool matches(const LogcatEntry& entry, const Filters& filters, const Filters& exclusions) { + return !matches(entry, exclusions, false) && matches(entry, filters, true); } diff --git a/filters.h b/filters.h index 076e541..b097afb 100644 --- a/filters.h +++ b/filters.h @@ -141,7 +141,7 @@ private: typedef std::vector>> Filters; void copy_filters(Filters& filters, const Filters& other); -bool matches(const Filters& filters, const LogcatEntry& entry); +bool matches(const LogcatEntry& entry, const Filters& filters, const Filters& exclusions); void from_json(const nlohmann::json& j, FilterKey& key); void to_json(nlohmann::json& j, const FilterKey& key); diff --git a/fragments/filters.cpp b/fragments/filters.cpp new file mode 100644 index 0000000..aaf3d33 --- /dev/null +++ b/fragments/filters.cpp @@ -0,0 +1,269 @@ +#include +#include + +#include "../group_panel.h" +#include "../filters.h" +#include "../config.h" +#include "filters.h" + +static inline void render_integer_filter(IntegerFilter* filter); +static inline void render_string_filter(StringFilter* filter); +static inline void render_buffer_filter(BufferFilter* filter); +static inline void render_priority_filter(PriorityFilter* filter); +static inline void render_group_filter(GroupFilter* filter); +static std::unique_ptr render_add_filter_popup(); +static void update_logcat_entries(const Config& active_config, + 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); + ImGui::BeginGroupPanel(); + + if (title) { + ImGui::AlignTextToFramePadding(); + ImGui::Text("Title:%s%s", title->empty() ? "" : " ", title->c_str()); + ImGui::SameLine(); + std::string change_title_id = std::string("changefiltertitle_") + std::to_string(reinterpret_cast(filter)); + if (ImGui::Button("Edit")) { + ImGui::OpenPopup(change_title_id.c_str()); + } + if (ImGui::BeginPopup(change_title_id.c_str())) { + ImGui::InputText("##title", title); + ImGui::EndPopup(); + } + ImGui::SameLine(); + } + + if (ImGui::Button("Remove")) { + *request_removal = true; + } + + { + ImGui::SameLine(); + bool disabled = filter->disabled(); + if (ImGui::Checkbox("Disabled", &disabled)) { + filter->disabled(disabled); + } + } + + { + StringFilter* sfilter = dynamic_cast(filter); + IntegerFilter* ifilter = !sfilter ? dynamic_cast(filter) : nullptr; + if (sfilter || ifilter) { + ImGui::SameLine(); + ImGui::Checkbox("Inverted", sfilter ? &sfilter->inverted : &ifilter->inverted); + } + if (sfilter) { + ImGui::SameLine(); + ImGui::Checkbox("Exact match", &sfilter->exact_match); + } + } + + if (filter->error()) { + ImGui::SameLine(); + ImGui::Text("(%s)", filter->error()->c_str()); + } + + if (IntegerFilter* ifilter = dynamic_cast(filter)) { + render_integer_filter(ifilter); + } else if (StringFilter* sfilter = dynamic_cast(filter)) { + render_string_filter(sfilter); + } else if (BufferFilter* bfilter = dynamic_cast(filter)) { + render_buffer_filter(bfilter); + } else if (PriorityFilter* pfilter = dynamic_cast(filter)) { + render_priority_filter(pfilter); + } else if (GroupFilter* gfilter = dynamic_cast(filter)) { + render_group_filter(gfilter); + } else { + ImGui::TextUnformatted("An unknown filter, this probably shouldn't be mutated"); + } + + ImGui::EndGroupPanel(); + ImGui::PopID(); +} + +static inline void render_integer_filter(IntegerFilter* filter) { + const char* head; + switch (filter->key) { + case FilterKey::PID: head = "PID"; break; + case FilterKey::TID: head = "TID"; break; + default: head = "Something"; + }; + + ImGui::AlignTextToFramePadding(); + ImGui::Text("%s is%s", head, filter->inverted ? " not" : ""); + ImGui::SameLine(); + if (ImGui::InputScalar("##int", ImGuiDataType_U64, &filter->other)) { + filter->updated(); + } +} + +static inline void render_string_filter(StringFilter* filter) { + const char* head; + switch (filter->key) { + case FilterKey::User: head = "User"; break; + case FilterKey::Tag: head = "Tag"; break; + case FilterKey::Message: head = "Message"; break; + default: head = "Something"; + }; + + ImGui::AlignTextToFramePadding(); + ImGui::Text("%s %s", head, filter->exact_match + ? (filter->inverted ? "is not" : "is") + : (filter->inverted ? "doesn't have" : "has")); + ImGui::SameLine(); + if (ImGui::InputText("##str", &filter->other)) { + filter->updated(); + } +} + +static inline void render_buffer_filter(BufferFilter* filter) { + auto update_if_needed = [&](bool updated) { + if (updated) { + filter->updated(); + } + }; + ImGui::AlignTextToFramePadding(); + ImGui::TextUnformatted("Buffer is:"); ImGui::SameLine(); + update_if_needed(ImGui::CheckboxFlags("Unknown", &filter->wanted, static_cast(Buffer::Unknown))); ImGui::SameLine(); + update_if_needed(ImGui::CheckboxFlags("Main", &filter->wanted, static_cast(Buffer::Main))); ImGui::SameLine(); + update_if_needed(ImGui::CheckboxFlags("System", &filter->wanted, static_cast(Buffer::System))); ImGui::SameLine(); + update_if_needed(ImGui::CheckboxFlags("Radio", &filter->wanted, static_cast(Buffer::Radio))); ImGui::SameLine(); + update_if_needed(ImGui::CheckboxFlags("Events", &filter->wanted, static_cast(Buffer::Events))); ImGui::SameLine(); + update_if_needed(ImGui::CheckboxFlags("Crash", &filter->wanted, static_cast(Buffer::Crash))); +} + +static inline void render_priority_filter(PriorityFilter* filter) { + auto update_if_needed = [&](bool updated) { + if (updated) { + filter->updated(); + } + }; + ImGui::AlignTextToFramePadding(); + ImGui::TextUnformatted("Priority is:"); ImGui::SameLine(); + update_if_needed(ImGui::CheckboxFlags("Unknown", &filter->wanted, static_cast(Priority::Unknown))); ImGui::SameLine(); + update_if_needed(ImGui::CheckboxFlags("Verbose", &filter->wanted, static_cast(Priority::Verbose))); ImGui::SameLine(); + update_if_needed(ImGui::CheckboxFlags("Debug", &filter->wanted, static_cast(Priority::Debug))); ImGui::SameLine(); + update_if_needed(ImGui::CheckboxFlags("Info", &filter->wanted, static_cast(Priority::Info))); ImGui::SameLine(); + update_if_needed(ImGui::CheckboxFlags("Warning", &filter->wanted, static_cast(Priority::Warn))); ImGui::SameLine(); + update_if_needed(ImGui::CheckboxFlags("Error", &filter->wanted, static_cast(Priority::Error))); ImGui::SameLine(); + update_if_needed(ImGui::CheckboxFlags("Fatal", &filter->wanted, static_cast(Priority::Fatal))); +} + +static inline void render_group_filter(GroupFilter* filter) { + int selected_type = static_cast(filter->type); + if (ImGui::Combo("of these are true", &selected_type, "All\0Any\0One\0None\0")) { + filter->type = static_cast(selected_type); + } + + for (std::vector>::iterator it = filter->filters.begin(); it != filter->filters.end();) { + bool removal_requested = false; + render_filter(it->get(), nullptr, &removal_requested); + if (removal_requested) { + filter->filters.erase(it); + filter->updated(); + } else { + it++; + } + } + + std::string add_filter_id = std::string("addfilter_") + std::to_string(reinterpret_cast(filter)); + if (ImGui::Button("+ add filter")) { + ImGui::OpenPopup(add_filter_id.c_str()); + } + if (ImGui::BeginPopup(add_filter_id.c_str())) { + std::unique_ptr added_filter = render_add_filter_popup(); + if (added_filter) { + filter->filters.push_back(std::move(added_filter)); + filter->updated(); + } + ImGui::EndPopup(); + } +} + +static std::unique_ptr render_add_filter_popup() { + if (ImGui::Selectable("Buffer")) { + return std::make_unique(0, false); + } else if (ImGui::Selectable("User")) { + return std::make_unique(FilterKey::User, "", false, true, false); + } else if (ImGui::Selectable("PID")) { + return std::make_unique(FilterKey::PID, 0, false, false); + } else if (ImGui::Selectable("TID")) { + return std::make_unique(FilterKey::TID, 0, false, false); + } else if (ImGui::Selectable("Priority")) { + return std::make_unique(0, false); + } else if (ImGui::Selectable("Tag")) { + return std::make_unique(FilterKey::Tag, "", false, true, false); + } else if (ImGui::Selectable("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, false); + } + + return std::unique_ptr(); +} + +static void update_logcat_entries(const Config& active_config, + const std::vector& logcat_entries, std::vector& filtered_logcat_entry_offsets) { + filtered_logcat_entry_offsets.clear(); + for (size_t i=0; i < logcat_entries.size(); i++) { + if (matches(logcat_entries[i], active_config.filters, active_config.exclusions)) { + filtered_logcat_entry_offsets.push_back(i); + } + } +} + +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_fragment(Config& active_config, Filters& active_filters, Filters& inactive_filters, + const std::vector& logcat_entries, std::vector& filtered_logcat_entry_offsets, + bool* p_open) { + ImGui::TextUnformatted("You can use regex for strings by prepending \"regex:\""); + + for (Filters::iterator it = inactive_filters.begin(); it != inactive_filters.end();) { + bool removal_requested = false; + render_filter(it->second.get(), &it->first, &removal_requested); + if (removal_requested) { + inactive_filters.erase(it); + } else { + it++; + } + } + + if (ImGui::Button("+ add filter")) { + ImGui::OpenPopup("addfilter_root"); + } + 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))); + } + ImGui::EndPopup(); + } + + ImGui::Separator(); + ImVec2 button_size(4 * ImGui::GetFontSize(), 0); + if (ImGui::Button("OK", button_size)) { + active_filters = std::move(inactive_filters); + try_write_config(active_config); + update_logcat_entries(active_config, logcat_entries, filtered_logcat_entry_offsets); + *p_open = false; + } + ImGui::SameLine(); + if (ImGui::Button("Cancel", button_size)) { + *p_open = false; + } + ImGui::SameLine(); + if (ImGui::Button("Apply", button_size)) { + copy_filters(active_filters, inactive_filters); + try_write_config(active_config); + update_logcat_entries(active_config, logcat_entries, filtered_logcat_entry_offsets); + } +} diff --git a/fragments/filters.h b/fragments/filters.h new file mode 100644 index 0000000..728ec55 --- /dev/null +++ b/fragments/filters.h @@ -0,0 +1,9 @@ +#pragma once + +#include +#include "../config.h" +#include "../filters.h" + +void filters_fragment(Config& active_config, Filters& active_filters, Filters& inactive_filters, + const std::vector& logcat_entries, std::vector& filtered_logcat_entry_offsets, + bool* p_open); diff --git a/windows/exclusions.cpp b/windows/exclusions.cpp new file mode 100644 index 0000000..3bd8b35 --- /dev/null +++ b/windows/exclusions.cpp @@ -0,0 +1,19 @@ +#include + +#include "../fragments/filters.h" +#include "../filters.h" +#include "../config.h" +#include "exclusions.h" + +void exclusions_window(Config& active_config, Config& inactive_config, + const std::vector& logcat_entries, std::vector& filtered_logcat_entry_offsets, + bool* p_open) { + if (!ImGui::Begin("Exclusions", p_open)) { + ImGui::End(); + return; + } + + filters_fragment(active_config, active_config.exclusions, inactive_config.exclusions, logcat_entries, filtered_logcat_entry_offsets, p_open); + + ImGui::End(); +} diff --git a/windows/exclusions.h b/windows/exclusions.h new file mode 100644 index 0000000..cb97c43 --- /dev/null +++ b/windows/exclusions.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +#include "../logcat_entry.h" +#include "../config.h" + +void exclusions_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/filters.cpp b/windows/filters.cpp index 5b63183..84b47ee 100644 --- a/windows/filters.cpp +++ b/windows/filters.cpp @@ -1,227 +1,10 @@ #include -#include -#include "../group_panel.h" +#include "../fragments/filters.h" #include "../filters.h" #include "../config.h" #include "filters.h" -static inline void render_integer_filter(IntegerFilter* filter); -static inline void render_string_filter(StringFilter* filter); -static inline void render_buffer_filter(BufferFilter* filter); -static inline void render_priority_filter(PriorityFilter* filter); -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); - ImGui::BeginGroupPanel(); - - if (title) { - ImGui::AlignTextToFramePadding(); - ImGui::Text("Title:%s%s", title->empty() ? "" : " ", title->c_str()); - ImGui::SameLine(); - std::string change_title_id = std::string("changefiltertitle_") + std::to_string(reinterpret_cast(filter)); - if (ImGui::Button("Edit")) { - ImGui::OpenPopup(change_title_id.c_str()); - } - if (ImGui::BeginPopup(change_title_id.c_str())) { - ImGui::InputText("##title", title); - ImGui::EndPopup(); - } - ImGui::SameLine(); - } - - if (ImGui::Button("Remove")) { - *request_removal = true; - } - - { - ImGui::SameLine(); - bool disabled = filter->disabled(); - if (ImGui::Checkbox("Disabled", &disabled)) { - filter->disabled(disabled); - } - } - - { - StringFilter* sfilter = dynamic_cast(filter); - IntegerFilter* ifilter = !sfilter ? dynamic_cast(filter) : nullptr; - if (sfilter || ifilter) { - ImGui::SameLine(); - ImGui::Checkbox("Inverted", sfilter ? &sfilter->inverted : &ifilter->inverted); - } - if (sfilter) { - ImGui::SameLine(); - ImGui::Checkbox("Exact match", &sfilter->exact_match); - } - } - - if (filter->error()) { - ImGui::SameLine(); - ImGui::Text("(%s)", filter->error()->c_str()); - } - - if (IntegerFilter* ifilter = dynamic_cast(filter)) { - render_integer_filter(ifilter); - } else if (StringFilter* sfilter = dynamic_cast(filter)) { - render_string_filter(sfilter); - } else if (BufferFilter* bfilter = dynamic_cast(filter)) { - render_buffer_filter(bfilter); - } else if (PriorityFilter* pfilter = dynamic_cast(filter)) { - render_priority_filter(pfilter); - } else if (GroupFilter* gfilter = dynamic_cast(filter)) { - render_group_filter(gfilter); - } else { - ImGui::TextUnformatted("An unknown filter, this probably shouldn't be mutated"); - } - - ImGui::EndGroupPanel(); - ImGui::PopID(); -} - -static inline void render_integer_filter(IntegerFilter* filter) { - const char* head; - switch (filter->key) { - case FilterKey::PID: head = "PID"; break; - case FilterKey::TID: head = "TID"; break; - default: head = "Something"; - }; - - ImGui::AlignTextToFramePadding(); - ImGui::Text("%s is%s", head, filter->inverted ? " not" : ""); - ImGui::SameLine(); - if (ImGui::InputScalar("##int", ImGuiDataType_U64, &filter->other)) { - filter->updated(); - } -} - -static inline void render_string_filter(StringFilter* filter) { - const char* head; - switch (filter->key) { - case FilterKey::User: head = "User"; break; - case FilterKey::Tag: head = "Tag"; break; - case FilterKey::Message: head = "Message"; break; - default: head = "Something"; - }; - - ImGui::AlignTextToFramePadding(); - ImGui::Text("%s %s", head, filter->exact_match - ? (filter->inverted ? "is not" : "is") - : (filter->inverted ? "doesn't have" : "has")); - ImGui::SameLine(); - if (ImGui::InputText("##str", &filter->other)) { - filter->updated(); - } -} - -static inline void render_buffer_filter(BufferFilter* filter) { - auto update_if_needed = [&](bool updated) { - if (updated) { - filter->updated(); - } - }; - ImGui::AlignTextToFramePadding(); - ImGui::TextUnformatted("Buffer is:"); ImGui::SameLine(); - update_if_needed(ImGui::CheckboxFlags("Unknown", &filter->wanted, static_cast(Buffer::Unknown))); ImGui::SameLine(); - update_if_needed(ImGui::CheckboxFlags("Main", &filter->wanted, static_cast(Buffer::Main))); ImGui::SameLine(); - update_if_needed(ImGui::CheckboxFlags("System", &filter->wanted, static_cast(Buffer::System))); ImGui::SameLine(); - update_if_needed(ImGui::CheckboxFlags("Radio", &filter->wanted, static_cast(Buffer::Radio))); ImGui::SameLine(); - update_if_needed(ImGui::CheckboxFlags("Events", &filter->wanted, static_cast(Buffer::Events))); ImGui::SameLine(); - update_if_needed(ImGui::CheckboxFlags("Crash", &filter->wanted, static_cast(Buffer::Crash))); -} - -static inline void render_priority_filter(PriorityFilter* filter) { - auto update_if_needed = [&](bool updated) { - if (updated) { - filter->updated(); - } - }; - ImGui::AlignTextToFramePadding(); - ImGui::TextUnformatted("Priority is:"); ImGui::SameLine(); - update_if_needed(ImGui::CheckboxFlags("Unknown", &filter->wanted, static_cast(Priority::Unknown))); ImGui::SameLine(); - update_if_needed(ImGui::CheckboxFlags("Verbose", &filter->wanted, static_cast(Priority::Verbose))); ImGui::SameLine(); - update_if_needed(ImGui::CheckboxFlags("Debug", &filter->wanted, static_cast(Priority::Debug))); ImGui::SameLine(); - update_if_needed(ImGui::CheckboxFlags("Info", &filter->wanted, static_cast(Priority::Info))); ImGui::SameLine(); - update_if_needed(ImGui::CheckboxFlags("Warning", &filter->wanted, static_cast(Priority::Warn))); ImGui::SameLine(); - update_if_needed(ImGui::CheckboxFlags("Error", &filter->wanted, static_cast(Priority::Error))); ImGui::SameLine(); - update_if_needed(ImGui::CheckboxFlags("Fatal", &filter->wanted, static_cast(Priority::Fatal))); -} - -static inline void render_group_filter(GroupFilter* filter) { - int selected_type = static_cast(filter->type); - if (ImGui::Combo("of these are true", &selected_type, "All\0Any\0One\0None\0")) { - filter->type = static_cast(selected_type); - } - - for (std::vector>::iterator it = filter->filters.begin(); it != filter->filters.end();) { - bool removal_requested = false; - render_filter(it->get(), nullptr, &removal_requested); - if (removal_requested) { - filter->filters.erase(it); - filter->updated(); - } else { - it++; - } - } - - std::string add_filter_id = std::string("addfilter_") + std::to_string(reinterpret_cast(filter)); - if (ImGui::Button("+ add filter")) { - ImGui::OpenPopup(add_filter_id.c_str()); - } - if (ImGui::BeginPopup(add_filter_id.c_str())) { - std::unique_ptr added_filter = render_add_filter_popup(); - if (added_filter) { - filter->filters.push_back(std::move(added_filter)); - filter->updated(); - } - ImGui::EndPopup(); - } -} - -static std::unique_ptr render_add_filter_popup() { - if (ImGui::Selectable("Buffer")) { - return std::make_unique(0, false); - } else if (ImGui::Selectable("User")) { - return std::make_unique(FilterKey::User, "", false, true, false); - } else if (ImGui::Selectable("PID")) { - return std::make_unique(FilterKey::PID, 0, false, false); - } else if (ImGui::Selectable("TID")) { - return std::make_unique(FilterKey::TID, 0, false, false); - } else if (ImGui::Selectable("Priority")) { - return std::make_unique(0, false); - } else if (ImGui::Selectable("Tag")) { - return std::make_unique(FilterKey::Tag, "", false, true, false); - } else if (ImGui::Selectable("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, false); - } - - return std::unique_ptr(); -} - -static void update_logcat_entries(const Filters& filters, - const std::vector& logcat_entries, std::vector& filtered_logcat_entry_offsets) { - filtered_logcat_entry_offsets.clear(); - for (size_t i=0; i < logcat_entries.size(); i++) { - if (matches(filters, logcat_entries[i])) { - filtered_logcat_entry_offsets.push_back(i); - } - } -} - -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) { @@ -230,46 +13,7 @@ void filters_window(Config& active_config, Config& inactive_config, return; } - ImGui::TextUnformatted("You can use regex for strings by prepending \"regex:\""); + filters_fragment(active_config, active_config.filters, inactive_config.filters, logcat_entries, filtered_logcat_entry_offsets, p_open); - 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_config.filters.erase(it); - } else { - it++; - } - } - - if (ImGui::Button("+ add filter")) { - ImGui::OpenPopup("addfilter_root"); - } - if (ImGui::BeginPopup("addfilter_root")) { - std::unique_ptr added_filter = render_add_filter_popup(); - if (added_filter) { - inactive_config.filters.push_back(std::make_pair("", std::move(added_filter))); - } - ImGui::EndPopup(); - } - - ImGui::Separator(); - ImVec2 button_size(4 * ImGui::GetFontSize(), 0); - if (ImGui::Button("OK", button_size)) { - 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(); - if (ImGui::Button("Cancel", button_size)) { - *p_open = false; - } - ImGui::SameLine(); - if (ImGui::Button("Apply", button_size)) { - 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/main.cpp b/windows/main.cpp index 64dea2d..fcb8c1a 100644 --- a/windows/main.cpp +++ b/windows/main.cpp @@ -55,7 +55,7 @@ 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, - bool* show_settings_window, bool* show_filters_window, bool* show_logs_window, bool* run_event_loop) { + bool* show_settings_window, bool* show_filters_window, bool* show_exclusions_window, bool* show_logs_window, bool* run_event_loop) { ImGui::SetNextWindowPos(ImGui::GetMainViewport()->WorkPos); ImGui::SetNextWindowSize(ImGui::GetMainViewport()->WorkSize); @@ -78,6 +78,12 @@ void main_window(bool latest_log_entries_read, ImFont* monospace_font, *show_filters_window = true; } + ImGui::SameLine(); + if (ImGui::Button("Exclusions") && !*show_exclusions_window) { + copy_filters(inactive_config.exclusions, active_config.exclusions); + *show_exclusions_window = true; + } + ImGui::SameLine(); bool open_logs; if (!latest_log_entries_read) { diff --git a/windows/main.h b/windows/main.h index e9750e4..f5b5bd4 100644 --- a/windows/main.h +++ b/windows/main.h @@ -9,4 +9,4 @@ 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, - bool* show_settings_window, bool* show_filters_window, bool* show_logs_window, bool* run_event_loop); + bool* show_settings_window, bool* show_filters_window, bool* show_exclusions_window, bool* show_logs_window, bool* run_event_loop);