From 0cc1dab315c19bc951dae22fd4f1b8f07b4399b5 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Fri, 8 Sep 2023 00:43:44 +0200 Subject: [PATCH] Add no desktop to extensions --- share/ui/menus.ui | 2 + src/actions/actions-effect.cpp | 8 +- src/actions/actions-file.cpp | 2 +- src/actions/actions-tutorial.cpp | 2 +- src/extension/effect.cpp | 33 ++++++-- src/extension/effect.h | 13 ++-- src/extension/execution-env.cpp | 78 ++++++++++++------- src/extension/execution-env.h | 2 +- src/extension/extension.cpp | 19 +++-- src/extension/implementation/implementation.h | 3 +- src/extension/implementation/script.cpp | 49 +++++++----- src/extension/implementation/script.h | 2 +- src/extension/internal/bitmap/imagemagick.cpp | 31 +++++--- src/extension/internal/bitmap/imagemagick.h | 2 +- src/extension/internal/bluredge.cpp | 2 +- src/extension/internal/bluredge.h | 2 +- src/extension/internal/filter/filter.cpp | 2 +- src/extension/internal/filter/filter.h | 2 +- src/extension/internal/grid.cpp | 2 +- src/extension/internal/grid.h | 2 +- src/extension/plugins/grid2/grid.cpp | 2 +- src/extension/plugins/grid2/grid.h | 2 +- src/extension/prefdialog/prefdialog.cpp | 6 +- src/extension/prefdialog/prefdialog.h | 5 +- src/file.cpp | 6 +- src/inkscape-application.cpp | 72 +++++++++++++---- src/inkscape-application.h | 4 +- src/ui/desktop/menubar.cpp | 8 +- src/ui/interface.cpp | 4 +- src/util/action-accel.cpp | 2 +- 30 files changed, 245 insertions(+), 124 deletions(-) diff --git a/share/ui/menus.ui b/share/ui/menus.ui index 0dda0f0d02f..effadafc885 100644 --- a/share/ui/menus.ui +++ b/share/ui/menus.ui @@ -58,6 +58,7 @@ Import _Web Image... app.org.inkscape.import-web-image + document-import-web @@ -1215,6 +1216,7 @@ Manage Extensions... app.org.inkscape.extension.manager + diff --git a/src/actions/actions-effect.cpp b/src/actions/actions-effect.cpp index 6e5b2f8aa6f..a6a95c0fe60 100644 --- a/src/actions/actions-effect.cpp +++ b/src/actions/actions-effect.cpp @@ -37,9 +37,9 @@ last_effect(InkscapeApplication *app) if (effect == nullptr) { return; } - + std::list params = Inkscape::Extension::Effect::get_last_params(); // Last Effect - effect->effect(InkscapeApplication::instance()->get_active_desktop()); + effect->effect(InkscapeApplication::instance()->get_active_desktop(), params); } void @@ -50,9 +50,9 @@ last_effect_pref(InkscapeApplication *app) if (effect == nullptr) { return; } - + std::list params; // Last Effect Pref - effect->prefs(InkscapeApplication::instance()->get_active_desktop()); + effect->prefs(InkscapeApplication::instance()->get_active_desktop(), params); } void diff --git a/src/actions/actions-file.cpp b/src/actions/actions-file.cpp index a1254829da7..8bcddbbbfff 100644 --- a/src/actions/actions-file.cpp +++ b/src/actions/actions-file.cpp @@ -116,7 +116,7 @@ std::vector> hint_data_file = {"app.file-open", N_("Enter file name")}, {"app.file-new", N_("Enter file name")}, {"app.file-open-window", N_("Enter file name")}, - {"app.file-rebase-from-saved", N_("Namedview; Update=1, Replace=0")} + {"app.file-rebase", N_("Namedview; Update=1, Replace=0")} // clang-format on }; diff --git a/src/actions/actions-tutorial.cpp b/src/actions/actions-tutorial.cpp index 253ed70a18f..223926c67ee 100644 --- a/src/actions/actions-tutorial.cpp +++ b/src/actions/actions-tutorial.cpp @@ -36,7 +36,7 @@ void help_open_tutorial(Glib::ustring name) filename = Inkscape::IO::Resource::get_filename(Inkscape::IO::Resource::TUTORIALS, filename.c_str(), true); if (!filename.empty()) { - auto *app = InkscapeApplication::instance(); + auto app = InkscapeApplication::instance(); SPDocument* doc = app->document_new(filename); app->window_open(doc); } else { diff --git a/src/extension/effect.cpp b/src/extension/effect.cpp index 4181edeef3a..e94c52cdbc0 100644 --- a/src/extension/effect.cpp +++ b/src/extension/effect.cpp @@ -36,6 +36,7 @@ namespace Inkscape { namespace Extension { Effect * Effect::_last_effect = nullptr; +std::list Effect::_last_params; Effect::Effect (Inkscape::XML::Node *in_repr, Implementation::Implementation *in_imp, std::string *base_directory, std::string* file_name) : Extension(in_repr, in_imp, base_directory) @@ -105,7 +106,7 @@ Effect::Effect (Inkscape::XML::Node *in_repr, Implementation::Implementation *in /** Sanitizes the passed id in place. If an invalid character is found in the ID, a warning * is printed to stderr. All invalid characters are replaced with an 'X'. */ -void Effect::_sanitizeId(std::string &id) +void Effect::sanitizeId(std::string &id) { auto allowed = [] (char ch) { // Note: std::isalnum() is locale-dependent @@ -125,7 +126,7 @@ void Effect::_sanitizeId(std::string &id) if (!allowed(ch)) { if (!errored) { auto message = std::string{"Invalid extension action ID found: \""} + id + "\"."; - g_warn_message("Inkscape", __FILE__, __LINE__, "Effect::_sanitizeId()", message.c_str()); + g_warn_message("Inkscape", __FILE__, __LINE__, "Effect::sanitizeId()", message.c_str()); errored = true; } ch = 'X'; @@ -177,8 +178,11 @@ Effect::deactivate() Effect::~Effect () { - if (get_last_effect() == this) + if (get_last_effect() == this) { set_last_effect(nullptr); + std::list params; + set_last_params(params); + } if (_menu_node) { if (_menu_node->parent()) { _menu_node->parent()->removeChild(_menu_node); @@ -189,7 +193,7 @@ Effect::~Effect () } bool -Effect::prefs (SPDesktop * desktop) +Effect::prefs (SPDesktop * desktop, std::list ¶ms) { if (_prefDialog != nullptr) { _prefDialog->raise(); @@ -197,7 +201,7 @@ Effect::prefs (SPDesktop * desktop) } if (!widget_visible_count()) { - effect(desktop); + effect(desktop, params); return true; } @@ -223,7 +227,7 @@ Effect::prefs (SPDesktop * desktop) stack. */ void -Effect::effect (SPDesktop * desktop) +Effect::effect (SPDesktop * desktop, std::list ¶ms) { //printf("Execute effect\n"); if (!loaded()) @@ -232,7 +236,7 @@ Effect::effect (SPDesktop * desktop) ExecutionEnv executionEnv(this, desktop, nullptr, _workingDialog, true); execution_env = &executionEnv; timer->lock(); - executionEnv.run(); + executionEnv.run(params); if (executionEnv.wait()) { executionEnv.commit(); } else { @@ -259,6 +263,19 @@ Effect::set_last_effect (Effect * in_effect) return; } +/** \brief Sets which params was called last + \param in_effect + + This function sets the static variable \c _last_params + +*/ +void +Effect::set_last_params (std::list in_params) +{ + _last_params = in_params; + return; +} + Inkscape::XML::Node * Effect::find_menu (Inkscape::XML::Node * menustruct, const gchar *name) { @@ -355,7 +372,7 @@ const Glib::ustring& Effect::get_menu_tip() const { std::string Effect::get_sanitized_id() const { std::string id = get_id(); - _sanitizeId(id); + sanitizeId(id); return id; } diff --git a/src/extension/effect.h b/src/extension/effect.h index 82502aefc4c..d74c98c3172 100644 --- a/src/extension/effect.h +++ b/src/extension/effect.h @@ -40,7 +40,7 @@ class Effect : public Extension { /** \brief This is the last effect that was used. This is used in a menu item to rapidly recall the same effect. */ static Effect * _last_effect; - + static std::list _last_params; Inkscape::XML::Node *find_menu (Inkscape::XML::Node * menustruct, const gchar *name); void get_menu(Inkscape::XML::Node * pattern, std::list& sub_menu_list) const; @@ -54,8 +54,8 @@ public: Effect(Inkscape::XML::Node *in_repr, Implementation::Implementation *in_imp, std::string *base_directory, std::string* file_name); ~Effect () override; - bool prefs (SPDesktop * desktop); - void effect (SPDesktop * desktop); + bool prefs (SPDesktop * desktop, std::list ¶ms); + void effect (SPDesktop * desktop, std::list ¶ms); /** \brief Whether a working dialog should be shown */ bool _workingDialog = true; @@ -65,7 +65,10 @@ public: /** \brief Static function to get the last effect used */ static Effect * get_last_effect () { return _last_effect; }; + static std::list get_last_params () { return _last_params; }; + static void set_last_effect (Effect * in_effect); + static void set_last_params (std::list in_params); static void place_menus (); void place_menu (Inkscape::XML::Node * menus); @@ -105,7 +108,8 @@ public: // apply filter effect to 'item' bool apply_filter(SPItem* item); - + + static void sanitizeId(std::string &id); private: std::string _file_name; // extension file name, if provided bool _hidden_from_menu = false; @@ -115,7 +119,6 @@ private: std::string _icon_path; static gchar * remove_ (gchar * instr); - static void _sanitizeId(std::string &id); }; } } /* namespace Inkscape, Extension */ diff --git a/src/extension/execution-env.cpp b/src/extension/execution-env.cpp index 6320264396b..ee35d03389e 100644 --- a/src/extension/execution-env.cpp +++ b/src/extension/execution-env.cpp @@ -15,6 +15,8 @@ #include "execution-env.h" #include "prefdialog/prefdialog.h" #include "implementation/implementation.h" +#include "actions/actions-helper.h" +#include "inkscape-application.h" #include "selection.h" #include "effect.h" @@ -50,17 +52,15 @@ ExecutionEnv::ExecutionEnv (Effect * effect, SPDesktop * desktop, Implementation _effect(effect), _show_working(show_working) { - SPDocument *document = desktop->doc(); - if (document && desktop) { - // Temporarily prevent undo in this scope - Inkscape::DocumentUndo::ScopedInsensitive pauseUndo(document); - Inkscape::Selection *selection = desktop->getSelection(); - if (selection) { - // Make sure all selected objects have an ID attribute - selection->enforceIds(); - } + auto app = InkscapeApplication::instance(); + SPDocument* document = nullptr; + Inkscape::Selection* selection = nullptr; + if (!get_document_and_selection(app, &document, &selection)) { + std::cerr << "No selection or document" << std::endl; } - + // Temporarily prevent undo in this scope + Inkscape::DocumentUndo::ScopedInsensitive pauseUndo(document); + selection->enforceIds(); genDocCache(); return; @@ -115,6 +115,9 @@ ExecutionEnv::killDocCache () { */ void ExecutionEnv::createWorkingDialog () { + if (!_desktop) { + return; + } if (_visibleDialog != nullptr) { _visibleDialog->set_visible(false); delete _visibleDialog; @@ -159,20 +162,34 @@ ExecutionEnv::workingCanceled( const int /*resp*/) { void ExecutionEnv::cancel () { - _desktop->clearWaitingCursor(); + if (_desktop) { + _desktop->clearWaitingCursor(); + } _effect->get_imp()->cancelProcessing(); return; } void ExecutionEnv::undo () { - DocumentUndo::cancel(_desktop->doc()); + auto app = InkscapeApplication::instance(); + SPDocument* document = nullptr; + Inkscape::Selection* selection = nullptr; + if (!get_document_and_selection(app, &document, &selection)) { + std::cerr << "No selection or document" << std::endl; + } + DocumentUndo::cancel(document); return; } void ExecutionEnv::commit () { - DocumentUndo::done(_desktop->doc(), _effect->get_name(), ""); + auto app = InkscapeApplication::instance(); + SPDocument* document = nullptr; + Inkscape::Selection* selection = nullptr; + if (!get_document_and_selection(app, &document, &selection)) { + std::cerr << "No selection or document" << std::endl; + } + DocumentUndo::done(document, _effect->get_name(), ""); Effect::set_last_effect(_effect); _effect->get_imp()->commitDocument(); killDocCache(); @@ -181,27 +198,36 @@ ExecutionEnv::commit () { void ExecutionEnv::reselect () { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; // Why not use _desktop? - if (desktop) { - Inkscape::Selection *selection = desktop->getSelection(); - if (selection) { - selection->restoreBackup(); - } + auto app = InkscapeApplication::instance(); + SPDocument* document = nullptr; + Inkscape::Selection* selection = nullptr; + if (!get_document_and_selection(app, &document, &selection)) { + return; } - return; + selection->restoreBackup(); } void -ExecutionEnv::run () { +ExecutionEnv::run (std::list ¶ms) { _state = ExecutionEnv::RUNNING; - if (_show_working) { + auto app = InkscapeApplication::instance(); + SPDocument* document = nullptr; + Inkscape::Selection* selection = nullptr; + if (!get_document_and_selection(app, &document, &selection)) { + std::cerr << "No selection or document" << std::endl; + } + if (_desktop && _show_working) { createWorkingDialog(); } - Inkscape::Selection *selection = _desktop->getSelection(); selection->setBackup(); - _desktop->setWaitingCursor(); - _effect->get_imp()->effect(_effect, _desktop, _docCache); - _desktop->clearWaitingCursor(); + if (_desktop) { + _desktop->setWaitingCursor(); + } + _effect->get_imp()->effect(_effect, _desktop, _docCache, params); + Effect::set_last_params(params); + if (_desktop) { + _desktop->clearWaitingCursor(); + } _state = ExecutionEnv::COMPLETE; selection->restoreBackup(); // _runComplete.signal(); diff --git a/src/extension/execution-env.h b/src/extension/execution-env.h index ce56b0d3139..79921f21541 100644 --- a/src/extension/execution-env.h +++ b/src/extension/execution-env.h @@ -77,7 +77,7 @@ public: /** \brief Starts the execution of the effect \return Returns whether the effect was executed to completion */ - void run (); + void run (std::list ¶ms); /** \brief Cancel the execution of the effect */ void cancel (); /** \brief Commit the changes to the document */ diff --git a/src/extension/extension.cpp b/src/extension/extension.cpp index 577b56cc63c..db2f70be7bf 100644 --- a/src/extension/extension.cpp +++ b/src/extension/extension.cpp @@ -631,12 +631,21 @@ Extension::paramListString (std::list &retlist) if (parameter) { const char *name = parameter->name(); std::string value = parameter->value_to_string(); - + std::string parameter_string; + parameter_string += "--"; + parameter_string += name; + parameter_string += "="; + bool continueit = false; + for(auto parm : retlist) { + if (!parm.find(parameter_string)) { + continueit = true; + break; + } + } + if (continueit) { + continue; + } if (name && !value.empty()) { // TODO: Shouldn't empty string values be allowed? - std::string parameter_string; - parameter_string += "--"; - parameter_string += name; - parameter_string += "="; parameter_string += value; retlist.push_back(parameter_string); } diff --git a/src/extension/implementation/implementation.h b/src/extension/implementation/implementation.h index da9f4ca3c04..92d939b00fe 100644 --- a/src/extension/implementation/implementation.h +++ b/src/extension/implementation/implementation.h @@ -126,7 +126,8 @@ public: ImplementationDocumentCache *docCache); virtual void effect(Inkscape::Extension::Effect * /*module*/, SPDesktop * /*desktop*/, - ImplementationDocumentCache * /*docCache*/) {} + ImplementationDocumentCache * /*docCache*/, + std::list &/*params*/) {} virtual bool apply_filter(Inkscape::Extension::Effect* module, SPItem* item) { return false; } // ----- Print functions ----- diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index 5abc7f2f73e..a5cb8986140 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -27,6 +27,7 @@ #include #include "desktop.h" +#include "inkscape-application.h" #include "extension/db.h" #include "extension/effect.h" #include "extension/execution-env.h" @@ -39,6 +40,7 @@ #include "inkscape.h" #include "io/resource.h" #include "io/file.h" +#include "actions/actions-helper.h" #include "layer-manager.h" #include "object/sp-namedview.h" #include "object/sp-page.h" @@ -532,23 +534,30 @@ void Script::export_raster(Inkscape::Extension::Output *module, */ void Script::effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, - ImplementationDocumentCache * docCache) + ImplementationDocumentCache * docCache, + std::list ¶ms) { - if (desktop == nullptr) - { - g_warning("Script::effect: Desktop not defined"); + auto app = InkscapeApplication::instance(); + SPDocument* document = nullptr; + Inkscape::Selection* selection = nullptr; + if (!get_document_and_selection(app, &document, &selection)) { + std::cerr << "Need selection and document" << std::endl; return; } - - sp_namedview_document_from_window(desktop); + if (params.empty()) { + params = selection->params; + } + selection->clear(); + //this store things related to desktop in cuurent document + if (desktop) { + sp_namedview_document_from_window(desktop); + } if (module->no_doc) { // this is a no-doc extension, e.g. a Help menu command; // just run the command without any files, ignoring errors - std::list params; - module->paramListString(params); - module->set_environment(desktop->getDocument()); + module->set_environment(document); Glib::ustring empty; file_listener outfile; @@ -557,23 +566,14 @@ void Script::effect(Inkscape::Extension::Effect *module, // Hack to allow for extension manager to reload extensions // TODO: Find a better way to do this, e.g. implement an action and have extensions (or users) // call that instead when there's a change that requires extensions to reload - if (!g_strcmp0(module->get_id(), "org.inkscape.extension.manager")) { + if (desktop && !g_strcmp0(module->get_id(), "org.inkscape.extension.manager")) { Inkscape::Extension::refresh_user_extensions(); build_menu(); // Rebuild main menubar. } return; } - - std::list params; - if (desktop) { - Inkscape::Selection * selection = desktop->getSelection(); - if (selection) { - params = selection->params; - selection->clear(); - } - } - _change_extension(module, desktop->getDocument(), params, module->ignore_stderr); + _change_extension(module, document, params, module->ignore_stderr); } //uncomment if issues on ref extensions links @@ -614,9 +614,9 @@ void Script::effect(Inkscape::Extension::Effect *module, */ void Script::_change_extension(Inkscape::Extension::Extension *module, SPDocument *doc, std::list ¶ms, bool ignore_stderr) { + module->paramListString(params); module->set_environment(doc); - if (auto env = module->get_execution_env()) { parent_window = env->get_working_dialog(); } @@ -638,6 +638,13 @@ void Script::_change_extension(Inkscape::Extension::Extension *module, SPDocumen if (data_read == 0) { return; } + if (!SP_ACTIVE_DESKTOP && doc->getDocumentFilename()) { + Glib::ustring fn = g_strdup(doc->getDocumentFilename()); + fileout.toFile(fn); + return; + } else if (!SP_ACTIVE_DESKTOP) { + Inkscape::UI::gui_warning(_("Couldent save documen woithout file."), parent_window); + } fileout.toFile(tempfile_out.get_filename()); pump_events(); diff --git a/src/extension/implementation/script.h b/src/extension/implementation/script.h index 813891e9f82..6bc2d7edfc1 100644 --- a/src/extension/implementation/script.h +++ b/src/extension/implementation/script.h @@ -63,7 +63,7 @@ public: void save(Inkscape::Extension::Output *module, SPDocument *doc, gchar const *filename) override; void export_raster(Inkscape::Extension::Output *module, const SPDocument *doc, std::string const &png_file, gchar const *filename) override; - void effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, ImplementationDocumentCache * docCache) override; + void effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, ImplementationDocumentCache * docCache, std::list ¶ms) override; bool cancelProcessing () override; private: diff --git a/src/extension/internal/bitmap/imagemagick.cpp b/src/extension/internal/bitmap/imagemagick.cpp index 96571dc6bb4..0b66c30e9d3 100644 --- a/src/extension/internal/bitmap/imagemagick.cpp +++ b/src/extension/internal/bitmap/imagemagick.cpp @@ -18,9 +18,10 @@ #include #include "desktop.h" - +#include "inkscape-application.h" #include "selection.h" +#include "actions/actions-helper.h" #include "extension/effect.h" #include "extension/system.h" @@ -62,7 +63,13 @@ ImageMagickDocCache::ImageMagickDocCache(SPDesktop *desktop) : _originals(NULL), _imageItems(NULL) { - auto selectedItemList = desktop->getSelection()->items(); + auto app = InkscapeApplication::instance(); + SPDocument* document = nullptr; + Inkscape::Selection* selection = nullptr; + if (!get_document_and_selection(app, &document, &selection)) { + std::cerr << "No selection or document" << std::endl; + } + auto selectedItemList = selection->items(); int selectCount = (int) boost::distance(selectedItemList); // Init the data-holders @@ -154,7 +161,7 @@ ImageMagick::newDocCache (Inkscape::Extension::Extension * /*ext*/, SPDesktop *d } void -ImageMagick::effect (Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache) +ImageMagick::effect (Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache, std::list ¶ms) { refreshParameters(module); @@ -235,14 +242,18 @@ ImageMagick::effect (Inkscape::Extension::Effect *module, SPDesktop *desktop, In Gtk::Widget * ImageMagick::prefs_effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, sigc::signal * changeSignal, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/) { - SPDocument * current_document = desktop->doc(); - - auto selected = desktop->getSelection()->items(); - Inkscape::XML::Node * first_select = NULL; - if (!selected.empty()) { + auto app = InkscapeApplication::instance(); + SPDocument* current_document = nullptr; + Inkscape::Selection* selection = nullptr; + if (!get_document_and_selection(app, ¤t_document, &selection)) { + std::cerr << "No selection or document" << std::endl; + } + auto selected = selection->items(); + Inkscape::XML::Node * first_select = NULL; + if (!selected.empty()) { first_select = (selected.front())->getRepr(); - } - return module->autogui(current_document, first_select, changeSignal); + } + return module->autogui(current_document, first_select, changeSignal); } }; /* namespace Bitmap */ diff --git a/src/extension/internal/bitmap/imagemagick.h b/src/extension/internal/bitmap/imagemagick.h index f8cee57c51f..19850716a9e 100644 --- a/src/extension/internal/bitmap/imagemagick.h +++ b/src/extension/internal/bitmap/imagemagick.h @@ -37,7 +37,7 @@ public: /* Functions implemented from ::Implementation */ bool load(Inkscape::Extension::Extension *module) override; Inkscape::Extension::Implementation::ImplementationDocumentCache * newDocCache (Inkscape::Extension::Extension * ext, SPDesktop * desktop) override; - void effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache) override; + void effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache, std::list ¶ms) override; Gtk::Widget* prefs_effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, sigc::signal * changeSignal, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache) override; }; diff --git a/src/extension/internal/bluredge.cpp b/src/extension/internal/bluredge.cpp index 2734b380d56..b5b8e7ad21a 100644 --- a/src/extension/internal/bluredge.cpp +++ b/src/extension/internal/bluredge.cpp @@ -52,7 +52,7 @@ BlurEdge::load (Inkscape::Extension::Extension */*module*/) \param desktop What should be edited. */ void -BlurEdge::effect (Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/) +BlurEdge::effect (Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/, std::list &/*params*/) { Inkscape::Selection * selection = desktop->getSelection(); diff --git a/src/extension/internal/bluredge.h b/src/extension/internal/bluredge.h index d01a02acd3b..0189d87148e 100644 --- a/src/extension/internal/bluredge.h +++ b/src/extension/internal/bluredge.h @@ -25,7 +25,7 @@ class BlurEdge : public Inkscape::Extension::Implementation::Implementation { public: bool load(Inkscape::Extension::Extension *module) override; - void effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache) override; + void effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache, std::list ¶ms) override; Gtk::Widget * prefs_effect(Inkscape::Extension::Effect * module, SPDesktop *desktop, sigc::signal * changeSignal, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache) override; static void init (); diff --git a/src/extension/internal/filter/filter.cpp b/src/extension/internal/filter/filter.cpp index 211fd10e226..63a6b9e2b7c 100644 --- a/src/extension/internal/filter/filter.cpp +++ b/src/extension/internal/filter/filter.cpp @@ -132,7 +132,7 @@ void create_and_apply_filter(SPItem* item, Inkscape::XML::Document* filterdoc) { #define FILTER_SRC_GRAPHIC_ALPHA "fbSourceGraphicAlpha" void Filter::effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, - Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/) + Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/, std::list &/*params*/) { Inkscape::XML::Document *filterdoc = get_filter(module); if (filterdoc == nullptr) { diff --git a/src/extension/internal/filter/filter.h b/src/extension/internal/filter/filter.h index 57b8af75bc0..8f146f6fba8 100644 --- a/src/extension/internal/filter/filter.h +++ b/src/extension/internal/filter/filter.h @@ -43,7 +43,7 @@ public: bool load(Inkscape::Extension::Extension *module) override; Inkscape::Extension::Implementation::ImplementationDocumentCache * newDocCache (Inkscape::Extension::Extension * ext, SPDesktop * desktop) override; - void effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache) override; + void effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache, std::list ¶ms) override; static void filter_init(gchar const * id, gchar const * name, gchar const * submenu, gchar const * tip, gchar const * filter); static void filters_all(); diff --git a/src/extension/internal/grid.cpp b/src/extension/internal/grid.cpp index ca710d7629b..c5ad3e9f4e5 100644 --- a/src/extension/internal/grid.cpp +++ b/src/extension/internal/grid.cpp @@ -82,7 +82,7 @@ Glib::ustring build_lines(Geom::Rect bounding_area, \param document What should be edited. */ void -Grid::effect (Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/) +Grid::effect (Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/, std::list &/*params*/) { Inkscape::Selection *selection = desktop->getSelection(); SPDocument *doc = desktop->doc(); diff --git a/src/extension/internal/grid.h b/src/extension/internal/grid.h index c2641d6560c..a79d17cfc27 100644 --- a/src/extension/internal/grid.h +++ b/src/extension/internal/grid.h @@ -24,7 +24,7 @@ class Grid : public Inkscape::Extension::Implementation::Implementation { public: bool load(Inkscape::Extension::Extension *module) override; - void effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache) override; + void effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache, std::list ¶ms) override; Gtk::Widget * prefs_effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, sigc::signal * changeSignal, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache) override; static void init (); diff --git a/src/extension/plugins/grid2/grid.cpp b/src/extension/plugins/grid2/grid.cpp index cb2cf1d5013..47e22510798 100644 --- a/src/extension/plugins/grid2/grid.cpp +++ b/src/extension/plugins/grid2/grid.cpp @@ -87,7 +87,7 @@ Glib::ustring build_lines(Geom::Rect bounding_area, \param document What should be edited. */ void -Grid::effect (Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/) +Grid::effect (Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/, std::list &/*params*/) { std::cerr << "Executing effect" << std::endl; diff --git a/src/extension/plugins/grid2/grid.h b/src/extension/plugins/grid2/grid.h index e17b136c5b6..c36c6fff531 100644 --- a/src/extension/plugins/grid2/grid.h +++ b/src/extension/plugins/grid2/grid.h @@ -36,7 +36,7 @@ class Grid : public Inkscape::Extension::Implementation::Implementation { public: bool load(Inkscape::Extension::Extension *module) override; void effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache) override; - Gtk::Widget * prefs_effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, sigc::signal * changeSignal, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache) override; + Gtk::Widget * prefs_effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, sigc::signal * changeSignal, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache, std::list ¶ms) override; }; diff --git a/src/extension/prefdialog/prefdialog.cpp b/src/extension/prefdialog/prefdialog.cpp index e4f23a1f27b..77a20e4f69c 100644 --- a/src/extension/prefdialog/prefdialog.cpp +++ b/src/extension/prefdialog/prefdialog.cpp @@ -135,7 +135,7 @@ PrefDialog::preview_toggle () { _exEnv = std::make_unique(_effect, SP_ACTIVE_DESKTOP, nullptr, false, false); _effect->set_execution_env(_exEnv.get()); - _exEnv->run(); + _exEnv->run(_params); } } else { set_modal(false); @@ -175,7 +175,7 @@ PrefDialog::param_timer_expire () { _exEnv->cancel(); _exEnv->undo(); _exEnv->reselect(); - _exEnv->run(); + _exEnv->run(_params); } return false; @@ -186,7 +186,7 @@ PrefDialog::on_response (int signal) { if (signal == Gtk::RESPONSE_OK) { if (_exEnv == nullptr) { if (_effect != nullptr) { - _effect->effect(SP_ACTIVE_DESKTOP); + _effect->effect(SP_ACTIVE_DESKTOP,_params); } else { // Shutdown run() return; diff --git a/src/extension/prefdialog/prefdialog.h b/src/extension/prefdialog/prefdialog.h index f96765b38f8..2f8f9b3b3f9 100644 --- a/src/extension/prefdialog/prefdialog.h +++ b/src/extension/prefdialog/prefdialog.h @@ -41,7 +41,7 @@ class PrefDialog : public Gtk::Dialog { Gtk::Widget *_button_preview; /** \brief Checkbox for the preview */ Gtk::CheckButton *_checkbox_preview; - + /** \brief Parameter to control live preview */ std::unique_ptr _param_preview; @@ -64,7 +64,8 @@ class PrefDialog : public Gtk::Dialog { /** \brief The timer used to make it so that parameters don't respond directly and allows for changes. */ sigc::connection _timersig; - + /* Empty param needed to RUN */ + std::list _params; void preview_toggle(); void param_change(); bool param_timer_expire(); diff --git a/src/file.cpp b/src/file.cpp index fc4f39661c8..4feb62d1016 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -105,7 +105,7 @@ void dump_ustr(Glib::ustring const &ustr); */ SPDesktop *sp_file_new(const std::string &templ) { - auto *app = InkscapeApplication::instance(); + auto app = InkscapeApplication::instance(); SPDocument* doc = app->document_new (templ); if (!doc) { @@ -187,7 +187,7 @@ void sp_file_revert_dialog() bool reverted = false; if (do_revert) { - auto *app = InkscapeApplication::instance(); + auto app = InkscapeApplication::instance(); reverted = app->document_revert (doc); } @@ -373,7 +373,7 @@ sp_file_open_dialog(Gtk::Window &parentWindow, gpointer /*object*/, gpointer /*d delete openDialogInstance; openDialogInstance = nullptr; - auto *app = InkscapeApplication::instance(); + auto app = InkscapeApplication::instance(); //# Iterate through filenames if more than 1 if (flist.size() > 1) diff --git a/src/inkscape-application.cpp b/src/inkscape-application.cpp index 03c21847872..56c3edd7eaa 100644 --- a/src/inkscape-application.cpp +++ b/src/inkscape-application.cpp @@ -75,6 +75,8 @@ #include "extension/init.h" #include "extension/db.h" #include "extension/effect.h" +#include "extension/implementation/script.h" + #include "io/file.h" // File open (command line). #include "io/resource.h" // TEMPLATE #include "io/fix-broken-links.h" // Fix up references. @@ -1104,7 +1106,7 @@ InkscapeApplication::on_activate() process_document (document, output); if (_batch_process) { - // If with_gui, we've reused a window for each file. We must quit to destroy it. + // If _with_gui, we've reused a window for each file. We must quit to destroy it. gio_app()->quit(); } } @@ -1158,7 +1160,7 @@ InkscapeApplication::on_open(const Gio::Application::type_vec_files& files, cons } if (_batch_process) { - // If with_gui, we've reused a window for each file. We must quit to destroy it. + // If _with_gui, we've reused a window for each file. We must quit to destroy it. gio_app()->quit(); } } @@ -1186,6 +1188,10 @@ InkscapeApplication::parse_actions(const Glib::ustring& input, action_vector_t& } Glib::RefPtr action_ptr = _gio_application->lookup_action(action); + if (!action_ptr) { + Inkscape::Extension::Effect::sanitizeId(action); + action_ptr = _gio_application->lookup_action(action); + } if (action_ptr) { // Doesn't seem to be a way to test this using the C++ binding without Glib-CRITICAL errors. const GVariantType* gtype = g_action_get_parameter_type(action_ptr->gobj()); @@ -1254,7 +1260,7 @@ char* readline_generator (const char* text, int state) // Fill the vector of action names. if (actions.size() == 0) { - auto *app = InkscapeApplication::instance(); + auto app = InkscapeApplication::instance(); actions = app->gio_app()->list_actions(); std::sort(actions.begin(), actions.end()); } @@ -1566,7 +1572,9 @@ InkscapeApplication::on_handle_local_options(const Glib::RefPtrcontains("with-gui")) { + std::cout << "Now can run any extension without need --with-gui parameter" << std::endl; + } if (options->contains("with-gui") || options->contains("batch-process") ) { @@ -1798,8 +1806,11 @@ InkscapeApplication::on_handle_local_options(const Glib::RefPtrgetBool("/options/dithering/value", true); - if (use_active_window) { + // Extensions + Inkscape::Extension::init(); + // After extensions are loaded query effects to construct action data + init_extension_action_data(); _gio_application->register_application(); if (!_gio_application->get_default()->is_remote()) { #ifdef __APPLE__ @@ -1895,12 +1906,40 @@ int InkscapeApplication::get_number_of_windows() const { * \c effect is Filter or Extension * \c show_prefs is used to show preferences dialog */ -void action_effect(Inkscape::Extension::Effect* effect, bool show_prefs) { - auto desktop = InkscapeApplication::instance()->get_active_desktop(); - if (effect->_workingDialog && show_prefs) { - effect->prefs(desktop); +void action_effect(const Glib::VariantBase& value, Inkscape::Extension::Effect* effect, bool show_prefs, InkscapeApplication *app) { + Glib::Variant s = Glib::VariantBase::cast_dynamic >(value); + Glib::ustring paramstr = s.get(); + SPDesktop *desktop = InkscapeApplication::instance()->get_active_desktop(); + std::list params; + /* + / This mimic previous behabiour when gui + / if we want run from command line with --with-gui and no show dialog + / on extensions, one way is create a bool member variable that store "with-gui" + / command and use as a extra parameter to this function. + / other approach is use a param in the extension + */ + size_t pos = paramstr.find("--no-ext-dialog"); + bool no_ext_dialog = false; + if (pos != std::string::npos) { + no_ext_dialog = true; + paramstr.erase(pos,15); + } + if (!app->get_with_gui() || no_ext_dialog) { + desktop = nullptr; + std::stringstream ss(paramstr); + std::string p; + while (getline (ss, p, ' ')) { + p.erase(p.find_last_not_of(' ')+1); + p.erase(0, p.find_first_not_of(' ')); + if (!p.empty()) { + params.push_back(p); + } + } + } + if (effect->_workingDialog && show_prefs && desktop) { + effect->prefs(desktop, params); } else { - effect->effect(desktop); + effect->effect(desktop, params); } } @@ -1920,11 +1959,10 @@ void InkscapeApplication::init_extension_action_data() { std::string aid = effect->get_sanitized_id(); std::string action_id = "app." + aid; - - auto app = this; + Glib::VariantType String(Glib::VARIANT_TYPE_STRING); if (auto gapp = gtk_app()) { - auto action = gapp->add_action(aid, [effect](){ action_effect(effect, true); }); - auto action_noprefs = gapp->add_action(aid + ".noprefs", [effect](){ action_effect(effect, false); }); + auto action = gapp->add_action_with_parameter(aid, String,sigc::bind(sigc::ptr_fun(&action_effect), effect, true, this)); + auto action_noprefs = gapp->add_action_with_parameter(aid + ".noprefs", String,sigc::bind(sigc::ptr_fun(&action_effect), effect, false, this)); _effect_actions.emplace_back(action); _effect_actions.emplace_back(action_noprefs); } @@ -1942,12 +1980,12 @@ void InkscapeApplication::init_extension_action_data() { std::vector>raw_data_filter = {{ action_id, effect->get_name(), "Filters", description }, { action_id + ".noprefs", Glib::ustring(effect->get_name()) + " " + _("(No preferences)"), "Filters (no prefs)", description }}; - app->get_action_extra_data().add_data(raw_data_filter); + get_action_extra_data().add_data(raw_data_filter); } else { std::vector>raw_data_effect = {{ action_id, effect->get_name(), "Extensions", description }, { action_id + ".noprefs", Glib::ustring(effect->get_name()) + " " + _("(No preferences)"), "Extensions (no prefs)", description }}; - app->get_action_extra_data().add_data(raw_data_effect); + get_action_extra_data().add_data(raw_data_effect); } #if false // enable to see all the loaded effects @@ -1965,7 +2003,7 @@ void InkscapeApplication::init_extension_action_data() { gchar *ellipsized_name = effect->takes_input() ? g_strdup_printf(_("%s..."), effect->get_name()) : nullptr; Glib::ustring menu_name = ellipsized_name ? ellipsized_name : effect->get_name(); bool is_filter = effect->is_filter_effect(); - app->get_action_effect_data().add_data(aid, is_filter, sub_menu_list, menu_name); + get_action_effect_data().add_data(aid, is_filter, sub_menu_list, menu_name); g_free(ellipsized_name); } } diff --git a/src/inkscape-application.h b/src/inkscape-application.h index 46317b38a27..768f994b62f 100644 --- a/src/inkscape-application.h +++ b/src/inkscape-application.h @@ -87,7 +87,7 @@ public: // This will replace _active_desktop. InkscapeWindow* get_active_window() { return _active_window; } void set_active_window(InkscapeWindow* window) { _active_window = window; } - + bool get_with_gui() const { return _with_gui; } /****** Document ******/ /* These should not require a GUI! */ void document_add(SPDocument* document); @@ -131,7 +131,7 @@ public: // void unreference() { /*printf("unreference()\n");*/ } int get_number_of_windows() const; - + protected: bool _with_gui = true; bool _batch_process = false; // Temp diff --git a/src/ui/desktop/menubar.cpp b/src/ui/desktop/menubar.cpp index d278d775d98..5d52d8bc8b4 100644 --- a/src/ui/desktop/menubar.cpp +++ b/src/ui/desktop/menubar.cpp @@ -122,7 +122,13 @@ build_menu() current_menu = it->second; } - current_menu->append(entry.effect_name, "app." + entry.effect_id); + auto item { Gio::MenuItem::create(std::move(entry.effect_name), Glib::ustring()) }; + // we need empty target on filters and extensions to run from menu (no params) + auto target { Glib::Variant::create("") }; + // note: setting action and target separately rather than using convenience menu method append + // since some filename characters can result in invalid "direct action" string + item->set_action_and_target(Glib::ustring("app." + entry.effect_id), target); + current_menu->append_item(item); } } diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp index 9edaeac3314..aae17312bc5 100644 --- a/src/ui/interface.cpp +++ b/src/ui/interface.cpp @@ -52,7 +52,7 @@ sp_ui_new_view() document = SP_ACTIVE_DOCUMENT; if (!document) return; - auto *app = InkscapeApplication::instance(); + auto app = InkscapeApplication::instance(); app->window_open(document); } @@ -60,7 +60,7 @@ sp_ui_new_view() void sp_ui_close_view(GtkWidget */*widget*/) { - auto *app = InkscapeApplication::instance(); + auto app = InkscapeApplication::instance(); auto window = app->get_active_window(); assert(window); diff --git a/src/util/action-accel.cpp b/src/util/action-accel.cpp index 9d03404594b..911bacbab5e 100644 --- a/src/util/action-accel.cpp +++ b/src/util/action-accel.cpp @@ -41,7 +41,7 @@ void ActionAccel::_onShortcutsModified() bool ActionAccel::_query() { - auto *app = InkscapeApplication::instance(); + auto app = InkscapeApplication::instance(); if (!app) { g_warn_message("Inkscape", __FILE__, __LINE__, __func__, "Attempt to read keyboard shortcuts while running without an InkscapeApplication!"); -- GitLab