diff options
| author | Patrick Storz <eduard.braun2@gmx.de> | 2019-07-22 23:06:21 +0000 |
|---|---|---|
| committer | Patrick Storz <eduard.braun2@gmx.de> | 2019-08-31 14:50:38 +0000 |
| commit | 8f7a3a637f6a465e78e88490a03f539f0d8fdc1a (patch) | |
| tree | e503502036ba4268921ded10a81ab3b4157d89d5 /src/extension/prefdialog | |
| parent | Move error classes to Parameter where they belong (diff) | |
| download | inkscape-8f7a3a637f6a465e78e88490a03f539f0d8fdc1a.tar.gz inkscape-8f7a3a637f6a465e78e88490a03f539f0d8fdc1a.zip | |
Refactor a lot of the parameter handling code
Many fixes, improvements and simplifications to existing code.
Implements the first part of the changes discussed in
https://gitlab.com/inkscape/inkscape/issues/333
Diffstat (limited to 'src/extension/prefdialog')
24 files changed, 1083 insertions, 1647 deletions
diff --git a/src/extension/prefdialog/parameter-bool.cpp b/src/extension/prefdialog/parameter-bool.cpp index 8277d3120..cdd754d2d 100644 --- a/src/extension/prefdialog/parameter-bool.cpp +++ b/src/extension/prefdialog/parameter-bool.cpp @@ -21,43 +21,38 @@ namespace Inkscape { namespace Extension { -ParamBool::ParamBool(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml) - : Parameter(name, text, description, hidden, indent, ext) - , _value(false) +ParamBool::ParamBool(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext) + : Parameter(xml, ext) { - const char * defaultval = nullptr; - if (xml->firstChild() != nullptr) { - defaultval = xml->firstChild()->content(); + // get value + if (xml->firstChild()) { + const char *value = xml->firstChild()->content(); + if (value) { + if (!strcmp(value, "true")) { + _value = true; + } else if (!strcmp(value, "false")) { + _value = false; + } else { + g_warning("Invalid default value ('%s') for parameter '%s' in extension '%s'", + value, _name, _extension->get_id()); + } + } } - if (defaultval != nullptr && (!strcmp(defaultval, "true") || !strcmp(defaultval, "1"))) { - _value = true; - } else { - _value = false; - } - - gchar * pref_name = this->pref_name(); + gchar *pref_name = this->pref_name(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); _value = prefs->getBool(extension_pref_root + pref_name, _value); g_free(pref_name); - - return; } bool ParamBool::set( bool in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/ ) { _value = in; - gchar * prefname = this->pref_name(); + gchar *pref_name = this->pref_name(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setBool(extension_pref_root + prefname, _value); - g_free(prefname); + prefs->setBool(extension_pref_root + pref_name, _value); + g_free(pref_name); return _value; } @@ -81,7 +76,7 @@ public: * * @param param Which parameter to adjust on changing the check button */ - ParamBoolCheckButton (ParamBool * param, gchar * label, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) : + ParamBoolCheckButton (ParamBool *param, gchar *label, SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) : Gtk::CheckButton(label), _pref(param), _doc(doc), _node(node), _changeSignal(changeSignal) { this->set_active(_pref->get(nullptr, nullptr) /**\todo fix */); this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle)); @@ -96,10 +91,10 @@ public: private: /** Param to change. */ - ParamBool * _pref; - SPDocument * _doc; - Inkscape::XML::Node * _node; - sigc::signal<void> * _changeSignal; + ParamBool *_pref; + SPDocument *_doc; + Inkscape::XML::Node *_node; + sigc::signal<void> *_changeSignal; }; void ParamBoolCheckButton::on_toggle() @@ -122,7 +117,7 @@ void ParamBool::string(std::string &string) const return; } -Gtk::Widget *ParamBool::get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) +Gtk::Widget *ParamBool::get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) { if (_hidden) { return nullptr; diff --git a/src/extension/prefdialog/parameter-bool.h b/src/extension/prefdialog/parameter-bool.h index 9864cac38..5a73b42b3 100644 --- a/src/extension/prefdialog/parameter-bool.h +++ b/src/extension/prefdialog/parameter-bool.h @@ -29,17 +29,7 @@ namespace Extension { */ class ParamBool : public Parameter { public: - - /** - * Use the superclass' allocator and set the \c _value. - */ - ParamBool(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml); + ParamBool(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext); /** * Returns the current state/value. @@ -56,13 +46,13 @@ public: * @param doc A document that should be used to set the value. * @param node The node where the value may be placed */ - bool set(bool in, SPDocument * doc, Inkscape::XML::Node * node); + bool set(bool in, SPDocument *doc, Inkscape::XML::Node *node); /** * Creates a bool check button for a bool parameter. * Builds a hbox with a label and a check button in it. */ - Gtk::Widget *get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) override; + Gtk::Widget *get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) override; // Explicitly call superclass version to avoid method being hidden. void string(std::list <std::string> &list) const override { return Parameter::string(list); } @@ -75,7 +65,7 @@ public: private: /** Internal value. */ - bool _value; + bool _value = true; }; } // namespace Extension diff --git a/src/extension/prefdialog/parameter-color.cpp b/src/extension/prefdialog/parameter-color.cpp index 385c7b90f..52ee3de73 100644 --- a/src/extension/prefdialog/parameter-color.cpp +++ b/src/extension/prefdialog/parameter-color.cpp @@ -28,65 +28,44 @@ namespace Inkscape { namespace Extension { -ParamColor::~ParamColor() -{ - _color_changed.disconnect(); -} - -guint32 ParamColor::set( guint32 in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/ ) +ParamColor::ParamColor(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext) + : Parameter(xml, ext) { - _color_changed.block(true); - _color.setValue(in); - _color_changed.block(false); - - gchar * prefname = this->pref_name(); - std::string value; - string(value); - - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setString(extension_pref_root + prefname, value); - g_free(prefname); - - return in; -} - -ParamColor::ParamColor(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml) - : Parameter(name, text, description, hidden, indent, ext) - , _changeSignal(nullptr) -{ - const char * defaulthex = nullptr; - if (xml->firstChild() != nullptr) - defaulthex = xml->firstChild()->content(); + // get value + unsigned int _value = 0x000000ff; // default to black + if (xml->firstChild()) { + const char *value = xml->firstChild()->content(); + if (value) { + _value = strtoul(value, nullptr, 0); + } + } - gchar * pref_name = this->pref_name(); + gchar *pref_name = this->pref_name(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Glib::ustring paramval = prefs->getString(extension_pref_root + pref_name); + _value = prefs->getUInt(extension_pref_root + pref_name, _value); g_free(pref_name); - if (!paramval.empty()) - defaulthex = paramval.data(); + _color.setValue(_value); - if (defaulthex) { - _color.setValue(atoi(defaulthex)); - } _color_changed = _color.signal_changed.connect(sigc::mem_fun(this, &ParamColor::_onColorChanged)); + // TODO: SelectedColor does not properly emit signal_changed after dragging, so we also need the following + _color_released = _color.signal_released.connect(sigc::mem_fun(this, &ParamColor::_onColorChanged)); +} +ParamColor::~ParamColor() +{ + _color_changed.disconnect(); + _color_released.disconnect(); } -void ParamColor::string(std::string &string) const +guint32 ParamColor::set(guint32 in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) { - char str[16]; - snprintf(str, 16, "%i", _color.value()); - string += str; + _color.setValue(in); + + return in; } -Gtk::Widget *ParamColor::get_widget( SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/, sigc::signal<void> * changeSignal ) +Gtk::Widget *ParamColor::get_widget( SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/, sigc::signal<void> *changeSignal ) { using Inkscape::UI::Widget::ColorNotebook; @@ -96,25 +75,32 @@ Gtk::Widget *ParamColor::get_widget( SPDocument * /*doc*/, Inkscape::XML::Node * _changeSignal = new sigc::signal<void>(*changeSignal); } - if (_color.value() < 1) { - _color_changed.block(true); - _color.setValue(0xFF000000); - _color_changed.block(false); - } - Gtk::HBox *hbox = Gtk::manage(new Gtk::HBox(false, Parameter::GUI_PARAM_WIDGETS_SPACING)); Gtk::Widget *selector = Gtk::manage(new ColorNotebook(_color)); hbox->pack_start(*selector, true, true, 0); selector->show(); hbox->show(); + return hbox; } void ParamColor::_onColorChanged() { + gchar *pref_name = this->pref_name(); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setUInt(extension_pref_root + pref_name, _color.value()); + g_free(pref_name); + if (_changeSignal) _changeSignal->emit(); } +void ParamColor::string(std::string &string) const +{ + char str[16]; + snprintf(str, 16, "%u", _color.value()); + string += str; +} + }; /* namespace Extension */ }; /* namespace Inkscape */ diff --git a/src/extension/prefdialog/parameter-color.h b/src/extension/prefdialog/parameter-color.h index c2d3c2ccb..da78f5d61 100644 --- a/src/extension/prefdialog/parameter-color.h +++ b/src/extension/prefdialog/parameter-color.h @@ -31,29 +31,24 @@ private: Inkscape::UI::SelectedColor _color; sigc::connection _color_changed; + sigc::connection _color_released; public: - ParamColor(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml); + ParamColor(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext); ~ParamColor() override; /** Returns \c _value, with a \i const to protect it. */ guint32 get( SPDocument const * /*doc*/, Inkscape::XML::Node const * /*node*/ ) const { return _color.value(); } - guint32 set (guint32 in, SPDocument * doc, Inkscape::XML::Node * node); + guint32 set (guint32 in, SPDocument *doc, Inkscape::XML::Node *node); - Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) override; + Gtk::Widget *get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) override; // Explicitly call superclass version to avoid method being hidden. void string(std::list <std::string> &list) const override { return Parameter::string(list); } void string (std::string &string) const override; - sigc::signal<void> * _changeSignal; + sigc::signal<void> *_changeSignal; }; // class ParamColor diff --git a/src/extension/prefdialog/parameter-description.cpp b/src/extension/prefdialog/parameter-description.cpp index 667670443..3ceea7665 100644 --- a/src/extension/prefdialog/parameter-description.cpp +++ b/src/extension/prefdialog/parameter-description.cpp @@ -21,79 +21,68 @@ namespace Inkscape { namespace Extension { -/** \brief Initialize the object, to do that, copy the data. */ -ParamDescription::ParamDescription(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml, - AppearanceMode mode) - : Parameter(name, text, description, hidden, indent, ext) - , _value(nullptr) - , _mode(mode) +ParamDescription::ParamDescription(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext) + : Parameter(xml, ext) { // construct the text content by concatenating all (non-empty) text nodes, // removing all other nodes (e.g. comment nodes) and replacing <extension:br> elements with "<br/>" - Glib::ustring value; Inkscape::XML::Node * cur_child = xml->firstChild(); while (cur_child != nullptr) { if (cur_child->type() == XML::TEXT_NODE && cur_child->content() != nullptr) { - value += cur_child->content(); + _value += cur_child->content(); } else if (cur_child->type() == XML::ELEMENT_NODE && !g_strcmp0(cur_child->name(), "extension:br")) { - value += "<br/>"; + _value += "<br/>"; } cur_child = cur_child->next(); } - // if there is no text content we can return immediately (the description will be invisible) - if (value == Glib::ustring("")) { - return; - } - // do replacements in the source string to account for the attribute xml:space="preserve" // (those should match replacements potentially performed by xgettext to allow for proper translation) if (g_strcmp0(xml->attribute("xml:space"), "preserve") == 0) { // xgettext copies the source string verbatim in this case, so no changes needed } else { // remove all whitespace from start/end of string and replace intermediate whitespace with a single space - value = Glib::Regex::create("^\\s+|\\s+$")->replace_literal(value, 0, "", (Glib::RegexMatchFlags)0); - value = Glib::Regex::create("\\s+")->replace_literal(value, 0, " ", (Glib::RegexMatchFlags)0); + _value = Glib::Regex::create("^\\s+|\\s+$")->replace_literal(_value, 0, "", (Glib::RegexMatchFlags)0); + _value = Glib::Regex::create("\\s+")->replace_literal(_value, 0, " ", (Glib::RegexMatchFlags)0); } - // translate if underscored version (_param) was used - if (g_str_has_prefix(xml->name(), "extension:_")) { - const gchar * context = xml->attribute("msgctxt"); - if (context != nullptr) { - value = g_dpgettext2(nullptr, context, value.c_str()); - } else { - value = _(value.c_str()); + // translate value + if (!_value.empty()) { + if (_translatable != NO) { // translate unless explicitly marked untranslatable + if (_context) { + _value = g_dpgettext2(nullptr, _context, _value.c_str()); + } else { + _value = _(_value.c_str()); + } } } // finally replace all remaining <br/> with a real newline character - value = Glib::Regex::create("<br/>")->replace_literal(value, 0, "\n", (Glib::RegexMatchFlags)0); - - _value = g_strdup(value.c_str()); - - return; + _value = Glib::Regex::create("<br/>")->replace_literal(_value, 0, "\n", (Glib::RegexMatchFlags)0); + + // parse appearance + if (_appearance) { + if (!strcmp(_appearance, "header")) { + _mode = HEADER; + } else if (!strcmp(_appearance, "url")) { + _mode = URL; + } else { + g_warning("Invalid value ('%s') for appearance of parameter '%s' in extension '%s'", + _appearance, _name, _extension->get_id()); + } + } } /** \brief Create a label for the description */ -Gtk::Widget * -ParamDescription::get_widget (SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/, sigc::signal<void> * /*changeSignal*/) +Gtk::Widget *ParamDescription::get_widget (SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/, sigc::signal<void> * /*changeSignal*/) { if (_hidden) { return nullptr; } - if (_value == nullptr) { - return nullptr; - } Glib::ustring newtext = _value; - Gtk::Label * label = Gtk::manage(new Gtk::Label()); + Gtk::Label *label = Gtk::manage(new Gtk::Label()); if (_mode == HEADER) { label->set_markup(Glib::ustring("<b>") + Glib::Markup::escape_text(newtext) + Glib::ustring("</b>")); label->set_margin_top(5); @@ -109,10 +98,10 @@ ParamDescription::get_widget (SPDocument * /*doc*/, Inkscape::XML::Node * /*node // TODO: Ugly "fix" for gtk3 width/height calculation of labels. // - If not applying any limits long labels will make the window grow horizontally until it uses up - // most of the available space (i.e. most of the screen area) which is ridicously wide + // most of the available space (i.e. most of the screen area) which is ridiculously wide. // - By using "set_default_size(0,0)" in prefidalog.cpp we tell the window to shrink as much as possible, - // however this can result in a much to narrow dialog instead and much unnecessary wrapping - // - Here we set a lower limit of GUI_MAX_LINE_LENGTH characters per line that long texts will always use + // however this can result in a much too narrow dialog instead and a lot of unnecessary wrapping. + // - Here we set a lower limit of GUI_MAX_LINE_LENGTH characters per line that long texts will always use. // This means texts can not shrink anymore (they can still grow, though) and it's also necessary // to prevent https://bugzilla.gnome.org/show_bug.cgi?id=773572 int len = newtext.length(); @@ -120,7 +109,7 @@ ParamDescription::get_widget (SPDocument * /*doc*/, Inkscape::XML::Node * /*node label->show(); - Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox()); + Gtk::HBox *hbox = Gtk::manage(new Gtk::HBox()); hbox->pack_start(*label, true, true); hbox->show(); diff --git a/src/extension/prefdialog/parameter-description.h b/src/extension/prefdialog/parameter-description.h index 822370b82..7eac524a8 100644 --- a/src/extension/prefdialog/parameter-description.h +++ b/src/extension/prefdialog/parameter-description.h @@ -28,22 +28,18 @@ namespace Extension { class ParamDescription : public Parameter { public: enum AppearanceMode { - DESCRIPTION, HEADER, URL + DEFAULT, HEADER, URL }; - ParamDescription(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml, - AppearanceMode mode); - - Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) override; + + ParamDescription(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext); + + Gtk::Widget *get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) override; private: /** \brief Internal value. */ - gchar * _value; - AppearanceMode _mode; + Glib::ustring _value; + + /** appearance mode **/ + AppearanceMode _mode = DEFAULT; }; } /* namespace Extension */ diff --git a/src/extension/prefdialog/parameter-enum.cpp b/src/extension/prefdialog/parameter-enum.cpp deleted file mode 100644 index 9c71c3df8..000000000 --- a/src/extension/prefdialog/parameter-enum.cpp +++ /dev/null @@ -1,269 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/** \file - * extension parameter for enumerations. - * - * It uses a Gtk:ComboBoxText widget in the extension UI. - */ - -/* - * Author: - * Johan Engelen <johan@shouraizou.nl> - * Jon A. Cruz <jon@joncruz.org> - * - * Copyright (C) 2006-2007 Johan Engelen - * - * Released under GNU GPL v2+, read the file 'COPYING' for more information. - */ - -#include "parameter-enum.h" - -#include <gtkmm/box.h> -#include <gtkmm/comboboxtext.h> -#include <glibmm/i18n.h> - -#include "xml/node.h" -#include "extension/extension.h" -#include "preferences.h" - -namespace Inkscape { -namespace Extension { - -ParamComboBox::ParamComboBox(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml) - : Parameter(name, text, description, hidden, indent, ext) - , _value(nullptr) -{ - const char *xmlval = nullptr; // the value stored in XML - - if (xml != nullptr) { - // Read XML tree to add enumeration items: - for (Inkscape::XML::Node *node = xml->firstChild(); node; node = node->next()) { - char const * chname = node->name(); - if (!strcmp(chname, INKSCAPE_EXTENSION_NS "item") || !strcmp(chname, INKSCAPE_EXTENSION_NS "_item")) { - Glib::ustring newtext, newvalue; - const char * contents = nullptr; - if (node->firstChild()) { - contents = node->firstChild()->content(); - } - if (contents != nullptr) { - // don't translate when 'item' but do translate when '_item' - // NOTE: internal extensions use build_from_mem and don't need _item but - // still need to include if are to be localized - if (!strcmp(chname, INKSCAPE_EXTENSION_NS "_item")) { - if (node->attribute("msgctxt") != nullptr) { - newtext = g_dpgettext2(nullptr, node->attribute("msgctxt"), contents); - } else { - newtext = _(contents); - } - } else { - newtext = contents; - } - } else - continue; - - const char * val = node->attribute("value"); - if (val != nullptr) { - newvalue = val; - } else { - newvalue = contents; - } - - if ( (!newtext.empty()) && (!newvalue.empty()) ) { // logical error if this is not true here - choices.push_back(new enumentry(newvalue, newtext) ); - } - } - } - - // Initialize _value with the default value from xml - // for simplicity : default to the contents of the first xml-child - if (xml->firstChild() && xml->firstChild()->firstChild()) { - xmlval = xml->firstChild()->attribute("value"); - } - } - - gchar * pref_name = this->pref_name(); - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Glib::ustring paramval = prefs ? prefs->getString(extension_pref_root + pref_name) : ""; - g_free(pref_name); - - if (!paramval.empty()) { - _value = g_strdup(paramval.data()); - } else if (xmlval) { - _value = g_strdup(xmlval); - } -} - -ParamComboBox::~ParamComboBox () -{ - //destroy choice strings - for (auto i:choices) { - delete i; - } - g_free(_value); -} - - -/** - * A function to set the \c _value. - * - * This function sets ONLY the internal value, but it also sets the value - * in the preferences structure. To put it in the right place, \c PREF_DIR - * and \c pref_name() are used. - * - * To copy the data into _value the old memory must be free'd first. - * It is important to note that \c g_free handles \c NULL just fine. Then - * the passed in value is duplicated using \c g_strdup(). - * - * @param in The value to set. - * @param doc A document that should be used to set the value. - * @param node The node where the value may be placed. - */ -const gchar *ParamComboBox::set(const gchar * in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) -{ - if (in == nullptr) { - return nullptr; /* Can't have NULL string */ - } - - Glib::ustring settext; - for (auto entr:choices) { - if ( !entr->text.compare(in) ) { - settext = entr->value; - break; // break out of for loop - } - } - if (!settext.empty()) { - if (_value != nullptr) { - g_free(_value); - } - _value = g_strdup(settext.data()); - gchar * prefname = this->pref_name(); - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setString(extension_pref_root + prefname, _value); - g_free(prefname); - } - - return _value; -} - -/** - * function to test if \c text is selectable - */ -bool ParamComboBox::contains(const gchar * text, SPDocument const * /*doc*/, Inkscape::XML::Node const * /*node*/) const -{ - if (text == nullptr) { - return false; /* Can't have NULL string */ - } - - for (auto entr:choices) { - if ( !entr->text.compare(text) ) - return true; - } - // if we did not find the text in this ParamComboBox: - return false; -} - -void -ParamComboBox::changed () { - -} - -void ParamComboBox::string(std::string &string) const -{ - string += _value; -} - - - - -/** A special category of Gtk::Entry to handle string parameteres. */ -class ParamComboBoxEntry : public Gtk::ComboBoxText { -private: - ParamComboBox * _pref; - SPDocument * _doc; - Inkscape::XML::Node * _node; - sigc::signal<void> * _changeSignal; -public: - /** - * Build a string preference for the given parameter. - * @param pref Where to get the string from, and where to put it - * when it changes. - */ - ParamComboBoxEntry (ParamComboBox * pref, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) : - Gtk::ComboBoxText(), _pref(pref), _doc(doc), _node(node), _changeSignal(changeSignal) { - this->signal_changed().connect(sigc::mem_fun(this, &ParamComboBoxEntry::changed)); - }; - void changed (); -}; - -/** - * Respond to the text box changing. - * - * This function responds to the box changing by grabbing the value - * from the text box and putting it in the parameter. - */ -void -ParamComboBoxEntry::changed () -{ - Glib::ustring data = this->get_active_text(); - _pref->set(data.c_str(), _doc, _node); - if (_changeSignal != nullptr) { - _changeSignal->emit(); - } -} - -/** - * Creates a combobox widget for an enumeration parameter. - */ -Gtk::Widget *ParamComboBox::get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) -{ - if (_hidden) { - return nullptr; - } - - Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, Parameter::GUI_PARAM_WIDGETS_SPACING)); - Gtk::Label * label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START)); - label->show(); - hbox->pack_start(*label, false, false); - - ParamComboBoxEntry * combo = Gtk::manage(new ParamComboBoxEntry(this, doc, node, changeSignal)); - // add choice strings: - Glib::ustring settext; - for (auto entr:choices) { - Glib::ustring text = entr->text; - combo->append(text); - - if ( _value && !entr->value.compare(_value) ) { - settext = entr->text; - } - } - if (!settext.empty()) { - combo->set_active_text(settext); - } - - combo->show(); - hbox->pack_start(*combo, true, true); - - hbox->show(); - - return dynamic_cast<Gtk::Widget *>(hbox); -} - - -} // namespace Extension -} // namespace Inkscape - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/extension/prefdialog/parameter-enum.h b/src/extension/prefdialog/parameter-enum.h deleted file mode 100644 index 329bb26f9..000000000 --- a/src/extension/prefdialog/parameter-enum.h +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -#ifndef INK_EXTENSION_PARAMENUM_H_SEEN -#define INK_EXTENSION_PARAMENUM_H_SEEN - -/** \file - * Enumeration parameter for extensions. - */ - -/* - * Authors: - * Johan Engelen <johan@shouraizou.nl> - * Jon A. Cruz <jon@joncruz.org> - * - * Copyright (C) 2006-2007 Johan Engelen - * - * Released under GNU GPL v2+, read the file 'COPYING' for more information. - */ - -#include <vector> - -#include "parameter.h" -#include "document.h" - -namespace Gtk { -class Widget; -} - -namespace Inkscape { -namespace Extension { - -class Extension; - - -// \brief A class to represent a notebookparameter of an extension -class ParamComboBox : public Parameter { -private: - /** \brief Internal value. This should point to a string that has - been allocated in memory. And should be free'd. - It is the value of the current selected string */ - gchar * _value; - - /* For internal use only. - * Note that value and text MUST be non-NULL. - * This is ensured by newing only at one location in the code where non-NULL checks are made. - */ - class enumentry { - public: - enumentry (Glib::ustring &val, Glib::ustring &text) : - value(val), - text(text) - {} - - Glib::ustring value; - Glib::ustring text; - }; - - std::vector<enumentry *> choices; /**< A table to store the choice strings */ - -public: - ParamComboBox(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml); - ~ParamComboBox() override; - - Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) override; - - // Explicitly call superclass version to avoid method being hidden. - void string(std::list <std::string> &list) const override { return Parameter::string(list); } - - void string(std::string &string) const override; - - gchar const *get(SPDocument const * /*doc*/, Inkscape::XML::Node const * /*node*/) const { return _value; } - - const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node); - - /** - * @returns true if text is part of this enum - */ - bool contains(const gchar * text, SPDocument const * /*doc*/, Inkscape::XML::Node const * /*node*/) const; - - void changed (); -}; /* class ParamComboBox */ - - - - - -} /* namespace Extension */ -} /* namespace Inkscape */ - -#endif /* INK_EXTENSION_PARAMENUM_H_SEEN */ - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/extension/prefdialog/parameter-float.cpp b/src/extension/prefdialog/parameter-float.cpp index 79908d841..fe8a55093 100644 --- a/src/extension/prefdialog/parameter-float.cpp +++ b/src/extension/prefdialog/parameter-float.cpp @@ -22,67 +22,57 @@ namespace Inkscape { namespace Extension { - -/** Use the superclass' allocator and set the \c _value. */ -ParamFloat::ParamFloat(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml, - AppearanceMode mode) - : Parameter(name, text, description, hidden, indent, ext) - , _value(0.0) - , _mode(mode) - , _min(0.0) - , _max(10.0) +ParamFloat::ParamFloat(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext) + : Parameter(xml, ext) { - const gchar * defaultval = nullptr; - if (xml->firstChild() != nullptr) { - defaultval = xml->firstChild()->content(); - } - if (defaultval != nullptr) { - _value = g_ascii_strtod (defaultval,nullptr); + // get value + if (xml->firstChild()) { + const char *value = xml->firstChild()->content(); + if (value) { + _value = g_ascii_strtod(value, nullptr); + } } - const char * maxval = xml->attribute("max"); - if (maxval != nullptr) { - _max = g_ascii_strtod (maxval,nullptr); - } + gchar *pref_name = this->pref_name(); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + _value = prefs->getDouble(extension_pref_root + pref_name, _value); + g_free(pref_name); - const char * minval = xml->attribute("min"); - if (minval != nullptr) { - _min = g_ascii_strtod (minval,nullptr); + // parse and apply limits + const char *min = xml->attribute("min"); + if (min) { + _min = g_ascii_strtod(min, nullptr); } - _precision = 1; - const char * precision = xml->attribute("precision"); - if (precision != nullptr) { - _precision = atoi(precision); + const char *max = xml->attribute("max"); + if (max) { + _max = g_ascii_strtod(max, nullptr); } - /* We're handling this by just killing both values */ - if (_max < _min) { - _max = 10.0; - _min = 0.0; + if (_value < _min) { + _value = _min; } - gchar * pref_name = this->pref_name(); - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - _value = prefs->getDouble(extension_pref_root + pref_name, _value); - g_free(pref_name); - - // std::cout << "New Float:: value: " << _value << " max: " << _max << " min: " << _min << std::endl; - if (_value > _max) { _value = _max; } - if (_value < _min) { - _value = _min; + + // parse precision + const char *precision = xml->attribute("precision"); + if (precision != nullptr) { + _precision = strtol(precision, nullptr, 0); } - return; + + // parse appearance + if (_appearance) { + if (!strcmp(_appearance, "full")) { + _mode = FULL; + } else { + g_warning("Invalid value ('%s') for appearance of parameter '%s' in extension '%s'", + _appearance, _name, _extension->get_id()); + } + } } /** @@ -106,10 +96,10 @@ float ParamFloat::set(float in, SPDocument * /*doc*/, Inkscape::XML::Node * /*no _value = _min; } - gchar * prefname = this->pref_name(); + gchar *pref_name = this->pref_name(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setDouble(extension_pref_root + prefname, _value); - g_free(prefname); + prefs->setDouble(extension_pref_root + pref_name, _value); + g_free(pref_name); return _value; } @@ -125,14 +115,14 @@ void ParamFloat::string(std::string &string) const /** A class to make an adjustment that uses Extension params. */ class ParamFloatAdjustment : public Gtk::Adjustment { /** The parameter to adjust. */ - ParamFloat * _pref; - SPDocument * _doc; - Inkscape::XML::Node * _node; - sigc::signal<void> * _changeSignal; + ParamFloat *_pref; + SPDocument *_doc; + Inkscape::XML::Node *_node; + sigc::signal<void> *_changeSignal; public: /** Make the adjustment using an extension and the string describing the parameter. */ - ParamFloatAdjustment (ParamFloat * param, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) : + ParamFloatAdjustment (ParamFloat *param, SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) : Gtk::Adjustment(0.0, param->min(), param->max(), 0.1, 1.0, 0), _pref(param), _doc(doc), _node(node), _changeSignal(changeSignal) { this->set_value(_pref->get(nullptr, nullptr) /* \todo fix */); this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed)); @@ -163,13 +153,13 @@ void ParamFloatAdjustment::val_changed() * * Builds a hbox with a label and a float adjustment in it. */ -Gtk::Widget * ParamFloat::get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) +Gtk::Widget *ParamFloat::get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) { if (_hidden) { return nullptr; } - Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, Parameter::GUI_PARAM_WIDGETS_SPACING)); + Gtk::HBox *hbox = Gtk::manage(new Gtk::HBox(false, Parameter::GUI_PARAM_WIDGETS_SPACING)); auto pfa = new ParamFloatAdjustment(this, doc, node, changeSignal); Glib::RefPtr<Gtk::Adjustment> fadjust(pfa); @@ -185,9 +175,9 @@ Gtk::Widget * ParamFloat::get_widget(SPDocument * doc, Inkscape::XML::Node * nod hbox->pack_start(*scale, true, true); } - else if (_mode == MINIMAL) { + else if (_mode == DEFAULT) { - Gtk::Label * label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START)); + Gtk::Label *label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START)); label->show(); hbox->pack_start(*label, true, true); diff --git a/src/extension/prefdialog/parameter-float.h b/src/extension/prefdialog/parameter-float.h index c1d0f0f79..0c42ef2bc 100644 --- a/src/extension/prefdialog/parameter-float.h +++ b/src/extension/prefdialog/parameter-float.h @@ -28,21 +28,15 @@ namespace Extension { class ParamFloat : public Parameter { public: enum AppearanceMode { - FULL, MINIMAL + DEFAULT, FULL }; - ParamFloat(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml, - AppearanceMode mode); + + ParamFloat(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext); /** Returns \c _value. */ float get(const SPDocument * /*doc*/, const Inkscape::XML::Node * /*node*/) const { return _value; } - float set (float in, SPDocument * doc, Inkscape::XML::Node * node); + float set (float in, SPDocument *doc, Inkscape::XML::Node *node); float max () { return _max; } @@ -50,7 +44,7 @@ public: float precision () { return _precision; } - Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) override; + Gtk::Widget *get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) override; // Explicitly call superclass version to avoid method being hidden. void string(std::list <std::string> &list) const override { return Parameter::string(list); } @@ -59,11 +53,18 @@ public: private: /** Internal value. */ - float _value; - AppearanceMode _mode; - float _min; - float _max; - int _precision; + float _value = 0; + + /** limits */ + // TODO: do these defaults make sense or should we be unbounded by default? + float _min = 0; + float _max = 10; + + /** numeric precision (i.e. number of digits) */ + int _precision = 1; + + /** appearance mode **/ + AppearanceMode _mode = DEFAULT; }; } /* namespace Extension */ diff --git a/src/extension/prefdialog/parameter-int.cpp b/src/extension/prefdialog/parameter-int.cpp index 2b9e2c5f6..b03afc1e1 100644 --- a/src/extension/prefdialog/parameter-int.cpp +++ b/src/extension/prefdialog/parameter-int.cpp @@ -23,42 +23,15 @@ namespace Inkscape { namespace Extension { -/** Use the superclass' allocator and set the \c _value. */ -ParamInt::ParamInt(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml, - AppearanceMode mode) - : Parameter(name, text, description, hidden, indent, ext) - , _value(0) - , _mode(mode) - , _min(0) - , _max(10) +ParamInt::ParamInt(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext) + : Parameter(xml, ext) { - const char * defaultval = nullptr; - if (xml->firstChild() != nullptr) { - defaultval = xml->firstChild()->content(); - } - if (defaultval != nullptr) { - _value = atoi(defaultval); - } - - const char * maxval = xml->attribute("max"); - if (maxval != nullptr) { - _max = atoi(maxval); - } - - const char * minval = xml->attribute("min"); - if (minval != nullptr) { - _min = atoi(minval); - } - /* We're handling this by just killing both values */ - if (_max < _min) { - _max = 10; - _min = 0; + // get value + if (xml->firstChild()) { + const char *value = xml->firstChild()->content(); + if (value) { + _value = strtol(value, nullptr, 0); + } } gchar *pref_name = this->pref_name(); @@ -66,14 +39,34 @@ ParamInt::ParamInt(const gchar * name, _value = prefs->getInt(extension_pref_root + pref_name, _value); g_free(pref_name); - // std::cout << "New Int:: value: " << _value << " max: " << _max << " min: " << _min << std::endl; + // parse and apply limits + const char *min = xml->attribute("min"); + if (min) { + _min = strtol(min, nullptr, 0); + } - if (_value > _max) { - _value = _max; + const char *max = xml->attribute("max"); + if (max) { + _max = strtol(max, nullptr, 0); } + if (_value < _min) { _value = _min; } + + if (_value > _max) { + _value = _max; + } + + // parse appearance + if (_appearance) { + if (!strcmp(_appearance, "full")) { + _mode = FULL; + } else { + g_warning("Invalid value ('%s') for appearance of parameter '%s' in extension '%s'", + _appearance, _name, _extension->get_id()); + } + } } /** @@ -96,10 +89,10 @@ int ParamInt::set(int in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) _value = _min; } - gchar * prefname = this->pref_name(); + gchar *pref_name = this->pref_name(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setInt(extension_pref_root + prefname, _value); - g_free(prefname); + prefs->setInt(extension_pref_root + pref_name, _value); + g_free(pref_name); return _value; } @@ -107,14 +100,14 @@ int ParamInt::set(int in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) /** A class to make an adjustment that uses Extension params. */ class ParamIntAdjustment : public Gtk::Adjustment { /** The parameter to adjust. */ - ParamInt * _pref; - SPDocument * _doc; - Inkscape::XML::Node * _node; - sigc::signal<void> * _changeSignal; + ParamInt *_pref; + SPDocument *_doc; + Inkscape::XML::Node *_node; + sigc::signal<void> *_changeSignal; public: /** Make the adjustment using an extension and the string describing the parameter. */ - ParamIntAdjustment (ParamInt * param, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) : + ParamIntAdjustment (ParamInt *param, SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) : Gtk::Adjustment(0.0, param->min(), param->max(), 1.0, 10.0, 0), _pref(param), _doc(doc), _node(node), _changeSignal(changeSignal) { this->set_value(_pref->get(nullptr, nullptr) /* \todo fix */); this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed)); @@ -144,13 +137,13 @@ void ParamIntAdjustment::val_changed() * Builds a hbox with a label and a int adjustment in it. */ Gtk::Widget * -ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) +ParamInt::get_widget (SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) { if (_hidden) { return nullptr; } - Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, Parameter::GUI_PARAM_WIDGETS_SPACING)); + Gtk::HBox *hbox = Gtk::manage(new Gtk::HBox(false, Parameter::GUI_PARAM_WIDGETS_SPACING)); auto pia = new ParamIntAdjustment(this, doc, node, changeSignal); Glib::RefPtr<Gtk::Adjustment> fadjust(pia); @@ -165,8 +158,8 @@ ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal scale->show(); hbox->pack_start(*scale, true, true); } - else if (_mode == MINIMAL) { - Gtk::Label * label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START)); + else if (_mode == DEFAULT) { + Gtk::Label *label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START)); label->show(); hbox->pack_start(*label, true, true); diff --git a/src/extension/prefdialog/parameter-int.h b/src/extension/prefdialog/parameter-int.h index fac481267..30e34740c 100644 --- a/src/extension/prefdialog/parameter-int.h +++ b/src/extension/prefdialog/parameter-int.h @@ -28,27 +28,21 @@ namespace Extension { class ParamInt : public Parameter { public: enum AppearanceMode { - FULL, MINIMAL + DEFAULT, FULL }; - ParamInt(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml, - AppearanceMode mode); + + ParamInt(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext); /** Returns \c _value. */ int get(const SPDocument * /*doc*/, const Inkscape::XML::Node * /*node*/) const { return _value; } - int set (int in, SPDocument * doc, Inkscape::XML::Node * node); + int set (int in, SPDocument *doc, Inkscape::XML::Node *node); int max () { return _max; } int min () { return _min; } - Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) override; + Gtk::Widget *get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) override; // Explicitly call superclass version to avoid method being hidden. void string(std::list <std::string> &list) const override { return Parameter::string(list); } @@ -57,10 +51,15 @@ public: private: /** Internal value. */ - int _value; - AppearanceMode _mode; - int _min; - int _max; + int _value = 0; + + /** limits */ + // TODO: do these defaults make sense or should we be unbounded by default? + int _min = 0; + int _max = 10; + + /** appearance mode **/ + AppearanceMode _mode = DEFAULT; }; } /* namespace Extension */ diff --git a/src/extension/prefdialog/parameter-notebook.cpp b/src/extension/prefdialog/parameter-notebook.cpp index 77d94aa5a..6e733a4b4 100644 --- a/src/extension/prefdialog/parameter-notebook.cpp +++ b/src/extension/prefdialog/parameter-notebook.cpp @@ -38,30 +38,28 @@ namespace Inkscape { namespace Extension { -ParamNotebook::ParamNotebookPage::ParamNotebookPage(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml) - : Parameter(name, text, description, hidden, /*indent*/ 0, ext) +ParamNotebook::ParamNotebookPage::ParamNotebookPage(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext) + : Parameter(xml, ext) { - - // Read XML to build page - if (xml != nullptr) { + // Read XML tree of page and parse parameters + if (xml) { Inkscape::XML::Node *child_repr = xml->firstChild(); - while (child_repr != nullptr) { - char const * chname = child_repr->name(); + while (child_repr) { + const char *chname = child_repr->name(); if (!strncmp(chname, INKSCAPE_EXTENSION_NS_NC, strlen(INKSCAPE_EXTENSION_NS_NC))) { chname += strlen(INKSCAPE_EXTENSION_NS); } - if (chname[0] == '_') // Allow _ for translation of tags + if (chname[0] == '_') { // allow leading underscore in tag names for backwards-compatibility chname++; + } + if (!strcmp(chname, "param") || !strcmp(chname, "_param")) { - Parameter * param; - param = Parameter::make(child_repr, ext); - if (param != nullptr) parameters.push_back(param); + Parameter *param = Parameter::make(child_repr, ext); + if (param) { + parameters.push_back(param); + } } + child_repr = child_repr->next(); } } @@ -70,88 +68,25 @@ ParamNotebook::ParamNotebookPage::ParamNotebookPage(const gchar * name, ParamNotebook::ParamNotebookPage::~ParamNotebookPage () { //destroy parameters - for (auto param:parameters) { - delete param; + for (auto parameter : parameters) { + delete parameter; } } /** Return the value as a string. */ void ParamNotebook::ParamNotebookPage::paramString(std::list <std::string> &list) { - for (auto param:parameters) { - param->string(list); - } -} - - -/** - \return None - \brief This function creates a page that can be used later. This - is typically done in the creation of the notebook and defined - in the XML file describing the extension (it's private so people - have to use the system) :) - \param in_repr The XML describing the page - \todo the 'gui-hidden' attribute is read but not used! - - This function first grabs all of the data out of the Repr and puts - it into local variables. Actually, these are just pointers, and the - data is not duplicated so we need to be careful with it. If there - isn't a name in the XML, then no page is created as - the function just returns. - - From this point on, we're pretty committed as we've allocated an - object and we're starting to fill it. The name is set first, and - is created with a strdup to actually allocate memory for it. Then - there is a case statement (roughly because strcmp requires 'ifs') - based on what type of parameter this is. Depending which type it - is, the value is interpreted differently, but they are relatively - straight forward. In all cases the value is set to the default - value from the XML and the type is set to the interpreted type. -*/ -ParamNotebook::ParamNotebookPage * -ParamNotebook::ParamNotebookPage::makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext) -{ - const char * name; - const char * text; - const char * description; - bool hidden = false; - const char * hide; - - name = in_repr->attribute("name"); - text = in_repr->attribute("gui-text"); - if (text == nullptr) - text = in_repr->attribute("_gui-text"); - description = in_repr->attribute("gui-description"); - if (description == nullptr) - description = in_repr->attribute("_gui-description"); - hide = in_repr->attribute("gui-hidden"); - if (hide != nullptr) { - if (strcmp(hide, "1") == 0 || - strcmp(hide, "true") == 0) { - hidden = true; - } - /* else stays false */ + for (auto parameter : parameters) { + parameter->string(list); } - - /* In this case we just don't have enough information */ - if (name == nullptr) { - return nullptr; - } - - ParamNotebookPage * page = new ParamNotebookPage(name, text, description, hidden, in_ext, in_repr); - - /* Note: page could equal NULL */ - return page; } - - /** * Creates a notebookpage widget for a notebook. * * Builds a notebook page (a vbox) and puts parameters on it. */ -Gtk::Widget * ParamNotebook::ParamNotebookPage::get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) +Gtk::Widget *ParamNotebook::ParamNotebookPage::get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) { if (_hidden) { return nullptr; @@ -162,19 +97,16 @@ Gtk::Widget * ParamNotebook::ParamNotebookPage::get_widget(SPDocument * doc, Ink vbox->set_spacing(Parameter::GUI_BOX_SPACING); // add parameters onto page (if any) - for (auto param:parameters) { - Gtk::Widget * widg = param->get_widget(doc, node, changeSignal); - if (widg) { - int indent = param->get_indent(); - widg->set_margin_start(indent * Parameter::GUI_INDENTATION); - vbox->pack_start(*widg, false, false, 0); - - gchar const * tip = param->get_tooltip(); - if (tip) { - widg->set_tooltip_text(tip); - } else { - widg->set_tooltip_text(""); - widg->set_has_tooltip(false); + for (auto parameter : parameters) { + Gtk::Widget *parameter_widget = parameter->get_widget(doc, node, changeSignal); + if (parameter_widget) { + int indent = parameter->get_indent(); + parameter_widget->set_margin_start(indent *Parameter::GUI_INDENTATION); + vbox->pack_start(*parameter_widget, false, false, 0); + + const gchar *tooltip = parameter->get_tooltip(); + if (tooltip) { + parameter_widget->set_tooltip_text(tooltip); } } } @@ -185,7 +117,7 @@ Gtk::Widget * ParamNotebook::ParamNotebookPage::get_widget(SPDocument * doc, Ink } /** Search the parameter's name in the page content. */ -Parameter *ParamNotebook::ParamNotebookPage::get_param(const gchar * name) +Parameter *ParamNotebook::ParamNotebookPage::get_param(const gchar *name) { if (name == nullptr) { throw Extension::param_not_exist(); @@ -195,7 +127,7 @@ Parameter *ParamNotebook::ParamNotebookPage::get_param(const gchar * name) throw Extension::param_not_exist(); } - for (auto param:parameters) { + for (auto param : parameters) { if (!strcmp(param->name(), name)) { return param; } @@ -207,59 +139,49 @@ Parameter *ParamNotebook::ParamNotebookPage::get_param(const gchar * name) /** End ParamNotebookPage **/ /** ParamNotebook **/ -ParamNotebook::ParamNotebook(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml) - : Parameter(name, text, description, hidden, indent, ext) +ParamNotebook::ParamNotebook(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext) + : Parameter(xml, ext) { - // Read XML tree to add pages: - if (xml != nullptr) { + // Read XML tree to add pages (allow _page for backwards compatibility) + if (xml) { Inkscape::XML::Node *child_repr = xml->firstChild(); - while (child_repr != nullptr) { - char const * chname = child_repr->name(); - if (!strncmp(chname, INKSCAPE_EXTENSION_NS_NC, strlen(INKSCAPE_EXTENSION_NS_NC))) { - chname += strlen(INKSCAPE_EXTENSION_NS); - } - if (chname[0] == '_') // Allow _ for translation of tags - chname++; - if (!strcmp(chname, "page")) { - ParamNotebookPage * page; - page = ParamNotebookPage::makepage(child_repr, ext); - if (page != nullptr) pages.push_back(page); + while (child_repr) { + const char *chname = child_repr->name(); + if (chname && (!strcmp(chname, INKSCAPE_EXTENSION_NS "page") || + !strcmp(chname, INKSCAPE_EXTENSION_NS "_page") )) { + ParamNotebookPage *page; + page = new ParamNotebookPage(child_repr, ext); + + if (page) { + pages.push_back(page); + } } child_repr = child_repr->next(); } } - - // Initialize _value with the current page - const char * defaultval = nullptr; - // set first page as default - if (!pages.empty()) { - defaultval = pages[0]->name(); + if (pages.empty()) { + g_warning("No (valid) pages for parameter '%s' in extension '%s'", _name, _extension->get_id()); } - gchar * pref_name = this->pref_name(); + // get value (initialize with value of first page if pref is empty) + gchar *pref_name = this->pref_name(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Glib::ustring paramval = prefs->getString(extension_pref_root + pref_name); + _value = prefs->getString(extension_pref_root + pref_name); g_free(pref_name); - if (!paramval.empty()) - defaultval = paramval.data(); - if (defaultval != nullptr) - _value = g_strdup(defaultval); // allocate space for _value + if (_value.empty()) { + if (!pages.empty()) { + _value = pages[0]->name(); + } + } } ParamNotebook::~ParamNotebook () { //destroy pages - for (auto page:pages) { + for (auto page : pages) { delete page; } - g_free(_value); } @@ -270,28 +192,23 @@ ParamNotebook::~ParamNotebook () * in the preferences structure. To put it in the right place, \c PREF_DIR * and \c pref_name() are used. * - * To copy the data into _value the old memory must be free'd first. - * It is important to note that \c g_free handles \c NULL just fine. Then - * the passed in value is duplicated using \c g_strdup(). - * - * @param in The number of the page which value must be set. + * @param in The number of the page to set as new value. * @param doc A document that should be used to set the value. * @param node The node where the value may be placed. */ -const gchar *ParamNotebook::set(const int in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) +const Glib::ustring& ParamNotebook::set(const int in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) { int i = in < pages.size() ? in : pages.size()-1; - ParamNotebookPage * page = pages[i]; - - if (page == nullptr) return _value; + ParamNotebookPage *page = pages[i]; - if (_value != nullptr) g_free(_value); - _value = g_strdup(page->name()); + if (page) { + _value = page->name(); - gchar * prefname = this->pref_name(); - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setString(extension_pref_root + prefname, _value); - g_free(prefname); + gchar *pref_name = this->pref_name(); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setString(extension_pref_root + pref_name, _value); + g_free(pref_name); + } return _value; } @@ -300,7 +217,7 @@ void ParamNotebook::string(std::list <std::string> &list) const { std::string param_string; param_string += "--"; - param_string += name(); + param_string += _name; param_string += "="; param_string += "\""; @@ -308,30 +225,35 @@ void ParamNotebook::string(std::list <std::string> &list) const param_string += "\""; list.insert(list.end(), param_string); - for (auto page:pages) { + for (auto page : pages) { page->paramString(list); } } /** A special category of Gtk::Notebook to handle notebook parameters. */ -class ParamNotebookWdg : public Gtk::Notebook { +class NotebookWidget : public Gtk::Notebook { private: - ParamNotebook * _pref; - SPDocument * _doc; - Inkscape::XML::Node * _node; + ParamNotebook *_pref; + SPDocument *_doc; + Inkscape::XML::Node *_node; public: /** * Build a notebookpage preference for the given parameter. - * @param pref Where to get the string (pagename) from, and where to put it - * when it changes. + * @param pref Where to get the string (pagename) from, and where to put it when it changes. */ - ParamNotebookWdg (ParamNotebook * pref, SPDocument * doc, Inkscape::XML::Node * node) : - Gtk::Notebook(), _pref(pref), _doc(doc), _node(node), activated(false) { - // don't have to set the correct page: this is done in ParamNotebook::get_widget. - // hook function - this->signal_switch_page().connect(sigc::mem_fun(this, &ParamNotebookWdg::changed_page)); - }; + NotebookWidget (ParamNotebook *pref, SPDocument *doc, Inkscape::XML::Node *node) + : Gtk::Notebook() + , _pref(pref) + , _doc(doc) + , _node(node) + , activated(false) + { + // don't have to set the correct page: this is done in ParamNotebook::get_widget hook function + this->signal_switch_page().connect(sigc::mem_fun(this, &NotebookWidget::changed_page)); + } + void changed_page(Gtk::Widget *page, guint pagenum); + bool activated; }; @@ -342,7 +264,7 @@ public: * is actually visible. This to exclude 'fake' changes when the * notebookpages are added or removed. */ -void ParamNotebookWdg::changed_page(Gtk::Widget * /*page*/, guint pagenum) +void NotebookWidget::changed_page(Gtk::Widget * /*page*/, guint pagenum) { if (get_visible()) { _pref->set((int)pagenum, _doc, _node); @@ -350,13 +272,13 @@ void ParamNotebookWdg::changed_page(Gtk::Widget * /*page*/, guint pagenum) } /** Search the parameter's name in the notebook content. */ -Parameter *ParamNotebook::get_param(const gchar * name) +Parameter *ParamNotebook::get_param(const gchar *name) { if (name == nullptr) { throw Extension::param_not_exist(); } - for (auto page:pages) { - Parameter * subparam = page->get_param(name); + for (auto page : pages) { + Parameter *subparam = page->get_param(name); if (subparam) { return subparam; } @@ -371,31 +293,32 @@ Parameter *ParamNotebook::get_param(const gchar * name) * * Builds a notebook and puts pages in it. */ -Gtk::Widget * ParamNotebook::get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) +Gtk::Widget *ParamNotebook::get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) { if (_hidden) { return nullptr; } - ParamNotebookWdg * nb = Gtk::manage(new ParamNotebookWdg(this, doc, node)); - - // add pages (if any) - int i = -1; - int pagenr = i; - for (auto page:pages) { - i++; - Gtk::Widget * widg = page->get_widget(doc, node, changeSignal); - nb->append_page(*widg, _(page->get_text())); - if (!strcmp(_value, page->name())) { - pagenr = i; // this is the page to be displayed? + NotebookWidget *notebook = Gtk::manage(new NotebookWidget(this, doc, node)); + + // add pages (if any) and switch to previously selected page + int current_page = -1; + int selected_page = -1; + for (auto page : pages) { + current_page++; + Gtk::Widget *page_widget = page->get_widget(doc, node, changeSignal); + notebook->append_page(*page_widget, _(page->get_text())); + if (_value == page->name()) { + selected_page = current_page; } } + if (selected_page >= 0) { + notebook->set_current_page(selected_page); + } - nb->show(); - - if (pagenr >= 0) nb->set_current_page(pagenr); + notebook->show(); - return dynamic_cast<Gtk::Widget *>(nb); + return static_cast<Gtk::Widget *>(notebook); } diff --git a/src/extension/prefdialog/parameter-notebook.h b/src/extension/prefdialog/parameter-notebook.h index f1e16308b..8f6243fc8 100644 --- a/src/extension/prefdialog/parameter-notebook.h +++ b/src/extension/prefdialog/parameter-notebook.h @@ -24,63 +24,50 @@ namespace Gtk { class Widget; } +namespace Glib { +class ustring; +} + namespace Inkscape { namespace Extension { class Extension; -/** A class to represent a notebookparameter of an extension. */ +/** A class to represent a notebook parameter of an extension. */ class ParamNotebook : public Parameter { private: - /** - * Internal value. This should point to a string that has - * been allocated in memory. And should be free'd. - * It is the name of the current page. - */ - gchar * _value; + /** Internal value. */ + Glib::ustring _value; /** - * A class to represent the pages of a notebookparameter of an extension. + * A class to represent the pages of a notebook parameter of an extension. */ class ParamNotebookPage : public Parameter { private: - std::vector<Parameter *> parameters; /**< A table to store the parameters for this page. - This only gets created if there are parameters on this - page */ + /** A table to store the parameters for this page. + * This only gets created if there are parameters on this page */ + std::vector<Parameter *> parameters; public: - static ParamNotebookPage * makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext); - - ParamNotebookPage(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml); + ParamNotebookPage(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext); ~ParamNotebookPage() override; - Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) override; + Gtk::Widget *get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) override; void paramString (std::list <std::string> &list); - gchar * get_text () {return _text;}; - Parameter * get_param (const gchar * name) override; + gchar *get_text () {return _text;}; + Parameter *get_param (const gchar *name) override; }; /* class ParamNotebookPage */ + /** A table to store the pages with parameters for this notebook. + * This only gets created if there are pages in this notebook */ + std::vector<ParamNotebookPage*> pages; - std::vector<ParamNotebookPage*> pages; /**< A table to store the pages with parameters for this notebook. - This only gets created if there are pages in this - notebook */ public: - ParamNotebook(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml); + ParamNotebook(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext); ~ParamNotebook() override; - Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) override; + Gtk::Widget *get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) override; /** * A function to get the currentpage and the parameters in a string form. @@ -92,10 +79,10 @@ public: void string(std::string &string) const override {return Parameter::string(string);} - Parameter * get_param (const gchar * name) override; + Parameter *get_param (const gchar *name) override; - const gchar * get (const SPDocument * /*doc*/, const Inkscape::XML::Node * /*node*/) { return _value; } - const gchar * set (const int in, SPDocument * doc, Inkscape::XML::Node * node); + const Glib::ustring& get (const SPDocument * /*doc*/, const Inkscape::XML::Node * /*node*/) { return _value; } + const Glib::ustring& set (const int in, SPDocument *doc, Inkscape::XML::Node *node); }; /* class ParamNotebook */ diff --git a/src/extension/prefdialog/parameter-optiongroup.cpp b/src/extension/prefdialog/parameter-optiongroup.cpp new file mode 100644 index 000000000..4fa43d44c --- /dev/null +++ b/src/extension/prefdialog/parameter-optiongroup.cpp @@ -0,0 +1,342 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** \file + *extension parameter for options with multiple predefined value choices + * + * Currently implemented as either Gtk::RadioButton or Gtk::ComboBoxText + */ + +/* + * Author: + * Johan Engelen <johan@shouraizou.nl> + * + * Copyright (C) 2006-2007 Johan Engelen + * Copyright (C) 2008 Jon A. Cruz + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include "parameter-optiongroup.h" + +#include <gtkmm/box.h> +#include <gtkmm/comboboxtext.h> +#include <gtkmm/radiobutton.h> +#include <glibmm/i18n.h> + +#include "xml/node.h" +#include "extension/extension.h" +#include "preferences.h" + +/** + * The root directory in the preferences database for extension + * related parameters. + */ +#define PREF_DIR "extensions" + +namespace Inkscape { +namespace Extension { + +ParamOptionGroup::ParamOptionGroup(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext) + : Parameter(xml, ext) +{ + // Read valid optiongroup choices from XML tree, i,e. + // - <option> elements + // - <item> elements (for backwards-compatibility with params of type enum) + // - underscored variants of both (for backwards-compatibility) + if (xml) { + Inkscape::XML::Node *child_repr = xml->firstChild(); + while (child_repr) { + const char *chname = child_repr->name(); + if (chname && (!strcmp(chname, INKSCAPE_EXTENSION_NS "option") || + !strcmp(chname, INKSCAPE_EXTENSION_NS "_option") || + !strcmp(chname, INKSCAPE_EXTENSION_NS "item") || + !strcmp(chname, INKSCAPE_EXTENSION_NS "_item")) ) { + Glib::ustring newtext; + Glib::ustring newvalue; + + // get content (=label) of option and translate it + const char *text = nullptr; + if (child_repr->firstChild()) { + text = child_repr->firstChild()->content(); + } + if (text) { + if (_translatable != NO) { // translate unless explicitly marked untranslatable + if (_context) { + newtext = g_dpgettext2(nullptr, _context, text); + } else { + newtext = _(text); + } + } else { + newtext = text; + } + } else { + g_warning("Missing content in option of parameter '%s' in extension '%s'.", + _name, _extension->get_id()); + } + + // get string value of option + const char *value = child_repr->attribute("value"); + if (value) { + newvalue = value; + } else { + g_warning("Missing value for option '%s' of parameter '%s' in extension '%s'.", + newtext.c_str(), _name, _extension->get_id()); + } + + choices.push_back(new optionentry(newvalue, newtext)); + } else if (child_repr->type() == XML::ELEMENT_NODE) { + g_warning("Invalid child element ('%s') for parameter '%s' in extension '%s'. Expected 'option'.", + chname, _name, _extension->get_id()); + } else if (child_repr->type() != XML::COMMENT_NODE){ + g_warning("Invalid child element found in parameter '%s' in extension '%s'. Expected 'option'.", + _name, _extension->get_id()); + } + child_repr = child_repr->next(); + } + } + if (choices.empty()) { + g_warning("No (valid) choices for parameter '%s' in extension '%s'", _name, _extension->get_id()); + } + + // get value (initialize with value of first choice if pref is empty) + gchar *pref_name = this->pref_name(); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + _value = prefs->getString(extension_pref_root + pref_name); + g_free(pref_name); + + if (_value.empty()) { + if (!choices.empty()) { + _value = choices[0]->value; + } + } + + // parse appearance + // (we support "combo" and "radio"; "minimal" is for backwards-compatibility) + if (_appearance) { + if (!strcmp(_appearance, "combo") || !strcmp(_appearance, "minimal")) { + _mode = COMBOBOX; + } else if (!strcmp(_appearance, "radio")) { + _mode = RADIOBUTTON; + } else { + g_warning("Invalid value ('%s') for appearance of parameter '%s' in extension '%s'", + _appearance, _name, _extension->get_id()); + } + } +} + +ParamOptionGroup::~ParamOptionGroup () +{ + // destroy choice strings + for (auto choice : choices) { + delete choice; + } +} + + +/** + * A function to set the \c _value. + * + * This function sets ONLY the internal value, but it also sets the value + * in the preferences structure. To put it in the right place, \c PREF_DIR + * and \c pref_name() are used. + * + * @param in The value to set. + * @param doc A document that should be used to set the value. + * @param node The node where the value may be placed. + */ +const Glib::ustring& ParamOptionGroup::set(Glib::ustring in, SPDocument *doc, Inkscape::XML::Node *node) +{ + if (contains(in, doc, node)) { + _value = in; + gchar *pref_name = this->pref_name(); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setString(extension_pref_root + pref_name, _value.c_str()); + g_free(pref_name); + } else { + g_warning("Could not set value ('%s') for parameter '%s' in extension '%s'. Not a valid choice.", + in.c_str(), _name, _extension->get_id()); + } + + return _value; +} + +bool ParamOptionGroup::contains(const Glib::ustring text, SPDocument const * /*doc*/, Inkscape::XML::Node const * /*node*/) const +{ + for (auto choice : choices) { + if (choice->value == text) { + return true; + } + } + + return false; +} + +void ParamOptionGroup::string(std::string &string) const +{ + string += _value; +} + +/** + * Returns the value for the options label parameter + */ +Glib::ustring ParamOptionGroup::value_from_label(const Glib::ustring label) +{ + Glib::ustring value; + + for (auto choice : choices) { + if (choice->text == label) { + value = choice->value; + break; + } + } + + return value; +} + + + +/** A special RadioButton class to use in ParamOptionGroup. */ +class RadioWidget : public Gtk::RadioButton { +private: + ParamOptionGroup *_pref; + SPDocument *_doc; + Inkscape::XML::Node *_node; + sigc::signal<void> *_changeSignal; +public: + RadioWidget(Gtk::RadioButtonGroup& group, const Glib::ustring& label, + ParamOptionGroup *pref, SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) + : Gtk::RadioButton(group, label) + , _pref(pref) + , _doc(doc) + , _node(node) + , _changeSignal(changeSignal) + { + add_changesignal(); + }; + + void add_changesignal() { + this->signal_toggled().connect(sigc::mem_fun(this, &RadioWidget::changed)); + }; + + void changed(); +}; + +/** + * Respond to the selected radiobutton changing. + * + * This function responds to the radiobutton selection changing by grabbing the value + * from the text box and putting it in the parameter. + */ +void RadioWidget::changed() +{ + if (this->get_active()) { + Glib::ustring value = _pref->value_from_label(this->get_label()); + _pref->set(value.c_str(), _doc, _node); + } + + if (_changeSignal) { + _changeSignal->emit(); + } +} + + +/** A special ComboBoxText class to use in ParamOptionGroup. */ +class ComboWidget : public Gtk::ComboBoxText { +private: + ParamOptionGroup *_pref; + SPDocument *_doc; + Inkscape::XML::Node *_node; + sigc::signal<void> *_changeSignal; + +public: + ComboWidget(ParamOptionGroup *pref, SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) + : _pref(pref) + , _doc(doc) + , _node(node) + , _changeSignal(changeSignal) + { + this->signal_changed().connect(sigc::mem_fun(this, &ComboWidget::changed)); + } + + ~ComboWidget() override = default; + + void changed(); +}; + +void ComboWidget::changed() +{ + if (_pref) { + Glib::ustring value = _pref->value_from_label(get_active_text()); + _pref->set(value.c_str(), _doc, _node); + } + + if (_changeSignal) { + _changeSignal->emit(); + } +} + + + +/** + * Creates the widget for the optiongroup parameter. + */ +Gtk::Widget *ParamOptionGroup::get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) +{ + if (_hidden) { + return nullptr; + } + + auto hbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, Parameter::GUI_PARAM_WIDGETS_SPACING)); + + Gtk::Label *label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START)); + hbox->pack_start(*label, false, false); + + if (_mode == COMBOBOX) { + ComboWidget *combo = Gtk::manage(new ComboWidget(this, doc, node, changeSignal)); + + for (auto choice : choices) { + combo->append(choice->text); + if (choice->value == _value) { + combo->set_active_text(choice->text); + } + } + + if (combo->get_active_row_number() == -1) { + combo->set_active(0); + } + + hbox->pack_end(*combo, false, false); + } else if (_mode == RADIOBUTTON) { + label->set_valign(Gtk::ALIGN_START); // align label and first radio + + Gtk::Box *radios = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL, 0)); + Gtk::RadioButtonGroup group; + + for (auto choice : choices) { + RadioWidget *radio = Gtk::manage(new RadioWidget(group, choice->text, this, doc, node, changeSignal)); + radios->pack_start(*radio, true, true); + if (choice->value == _value) { + radio->set_active(); + } + } + + hbox->pack_end(*radios, false, false); + } + + hbox->show_all(); + return static_cast<Gtk::Widget *>(hbox); +} + + +} /* namespace Extension */ +} /* namespace Inkscape */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/extension/prefdialog/parameter-optiongroup.h b/src/extension/prefdialog/parameter-optiongroup.h new file mode 100644 index 000000000..21a01d801 --- /dev/null +++ b/src/extension/prefdialog/parameter-optiongroup.h @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#ifndef INK_EXTENSION_PARAMOPTIONGROUP_H_SEEN +#define INK_EXTENSION_PARAMOPTIONGROUP_H_SEEN + +/** \file + * extension parameter for options with multiple predefined value choices + * + * Currently implemented as either Gtk::RadioButton or Gtk::ComboBoxText + */ + +/* + * Authors: + * Johan Engelen <johan@shouraizou.nl> + * Jon A. Cruz <jon@joncruz.org> + * + * Copyright (C) 2006-2007 Johan Engelen + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include <vector> + +#include "parameter.h" + +namespace Gtk { +class Widget; +} + +namespace Glib { +class ustring; +} + +namespace Inkscape { +namespace Extension { + +class Extension; + + + +// \brief A class to represent an optiongroup (option with multiple predefined value choices) parameter of an extension +class ParamOptionGroup : public Parameter { +public: + enum AppearanceMode { + RADIOBUTTON, COMBOBOX + }; + + ParamOptionGroup(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext); + ~ParamOptionGroup() override; + + Gtk::Widget *get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) override; + + // Explicitly call superclass version to avoid method being hidden. + void string(std::list <std::string> &list) const override { return Parameter::string(list); } + + void string(std::string &string) const override; + + Glib::ustring value_from_label(const Glib::ustring label); + + const Glib::ustring& get(const SPDocument * /*doc*/, const Inkscape::XML::Node * /*node*/) const { return _value; } + + const Glib::ustring& set(const Glib::ustring in, SPDocument *doc, Inkscape::XML::Node *node); + + /** + * @returns true if text is a valid choice for this option group + * @param text string value to check (this is an actual option value, not the user-visible option name!) + */ + bool contains(const Glib::ustring text, SPDocument const * /*doc*/, Inkscape::XML::Node const * /*node*/) const; + +private: + /** \brief Internal value. */ + Glib::ustring _value; + + /** appearance mode **/ + AppearanceMode _mode = RADIOBUTTON; + + /* For internal use only. */ + class optionentry { + public: + optionentry (Glib::ustring val, Glib::ustring txt) + : value(val) + , text(txt) + {} + Glib::ustring value; + Glib::ustring text; + }; + + std::vector<optionentry*> choices; /**< A table to store the choice strings */ +}; /* class ParamOptionGroup */ + + + + + +} /* namespace Extension */ +} /* namespace Inkscape */ + +#endif /*INK_EXTENSION_PARAMOPTIONGROUP_H_SEEN */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/extension/prefdialog/parameter-radiobutton.cpp b/src/extension/prefdialog/parameter-radiobutton.cpp deleted file mode 100644 index f2c3187af..000000000 --- a/src/extension/prefdialog/parameter-radiobutton.cpp +++ /dev/null @@ -1,349 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/** \file - * extension parameter for radiobuttons. - * - * It uses a Gtk:ComboBoxText widget in the extension UI. - */ - -/* - * Author: - * Johan Engelen <johan@shouraizou.nl> - * - * Copyright (C) 2006-2007 Johan Engelen - * Copyright (C) 2008 Jon A. Cruz - * - * Released under GNU GPL v2+, read the file 'COPYING' for more information. - */ - -#include "parameter-radiobutton.h" - -#include <gtkmm/box.h> -#include <gtkmm/comboboxtext.h> -#include <gtkmm/radiobutton.h> -#include <glibmm/i18n.h> - -#include "xml/node.h" -#include "extension/extension.h" -#include "preferences.h" - -/** - * The root directory in the preferences database for extension - * related parameters. - */ -#define PREF_DIR "extensions" - -namespace Inkscape { -namespace Extension { - -/* For internal use only. - Note that value and text MUST be non-NULL. This is ensured by newing only at one location in the code where non-NULL checks are made. */ - -ParamRadioButton::ParamRadioButton(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml, - AppearanceMode mode) - : Parameter(name, text, description, hidden, indent, ext) - , _value(nullptr) - , _mode(mode) -{ - // Read XML tree to add enumeration items: - // printf("Extension Constructor: "); - if (xml != nullptr) { - Inkscape::XML::Node *child_repr = xml->firstChild(); - while (child_repr != nullptr) { - char const * chname = child_repr->name(); - if (!strcmp(chname, INKSCAPE_EXTENSION_NS "option") || !strcmp(chname, INKSCAPE_EXTENSION_NS "_option")) { - Glib::ustring * newtext = nullptr; - Glib::ustring * newvalue = nullptr; - const char * contents = child_repr->firstChild()->content(); - - if (contents != nullptr) { - // don't translate when 'item' but do translate when '_option' - if (!strcmp(chname, INKSCAPE_EXTENSION_NS "_option")) { - if (child_repr->attribute("msgctxt") != nullptr) { - newtext = new Glib::ustring(g_dpgettext2(nullptr, child_repr->attribute("msgctxt"), contents)); - } else { - newtext = new Glib::ustring(_(contents)); - } - } else { - newtext = new Glib::ustring(contents); - } - } else { - continue; - } - - - const char * val = child_repr->attribute("value"); - if (val != nullptr) { - newvalue = new Glib::ustring(val); - } else { - newvalue = new Glib::ustring(contents); - } - - if ( (newtext) && (newvalue) ) { // logical error if this is not true here - choices.push_back(new optionentry(newvalue, newtext)); - } - } - child_repr = child_repr->next(); - } - } - - // Initialize _value with the default value from xml - // for simplicity : default to the contents of the first xml-child - const char * defaultval = nullptr; - if (!choices.empty()) { - defaultval = (static_cast<optionentry*> (choices[0]))->value->c_str(); - } - - gchar * pref_name = this->pref_name(); - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Glib::ustring paramval = prefs->getString(extension_pref_root + pref_name); - g_free(pref_name); - - if (!paramval.empty()) { - defaultval = paramval.data(); - } - if (defaultval != nullptr) { - _value = g_strdup(defaultval); // allocate space for _value - } -} - -ParamRadioButton::~ParamRadioButton () -{ - //destroy choice strings - for(auto i:choices) { - delete i; - } - g_free(_value); -} - - -/** - * A function to set the \c _value. - * - * This function sets ONLY the internal value, but it also sets the value - * in the preferences structure. To put it in the right place, \c PREF_DIR - * and \c pref_name() are used. - * - * To copy the data into _value the old memory must be free'd first. - * It is important to note that \c g_free handles \c NULL just fine. Then - * the passed in value is duplicated using \c g_strdup(). - * - * @param in The value to set. - * @param doc A document that should be used to set the value. - * @param node The node where the value may be placed. - */ -const gchar *ParamRadioButton::set(const gchar * in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) -{ - if (in == nullptr) { - return nullptr; /* Can't have NULL string */ - } - - Glib::ustring * settext = nullptr; - for (auto entr:choices) { - if ( !entr->value->compare(in) ) { - settext = entr->value; - break; // break out of for loop - } - } - if (settext) { - if (_value != nullptr) { - g_free(_value); - } - _value = g_strdup(settext->c_str()); - gchar * prefname = this->pref_name(); - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setString(extension_pref_root + prefname, _value); - g_free(prefname); - } else { - g_warning("Couldn't set ParamRadioButton %s", in); - } - - return _value; -} - -void ParamRadioButton::string(std::string &string) const -{ - string += _value; -} - -/** A special radiobutton class to use in ParamRadioButton. */ -class ParamRadioButtonWdg : public Gtk::RadioButton { -private: - ParamRadioButton * _pref; - SPDocument * _doc; - Inkscape::XML::Node * _node; - sigc::signal<void> * _changeSignal; -public: - /** - * Build a string preference for the given parameter. - * @param pref Where to put the radiobutton's string when it is selected. - */ - ParamRadioButtonWdg ( Gtk::RadioButtonGroup& group, const Glib::ustring& label, - ParamRadioButton * pref, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal ) : - Gtk::RadioButton(group, label), _pref(pref), _doc(doc), _node(node), _changeSignal(changeSignal) { - add_changesignal(); - }; - ParamRadioButtonWdg ( const Glib::ustring& label, - ParamRadioButton * pref, SPDocument * doc, Inkscape::XML::Node * node , sigc::signal<void> * changeSignal) : - Gtk::RadioButton(label), _pref(pref), _doc(doc), _node(node), _changeSignal(changeSignal) { - add_changesignal(); - }; - void add_changesignal() { - this->signal_toggled().connect(sigc::mem_fun(this, &ParamRadioButtonWdg::changed)); - }; - void changed (); -}; - -/** - * Respond to the selected radiobutton changing. - * - * This function responds to the radiobutton selection changing by grabbing the value - * from the text box and putting it in the parameter. - */ -void ParamRadioButtonWdg::changed() -{ - if (this->get_active()) { - Glib::ustring value = _pref->value_from_label(this->get_label()); - _pref->set(value.c_str(), _doc, _node); - } - if (_changeSignal != nullptr) { - _changeSignal->emit(); - } -} - - -class ComboWdg : public Gtk::ComboBoxText { -private: - ParamRadioButton* _base; - SPDocument* _doc; - Inkscape::XML::Node* _node; - sigc::signal<void> * _changeSignal; - -public: - ComboWdg(ParamRadioButton* base, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) : - _base(base), - _doc(doc), - _node(node), - _changeSignal(changeSignal) - { - this->signal_changed().connect(sigc::mem_fun(this, &ComboWdg::changed)); - } - ~ComboWdg() override = default; - void changed (); -}; - -void ComboWdg::changed() -{ - if ( _base ) { - Glib::ustring value = _base->value_from_label(get_active_text()); - _base->set(value.c_str(), _doc, _node); - } - if (_changeSignal != nullptr) { - _changeSignal->emit(); - } -} - -/** - * Returns the value for the options label parameter - */ -Glib::ustring ParamRadioButton::value_from_label(const Glib::ustring label) -{ - Glib::ustring value = ""; - - for ( auto entr:choices) { - if ( !entr->text->compare(label) ) { - value = *(entr->value); - break; - } - } - - return value; - -} - -/** - * Creates a combobox widget for an enumeration parameter. - */ -Gtk::Widget * ParamRadioButton::get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) -{ - if (_hidden) { - return nullptr; - } - - auto hbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, Parameter::GUI_PARAM_WIDGETS_SPACING)); - hbox->set_homogeneous(false); - auto vbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL, 0)); - vbox->set_homogeneous(false); - - Gtk::Label * label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START, Gtk::ALIGN_START)); - label->show(); - hbox->pack_start(*label, false, false); - - Gtk::ComboBoxText* cbt = nullptr; - bool comboSet = false; - if (_mode == MINIMAL) { - cbt = Gtk::manage(new ComboWdg(this, doc, node, changeSignal)); - cbt->show(); - vbox->pack_start(*cbt, false, false); - } - - // add choice strings as radiobuttons - // and select last selected option (_value) - Gtk::RadioButtonGroup group; - for (auto entr:choices) { - Glib::ustring * text = entr->text; - switch ( _mode ) { - case MINIMAL: - { - cbt->append(*text); - if (!entr->value->compare(_value)) { - cbt->set_active_text(*text); - comboSet = true; - } - } - break; - case COMPACT: - case FULL: - { - ParamRadioButtonWdg * radio = Gtk::manage(new ParamRadioButtonWdg(group, *text, this, doc, node, changeSignal)); - radio->show(); - vbox->pack_start(*radio, true, true); - if (!entr->value->compare(_value)) { - radio->set_active(); - } - } - break; - } - } - - if ( (_mode == MINIMAL) && !comboSet) { - cbt->set_active(0); - } - - vbox->show(); - hbox->pack_end(*vbox, false, false); - hbox->show(); - - - return dynamic_cast<Gtk::Widget *>(hbox); -} - - -} /* namespace Extension */ -} /* namespace Inkscape */ - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/extension/prefdialog/parameter-radiobutton.h b/src/extension/prefdialog/parameter-radiobutton.h deleted file mode 100644 index f35126d13..000000000 --- a/src/extension/prefdialog/parameter-radiobutton.h +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -#ifndef INK_EXTENSION_PARAMRADIOBUTTON_H_SEEN -#define INK_EXTENSION_PARAMRADIOBUTTON_H_SEEN - -/** \file - * Radiobutton parameter for extensions. - */ - -/* - * Authors: - * Johan Engelen <johan@shouraizou.nl> - * Jon A. Cruz <jon@joncruz.org> - * - * Copyright (C) 2006-2007 Johan Engelen - * - * Released under GNU GPL v2+, read the file 'COPYING' for more information. - */ - -#include <vector> - -#include "parameter.h" - -namespace Gtk { -class Widget; -} - -namespace Inkscape { -namespace Extension { - -class Extension; - - - -// \brief A class to represent a radiobutton parameter of an extension -class ParamRadioButton : public Parameter { -public: - enum AppearanceMode { - FULL, COMPACT, MINIMAL - }; - - ParamRadioButton(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml, - AppearanceMode mode); - ~ParamRadioButton() override; - - Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) override; - - // Explicitly call superclass version to avoid method being hidden. - void string(std::list <std::string> &list) const override { return Parameter::string(list); } - - void string(std::string &string) const override; - - Glib::ustring value_from_label(const Glib::ustring label); - - const gchar *get(const SPDocument * /*doc*/, const Inkscape::XML::Node * /*node*/) const { return _value; } - - const gchar *set(const gchar *in, SPDocument *doc, Inkscape::XML::Node *node); - -private: - /** \brief Internal value. This should point to a string that has - been allocated in memory. And should be free'd. - It is the value of the current selected string */ - gchar * _value; - AppearanceMode _mode; - - /* For internal use only. - Note that value and text MUST be non-NULL. This is ensured by newing only at one location in the code where non-NULL checks are made. */ - class optionentry { - public: - optionentry (Glib::ustring * val, Glib::ustring * txt) { - value = val; - text = txt; - } - ~optionentry() { - delete value; - delete text; - } - Glib::ustring * value; - Glib::ustring * text; - }; - - std::vector<optionentry*> choices; /**< A table to store the choice strings */ - -}; /* class ParamRadioButton */ - - - - - -} /* namespace Extension */ -} /* namespace Inkscape */ - -#endif /* INK_EXTENSION_PARAMRADIOBUTTON_H_SEEN */ - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/extension/prefdialog/parameter-string.cpp b/src/extension/prefdialog/parameter-string.cpp index 829b603d8..d93102a20 100644 --- a/src/extension/prefdialog/parameter-string.cpp +++ b/src/extension/prefdialog/parameter-string.cpp @@ -23,12 +23,43 @@ namespace Inkscape { namespace Extension { - -/** Free the allocated data. */ -ParamString::~ParamString() +ParamString::ParamString(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext) + : Parameter(xml, ext) { - g_free(_value); - _value = nullptr; + // get value + const char *value = nullptr; + if (xml->firstChild()) { + value = xml->firstChild()->content(); + } + + gchar *pref_name = this->pref_name(); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + _value = prefs->getString(extension_pref_root + pref_name); + g_free(pref_name); + + if (_value.empty() && value) { + _value = value; + } + + // translate value + if (!_value.empty()) { + if (_translatable == YES) { // translate only if explicitly marked translatable + if (_context) { + _value = g_dpgettext2(nullptr, _context, _value.c_str()); + } else { + _value = _(_value.c_str()); + } + } + } + + // max-length + const char *max_length = xml->attribute("max-length"); + if (!max_length) { + max_length = xml->attribute("max_length"); // backwards-compatibility with old name (underscore) + } + if (max_length) { + _max_length = strtoul(max_length, nullptr, 0); + } } /** @@ -46,95 +77,49 @@ ParamString::~ParamString() * @param doc A document that should be used to set the value. * @param node The node where the value may be placed. */ -const gchar * ParamString::set(const gchar * in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) +const Glib::ustring& ParamString::set(const Glib::ustring in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) { - if (in == nullptr) { - return nullptr; /* Can't have NULL string */ - } - - if (_value != nullptr) { - g_free(_value); - } + _value = in; - _value = g_strdup(in); - - gchar * prefname = this->pref_name(); + gchar *pref_name = this->pref_name(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setString(extension_pref_root + prefname, _value); - g_free(prefname); + prefs->setString(extension_pref_root + pref_name, _value); + g_free(pref_name); return _value; } void ParamString::string(std::string &string) const { - if (_value) { - string += _value; - } + string += _value; } -/** Initialize the object, to do that, copy the data. */ -ParamString::ParamString(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml) - : Parameter(name, text, description, hidden, indent, ext) - , _value(nullptr) -{ - const char * defaultval = nullptr; - if (xml->firstChild() != nullptr) { - defaultval = xml->firstChild()->content(); - } - - gchar * pref_name = this->pref_name(); - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Glib::ustring paramval = prefs->getString(extension_pref_root + pref_name); - g_free(pref_name); - - if (!paramval.empty()) { - defaultval = paramval.data(); - } - if (defaultval != nullptr) { - char const * chname = xml->name(); - if (!strcmp(chname, INKSCAPE_EXTENSION_NS "_param")) { - if (xml->attribute("msgctxt") != nullptr) { - _value = g_strdup(g_dpgettext2(nullptr, xml->attribute("msgctxt"), defaultval)); - } else { - _value = g_strdup(_(defaultval)); - } - } else { - _value = g_strdup(defaultval); - } - } - - _max_length = 0; -} /** A special type of Gtk::Entry to handle string parameteres. */ class ParamStringEntry : public Gtk::Entry { private: - ParamString * _pref; - SPDocument * _doc; - Inkscape::XML::Node * _node; - sigc::signal<void> * _changeSignal; + ParamString *_pref; + SPDocument *_doc; + Inkscape::XML::Node *_node; + sigc::signal<void> *_changeSignal; public: /** * Build a string preference for the given parameter. * @param pref Where to get the string from, and where to put it * when it changes. */ - ParamStringEntry (ParamString * pref, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) : - Gtk::Entry(), _pref(pref), _doc(doc), _node(node), _changeSignal(changeSignal) { - if (_pref->get(nullptr, nullptr) != nullptr) { - this->set_text(Glib::ustring(_pref->get(nullptr, nullptr))); - } + ParamStringEntry(ParamString *pref, SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) + : Gtk::Entry() + , _pref(pref) + , _doc(doc) + , _node(node) + , _changeSignal(changeSignal) + { + this->set_text(_pref->get(nullptr, nullptr)); this->set_max_length(_pref->getMaxLength()); //Set the max length - default zero means no maximum this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text)); }; - void changed_text (); + void changed_text(); }; @@ -158,14 +143,14 @@ void ParamStringEntry::changed_text() * * Builds a hbox with a label and a text box in it. */ -Gtk::Widget * ParamString::get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) +Gtk::Widget *ParamString::get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) { if (_hidden) { return nullptr; } - Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, Parameter::GUI_PARAM_WIDGETS_SPACING)); - Gtk::Label * label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START)); + Gtk::HBox *hbox = Gtk::manage(new Gtk::HBox(false, Parameter::GUI_PARAM_WIDGETS_SPACING)); + Gtk::Label *label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START)); label->show(); hbox->pack_start(*label, false, false); diff --git a/src/extension/prefdialog/parameter-string.h b/src/extension/prefdialog/parameter-string.h index 7c094d394..476807936 100644 --- a/src/extension/prefdialog/parameter-string.h +++ b/src/extension/prefdialog/parameter-string.h @@ -12,33 +12,22 @@ #include "parameter.h" +namespace Glib { +class ustring; +} + namespace Inkscape { namespace Extension { class ParamString : public Parameter { -private: - /** \brief Internal value. This should point to a string that has - been allocated in memory. And should be free'd. */ - gchar * _value; - /** \brief Internal value. This indicates the maximum length of the string. Zero meaning unlimited. - */ - gint _max_length; public: - ParamString(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - int indent, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml); - ~ParamString() override; + ParamString(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext); /** \brief Returns \c _value, with a \i const to protect it. */ - const gchar *get(SPDocument const * /*doc*/, Inkscape::XML::Node const * /*node*/) const { return _value; } - - const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node); + const Glib::ustring& get(SPDocument const * /*doc*/, Inkscape::XML::Node const * /*node*/) const { return _value; } + const Glib::ustring& set(const Glib::ustring in, SPDocument *doc, Inkscape::XML::Node *node); - Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) override; + Gtk::Widget *get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal) override; // Explicitly call superclass version to avoid method being hidden. void string(std::list <std::string> &list) const override { return Parameter::string(list); } @@ -47,6 +36,14 @@ public: void setMaxLength(int maxLength) { _max_length = maxLength; } int getMaxLength() { return _max_length; } + +private: + /** \brief Internal value. */ + Glib::ustring _value; + + /** \brief Maximum length of the string in characters (zero meaning unlimited). + */ + int _max_length = 0; }; diff --git a/src/extension/prefdialog/parameter.cpp b/src/extension/prefdialog/parameter.cpp index 7a3748100..d3293a0db 100644 --- a/src/extension/prefdialog/parameter.cpp +++ b/src/extension/prefdialog/parameter.cpp @@ -22,11 +22,10 @@ #include "parameter-bool.h" #include "parameter-color.h" #include "parameter-description.h" -#include "parameter-enum.h" #include "parameter-float.h" #include "parameter-int.h" #include "parameter-notebook.h" -#include "parameter-radiobutton.h" +#include "parameter-optiongroup.h" #include "parameter-string.h" #include "extension/extension.h" @@ -43,118 +42,36 @@ namespace Extension { Parameter *Parameter::make(Inkscape::XML::Node *in_repr, Inkscape::Extension::Extension *in_ext) { - const char *name = in_repr->attribute("name"); - const char *type = in_repr->attribute("type"); + Parameter *param = nullptr; - // we can't create a parameter without type + const char *type = in_repr->attribute("type"); if (!type) { - return nullptr; - } - // also require name unless it's a pure UI element that does not store its value - if (!name) { - static std::vector<std::string> ui_elements = {"description"}; - if (std::find(ui_elements.begin(), ui_elements.end(), type) == ui_elements.end()) { - return nullptr; - } - } - - const char *text = in_repr->attribute("gui-text"); - if (text == nullptr) { - text = in_repr->attribute("_gui-text"); - if (text == nullptr) { - // text = ""; // probably better to require devs to explicitly set an empty gui-text if this is what they want - } else { - const char *context = in_repr->attribute("msgctxt"); - if (context != nullptr) { - text = g_dpgettext2(nullptr, context, text); - } else { - text = _(text); - } - } - } - const char *description = in_repr->attribute("gui-description"); - if (description == nullptr) { - description = in_repr->attribute("_gui-description"); - if (description != nullptr) { - const char *context = in_repr->attribute("msgctxt"); - if (context != nullptr) { - description = g_dpgettext2(nullptr, context, description); - } else { - description = _(description); - } - } - } - bool hidden = false; - { - const char *gui_hide = in_repr->attribute("gui-hidden"); - if (gui_hide != nullptr) { - if (strcmp(gui_hide, "1") == 0 || - strcmp(gui_hide, "true") == 0) { - hidden = true; - } - /* else stays false */ - } - } - int indent = 0; - { - const char *indent_attr = in_repr->attribute("indent"); - if (indent_attr != nullptr) { - if (strcmp(indent_attr, "true") == 0) { - indent = 1; - } else { - indent = atoi(indent_attr); - } - } - } - const gchar* appearance = in_repr->attribute("appearance"); - - Parameter * param = nullptr; - if (!strcmp(type, "boolean")) { - param = new ParamBool(name, text, description, hidden, indent, in_ext, in_repr); + // we can't create a parameter without type + g_warning("Parameter without type in extension '%s'.", in_ext->get_id()); + } else if(!strcmp(type, "boolean")) { + param = new ParamBool(in_repr, in_ext); } else if (!strcmp(type, "int")) { - if (appearance && !strcmp(appearance, "full")) { - param = new ParamInt(name, text, description, hidden, indent, in_ext, in_repr, ParamInt::FULL); - } else { - param = new ParamInt(name, text, description, hidden, indent, in_ext, in_repr, ParamInt::MINIMAL); - } + param = new ParamInt(in_repr, in_ext); } else if (!strcmp(type, "float")) { - if (appearance && !strcmp(appearance, "full")) { - param = new ParamFloat(name, text, description, hidden, indent, in_ext, in_repr, ParamFloat::FULL); - } else { - param = new ParamFloat(name, text, description, hidden, indent, in_ext, in_repr, ParamFloat::MINIMAL); - } + param = new ParamFloat(in_repr, in_ext); } else if (!strcmp(type, "string")) { - param = new ParamString(name, text, description, hidden, indent, in_ext, in_repr); - gchar const * max_length = in_repr->attribute("max_length"); - if (max_length != nullptr) { - ParamString * ps = dynamic_cast<ParamString *>(param); - ps->setMaxLength(atoi(max_length)); - } + param = new ParamString(in_repr, in_ext); } else if (!strcmp(type, "description")) { - ParamDescription::AppearanceMode appearance_mode = ParamDescription::DESCRIPTION; - if (appearance) { - if (!strcmp(appearance, "header")) { - appearance_mode = ParamDescription::HEADER; - } else if (!strcmp(appearance, "url")) { - appearance_mode = ParamDescription::URL; - } - } - param = new ParamDescription(name, text, description, hidden, indent, in_ext, in_repr, appearance_mode); - } else if (!strcmp(type, "enum")) { - param = new ParamComboBox(name, text, description, hidden, indent, in_ext, in_repr); + param = new ParamDescription(in_repr, in_ext); } else if (!strcmp(type, "notebook")) { - param = new ParamNotebook(name, text, description, hidden, indent, in_ext, in_repr); + param = new ParamNotebook(in_repr, in_ext); } else if (!strcmp(type, "optiongroup")) { - if (appearance && !strcmp(appearance, "minimal")) { - param = new ParamRadioButton(name, text, description, hidden, indent, in_ext, in_repr, ParamRadioButton::MINIMAL); - } else { - param = new ParamRadioButton(name, text, description, hidden, indent, in_ext, in_repr, ParamRadioButton::FULL); - } + param = new ParamOptionGroup(in_repr, in_ext); + } else if (!strcmp(type, "enum")) { // support deprecated "enum" for backwards-compatibilty + in_repr->setAttribute("appearance", "combo"); + param = new ParamOptionGroup(in_repr, in_ext); } else if (!strcmp(type, "color")) { - param = new ParamColor(name, text, description, hidden, indent, in_ext, in_repr); + param = new ParamColor(in_repr, in_ext); + } else { + g_warning("Unknown parameter type ('%s') in extension '%s'", type, in_ext->get_id()); } - // Note: param could equal NULL + // Note: param could equal nullptr return param; } @@ -185,40 +102,31 @@ float Parameter::get_float(SPDocument const *doc, Inkscape::XML::Node const *nod return floatpntr->get(doc, node); } -gchar const *Parameter::get_string(SPDocument const *doc, Inkscape::XML::Node const *node) const +const char *Parameter::get_string(SPDocument const *doc, Inkscape::XML::Node const *node) const { ParamString const *stringpntr = dynamic_cast<ParamString const *>(this); if (!stringpntr) { throw param_not_string_param(); } - return stringpntr->get(doc, node); + return stringpntr->get(doc, node).c_str(); } -gchar const *Parameter::get_enum(SPDocument const *doc, Inkscape::XML::Node const *node) const +const char *Parameter::get_optiongroup(SPDocument const *doc, Inkscape::XML::Node const *node) const { - ParamComboBox const *param = dynamic_cast<ParamComboBox const *>(this); + ParamOptionGroup const *param = dynamic_cast<ParamOptionGroup const *>(this); if (!param) { - throw param_not_enum_param(); - } - return param->get(doc, node); -} - -bool Parameter::get_enum_contains(gchar const * value, SPDocument const *doc, Inkscape::XML::Node const *node) const -{ - ParamComboBox const *param = dynamic_cast<ParamComboBox const *>(this); - if (!param) { - throw param_not_enum_param(); + throw param_not_optiongroup_param(); } - return param->contains(value, doc, node); + return param->get(doc, node).c_str(); } -gchar const *Parameter::get_optiongroup(SPDocument const *doc, Inkscape::XML::Node const * node) const +bool Parameter::get_optiongroup_contains(const char *value, SPDocument const *doc, Inkscape::XML::Node const *node) const { - ParamRadioButton const *param = dynamic_cast<ParamRadioButton const *>(this); + ParamOptionGroup const *param = dynamic_cast<ParamOptionGroup const *>(this); if (!param) { throw param_not_optiongroup_param(); } - return param->get(doc, node); + return param->contains(value, doc, node); } guint32 Parameter::get_color(const SPDocument* doc, Inkscape::XML::Node const *node) const @@ -230,7 +138,7 @@ guint32 Parameter::get_color(const SPDocument* doc, Inkscape::XML::Node const *n return param->get(doc, node); } -bool Parameter::set_bool(bool in, SPDocument * doc, Inkscape::XML::Node * node) +bool Parameter::set_bool(bool in, SPDocument *doc, Inkscape::XML::Node *node) { ParamBool * boolpntr = dynamic_cast<ParamBool *>(this); if (boolpntr == nullptr) @@ -238,17 +146,15 @@ bool Parameter::set_bool(bool in, SPDocument * doc, Inkscape::XML::Node * node) return boolpntr->set(in, doc, node); } -int Parameter::set_int(int in, SPDocument * doc, Inkscape::XML::Node * node) +int Parameter::set_int(int in, SPDocument *doc, Inkscape::XML::Node *node) { - ParamInt * intpntr = dynamic_cast<ParamInt *>(this); + ParamInt *intpntr = dynamic_cast<ParamInt *>(this); if (intpntr == nullptr) throw param_not_int_param(); return intpntr->set(in, doc, node); } -/** Wrapper to cast to the object and use it's function. */ -float -Parameter::set_float (float in, SPDocument * doc, Inkscape::XML::Node * node) +float Parameter::set_float(float in, SPDocument *doc, Inkscape::XML::Node *node) { ParamFloat * floatpntr; floatpntr = dynamic_cast<ParamFloat *>(this); @@ -257,48 +163,33 @@ Parameter::set_float (float in, SPDocument * doc, Inkscape::XML::Node * node) return floatpntr->set(in, doc, node); } -/** Wrapper to cast to the object and use it's function. */ -gchar const * -Parameter::set_string (gchar const * in, SPDocument * doc, Inkscape::XML::Node * node) +const char *Parameter::set_string(const char *in, SPDocument *doc, Inkscape::XML::Node *node) { ParamString * stringpntr = dynamic_cast<ParamString *>(this); if (stringpntr == nullptr) throw param_not_string_param(); - return stringpntr->set(in, doc, node); + return stringpntr->set(in, doc, node).c_str(); } -gchar const * Parameter::set_optiongroup( gchar const * in, SPDocument * doc, Inkscape::XML::Node * node ) +const char *Parameter::set_optiongroup(const char *in, SPDocument *doc, Inkscape::XML::Node *node) { - ParamRadioButton *param = dynamic_cast<ParamRadioButton *>(this); + ParamOptionGroup *param = dynamic_cast<ParamOptionGroup *>(this); if (!param) { throw param_not_optiongroup_param(); } - return param->set(in, doc, node); + return param->set(in, doc, node).c_str(); } -gchar const *Parameter::set_enum( gchar const * in, SPDocument * doc, Inkscape::XML::Node * node ) +guint32 Parameter::set_color(guint32 in, SPDocument *doc, Inkscape::XML::Node *node) { - ParamComboBox *param = dynamic_cast<ParamComboBox *>(this); - if (!param) { - throw param_not_enum_param(); - } - return param->set(in, doc, node); -} - - -/** Wrapper to cast to the object and use it's function. */ -guint32 -Parameter::set_color (guint32 in, SPDocument * doc, Inkscape::XML::Node * node) -{ - ParamColor* param = dynamic_cast<ParamColor *>(this); + ParamColor*param = dynamic_cast<ParamColor *>(this); if (param == nullptr) throw param_not_color_param(); return param->set(in, doc, node); } -/** Oop, now that we need a parameter, we need it's name. */ -Parameter::Parameter(gchar const * name, gchar const * text, gchar const * description, bool hidden, int indent, Inkscape::Extension::Extension * ext) : +Parameter::Parameter(gchar const *name, gchar const *text, gchar const *description, bool hidden, int indent, Inkscape::Extension::Extension *ext) : _description(nullptr), _text(nullptr), _hidden(hidden), @@ -323,8 +214,7 @@ Parameter::Parameter(gchar const * name, gchar const * text, gchar const * descr return; } -/** Oop, now that we need a parameter, we need it's name. */ -Parameter::Parameter (gchar const * name, gchar const * text, Inkscape::Extension::Extension * ext) : +Parameter::Parameter (gchar const *name, gchar const *text, Inkscape::Extension::Extension *ext) : _description(nullptr), _text(nullptr), _hidden(false), @@ -344,6 +234,92 @@ Parameter::Parameter (gchar const * name, gchar const * text, Inkscape::Extensio return; } +Parameter::Parameter (Inkscape::XML::Node *in_repr, Inkscape::Extension::Extension *ext) + : _extension(ext) +{ + // name (mandatory for all paramters) + const char *name = in_repr->attribute("name"); + if (!name) { + throw param_no_name(); + } + _name = g_strdup(name); + + + // translatable (optional, required to translate gui-text and gui-description) + const char *translatable = in_repr->attribute("translatable"); + if (translatable) { + if (!strcmp(translatable, "yes")) { + _translatable = YES; + } else if (!strcmp(translatable, "no")) { + _translatable = NO; + } else { + g_warning("Invalid value ('%s') for translatable attribute of parameter '%s' in extension '%s'", + translatable, _name, _extension->get_id()); + } + } + + // context (optional, required to translate gui-text and gui-description) + const char *context = in_repr->attribute("context"); + if (!context) { + context = in_repr->attribute("msgctxt"); // backwards-compatibility with previous name + } + if (context) { + _context = g_strdup(context); + } + + // gui-text (TODO: should likely be mandatory for all parameters; maybe not for hidden ones?) + const char *gui_text = in_repr->attribute("gui-text"); + if (!gui_text) { + gui_text = in_repr->attribute("_gui-text"); // backwards-compatibility with underscored variants + } + if (gui_text) { + if (_translatable != NO) { // translate unless explicitly marked untranslatable + if (_context) { + gui_text = g_dpgettext2(nullptr, context, gui_text); + } else { + gui_text = _(gui_text); + } + } + _text = g_strdup(gui_text); + } + + // gui-description (optional) + const char *gui_description = in_repr->attribute("gui-description"); + if (!gui_description) { + gui_description = in_repr->attribute("_gui-description"); // backwards-compatibility with underscored variants + } + if (gui_description) { + if (_translatable != NO) { // translate unless explicitly marked untranslatable + if (_context) { + gui_description = g_dpgettext2(nullptr, context, gui_description); + } else { + gui_description = _(gui_description); + } + } + _description = g_strdup(gui_description); + } + + // gui-hidden (optional) + const char *gui_hidden = in_repr->attribute("gui-hidden"); + if (gui_hidden != nullptr) { + if (strcmp(gui_hidden, "true") == 0) { + _hidden = true; + } + } + + // indent (optional) + const char *indent = in_repr->attribute("indent"); + if (indent != nullptr) { + _indent = strtol(indent, nullptr, 0); + } + + // appearance (optional, does not apply to all parameters) + const char *appearance = in_repr->attribute("appearance"); + if (appearance) { + _appearance = g_strdup(appearance); + } +} + Parameter::~Parameter() { g_free(_name); @@ -354,6 +330,12 @@ Parameter::~Parameter() g_free(_description); _description = nullptr; + + g_free(_appearance); + _description = nullptr; + + g_free(_context); + _context = nullptr; } gchar *Parameter::pref_name() const @@ -389,7 +371,7 @@ void Parameter::string(std::list <std::string> &list) const } } -Parameter *Parameter::get_param(gchar const * /*name*/) +Parameter *Parameter::get_param(const gchar */*name*/) { return nullptr; } diff --git a/src/extension/prefdialog/parameter.h b/src/extension/prefdialog/parameter.h index 25762f725..f1c298fb9 100644 --- a/src/extension/prefdialog/parameter.h +++ b/src/extension/prefdialog/parameter.h @@ -52,18 +52,25 @@ extern Glib::ustring const extension_pref_root; * different parameters. */ class Parameter { - public: + + enum Translatable { + UNSET, YES, NO + }; + Parameter(gchar const *name, gchar const *text, gchar const *description, bool hidden, int indent, - Inkscape::Extension::Extension * ext); + Inkscape::Extension::Extension *ext); Parameter(gchar const *name, gchar const *text, - Inkscape::Extension::Extension * ext); + Inkscape::Extension::Extension *ext); + + Parameter(Inkscape::XML::Node *in_repr, + Inkscape::Extension::Extension *ext); virtual ~Parameter(); @@ -77,36 +84,34 @@ public: float get_float(SPDocument const *doc, Inkscape::XML::Node const *node) const; /** Wrapper to cast to the object and use it's function. */ - gchar const *get_string(SPDocument const *doc, Inkscape::XML::Node const *node) const; - - guint32 get_color(SPDocument const *doc, Inkscape::XML::Node const *node) const; + const char *get_string(SPDocument const *doc, Inkscape::XML::Node const *node) const; /** Wrapper to cast to the object and use it's function. */ - gchar const *get_enum(SPDocument const *doc, Inkscape::XML::Node const *node) const; + const char *get_optiongroup(SPDocument const * doc, Inkscape::XML::Node const *node) const; + bool get_optiongroup_contains(const char *value, SPDocument const *doc, Inkscape::XML::Node const *node) const; /** Wrapper to cast to the object and use it's function. */ - bool get_enum_contains(gchar const * value, SPDocument const *doc, Inkscape::XML::Node const *node) const; + guint32 get_color(SPDocument const *doc, Inkscape::XML::Node const *node) const; /** Wrapper to cast to the object and use it's function. */ - gchar const *get_optiongroup(SPDocument const * doc, Inkscape::XML::Node const *node) const; + bool set_bool(bool in, SPDocument *doc, Inkscape::XML::Node *node); /** Wrapper to cast to the object and use it's function. */ - bool set_bool(bool in, SPDocument * doc, Inkscape::XML::Node * node); + int set_int(int in, SPDocument *doc, Inkscape::XML::Node *node); /** Wrapper to cast to the object and use it's function. */ - int set_int(int in, SPDocument * doc, Inkscape::XML::Node * node); - - float set_float(float in, SPDocument * doc, Inkscape::XML::Node * node); + float set_float(float in, SPDocument *doc, Inkscape::XML::Node *node); - gchar const *set_optiongroup(gchar const *in, SPDocument * doc, Inkscape::XML::Node *node); - - gchar const *set_enum(gchar const * in, SPDocument * doc, Inkscape::XML::Node *node); + /** Wrapper to cast to the object and use it's function. */ + const char *set_string(const char *in, SPDocument *doc, Inkscape::XML::Node *node); - gchar const *set_string(gchar const * in, SPDocument * doc, Inkscape::XML::Node * node); + /** Wrapper to cast to the object and use it's function. */ + const char *set_optiongroup(const char *in, SPDocument *doc, Inkscape::XML::Node *node); - guint32 set_color(guint32 in, SPDocument * doc, Inkscape::XML::Node * node); + /** Wrapper to cast to the object and use it's function. */ + guint32 set_color(guint32 in, SPDocument *doc, Inkscape::XML::Node *node); - gchar const * name() const {return _name;} + gchar const *name() const { return _name; } /** * This function creates a parameter that can be used later. This @@ -132,11 +137,11 @@ public: * @param in_repr The XML describing the parameter. * @return a pointer to a new Parameter if applicable, null otherwise.. */ - static Parameter *make(Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext); + static Parameter *make(Inkscape::XML::Node *in_repr, Inkscape::Extension::Extension *in_ext); - virtual Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal); + virtual Gtk::Widget *get_widget(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void> *changeSignal); - gchar const * get_tooltip() const { return _description; } + const gchar *get_tooltip() const { return _description; } /** Indicates if the GUI for this parameter is hidden or not */ bool get_hidden() const { return _hidden; } @@ -171,27 +176,41 @@ public: /** An error class for when a parameter is called on a type it is not */ class param_no_name {}; class param_no_type {}; + class param_not_bool_param {}; class param_not_color_param {}; - class param_not_enum_param {}; - class param_not_optiongroup_param {}; - class param_not_string_param {}; class param_not_float_param {}; class param_not_int_param {}; - class param_not_bool_param {}; + class param_not_optiongroup_param {}; + class param_not_string_param {}; protected: + /** Which extension is this parameter attached to. */ + Inkscape::Extension::Extension *_extension = nullptr; + + /** The name of this parameter. */ + gchar *_name = nullptr; + /** Parameter text to show as the GUI label. */ - gchar * _text; + gchar *_text = nullptr; - /** Extended description of the parameter (crrently shown as tooltip on hover). */ - gchar * _description; + /** Extended description of the parameter (currently shown as tooltip on hover). */ + gchar *_description = nullptr; /** Whether the parameter is visible. */ - bool _hidden; + bool _hidden = false; /** Indentation level of the parameter. */ - int _indent; + int _indent = 0; + + /** Appearance of the parameter (not used by all Parameters). */ + gchar *_appearance = nullptr; + + /** Is parameter translatable? */ + Translatable _translatable = UNSET; + + /** context for translation of translatable strings. */ + gchar *_context = nullptr; /* **** funcs **** */ @@ -200,14 +219,6 @@ protected: * Build the name to write the parameter from the extension's ID and the name of this parameter. */ gchar *pref_name() const; - - -private: - /** Which extension is this parameter attached to. */ - Inkscape::Extension::Extension *_extension; - - /** The name of this parameter. */ - gchar *_name; }; } // namespace Extension diff --git a/src/extension/prefdialog/prefdialog.cpp b/src/extension/prefdialog/prefdialog.cpp index e0fea98c8..17deb7a20 100644 --- a/src/extension/prefdialog/prefdialog.cpp +++ b/src/extension/prefdialog/prefdialog.cpp @@ -54,7 +54,7 @@ PrefDialog::PrefDialog (Glib::ustring name, Gtk::Widget * controls, Effect * eff { this->set_default_size(0,0); // we want the window to be as small as possible instead of clobbering up space - Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox()); + Gtk::HBox *hbox = Gtk::manage(new Gtk::HBox()); if (controls == nullptr) { if (_effect == nullptr) { std::cout << "AH!!! No controls and no effect!!!" << std::endl; @@ -98,7 +98,7 @@ PrefDialog::PrefDialog (Glib::ustring name, Gtk::Widget * controls, Effect * eff this->get_content_area()->pack_start(*hbox, false, false, 0); - Gtk::Box * hbox = dynamic_cast<Gtk::Box *>(_button_preview); + Gtk::Box *hbox = dynamic_cast<Gtk::Box *>(_button_preview); if (hbox != nullptr) { _checkbox_preview = dynamic_cast<Gtk::CheckButton *>(hbox->get_children().front()); } diff --git a/src/extension/prefdialog/prefdialog.h b/src/extension/prefdialog/prefdialog.h index 295b4a445..57d33bb28 100644 --- a/src/extension/prefdialog/prefdialog.h +++ b/src/extension/prefdialog/prefdialog.h @@ -31,17 +31,17 @@ class PrefDialog : public Gtk::Dialog { Glib::ustring _name; /** \brief A pointer to the OK button */ - Gtk::Button * _button_ok; + Gtk::Button *_button_ok; /** \brief A pointer to the CANCEL button */ - Gtk::Button * _button_cancel; + Gtk::Button *_button_cancel; /** \brief Button to control live preview */ - Gtk::Widget * _button_preview; + Gtk::Widget *_button_preview; /** \brief Checkbox for the preview */ - Gtk::CheckButton * _checkbox_preview; + Gtk::CheckButton *_checkbox_preview; /** \brief Parameter to control live preview */ - Parameter * _param_preview; + Parameter *_param_preview; /** \brief XML to define the live effects parameter on the dialog */ static const char * live_param_xml; @@ -53,10 +53,10 @@ class PrefDialog : public Gtk::Dialog { /** \brief If this is the preferences for an effect, the effect that we're working with. */ - Effect * _effect; + Effect *_effect; /** \brief If we're executing in preview mode here is the execution environment for the effect. */ - ExecutionEnv * _exEnv; + ExecutionEnv *_exEnv; /** \brief The timer used to make it so that parameters don't respond directly and allows for changes. */ |
