Inkscape
Vector Graphics Editor
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
173Extension::~Extension()
174{
176}
177
189void
190Extension::set_state (state_t in_state)
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
225Extension::get_state ()
226{
227 return _state;
228}
229
234bool
235Extension::loaded ()
236{
237 return get_state() == STATE_LOADED;
238}
239
256bool
257Extension::check ()
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
306Extension::get_repr ()
307{
308 return repr;
309}
310
315char const *
317{
318 return _id.c_str();
319}
320
325char const *
326Extension::get_name () const
327{
328 return get_translation(_name.c_str(), nullptr);
329}
330
346void
347Extension::deactivate ()
348{
350
351 /* Removing the old implementation, and making this use the default. */
352 /* This should save some memory */
354}
355
360bool
361Extension::deactivated ()
362{
363 return get_state() == STATE_DEACTIVATED;
364}
365
379std::string Extension::get_dependency_location(char const *name)
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
424void Extension::lookup_translation_catalog() {
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
522void Extension::set_environment(const SPDocument *doc) {
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
553ModuleImpType Extension::get_implementation_type()
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
597InxParameter *Extension::get_param(char const *name)
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
634Extension::get_param_bool(char const *name) const
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
662Extension::get_param_int(char const *name) const
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
690Extension::get_param_float(char const *name) const
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 *
718Extension::get_param_string(char const *name) 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 *
746Extension::get_param_optiongroup(char const *name) 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 {
760 return get_param_optiongroup(name);
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
787std::uint32_t
788Extension::get_param_color(char const *name) const
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
883std::uint32_t
884Extension::set_param_color(char const *name, const std::uint32_t color)
885{
886 InxParameter *param;
887 param = get_param(name);
888 return 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
908Extension::error_file_open ()
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
919Extension::error_file_close ()
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 *
1003Extension::get_info_widget()
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 *
1036Extension::get_params_widget()
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
1044unsigned int Extension::widget_visible_count() const
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
1061bool Extension::prefs()
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
1085void Extension::run_processing_actions(SPDocument *doc)
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:219
no valid name found while parsing XML representation
Definition: extension.h:222
extension is not compatible with the current system and should not be loaded
Definition: extension.h:225
No implementation could be loaded for the extension.
Definition: extension.h:228
An error class for when a parameter is looked for that just simply doesn't exist.
Definition: extension.h:216
The object that is the basis for the Extension system.
Definition: extension.h:130
state_t get_state()
A getter for the state variable.
Definition: extension.cpp:225
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.
Definition: extension.cpp:757
std::string _name
A user friendly name for the Extension.
Definition: extension.h:142
int get_param_int(char const *name) const
Gets a parameter identified by name with the integer placed in value.
Definition: extension.cpp:662
char const * get_translation(char const *msgid, char const *msgctxt=nullptr) const
Gets a translation within the context of the current extension.
Definition: extension.cpp:498
static void error_file_write(Glib::ustring const &text)
A function to write to the error log file.
Definition: extension.cpp:928
std::unique_ptr< ExpirationTimer > timer
Timeout to unload after a given time.
Definition: extension.h:164
std::string _error_reason
Short, textual explanation for the latest error.
Definition: extension.h:147
state_t
An enumeration to identify if the Extension has been loaded or not.
Definition: extension.h:133
@ STATE_LOADED
The extension has been loaded successfully.
Definition: extension.h:134
@ STATE_DEACTIVATED
The extension is missing something which makes it unusable.
Definition: extension.h:136
@ STATE_UNLOADED
The extension has not been loaded.
Definition: extension.h:135
unsigned int widget_visible_count() const
A function to get the number of visible parameters of the extension.
Definition: extension.cpp:1044
char const * get_name() const
Get the name of this extension - not a copy don't delete!
Definition: extension.cpp:326
double get_param_float(char const *name) const
Gets a float parameter identified by name with the double placed in value.
Definition: extension.cpp:690
Inkscape::XML::Node * repr
The XML description of the Extension.
Definition: extension.h:153
std::string _id
The unique identifier for the Extension.
Definition: extension.h:141
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.
Definition: extension.cpp:975
std::vector< std::unique_ptr< Dependency > > _deps
Dependencies for this extension.
Definition: extension.h:145
ImplementationHolder imp
An Implementation object provides the actual implementation of the Extension.
Definition: extension.h:159
std::vector< std::unique_ptr< InxWidget > > _widgets
A list of widgets for this extension.
Definition: extension.h:207
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.
Definition: extension.cpp:729
void set_state(state_t in_state)
A function to set whether the extension should be loaded or unloaded.
Definition: extension.cpp:190
bool _translation_enabled
Attempt translation of strings provided by the extension?
Definition: extension.h:165
static void add_val(Glib::ustring const &labelstr, Glib::ustring const &valuestr, Gtk::Grid *table, int *row)
Definition: extension.cpp:1024
std::vector< ProcessingAction > _actions
Processing actions.
Definition: extension.h:150
bool loaded()
A quick function to test the state of the extension.
Definition: extension.cpp:235
std::string _base_directory
Directory containing the .inx file, relative paths in the extension should usually be relative to it.
Definition: extension.h:162
char const * _translationdomain
Domainname of gettext textdomain that should be used for translation of the extension's strings.
Definition: extension.h:168
void printFailure(Glib::ustring const &reason)
A quick function to print out a standard start of extension errors in the log.
Definition: extension.cpp:295
bool get_param_bool(char const *name) const
Gets a parameter identified by name with the bool placed in value.
Definition: extension.cpp:634
std::string _gettext_catalog_dir
Directory containing the gettext catalog for _translationdomain.
Definition: extension.h:170
state_t _state
Which state the Extension is currently in.
Definition: extension.h:143
void lookup_translation_catalog()
Searches for a gettext catalog matching the extension's translationdomain.
Definition: extension.cpp:424
InxParameter * get_param(char const *name)
Looks up the parameter with the specified name.
Definition: extension.cpp:597
Util::HybridPointer< Implementation::Implementation > ImplementationHolder
Definition: extension.h:138
static FILE * error_file
This is the place where errors get reported.
Definition: extension.h:146
Utility class used for loading and launching script extensions.
Definition: script.h:50
A class to represent the parameter of an extension.
Definition: parameter.h:34
bool get_bool() const
Wrapper to cast to the object and use its function.
Definition: parameter.cpp:110
double set_float(double in)
Wrapper to cast to the object and use it's function.
Definition: parameter.cpp:191
const char * get_optiongroup() const
Wrapper to cast to the object and use it's function.
Definition: parameter.cpp:148
unsigned int set_color(unsigned int in)
Wrapper to cast to the object and use it's function.
Definition: parameter.cpp:217
bool get_optiongroup_contains(const char *value) const
Definition: parameter.cpp:157
unsigned int get_color() const
Wrapper to cast to the object and use it's function.
Definition: parameter.cpp:166
virtual const std::string & set(const std::string &in)
Calls string_to_value and then saves the result in the prefs.
Definition: parameter.cpp:301
const char * set_optiongroup(const char *in)
Wrapper to cast to the object and use it's function.
Definition: parameter.cpp:208
virtual std::string value_to_string() const
Gets the current value of the parameter in a string form.
Definition: parameter.cpp:286
int set_int(int in)
Wrapper to cast to the object and use it's function.
Definition: parameter.cpp:183
const char * get_string() const
Wrapper to cast to the object and use it's function.
Definition: parameter.cpp:139
double get_float() const
Wrapper to cast to the object and use it's function.
Definition: parameter.cpp:130
char const * name() const
Definition: parameter.h:78
const char * set_string(const char *in)
Wrapper to cast to the object and use it's function.
Definition: parameter.cpp:200
int get_int() const
Wrapper to cast to the object and use it's function.
Definition: parameter.cpp:119
bool set_bool(bool in)
Wrapper to cast to the object and use it's function.
Definition: parameter.cpp:175
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
NonOwningPtr get() const
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:106
char const * getDocumentFilename() const
Definition: document.h:234
Parameters for extensions.
Inkscape::Extension::Extension: Frontend to certain, possibly pluggable, actions.
ModuleImpType
Definition: extension.h:85
@ MODULE_PLUGIN
Definition: extension.h:88
@ MODULE_EXTENSION
Definition: extension.h:86
@ MODULE_XSLT
Definition: extension.h:87
Inkscape::XML::Node * node
Definition: imagemagick.cpp:39
D2< T > compose(D2< T > const &a, T const &b)
Definition: d2.h:405
Definition: desktop.h:51
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
Definition: extension.cpp:391
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.
Definition: gc-anchored.h:133
std::string profile_path(const char *filename)
Get, or guess, or decide the location where the preferences.xml file should be located.
Definition: resource.cpp:404
std::string log_path(const char *filename)
Definition: resource.cpp:505
bool file_test(char const *utf8name, GFileTest test)
Definition: sys.cpp:109
FILE * fopen_utf8name(char const *utf8name, char const *mode)
Definition: sys.cpp:65
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.
Definition: dialog-run.cpp:13
@ ELEMENT_NODE
Regular element node, e.g. <group />.
STL namespace.
@ VERTICAL
The y-dimension (1).
Definition: rectangle.h:47
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.
Base class for extension widgets.
Interface for XML nodes.