diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/document_scripter/document.py b/plugins/extensions/pykrita/plugin/plugins/scripter/document_scripter/document.py index 9b87a35983..317a428aac 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/document_scripter/document.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/document_scripter/document.py @@ -1,24 +1,48 @@ from PyQt5.QtCore import QFile, QIODevice, QTextStream class Document(object): def __init__(self, filePath): self._document = [] self._filePath = filePath def open(self, filePath=''): if filePath: self._filePath = filePath _file = QFile(self._filePath) if _file.open(QIODevice.ReadOnly | QIODevice.Text): out = QTextStream(_file) while not out.atEnd(): line = out.readLine() self._document.append(line) _file.close() + def save(self): + with open(self._filePath, 'w') as pythonFile: + for line in self._document: + print(line, file=pythonFile) + + def compare(self, new_doc): + if len(self._document) != len(new_doc): + return False + + for line in range(len(new_doc)): + if new_doc[line] != self._document[line]: + return False + + return True + + @property def data(self): return self._document + + @data.setter + def data(self, data): + self._document = data + + @property + def filePath(self): + return self._filePath diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/documentcontroller.py b/plugins/extensions/pykrita/plugin/plugins/scripter/documentcontroller.py index 890b6aa46c..634cbd29c7 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/documentcontroller.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/documentcontroller.py @@ -1,18 +1,33 @@ from scripter.document_scripter import document class DocumentController(object): def __init__(self): self._activeDocument = None @property def activeDocument(self): return self._activeDocument def openDocument(self, filePath): if filePath: newDocument = document.Document(filePath) newDocument.open() self._activeDocument = newDocument return newDocument + + def saveDocument(self, data, filePath): + if not self._activeDocument: + self._activeDocument = document.Document(filePath) + + dataList = str(data).splitlines() + + if not self._activeDocument.compare(dataList): + self._activeDocument.data = dataList + self._activeDocument.save() + + return self._activeDocument + + def clearActiveDocument(self): + self._activeDocument = None 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 index f2c3be7c21..dfc992b2c7 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/__init__.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/__init__.py @@ -1,3 +1,5 @@ -action_classes = ['openaction.openaction.OpenAction', +action_classes = ['newaction.newaction.NewAction', + 'openaction.openaction.OpenAction', + 'saveaction.saveaction.SaveAction', 'runaction.runaction.RunAction', 'settingsaction.settingsaction.SettingsAction'] diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/newaction/__init__.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/newaction/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/newaction/newaction.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/newaction/newaction.py new file mode 100644 index 0000000000..7a160c3317 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/newaction/newaction.py @@ -0,0 +1,36 @@ +from PyQt5.QtWidgets import QAction, QMessageBox + + +class NewAction(QAction): + + def __init__(self, scripter, parent=None): + super(NewAction, self).__init__(parent) + self.scripter = scripter + + self.triggered.connect(self.new) + + self.setText('New') + self.setObjectName('new') + + @property + def parent(self): + return 'File' + + def new(self): + msgBox = QMessageBox(self.scripter.uicontroller.mainWidget) + + msgBox.setText("The document has been modified."); + msgBox.setInformativeText("Do you want to save your changes?"); + msgBox.setStandardButtons(QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel); + msgBox.setDefaultButton(QMessageBox.Save); + + ret = msgBox.exec(); + + if ret == QMessageBox.Cancel: + return + if ret == QMessageBox.Save: + self.scripter.uicontroller.invokeAction('save') + + self.scripter.documentcontroller.clearActiveDocument() + self.scripter.uicontroller.setStatusBar() + self.scripter.uicontroller.clearEditor() diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/openaction/openaction.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/openaction/openaction.py index 113a9ee61d..ea2054d582 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/openaction/openaction.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/openaction/openaction.py @@ -1,33 +1,36 @@ from PyQt5.QtWidgets import QAction, QFileDialog, QMessageBox + class OpenAction(QAction): def __init__(self, scripter, parent=None): super(OpenAction, self).__init__(parent) self.scripter = scripter self.triggered.connect(self.open) self.setText('Open') + self.setObjectName('open') @property def parent(self): return 'File' def open(self): dialog = QFileDialog(self.scripter.uicontroller.mainWidget) dialog.setNameFilter('Python files (*.py)') if dialog.exec(): try: selectedFile = dialog.selectedFiles()[0] fileExtension = selectedFile.rsplit('.', maxsplit=1)[1] if fileExtension=='py': document = self.scripter.documentcontroller.openDocument(selectedFile) self.scripter.uicontroller.setDocumentEditor(document) + self.scripter.uicontroller.setStatusBar(document.filePath) except: QMessageBox.information(self.scripter.uicontroller.mainWidget, 'Invalid File', 'Open files with .py extension') diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/saveaction/__init__.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/saveaction/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/saveaction/saveaction.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/saveaction/saveaction.py new file mode 100644 index 0000000000..8109c8bf81 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/saveaction/saveaction.py @@ -0,0 +1,38 @@ +from PyQt5.QtWidgets import QAction, QFileDialog + +class SaveAction(QAction): + + def __init__(self, scripter, parent=None): + super(SaveAction, self).__init__(parent) + self.scripter = scripter + self.editor = self.scripter.uicontroller.editor + + self.triggered.connect(self.save) + + self.setText('Save') + self.setObjectName('save') + + @property + def parent(self): + return 'File' + + def save(self): + text = self.editor.toPlainText() + fileName = '' + + if not self.scripter.documentcontroller.activeDocument: + fileName = QFileDialog.getSaveFileName(self.scripter.uicontroller.mainWidget, + 'Save Python File', '', + 'Python File (*.py)')[0] + if not fileName: + return + + fileExtension = fileName.rsplit('.', maxsplit=1)[1] + if not fileExtension=='py': + return + + document = self.scripter.documentcontroller.saveDocument(text, fileName) + if document: + self.scripter.uicontroller.setStatusBar(document.filePath) + else: + self.scripter.uicontroller.setStatusBar('untitled') diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/linenumberarea.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/linenumberarea.py index dac284e6d2..564ecb7df3 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/linenumberarea.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/linenumberarea.py @@ -1,19 +1,16 @@ -# -*- 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/ui_scripter/editor/statusbar.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/statusbar.py new file mode 100644 index 0000000000..a0f89628a2 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/editor/statusbar.py @@ -0,0 +1,16 @@ +from PyQt5.QtWidgets import * +from PyQt5.QtCore import * + + +class StatusBar(QWidget): + + def __init__(self, editor): + super(StatusBar, self).__init__(editor) + self.codeEditor = editor + + def sizeHint(self): + return QSize(self.codeEditor.width(), 0) + + def paintEvent(self, event): + """It Invokes the draw method(statusBarPaintEvent) in CodeEditor""" + self.codeEditor.statusBarPaintEvent(event) diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py b/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py index 725dda4a46..e846dc7ba3 100644 --- a/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/uicontroller.py @@ -1,87 +1,102 @@ 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) self.editor = pythoneditor.CodeEditor() self.output = QPlainTextEdit() + self.statusBar = QLabel('untitled') self.highlight = syntax.PythonHighlighter(self.editor.document(), syntaxstyles.DefaultSyntaxStyle()) def initialize(self, scripter): self.scripter = scripter self.loadMenus() self.loadActions() vbox = QVBoxLayout(self.mainWidget) vbox.addWidget(self.menu_bar) vbox.addWidget(self.editor) vbox.addWidget(self.actionToolbar) vbox.addWidget(self.output) + vbox.addWidget(self.statusBar) 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 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 invokeAction(self, actionName): + for action in self.actions: + if action['action'].objectName() == actionName: + method = getattr(action['action'], actionName) + if method: + return method() + def setDocumentEditor(self, document): self.editor.clear() - for line in document.data(): + for line in document.data: self.editor.appendPlainText(line) + + def setStatusBar(self, value='untitled'): + self.statusBar.setText(value) + + def clearEditor(self): + self.editor.clear()