Esempio n. 1
0
class QFileEditor(QMainWindow):
    """
    Editor class. Used for file editing and/or viewing
    """

    # ---------------------------------------------------------------
    def __init__(self,
                 parent=None,
                 case_dir=None,
                 reference_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

        # 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 = Explorer(parent=self,
                                 root_dir=self.case_dir,
                                 dir_type=self.case_name,
                                 case_name=self.case_name)

        # Explorer
        self.explorer_ref = None
        if reference_dir:
            self.explorer_ref = Explorer(parent=self,
                                         root_dir=reference_dir,
                                         dir_type='SHARE',
                                         case_name=self.case_name)

        # 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 = ""

        if self.explorer_ref:
            self.mainWidget = FormWidget(self, [
                self.explorer.explorer, self.explorer_ref.explorer,
                self.textEdit
            ])
        else:
            self.mainWidget = FormWidget(
                self, [self.explorer.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, name="User Files"):
        """
        Create the File explorer object based on the QFileSystemModel widget.
        """

        #model = QtWidgets.QFileSystemModel()
        model = FileSystemModel(name)
        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 _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 in ('SRC', 'DATA'):
            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 in ('SRC', 'DATA'):
                    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 _restoreSelectedFile(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 _deleteSelectedFile(self):
        """
        Remove a file from the SRC dir
        """

        title = "Delete file"
        question = "Really delete %s ?" % (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'])

            try:
                os.remove(fn)
            except Exception:
                # TODO add error popup
                pass

            d = os.path.split(fn)[0]
            if os.path.basename(d) in ('DRAFT', 'STASH'):
                l = os.listdir(d)
                if len(l) < 1:
                    try:
                        os.rmdir(d)
                    except Exception:
                        pass
        else:
            pass

    # ---------------------------------------------------------------

    # ---------------------------------------------------------------
    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 = 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 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 = 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 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()
Esempio n. 2
0
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()
class QCouplingEditor(QMainWindow):
    """
    Independant window
    """

    # ---------------------------------------------------------------
    def __init__(self, parent=None, cfgfile=None, standalone_mode=False):
        """
        Constructor
        """

        super(QCouplingEditor, self).__init__(parent)
        self.setGeometry(50, 50, 500, 300)

        self.setWindowTitle("Coupling parameters editor")
        self.parent = parent
        self.stdalone = standalone_mode

        self.cfgfile = cfgfile

        self.editorView = CouplingEditorView(None, self.cfgfile)

        # If standalone mode, exit if file not loaded
        if self.stdalone:
            if not self.editorView.file_loaded:
                self.close()
                sys.exit(0)
                return None

        # Save file action
        save_img_path = ":/icons/22x22/document-save.png"
        icon_save     = QIcon()
        icon_save.addPixmap(QPixmap(_fromUtf8(save_img_path)),
                            QIcon.Normal,
                            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)

        # Close file action
        close_img_path = ":/icons/22x22/process-stop.png"
        icon_close     = QIcon()
        icon_close.addPixmap(QPixmap(_fromUtf8(close_img_path)),
                             QIcon.Normal,
                             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)

        # Toolbar
        self.toolbar = self.addToolBar("Options")
        self.toolbar.addAction(self.saveFileAction)
        self.toolbar.addAction(self.closeFileAction)

        self.setCentralWidget(self.editorView)
    # ---------------------------------------------------------------

    # ---------------------------------------------------------------
    def saveFile(self):
        """
        Save the configuration file
        """

        self.editorView.save_cfg_file()
        self.editorView.data_modified = False
    # ---------------------------------------------------------------

    # ---------------------------------------------------------------
    def closeOpenedFile(self):
        """
        Close and save if necessary the opened configuration file
        """

        if self.editorView.file_loaded:
            choice = QMessageBox.question(self, 'Coupling parameters editor',
                                          'Exit editor ?',
                                          QMessageBox.Yes | QMessageBox.No)
        else:
            choice = QMessageBox.Yes

        if choice == QMessageBox.Yes:

            if self.editorView.data_modified:
                choice = QMessageBox.question(self, 'Coupling parameters editor',
                                              'Save modifications ?',
                                              QMessageBox.Yes | QMessageBox.No)
                if choice == QMessageBox.Yes:
                    self.saveFile()
                else:
                    pass

            settings = QSettings()
            settings.setValue("MainWindow/Geometry",
                              self.saveGeometry())

            self.editorView.file_loaded = False

            self.close()
            return 0
        else:
            return 1