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 index 0000000000..e69de29bb2 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 index 0000000000..e69de29bb2 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 index 0000000000..670cc3936b --- /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 index 0000000000..e69de29bb2 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 index 0000000000..e69de29bb2 diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/scripter.py b/plugins/extensions/pykrita/plugin/plugins/scripter/scripter.py index fd795b69c0..aad884f4e6 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/scripter.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/scripter.py @@ -1,80 +1,22 @@ from PyQt5.QtGui import * 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 index 0000000000..e69de29bb2 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 index 0000000000..e69de29bb2 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 index 0000000000..bf5dcf859e --- /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 index 0000000000..53d15523b5 --- /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 index 0000000000..e69de29bb2 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 index 0000000000..002b3f5f89 --- /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 similarity index 98% rename from plugins/extensions/pykrita/plugin/plugins/scripter/pythoneditor.py rename to plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/pythoneditor.py index 832831feb2..c4ab1be690 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/pythoneditor.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/pythoneditor.py @@ -1,110 +1,112 @@ # -*- 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): super(CodeEditor, self).__init__(parent) self.setLineWrapMode(self.NoWrap) self.lineNumberArea = linenumberarea.LineNumberArea(self) self.blockCountChanged.connect(self.updateLineNumberAreaWidth) self.updateRequest.connect(self.updateLineNumberArea) self.cursorPositionChanged.connect(self.highlightCurrentLine) self.updateLineNumberAreaWidth() self.highlightCurrentLine() self.font = "Monospace" 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.lineNumberArea.setGeometry(QRect(qRect.left(), qRect.top(), self.lineNumberAreaWidth(), qRect.height())); def updateLineNumberAreaWidth(self): self.setViewportMargins(self.lineNumberAreaWidth(), 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) else: self.lineNumberArea.update(0, rect.y(), self.lineNumberArea.width(), rect.height()) if rect.contains(self.viewport().rect()): self.updateLineNumberAreaWidth() 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 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)) 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 index 0000000000..e69de29bb2 diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/syntax.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/syntax/syntax.py similarity index 100% rename from plugins/extensions/pykrita/plugin/plugins/scripter/syntax.py rename to plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/syntax/syntax.py index 2dc67e747d..e144f15217 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/syntax.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/syntax/syntax.py @@ -1,156 +1,156 @@ # 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 * class PythonHighlighter (QSyntaxHighlighter): """Syntax highlighter for the Python language. """ # Python keywords keywords = [ 'and', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'yield', 'None', 'True', 'False', ] # Python operators operators = [ '=', # Comparison '==', '!=', '<', '<=', '>', '>=', # Arithmetic '\+', '-', '\*', '/', '//', '\%', '\*\*', # In-place '\+=', '-=', '\*=', '/=', '\%=', # Bitwise '\^', '\|', '\&', '\~', '>>', '<<', ] # Python braces braces = [ '\{', '\}', '\(', '\)', '\[', '\]', ] def __init__(self, document, syntaxStyle): QSyntaxHighlighter.__init__(self, document) self.syntaxStyle = syntaxStyle self.document = document # Multi-line strings (expression, flag, style) # FIXME: The triple-quotes in these two lines will mess up the # syntax highlighting from this point onward self.tri_single = (QRegExp(r"""'''(?!")"""), 1, 'string2') self.tri_double = (QRegExp(r'''"""(?!')'''), 2, 'string2') rules = [] # Keyword, operator, and brace rules rules += [(r'\b%s\b' % w, 0, 'keyword') for w in PythonHighlighter.keywords] rules += [(r'%s' % o, 0, 'operator') for o in PythonHighlighter.operators] rules += [(r'%s' % b, 0, 'brace') for b in PythonHighlighter.braces] # All other rules rules += [ # 'self' (r'\bself\b', 0, 'self'), # Double-quoted string, possibly containing escape sequences (r'"[^"\\]*(\\.[^"\\]*)*"', 0, 'string'), # Single-quoted string, possibly containing escape sequences (r"'[^'\\]*(\\.[^'\\]*)*'", 0, 'string'), # 'def' followed by an identifier (r'\bdef\b\s*(\w+)', 1, 'defclass'), # 'class' followed by an identifier (r'\bclass\b\s*(\w+)', 1, 'defclass'), # From '#' until a newline (r'#[^\n]*', 0, 'comment'), # Numeric literals (r'\b[+-]?[0-9]+[lL]?\b', 0, 'numbers'), (r'\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b', 0, 'numbers'), (r'\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b', 0, 'numbers'), ] # Build a QRegExp for each pattern self.rules = [(QRegExp(pat), index, identifier) for (pat, index, identifier) in rules] def highlightBlock(self, text): """Apply syntax highlighting to the given block of text.""" # Do other syntax formatting for expression, nth, identifier in self.rules: index = expression.indexIn(text, 0) while index >= 0: # We actually want the index of the nth match index = expression.pos(nth) length = len(expression.cap(nth)) self.setFormat(index, length, self.syntaxStyle[identifier]) index = expression.indexIn(text, index + length) self.setCurrentBlockState(0) # Do multi-line strings in_multiline = self.match_multiline(text, *self.tri_single) if not in_multiline: in_multiline = self.match_multiline(text, *self.tri_double) def match_multiline(self, text, delimiter, in_state, style): """Do highlighting of multi-line strings. ``delimiter`` should be a ``QRegExp`` for triple-single-quotes or triple-double-quotes, and ``in_state`` should be a unique integer to represent the corresponding state changes when inside those strings. Returns True if we're still inside a multi-line string when this function is finished. """ # If inside triple-single quotes, start at 0 if self.previousBlockState() == in_state: start = 0 add = 0 # Otherwise, look for the delimiter on this line else: start = delimiter.indexIn(text) # Move past this match add = delimiter.matchedLength() # As long as there's a delimiter match on this line... while start >= 0: # Look for the ending delimiter end = delimiter.indexIn(text, start + add) # Ending delimiter on this line? if end >= add: length = end - start + add + delimiter.matchedLength() self.setCurrentBlockState(0) # No; multi-line string else: self.setCurrentBlockState(in_state) length = len(text) - start + add # Apply formatting self.setFormat(start, length, self.syntaxStyle[style]) # Look for the next match start = delimiter.indexIn(text, start + length) # Return True if still inside a multi-line string, False otherwise if self.currentBlockState() == in_state: return True else: return False def getSyntaxStyle(self): return self.syntaxStyle def setSyntaxStyle(self, syntaxStyle): self.syntaxStyle = syntaxStyle diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/syntaxstyles.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/syntax/syntaxstyles.py similarity index 96% rename from plugins/extensions/pykrita/plugin/plugins/scripter/syntaxstyles.py rename to plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/syntax/syntaxstyles.py index 07ce7d4d5f..31dab0b1bb 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/syntaxstyles.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/syntax/syntaxstyles.py @@ -1,58 +1,56 @@ -from PyQt5.QtCore import * -from PyQt5.QtWidgets import * from PyQt5.QtGui import * def format(color, style='', darker=100, lighter=100): """Return a QTextCharFormat with the given attributes. """ _color = QColor(color) _color = _color.darker(darker) _color = _color.lighter(lighter) _format = QTextCharFormat() _format.setForeground(_color) if 'bold' in style: _format.setFontWeight(QFont.Bold) if 'italic' in style: _format.setFontItalic(True) return _format class DefaultSyntaxStyle(object): # Syntax styles that combines with dark backgrounds STYLES = { 'keyword': format('cyan'), 'operator': format('orange'), 'brace': format('gray'), 'defclass': format('black', 'bold'), 'string': format('magenta'), 'string2': format('darkMagenta'), 'comment': format('darkGreen', 'italic'), 'self': format('black', 'italic'), 'numbers': format('brown'), } def __getitem__(self, key): return self.STYLES[key] class PythonVimSyntaxStyle(object): """ It based in the colorschemme of the Vim editor for python code http://www.vim.org/scripts/script.php?script_id=790 """ # Syntax styles that combines with dark backgrounds STYLES = { 'keyword': format('yellow', darker=125), 'operator': format('magenta', darker=150), 'brace': format('white'), 'defclass': format('orange', 'bold'), 'string': format('green', lighter=160), 'string2': format('lightGray', 'italic', darker=120), 'comment': format('gray', 'italic'), 'self': format('blue', lighter=170), 'numbers': format('yellow', lighter=130), } def __getitem__(self, key): return self.STYLES[key] 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 index 0000000000..e69de29bb2 diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/fontscombobox.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/fontscombobox.py similarity index 93% rename from plugins/extensions/pykrita/plugin/plugins/scripter/fontscombobox.py rename to plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/fontscombobox.py index cb48437856..56b4bc6d23 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/fontscombobox.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/fontscombobox.py @@ -1,28 +1,29 @@ from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * + class FontsComboBox(QComboBox): def __init__(self, editor, parent=None): super(FontsComboBox, self).__init__(parent) self.editor = editor _fontDataBase = QFontDatabase() self.addItems(_fontDataBase.families()) self.setCurrentIndex(self.findText(self.editor.font)) com = QCompleter() 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) self.currentIndexChanged.connect(self._currentIndexChanged) def _currentIndexChanged(self, index): self.editor.font = self.itemText(index) diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/linenumberarea.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/linenumberarea.py similarity index 99% rename from plugins/extensions/pykrita/plugin/plugins/scripter/linenumberarea.py rename to plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/linenumberarea.py index d7ac02a844..dac284e6d2 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/linenumberarea.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/linenumberarea.py @@ -1,17 +1,19 @@ # -*- coding: utf-8 -*- + from PyQt5.QtWidgets import * from PyQt5.QtCore import * + class LineNumberArea(QWidget): def __init__(self, editor): super(LineNumberArea, self).__init__(editor) self.codeEditor = editor def sizeHint(self): return QSize(self.codeEditor.lineNumberAreaWidth(), 0) def paintEvent(self, event): """It Invokes the draw method(lineNumberAreaPaintEvent) in CodeEditor""" self.codeEditor.lineNumberAreaPaintEvent(event) diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/settingsdialog.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/settingsdialog.py similarity index 70% rename from plugins/extensions/pykrita/plugin/plugins/scripter/settingsdialog.py rename to plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/settingsdialog.py index 5fd411cde6..e5399a1b5e 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/settingsdialog.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/settingsdialog.py @@ -1,15 +1,16 @@ # -*- coding: utf-8 -*- + from PyQt5.QtWidgets import * -from scripter import syntaxstylescombobox, fontscombobox +from ..widgets import syntaxstylescombobox, fontscombobox class SettingsDialog(QDialog): def __init__(self, scripter, parent=None): super(SettingsDialog, self).__init__(parent) 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 similarity index 93% rename from plugins/extensions/pykrita/plugin/plugins/scripter/syntaxstylescombobox.py rename to plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/syntaxstylescombobox.py index 0085570003..59e0a40442 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/syntaxstylescombobox.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/widgets/syntaxstylescombobox.py @@ -1,26 +1,27 @@ # -*- coding: utf-8 -*- + from PyQt5.QtWidgets import * -from scripter import syntaxstyles +from scripter.ui_scripter.syntax import syntaxstyles class SyntaxStylesComboBox(QComboBox): def __init__(self, highlight, parent=None): super(SyntaxStylesComboBox, self).__init__(parent) self.highlight = highlight self.styleClasses = [syntaxstyles.DefaultSyntaxStyle, syntaxstyles.PythonVimSyntaxStyle] for styleClass in self.styleClasses: className = styleClass.__name__ self.addItem(className) if className == type(self.highlight.getSyntaxStyle()).__name__: self.setCurrentIndex(self.findText(className)) self.currentIndexChanged.connect(self._currentIndexChanged) def _currentIndexChanged(self, index): self.highlight.setSyntaxStyle(getattr(syntaxstyles, self.itemText(index))()) self.highlight.rehighlight() diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py b/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py new file mode 100644 index 0000000000..f0c85cef7a --- /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)