diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/scripter.py b/plugins/extensions/pykrita/plugin/plugins/scripter/scripter.py index 0c55d8eda5..961f806aaf 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/scripter.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/scripter.py @@ -1,24 +1,26 @@ from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PyQt5.QtCore import * from krita import * from scripter import uicontroller, documentcontroller, debugcontroller +import os as osp +import sys class ScripterViewExtension(ViewExtension): def __init__(self, parent): super().__init__(parent) def setup(self): print("Scripter setup") action = Krita.instance().createAction("Scripter") action.triggered.connect(self.initialize) def initialize(self): self.uicontroller = uicontroller.UIController(QDialog()) self.documentcontroller = documentcontroller.DocumentController() self.debugcontroller = debugcontroller.DebugController(self) self.uicontroller.initialize(self) Krita.instance().addViewExtension(ScripterViewExtension(Krita.instance())) diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/debugaction/debugaction.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/debugaction/debugaction.py index a6b688b466..b230f68f42 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/debugaction/debugaction.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/debugaction/debugaction.py @@ -1,26 +1,26 @@ from PyQt5.QtWidgets import QAction from PyQt5.QtGui import QIcon, QPixmap class DebugAction(QAction): def __init__(self, scripter, parent=None): super(DebugAction, self).__init__(parent) self.scripter = scripter self.triggered.connect(self.debug) self.setText('Debug') # path to the icon - self.setIcon(QIcon('/home/eliakincosta/Pictures/debug.svg')) + #self.setIcon(QIcon('/home/eliakincosta/Pictures/debug.svg')) @property def parent(self): return 'toolBar' def debug(self): if self.scripter.uicontroller.invokeAction('save'): self.scripter.uicontroller.setActiveWidget('Debugger') self.scripter.debugcontroller.start(self.scripter.documentcontroller.activeDocument) widget = self.scripter.uicontroller.findStackWidget('Debugger') widget.startDebugger() diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/runaction/runaction.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/runaction/runaction.py index 6a095b0bcf..d19f670082 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/runaction/runaction.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/runaction/runaction.py @@ -1,43 +1,46 @@ from PyQt5.QtWidgets import QAction, QMessageBox from PyQt5.QtGui import QIcon import sys from . import docwrapper +import os 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.findStackWidget('OutPut') self.triggered.connect(self.run) self.setText('Run') # path to the icon - self.setIcon(QIcon('/home/eliakincosta/Pictures/play.svg')) + #self.setIcon(QIcon('/home/eliakincosta/Pictures/play.svg')) @property def parent(self): return 'toolBar' def run(self): - print('roda roda') - 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 + document = self.scripter.uicontroller.invokeAction('save') + + if document: + 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(document.data, document.filePath, "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/editor/pythoneditor.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/pythoneditor.py index 1d6d02bf5d..545589ed04 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/pythoneditor.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/pythoneditor.py @@ -1,149 +1,147 @@ from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtGui import * from scripter.ui_scripter.editor import linenumberarea, debugarea class CodeEditor(QPlainTextEdit): DEBUG_AREA_WIDTH = 20 def __init__(self, scripter, parent=None): super(CodeEditor, self).__init__(parent) self.setLineWrapMode(self.NoWrap) self.scripter = scripter self.lineNumberArea = linenumberarea.LineNumberArea(self) self.debugArea = debugarea.DebugArea(self) - self.debugIcon = QIcon('/home/eliakincosta/Pictures/debug_arrow.svg') self.blockCountChanged.connect(self.updateMarginsWidth) self.updateRequest.connect(self.updateLineNumberArea) self.cursorPositionChanged.connect(self.highlightCurrentLine) self.updateMarginsWidth() self.highlightCurrentLine() self.font = "Monospace" self._stepped = False def debugAreaWidth(self): return self.DEBUG_AREA_WIDTH def lineNumberAreaWidth(self): """The lineNumberAreaWidth is the quatity of decimal places in blockCount""" digits = 1 max_ = max(1, self.blockCount()) while (max_ >= 10): max_ /= 10 digits += 1 space = 3 + self.fontMetrics().width('9') * digits return space def resizeEvent(self, event): super(CodeEditor, self).resizeEvent(event) qRect = self.contentsRect() self.debugArea.setGeometry(QRect(qRect.left(), qRect.top(), self.debugAreaWidth(), qRect.height())) self.lineNumberArea.setGeometry(QRect(qRect.left() + self.debugAreaWidth(), qRect.top(), self.lineNumberAreaWidth(), qRect.height())) def updateMarginsWidth(self): self.setViewportMargins(self.lineNumberAreaWidth() + self.debugAreaWidth(), 0, 0, 0) def updateLineNumberArea(self, rect, dy): """ This slot is invoked when the editors viewport has been scrolled """ if dy: self.lineNumberArea.scroll(0, dy) self.debugArea.scroll(0, dy) else: self.lineNumberArea.update(0, rect.y(), self.lineNumberArea.width(), rect.height()) if rect.contains(self.viewport().rect()): self.updateMarginsWidth() def lineNumberAreaPaintEvent(self, event): """This method draws the current lineNumberArea for while""" painter = QPainter(self.lineNumberArea) painter.fillRect(event.rect(), QColor(Qt.lightGray).darker(300)) block = self.firstVisibleBlock() blockNumber = block.blockNumber() top = int(self.blockBoundingGeometry(block).translated(self.contentOffset()).top()) bottom = top + int(self.blockBoundingRect(block).height()) while block.isValid() and top <= event.rect().bottom(): if block.isVisible() and bottom >= event.rect().top(): number = str(blockNumber + 1) painter.setPen(QColor(Qt.lightGray)) painter.drawText(0, top, self.lineNumberArea.width(), self.fontMetrics().height(), Qt.AlignRight, number) block = block.next() top = bottom bottom = top + int(self.blockBoundingRect(block).height()) blockNumber += 1 def debugAreaPaintEvent(self, event): if self.scripter.debugcontroller.isActive and self.scripter.debugcontroller.currentLine: lineNumber = self.scripter.debugcontroller.currentLine block = self.document().findBlockByLineNumber(lineNumber-1) if self._stepped: cursor = QTextCursor(block) self.setTextCursor(cursor) self._stepped = False top = int(self.blockBoundingGeometry(block).translated(self.contentOffset()).top()) bottom = top + int(self.blockBoundingRect(block).height()) painter = QPainter(self.debugArea) - pixmap = self.debugIcon.pixmap(QSize(self.debugAreaWidth()-3, int(self.blockBoundingRect(block).height()))) - painter.drawPixmap(QPoint(0, top), pixmap) + painter.fillRect(0, top, self.debugAreaWidth()-3, int(self.blockBoundingRect(block).height()), QColor(Qt.yellow).darker(300)) def highlightCurrentLine(self): """Highlight current line under cursor""" currentSelection = QTextEdit.ExtraSelection() lineColor = QColor(Qt.gray).darker(250) currentSelection.format.setBackground(lineColor) currentSelection.format.setProperty(QTextFormat.FullWidthSelection, True) currentSelection.cursor = self.textCursor() currentSelection.cursor.clearSelection() self.setExtraSelections([currentSelection]) def wheelEvent(self, e): """When the CTRL is pressed during the wheelEvent, zoomIn and zoomOut slots are invoked""" if e.modifiers() == Qt.ControlModifier: delta = e.angleDelta().y() if delta < 0: self.zoomOut() elif delta > 0: self.zoomIn() else: super(CodeEditor, self).wheelEvent(e) @property def font(self): return self._font @font.setter def font(self, font): self._font = font self.setFont(QFont(font, 10)) def setStepped(self, status): self._stepped = status def repaintDebugArea(self): self.debugArea.repaint() diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/debuggerwidget.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/debuggerwidget.py index 7bff52d43a..b5ee4e9cea 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/debuggerwidget.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/debuggerwidget.py @@ -1,32 +1,32 @@ -from PyQt5.QtWidgets import QWidget, QVBoxLayout, QToolBar, QTableWidget,QAction -from PyQt5.QtGui import QIcon +from PyQt5.QtWidgets import QWidget, QVBoxLayout, QToolBar, QTableWidget, QAction from . import stepaction, stopaction + class DebuggerWidget(QWidget): def __init__(self, scripter, parent=None): super(DebuggerWidget, self).__init__(parent) self.scripter = scripter self.setObjectName('Debugger') self.layout = QVBoxLayout() - self.toolbar = QToolBar() self.stopAction = stopaction.StopAction(self.scripter, self) + self.toolbar = QToolBar() self.stepAction = stepaction.StepAction(self.scripter, self) self.toolbar.addAction(self.stopAction) self.toolbar.addAction(self.stepAction) self.disableToolbar(True) self.table = QTableWidget(4, 4) self.layout.addWidget(self.toolbar) self.layout.addWidget(self.table) self.setLayout(self.layout) def startDebugger(self): self.disableToolbar(False) def disableToolbar(self, status): for action in self.toolbar.actions(): action.setDisabled(status) diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/stepaction.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/stepaction.py index 2e29722ff1..c210cd9076 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/stepaction.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/stepaction.py @@ -1,23 +1,23 @@ from PyQt5.QtWidgets import QAction from PyQt5.QtGui import QIcon class StepAction(QAction): def __init__(self, scripter, toolbar, parent=None): super(StepAction, self).__init__(parent) self.scripter = scripter self.toolbar = toolbar self.triggered.connect(self.step) self.setText('Step Over') # path to the icon - self.setIcon(QIcon('/home/eliakincosta/Pictures/step.svg')) + #self.setIcon(QIcon('/home/eliakincosta/Pictures/step.svg')) def step(self): status = self.scripter.debugcontroller.isActive if status: self.scripter.debugcontroller.step() else: self.toolbar.disableToolbar(True) diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/stopaction.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/stopaction.py index 3343c9d355..01ca641fd7 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/stopaction.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/stackwidgets/debuggerwidget/stopaction.py @@ -1,20 +1,20 @@ from PyQt5.QtWidgets import QAction from PyQt5.QtGui import QIcon class StopAction(QAction): def __init__(self, scripter, toolbar, parent=None): super(StopAction, self).__init__(parent) self.scripter = scripter self.toolbar = toolbar self.triggered.connect(self.stop) self.setText('Stop') # path to the icon - self.setIcon(QIcon('/home/eliakincosta/Pictures/stop.svg')) + #self.setIcon(QIcon('/home/eliakincosta/Pictures/stop.svg')) def stop(self): self.scripter.debugcontroller.stop() self.toolbar.disableToolbar(True) diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py b/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py index 754aae96ac..e95a2033fb 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py @@ -1,144 +1,146 @@ from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PyQt5.QtCore import * from scripter.ui_scripter.syntax import syntax, syntaxstyles from scripter.ui_scripter.editor import pythoneditor import os import importlib 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.actions = [] self.mainWidget.setWindowModality(Qt.NonModal) def initialize(self, scripter): self.editor = pythoneditor.CodeEditor(scripter) self.widgetSelector = QComboBox() self.stackedWidget = QStackedWidget() self.statusBar = QLabel('untitled') self.highlight = syntax.PythonHighlighter(self.editor.document(), syntaxstyles.DefaultSyntaxStyle()) self.scripter = scripter self.loadMenus() self.loadWidgets() self.loadActions() self.widgetSelector.currentIndexChanged.connect(self._currentIndexChanged) vbox = QVBoxLayout(self.mainWidget) vbox.addWidget(self.menu_bar) vbox.addWidget(self.editor) vbox.addWidget(self.actionToolbar) vbox.addWidget(self.widgetSelector) vbox.addWidget(self.stackedWidget) vbox.addWidget(self.statusBar) self.mainWidget.resize(400, 500) self.mainWidget.setWindowTitle("Scripter") self.mainWidget.setSizeGripEnabled(True) self.addMenu('Edit', 'Edit') self.mainWidget.show() self.mainWidget.activateWindow() def loadMenus(self): self.addMenu('File', 'File') 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 loadActions(self): module_path = 'scripter.ui_scripter.actions' actions_module = importlib.import_module(module_path) modules = [] for class_path in actions_module.action_classes: _module, _klass = class_path.rsplit('.', maxsplit=1) modules.append(dict(module='{0}.{1}'.format(module_path, _module), klass=_klass)) for module in modules: m = importlib.import_module(module['module']) action_class = getattr(m, module['klass']) obj = action_class(self.scripter) parent = self.mainWidget.findChild(QObject, obj.parent) self.actions.append(dict(action=obj, parent=parent)) for action in self.actions: action['parent'].addAction(action['action']) def loadWidgets(self): modulePath = 'scripter.ui_scripter.stackwidgets' widgetsModule = importlib.import_module(modulePath) modules = [] for classPath in widgetsModule.widgetClasses: _module, _klass = classPath.rsplit('.', maxsplit=1) modules.append(dict(module='{0}.{1}'.format(modulePath, _module), klass=_klass)) for module in modules: m = importlib.import_module(module['module']) widgetClass = getattr(m, module['klass']) obj = widgetClass(self.scripter) self.stackedWidget.addWidget(obj) self.widgetSelector.addItem(obj.objectName()) def invokeAction(self, actionName): for action in self.actions: if action['action'].objectName() == actionName: method = getattr(action['action'], actionName) if method: return method() def findStackWidget(self, widgetName): for index in range(self.stackedWidget.count()): widget = self.stackedWidget.widget(index) if widget.objectName() == widgetName: return widget def setDocumentEditor(self, document): self.editor.clear() - self.editor.appendPlainText(document.data) + self.editor.moveCursor(QTextCursor.Start) + self.editor.insertPlainText(document.data) + self.editor.moveCursor(QTextCursor.End) def setStatusBar(self, value='untitled'): self.statusBar.setText(value) def setActiveWidget(self, widgetName): index = self.widgetSelector.findText(widgetName) if index!=-1: self.widgetSelector.setCurrentIndex(index) def setStepped(self, status): self.editor.setStepped(status) def clearEditor(self): self.editor.clear() def _currentIndexChanged(self, index): if index != -1: self.stackedWidget.setCurrentIndex(index) def repaintDebugArea(self): self.editor.repaintDebugArea()