[krita/krita/4.0] /: Create actions per-window instead of per-application

Boudewijn Rempt null at kde.org
Wed Mar 14 13:24:33 UTC 2018


Git commit 3de294bc464390acc33be19aa89a74ebfb18963e by Boudewijn Rempt.
Committed on 14/03/2018 at 13:24.
Pushed by rempt into branch 'krita/4.0'.

Create actions per-window instead of per-application

Note that this changes the libkis scripting api. The Extension
class now has two methods: setup and createActions. Old code
was like this:

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from krita import *

def hello():
    QMessageBox.information(QWidget(), "Test", "Hello World")

class HelloExtension(Extension):

  def __init__(self, parent):
      super().__init__(parent)

  def setup(self):
      action = Krita.createAction("Hello")
      action.triggered.connect(hello)

Krita.instance().addExtension(HelloExtension(Krita.instance()))

New code is like this:

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from krita import *

def hello():
    QMessageBox.information(QWidget(), "Test", "Hello World")

class HelloExtension(Extension):

  def __init__(self, parent):
      super().__init__(parent)

  def setup(self):
      pass

  def createActions(self, window):
      action = window.createAction("Hello")
      action.triggered.connect(hello)

Krita.instance().addExtension(HelloExtension(Krita.instance()))

This also adds a new parameter to createAction: the menu location. This
is a path separated by /, for instance tools/scripts. Note that this
path must exist, otherwise a crash will happen. The paths are defined in
krita4.xmlgui...

BUG:391705

Note: we're still leaking Action objects created in Window::createAction;
that's the next fix.

CCMAIL:kimageshop at kde.org
(cherry picked from commit e9b0661657f67ac4d1186641a78357f695a9a717)

M  +1    -1    krita/krita4.xmlgui
M  +0    -11   libs/libkis/Action.cpp
M  +0    -12   libs/libkis/Action.h
M  +22   -14   libs/libkis/Extension.h
M  +10   -20   libs/libkis/Krita.cpp
M  +4    -10   libs/libkis/Krita.h
M  +5    -2    libs/libkis/Mainpage.dox
M  +35   -1    libs/libkis/Window.cpp
M  +17   -0    libs/libkis/Window.h
M  +0    -1    libs/ui/CMakeLists.txt
M  +0    -11   libs/ui/KisPart.cpp
M  +0    -11   libs/ui/KisPart.h
M  +0    -10   libs/ui/KisViewManager.cpp
M  +0    -3    libs/ui/KisViewManager.h
D  +0    -90   libs/ui/kis_script_manager.cpp
D  +0    -52   libs/ui/kis_script_manager.h
M  +2    -2    plugins/extensions/pykrita/plugin/plugin.cpp
M  +1    -2    plugins/extensions/pykrita/sip/krita/Action.sip
M  +1    -0    plugins/extensions/pykrita/sip/krita/Extension.sip
M  +0    -1    plugins/extensions/pykrita/sip/krita/Krita.sip
M  +1    -0    plugins/extensions/pykrita/sip/krita/Window.sip
M  +4    -1    plugins/python/assignprofiledialog/assignprofiledialog.py
M  +4    -1    plugins/python/colorspace/colorspace.py
M  +4    -1    plugins/python/documenttools/documenttools.py
M  +4    -1    plugins/python/exportlayers/exportlayers.py
M  +4    -1    plugins/python/filtermanager/filtermanager.py
M  +4    -2    plugins/python/hello/hello.py
M  +4    -1    plugins/python/highpass/highpass.py
M  +4    -1    plugins/python/scripter/scripter.py
M  +7    -9    plugins/python/tenbrushes/tenbrushes.py
M  +7    -7    plugins/python/tenscripts/tenscripts.py

https://commits.kde.org/krita/3de294bc464390acc33be19aa89a74ebfb18963e

diff --git a/krita/krita4.xmlgui b/krita/krita4.xmlgui
index b933f80cf4f..1e8ec064285 100644
--- a/krita/krita4.xmlgui
+++ b/krita/krita4.xmlgui
@@ -307,7 +307,7 @@ xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0  http://www.kde.org
     </Menu>
     <Menu name="tools">
       <text>&Tools</text>
-      <Action name="scripts"/>
+      <Menu name="scripts"><text>Scripting</text></Menu>
       <Menu name="Recording">
         <text>Recording</text>
         <Action name="Recording_Start_Recording_Macro"/>
diff --git a/libs/libkis/Action.cpp b/libs/libkis/Action.cpp
index 75005dce79f..faafc23113a 100644
--- a/libs/libkis/Action.cpp
+++ b/libs/libkis/Action.cpp
@@ -156,14 +156,3 @@ void Action::trigger()
 {
     d->action->trigger();
 }
-
-
-void Action::setMenu(const QString menu)
-{
-    d->action->setProperty("menu", menu);
-}
-
-QString Action::menu() const
-{
-    return d->action->property("menu").toString();
-}
diff --git a/libs/libkis/Action.h b/libs/libkis/Action.h
index 3d8b4700134..9546fc644da 100644
--- a/libs/libkis/Action.h
+++ b/libs/libkis/Action.h
@@ -136,18 +136,6 @@ public Q_SLOTS:
      */
     void trigger();
 
-    /**
-     * @brief setMenu determines in which menu the action will be placed. The default is tools/scripts
-     * @param menu the menu where the action should go, / -separated to drill down the hierarchy
-     */
-    void setMenu(const QString menu);
-
-    /**
-     * @return the menu in which this action is to be placed.
-     */
-    QString menu() const;
-
-
 Q_SIGNALS:
 
     /**
diff --git a/libs/libkis/Extension.h b/libs/libkis/Extension.h
index fc9d76c47e7..eb9502a9532 100644
--- a/libs/libkis/Extension.h
+++ b/libs/libkis/Extension.h
@@ -22,17 +22,18 @@
 #include "kritalibkis_export.h"
 
 #include <QObject>
+#include <Window.h>
 
 /**
- * An Extension is the base for classes that extend Krita. An Extension 
+ * An Extension is the base for classes that extend Krita. An Extension
  * is loaded on startup, when the setup() method will be executed.
- * 
- * The extension instance should be added to the Krita Application object 
+ *
+ * The extension instance should be added to the Krita Application object
  * using Krita.instance().addViewExtension or Application.addViewExtension
  * or Scripter.addViewExtension.
- * 
+ *
  * Example:
- * 
+ *
  * @code
  * import sys
  * from PyQt5.QtGui import *
@@ -45,34 +46,41 @@
  *
  * def hello(self):
  *     QMessageBox.information(QWidget(), "Test", "Hello! This is Krita " + Application.version())
- * 
+ *
  * def setup(self):
  *     qDebug("Hello Setup")
- *     action = Krita.instance().createAction("hello")
+ *
+ * def createActions(self, window)
+ *     action = window.createAction("hello")
  *     action.triggered.connect(self.hello)
  *
  * Scripter.addExtension(HelloExtension(Krita.instance()))
- * 
+ *
  * @endcode
  */
 class KRITALIBKIS_EXPORT Extension : public QObject
 {
     Q_OBJECT
 public:
-    
+
     /**
-     * Create a new extension. The extension will be 
+     * Create a new extension. The extension will be
      * owned by @param parent.
      */
     explicit Extension(QObject *parent = 0);
     ~Extension() override;
-    
+
     /**
-     * Override this function to setup your Extension. You can use it to add
-     * Actions to the action collection or integrate in any other way with 
-     * the application.
+     * Override this function to setup your Extension. You can use it to integrate
+     * with the Krita application instance.
      */
     virtual void setup() = 0;
+
+    virtual void createActions(Window *window) = 0;
+
 };
 
+
+
+
 #endif
diff --git a/libs/libkis/Krita.cpp b/libs/libkis/Krita.cpp
index b9421a573e6..a90f5ec0ea6 100644
--- a/libs/libkis/Krita.cpp
+++ b/libs/libkis/Krita.cpp
@@ -38,7 +38,6 @@
 #include <KisDocument.h>
 #include <kis_image.h>
 #include <kis_action.h>
-#include <kis_script_manager.h>
 #include <KisViewManager.h>
 #include <KritaVersionWrapper.h>
 #include <kis_filter_registry.h>
@@ -53,6 +52,7 @@
 #include <KoResourceServerProvider.h>
 #include <kis_action_registry.h>
 #include <kis_icon_utils.h>
+#include <KisPart.h>
 
 #include "View.h"
 #include "Document.h"
@@ -77,6 +77,7 @@ Krita::Krita(QObject *parent)
     , d(new Private)
 {
     qRegisterMetaType<Notifier*>();
+    connect(KisPart::instance(), SIGNAL(sigWindowAdded(KisMainWindow*)), SLOT(mainWindowAdded(KisMainWindow*)));
 }
 
 Krita::~Krita()
@@ -348,25 +349,6 @@ Window* Krita::openWindow()
     return new Window(mw);
 }
 
-Action *Krita::createAction(const QString &id, const QString &text, bool addToScriptMenu)
-{
-    KisAction *action = new KisAction(text, this);
-    action->setObjectName(id);
-
-    KisActionRegistry *actionRegistry = KisActionRegistry::instance();
-    actionRegistry->propertizeAction(action->objectName(), action);
-    bool ok; // We will skip this check
-    int activationFlags = actionRegistry->getActionProperty(id, "activationFlags").toInt(&ok, 2);
-    int activationConditions = actionRegistry->getActionProperty(id, "activationConditions").toInt(&ok, 2);
-    action->setActivationFlags((KisAction::ActivationFlags) activationFlags);
-    action->setActivationConditions((KisAction::ActivationConditions) activationConditions);
-
-    if (addToScriptMenu) {
-        KisPart::instance()->addScriptAction(action);
-    }
-    return new Action(action->objectName(), action);
-}
-
 void Krita::addExtension(Extension* extension)
 {
     d->extensions.append(extension);
@@ -431,3 +413,11 @@ QObject *Krita::fromVariant(const QVariant& v)
     else
         return 0;
 }
+
+void Krita::mainWindowAdded(KisMainWindow *kisWindow)
+{
+    Q_FOREACH(Extension *extension, d->extensions) {
+        Window window(kisWindow);
+        extension->createActions(&window);
+    }
+}
diff --git a/libs/libkis/Krita.h b/libs/libkis/Krita.h
index fc4f5b6a36f..5fd47153fb5 100644
--- a/libs/libkis/Krita.h
+++ b/libs/libkis/Krita.h
@@ -273,16 +273,6 @@ add_document_to_window()
      */
     Window *openWindow();
 
-    /**
-     * @brief createAction creates an action with the given text and passes it to Krita. Every newly created
-     *     mainwindow will create an instance of this action. This means that actions need to be created in the
-     *     setup phase of the plugin, not on the fly.
-     * @param id the unique id for this action
-     * @param text the user-visible text
-     * @return the Action you can connect a slot to.
-     */
-    Action *createAction(const QString &name, const QString &text, bool addToScriptMenu = true);
-
     /**
      * @brief addExtension add the given plugin to Krita. There will be a single instance of each Extension in the Krita process.
      * @param extension the extension to add.
@@ -338,6 +328,10 @@ add_document_to_window()
     // Internal only: for use with mikro.py
     static QObject *fromVariant(const QVariant& v);
 
+private Q_SLOTS:
+
+    void mainWindowAdded(KisMainWindow *window);
+
 private:
     struct Private;
     Private *const d;
diff --git a/libs/libkis/Mainpage.dox b/libs/libkis/Mainpage.dox
index 03b09767d32..c98cbcf7c89 100644
--- a/libs/libkis/Mainpage.dox
+++ b/libs/libkis/Mainpage.dox
@@ -102,8 +102,11 @@ class HelloExtension(Extension):
   def __init__(self, parent):
       super().__init__(parent)
 
-  def setup(self, viewManager):
-      action = viewManager.createAction("Hello")
+  def setup(self):
+      pass
+
+  def createActions(self, window):
+      action = window.createAction("Hello")
       action.triggered.connect(hello)
 
 Krita.instance().addExtension(HelloExtension(Krita.instance()))
diff --git a/libs/libkis/Window.cpp b/libs/libkis/Window.cpp
index e5b2189e776..59d273e1b13 100644
--- a/libs/libkis/Window.cpp
+++ b/libs/libkis/Window.cpp
@@ -17,13 +17,18 @@
  */
 #include "Window.h"
 
+#include <QMenuBar>
+#include <QObject>
+
 #include <KisMainWindow.h>
 #include <KisPart.h>
 #include <KisDocument.h>
+#include <KisViewManager.h>
+#include <kis_action_manager.h>
 
 #include <Document.h>
 #include <View.h>
-
+#include <Action.h>
 
 struct Window::Private {
     Private() {}
@@ -114,4 +119,33 @@ void Window::close()
 }
 
 
+Action *Window::createAction(const QString &id, const QString &text, const QString &menuLocation)
+{
+    KisAction *action = d->window->viewManager()->actionManager()->createAction(id);
+    action->setText(text);
+    action->setObjectName(id);
+    if (!menuLocation.isEmpty()) {
+        QAction *found = 0;
+        QList<QAction *> candidates = d->window->menuBar()->actions();
+        Q_FOREACH(const QString &name, menuLocation.split("/")) {
+            Q_FOREACH(QAction *candidate, candidates) {
+                if (candidate->objectName() == name) {
+                    found = candidate;
+                    candidates = candidate->menu()->actions();
+                    break;
+                }
+            }
+            if (candidates.isEmpty()) {
+                break;
+            }
+        }
+
+        if (found && found->menu()) {
+            found->menu()->addAction(action);
+        }
+    }
+    return new Action(action->objectName(), action);
+}
+
+
 
diff --git a/libs/libkis/Window.h b/libs/libkis/Window.h
index f6a5b0eac4b..53c5f139427 100644
--- a/libs/libkis/Window.h
+++ b/libs/libkis/Window.h
@@ -19,12 +19,16 @@
 #define LIBKIS_WINDOW_H
 
 #include <QObject>
+#include <QAction>
 #include <QMainWindow>
 
 #include "kritalibkis_export.h"
 #include "libkis.h"
 
 #include <KisMainWindow.h>
+
+class Action;
+
 /**
  * Window represents one Krita mainwindow. A window can have any number
  * of views open on any number of documents.
@@ -82,6 +86,19 @@ public Q_SLOTS:
      */
     void close();
 
+    /**
+     * @brief createAction creates an Action object and adds it to the action
+     * manager for this Window.
+     * @param id The unique id for the action. This will be used to
+     *     propertize the action if any .action file is present
+     * @param text The user-visible text of the action. If empty, the text from the
+     *    .action file is used.
+     * @param menu a /-separated string that describes which menu the action should
+     *     be places in. Default is "tools/scripts"
+     * @return the new action.
+     */
+    Action *createAction(const QString &id, const QString &text = QString(), const QString &menuLocation = QString("tools/scripts"));
+
 Q_SIGNALS:
     /// Emitted when the window is closed.
     void windowClosed();
diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt
index e1fa6a93e21..6d69cf303ae 100644
--- a/libs/ui/CMakeLists.txt
+++ b/libs/ui/CMakeLists.txt
@@ -134,7 +134,6 @@ set(kritaui_LIB_SRCS
     kis_popup_palette.cpp
     kis_png_converter.cpp
     kis_preference_set_registry.cpp
-    kis_script_manager.cpp
     kis_resource_server_provider.cpp
     KisSelectedShapesProxy.cpp
     kis_selection_decoration.cc
diff --git a/libs/ui/KisPart.cpp b/libs/ui/KisPart.cpp
index 645991d7986..cf34bffca36 100644
--- a/libs/ui/KisPart.cpp
+++ b/libs/ui/KisPart.cpp
@@ -70,7 +70,6 @@
 #include "KisDocument.h"
 #include "KoToolManager.h"
 #include "KisViewManager.h"
-#include "kis_script_manager.h"
 #include "KisOpenPane.h"
 
 #include "kis_color_manager.h"
@@ -101,10 +100,7 @@ public:
     QList<QPointer<KisView> > views;
     QList<QPointer<KisMainWindow> > mainWindows;
     QList<QPointer<KisDocument> > documents;
-    QList<KisAction*> scriptActions;
-
     KActionCollection *actionCollection{0};
-
     KisIdleWatcher idleWatcher;
     KisAnimationCachePopulator animationCachePopulator;
 };
@@ -208,9 +204,6 @@ void KisPart::removeDocument(KisDocument *document)
 KisMainWindow *KisPart::createMainWindow()
 {
     KisMainWindow *mw = new KisMainWindow();
-    Q_FOREACH(KisAction *action, d->scriptActions) {
-        mw->viewManager()->scriptManager()->addAction(action);
-    }
     dbgUI <<"mainWindow" << (void*)mw << "added to view" << this;
     d->mainWindows.append(mw);
     emit sigWindowAdded(mw);
@@ -352,10 +345,6 @@ KisMainWindow *KisPart::currentMainwindow() const
 
 }
 
-void KisPart::addScriptAction(KisAction *action)
-{
-    d->scriptActions << action;
-}
 
 KisIdleWatcher* KisPart::idleWatcher() const
 {
diff --git a/libs/ui/KisPart.h b/libs/ui/KisPart.h
index b0c71af228e..434792e2da1 100644
--- a/libs/ui/KisPart.h
+++ b/libs/ui/KisPart.h
@@ -134,17 +134,6 @@ public:
      */
     KisMainWindow *currentMainwindow() const;
 
-    /**
-     * Add a given action to the list of dynamically defined actions. On creating
-     * a mainwindow, all these actions will be added to the script manager.
-     */
-    void addScriptAction(KisAction *);
-
-    /**
-     * Load actions for currently active main window into KisActionRegistry.
-     */
-    void loadActions();
-
     /**
      * @return the application-wide KisIdleWatcher.
      */
diff --git a/libs/ui/KisViewManager.cpp b/libs/ui/KisViewManager.cpp
index 3a129a4536c..643857bd6fc 100644
--- a/libs/ui/KisViewManager.cpp
+++ b/libs/ui/KisViewManager.cpp
@@ -127,7 +127,6 @@
 #include "kis_zoom_manager.h"
 #include "widgets/kis_floating_message.h"
 #include "kis_signal_auto_connection.h"
-#include "kis_script_manager.h"
 #include "kis_icon_utils.h"
 #include "kis_guides_manager.h"
 #include "kis_derived_resources.h"
@@ -192,7 +191,6 @@ public:
         , actionCollection(_actionCollection)
         , mirrorManager(_q)
         , inputManager(_q)
-        , scriptManager(_q)
         , actionAuthor(0)
         , showPixelGrid(0)
     {
@@ -247,7 +245,6 @@ public:
     KisInputManager inputManager;
 
     KisSignalAutoConnectionsStore viewConnections;
-    KisScriptManager scriptManager;
     KSelectAction *actionAuthor; // Select action for author profile.
     KisAction *showPixelGrid;
 
@@ -769,8 +766,6 @@ void KisViewManager::setupManagers()
     d->canvasControlsManager.setup(actionManager());
 
     d->mirrorManager.setup(actionCollection());
-
-    d->scriptManager.setup(actionCollection(), actionManager());
 }
 
 void KisViewManager::updateGUI()
@@ -812,11 +807,6 @@ KisDocument *KisViewManager::document() const
     return 0;
 }
 
-KisScriptManager *KisViewManager::scriptManager() const
-{
-  return &d->scriptManager;
-}
-
 int KisViewManager::viewCount() const
 {
     KisMainWindow *mw  = qobject_cast<KisMainWindow*>(d->mainWindow);
diff --git a/libs/ui/KisViewManager.h b/libs/ui/KisViewManager.h
index 98c90d265b4..861916e52f0 100644
--- a/libs/ui/KisViewManager.h
+++ b/libs/ui/KisViewManager.h
@@ -50,7 +50,6 @@ class KisUndoAdapter;
 class KisZoomManager;
 class KisPaintopBox;
 class KisActionManager;
-class KisScriptManager;
 class KisInputManager;
 class KoUpdater;
 class KoProgressUpdater;
@@ -164,8 +163,6 @@ public:  // Krita specific interfaces
 
     KisDocument *document() const;
 
-    KisScriptManager *scriptManager() const;
-
     int viewCount() const;
 
     /**
diff --git a/libs/ui/kis_script_manager.cpp b/libs/ui/kis_script_manager.cpp
deleted file mode 100644
index a93d544a5ae..00000000000
--- a/libs/ui/kis_script_manager.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- *  Copyright (c) 2014 Boudewijn Rempt <boud at valdyas.org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU Lesser General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "kis_script_manager.h"
-
-#include <QMenu>
-
-#include <KisPart.h>
-
-#include <kactionmenu.h>
-#include <klocalizedstring.h>
-#include <kactionmenu.h>
-#include <kactioncollection.h>
-#include <kis_action.h>
-
-#include <kis_action_manager.h>
-#include "KisViewManager.h"
-
-struct KisScriptManager::Private {
-    Private()
-        : actionCollection(0)
-        , actionManager(0)
-        , viewManager(0)
-        , scriptMenu(0)
-    {
-    }
-
-    KActionCollection *actionCollection;
-    KisActionManager *actionManager;
-    KisViewManager *viewManager;
-    KActionMenu *scriptMenu;
-    KActionMenu *hiddenMenu;
-};
-
-
-KisScriptManager::KisScriptManager(KisViewManager *view)
-    : QObject(view)
-    , d(new Private())
-{
-    d->viewManager = view;
-}
-
-KisScriptManager::~KisScriptManager()
-{
-    delete d;
-}
-
-
-void KisScriptManager::setup(KActionCollection * ac, KisActionManager *actionManager)
-{
-    d->actionCollection = ac;
-    d->actionManager = actionManager;
-
-    d->scriptMenu = new KActionMenu(i18n("Scripts"), this);
-    d->actionCollection->addAction("scripts", d->scriptMenu);
-    d->hiddenMenu = new KActionMenu("hidden", this);
-}
-
-void KisScriptManager::updateGUI()
-{
-    if (!d->viewManager) return;
-}
-
-void KisScriptManager::addAction(KisAction *action)
-{
-    d->actionManager->addAction(action->objectName(), action);
-    if (action->property("menu").toString() != "None") {
-        // XXX: find the right menu and add it there.
-        d->scriptMenu->addAction(action);
-    }
-    else {
-        d->hiddenMenu->addAction(action);
-        action->setShortcutContext(Qt::ApplicationShortcut);
-    }
-}
diff --git a/libs/ui/kis_script_manager.h b/libs/ui/kis_script_manager.h
deleted file mode 100644
index b1099473e92..00000000000
--- a/libs/ui/kis_script_manager.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *  Copyright (c) 2014 Boudewijn Rempt <boud at valdyas.org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU Lesser General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef KIS_SCRIPT_MANAGER_H
-#define KIS_SCRIPT_MANAGER_H
-
-#include <QObject>
-
-#include <kritaui_export.h>
-
-class KisAction;
-
-class KisActionManager;
-class KisViewManager;
-class KActionCollection;
-
-/**
- * @brief The KisScriptManager class is responsible for adding scripts to the menu
- */
-class KRITAUI_EXPORT KisScriptManager : public QObject
-{
-    Q_OBJECT
-public:
-    explicit KisScriptManager(KisViewManager * view);
-    ~KisScriptManager() override;
-
-    void setup(KActionCollection * ac, KisActionManager *actionManager);
-    void updateGUI();
-
-    void addAction(KisAction *action);
-
-private:
-    struct Private;
-    Private * const d;
-};
-
-#endif // KIS_SCRIPT_MANAGER_H
diff --git a/plugins/extensions/pykrita/plugin/plugin.cpp b/plugins/extensions/pykrita/plugin/plugin.cpp
index 0bf434d1e71..f97c9f60450 100644
--- a/plugins/extensions/pykrita/plugin/plugin.cpp
+++ b/plugins/extensions/pykrita/plugin/plugin.cpp
@@ -82,8 +82,8 @@ KritaPyQtPlugin::KritaPyQtPlugin(QObject *parent, const QVariantList &)
         dbgScript << "Cannot load pykrita module";
     }
 
-    Q_FOREACH (Extension* ext, Krita::instance()->extensions()) {
-        ext->setup();
+    Q_FOREACH (Extension *extension, Krita::instance()->extensions()) {
+        extension->setup();
     }
 }
 
diff --git a/plugins/extensions/pykrita/sip/krita/Action.sip b/plugins/extensions/pykrita/sip/krita/Action.sip
index 28a2b4e51d1..f5f1e1c4bb1 100644
--- a/plugins/extensions/pykrita/sip/krita/Action.sip
+++ b/plugins/extensions/pykrita/sip/krita/Action.sip
@@ -28,8 +28,7 @@ public Q_SLOTS:
     void setToolTip(QString tooltip);
     QString tooltip() const;
     void trigger();
-    void setMenu(const QString menu);
-    QString menu() const;
+
 Q_SIGNALS:
     void triggered(bool);
 private:
diff --git a/plugins/extensions/pykrita/sip/krita/Extension.sip b/plugins/extensions/pykrita/sip/krita/Extension.sip
index 78ffa9d6f0b..92babb2855e 100644
--- a/plugins/extensions/pykrita/sip/krita/Extension.sip
+++ b/plugins/extensions/pykrita/sip/krita/Extension.sip
@@ -8,4 +8,5 @@ class Extension : QObject
 public:
     explicit Extension(QObject *parent  /TransferThis/ = 0);
     virtual void setup() = 0;
+    virtual void createActions(Window *window) = 0;
 };
diff --git a/plugins/extensions/pykrita/sip/krita/Krita.sip b/plugins/extensions/pykrita/sip/krita/Krita.sip
index 21e8f129000..1d77a00b20f 100644
--- a/plugins/extensions/pykrita/sip/krita/Krita.sip
+++ b/plugins/extensions/pykrita/sip/krita/Krita.sip
@@ -34,7 +34,6 @@ public Q_SLOTS:
     QList<Extension*> extensions() /Factory/;
     Document * openDocument(const QString &filename)  /Factory/;
     Window * openWindow();
-    Action * createAction(const QString &id, const QString & text, bool addToScriptMenu = true);
     QIcon icon(QString &iconName) const;
 
     void addExtension(Extension* _extension /GetWrapper/);
diff --git a/plugins/extensions/pykrita/sip/krita/Window.sip b/plugins/extensions/pykrita/sip/krita/Window.sip
index fca6cbed719..aa578cb58b6 100644
--- a/plugins/extensions/pykrita/sip/krita/Window.sip
+++ b/plugins/extensions/pykrita/sip/krita/Window.sip
@@ -16,6 +16,7 @@ public Q_SLOTS:
     View *activeView() const /Factory/;
     void activate();
     void close();
+    QAction *createAction(const QString &id, const QString &text = QString(), const QString &menuLocation = QString("tools/scripts"));
 Q_SIGNALS:
     void windowClosed();
 private:
diff --git a/plugins/python/assignprofiledialog/assignprofiledialog.py b/plugins/python/assignprofiledialog/assignprofiledialog.py
index 1b3f2c7ddcb..c4b92bec311 100644
--- a/plugins/python/assignprofiledialog/assignprofiledialog.py
+++ b/plugins/python/assignprofiledialog/assignprofiledialog.py
@@ -50,7 +50,10 @@ class AssignProfileDialog(Extension):
         doc.setColorProfile(self.cmbProfile.currentText())
 
     def setup(self):
-        action = Application.createAction("assing_profile_to_image", "Assign Profile to Image")
+        pass
+    
+    def createActions(self, window):
+        action = window.createAction("assing_profile_to_image", "Assign Profile to Image")
         action.triggered.connect(self.assignProfile)
 
 Scripter.addExtension(AssignProfileDialog(Application))
diff --git a/plugins/python/colorspace/colorspace.py b/plugins/python/colorspace/colorspace.py
index 39d0cd5bb34..938326960bc 100644
--- a/plugins/python/colorspace/colorspace.py
+++ b/plugins/python/colorspace/colorspace.py
@@ -19,7 +19,10 @@ class ColorSpaceExtension(krita.Extension):
         super(ColorSpaceExtension, self).__init__(parent)
 
     def setup(self):
-        action = krita.Krita.instance().createAction("color_space", "Color Space")
+        pass
+    
+    def createActions(self, window):
+        action = window.createAction("color_space", "Color Space")
         action.setToolTip("Plugin to change color space to selected documents")
         action.triggered.connect(self.initialize)
 
diff --git a/plugins/python/documenttools/documenttools.py b/plugins/python/documenttools/documenttools.py
index 5bede48f4c8..9432c9309ee 100644
--- a/plugins/python/documenttools/documenttools.py
+++ b/plugins/python/documenttools/documenttools.py
@@ -19,7 +19,10 @@ class DocumentToolsExtension(krita.Extension):
         super(DocumentToolsExtension, self).__init__(parent)
 
     def setup(self):
-        action = krita.Krita.instance().createAction("document_tools", "Document Tools")
+        pass
+    
+    def createActions(self, window):
+        action = window.createAction("document_tools", "Document Tools")
         action.setToolTip("Plugin to manipulate properties of selected documents")
         action.triggered.connect(self.initialize)
 
diff --git a/plugins/python/exportlayers/exportlayers.py b/plugins/python/exportlayers/exportlayers.py
index f98ffa155a9..de0b65af499 100644
--- a/plugins/python/exportlayers/exportlayers.py
+++ b/plugins/python/exportlayers/exportlayers.py
@@ -19,7 +19,10 @@ class ExportLayersExtension(krita.Extension):
         super(ExportLayersExtension, self).__init__(parent)
 
     def setup(self):
-        action = krita.Krita.instance().createAction("export_layers", "Export Layers")
+        pass
+    
+    def createActions(self, window):
+        action = window.createAction("export_layers", "Export Layers")
         action.setToolTip("Plugin to export layers from a document")
         action.triggered.connect(self.initialize)
 
diff --git a/plugins/python/filtermanager/filtermanager.py b/plugins/python/filtermanager/filtermanager.py
index dfc7d765822..0e9e3fd8d5a 100644
--- a/plugins/python/filtermanager/filtermanager.py
+++ b/plugins/python/filtermanager/filtermanager.py
@@ -19,7 +19,10 @@ class FilterManagerExtension(krita.Extension):
         super(FilterManagerExtension, self).__init__(parent)
 
     def setup(self):
-        action = krita.Krita.instance().createAction("filter_manager", "Filter Manager")
+        pass
+    
+    def createActions(self, window):
+        action = window.createAction("filter_manager", "Filter Manager")
         action.setToolTip("Plugin to filters management")
         action.triggered.connect(self.initialize)
 
diff --git a/plugins/python/hello/hello.py b/plugins/python/hello/hello.py
index e4966c6599e..bd31a900684 100644
--- a/plugins/python/hello/hello.py
+++ b/plugins/python/hello/hello.py
@@ -42,11 +42,13 @@ class HelloExtension(Extension):
         super().__init__(parent)
 
     def setup(self):
+        pass
+
+    def createActions(self, window):
         """
         This is where most of the setup takes place!
         """
-        #qDebug("Hello Setup")
-        action = Krita.instance().createAction("hello_python", "hello", False)
+        action = window.createAction("hello_python", "hello")
         action.triggered.connect(hello)
 
 
diff --git a/plugins/python/highpass/highpass.py b/plugins/python/highpass/highpass.py
index 24aec83f34c..a5a92a24dae 100644
--- a/plugins/python/highpass/highpass.py
+++ b/plugins/python/highpass/highpass.py
@@ -21,7 +21,10 @@ class HighpassExtension(Extension):
         super().__init__(parent)
 
     def setup(self):
-        action = Application.createAction("high_pass_filter", "High Pass")
+        pass
+    
+    def createActions(self, window):
+        action = window.createAction("high_pass_filter", "High Pass")
         action.triggered.connect(self.showDialog)
 
     def showDialog(self):
diff --git a/plugins/python/scripter/scripter.py b/plugins/python/scripter/scripter.py
index 5f2a3a2f670..2653fe788e5 100644
--- a/plugins/python/scripter/scripter.py
+++ b/plugins/python/scripter/scripter.py
@@ -27,7 +27,10 @@ class ScripterExtension(Extension):
         super().__init__(parent)
 
     def setup(self):
-        action = Krita.instance().createAction("python_scripter", "Scripter")
+        pass
+    
+    def createActions(self, window):
+        action = window.createAction("python_scripter", "Scripter")
         action.triggered.connect(self.initialize)
 
     def initialize(self):
diff --git a/plugins/python/tenbrushes/tenbrushes.py b/plugins/python/tenbrushes/tenbrushes.py
index aa280bcf39b..d21c66a6fb8 100644
--- a/plugins/python/tenbrushes/tenbrushes.py
+++ b/plugins/python/tenbrushes/tenbrushes.py
@@ -23,12 +23,13 @@ class TenBrushesExtension(krita.Extension):
         self.selectedPresets = []
 
     def setup(self):
-        action = Application.createAction("ten_brushes", "Ten Brushes")
+        self.readSettings()
+        
+    def createActions(self, window):
+        action = window.createAction("ten_brushes", "Ten Brushes")
         action.setToolTip("Assign ten brush presets to ten shortcuts.")
         action.triggered.connect(self.initialize)
-
-        self.readSettings()
-        self.loadActions()
+        self.loadActions(window)
 
     def initialize(self):
         self.uitenbrushes = uitenbrushes.UITenBrushes()
@@ -45,15 +46,12 @@ class TenBrushesExtension(krita.Extension):
             presets.append(button.preset)
         Application.writeSetting("", "tenbrushes", ','.join(map(str, presets)))
 
-    def loadActions(self):
+    def loadActions(self, window):
         allPresets = Application.resources("preset")
 
         for index, item in enumerate(['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']):
-            action = Application.createAction("activate_preset_" + item, "Activate Brush Preset " + item)
-            action.setMenu("None")
+            action = window.createAction("activate_preset_" + item, "Activate Brush Preset " + item, "")
             action.triggered.connect(self.activatePreset)
-            
-            
 
             if index < len(self.selectedPresets) and self.selectedPresets[index] in allPresets:
                 action.preset = self.selectedPresets[index]
diff --git a/plugins/python/tenscripts/tenscripts.py b/plugins/python/tenscripts/tenscripts.py
index 100edaa40cb..b556580aae8 100644
--- a/plugins/python/tenscripts/tenscripts.py
+++ b/plugins/python/tenscripts/tenscripts.py
@@ -24,12 +24,13 @@ class TenScriptsExtension(krita.Extension):
        self.scripts = []
 
     def setup(self):
-        action = Application.createAction("ten_scripts", "Ten Scripts")
+        self.readSettings()
+        
+    def createActions(self, window):
+        action = window.createAction("ten_scripts", "Ten Scripts")
         action.setToolTip("Assign ten scripts to ten shortcuts.")
         action.triggered.connect(self.initialize)
-
-        self.readSettings()
-        self.loadActions()
+        self.loadActions(window)
 
     def initialize(self):
         self.uitenscripts = uitenscripts.UITenScripts()
@@ -46,11 +47,10 @@ class TenScriptsExtension(krita.Extension):
 
         Application.writeSetting("tenscripts", "scripts", ','.join(map(str, saved_scripts)))
 
-    def loadActions(self):
+    def loadActions(self, window):
         for index, item in enumerate(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']):
-            action = Application.createAction("execute_script_" + item, "Execute Script " + item)
+            action = window.createAction("execute_script_" + item, "Execute Script " + item, "")
             action.script = None
-            action.setMenu("None")
             action.triggered.connect(self._executeScript)
 
             if index < len(self.scripts):


More information about the kimageshop mailing list