21#include <glib/gprintf.h>
22#include <glibmm/fileutils.h>
23#include <glibmm/i18n.h>
24#include <glibmm/miscutils.h>
26#include <gtkmm/frame.h>
27#include <gtkmm/grid.h>
28#include <gtkmm/label.h>
67 : imp{
std::move(implementation)}
72 g_return_if_fail(in_repr);
82 char const *translationdomain =
repr->
attribute(
"translationdomain");
83 if (translationdomain) {
102 char const *chname = child_repr->
name();
103 if (!strncmp(chname, INKSCAPE_EXTENSION_NS_NC, strlen(INKSCAPE_EXTENSION_NS_NC))) {
104 chname += strlen(INKSCAPE_EXTENSION_NS);
106 if (chname[0] ==
'_') {
110 if (!strcmp(chname,
"id")) {
117 }
else if (!strcmp(chname,
"name")) {
129 }
else if (!strcmp(chname,
"action")) {
131 }
else if (!strcmp(chname,
"dependency")) {
132 _deps.push_back(std::make_unique<Dependency>(child_repr,
this));
133 }
else if (!strcmp(chname,
"script")) {
136 char const *interpreted =
child->attribute(
"interpreter");
138 _deps.push_back(std::make_unique<Dependency>(
child,
this, type));
142 }
else if (!strcmp(chname,
"xslt")) {
154 child_repr = child_repr->
next();
167 if (
_id.find(
"win32") !=
_id.npos) {
200 timer = std::make_unique<ExpirationTimer>(
this);
259 char const *inx_failure = _(
" This is caused by an improper .inx file for this extension."
260 " An improper .inx file could have been caused by a faulty installation of Inkscape.");
262 if (
repr ==
nullptr) {
263 printFailure(Glib::ustring(_(
"the XML description of it got lost.")) += inx_failure);
267 printFailure(Glib::ustring(_(
"no implementation was defined for the extension.")) += inx_failure);
272 for (
auto const &dep :
_deps) {
273 if (dep->check() ==
false) {
274 printFailure(Glib::ustring(_(
"a dependency was not met.")));
281 return imp->check(
this);
297 _error_reason = Glib::ustring::compose(_(
"Extension \"%1\" failed to load because %2"),
_name, reason);
381 for (
auto const &dep :
_deps) {
382 if (!strcmp(
name, dep->get_name())) {
383 return dep->get_path();
392 Glib::Dir dir(directory);
394 std::string
name = dir.read_name();
395 while (!
name.empty()) {
396 std::string fullpath = Glib::build_filename(directory,
name);
399 if (Glib::file_test(fullpath, Glib::FileTest::IS_DIR)) {
403 }
else if (
name == filename) {
406 name = dir.read_name();
428 std::string locale_dir_current_extension;
429 std::string locale_dir_extensions;
430 std::string locale_dir_system;
432 locale_dir_current_extension = Glib::build_filename(
_base_directory,
"locale");
435 if (
index != std::string::npos) {
439 locale_dir_system = bindtextdomain(
"inkscape",
nullptr);
442 std::vector<std::string> locale_dirs;
443 if (locale_dir_current_extension != locale_dir_extensions) {
444 locale_dirs.push_back(std::move(locale_dir_current_extension));
446 locale_dirs.push_back(std::move(locale_dir_extensions));
447 locale_dirs.push_back(std::move(locale_dir_system));
450 std::string search_name;
452 search_name +=
".mo";
453 for (
auto &&locale_dir : locale_dirs) {
454 if (!Glib::file_test(locale_dir, Glib::FileTest::IS_DIR)) {
482 g_warning(
"Failed to locate message catalog for textdomain '%s'.",
_translationdomain);
503 if (!strcmp(msgid,
"")) {
504 g_warning(
"Attempting to translate an empty string in extension '%s', which is not supported.",
_id.c_str());
523 Glib::unsetenv(
"INKEX_GETTEXT_DOMAIN");
524 Glib::unsetenv(
"INKEX_GETTEXT_DIRECTORY");
530 Glib::setenv(
"SELF_CALL",
"true");
538 Glib::setenv(
"DOCUMENT_PATH", std::string(path));
573 std::vector<InxWidget *> widget_list;
574 for (
auto const &widget :
_widgets) {
575 widget->get_widgets(widget_list);
579 for (
auto widget : widget_list) {
582 char const *
name = parameter->
name();
585 if (
name && !value.empty()) {
586 std::string parameter_string;
587 parameter_string +=
"--";
588 parameter_string +=
name;
589 parameter_string +=
"=";
590 parameter_string += value;
591 retlist.push_back(std::move(parameter_string));
604 std::vector<InxWidget *> widget_list;
605 for (
auto const &widget :
_widgets) {
606 widget->get_widgets(widget_list);
610 for (
auto widget : widget_list) {
612 if (parameter && !strcmp(parameter->
name(),
name)) {
913 g_warning(_(
"Could not create extension error log file '%s'"), ext_error_file.c_str());
936class AutoGUI :
public Gtk::Box {
951 void addWidget(Gtk::Widget *widg,
char const *tooltip,
int indent) {
957 widg->set_tooltip_text(tooltip);
959 widg->set_tooltip_text(
"");
960 widg->set_has_tooltip(
false);
981 auto const agui = Gtk::make_managed<AutoGUI>();
986 for (
auto const &widget :
_widgets) {
987 if (widget->get_hidden()) {
991 Gtk::Widget *widg = widget->get_widget(changeSignal);
992 char const *tip = widget->get_tooltip();
993 int indent = widget->get_indent();
994 agui->addWidget(widg, tip, indent);
1005 auto const retval = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 4);
1006 retval->set_margin(4);
1008 auto const info = Gtk::make_managed<Gtk::Frame>(
"General Extension Information");
1011 auto const table = Gtk::make_managed<Gtk::Grid>();
1012 table->set_margin(4);
1013 table->set_column_spacing(4);
1014 info->set_child(*table);
1025 Gtk::Grid * table,
int * row)
1027 auto const label = Gtk::make_managed<Gtk::Label>(labelstr, Gtk::Align::START);
1028 auto const value = Gtk::make_managed<Gtk::Label>(valuestr, Gtk::Align::START);
1031 table->attach(*
label, 0, (*row) - 1, 1, 1);
1032 table->attach(*value, 1, (*row) - 1, 1, 1);
1038 auto const retval = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL);
1039 Gtk::Widget * content = Gtk::make_managed<Gtk::Label>(
"Params");
1046 unsigned int _visible_count = 0;
1047 for (
auto const &widget :
_widgets) {
1048 if (!widget->get_hidden()) {
1052 return _visible_count;
1063 if (!INKSCAPE.use_gui()) {
1072 if (
auto controls =
autogui(
nullptr,
nullptr)) {
1075 return response == Gtk::ResponseType::OK;
1087 for (
auto &process_action :
_actions) {
1089 if (process_action.is_enabled()) {
1090 process_action.run(doc);
type_t
All the possible types of dependencies.
@ TYPE_FILE
Look to make sure a file exists.
@ TYPE_EXECUTABLE
Look for an executable.
no valid ID found while parsing XML representation
no valid name found while parsing XML representation
extension is not compatible with the current system and should not be loaded
No implementation could be loaded for the extension.
An error class for when a parameter is looked for that just simply doesn't exist.
The object that is the basis for the Extension system.
double set_param_float(char const *name, double value)
Sets a parameter identified by name with the double in the parameter value.
state_t get_state()
A getter for the state variable.
char const * get_param_optiongroup(char const *name, char const *alt) const
Like get_param_optiongroup but with a default on param_not_exist error.
virtual void deactivate()
This function diactivates the extension (which makes it unusable, but not deleted)
std::string _name
A user friendly name for the Extension.
int get_param_int(char const *name) const
Gets a parameter identified by name with the integer placed in value.
char const * get_translation(char const *msgid, char const *msgctxt=nullptr) const
Gets a translation within the context of the current extension.
static void error_file_write(Glib::ustring const &text)
A function to write to the error log file.
std::unique_ptr< ExpirationTimer > timer
Timeout to unload after a given time.
std::string _error_reason
Short, textual explanation for the latest error.
state_t
An enumeration to identify if the Extension has been loaded or not.
@ STATE_LOADED
The extension has been loaded successfully.
@ STATE_DEACTIVATED
The extension is missing something which makes it unusable.
@ STATE_UNLOADED
The extension has not been loaded.
unsigned int widget_visible_count() const
A function to get the number of visible parameters of the extension.
char const * get_name() const
Get the name of this extension - not a copy don't delete!
bool get_param_optiongroup_contains(char const *name, char const *value) const
This is useful to find out, if a given string value is selectable in a optiongroup named \cname.
void paramListString(std::list< std::string > &retlist) const
A function to get the parameters in a string form.
double get_param_float(char const *name) const
Gets a float parameter identified by name with the double placed in value.
bool set_param_bool(char const *name, bool value)
Sets a parameter identified by name with the boolean in the parameter value.
virtual void run_processing_actions(SPDocument *doc)
Runs any pre-processing actions and modifies the document.
Inkscape::XML::Node * repr
The XML description of the Extension.
std::string _id
The unique identifier for the Extension.
Gtk::Widget * autogui(SPDocument *doc, Inkscape::XML::Node *node, sigc::signal< void()> *changeSignal=nullptr)
A function to automatically generate a GUI from the extensions' widgets.
std::vector< std::unique_ptr< Dependency > > _deps
Dependencies for this extension.
int set_param_int(char const *name, int value)
Sets a parameter identified by name with the integer in the parameter value.
ImplementationHolder imp
An Implementation object provides the actual implementation of the Extension.
char const * get_id() const
Get the ID of this extension - not a copy don't delete!
static void error_file_open()
A function to open the error log file.
std::vector< std::unique_ptr< InxWidget > > _widgets
A list of widgets for this extension.
ModuleImpType get_implementation_type()
Uses the object's type to figure out what the type is.
char const * get_param_string(char const *name, char const *alt) const
Like get_param_string but with a default on param_not_exist error.
virtual bool check()
A function to check the validity of the extension.
void set_state(state_t in_state)
A function to set whether the extension should be loaded or unloaded.
Colors::Color get_param_color(char const *name) const
Gets a parameter identified by name with the unsigned int placed in value.
bool _translation_enabled
Attempt translation of strings provided by the extension?
static void add_val(Glib::ustring const &labelstr, Glib::ustring const &valuestr, Gtk::Grid *table, int *row)
Gtk::Box * get_params_widget()
void set_param_color(char const *name, Colors::Color const &color)
char const * set_param_optiongroup(char const *name, char const *value)
Sets a parameter identified by name with the string in the parameter value.
std::string get_dependency_location(char const *name)
Gets the location of the dependency file as an absolute path.
void set_param_hidden(char const *name, bool hidden)
static void error_file_close()
A function to close the error log file.
std::vector< ProcessingAction > _actions
Processing actions.
bool loaded()
A quick function to test the state of the extension.
Inkscape::XML::Node * get_repr()
A getter for the internal Repr, does not add a reference.
std::string _base_directory
Directory containing the .inx file, relative paths in the extension should usually be relative to it.
char const * _translationdomain
Domainname of gettext textdomain that should be used for translation of the extension's strings.
void set_environment(SPDocument const *doc=nullptr)
Sets environment suitable for executing this Extension.
void printFailure(Glib::ustring const &reason)
A quick function to print out a standard start of extension errors in the log.
Gtk::Box * get_info_widget()
char const * set_param_string(char const *name, char const *value)
Sets a parameter identified by name with the string in the parameter value.
bool deactivated()
Find out the status of the extension.
bool get_param_bool(char const *name) const
Gets a parameter identified by name with the bool placed in value.
std::string _gettext_catalog_dir
Directory containing the gettext catalog for _translationdomain.
virtual bool prefs()
Create a dialog for preference for this extension.
state_t _state
Which state the Extension is currently in.
void lookup_translation_catalog()
Searches for a gettext catalog matching the extension's translationdomain.
InxParameter * get_param(char const *name)
Looks up the parameter with the specified name.
void set_param_any(char const *name, std::string const &value)
Parses the given string value and sets a parameter identified by name.
Util::HybridPointer< Implementation::Implementation > ImplementationHolder
static FILE * error_file
This is the place where errors get reported.
Utility class used for loading and launching script extensions.
A class to represent the parameter of an extension.
bool get_bool() const
Wrapper to cast to the object and use its function.
double set_float(double in)
Wrapper to cast to the object and use it's function.
const char * get_optiongroup() const
Wrapper to cast to the object and use it's function.
bool get_optiongroup_contains(const char *value) const
void set_color(Inkscape::Colors::Color const &in)
Wrapper to cast to the object and use it's function.
virtual const std::string & set(const std::string &in)
Calls string_to_value and then saves the result in the prefs.
const char * set_optiongroup(const char *in)
Wrapper to cast to the object and use it's function.
virtual std::string value_to_string() const
Gets the current value of the parameter in a string form.
int set_int(int in)
Wrapper to cast to the object and use it's function.
const char * get_string() const
Wrapper to cast to the object and use it's function.
double get_float() const
Wrapper to cast to the object and use it's function.
char const * name() const
const char * set_string(const char *in)
Wrapper to cast to the object and use it's function.
int get_int() const
Wrapper to cast to the object and use it's function.
Inkscape::Colors::Color get_color() const
Wrapper to cast to the object and use it's function.
bool set_bool(bool in)
Wrapper to cast to the object and use it's function.
A class to represent the preferences for an extension.
Interface for refcounted XML nodes.
virtual Node * next()=0
Get the next sibling of this node.
virtual char const * name() const =0
Get the name of the element node.
virtual Node * firstChild()=0
Get the first child of this node.
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
virtual char const * content() const =0
Get the content of a text or comment node.
Typed SVG document implementation.
char const * getDocumentFilename() const
Parameters for extensions.
Inkscape::Extension::Extension: Frontend to certain, possibly pluggable, actions.
Inkscape::XML::Node * node
static bool _find_filename_recursive(std::string directory, std::string const &filename)
recursively searches directory for a file named filename; returns true if found
static R & anchor(R &r)
Increments the reference count of a anchored object.
static R & release(R &r)
Decrements the reference count of a anchored object.
std::string profile_path()
std::string log_path(const char *filename)
FILE * fopen_utf8name(char const *utf8name, char const *mode)
Open a file with g_fopen().
void pack_start(Gtk::Box &box, Gtk::Widget &child, bool const expand, bool const fill, unsigned const padding)
Adds child to box, packed with reference to the start of box.
int dialog_run(Gtk::Dialog &dialog)
This is a GTK4 porting aid meant to replace the removal of the Gtk::Dialog synchronous API.
@ ELEMENT_NODE
Regular element node, e.g. <group />.
Helpers for using Gtk::Boxes, encapsulating large changes between GTK3 & GTK4.
C facade to Inkscape::XML::Node.
Inkscape::IO::Resource - simple resource API.