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>
52FILE *Extension::error_file =
nullptr;
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) {
173Extension::~Extension()
200 timer = std::make_unique<ExpirationTimer>(
this);
225Extension::get_state ()
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);
295Extension::printFailure(Glib::ustring
const &reason)
306Extension::get_repr ()
326Extension::get_name ()
const
347Extension::deactivate ()
361Extension::deactivated ()
379std::string Extension::get_dependency_location(
char const *name)
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);
403 }
else if (name == filename) {
406 name = dir.read_name();
424void Extension::lookup_translation_catalog() {
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) {
436 locale_dir_extensions = Glib::build_filename(
_base_directory.substr(0, index+1),
"locale");
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) {
482 g_warning(
"Failed to locate message catalog for textdomain '%s'.",
_translationdomain);
498char const *Extension::get_translation(
char const *msgid,
char const *msgctxt)
const {
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));
570Extension::paramListString(std::list<std::string> &retlist)
const
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)) {
634Extension::get_param_bool(
char const *name)
const
645bool Extension::get_param_bool(
char const *name,
bool alt)
const
662Extension::get_param_int(
char const *name)
const
673int Extension::get_param_int(
char const *name,
int alt)
const
690Extension::get_param_float(
char const *name)
const
701double Extension::get_param_float(
char const *name,
double alt)
const
718Extension::get_param_string(
char const *name)
const
729char const *Extension::get_param_string(
char const *name,
char const *alt)
const
746Extension::get_param_optiongroup(
char const *name)
const
757char const *Extension::get_param_optiongroup(
char const *name,
char const *alt)
const
773Extension::get_param_optiongroup_contains(
char const *name,
char const *value)
const
788Extension::get_param_color(
char const *name)
const
804Extension::set_param_bool(
char const *name,
const bool value)
820Extension::set_param_int(
char const *name,
const int value)
836Extension::set_param_float(
char const *name,
const double value)
852Extension::set_param_string(
char const *name,
char const *value)
868Extension::set_param_optiongroup(
char const *name,
char const *value)
884Extension::set_param_color(
char const *name,
const std::uint32_t color)
896void Extension::set_param_any(
char const *name, std::string
const &value)
901void Extension::set_param_hidden(
char const *name,
bool hidden)
908Extension::error_file_open ()
913 g_warning(_(
"Could not create extension error log file '%s'"), ext_error_file.c_str());
919Extension::error_file_close ()
928Extension::error_file_write(Glib::ustring
const &text)
936class AutoGUI :
public Gtk::Box {
939 AutoGUI () :
Gtk::Box(
Gtk::Orientation::VERTICAL) {};
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);
1003Extension::get_info_widget()
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);
1024void Extension::add_val(Glib::ustring
const &labelstr, Glib::ustring
const &valuestr,
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);
1036Extension::get_params_widget()
1039 Gtk::Widget * content = Gtk::make_managed<Gtk::Label>(
"Params");
1044unsigned int Extension::widget_visible_count()
const
1046 unsigned int _visible_count = 0;
1047 for (
auto const &widget :
_widgets) {
1048 if (!widget->get_hidden()) {
1052 return _visible_count;
1061bool Extension::prefs()
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.
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.
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!
double get_param_float(char const *name) const
Gets a float parameter identified by name with the double placed in value.
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.
ImplementationHolder imp
An Implementation object provides the actual implementation of the Extension.
std::vector< std::unique_ptr< InxWidget > > _widgets
A list of widgets for this extension.
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.
void set_state(state_t in_state)
A function to set whether the extension should be loaded or unloaded.
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)
std::vector< ProcessingAction > _actions
Processing actions.
bool loaded()
A quick function to test the state of the extension.
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 printFailure(Glib::ustring const &reason)
A quick function to print out a standard start of extension errors in the log.
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.
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.
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.
unsigned int set_color(unsigned int in)
Wrapper to cast to the object and use it's function.
bool get_optiongroup_contains(const char *value) const
unsigned int get_color() const
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.
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
D2< T > compose(D2< T > const &a, T const &b)
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(const char *filename)
Get, or guess, or decide the location where the preferences.xml file should be located.
std::string log_path(const char *filename)
bool file_test(char const *utf8name, GFileTest test)
FILE * fopen_utf8name(char const *utf8name, char const *mode)
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 />.
@ VERTICAL
The y-dimension (1).
Helpers for using Gtk::Boxes, encapsulating large changes between GTK3 & GTK4.
C facade to Inkscape::XML::Node.
Inkscape::IO::Resource - simple resource API.