Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
extension.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
9/*
10 * Authors:
11 * Ted Gould <ted@gould.cx>
12 *
13 * Copyright (C) 2002-2005 Authors
14 *
15 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
16 */
17
18#include "extension.h"
19
20#include <utility>
21#include <glib/gprintf.h>
22#include <glibmm/fileutils.h>
23#include <glibmm/i18n.h>
24#include <glibmm/miscutils.h>
25#include <gtkmm/box.h>
26#include <gtkmm/frame.h>
27#include <gtkmm/grid.h>
28#include <gtkmm/label.h>
29
30#include "db.h"
31#include "dependency.h"
32#include "document.h"
33#include "processing-action.h"
36#include "implementation/xslt.h"
37#include "inkscape.h"
38#include "io/resource.h"
39#include "io/sys.h"
42#include "prefdialog/widget.h"
43#include "timer.h"
44#include "ui/dialog-run.h"
45#include "ui/pack.h"
46#include "ui/util.h"
47#include "xml/node.h"
48#include "xml/repr.h"
49
50namespace Inkscape::Extension {
51
52FILE *Extension::error_file = nullptr;
53
66Extension::Extension(Inkscape::XML::Node *in_repr, ImplementationHolder implementation, std::string *base_directory)
67 : imp{std::move(implementation)}
68{
69 if (!imp) {
71 }
72 g_return_if_fail(in_repr); // should be ensured in system.cpp
73 repr = in_repr;
75
76 if (base_directory) {
77 _base_directory = *base_directory;
78 }
79
80 // get name of the translation catalog ("gettext textdomain") that the extension wants to use for translations
81 // and lookup the locale directory for it
82 char const *translationdomain = repr->attribute("translationdomain");
83 if (translationdomain) {
84 _translationdomain = translationdomain;
85 } else {
86 _translationdomain = "inkscape"; // default to the Inkscape catalog
87 }
88 if (!strcmp(_translationdomain, "none")) {
89 // special keyword "none" means the extension author does not want translation of extension strings
91 _translationdomain = nullptr;
92 } else if (!strcmp(_translationdomain, "inkscape")) {
93 // this is our default domain; we know the location already (also respects INKSCAPE_LOCALEDIR)
94 _gettext_catalog_dir = bindtextdomain("inkscape", nullptr);
95 } else {
97 }
98
99 // Read XML tree and parse extension
100 Inkscape::XML::Node *child_repr = repr->firstChild();
101 while (child_repr) {
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);
105 }
106 if (chname[0] == '_') { // allow leading underscore in tag names for backwards-compatibility
107 chname++;
108 }
109
110 if (!strcmp(chname, "id")) {
111 char const *id = child_repr->firstChild() ? child_repr->firstChild()->content() : nullptr;
112 if (id) {
113 _id = id;
114 } else {
115 throw extension_no_id();
116 }
117 } else if (!strcmp(chname, "name")) {
118 char const *name = child_repr->firstChild() ? child_repr->firstChild()->content() : nullptr;
119 if (name) {
120 _name = name;
121 } else {
122 throw extension_no_name();
123 }
124 } else if (InxWidget::is_valid_widget_name(chname)) {
125 InxWidget *widget = InxWidget::make(child_repr, this);
126 if (widget) {
127 _widgets.emplace_back(widget);
128 }
129 } else if (!strcmp(chname, "action")) {
130 _actions.emplace_back(child_repr);
131 } else if (!strcmp(chname, "dependency")) {
132 _deps.push_back(std::make_unique<Dependency>(child_repr, this));
133 } else if (!strcmp(chname, "script")) { // TODO: should these be parsed in their respective Implementation?
134 for (auto child = child_repr->firstChild(); child != nullptr; child = child->next()) {
135 if (child->type() == Inkscape::XML::NodeType::ELEMENT_NODE) { // skip non-element nodes (see LP #1372200)
136 char const *interpreted = child->attribute("interpreter");
138 _deps.push_back(std::make_unique<Dependency>(child, this, type));
139 break;
140 }
141 }
142 } else if (!strcmp(chname, "xslt")) { // TODO: should these be parsed in their respective Implementation?
143 for (auto child = child_repr->firstChild(); child != nullptr; child = child->next()) {
144 if (child->type() == Inkscape::XML::NodeType::ELEMENT_NODE) { // skip non-element nodes (see LP #1372200)
145 _deps.push_back(std::make_unique<Dependency>(child, this, Dependency::TYPE_FILE));
146 break;
147 }
148 }
149 } else {
150 // We could do some sanity checking here.
151 // However, we don't really know which additional elements Extension subclasses might need...
152 }
153
154 child_repr = child_repr->next();
155 }
156
157 // all extensions need an ID and a name
158 if (_id.empty()) {
159 throw extension_no_id();
160 }
161 if (_name.empty()) {
162 throw extension_no_name();
163 }
164
165 // filter out extensions that are not compatible with the current platform
166#ifndef _WIN32
167 if (_id.find("win32") != _id.npos) {
169 }
170#endif
171}
172
177
189void
191{
192 if (_state == STATE_DEACTIVATED) return;
193 if (in_state != _state) {
195 switch (in_state) {
196 case STATE_LOADED:
197 if (imp->load(this))
199
200 timer = std::make_unique<ExpirationTimer>(this);
201 break;
202
203 case STATE_UNLOADED:
204 imp->unload(this);
206 timer.reset();
207 break;
208
211 timer.reset();
212 break;
213
214 default:
215 break;
216 }
217 }
218}
219
226{
227 return _state;
228}
229
234bool
236{
237 return get_state() == STATE_LOADED;
238}
239
256bool
258{
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.");
261
262 if (repr == nullptr) {
263 printFailure(Glib::ustring(_("the XML description of it got lost.")) += inx_failure);
264 return false;
265 }
266 if (!imp) {
267 printFailure(Glib::ustring(_("no implementation was defined for the extension.")) += inx_failure);
268 return false;
269 }
270
271 bool retval = true;
272 for (auto const &dep : _deps) {
273 if (dep->check() == false) {
274 printFailure(Glib::ustring(_("a dependency was not met.")));
275 error_file_write(dep->info_string());
276 retval = false;
277 }
278 }
279
280 if (retval) {
281 return imp->check(this);
282 }
283
285 return retval;
286}
287
294void
295Extension::printFailure(Glib::ustring const &reason)
296{
297 _error_reason = Glib::ustring::compose(_("Extension \"%1\" failed to load because %2"), _name, reason);
299}
300
307{
308 return repr;
309}
310
315char const *
317{
318 return _id.c_str();
319}
320
325char const *
327{
328 return get_translation(_name.c_str(), nullptr);
329}
330
346void
348{
350
351 /* Removing the old implementation, and making this use the default. */
352 /* This should save some memory */
354}
355
360bool
365
380{
381 for (auto const &dep : _deps) {
382 if (!strcmp(name, dep->get_name())) {
383 return dep->get_path();
384 }
385 }
386
387 return "";
388}
389
391static bool _find_filename_recursive(std::string directory, std::string const &filename) {
392 Glib::Dir dir(directory);
393
394 std::string name = dir.read_name();
395 while (!name.empty()) {
396 std::string fullpath = Glib::build_filename(directory, name);
397 // g_message("%s", fullpath.c_str());
398
399 if (Glib::file_test(fullpath, Glib::FileTest::IS_DIR)) {
400 if (_find_filename_recursive(fullpath, filename)) {
401 return true;
402 }
403 } else if (name == filename) {
404 return true;
405 }
406 name = dir.read_name();
407 }
408
409 return false;
410}
411
425 g_assert(!_base_directory.empty());
426
427 // get locale folder locations
428 std::string locale_dir_current_extension;
429 std::string locale_dir_extensions;
430 std::string locale_dir_system;
431
432 locale_dir_current_extension = Glib::build_filename(_base_directory, "locale");
433
434 size_t index = _base_directory.find_last_of("extensions");
435 if (index != std::string::npos) {
436 locale_dir_extensions = Glib::build_filename(_base_directory.substr(0, index+1), "locale");
437 }
438
439 locale_dir_system = bindtextdomain("inkscape", nullptr);
440
441 // collect unique locations into vector
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));
445 }
446 locale_dirs.push_back(std::move(locale_dir_extensions));
447 locale_dirs.push_back(std::move(locale_dir_system));
448
449 // iterate over locations and look for the one that has the correct catalog
450 std::string search_name;
451 search_name += _translationdomain;
452 search_name += ".mo";
453 for (auto &&locale_dir : locale_dirs) {
454 if (!Glib::file_test(locale_dir, Glib::FileTest::IS_DIR)) {
455 continue;
456 }
457
458 if (_find_filename_recursive(locale_dir, search_name)) {
459 _gettext_catalog_dir = std::move(locale_dir);
460 break;
461 }
462 }
463
464#ifdef _WIN32
465 // obtain short path, bindtextdomain doesn't understand UTF-8
466 if (!_gettext_catalog_dir.empty()) {
467 auto shortpath = g_win32_locale_filename_from_utf8(_gettext_catalog_dir.c_str());
468 _gettext_catalog_dir = shortpath;
469 g_free(shortpath);
470 }
471#endif
472
473 // register catalog with gettext if found, disable translation for this extension otherwise
474 if (!_gettext_catalog_dir.empty()) {
475 char const *current_dir = bindtextdomain(_translationdomain, nullptr);
476 if (_gettext_catalog_dir != current_dir) {
477 g_info("Binding textdomain '%s' to '%s'.", _translationdomain, _gettext_catalog_dir.c_str());
478 bindtextdomain(_translationdomain, _gettext_catalog_dir.c_str());
479 bind_textdomain_codeset(_translationdomain, "UTF-8");
480 }
481 } else {
482 g_warning("Failed to locate message catalog for textdomain '%s'.", _translationdomain);
483 _translation_enabled = false;
484 _translationdomain = nullptr;
485 }
486}
487
498char const *Extension::get_translation(char const *msgid, char const *msgctxt) const {
500 return msgid;
501 }
502
503 if (!strcmp(msgid, "")) {
504 g_warning("Attempting to translate an empty string in extension '%s', which is not supported.", _id.c_str());
505 return msgid;
506 }
507
508 if (msgctxt) {
509 return g_dpgettext2(_translationdomain, msgctxt, msgid);
510 } else {
511 return g_dgettext(_translationdomain, msgid);
512 }
513}
514
523 Glib::unsetenv("INKEX_GETTEXT_DOMAIN");
524 Glib::unsetenv("INKEX_GETTEXT_DIRECTORY");
525
526 // This is needed so extensions can interact with the user's profile, keep settings etc.
527 Glib::setenv("INKSCAPE_PROFILE_DIR", Inkscape::IO::Resource::profile_path());
528
529 // This is needed if an extension calls inkscape itself
530 Glib::setenv("SELF_CALL", "true");
531
532 // This is needed so files can be saved relative to their document location (see image-extract)
533 if (doc) {
534 auto path = doc->getDocumentFilename();
535 if (!path) {
536 path = ""; // Set to blank string so extensions know the difference between old inkscape and not-saved document.
537 }
538 Glib::setenv("DOCUMENT_PATH", std::string(path));
539 }
540
541 if (_translationdomain) {
542 Glib::setenv("INKEX_GETTEXT_DOMAIN", std::string(_translationdomain));
543 }
544 if (!_gettext_catalog_dir.empty()) {
545 Glib::setenv("INKEX_GETTEXT_DIRECTORY", _gettext_catalog_dir);
546 }
547}
548
554{
555 if (dynamic_cast<Implementation::Script *>(imp.get())) {
556 return MODULE_EXTENSION;
557 } else if (dynamic_cast<Implementation::XSLT *>(imp.get())) {
558 return MODULE_XSLT;
559 }
560 // MODULE_UNKNOWN_IMP is not required because it never results in an
561 // object being created. Thus this function wouldn't be available.
562 return MODULE_PLUGIN;
563}
564
569void
570Extension::paramListString(std::list<std::string> &retlist) const
571{
572 // first collect all widgets in the current extension
573 std::vector<InxWidget *> widget_list;
574 for (auto const &widget : _widgets) {
575 widget->get_widgets(widget_list);
576 }
577
578 // then build a list of parameter strings from parameter names and values, as '--name=value'
579 for (auto widget : widget_list) {
580 InxParameter *parameter = dynamic_cast<InxParameter *>(widget); // filter InxParameters from InxWidgets
581 if (parameter) {
582 char const *name = parameter->name();
583 std::string value = parameter->value_to_string();
584
585 if (name && !value.empty()) { // TODO: Shouldn't empty string values be allowed?
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));
592 }
593 }
594 }
595}
596
598{
599 if (!name || _widgets.empty()) {
601 }
602
603 // first collect all widgets in the current extension
604 std::vector<InxWidget *> widget_list;
605 for (auto const &widget : _widgets) {
606 widget->get_widgets(widget_list);
607 }
608
609 // then search for a parameter with a matching name
610 for (auto widget : widget_list) {
611 InxParameter *parameter = dynamic_cast<InxParameter *>(widget); // filter InxParameters from InxWidgets
612 if (parameter && !strcmp(parameter->name(), name)) {
613 return parameter;
614 }
615 }
616
617 // if execution reaches here, no parameter matching 'name' was found
619}
620
621InxParameter const *Extension::get_param(char const *name) const
622{
623 return const_cast<Extension *>(this)->get_param(name);
624}
625
633bool
635{
636 const InxParameter *param;
637 param = get_param(name);
638 return param->get_bool();
639}
640
645bool Extension::get_param_bool(char const *name, bool alt) const
646{
647 try {
648 return get_param_bool(name);
650 return alt;
651 }
652}
653
661int
663{
664 const InxParameter *param;
665 param = get_param(name);
666 return param->get_int();
667}
668
673int Extension::get_param_int(char const *name, int alt) const
674{
675 try {
676 return get_param_int(name);
678 return alt;
679 }
680}
681
689double
691{
692 const InxParameter *param;
693 param = get_param(name);
694 return param->get_float();
695}
696
701double Extension::get_param_float(char const *name, double alt) const
702{
703 try {
704 return get_param_float(name);
706 return alt;
707 }
708}
709
717char const *
719{
720 const InxParameter *param;
721 param = get_param(name);
722 return param->get_string();
723}
724
729char const *Extension::get_param_string(char const *name, char const *alt) const
730{
731 try {
732 return get_param_string(name);
734 return alt;
735 }
736}
737
745char const *
747{
748 const InxParameter *param;
749 param = get_param(name);
750 return param->get_optiongroup();
751}
752
757char const *Extension::get_param_optiongroup(char const *name, char const *alt) const
758{
759 try {
762 return alt;
763 }
764}
765
772bool
773Extension::get_param_optiongroup_contains(char const *name, char const *value) const
774{
775 const InxParameter *param;
776 param = get_param(name);
777 return param->get_optiongroup_contains(value);
778}
779
789{
790 const InxParameter *param;
791 param = get_param(name);
792 return param->get_color();
793}
794
803bool
804Extension::set_param_bool(char const *name, const bool value)
805{
806 InxParameter *param;
807 param = get_param(name);
808 return param->set_bool(value);
809}
810
819int
820Extension::set_param_int(char const *name, const int value)
821{
822 InxParameter *param;
823 param = get_param(name);
824 return param->set_int(value);
825}
826
835double
836Extension::set_param_float(char const *name, const double value)
837{
838 InxParameter *param;
839 param = get_param(name);
840 return param->set_float(value);
841}
842
851char const *
852Extension::set_param_string(char const *name, char const *value)
853{
854 InxParameter *param;
855 param = get_param(name);
856 return param->set_string(value);
857}
858
867char const *
868Extension::set_param_optiongroup(char const *name, char const *value)
869{
870 InxParameter *param;
871 param = get_param(name);
872 return param->set_optiongroup(value);
873}
874
883void
885{
886 InxParameter *param;
887 param = get_param(name);
888 param->set_color(color);
889}
890
896void Extension::set_param_any(char const *name, std::string const &value)
897{
898 get_param(name)->set(value);
899}
900
901void Extension::set_param_hidden(char const *name, bool hidden)
902{
903 get_param(name)->set_hidden(hidden);
904}
905
907void
909{
910 auto ext_error_file = Inkscape::IO::Resource::log_path(EXTENSION_ERROR_LOG_FILENAME);
911 error_file = Inkscape::IO::fopen_utf8name(ext_error_file.c_str(), "w+");
912 if (!error_file) {
913 g_warning(_("Could not create extension error log file '%s'"), ext_error_file.c_str());
914 }
915};
916
918void
920{
921 if (error_file) {
922 fclose(error_file);
923 }
924};
925
927void
928Extension::error_file_write(Glib::ustring const &text)
929{
930 if (error_file) {
931 g_fprintf(error_file, "%s\n", text.c_str());
932 }
933};
934
936class AutoGUI : public Gtk::Box {
937public:
939 AutoGUI () : Gtk::Box(Gtk::Orientation::VERTICAL) {};
940
951 void addWidget(Gtk::Widget *widg, char const *tooltip, int indent) {
952 if (widg) {
953 widg->set_margin_start(indent * InxParameter::GUI_INDENTATION);
954 UI::pack_start(*this, *widg, widg->get_vexpand(), true);
955
956 if (tooltip) {
957 widg->set_tooltip_text(tooltip);
958 } else {
959 widg->set_tooltip_text("");
960 widg->set_has_tooltip(false);
961 }
962 }
963 };
964};
965
974Gtk::Widget *
975Extension::autogui (SPDocument *doc, Inkscape::XML::Node *node, sigc::signal<void ()> *changeSignal)
976{
977 if (!_gui || widget_visible_count() == 0) {
978 return nullptr;
979 }
980
981 auto const agui = Gtk::make_managed<AutoGUI>();
982 agui->set_margin(InxParameter::GUI_BOX_MARGIN);
983 agui->set_spacing(InxParameter::GUI_BOX_SPACING);
984
985 // go through the list of widgets and add the all non-hidden ones
986 for (auto const &widget : _widgets) {
987 if (widget->get_hidden()) {
988 continue;
989 }
990
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);
995 }
996
997 return agui;
998};
999
1000/* Extension editor dialog stuff */
1001
1002Gtk::Box *
1004{
1005 auto const retval = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 4);
1006 retval->set_margin(4);
1007
1008 auto const info = Gtk::make_managed<Gtk::Frame>("General Extension Information");
1009 UI::pack_start(*retval, *info, true, true, 4);
1010
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);
1015
1016 int row = 0;
1017 add_val(_("Name:"), get_translation(_name.c_str()), table, &row);
1018 add_val(_("ID:"), _id.c_str(), table, &row);
1019 add_val(_("State:"), _state == STATE_LOADED ? _("Loaded") : _state == STATE_UNLOADED ? _("Unloaded") : _("Deactivated"), table, &row);
1020
1021 return retval;
1022}
1023
1024void Extension::add_val(Glib::ustring const &labelstr, Glib::ustring const &valuestr,
1025 Gtk::Grid * table, int * row)
1026{
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);
1029
1030 (*row)++;
1031 table->attach(*label, 0, (*row) - 1, 1, 1);
1032 table->attach(*value, 1, (*row) - 1, 1, 1);
1033}
1034
1035Gtk::Box *
1037{
1038 auto const retval = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL);
1039 Gtk::Widget * content = Gtk::make_managed<Gtk::Label>("Params");
1040 UI::pack_start(*retval, *content, true, true, 4);
1041 return retval;
1042}
1043
1045{
1046 unsigned int _visible_count = 0;
1047 for (auto const &widget : _widgets) {
1048 if (!widget->get_hidden()) {
1049 _visible_count++;
1050 }
1051 }
1052 return _visible_count;
1053}
1054
1062{
1063 if (!INKSCAPE.use_gui()) {
1064 return true;
1065 }
1066
1067 if (!loaded())
1069 if (!loaded())
1070 return false;
1071
1072 if (auto controls = autogui(nullptr, nullptr)) {
1073 auto dialog = PrefDialog(get_name(), controls);
1074 int response = Inkscape::UI::dialog_run(dialog);
1075 return response == Gtk::ResponseType::OK;
1076 }
1077
1078 // No controls, no prefs
1079 return true;
1080}
1081
1086{
1087 for (auto &process_action : _actions) {
1088 // Pass in the extensions internal prefs if needed in the future.
1089 if (process_action.is_enabled()) {
1090 process_action.run(doc);
1091 }
1092 }
1093}
1094
1095} // namespace Inkscape::Extension
1096
1097/*
1098 Local Variables:
1099 mode:c++
1100 c-file-style:"stroustrup"
1101 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1102 indent-tabs-mode:nil
1103 fill-column:99
1104 End:
1105*/
1106// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
type_t
All the possible types of dependencies.
Definition dependency.h:31
@ TYPE_FILE
Look to make sure a file exists.
Definition dependency.h:33
@ TYPE_EXECUTABLE
Look for an executable.
Definition dependency.h:32
no valid ID found while parsing XML representation
Definition extension.h:218
no valid name found while parsing XML representation
Definition extension.h:221
extension is not compatible with the current system and should not be loaded
Definition extension.h:224
No implementation could be loaded for the extension.
Definition extension.h:227
An error class for when a parameter is looked for that just simply doesn't exist.
Definition extension.h:215
The object that is the basis for the Extension system.
Definition extension.h:133
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.
Definition extension.h:145
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.
Definition extension.h:165
std::string _error_reason
Short, textual explanation for the latest error.
Definition extension.h:150
state_t
An enumeration to identify if the Extension has been loaded or not.
Definition extension.h:136
@ STATE_LOADED
The extension has been loaded successfully.
Definition extension.h:137
@ STATE_DEACTIVATED
The extension is missing something which makes it unusable.
Definition extension.h:139
@ STATE_UNLOADED
The extension has not been loaded.
Definition extension.h:138
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.
Definition extension.h:156
std::string _id
The unique identifier for the Extension.
Definition extension.h:144
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.
Definition extension.h:148
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.
Definition extension.h:162
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.
Definition extension.h:206
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?
Definition extension.h:166
static void add_val(Glib::ustring const &labelstr, Glib::ustring const &valuestr, Gtk::Grid *table, int *row)
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.
Definition extension.h:153
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.
Definition extension.h:163
char const * _translationdomain
Domainname of gettext textdomain that should be used for translation of the extension's strings.
Definition extension.h:169
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.
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.
Definition extension.h:171
virtual bool prefs()
Create a dialog for preference for this extension.
state_t _state
Which state the Extension is currently in.
Definition extension.h:146
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
Definition extension.h:141
static FILE * error_file
This is the place where errors get reported.
Definition extension.h:149
Utility class used for loading and launching script extensions.
Definition script.h:52
A class to represent the parameter of an extension.
Definition parameter.h:38
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
Definition parameter.h:82
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.
Base class to represent all widgets of an extension (including parameters)
Definition widget.h:36
void set_hidden(bool hidden)
Sets the widget to being hidden, or shown.
Definition widget.h:73
static bool is_valid_widget_name(const char *name)
Checks if name is a valid widget name, i.e.
Definition widget.cpp:71
static InxWidget * make(Inkscape::XML::Node *in_repr, Inkscape::Extension::Extension *in_ext)
Creates a new extension widget for usage in a prefdialog.
Definition widget.cpp:34
static constexpr int GUI_BOX_SPACING
Recommended spacing between multiple widgets packed into a box (in px)
Definition widget.h:90
static constexpr int GUI_BOX_MARGIN
Recommended margin of boxes containing multiple widgets (in px)
Definition widget.h:88
static constexpr int GUI_INDENTATION
Recommended indentation width of widgets(in px)
Definition widget.h:92
A class to represent the preferences for an extension.
Definition prefdialog.h:31
Interface for refcounted XML nodes.
Definition node.h:80
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.
Definition document.h:103
char const * getDocumentFilename() const
Definition document.h:231
Parameters for extensions.
Inkscape::Extension::Extension: Frontend to certain, possibly pluggable, actions.
ModuleImpType
Definition extension.h:88
@ MODULE_PLUGIN
Definition extension.h:91
@ MODULE_EXTENSION
Definition extension.h:89
@ MODULE_XSLT
Definition extension.h:90
Inkscape::XML::Node * node
Glib::ustring label
Definition desktop.h:50
Extension support.
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.
Definition gc-anchored.h:92
static R & release(R &r)
Decrements the reference count of a anchored object.
std::string profile_path()
Definition resource.cpp:415
std::string log_path(const char *filename)
Definition resource.cpp:508
FILE * fopen_utf8name(char const *utf8name, char const *mode)
Open a file with g_fopen().
Definition sys.cpp:72
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.
Definition pack.cpp:141
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 />.
STL namespace.
Helpers for using Gtk::Boxes, encapsulating large changes between GTK3 & GTK4.
Ocnode * child[8]
Definition quantize.cpp:33
C facade to Inkscape::XML::Node.
Inkscape::IO::Resource - simple resource API.
int index
Glib::ustring name
Definition toolbars.cpp:55
Base class for extension widgets.
Interface for XML nodes.