Пример #1
0
class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.codeAreas = []
        self.iniManager = IniManager.getInstance()
        self.createComponents()
        self.createMenu()
        self.createLayout()
        self.createConnects()

        self.setWindowTitle('snowEdit')
        self.setWindowIcon(QtGui.QIcon(':icons/snow_logo.png'))
        self.move(100, 100)
        self.show()

    # Slots for file operations

    @QtCore.Slot()
    def onNewFileClicked(self):

        self.codeAreas.append(CodeArea())
        self.tabWidget.addTab(
            self.codeAreas[self.tabWidget.count()], 'new file')

    @QtCore.Slot()
    def onOpenFilesClicked(self):
        location = QtGui.QDesktopServices.storageLocation(
            QtGui.QDesktopServices.HomeLocation)
        files = QtGui.QFileDialog.getOpenFileNames(self, 'Open Files...',
                                                   location)

        for file in files[0]:
            self.checkIfFileOpen(file)

    @QtCore.Slot()
    def onOpenFolderClicked(self):
        location = QtGui.QDesktopServices.storageLocation(
            QtGui.QDesktopServices.HomeLocation)
        folder = QtGui.QFileDialog.getExistingDirectory(self, 'Open Folder...',
                                                        location)
        if folder != '':
            path = self.folderView.model.setRootPath(folder)
            self.folderView.setRootIndex(path)
            self.folderView.folderOpened = True

    @QtCore.Slot()
    def onSaveClicked(self):
        currentEditor = self.codeAreas[self.tabWidget.currentIndex()].codeEdit
        if getFileName(currentEditor.filePath) == 'new file':
            self.onSaveAsClicked()
        else:
            try:
                f = open(currentEditor.filePath, 'w')
                f.write(currentEditor.toPlainText())
                f.close
                currentIndex = self.tabWidget.currentIndex()
                if self.tabWidget.tabText(currentIndex).endswith('*'):
                    tabName = self.tabWidget.tabText(
                        currentIndex).rsplit('*', 1)[0]
                    self.tabWidget.setTabText(currentIndex, tabName)
            except IOError:
                QtGui.QMessageBox.critical(self, 'Error',
                                           'Error, while saving file',
                                           QtGui.QMessageBox.Ok)

    @QtCore.Slot()
    def onSaveAsClicked(self):
        location = QtGui.QDesktopServices.storageLocation(
            QtGui.QDesktopServices.HomeLocation)
        saveLocation = QtGui.QFileDialog.getSaveFileName(self, 'Save file...',
                                                         location,
                                                         'Rush Files (*.rs)')
        if saveLocation[0] != '':
            try:
                currentEditor = self.codeAreas[self.tabWidget.currentIndex()] \
                    .codeEdit
                f = open(saveLocation[0], 'w')
                f.write(currentEditor.toPlainText())
                f.close()
                currentEditor.filePath = saveLocation[0]
                self.tabWidget.setTabText(
                    self.tabWidget.currentIndex(),
                    getFileName(currentEditor.filePath))
                currentEditor.highlighter = chooseHighlighter(
                    currentEditor.document(), currentEditor.filePath)
                self.setHighlighterMenu(currentEditor)
            except IOError:
                QtGui.QMessageBox.critical(
                    self, 'Error', 'Error, while saving file',
                    QtGui.QMessageBox.Ok)

    @QtCore.Slot()
    def onSaveAllClicked(self):
        for i in range(len(self.codeAreas)):
            self.onSaveClicked(i)

    @QtCore.Slot()
    def onOptionsClicked(self):
        self.options = Options(self.codeAreas)

    # Slots for editing

    @QtCore.Slot()
    def undo(self):
        QtGui.QUndoStack
        self.codeAreas[self.tabWidget.currentIndex()].codeEdit.undo()

    @QtCore.Slot()
    def redo(self):
        self.codeAreas[self.tabWidget.currentIndex()].codeEdit.redo()

    @QtCore.Slot()
    def cut(self):
        self.codeAreas[self.tabWidget.currentIndex()].codeEdit.cut()

    @QtCore.Slot()
    def copy(self):
        self.codeAreas[self.tabWidget.currentIndex()].codeEdit.copy()

    @QtCore.Slot()
    def paste(self):
        self.codeAreas[self.tabWidget.currentIndex()].codeEdit.paste()

    @QtCore.Slot()
    def duplicateLine(self):
        self.codeAreas[self.tabWidget.currentIndex()].codeEdit.duplicateLine()


    @QtCore.Slot()
    def commentLine(self):
        self.codeAreas[self.tabWidget.currentIndex()].codeEdit.commentLine()

    @QtCore.Slot()
    def onFindClicked(self):
        self.codeAreas[self.tabWidget.currentIndex()].seFind.show()
        self.codeAreas[self.tabWidget.currentIndex()].seFind._searchLE \
            .setText('')
        self.codeAreas[self.tabWidget.currentIndex()].seFind._searchLE \
            .setFocus()

    def onGotoClicked(self):
        self.codeAreas[self.tabWidget.currentIndex()].seFind.show()
        self.codeAreas[self.tabWidget.currentIndex()].seFind._searchLE \
            .setText('@')
        self.codeAreas[self.tabWidget.currentIndex()].seFind._searchLE \
            .setFocus()

    # Slots for run
    @QtCore.Slot()
    def onRunClicked(self):
        compileArgs = []
        compileArgs.append(self.iniManager.readString('Compiler', 'path'))

        compilerFlags = self.iniManager.readString('Compiler', 'flags')
        compileArgs.extend(compilerFlags.split(" "))

        compileArgs.append('-lang=' + self.langCB.currentText())

        currentFile = self.codeAreas[self.tabWidget.currentIndex()] \
            .codeEdit.filePath
        compileArgs.append(currentFile)

        outputFile = currentFile.rsplit('.', 1)[0]
        if self.langCB.currentText() == 'cs':
            outputFile += '.cs'
        elif self.langCB.currentText() == 'd':
            outputFile += '.d'
        else:
            outputFile += '.cpp'

        output = subprocess.Popen(compileArgs,
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE)
        out, err = output.communicate()

        if output.returncode == 0:
            self.seConsole.writeToConsole(out)
            self.checkIfFileOpen(outputFile)
        elif output.returncode > 0:
            self.seConsole.writeToConsole(err, error=True)
            self.codeAreas[self.tabWidget.currentIndex()].codeEdit \
                .generateError(err)

        self.seConsole.tabWidget.setCurrentIndex(0)

    @QtCore.Slot()
    def onCompilerOptionsClicked(self):
        self.options = Options(self.codeAreas)
        self.options.showStackInt(1)

    #Slots for Optimization
    @QtCore.Slot()
    def onOptimizationClicked(self):
        flags = self.iniManager.readString('Compiler', 'flags')
        noteFlag = False
        if flags.find('-no_tc') >= 0:
            noteFlag = True

        self.seConsole.optProgress.show()
        opt = Optimizer()
        result = opt.optimize(self.codeAreas[self.tabWidget.currentIndex()].
                              codeEdit.toPlainText(),
                              noteFlag, self.seConsole.optProgress)

        self.seConsole.writeToOptimization(result)
        self.seConsole.tabWidget.setCurrentIndex(1)

    # Slots for help menu
    @QtCore.Slot()
    def onAboutClicked(self):
        self.about = About()

    # Slots for folderView
    @QtCore.Slot(QtCore.QModelIndex)
    def openFile(self, index):
        if self.folderView.model.fileInfo(index).isFile():
            fileName = self.folderView.model.filePath(index)
            self.checkIfFileOpen(fileName)

    @QtCore.Slot(QtCore.QModelIndex)
    def rename(self, index):
        if index.isValid():
            input, ok = QtGui.QInputDialog.getText(
                self, 'rename', 'New filename:')

            if ok:
                if self.folderView.model.fileInfo(index).isFile():
                    if not input.endswith('.rs'):
                        input += ".rs"

                oldName = self.folderView.model.filePath(index)
                newName = getPathOnly(oldName) + input
                try:
                    os.rename(oldName, newName)
                except OSError:
                    QtGui.QMessageBox.critical(
                        self, 'Error', 'Error, while renaming file',
                        QtGui.QMessageBox.Ok)

                for i in range(len(self.codeAreas)):
                    if self.codeAreas[i].codeEdit.filePath == oldName:
                        self.codeAreas[i].codeEdit.filePath = newName
                        self.tabWidget.setTabText(i, getFileName(newName))

    @QtCore.Slot(QtCore.QModelIndex)
    def delete(self, index):
        ret = self.createDeleteDialog()
        if ret == QtGui.QMessageBox.Yes:
            self.folderView.model.remove(index)

    @QtCore.Slot(QtCore.QModelIndex)
    def addFile(self, index):
        input, ok = QtGui.QInputDialog.getText(
            self, 'Filename', 'Type in filename:')
        if ok:
            if not input.endswith('.rs'):
                input += '.rs'
            if self.folderView.rootFolderClicked:
                file = open(
                    self.folderView.model.rootPath() + '/' + input, 'w')
                file.close()
            else:
                file = open(
                    self.folderView.model.filePath(index) + '/' + input, 'w')
                file.close()

    @QtCore.Slot(QtCore.QModelIndex)
    def addFolder(self, index):
        input, ok = QtGui.QInputDialog.getText(
            self, 'Foldername', 'Type in foldername:')
        if ok:
            if self.folderView.rootFolderClicked:
                os.mkdir(self.folderView.model.rootPath() + '/' + input)
            else:
                os.mkdir(self.folderView.model.filePath(index) + '/' + input)

    # Highlighting Slots

    @QtCore.Slot()
    def python(self):
        currentEditor = self.codeAreas[self.tabWidget.currentIndex()].codeEdit
        currentEditor.highlighter = PythonHighlighter(currentEditor.document())

    @QtCore.Slot()
    def none(self):
        currentEditor = self.codeAreas[self.tabWidget.currentIndex()].codeEdit
        currentEditor.highlighter = NoneHighlighter(currentEditor.document())

    @QtCore.Slot()
    def rasch(self):
        currentEditor = self.codeAreas[self.tabWidget.currentIndex()].codeEdit
        currentEditor.highlighter = RaschHighlighter(currentEditor.document())

    @QtCore.Slot()
    def cpp(self):
        currentEditor = self.codeAreas[self.tabWidget.currentIndex()].codeEdit
        currentEditor.highlighter = CppHighlighter(currentEditor.document())

    @QtCore.Slot()
    def cs(self):
        currentEditor = self.codeAreas[self.tabWidget.currentIndex()].codeEdit
        currentEditor.highlighter = CsHighlighter(currentEditor.document())

    @QtCore.Slot()
    def d(self):
        currentEditor = self.codeAreas[self.tabWidget.currentIndex()].codeEdit
        currentEditor.highlighter = DHighlighter(currentEditor.document())

    # Misc slots
    @QtCore.Slot()
    def deleteFromCodeEdits(self, index):
        del self.codeAreas[index]

    def createDeleteDialog(self):
        msgBox = QtGui.QMessageBox()
        msgBox.setWindowTitle('Delete')
        msgBox.setIconPixmap(':icons/delete.png')
        msgBox.setWindowIcon(QtGui.QIcon(':icons/delete.png'))
        msgBox.setText('Sure you want to delete the file or' +
                       'folder with all it\'s contents?')
        msgBox.setStandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
        msgBox.setDefaultButton(QtGui.QMessageBox.No)
        ret = msgBox.exec_()
        return ret

    def createComponents(self):
        self.folderView = SeTreeView()
        self.tabWidget = SeTabWidget()
        self.tabWidget.setTabsClosable(True)
        self.seConsole = SeConsole()

    def createMenu(self):

        # FileMenu Actions
        self.newFileAction = QtGui.QAction(
            QtGui.QIcon(':icons/newfile.png'), 'New File', self)
        self.newFileAction.setShortcut('Ctrl+Alt+N')

        self.openFileAction = QtGui.QAction(
            QtGui.QIcon(':icons/open.png'), 'Open Files', self)
        self.openFileAction.setShortcut('Ctrl+O')

        self.openFolderAction = QtGui.QAction(
            QtGui.QIcon(':icons/openFolder.png'), 'Open Folder', self)
        self.openFolderAction.setShortcut('Ctrl+Alt+O')

        self.saveAction = QtGui.QAction(
            QtGui.QIcon(':icons/save.png'), 'Save', self)
        self.saveAction.setShortcut('Ctrl+S')

        self.saveAsAction = QtGui.QAction('&Save as...', self)

        self.saveAllAction = QtGui.QAction(
            QtGui.QIcon(':icons/saveall.png'), 'Save All', self)
        self.saveAllAction.setShortcut('Ctrl+Alt+S')

        self.optionsAction = QtGui.QAction(
            QtGui.QIcon(':icons/options.png'), 'Options', self)
        self.optionsAction.setShortcut('Ctrl+Alt+O')

        self.exitAction = QtGui.QAction(
            QtGui.QIcon(':icons/quit.png'), 'Exit', self)
        self.exitAction.setShortcut('Ctrl+Q')

        # EditMenu Actions
        self.undoAction = QtGui.QAction(
            QtGui.QIcon(':icons/undo.png'), 'Undo', self)
        self.undoAction.setShortcut(QtGui.QKeySequence.Undo)

        self.redoAction = QtGui.QAction(
            QtGui.QIcon(':icons/redo.png'), 'Redo', self)
        self.redoAction.setShortcut(QtGui.QKeySequence.Redo)

        self.cutAction = QtGui.QAction(
            QtGui.QIcon(':icons/cut.png'), 'Cut', self)
        self.cutAction.setShortcut(QtGui.QKeySequence.Cut)

        self.copyAction = QtGui.QAction(
            QtGui.QIcon(':icons/copy.png'), 'Copy', self)
        self.copyAction.setShortcut(QtGui.QKeySequence.Copy)

        self.pasteAction = QtGui.QAction(
            QtGui.QIcon(':icons/paste.png'), 'Paste', self)
        self.pasteAction.setShortcut(QtGui.QKeySequence.Paste)

        self.duplicateLineAction = QtGui.QAction(
            QtGui.QIcon(':icons/duplicate-line.png'), 'Duplicate current line',
            self)
        self.duplicateLineAction.setShortcut('Ctrl+D')

        self.commentLineAction = QtGui.QAction(
            QtGui.QIcon(':icons/comment.png'),
            '(De-)comment current line', self)
        self.commentLineAction.setShortcut('Ctrl+7')

        #find actions
        self.findAction = QtGui.QAction(QtGui.QIcon(':icons/find.png'),
                                        'Find', self)
        self.findAction.setShortcut('Ctrl+F')
        self.gotoAction = QtGui.QAction(QtGui.QIcon(':icons/goto.png'),
                                        'Go to Line', self)
        self.gotoAction.setShortcut('Ctrl+G')

        # Highlightingactions
        highlightActionGroup = QtGui.QActionGroup(self)
        highlightActionGroup.setExclusive(True)

        self.noneAction = QtGui.QAction('None', highlightActionGroup)
        self.noneAction.setCheckable(True)
        self.noneAction.setChecked(True)

        self.pythonAction = QtGui.QAction('Python', highlightActionGroup)
        self.pythonAction.setCheckable(True)

        self.raschAction = QtGui.QAction('Rasch', highlightActionGroup)
        self.raschAction.setCheckable(True)

        self.cppAction = QtGui.QAction('C++', highlightActionGroup)
        self.cppAction.setCheckable(True)

        self.csAction = QtGui.QAction('C#', highlightActionGroup)
        self.csAction.setCheckable(True)

        self.dAction = QtGui.QAction('D', highlightActionGroup)
        self.dAction.setCheckable(True)

        # run actions and widgets
        self.runAction = QtGui.QAction(
            QtGui.QIcon(':icons/run.png'), 'Run', self)
        self.runAction.setShortcut('F5')
        self.compilerOptionsAction = QtGui.QAction('Configure Compiler', self)
        self.langCB = QtGui.QComboBox(self)
        self.langCB.addItem('cpp')
        self.langCB.addItem('cs')
        self.langCB.addItem('d')


        #Optimization Actions
        self.optimizeAction = QtGui.QAction(QtGui.QIcon(':icons/drill.png'),
                                            'Optimize current file', self)
        self.optimizeAction.setShortcut('F9')

        # Help Actions
        self.aboutAction = QtGui.QAction('About', self)

        # Creating file Toolbar
        fileToolBar = self.addToolBar('File')
        fileToolBar.setIconSize(QtCore.QSize(16, 16))
        fileToolBar.addAction(self.newFileAction)
        fileToolBar.addAction(self.openFileAction)
        fileToolBar.addAction(self.openFolderAction)
        fileToolBar.addAction(self.saveAction)
        fileToolBar.addAction(self.saveAllAction)

        # Creating Edit Toolbar
        editToolBar = self.addToolBar('Edit')
        editToolBar.setIconSize(QtCore.QSize(16, 16))
        editToolBar.addAction(self.undoAction)
        editToolBar.addAction(self.redoAction)
        editToolBar.addAction(self.cutAction)
        editToolBar.addAction(self.copyAction)
        editToolBar.addAction(self.pasteAction)
        editToolBar.addAction(self.duplicateLineAction)
        editToolBar.addAction(self.commentLineAction)

        # Creating Run Toolbar
        runToolBar = self.addToolBar('Run')
        runToolBar.setIconSize(QtCore.QSize(16, 16))
        runToolBar.addAction(self.runAction)
        runToolBar.addWidget(self.langCB)

        menuBar = self.menuBar()

        # Creating file menu
        fileMenu = menuBar.addMenu('File')
        fileMenu.addAction(self.newFileAction)
        fileMenu.addAction(self.openFileAction)
        fileMenu.addAction(self.openFolderAction)
        fileMenu.addSeparator()
        fileMenu.addAction(self.saveAction)
        fileMenu.addAction(self.saveAsAction)
        fileMenu.addAction(self.saveAllAction)
        fileMenu.addAction(self.optionsAction)
        fileMenu.addSeparator()
        fileMenu.addAction(self.exitAction)

        # creating edit menu
        editMenu = menuBar.addMenu('Edit')
        editMenu.addAction(self.undoAction)
        editMenu.addAction(self.redoAction)
        editMenu.addSeparator()
        editMenu.addAction(self.cutAction)
        editMenu.addAction(self.copyAction)
        editMenu.addAction(self.pasteAction)
        editMenu.addSeparator()
        editMenu.addAction(self.duplicateLineAction)
        editMenu.addAction(self.commentLineAction)

        #creating find menu
        findMenu = menuBar.addMenu('Find')
        findMenu.addAction(self.findAction)
        findMenu.addAction(self.gotoAction)

        # Creating highlight menu
        highlightMenu = menuBar.addMenu('Highlighting')
        highlightMenu.addAction(self.noneAction)
        highlightMenu.addAction(self.cppAction)
        highlightMenu.addAction(self.csAction)
        highlightMenu.addAction(self.dAction)
        highlightMenu.addAction(self.pythonAction)
        highlightMenu.addAction(self.raschAction)

        # Creating run menu
        runMenu = menuBar.addMenu('Run')
        runMenu.addAction(self.runAction)
        runMenu.addAction(self.compilerOptionsAction)

        #Creating Optimization Menu
        optMenu = menuBar.addMenu('Optimization')
        optMenu.addAction(self.optimizeAction)

        # creating help menu
        helpMenu = menuBar.addMenu('Help')
        helpMenu.addAction(self.aboutAction)

    def createConnects(self):
        # FileMenu Actions
        self.newFileAction.triggered.connect(self.onNewFileClicked)
        self.openFileAction.triggered.connect(self.onOpenFilesClicked)
        self.openFolderAction.triggered.connect(self.onOpenFolderClicked)
        self.saveAction.triggered.connect(self.onSaveClicked)
        self.saveAsAction.triggered.connect(self.onSaveAsClicked)
        self.saveAllAction.triggered.connect(self.onSaveAllClicked)
        self.optionsAction.triggered.connect(self.onOptionsClicked)
        self.exitAction.triggered.connect(self.close)

        # EditMenu Actions
        self.undoAction.triggered.connect(self.undo)
        self.redoAction.triggered.connect(self.redo)
        self.cutAction.triggered.connect(self.cut)
        self.copyAction.triggered.connect(self.copy)
        self.pasteAction.triggered.connect(self.paste)
        self.duplicateLineAction.triggered.connect(self.duplicateLine)
        self.commentLineAction.triggered.connect(self.commentLine)

        #FindEvents
        self.findAction.triggered.connect(self.onFindClicked)
        self.gotoAction.triggered.connect(self.onGotoClicked)

        # HighlightingEvents
        self.pythonAction.triggered.connect(self.python)
        self.noneAction.triggered.connect(self.none)
        self.raschAction.triggered.connect(self.rasch)
        self.cppAction.triggered.connect(self.cpp)
        self.csAction.triggered.connect(self.cs)
        self.dAction.triggered.connect(self.d)

        # Run menu actions
        self.runAction.triggered.connect(self.onRunClicked)
        self.compilerOptionsAction.triggered.connect(
            self.onCompilerOptionsClicked)

        #Optimization Actions
        self.optimizeAction.triggered.connect(self.onOptimizationClicked)

        # HelpMenu Actions
        self.aboutAction.triggered.connect(self.onAboutClicked)

        # Tab driven events
        QtCore.QObject.connect(
            self.tabWidget, QtCore.SIGNAL('tabCloseRequested(int)'),
            self.tabWidget, QtCore.SLOT('deleteTab(int)'))

        QtCore.QObject.connect(
            self.tabWidget, QtCore.SIGNAL('tabCloseRequested(int)'),
            self, QtCore.SLOT('deleteFromCodeEdits(int)'))

        self.connect(
            self.folderView, QtCore.SIGNAL(
                'doubleClicked(const QModelIndex&)'),
            self, QtCore.SLOT('openFile(const QModelIndex&)'))

        # Folder View Events

        self.folderView.openFileAction.triggered.connect(
            lambda: self.openFile(self.folderView.currentIndex()))
        self.folderView.renameAction.triggered.connect(
            lambda: self.rename(self.folderView.currentIndex()))
        self.folderView.deleteAction.triggered.connect(
            lambda: self.delete(self.folderView.currentIndex()))
        self.folderView.addFileAction.triggered.connect(
            lambda: self.addFile(self.folderView.currentIndex()))
        self.folderView.addFolderAction.triggered.connect(
            lambda: self.addFolder(self.folderView.currentIndex()))

    def createLayout(self):
        hlayout = QtGui.QHBoxLayout()
        vlayout = QtGui.QVBoxLayout()

        # self.tabWidget.setMovable(True)
        self.codeAreas.append(CodeArea())
        self.tabWidget.addTab(
            self.codeAreas[self.tabWidget.count()], 'new file')

        vlayout.addWidget(self.tabWidget, 3)
        vlayout.addWidget(self.seConsole, 1)

        hlayout.addWidget(self.folderView, 1)
        hlayout.addLayout(vlayout, 5)

        centralWidget = QtGui.QWidget()
        centralWidget.setLayout(hlayout)
        self.setCentralWidget(centralWidget)

    def setHighlighterMenu(self, editor):
        if editor.filePath.endswith('.py'):
            self.pythonAction.setChecked(True)
        elif editor.filePath.endswith('.rs'):
            self.raschAction.setChecked(True)
        elif editor.filePath.endswith('.cpp') or editor.filePath.endswith('.h'):
            self.cppAction.setChecked(True)
        elif editor.filePath.endswith('.cs'):
            self.csAction.setChecked(True)
        elif editor.filePath.endswith('d'):
            self.dAction.setChecked(True)
        else:
            self.noneAction.setChecked(True)

    def checkIfFileOpen(self, file):
        alreadyOpen = False
        for i in range(len(self.codeAreas)):
            if normalizeSeps(file) == self.codeAreas[i].codeEdit.filePath:
                self.tabWidget.setCurrentIndex(i)
                alreadyOpen = True
                return
        if not alreadyOpen:
            self.codeAreas.append(CodeArea(file))
            currentArea = self.codeAreas[self.tabWidget.count()]
            self.tabWidget.addTab(currentArea,
                                  getFileName(currentArea.codeEdit.filePath))

            self.tabWidget.setCurrentIndex(len(self.codeAreas) - 1)
            self.setHighlighterMenu(
                self.codeAreas[self.tabWidget.count() - 1].codeEdit)

            currentArea.codeEdit.updateCompleter()