File indexing completed on 2024-06-16 04:17:41

0001 """
0002 SPDX-FileCopyrightText: 2017 Eliakin Costa <eliakim170@gmail.com>
0003 
0004 SPDX-License-Identifier: GPL-2.0-or-later
0005 """
0006 from PyQt5.QtCore import Qt, QObject, QFileInfo, QRect
0007 from PyQt5.QtGui import QTextCursor, QPalette
0008 from PyQt5.QtWidgets import (QToolBar, QMenuBar, QTabWidget,
0009                              QLabel, QVBoxLayout, QMessageBox,
0010                              QSplitter, QSizePolicy)
0011 from .ui_scripter.syntax import syntax, syntaxstyles
0012 from .ui_scripter.editor import pythoneditor
0013 from . import scripterdialog, utils
0014 import importlib
0015 import krita
0016 
0017 KEY_GEOMETRY = "geometry"
0018 DEFAULT_GEOMETRY = QRect(600, 200, 400, 500)
0019 # essentially randomly placed
0020 
0021 
0022 class Elided_Text_Label(QLabel):
0023     mainText = str()
0024 
0025     def __init__(self, parent=None):
0026         super(QLabel, self).__init__(parent)
0027         self.setMinimumWidth(self.fontMetrics().width("..."))
0028         self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
0029 
0030     def setMainText(self, text=str()):
0031         self.mainText = text
0032         self.elideText()
0033 
0034     def elideText(self):
0035         self.setText(self.fontMetrics().elidedText(self.mainText, Qt.ElideRight, self.width()))
0036 
0037     def resizeEvent(self, event):
0038         self.elideText()
0039 
0040 
0041 class UIController(object):
0042     documentModifiedText = ""
0043     documentStatusBarText = "untitled"
0044 
0045     def __init__(self):
0046         self.mainWidget = scripterdialog.ScripterDialog(self)
0047         self.actionToolbar = QToolBar('toolBar', self.mainWidget)
0048         self.menu_bar = QMenuBar(self.mainWidget)
0049 
0050         self.actionToolbar.setObjectName('toolBar')
0051         self.menu_bar.setObjectName('menuBar')
0052 
0053         self.actions = []
0054 
0055         self.mainWidget.setWindowModality(Qt.NonModal)
0056 
0057     def initialize(self, scripter):
0058         self.editor = pythoneditor.CodeEditor(scripter)
0059         self.tabWidget = QTabWidget()
0060         self.statusBar = Elided_Text_Label()
0061         self.statusBar.setMainText('untitled')
0062         self.splitter = QSplitter()
0063         self.splitter.setOrientation(Qt.Vertical)
0064         self.highlight = syntax.PythonHighlighter(self.editor.document(), syntaxstyles.DefaultSyntaxStyle())
0065         p = self.editor.palette()
0066         p.setColor(QPalette.Base, syntaxstyles.DefaultSyntaxStyle()['background'].foreground().color())
0067         p.setColor(QPalette.Text, syntaxstyles.DefaultSyntaxStyle()['foreground'].foreground().color())
0068         self.editor.setPalette(p)
0069 
0070         utils.setNeedDarkIcon(self.mainWidget.palette().window().color())
0071         self.scripter = scripter
0072 
0073         self.loadMenus()
0074         self.loadWidgets()
0075         self.loadActions()
0076         self._readSettings()  # sets window size
0077 
0078         vbox = QVBoxLayout(self.mainWidget)
0079         vbox.addWidget(self.menu_bar)
0080         vbox.addWidget(self.actionToolbar)
0081         self.splitter.addWidget(self.editor)
0082         self.splitter.addWidget(self.tabWidget)
0083         vbox.addWidget(self.splitter)
0084         vbox.addWidget(self.statusBar)
0085 
0086         self.mainWidget.setWindowTitle(i18n("Scripter"))
0087         self.mainWidget.setSizeGripEnabled(True)
0088         self.mainWidget.show()
0089         self.mainWidget.activateWindow()
0090 
0091         self.editor.undoAvailable.connect(self.setStatusModified)
0092 
0093     def loadMenus(self):
0094         self.addMenu(i18n('File'), i18n('File'))
0095 
0096     def addMenu(self, menuName, parentName):
0097         parent = self.menu_bar.findChild(QObject, parentName)
0098         self.newMenu = None
0099 
0100         if parent:
0101             self.newMenu = parent.addMenu(menuName)
0102         else:
0103             self.newMenu = self.menu_bar.addMenu(menuName)
0104 
0105         self.newMenu.setObjectName(menuName)
0106 
0107         return self.newMenu
0108 
0109     def loadActions(self):
0110         module_path = 'scripter.ui_scripter.actions'
0111         actions_module = importlib.import_module(module_path)
0112         modules = []
0113 
0114         for class_path in actions_module.action_classes:
0115             _module = class_path[:class_path.rfind(".")]
0116             _klass = class_path[class_path.rfind(".") + 1:]
0117             modules.append(dict(module='{0}.{1}'.format(module_path, _module),
0118                                 klass=_klass))
0119 
0120         for module in modules:
0121             m = importlib.import_module(module['module'])
0122             action_class = getattr(m, module['klass'])
0123             obj = action_class(self.scripter)
0124             obj_parent = obj.parent
0125             for name in obj_parent:
0126                 parent = self.mainWidget.findChild(QObject, i18n(name))
0127                 self.actions.append(dict(action=obj, parent=parent))
0128 
0129         for action in self.actions:
0130             action['parent'].addAction(action['action'])
0131 
0132     def loadWidgets(self):
0133         modulePath = 'scripter.ui_scripter.tabwidgets'
0134         widgetsModule = importlib.import_module(modulePath)
0135         modules = []
0136 
0137         for class_path in widgetsModule.widgetClasses:
0138             _module = class_path[:class_path.rfind(".")]
0139             _klass = class_path[class_path.rfind(".") + 1:]
0140             modules.append(dict(module='{0}.{1}'.format(modulePath, _module),
0141                                 klass=_klass))
0142 
0143         for module in modules:
0144             m = importlib.import_module(module['module'])
0145             widgetClass = getattr(m, module['klass'])
0146             obj = widgetClass(self.scripter)
0147             self.tabWidget.addTab(obj, obj.objectName())
0148 
0149     def invokeAction(self, actionName):
0150         for action in self.actions:
0151             if action['action'].objectName() == actionName:
0152                 method = getattr(action['action'], actionName)
0153                 if method:
0154                     return method()
0155 
0156     def findTabWidget(self, widgetName, childName=''):
0157         for index in range(self.tabWidget.count()):
0158             widget = self.tabWidget.widget(index)
0159             if widget.objectName() == widgetName:
0160                 if childName:
0161                     widget = widget.findChild(QObject, childName)
0162                 return widget
0163 
0164     def showException(self, exception):
0165         QMessageBox.critical(self.editor, i18n("Error Running Script"), str(exception))
0166 
0167     def setDocumentEditor(self, document):
0168         self.editor.clear()
0169         self.editor.moveCursor(QTextCursor.Start)
0170         self.editor._documentModified = False
0171         self.editor.setPlainText(document.data)
0172         self.editor.moveCursor(QTextCursor.End)
0173 
0174     def setStatusBar(self, value='untitled'):
0175         self.documentStatusBarText = value
0176         self.statusBar.setMainText(self.documentStatusBarText + self.documentModifiedText)
0177 
0178     def setStatusModified(self):
0179         self.documentModifiedText = ""
0180         if (self.editor._documentModified is True):
0181             self.documentModifiedText = " [Modified]"
0182         self.statusBar.setMainText(self.documentStatusBarText + self.documentModifiedText)
0183 
0184     def setActiveWidget(self, widgetName):
0185         widget = self.findTabWidget(widgetName)
0186 
0187         if widget:
0188             self.tabWidget.setCurrentWidget(widget)
0189 
0190     def setStepped(self, status):
0191         self.editor.setStepped(status)
0192 
0193     def clearEditor(self):
0194         self.editor.clear()
0195 
0196     def repaintDebugArea(self):
0197         self.editor.repaintDebugArea()
0198 
0199     def closeScripter(self):
0200         self.mainWidget.close()
0201 
0202     def _writeSettings(self):
0203         """ _writeSettings is a method invoked when the scripter starts, making
0204             control inversion. Actions can implement a writeSettings method to
0205             save your own settings without this method to know about it. """
0206 
0207         self.scripter.settings.beginGroup('scripter')
0208 
0209         document = self.scripter.documentcontroller.activeDocument
0210         if document:
0211             self.scripter.settings.setValue('activeDocumentPath', document.filePath)
0212         else:
0213             self.scripter.settings.setValue('activeDocumentPath', '')
0214 
0215         self.scripter.settings.setValue('editorFontSize', self.editor.fontInfo().pointSize())
0216 
0217         for action in self.actions:
0218             writeSettings = getattr(action['action'], "writeSettings", None)
0219             if callable(writeSettings):
0220                 writeSettings()
0221 
0222         #  Window Geometry
0223         rect = self.mainWidget.geometry()
0224         self.scripter.settings.setValue(KEY_GEOMETRY, rect)
0225 
0226         self.scripter.settings.endGroup()
0227 
0228     def _readSettings(self):
0229         """ It's similar to _writeSettings, but reading the settings when the ScripterDialog is closed. """
0230 
0231         self.scripter.settings.beginGroup('scripter')
0232 
0233         activeDocumentPath = self.scripter.settings.value('activeDocumentPath', '')
0234 
0235         if activeDocumentPath:
0236             if QFileInfo(activeDocumentPath).exists():
0237                 document = self.scripter.documentcontroller.openDocument(activeDocumentPath)
0238                 self.setStatusBar(document.filePath)
0239                 self.setDocumentEditor(document)
0240 
0241         for action in self.actions:
0242             readSettings = getattr(action['action'], "readSettings", None)
0243             if callable(readSettings):
0244                 readSettings()
0245 
0246         pointSize = self.scripter.settings.value('editorFontSize', str(self.editor.fontInfo().pointSize()))
0247         self.editor.setFontSize(int(pointSize))
0248 
0249         # Window Geometry
0250         rect = self.scripter.settings.value(KEY_GEOMETRY, DEFAULT_GEOMETRY)
0251         self.mainWidget.setGeometry(rect)
0252 
0253         self.scripter.settings.endGroup()
0254 
0255     def _saveSettings(self):
0256         self.scripter.settings.sync()