def openFile(self, fn=None): """ Open a file in the editor """ if not self.saved: self.closeOpenedFile() if fn: self.filename = fn else: self.filename = QFileDialog.getOpenFileName( self, 'Open File', self.last_dir) if self.filename: self.last_dir = os.path.split(self.filename)[0] self.textEdit.setReadOnly(self.readOnly) self.saveFileAction.setEnabled(not self.readOnly) if self.filename != None and self.filename != '': file = open(self.filename, 'r') self.file_extension = self.filename.split('.')[-1] self.newFile() with file: text = file.read() self.textEdit.setPlainText(text) self.updateFileState(True)
def saveFileAs(self): """ Save file as """ if not self.opened: return ret = QFileDialog.getSaveFileName(self, 'Save File') if type(ret) == str: self.filename = ret elif type(ret) == tuple: self.filename = ret[0] else: raise Exception( "Uknown return type for 'QFileDialog.getSaveFileName'") self.last_dir = os.path.split(self.filename)[0] if self.filename != None and self.filename != '': file = open(self.filename, 'w') text = self.textEdit.toPlainText() file.write(text) file.close() self.updateFileState(True)
def saveFileAs(self): """ Save file as """ if not self.opened: return self.filename = QFileDialog.getSaveFileName(self, 'Save File') self.last_dir = os.path.split(self.filename)[0] if self.filename != None and self.filename != '': file = open(self.filename, 'w') text = self.textEdit.toPlainText() file.write(text) file.close() self.updateFileState(True)
def __init__(self, parent=None, case_dir=None, readOnly=False, noOpen=False, useHighlight=True): super(QFileEditor, self).__init__(parent) self.setGeometry(50, 50, 500, 300) self.setWindowTitle("code_saturne built-in file editor") self.parent = parent self.case_dir = case_dir if self.case_dir: self.case_name = os.path.split(case_dir)[-1] self.last_dir = case_dir self.readOnly = readOnly self.readerMode = readOnly # Activate text highlight self.useHighlight = useHighlight self.opened = False self.saved = True self.dialog = QFileDialog(self) # Open file action open_img_path = ":/icons/22x22/document-open.png" icon_open = QtGui.QIcon() icon_open.addPixmap(QtGui.QPixmap(_fromUtf8(open_img_path)), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.openFileAction = QAction(icon_open, "Open", self) self.openFileAction.setShortcut("Ctrl+O") self.openFileAction.setStatusTip('Open File') self.openFileAction.triggered.connect(self.openFileForAction) # New file action new_img_path = ":/icons/22x22/document-new.png" icon_new = QtGui.QIcon() icon_new.addPixmap(QtGui.QPixmap(_fromUtf8(new_img_path)), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.newFileAction = QAction(icon_new, "New", self) self.newFileAction.setShortcut("Ctrl+E") self.newFileAction.setStatusTip('Create new file') self.newFileAction.triggered.connect(self.newFile) # Save action save_img_path = ":/icons/22x22/document-save.png" icon_save = QtGui.QIcon() icon_save.addPixmap(QtGui.QPixmap(_fromUtf8(save_img_path)), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.saveFileAction = QAction(icon_save, "Save", self) self.saveFileAction.setShortcut("Ctrl+S") self.saveFileAction.setStatusTip('Save file') self.saveFileAction.triggered.connect(self.saveFile) # Save as action saveas_img_path = ":/icons/22x22/document-save-as.png" icon_saveas = QtGui.QIcon() icon_saveas.addPixmap(QtGui.QPixmap(_fromUtf8(saveas_img_path)), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.saveFileAsAction = QAction(icon_saveas, "Save as", self) self.saveFileAsAction.setStatusTip('Save file as') self.saveFileAsAction.triggered.connect(self.saveFileAs) # Close file action close_img_path = ":/icons/22x22/process-stop.png" icon_close = QtGui.QIcon() icon_close.addPixmap(QtGui.QPixmap(_fromUtf8(close_img_path)), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.closeFileAction = QAction(icon_close, "Close file", self) self.closeFileAction.setShortcut("Ctrl+Q") self.closeFileAction.setStatusTip('Close opened file') self.closeFileAction.triggered.connect(self.closeOpenedFile) # Exit editor action quit_img_path = ":/icons/22x22/system-log-out.png" icon_quit = QtGui.QIcon() icon_quit.addPixmap(QtGui.QPixmap(_fromUtf8(quit_img_path)), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.quitAction = QAction(icon_quit, "Quit", self) self.quitAction.setStatusTip('Quit the editor') self.quitAction.triggered.connect(self.closeApplication) self.statusBar() # File toolbar self.toolbar = self.addToolBar("Options") self.toolbar.addAction(self.newFileAction) if not noOpen: self.toolbar.addAction(self.openFileAction) self.toolbar.addAction(self.saveFileAction) self.toolbar.addAction(self.saveFileAsAction) self.toolbar.addAction(self.closeFileAction) self.toolbar.addAction(self.quitAction) # File menu self.mainMenu = self.menuBar() self.fileMenu = self.mainMenu.addMenu('&File') self.fileMenu.addAction(self.newFileAction) if not noOpen: self.fileMenu.addAction(self.openFileAction) self.fileMenu.addAction(self.saveFileAction) self.fileMenu.addAction(self.saveFileAsAction) self.fileMenu.addAction(self.closeFileAction) self.fileMenu.addAction(self.quitAction) # Explorer self.explorer = self._initFileExplorer() self._initExplorerActions() # Editor self.textEdit = self._initFileEditor() # Settings settings = QtCore.QSettings() try: # API 2 self.restoreGeometry( settings.value("MainWindow/Geometry", QtCore.QByteArray())) self.restoreState( settings.value("MainWindow/State", QtCore.QByteArray())) except: # API 1 self.recentFiles = settings.value("RecentFiles").toStringList() self.restoreGeometry( settings.value("MainWindow/Geometry").toByteArray()) self.restoreState(settings.value("MainWindow/State").toByteArray()) # file attributes self.filename = "" self.file_extension = "" self.mainWidget = FormWidget(self, [self.explorer, self.textEdit]) self.setCentralWidget(self.mainWidget)
class QFileEditor(QMainWindow): """ Editor class. Used for file editing and/or viewing """ # --------------------------------------------------------------- def __init__(self, parent=None, case_dir=None, readOnly=False, noOpen=False, useHighlight=True): super(QFileEditor, self).__init__(parent) self.setGeometry(50, 50, 500, 300) self.setWindowTitle("code_saturne built-in file editor") self.parent = parent self.case_dir = case_dir if self.case_dir: self.case_name = os.path.split(case_dir)[-1] self.last_dir = case_dir self.readOnly = readOnly self.readerMode = readOnly # Activate text highlight self.useHighlight = useHighlight self.opened = False self.saved = True self.dialog = QFileDialog(self) # Open file action open_img_path = ":/icons/22x22/document-open.png" icon_open = QtGui.QIcon() icon_open.addPixmap(QtGui.QPixmap(_fromUtf8(open_img_path)), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.openFileAction = QAction(icon_open, "Open", self) self.openFileAction.setShortcut("Ctrl+O") self.openFileAction.setStatusTip('Open File') self.openFileAction.triggered.connect(self.openFileForAction) # New file action new_img_path = ":/icons/22x22/document-new.png" icon_new = QtGui.QIcon() icon_new.addPixmap(QtGui.QPixmap(_fromUtf8(new_img_path)), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.newFileAction = QAction(icon_new, "New", self) self.newFileAction.setShortcut("Ctrl+E") self.newFileAction.setStatusTip('Create new file') self.newFileAction.triggered.connect(self.newFile) # Save action save_img_path = ":/icons/22x22/document-save.png" icon_save = QtGui.QIcon() icon_save.addPixmap(QtGui.QPixmap(_fromUtf8(save_img_path)), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.saveFileAction = QAction(icon_save, "Save", self) self.saveFileAction.setShortcut("Ctrl+S") self.saveFileAction.setStatusTip('Save file') self.saveFileAction.triggered.connect(self.saveFile) # Save as action saveas_img_path = ":/icons/22x22/document-save-as.png" icon_saveas = QtGui.QIcon() icon_saveas.addPixmap(QtGui.QPixmap(_fromUtf8(saveas_img_path)), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.saveFileAsAction = QAction(icon_saveas, "Save as", self) self.saveFileAsAction.setStatusTip('Save file as') self.saveFileAsAction.triggered.connect(self.saveFileAs) # Close file action close_img_path = ":/icons/22x22/process-stop.png" icon_close = QtGui.QIcon() icon_close.addPixmap(QtGui.QPixmap(_fromUtf8(close_img_path)), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.closeFileAction = QAction(icon_close, "Close file", self) self.closeFileAction.setShortcut("Ctrl+Q") self.closeFileAction.setStatusTip('Close opened file') self.closeFileAction.triggered.connect(self.closeOpenedFile) # Exit editor action quit_img_path = ":/icons/22x22/system-log-out.png" icon_quit = QtGui.QIcon() icon_quit.addPixmap(QtGui.QPixmap(_fromUtf8(quit_img_path)), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.quitAction = QAction(icon_quit, "Quit", self) self.quitAction.setStatusTip('Quit the editor') self.quitAction.triggered.connect(self.closeApplication) self.statusBar() # File toolbar self.toolbar = self.addToolBar("Options") self.toolbar.addAction(self.newFileAction) if not noOpen: self.toolbar.addAction(self.openFileAction) self.toolbar.addAction(self.saveFileAction) self.toolbar.addAction(self.saveFileAsAction) self.toolbar.addAction(self.closeFileAction) self.toolbar.addAction(self.quitAction) # File menu self.mainMenu = self.menuBar() self.fileMenu = self.mainMenu.addMenu('&File') self.fileMenu.addAction(self.newFileAction) if not noOpen: self.fileMenu.addAction(self.openFileAction) self.fileMenu.addAction(self.saveFileAction) self.fileMenu.addAction(self.saveFileAsAction) self.fileMenu.addAction(self.closeFileAction) self.fileMenu.addAction(self.quitAction) # Explorer self.explorer = self._initFileExplorer() self._initExplorerActions() # Editor self.textEdit = self._initFileEditor() # Settings settings = QtCore.QSettings() try: # API 2 self.restoreGeometry( settings.value("MainWindow/Geometry", QtCore.QByteArray())) self.restoreState( settings.value("MainWindow/State", QtCore.QByteArray())) except: # API 1 self.recentFiles = settings.value("RecentFiles").toStringList() self.restoreGeometry( settings.value("MainWindow/Geometry").toByteArray()) self.restoreState(settings.value("MainWindow/State").toByteArray()) # file attributes self.filename = "" self.file_extension = "" self.mainWidget = FormWidget(self, [self.explorer, self.textEdit]) self.setCentralWidget(self.mainWidget) # --------------------------------------------------------------- # --------------------------------------------------------------- def _initFileEditor(self): """ Create the Editor widget based on QTextEdit """ # Font base_font = QtGui.QFont() base_font.setFamily("Courier") base_font.setStyleHint(QtGui.QFont.Monospace) base_font.setFixedPitch(True) base_font.setPointSize(10) font_metrics = QtGui.QFontMetrics(base_font) _tab_string = '' for i in range(_tab_size): _tab_string += ' ' # Main text zone textEdit = CodeEditor() textEdit.setFont(base_font) textEdit.textChanged.connect(self.updateFileState) textEdit.setReadOnly(self.readOnly) policy = textEdit.sizePolicy() policy.setHorizontalPolicy(QSizePolicy.Expanding) textEdit.setSizePolicy(policy) # tab textEdit.setTabStopWidth(font_metrics.width(_tab_string)) return textEdit # --------------------------------------------------------------- # --------------------------------------------------------------- def _initFileExplorer(self, base_dir=None): """ Create the File explorer object based on the QFileSystemModel widget. """ model = QtWidgets.QFileSystemModel() rootp = '' if base_dir: rootp = base_dir elif self.case_dir: rootp = self.case_dir model.setRootPath(rootp) tree = QtWidgets.QTreeView(None) tree.setModel(model) tree.setSortingEnabled(True) tree.setWindowTitle('Explorer') tree.setRootIndex(model.index(rootp)) # Hide unnecessary columns nc = tree.header().count() for i in range(1, nc): tree.hideColumn(i) # Right click menu tree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) tree.customContextMenuRequested.connect(self.explorerContextMenu) # Double click tree.doubleClicked.connect(self._explorerDoubleClick) return tree # --------------------------------------------------------------- # --------------------------------------------------------------- def _initExplorerActions(self): """ Create explorer actions dictionary """ _editAction = QAction(self.explorer.model()) _editAction.setText('Edit file') _editAction.triggered.connect(self._editSelectedFile) _viewAction = QAction(self.explorer.model()) _viewAction.setText('View file') _viewAction.triggered.connect(self._viewSelectedFile) _copyAction = QAction(self.explorer.model()) _copyAction.setText('Copy to SRC') _copyAction.triggered.connect(self._copySelectedFile) _deleteAction = QAction(self.explorer.model()) _deleteAction.setText('Remove from SRC') _deleteAction.triggered.connect(self._removeSelectedFile) _undraftAction = QAction(self.explorer.model()) _undraftAction.setText('Move to SRC') _undraftAction.triggered.connect(self._unDraftSelectedFile) self._explorerActions = { 'edit': _editAction, 'view': _viewAction, 'copy': _copyAction, 'remove': _deleteAction, 'undraft': _undraftAction } # --------------------------------------------------------------- # --------------------------------------------------------------- def _editSelectedFile(self): """ Edit action for mouse right-click """ self.readOnly = False t = "Editor: %s" % (self._currentSelection['filename']) self.setWindowTitle(t) fn = os.path.join(self.case_dir, self._currentSelection['subpath'], self._currentSelection['filename']) self.openFile(fn=fn) # --------------------------------------------------------------- # --------------------------------------------------------------- def _viewSelectedFile(self): """ View action for mouse left-click """ self.readOnly = True t = "Viewer: %s" % (self._currentSelection['filename']) self.setWindowTitle(t) fn = os.path.join(self.case_dir, self._currentSelection['subpath'], self._currentSelection['filename']) self.openFile(fn=fn) # --------------------------------------------------------------- # --------------------------------------------------------------- def _copySelectedFile(self): """ Copy files in subdirectories, such as REFERENCES or EXAMPLES to the SRC folder. Used by the mouse right-click """ src_path = os.path.join(self.case_dir, self._currentSelection['subpath'], self._currentSelection['filename']) if self.case_name == 'SRC': trg_path = os.path.join(self.case_dir, self._currentSelection['filename']) else: sp = self._currentSelection['subpath'] while '/' in sp and len(sp) > 3: e1, e2 = os.path.split(sp) if e2 == 'SRC': break else: sp = e1 trg_path = os.path.join(sp, self._currentSelection['filename']) shutil.copy2(src_path, trg_path) # --------------------------------------------------------------- # --------------------------------------------------------------- def _removeSelectedFile(self): """ Remove a file from the SRC dir """ title = "Remove file" question = "Remove %s from the SRC folder (Stored in DRAFT) ?" % ( self._currentSelection['filename']) choice = QMessageBox.question(self, title, question, QMessageBox.Yes | QMessageBox.No) if choice == QMessageBox.Yes: fn = os.path.join(self.case_dir, self._currentSelection['subpath'], self._currentSelection['filename']) draft = os.path.join(self.case_dir, self._currentSelection['subpath'], 'DRAFT') if not os.path.exists(draft): os.mkdir(draft) fn2 = os.path.join(draft, self._currentSelection['filename']) if os.path.exists(fn2): q = 'A file named %s allready exists in DRAFT.\nDo you want to overwrite it?' % ( self._currentSelection['filename']) choice2 = QMessageBox.question( self, '', q, QMessageBox.Yes | QMessageBox.No) if choice2 == QMessageBox.No: return shutil.move(fn, fn2) else: pass # --------------------------------------------------------------- # --------------------------------------------------------------- def _unDraftSelectedFile(self): """ Move a file from DRAFT to the SRC folder """ title = "Move to SRC" question = "Move file %s from DRAFT to SRC folder ?" % ( self._currentSelection['filename']) choice = QMessageBox.question(self, title, question, QMessageBox.Yes | QMessageBox.No) if choice == QMessageBox.Yes: fn = os.path.join(self.case_dir, self._currentSelection['subpath'], self._currentSelection['filename']) fn2 = os.path.join(self.case_dir, self._currentSelection['filename']) if os.path.exists(fn2): q = 'A file named %s allready exists in SRC\nDo you want to overwrite it?' % ( self._currentSelection['filename']) choice2 = QMessageBox.question( self, '', q, QMessageBox.Yes | QMessageBox.No) if choice2 == QMessageBox.No: return shutil.move(fn, fn2) else: pass # --------------------------------------------------------------- # --------------------------------------------------------------- def _updateCurrentSelection(self): """ Update the current selection """ # Find file position (SRC, REFERENCE, EXAMPLES, other) path2file = '' for idx in self.explorer.selectedIndexes(): fname = idx.data(QtCore.Qt.DisplayRole) c = idx p = c.parent() ps = p.data(QtCore.Qt.DisplayRole) while True: ctxt = c.data(QtCore.Qt.DisplayRole) ptxt = p.data(QtCore.Qt.DisplayRole) if ptxt in [None, self.case_name]: pe = ptxt break path2file = ptxt + '/' + path2file c = p p = c.parent() self._currentSelection = { 'filename': fname, 'subpath': path2file, 'filedir': ps, 'origdir': pe } return # --------------------------------------------------------------- # --------------------------------------------------------------- def _explorerDoubleClick(self): """ Double click action """ self._updateCurrentSelection() clicked = os.path.join(self._currentSelection['subpath'], self._currentSelection['filename']) # To ensure that os.path.isdir works correctly we use the full path # to the object which is selected in the menu if self.case_dir: clicked = os.path.join(self.case_dir, clicked) edit_list = ['SRC'] if not os.path.isdir(clicked): if self._currentSelection['filedir'] in edit_list: self._editSelectedFile() else: self._viewSelectedFile() # --------------------------------------------------------------- # --------------------------------------------------------------- def explorerContextMenu(self, position): """ Custom menu for the mouse right-click. Depends on whether the file is in the SRC, SRC/subfolder or RESU/subfolder. Possible actions are 'edit', 'view' and 'copy' (to SRC) """ self._updateCurrentSelection() path2file = self._currentSelection['subpath'] fname = self._currentSelection['filename'] pe = self._currentSelection['origdir'] ps = self._currentSelection['filedir'] self._contextMenu = QMenu() if (path2file == '' or path2file == None) and self.case_dir: path2file = self.case_dir if pe == 'RESU': if not os.path.isdir(os.path.join(path2file, fname)): self._contextMenu.addAction(self._explorerActions['view']) elif pe == 'SRC': if not os.path.isdir(os.path.join(path2file, fname)): if ps == 'SRC': self._contextMenu.addAction(self._explorerActions['edit']) self._contextMenu.addAction( self._explorerActions['remove']) elif ps in ['EXAMPLES', 'REFERENCE']: self._contextMenu.addAction(self._explorerActions['view']) self._contextMenu.addAction(self._explorerActions['copy']) elif ps in ['DRAFT']: self._contextMenu.addAction(self._explorerActions['view']) self._contextMenu.addAction( self._explorerActions['undraft']) self._contextMenu.exec_(self.explorer.viewport().mapToGlobal(position)) # --------------------------------------------------------------- # --------------------------------------------------------------- def updateFileState(self, new_state=False): """ Update file state (saved or not) """ self.saved = new_state # To ensure syntax highlighting while modifying the text self.textEdit.viewport().update() # --------------------------------------------------------------- # --------------------------------------------------------------- def openFile(self, fn=None): """ Open a file in the editor """ if not self.saved: self.closeOpenedFile() if fn: self.filename = fn else: self.filename = self.dialog.getOpenFileName( self, 'Open File', self.last_dir) self.last_dir = os.path.split(self.filename)[0] self.textEdit.setReadOnly(self.readOnly) self.saveFileAction.setEnabled(not self.readOnly) if self.filename != None and self.filename != '': file = open(self.filename, 'r') self.file_extension = self.filename.split('.')[-1] self.newFile() with file: text = file.read() self.textEdit.setPlainText(text) self.updateFileState(True) def openFileForAction(self, fn=None): if self.readOnly != self.readerMode: self.readOnly = self.readerMode self.openFile(fn) # --------------------------------------------------------------- # --------------------------------------------------------------- def newFile(self): """ Create a new file (blank) """ self.opened = True self.updateFileState(False) if self.useHighlight: hl = QtextHighlighter(self.textEdit.document(), self.file_extension) self.textEdit.show() # --------------------------------------------------------------- # --------------------------------------------------------------- def saveFile(self): """ Save file """ if not self.opened: return if self.filename != None and self.filename != '': file = open(self.filename, 'w') text = self.textEdit.toPlainText() file.write(text) file.close() self.updateFileState(True) else: self.saveFileAs() # --------------------------------------------------------------- # --------------------------------------------------------------- def saveFileAs(self): """ Save file as """ if not self.opened: return self.filename = self.dialog.getSaveFileName(self, 'Save File') self.last_dir = os.path.split(self.filename)[0] if self.filename != None and self.filename != '': file = open(self.filename, 'w') text = self.textEdit.toPlainText() file.write(text) file.close() self.updateFileState(True) # --------------------------------------------------------------- # --------------------------------------------------------------- def closeOpenedFile(self): """ Close an opened file """ if self.saved == False and self.readOnly == False: choice = QMessageBox.question( self, 'Built-in editor', 'File changed.\nDo you want to save?', QMessageBox.Yes | QMessageBox.No) if choice == QMessageBox.Yes: self.saveFile() else: pass self.saved = True self.opened = False self.filename = '' self.textEdit.setPlainText('') # --------------------------------------------------------------- # --------------------------------------------------------------- def closeApplication(self): """ Close the editor """ if self.opened == True: choice = QMessageBox.question(self, 'Built-in editor', "Exit text editor?", QMessageBox.Yes | QMessageBox.No) else: choice = QMessageBox.Yes if choice == QMessageBox.Yes: self.closeOpenedFile() settings = QtCore.QSettings() settings.setValue("MainWindow/Geometry", self.saveGeometry()) self.close() return 0 else: return 1 # --------------------------------------------------------------- # --------------------------------------------------------------- def closeEvent(self, event): decision = self.closeApplication() if decision == 1: event.ignore()