Use json for config and persist filters
This commit is contained in:
parent
d157e983c4
commit
49a74d552b
|
@ -22,7 +22,8 @@ set(LINUX_GL_LIBS -lGL)
|
||||||
|
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
find_package(Freetype 2 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(IMGUI_LIBS SDL2 Freetype::Freetype)
|
||||||
|
|
||||||
set(INCLUDES imgui imgui/backends imgui/misc/cpp imgui/freetype /usr/include/SDL2)
|
set(INCLUDES imgui imgui/backends imgui/misc/cpp imgui/freetype /usr/include/SDL2)
|
||||||
|
|
146
config.cpp
146
config.cpp
|
@ -1,11 +1,8 @@
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cmath>
|
|
||||||
#include <cfloat>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "misc.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));
|
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() {
|
std::string get_config_folder() {
|
||||||
const char* path;
|
const char* path;
|
||||||
|
@ -86,7 +40,7 @@ std::string get_config_folder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_config_file_path() {
|
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
|
// 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) {
|
void from_json(const nlohmann::json& j, Config& config) {
|
||||||
if (strncmp(line, "logcat_command=", 15 * sizeof(char)) == 0) {
|
j.at("logcat_command").get_to(config.logcat_command);
|
||||||
config.logcat_command = &line[15];
|
j.at("normal_font_size").get_to(config.normal_font_size);
|
||||||
} else if (strncmp(line, "normal_font_size=", 17 * sizeof(char)) == 0) {
|
j.at("monospace_font_size").get_to(config.monospace_font_size);
|
||||||
float size = to_float(&line[17]);
|
j.at("filters").get_to(config.filters);
|
||||||
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<char*>(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Config load_config() {
|
Config load_config() {
|
||||||
|
@ -175,37 +81,15 @@ Config load_config() {
|
||||||
return Config();
|
return Config();
|
||||||
}
|
}
|
||||||
|
|
||||||
return load_config(config_file.get());
|
return nlohmann::json::parse(config_file.get()).get<Config>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void write_config(FILE* file, const Config& config) {
|
void to_json(nlohmann::json& j, const Config& config) {
|
||||||
if (!write("# This is an auto-generated file, modifications will be lost\n"
|
j["logcat_command"] = config.logcat_command;
|
||||||
"# This is a poor man's config file \"format\", there are only three legal lines:\n"
|
j["normal_font_size"] = config.normal_font_size;
|
||||||
"# # a comment, only available at the start of a line\n"
|
j["monospace_font_size"] = config.monospace_font_size;
|
||||||
"# (an empty line, no whitespace)\n"
|
j["filters"] = config.filters;
|
||||||
"# 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 write_config(const Config& config) {
|
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::string tmp_config_file_path = config_file_path + ".tmp";
|
||||||
|
|
||||||
std::unique_ptr<FILE, decltype(&fclose_and_log)> config_file(fopen_or_raise(tmp_config_file_path.c_str(), "w", false), fclose_and_log);
|
std::unique_ptr<FILE, decltype(&fclose_and_log)> 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();
|
config_file.reset();
|
||||||
|
|
||||||
if (!rename(tmp_config_file_path.c_str(), config_file_path.c_str())) {
|
if (!rename(tmp_config_file_path.c_str(), config_file_path.c_str())) {
|
||||||
|
|
6
config.h
6
config.h
|
@ -1,14 +1,20 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include "filters.h"
|
||||||
|
|
||||||
struct Config {
|
struct Config {
|
||||||
std::string logcat_command;
|
std::string logcat_command;
|
||||||
float normal_font_size = 13.0f;
|
float normal_font_size = 13.0f;
|
||||||
float monospace_font_size = 13.0f;
|
float monospace_font_size = 13.0f;
|
||||||
|
|
||||||
|
Filters filters;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string get_config_folder();
|
std::string get_config_folder();
|
||||||
void create_config_folders_if_necessary();
|
void create_config_folders_if_necessary();
|
||||||
|
void from_json(const nlohmann::json& j, Config& config);
|
||||||
Config load_config();
|
Config load_config();
|
||||||
|
void to_json(nlohmann::json& j, const Config& config);
|
||||||
void write_config(const Config& config);
|
void write_config(const Config& config);
|
||||||
|
|
|
@ -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 Config inactive_config;
|
||||||
static Filters inactive_filters;
|
|
||||||
static bool show_settings_window = false;
|
static bool show_settings_window = false;
|
||||||
static bool show_filters_window = false;
|
static bool show_filters_window = false;
|
||||||
static bool show_logs_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<LogcatEntry> logcat_entries;
|
static std::vector<LogcatEntry> logcat_entries;
|
||||||
static std::vector<size_t> filtered_logcat_entry_offsets;
|
static std::vector<size_t> 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
|
#ifndef NDEBUG
|
||||||
debug_window(logcat_thread);
|
debug_window(logcat_thread);
|
||||||
|
@ -54,7 +53,7 @@ void event_loop(ImFont* monospace_font, Config& active_config, Filters& active_f
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_filters_window) {
|
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) {
|
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,
|
main_window(log_entries_read == log_entries.size(), monospace_font,
|
||||||
logcat_entries, filtered_logcat_entry_offsets,
|
logcat_entries, filtered_logcat_entry_offsets,
|
||||||
active_config, inactive_config,
|
active_config, inactive_config,
|
||||||
active_filters, inactive_filters,
|
|
||||||
&show_settings_window, &show_filters_window, &show_logs_window, run_event_loop);
|
&show_settings_window, &show_filters_window, &show_logs_window, run_event_loop);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "filters.h"
|
|
||||||
#include "logcat_thread.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);
|
||||||
|
|
155
filters.cpp
155
filters.cpp
|
@ -289,3 +289,158 @@ bool matches(const Filters& filters, const LogcatEntry& entry) {
|
||||||
|
|
||||||
return !ok_filter_exists;
|
return !ok_filter_exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void from_json(const nlohmann::json& j, FilterKey& key) {
|
||||||
|
const std::string& str = j.get_ref<const nlohmann::json::string_t&>();
|
||||||
|
|
||||||
|
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<const nlohmann::json::string_t&>();
|
||||||
|
|
||||||
|
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>& filter) {
|
||||||
|
const std::string& filter_type = j.at("type").get_ref<const nlohmann::json::string_t&>();
|
||||||
|
bool disabled = j.at("disabled").get<bool>();
|
||||||
|
|
||||||
|
if (filter_type == "INTEGER") {
|
||||||
|
filter = std::make_unique<IntegerFilter>(j.at("key").get<FilterKey>(), j.at("other").get<size_t>(), j.at("inverted").get<bool>(), disabled);
|
||||||
|
} else if (filter_type == "STRING") {
|
||||||
|
filter = std::make_unique<StringFilter>(
|
||||||
|
j.at("key").get<FilterKey>(), j.at("other").get<std::string>(), j.at("inverted").get<bool>(), j.at("exact_match").get<bool>(), 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<unsigned int>(it->get<Buffer>());
|
||||||
|
}
|
||||||
|
|
||||||
|
filter = std::make_unique<BufferFilter>(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<unsigned int>(it->get<Priority>());
|
||||||
|
}
|
||||||
|
|
||||||
|
filter = std::make_unique<PriorityFilter>(wanted, disabled);
|
||||||
|
} else if (filter_type == "GROUP") {
|
||||||
|
filter = std::make_unique<GroupFilter>(
|
||||||
|
j.at("filters").get<std::vector<std::unique_ptr<Filter>>>(), j.at("group_type").get<GroupFilter::Type>(), disabled);
|
||||||
|
} else {
|
||||||
|
throw std::invalid_argument(std::string("Unknown filter type: ") + filter_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_json(nlohmann::json& j, const std::unique_ptr<Filter>& filter) {
|
||||||
|
j["disabled"] = filter->disabled();
|
||||||
|
|
||||||
|
if (const IntegerFilter* ifilter = dynamic_cast<const IntegerFilter*>(filter.get())) {
|
||||||
|
j["type"] = "INTEGER";
|
||||||
|
j["key"] = ifilter->key;
|
||||||
|
j["other"] = ifilter->other;
|
||||||
|
j["inverted"] = ifilter->inverted;
|
||||||
|
} else if (const StringFilter* sfilter = dynamic_cast<const StringFilter*>(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<const BufferFilter*>(filter.get())) {
|
||||||
|
j["type"] = "BUFFER";
|
||||||
|
j["wanted"] = nlohmann::json::array();
|
||||||
|
if (bfilter->wanted & static_cast<unsigned int>(Buffer::Unknown)) {
|
||||||
|
j["wanted"].emplace_back(Buffer::Unknown);
|
||||||
|
}
|
||||||
|
if (bfilter->wanted & static_cast<unsigned int>(Buffer::Main)) {
|
||||||
|
j["wanted"].emplace_back(Buffer::Main);
|
||||||
|
}
|
||||||
|
if (bfilter->wanted & static_cast<unsigned int>(Buffer::System)) {
|
||||||
|
j["wanted"].emplace_back(Buffer::System);
|
||||||
|
}
|
||||||
|
if (bfilter->wanted & static_cast<unsigned int>(Buffer::Radio)) {
|
||||||
|
j["wanted"].emplace_back(Buffer::Radio);
|
||||||
|
}
|
||||||
|
if (bfilter->wanted & static_cast<unsigned int>(Buffer::Events)) {
|
||||||
|
j["wanted"].emplace_back(Buffer::Events);
|
||||||
|
}
|
||||||
|
if (bfilter->wanted & static_cast<unsigned int>(Buffer::Crash)) {
|
||||||
|
j["wanted"].emplace_back(Buffer::Crash);
|
||||||
|
}
|
||||||
|
} else if (const PriorityFilter* pfilter = dynamic_cast<const PriorityFilter*>(filter.get())) {
|
||||||
|
j["type"] = "PRIORITY";
|
||||||
|
j["wanted"] = nlohmann::json::array();
|
||||||
|
if (pfilter->wanted & static_cast<unsigned int>(Priority::Unknown)) {
|
||||||
|
j["wanted"].emplace_back(Priority::Unknown);
|
||||||
|
}
|
||||||
|
if (pfilter->wanted & static_cast<unsigned int>(Priority::Verbose)) {
|
||||||
|
j["wanted"].emplace_back(Priority::Verbose);
|
||||||
|
}
|
||||||
|
if (pfilter->wanted & static_cast<unsigned int>(Priority::Debug)) {
|
||||||
|
j["wanted"].emplace_back(Priority::Debug);
|
||||||
|
}
|
||||||
|
if (pfilter->wanted & static_cast<unsigned int>(Priority::Info)) {
|
||||||
|
j["wanted"].emplace_back(Priority::Info);
|
||||||
|
}
|
||||||
|
if (pfilter->wanted & static_cast<unsigned int>(Priority::Warn)) {
|
||||||
|
j["wanted"].emplace_back(Priority::Warn);
|
||||||
|
}
|
||||||
|
if (pfilter->wanted & static_cast<unsigned int>(Priority::Error)) {
|
||||||
|
j["wanted"].emplace_back(Priority::Error);
|
||||||
|
}
|
||||||
|
if (pfilter->wanted & static_cast<unsigned int>(Priority::Fatal)) {
|
||||||
|
j["wanted"].emplace_back(Priority::Fatal);
|
||||||
|
}
|
||||||
|
} else if (const GroupFilter* gfilter = dynamic_cast<const GroupFilter*>(filter.get())) {
|
||||||
|
j["type"] = "GROUP";
|
||||||
|
j["group_type"] = gfilter->type;
|
||||||
|
j["filters"] = nlohmann::json::array();
|
||||||
|
for (const std::unique_ptr<Filter>& i : gfilter->filters) {
|
||||||
|
j["filters"].emplace_back(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw std::invalid_argument("Cannot serialize unknown filter");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
16
filters.h
16
filters.h
|
@ -4,6 +4,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#include "logcat_entry.h"
|
#include "logcat_entry.h"
|
||||||
#include "pcre2_wrapper.h"
|
#include "pcre2_wrapper.h"
|
||||||
|
@ -34,7 +35,7 @@ public:
|
||||||
|
|
||||||
class IntegerFilter : public Filter {
|
class IntegerFilter : public Filter {
|
||||||
public:
|
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;
|
void updated() override;
|
||||||
bool disabled() const override;
|
bool disabled() const override;
|
||||||
|
@ -57,7 +58,7 @@ public:
|
||||||
StringFilter(const StringFilter&) = delete;
|
StringFilter(const StringFilter&) = delete;
|
||||||
StringFilter& operator=(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;
|
void updated() override;
|
||||||
bool disabled() const override;
|
bool disabled() const override;
|
||||||
|
@ -81,7 +82,7 @@ private:
|
||||||
|
|
||||||
class BufferFilter : public Filter {
|
class BufferFilter : public Filter {
|
||||||
public:
|
public:
|
||||||
BufferFilter(unsigned int wanted_, bool disabled = false);
|
BufferFilter(unsigned int wanted_, bool disabled);
|
||||||
|
|
||||||
void updated() override;
|
void updated() override;
|
||||||
bool disabled() const override;
|
bool disabled() const override;
|
||||||
|
@ -122,7 +123,7 @@ public:
|
||||||
None = 3,
|
None = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
GroupFilter(std::vector<std::unique_ptr<Filter>> filters_, Type type_, bool disabled = false);
|
GroupFilter(std::vector<std::unique_ptr<Filter>> filters_, Type type_, bool disabled);
|
||||||
|
|
||||||
void updated() override;
|
void updated() override;
|
||||||
bool disabled() const override;
|
bool disabled() const override;
|
||||||
|
@ -141,3 +142,10 @@ private:
|
||||||
typedef std::vector<std::pair<std::string, std::unique_ptr<Filter>>> Filters;
|
typedef std::vector<std::pair<std::string, std::unique_ptr<Filter>>> Filters;
|
||||||
void copy_filters(Filters& filters, const Filters& other);
|
void copy_filters(Filters& filters, const Filters& other);
|
||||||
bool matches(const Filters& filters, const LogcatEntry& entry);
|
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>& filter);
|
||||||
|
void to_json(nlohmann::json& j, const std::unique_ptr<Filter>& filter);
|
||||||
|
|
|
@ -122,3 +122,52 @@ std::optional<Buffer> try_parse_buffer(char* buf, size_t length) {
|
||||||
if (!strncmp(buffer_str, "crash", 5)) return Buffer::Crash;
|
if (!strncmp(buffer_str, "crash", 5)) return Buffer::Crash;
|
||||||
return Buffer::Unknown;
|
return Buffer::Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void from_json(const nlohmann::json& j, Buffer& buffer) {
|
||||||
|
const std::string& str = j.get_ref<const nlohmann::json::string_t&>();
|
||||||
|
|
||||||
|
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<const nlohmann::json::string_t&>();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
enum class Buffer {
|
enum class Buffer {
|
||||||
Unknown = 0b1,
|
Unknown = 0b1,
|
||||||
|
@ -38,3 +39,8 @@ const char* priority_to(Priority priority);
|
||||||
const char* buffer_to(Buffer buffer);
|
const char* buffer_to(Buffer buffer);
|
||||||
std::optional<LogcatEntry> try_parse_logcat_entry(char* buf, size_t length, Buffer buffer);
|
std::optional<LogcatEntry> try_parse_logcat_entry(char* buf, size_t length, Buffer buffer);
|
||||||
std::optional<Buffer> try_parse_buffer(char* buf, size_t length);
|
std::optional<Buffer> 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);
|
||||||
|
|
4
main.cpp
4
main.cpp
|
@ -23,8 +23,6 @@
|
||||||
int main(int, char**) {
|
int main(int, char**) {
|
||||||
setlocale(LC_TIME, "");
|
setlocale(LC_TIME, "");
|
||||||
|
|
||||||
// TODO add saving
|
|
||||||
Filters filters;
|
|
||||||
Config config;
|
Config config;
|
||||||
try {
|
try {
|
||||||
config = load_config();
|
config = load_config();
|
||||||
|
@ -164,7 +162,7 @@ int main(int, char**) {
|
||||||
ImGui_ImplSDL2_NewFrame();
|
ImGui_ImplSDL2_NewFrame();
|
||||||
ImGui::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
|
// Rendering
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "../group_panel.h"
|
#include "../group_panel.h"
|
||||||
#include "../filters.h"
|
#include "../filters.h"
|
||||||
|
#include "../config.h"
|
||||||
#include "filters.h"
|
#include "filters.h"
|
||||||
|
|
||||||
static inline void render_integer_filter(IntegerFilter* filter);
|
static inline void render_integer_filter(IntegerFilter* filter);
|
||||||
|
@ -13,6 +14,7 @@ static inline void render_group_filter(GroupFilter* filter);
|
||||||
static std::unique_ptr<Filter> render_add_filter_popup();
|
static std::unique_ptr<Filter> render_add_filter_popup();
|
||||||
static void update_logcat_entries(const Filters& filters,
|
static void update_logcat_entries(const Filters& filters,
|
||||||
const std::vector<LogcatEntry>& logcat_entries, std::vector<size_t>& filtered_logcat_entry_offsets);
|
const std::vector<LogcatEntry>& logcat_entries, std::vector<size_t>& filtered_logcat_entry_offsets);
|
||||||
|
static void try_write_config(const Config& config);
|
||||||
|
|
||||||
static void render_filter(Filter* filter, std::string* title, bool* request_removal) {
|
static void render_filter(Filter* filter, std::string* title, bool* request_removal) {
|
||||||
ImGui::PushID(filter);
|
ImGui::PushID(filter);
|
||||||
|
@ -182,21 +184,21 @@ static inline void render_group_filter(GroupFilter* filter) {
|
||||||
|
|
||||||
static std::unique_ptr<Filter> render_add_filter_popup() {
|
static std::unique_ptr<Filter> render_add_filter_popup() {
|
||||||
if (ImGui::Selectable("Buffer")) {
|
if (ImGui::Selectable("Buffer")) {
|
||||||
return std::make_unique<BufferFilter>(0);
|
return std::make_unique<BufferFilter>(0, false);
|
||||||
} else if (ImGui::Selectable("User")) {
|
} else if (ImGui::Selectable("User")) {
|
||||||
return std::make_unique<StringFilter>(FilterKey::User, "");
|
return std::make_unique<StringFilter>(FilterKey::User, "", false, true, false);
|
||||||
} else if (ImGui::Selectable("PID")) {
|
} else if (ImGui::Selectable("PID")) {
|
||||||
return std::make_unique<IntegerFilter>(FilterKey::PID, 0);
|
return std::make_unique<IntegerFilter>(FilterKey::PID, 0, false, false);
|
||||||
} else if (ImGui::Selectable("TID")) {
|
} else if (ImGui::Selectable("TID")) {
|
||||||
return std::make_unique<IntegerFilter>(FilterKey::TID, 0);
|
return std::make_unique<IntegerFilter>(FilterKey::TID, 0, false, false);
|
||||||
} else if (ImGui::Selectable("Priority")) {
|
} else if (ImGui::Selectable("Priority")) {
|
||||||
return std::make_unique<PriorityFilter>(0);
|
return std::make_unique<PriorityFilter>(0, false);
|
||||||
} else if (ImGui::Selectable("Tag")) {
|
} else if (ImGui::Selectable("Tag")) {
|
||||||
return std::make_unique<StringFilter>(FilterKey::Tag, "");
|
return std::make_unique<StringFilter>(FilterKey::Tag, "", false, true, false);
|
||||||
} else if (ImGui::Selectable("Message")) {
|
} else if (ImGui::Selectable("Message")) {
|
||||||
return std::make_unique<StringFilter>(FilterKey::Message, "");
|
return std::make_unique<StringFilter>(FilterKey::Message, "", false, true, false);
|
||||||
} else if (ImGui::Selectable("Group of filters")) {
|
} else if (ImGui::Selectable("Group of filters")) {
|
||||||
return std::make_unique<GroupFilter>(std::vector<std::unique_ptr<Filter>>(), GroupFilter::Type::All);
|
return std::make_unique<GroupFilter>(std::vector<std::unique_ptr<Filter>>(), GroupFilter::Type::All, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::unique_ptr<Filter>();
|
return std::unique_ptr<Filter>();
|
||||||
|
@ -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<LogcatEntry>& logcat_entries, std::vector<size_t>& filtered_logcat_entry_offsets,
|
const std::vector<LogcatEntry>& logcat_entries, std::vector<size_t>& filtered_logcat_entry_offsets,
|
||||||
bool* p_open) {
|
bool* p_open) {
|
||||||
if (!ImGui::Begin("Filters", 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:\"");
|
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;
|
bool removal_requested = false;
|
||||||
render_filter(it->second.get(), &it->first, &removal_requested);
|
render_filter(it->second.get(), &it->first, &removal_requested);
|
||||||
if (removal_requested) {
|
if (removal_requested) {
|
||||||
inactive_filters.erase(it);
|
inactive_config.filters.erase(it);
|
||||||
} else {
|
} else {
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
|
@ -238,7 +248,7 @@ void filters_window(Filters& active_filters, Filters& inactive_filters,
|
||||||
if (ImGui::BeginPopup("addfilter_root")) {
|
if (ImGui::BeginPopup("addfilter_root")) {
|
||||||
std::unique_ptr<Filter> added_filter = render_add_filter_popup();
|
std::unique_ptr<Filter> added_filter = render_add_filter_popup();
|
||||||
if (added_filter) {
|
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();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
@ -246,8 +256,9 @@ void filters_window(Filters& active_filters, Filters& inactive_filters,
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImVec2 button_size(4 * ImGui::GetFontSize(), 0);
|
ImVec2 button_size(4 * ImGui::GetFontSize(), 0);
|
||||||
if (ImGui::Button("OK", button_size)) {
|
if (ImGui::Button("OK", button_size)) {
|
||||||
active_filters = std::move(inactive_filters);
|
active_config.filters = std::move(inactive_config.filters);
|
||||||
update_logcat_entries(active_filters, logcat_entries, filtered_logcat_entry_offsets);
|
try_write_config(active_config);
|
||||||
|
update_logcat_entries(active_config.filters, logcat_entries, filtered_logcat_entry_offsets);
|
||||||
*p_open = false;
|
*p_open = false;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
@ -256,8 +267,9 @@ void filters_window(Filters& active_filters, Filters& inactive_filters,
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Apply", button_size)) {
|
if (ImGui::Button("Apply", button_size)) {
|
||||||
copy_filters(active_filters, inactive_filters);
|
copy_filters(active_config.filters, inactive_config.filters);
|
||||||
update_logcat_entries(active_filters, logcat_entries, filtered_logcat_entry_offsets);
|
try_write_config(active_config);
|
||||||
|
update_logcat_entries(active_config.filters, logcat_entries, filtered_logcat_entry_offsets);
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../logcat_entry.h"
|
#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<LogcatEntry>& logcat_entries, std::vector<size_t>& filtered_logcat_entry_offsets,
|
const std::vector<LogcatEntry>& logcat_entries, std::vector<size_t>& filtered_logcat_entry_offsets,
|
||||||
bool* p_open);
|
bool* p_open);
|
||||||
|
|
|
@ -55,7 +55,6 @@ static inline void render_table(ImFont* monospace_font, std::vector<LogcatEntry>
|
||||||
void main_window(bool latest_log_entries_read, ImFont* monospace_font,
|
void main_window(bool latest_log_entries_read, ImFont* monospace_font,
|
||||||
std::vector<LogcatEntry>& logcat_entries, std::vector<size_t>& filtered_logcat_entry_offsets,
|
std::vector<LogcatEntry>& logcat_entries, std::vector<size_t>& filtered_logcat_entry_offsets,
|
||||||
const Config& active_config, Config& inactive_config,
|
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) {
|
bool* show_settings_window, bool* show_filters_window, bool* show_logs_window, bool* run_event_loop) {
|
||||||
|
|
||||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->WorkPos);
|
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) {
|
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;
|
*show_settings_window = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Filters") && !*show_filters_window) {
|
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;
|
*show_filters_window = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,9 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
#include "../filters.h"
|
|
||||||
#include "../logcat_entry.h"
|
#include "../logcat_entry.h"
|
||||||
|
|
||||||
void main_window(bool latest_log_entries_read, ImFont* monospace_font,
|
void main_window(bool latest_log_entries_read, ImFont* monospace_font,
|
||||||
std::vector<LogcatEntry>& logcat_entries, std::vector<size_t>& filtered_logcat_entry_offsets,
|
std::vector<LogcatEntry>& logcat_entries, std::vector<size_t>& filtered_logcat_entry_offsets,
|
||||||
const Config& active_config, Config& inactive_config,
|
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);
|
bool* show_settings_window, bool* show_filters_window, bool* show_logs_window, bool* run_event_loop);
|
||||||
|
|
|
@ -4,12 +4,11 @@
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
static void write_config_and_update_structures(const Config& config) {
|
static void try_write_config(const Config& config) {
|
||||||
try {
|
try {
|
||||||
write_config(config);
|
write_config(config);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
log(std::string("Failed to write config: ") + e.what());
|
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();
|
ImGui::Separator();
|
||||||
ImVec2 button_size(4 * ImGui::GetFontSize(), 0);
|
ImVec2 button_size(4 * ImGui::GetFontSize(), 0);
|
||||||
if (ImGui::Button("OK", button_size)) {
|
if (ImGui::Button("OK", button_size)) {
|
||||||
active_config = std::move(inactive_config);
|
active_config.logcat_command = std::move(inactive_config.logcat_command);
|
||||||
write_config_and_update_structures(active_config);
|
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;
|
*p_open = false;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
@ -41,8 +42,10 @@ void settings_window(Config& active_config, Config& inactive_config, bool* p_ope
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("Apply", button_size)) {
|
if (ImGui::Button("Apply", button_size)) {
|
||||||
active_config = inactive_config;
|
active_config.logcat_command = inactive_config.logcat_command;
|
||||||
write_config_and_update_structures(active_config);
|
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();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue