diff --git a/share/ui/menus.ui b/share/ui/menus.ui index 0dda0f0d02f2ea92be08419e9f86609af749ebc8..effadafc885fc9cd0cda7a729f850ff21cb3ab7a 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 6e5b2f8aa6f280fa7b24013d2b07f82262c9ee16..a6a95c0fe60b2958eceb31cab94766f3e85c6ca3 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 a1254829da7c69f785b6d723f667711761d78387..8bcddbbbfff102a743fc74712700e7505dc1ed7a 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 253ed70a18facd8db020e5f6044a5394bd6a9b6e..223926c67eeb2842dde0ae4e68d040766ccbc97b 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 4181edeef3a361fb44284c87542dde25d7863b8e..e94c52cdbc0fea73ad2f68aad0abcef93dad1e3d 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 82502aefc4cd7766d4e1d28d2aa635d8ca28600d..d74c98c3172ee34c3025e4f54cfff7b8202242b6 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 6320264396bc59ce989a85b4e124e7ff3489f19b..ee35d03389e62ef8b71d52431a9355db460a5805 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 ce56b0d3139971c010fcb7eae31aadf1571458d7..79921f215419b11cc3966ce9c132d299fd39e051 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 577b56cc63cf3af1a4d3e9cc00c3dfe2446f5265..db2f70be7bfce0c19bcf302dc7ebbd06ed333f87 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 da9f4ca3c0438c0eeeaf0a62449af9a2f890d3e3..92d939b00fe1077dc6dd8146056bbc9a32c4effd 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 5abc7f2f73e2e85d6bc57827fa2d440e23a4bd95..a5cb8986140edd3da5574e07efb4862c53ddf30e 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 813891e9f8228e46d3d61f67f2100abd33dab2ff..6bc2d7edfc199c56efbfd14a90590f720208c32a 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 96571dc6bb452e8f4cece7ff4d5b766ad8c0a7db..0b66c30e9d33386ddc2e1e29d5575db317d1474e 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 f8cee57c51f778ae6215cd8b1001f848fa458784..19850716a9e215ca416aeefcf675384163662332 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 2734b380d56aa30505497e0ca9524f63a8255faf..b5b8e7ad21a1eea7251135acd2c6e182bb836209 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 d01a02acd3bd0d67fc2973c7d4eae087df1bd5a3..0189d87148e1ff409dfe7a0c84b0d1259718daeb 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 211fd10e22656572f9426591e96b62aafddcad32..63a6b9e2b7c933d438accebd7e735f1a1d03bf73 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 57b8af75bc05f045a88ec69079616502ea4e3695..8f146f6fba8ba0a42f7e3051c746907f3249de3c 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 ca710d7629bd78a887ef083e49cd12cefa41ade3..c5ad3e9f4e501ea21be9de1c1f14d89891effc77 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 c2641d6560c5f65d5ec356a58869c2bedf3760d1..a79d17cfc27ca5efdf046dc19e27c219b6fb48e3 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 cb2cf1d50137b2bf769e534627d6376a9fcbcc50..47e225107983e6d7e857311ad2ce71ab0af02a69 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 e17b136c5b62d443d5c5ac919d9a7ec9295fb7c0..c36c6fff5315bbb47a60c3e6ecc5902b053886f0 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 e4f23a1f27b1f102d806dd82df980e4936e5c76e..77a20e4f69c9c88931b6c885d479a4b7601cf518 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 f96765b38f84c0795d94c8812b4b12941e6ae90e..2f8f9b3b3f99813b58965ae6bcb37c83ed3ba51e 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 fc4f39661c8a2fdbb112b6b71746f106cc2358e2..4feb62d101637b7aa7ec77441f38a40a50687599 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 03c2184787254cf2ceb72d9b612492516704b48b..56c3edd7eaa9e9093998b6afc547485a39cbe330 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 46317b38a27f3c17c5f5911a0699492a50d958c7..768f994b62ffabfe3689ece96aaca131795691d2 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 d278d775d989750cbfd2f980d23e12e03d9d9a18..5d52d8bc8b4ba6ff3ab8ca2d8e09eb3cf8c9508e 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 9edaeac3314521f86ec783a4469f3ead941b2cf1..aae17312bc5661b7f4ae4bf8108f22ba8f010ad6 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 9d03404594b5f6829e22dfe2ff8c44633ad60aef..911bacbab5eecf40a2a62edac52562c0b19b6947 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!");