From 10381d42e078658d685ac3ccdf994fe9f1bc2650 Mon Sep 17 00:00:00 2001 From: John Ralls Date: Wed, 18 Aug 2021 13:38:06 -0700 Subject: [PATCH] Fix color option handling. Read and write color options the way legacy code does. Pass only values with no alpha to gdk_rgba_parse because it fails if a hex-string has alpha. --- gnucash/gnome-utils/dialog-options.cpp | 8 ++++++-- libgnucash/app-utils/gnc-option-impl.hpp | 9 +++++++-- libgnucash/app-utils/gnc-option.cpp | 5 +++++ libgnucash/app-utils/gnc-option.hpp | 19 +++++++++++++++++++ libgnucash/app-utils/gnc-optiondb.i | 23 ++++++++++++++++++++++- 5 files changed, 59 insertions(+), 5 deletions(-) diff --git a/gnucash/gnome-utils/dialog-options.cpp b/gnucash/gnome-utils/dialog-options.cpp index ee14d4934a..7702c5485c 100644 --- a/gnucash/gnome-utils/dialog-options.cpp +++ b/gnucash/gnome-utils/dialog-options.cpp @@ -2140,8 +2140,12 @@ public: void set_ui_item_from_option(GncOption& option) noexcept override { GdkRGBA color; - auto rgba_str{g_strdup_printf("#%s", - option.get_value().c_str())}; + /* gdk_rgba_parse uses pango_color_parse for hex color strings instead + * of pango_color_parse_with_alpha and that fails if the string length + * is 8. + */ + auto value{option.get_value().substr(0,6)}; + auto rgba_str{g_strdup_printf("#%s", value.c_str())}; if (gdk_rgba_parse(&color, rgba_str)) { auto color_button = GTK_COLOR_CHOOSER(get_widget()); diff --git a/libgnucash/app-utils/gnc-option-impl.hpp b/libgnucash/app-utils/gnc-option-impl.hpp index ae386afe3d..663fba1288 100644 --- a/libgnucash/app-utils/gnc-option-impl.hpp +++ b/libgnucash/app-utils/gnc-option-impl.hpp @@ -388,11 +388,16 @@ gnc_option_to_scheme (std::ostream& oss, const OptType& opt) { oss << ")"; } + return oss; } - else + + if constexpr (std::is_same_v, std::string>) { - oss << "\"" << qof_instance_to_string(value) << "\""; + if (type == GncOptionUIType::COLOR) + return output_color_value(oss, value); } + + oss << "\"" << qof_instance_to_string(value) << "\""; return oss; } diff --git a/libgnucash/app-utils/gnc-option.cpp b/libgnucash/app-utils/gnc-option.cpp index 784a65b1df..f249ff06b7 100644 --- a/libgnucash/app-utils/gnc-option.cpp +++ b/libgnucash/app-utils/gnc-option.cpp @@ -453,7 +453,12 @@ GncOption::to_scheme(std::ostream& oss) const else if constexpr (std::is_same_v, std::string>) + { + if (option.get_ui_type() == GncOptionUIType::COLOR) + output_color_value(oss, option.get_value()); + else oss << '"' << option << '"'; + } else if constexpr (std::is_same_v, GncOptionRangeValue> || diff --git a/libgnucash/app-utils/gnc-option.hpp b/libgnucash/app-utils/gnc-option.hpp index 089ff08250..1677e7b5d2 100644 --- a/libgnucash/app-utils/gnc-option.hpp +++ b/libgnucash/app-utils/gnc-option.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include "gnc-option-ui.hpp" @@ -149,6 +150,24 @@ operator>>(std::istream& iss, GncOption& opt) return opt.in_stream(iss); } +inline std::ostream& +output_color_value(std::ostream& oss, const std::string& value) +{ + oss << "'("; + oss << std::fixed << std::showpoint << std::setprecision(1); + auto len{value.length() > 8 ? 8 : value.length()}; + for (size_t i{}; i < len; i += 2) + { + oss << static_cast(stoi(value.substr(i, 2), nullptr, 16)); + if (i < 6) + oss << " "; + } + if (len < 8) + oss << 256.0; + oss << ")"; + return oss; +} + template GncOption* gnc_make_option(const char* section, const char* name, const char* key, const char* doc_string, diff --git a/libgnucash/app-utils/gnc-optiondb.i b/libgnucash/app-utils/gnc-optiondb.i index 4350f1c83c..d53cc02421 100644 --- a/libgnucash/app-utils/gnc-optiondb.i +++ b/libgnucash/app-utils/gnc-optiondb.i @@ -46,6 +46,8 @@ namespace std { #include "gnc-optiondb.hpp" #include "gnc-optiondb-impl.hpp" #include "gnc-option-date.hpp" +#include +#include static const QofLogModule log_module = "gnc.optiondb"; @@ -240,6 +242,24 @@ scm_from_value(GncOwner* value) return scm_from_value(value); } +static std::string +scm_color_list_to_string(SCM list) +{ + std::ostringstream oss{}; + oss << std::hex << std::setfill('0'); + SCM cdr = list; + while (scm_is_pair(cdr)) + { + if (scm_is_rational(SCM_CAR(cdr))) + oss << std::setw(2) << + static_cast(scm_to_double(SCM_CAR(cdr))); + cdr = SCM_CDR(cdr); + } + if (scm_is_rational(cdr)) + oss << std::setw(2) << static_cast(scm_to_double(cdr)); + return oss.str(); +} + template inline ValueType scm_to_value(SCM new_value) { @@ -257,6 +277,8 @@ scm_to_value(SCM new_value) template <> inline std::string scm_to_value(SCM new_value) { + if (scm_is_true(scm_list_p(new_value))) + return scm_color_list_to_string(new_value); auto strval = scm_to_utf8_stringn(new_value, nullptr); std::string retval{strval}; free(strval); @@ -552,7 +574,6 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB); #include #include #include -#include #include "gnc-option.hpp" #include "gnc-option-ui.hpp"