diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/document_scripter/__init__.py b/plugins/extensions/pykrita/plugin/plugins/scripter/document_scripter/__init__.py new file mode 100644 diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/loaders/__init__.py b/plugins/extensions/pykrita/plugin/plugins/scripter/loaders/__init__.py new file mode 100644 diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/loaders/actionloader.py b/plugins/extensions/pykrita/plugin/plugins/scripter/loaders/actionloader.py new file mode 100644 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/loaders/actionloader.py @@ -0,0 +1,10 @@ +class ActionLoader(object): + + @property + def importPath(self): + return 'scripter.ui_scripter.actions' + + def addComponents(self, components): + for action in components: + if action['parent']: + action['parent'].addAction(action['component']) diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/loaders/menuloader.py b/plugins/extensions/pykrita/plugin/plugins/scripter/loaders/menuloader.py new file mode 100644 diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/loaders/widgetloader.py b/plugins/extensions/pykrita/plugin/plugins/scripter/loaders/widgetloader.py new file mode 100644 diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/scripter.py b/plugins/extensions/pykrita/plugin/plugins/scripter/scripter.py --- a/plugins/extensions/pykrita/plugin/plugins/scripter/scripter.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/scripter.py @@ -2,79 +2,21 @@ from PyQt5.QtWidgets import * from PyQt5.QtCore import * from krita import * -from scripter import syntax, pythoneditor, settingsdialog, syntaxstyles -import sys +from scripter import uicontroller -class docWrapper: - - def __init__(self, textdocument): - self.textdocument = textdocument - - def write(self, text, view = None): - cursor = QTextCursor(self.textdocument) - cursor.clearSelection() - cursor.movePosition(QTextCursor.End) - cursor.insertText(text) class ScripterViewExtension(ViewExtension): def __init__(self, parent): super().__init__(parent) + self.uicontroller = uicontroller.UIController(QDialog()) def setup(self): print("Scripter setup") action = Krita.instance().createAction("Scripter") - action.triggered.connect(self.showScripter) - - def execute(self): - stdout = sys.stdout - stderr = sys.stderr - output = docWrapper(self.output.document()) - output.write("======================================\n") - sys.stdout = output - sys.stderr = output - script = self.editor.document().toPlainText() - try: - bc = compile(script, "", "exec") - except Exception as e: - QMessageBox.critical(self.editor, "Error compiling script", str(e)) - return - - exec(bc) - - sys.stdout = stdout - sys.stderr = stderr - - def openSettings(self): - self.settingsDialog = settingsdialog.SettingsDialog(self) - self.settingsDialog.setWindowModality(Qt.WindowModal) - self.settingsDialog.setFixedSize(400, 250) - self.settingsDialog.show() - self.settingsDialog.exec() - - def showScripter(self): - dialog = QDialog() - dialog.setWindowModality(Qt.NonModal) - self.editor = pythoneditor.CodeEditor() - self.highlight = syntax.PythonHighlighter(self.editor.document(), syntaxstyles.DefaultSyntaxStyle()) - vbox = QVBoxLayout(dialog) - vbox.addWidget(self.editor) - buttonLayout = QHBoxLayout() - button = QPushButton("Run") - settingsButton = QPushButton("Settings") - button.clicked.connect(self.execute) - settingsButton.clicked.connect(self.openSettings) - buttonLayout.addWidget(button) - buttonLayout.addWidget(settingsButton) - vbox.addLayout(buttonLayout) - self.output = QPlainTextEdit() - vbox.addWidget(self.output) - dialog.resize(400, 500) - dialog.setWindowTitle("Scripter") - dialog.setSizeGripEnabled(True) - dialog.show() - dialog.activateWindow() - dialog.exec() + action.triggered.connect(self.initialize) + def initialize(self): + self.uicontroller.initialize(self) Krita.instance().addViewExtension(ScripterViewExtension(Krita.instance())) diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/__init__.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/__init__.py new file mode 100644 diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/__init__.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/__init__.py new file mode 100644 diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/runaction.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/runaction.py new file mode 100644 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/runaction.py @@ -0,0 +1,41 @@ +from PyQt5.QtWidgets import QAction, QMessageBox +from PyQt5.QtGui import QIcon +import sys +from ..editor import docwrapper + +class RunAction(QAction): + + def __init__(self, scripter, parent=None): + super(RunAction, self).__init__(parent) + self.scripter = scripter + + self.editor = self.scripter.uicontroller.editor + self.output = self.scripter.uicontroller.output + + self.triggered.connect(self.run) + + self.setText('Run') + self.setIcon(QIcon('/home/eliakincosta/Pictures/play.svg')) + + @property + def parent(self): + return 'toolBar' + + def run(self): + stdout = sys.stdout + stderr = sys.stderr + output = docwrapper.DocWrapper(self.output.document()) + output.write("======================================\n") + sys.stdout = output + sys.stderr = output + script = self.editor.document().toPlainText() + try: + bc = compile(script, "", "exec") + except Exception as e: + QMessageBox.critical(self.editor, "Error compiling script", str(e)) + return + + exec(bc) + + sys.stdout = stdout + sys.stderr = stderr diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/settingsaction.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/settingsaction.py new file mode 100644 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/settingsaction.py @@ -0,0 +1,25 @@ +from PyQt5.QtWidgets import QAction +from PyQt5.QtCore import Qt +from ..widgets import settingsdialog + + +class SettingsAction(QAction): + + def __init__(self, scripter, parent=None): + super(SettingsAction, self).__init__(parent) + self.scripter = scripter + + self.triggered.connect(self.openSettings) + + self.setText('Settings') + + @property + def parent(self): + return 'File' + + def openSettings(self): + self.settingsDialog = settingsdialog.SettingsDialog(self.scripter) + self.settingsDialog.setWindowModality(Qt.WindowModal) + self.settingsDialog.setFixedSize(400, 250) + self.settingsDialog.show() + self.settingsDialog.exec() diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/__init__.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/__init__.py new file mode 100644 diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/docwrapper.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/docwrapper.py new file mode 100644 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/docwrapper.py @@ -0,0 +1,12 @@ +from PyQt5.QtGui import QTextCursor + +class DocWrapper: + + def __init__(self, textdocument): + self.textdocument = textdocument + + def write(self, text, view = None): + cursor = QTextCursor(self.textdocument) + cursor.clearSelection() + cursor.movePosition(QTextCursor.End) + cursor.insertText(text) diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/pythoneditor.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/pythoneditor.py rename from plugins/extensions/pykrita/plugin/plugins/scripter/pythoneditor.py rename to plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/pythoneditor.py --- a/plugins/extensions/pykrita/plugin/plugins/scripter/pythoneditor.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/pythoneditor.py @@ -1,10 +1,12 @@ # -*- coding: utf-8 -*- + from PyQt5.QtCore import * from PyQt5.QtWidgets import * -from scripter import linenumberarea +from scripter.ui_scripter.widgets import linenumberarea from PyQt5.QtGui import * + class CodeEditor(QPlainTextEdit): def __init__(self, parent=None): diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/syntax/__init__.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/syntax/__init__.py new file mode 100644 diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/syntax.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/syntax/syntax.py rename from plugins/extensions/pykrita/plugin/plugins/scripter/syntax.py rename to plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/syntax/syntax.py --- a/plugins/extensions/pykrita/plugin/plugins/scripter/syntax.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/syntax/syntax.py @@ -1,7 +1,7 @@ # syntax.py: taken from https://wiki.python.org/moin/PyQt/Python%20syntax%20highlighting -import sys +import sys from PyQt5.QtCore import * from PyQt5.QtGui import * diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/syntaxstyles.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/syntax/syntaxstyles.py rename from plugins/extensions/pykrita/plugin/plugins/scripter/syntaxstyles.py rename to plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/syntax/syntaxstyles.py --- a/plugins/extensions/pykrita/plugin/plugins/scripter/syntaxstyles.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/syntax/syntaxstyles.py @@ -1,5 +1,3 @@ -from PyQt5.QtCore import * -from PyQt5.QtWidgets import * from PyQt5.QtGui import * diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/__init__.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/__init__.py new file mode 100644 diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/fontscombobox.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/fontscombobox.py rename from plugins/extensions/pykrita/plugin/plugins/scripter/fontscombobox.py rename to plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/fontscombobox.py --- a/plugins/extensions/pykrita/plugin/plugins/scripter/fontscombobox.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/fontscombobox.py @@ -2,6 +2,7 @@ from PyQt5.QtGui import * from PyQt5.QtCore import * + class FontsComboBox(QComboBox): def __init__(self, editor, parent=None): @@ -18,7 +19,7 @@ com.setCaseSensitivity(Qt.CaseInsensitive) com.setCompletionMode(QCompleter.PopupCompletion) - # Style sheet to set false on combobox-popup + # Style sheet to set false on combobox-popup self.setStyleSheet("QComboBox { combobox-popup: 0; }") self.setMaxVisibleItems(10) self.setCompleter(com) diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/linenumberarea.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/linenumberarea.py rename from plugins/extensions/pykrita/plugin/plugins/scripter/linenumberarea.py rename to plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/linenumberarea.py --- a/plugins/extensions/pykrita/plugin/plugins/scripter/linenumberarea.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/linenumberarea.py @@ -1,8 +1,10 @@ # -*- coding: utf-8 -*- + from PyQt5.QtWidgets import * from PyQt5.QtCore import * + class LineNumberArea(QWidget): def __init__(self, editor): diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/settingsdialog.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/settingsdialog.py rename from plugins/extensions/pykrita/plugin/plugins/scripter/settingsdialog.py rename to plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/settingsdialog.py --- a/plugins/extensions/pykrita/plugin/plugins/scripter/settingsdialog.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/settingsdialog.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- + from PyQt5.QtWidgets import * -from scripter import syntaxstylescombobox, fontscombobox +from ..widgets import syntaxstylescombobox, fontscombobox class SettingsDialog(QDialog): @@ -11,5 +12,5 @@ self.scripter = scripter self.mainLayout = QFormLayout(self) - self.mainLayout.addRow('Syntax Highlither', syntaxstylescombobox.SyntaxStylesComboBox(scripter.highlight)) - self.mainLayout.addRow('Fonts', fontscombobox.FontsComboBox(scripter.editor)) + self.mainLayout.addRow('Syntax Highlither', syntaxstylescombobox.SyntaxStylesComboBox(self.scripter.uicontroller.highlight)) + self.mainLayout.addRow('Fonts', fontscombobox.FontsComboBox(self.scripter.uicontroller.editor)) diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/syntaxstylescombobox.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/syntaxstylescombobox.py rename from plugins/extensions/pykrita/plugin/plugins/scripter/syntaxstylescombobox.py rename to plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/syntaxstylescombobox.py --- a/plugins/extensions/pykrita/plugin/plugins/scripter/syntaxstylescombobox.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/syntaxstylescombobox.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- + from PyQt5.QtWidgets import * -from scripter import syntaxstyles +from scripter.ui_scripter.syntax import syntaxstyles class SyntaxStylesComboBox(QComboBox): diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py b/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py new file mode 100644 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py @@ -0,0 +1,81 @@ +from PyQt5.QtGui import * +from PyQt5.QtWidgets import * +from PyQt5.QtCore import * +from scripter.ui_scripter.syntax import syntax, syntaxstyles +from scripter.ui_scripter import actions +from scripter.ui_scripter.editor import pythoneditor +from scripter.loaders import actionloader, menuloader, widgetloader +import os +import importlib +import inspect + +class UIController(object): + def __init__(self, mainWidget): + self.mainWidget = mainWidget + self.actionToolbar = QToolBar('toolBar', self.mainWidget) + self.menu_bar = QMenuBar(self.mainWidget) + + self.actionToolbar.setObjectName('toolBar') + self.menu_bar.setObjectName('menuBar') + + self.components = [] + + self.mainWidget.setWindowModality(Qt.NonModal) + self.editor = pythoneditor.CodeEditor() + self.output = QPlainTextEdit() + self.highlight = syntax.PythonHighlighter(self.editor.document(), syntaxstyles.DefaultSyntaxStyle()) + + def initialize(self, scripter): + self.scripter = scripter + + self.loadMenus() + self.loadComponents(actionloader.ActionLoader()) + + vbox = QVBoxLayout(self.mainWidget) + vbox.addWidget(self.menu_bar) + vbox.addWidget(self.editor) + vbox.addWidget(self.actionToolbar) + vbox.addWidget(self.output) + + self.mainWidget.resize(400, 500) + self.mainWidget.setWindowTitle("Scripter") + self.mainWidget.setSizeGripEnabled(True) + self.mainWidget.show() + self.mainWidget.activateWindow() + + def loadMenus(self): + self.addMenu('File', 'File') + self.addMenu('Edit', 'Edit') + + def addMenu(self, menuName, parentName): + parent = self.menu_bar.findChild(QObject, parentName) + self.newMenu = None + + if parent: + self.newMenu = parent.addMenu(menuName) + else: + self.newMenu = self.menu_bar.addMenu(menuName) + + self.newMenu.setObjectName(menuName) + + return self.newMenu + + + def loadComponents(self, loader): + component_module = importlib.import_module(loader.importPath) + + modules = [loader.importPath + '.' + str(module).split('.')[0] + for module in os.listdir(component_module.__path__[0]) + if module.endswith('.py') and (not '__init__' in module)] + + for module in modules: + m = importlib.import_module(module) + clsmembers = [klass for klass in inspect.getmembers(m, inspect.isclass) if klass[1].__module__ == module] + print(self.mainWidget.children()) + for klass in clsmembers: + obj = klass[1](self.scripter) + parent = self.mainWidget.findChild(QObject, obj.parent) + print('parent:', parent) + self.components.append(dict(component=obj, parent=parent)) + + loader.addComponents(self.components)