29
2019
01

pyqt5实现代码高亮显示

0x01.代码1

# coding:utf-8
from PyQt5 import QtWidgets
from PyQt5.QtCore import *
from PyQt5.Qsci import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import re
import keyword
import os

# 原址:https://blog.csdn.net/xiaoyangyang20/article/details/68923133


class highlight(QsciLexerPython):
    def __init__(self, parent):
        QsciLexerPython.__init__(self, parent)
        font = QFont()
        font.setFamily('Courier')
        font.setPointSize(12)
        font.setFixedPitch(True)
        self.setFont(font)
        self.setColor(QColor(0, 0, 0))
        self.setPaper(QColor(255, 255, 255))
        self.setColor(QColor("#00FF00"), QsciLexerPython.ClassName)
        self.setColor(QColor("#B0171F"), QsciLexerPython.Keyword)
        self.setColor(QColor("#00FF00"), QsciLexerPython.Comment)
        self.setColor(QColor("#FF00FF"), QsciLexerPython.Number)
        self.setColor(QColor("#0000FF"), QsciLexerPython.DoubleQuotedString)
        self.setColor(QColor("#0000FF"), QsciLexerPython.SingleQuotedString)
        self.setColor(QColor("#288B22"), QsciLexerPython.TripleSingleQuotedString)
        self.setColor(QColor("#288B22"), QsciLexerPython.TripleDoubleQuotedString)
        self.setColor(QColor("#0000FF"), QsciLexerPython.FunctionMethodName)
        self.setColor(QColor("#191970"), QsciLexerPython.Operator)
        self.setColor(QColor("#000000"), QsciLexerPython.Identifier)
        self.setColor(QColor("#00FF00"), QsciLexerPython.CommentBlock)
        self.setColor(QColor("#0000FF"), QsciLexerPython.UnclosedString)
        self.setColor(QColor("#FFFF00"), QsciLexerPython.HighlightedIdentifier)
        self.setColor(QColor("#FF8000"), QsciLexerPython.Decorator)
        self.setFont(QFont('Courier', 12, weight=QFont.Bold), 5)
        self.setFont(QFont('Courier', 12, italic=True), QsciLexerPython.Comment)


class MainWindow(QMainWindow):
    def __init__(self, parent=None, title='未命名', filenamearg=None):
        super(MainWindow, self).__init__(parent)
        self.setGeometry(100, 100, 1000, 700)
        self.setWindowTitle(title)
        font = QFont()
        font.setFamily('Courier')
        font.setPointSize(12)
        font.setFixedPitch(True)
        self.setFont(font)
        self.editor = QsciScintilla()
        self.editor.setFont(font)
        self.setCentralWidget(self.editor)
        self.editor.setUtf8(True)
        self.editor.setMarginsFont(font)
        self.editor.setMarginWidth(0, len(str(len(self.editor.text().split('\n')))) * 20)
        self.editor.setMarginLineNumbers(0, True)

        self.editor.setEdgeMode(QsciScintilla.EdgeLine)
        self.editor.setEdgeColumn(80)
        self.editor.setEdgeColor(QColor(0, 0, 0))

        self.editor.setBraceMatching(QsciScintilla.StrictBraceMatch)

        self.editor.setIndentationsUseTabs(True)
        self.editor.setIndentationWidth(4)
        self.editor.setTabIndents(True)
        self.editor.setAutoIndent(True)
        self.editor.setBackspaceUnindents(True)
        self.editor.setTabWidth(4)

        self.editor.setCaretLineVisible(True)
        self.editor.setCaretLineBackgroundColor(QColor('#FFFFCD'))

        self.editor.setIndentationGuides(True)

        self.editor.setFolding(QsciScintilla.PlainFoldStyle)
        self.editor.setMarginWidth(2, 12)

        self.editor.markerDefine(QsciScintilla.Minus, QsciScintilla.SC_MARKNUM_FOLDEROPEN)
        self.editor.markerDefine(QsciScintilla.Plus, QsciScintilla.SC_MARKNUM_FOLDER)
        self.editor.markerDefine(QsciScintilla.Minus, QsciScintilla.SC_MARKNUM_FOLDEROPENMID)
        self.editor.markerDefine(QsciScintilla.Plus, QsciScintilla.SC_MARKNUM_FOLDEREND)

        self.editor.setMarkerBackgroundColor(QColor("#FFFFFF"), QsciScintilla.SC_MARKNUM_FOLDEREND)
        self.editor.setMarkerForegroundColor(QColor("#272727"), QsciScintilla.SC_MARKNUM_FOLDEREND)
        self.editor.setMarkerBackgroundColor(QColor("#FFFFFF"), QsciScintilla.SC_MARKNUM_FOLDEROPENMID)
        self.editor.setMarkerForegroundColor(QColor("#272727"), QsciScintilla.SC_MARKNUM_FOLDEROPENMID)
        self.editor.setAutoCompletionSource(QsciScintilla.AcsAll)
        self.editor.setAutoCompletionCaseSensitivity(True)
        self.editor.setAutoCompletionReplaceWord(False)
        self.editor.setAutoCompletionThreshold(1)
        self.editor.setAutoCompletionUseSingle(QsciScintilla.AcusExplicit)
        self.lexer = highlight(self.editor)
        self.editor.setLexer(self.lexer)
        self.mod = False
        self.__api = QsciAPIs(self.lexer)
        autocompletions = keyword.kwlist + [
            "abs", "all", "any", "basestring", "bool",
            "callable", "chr", "classmethod", "cmp", "compile",
            "complex", "delattr", "dict", "dir", "divmod",
            "enumerate", "eval", "execfile", "exit", "file",
            "filter", "float", "frozenset", "getattr", "globals",
            "hasattr", "hex", "id", "int", "isinstance",
            "issubclass", "iter", "len", "list", "locals", "map",
            "max", "min", "object", "oct", "open", "ord", "pow",
            "property", "range", "reduce", "repr", "reversed",
            "round", "set", "setattr", "slice", "sorted",
            "staticmethod", "str", "sum", "super", "tuple", "type",
            "vars", "zip", 'print']
        for ac in autocompletions:
            self.__api.add(ac)
        self.__api.prepare()
        self.editor.autoCompleteFromAll()
        if filenamearg:
            obj = open(filenamearg, 'r+', encoding='utf-8')
            try:
                self.editor.setText(obj.read())
            except:
                QMessageBox.warning(self, '警告', '无法打开此文件!', QMessageBox.Ok)
                self.editor.document().clear()
        self.statusbar = QtWidgets.QStatusBar(self)
        self.setStatusBar(self.statusbar)
        fileNewAction = self.createAction(
            "新建", self.newfile, 'Ctrl+N', "filenew", "创建Python文件")
        fileOpenAction = self.createAction(
            "打开", self.fileopen, 'Ctrl+O', "fileopen", "打开Python文件")
        self.fileSaveAction = self.createAction(
            "保存", self.save, 'Ctrl+S', "filesave", "保存Python文件")
        self.fileSaveAsAction = self.createAction(
            "另存为", self.saveas, None, "用新名字保存文件")
        fileQuitAction = self.createAction(
            "退出", self.close, "Ctrl+Q", "filequit", "退出")
        self.editCopyAction = self.createAction(
            "撤销", self.editor.undo, 'Ctrl+Z', "editcopy", "撤销")
        self.editCutAction = self.createAction(
            "重做", self.editor.redo, 'Ctrl+Alt+Z', "editcut", "重做")
        self.findAction = self.createAction(
            "查找", self.findtext, 'Ctrl+F', "editcopy", "查找")
        self.replaceAction = self.createAction(
            "替换", None, 'Ctrl+R', "editcut", "替换")
        self.runAction = self.createAction('运行', self.run, 'Ctrl+B', '', '运行程序')
        fileMenu = self.menuBar().addMenu("文件")
        self.addActions(
            fileMenu, (
                fileNewAction, fileOpenAction,
                self.fileSaveAction, self.fileSaveAsAction, None,
                fileQuitAction))
        editMenu = self.menuBar().addMenu("编辑")
        self.addActions(
            editMenu, (
                self.editCopyAction,
                self.editCutAction, None, self.findAction, self.replaceAction))
        runMenu = self.menuBar().addMenu('运行')
        self.addActions(runMenu, (self.runAction,))
        self.name = ''
        self.editor.textChanged.connect(self.changed)
        self.filename = filenamearg

    def run(self):
        if self.windowTitle() == '未命名':
            self.askforsave()
        print(self.windowTitle())
        os.system('call python ' + self.windowTitle())

    def changed(self):
        self.mod = True
        self.editor.setMarginWidth(0, len(str(len(self.editor.text().split('\n')))) * 20)

    def createAction(
            self, text, slot=None, shortcut=None, icon=None,
            tip=None, checkable=False, signal="triggered()"):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(":/{0}.png".format(icon)))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            action.triggered.connect(slot)
        if checkable:
            action.setCheckable(True)
        return action

    def addActions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def askforsave(self):
        if self.mod:
            r = QMessageBox.question(
                self, '询问', '是否要保存?',
                QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
            if r == QMessageBox.Cancel:
                return False
            elif r == QMessageBox.Yes:
                return self.save()
            return True

    def save(self):
        if not self.name:
            return self.saveas()
        self.mod = False
        self.setWindowTitle(self.name)
        obj = open(self.name, 'w', encoding='utf-8')
        obj.truncate()
        obj.close()
        obj = open(self.name, 'r+', encoding='utf-8')
        try:
            obj.write(self.editor.text())
        except:
            obj.write('An error has occcured when trying to save this file.')
        obj.close()

    def saveas(self):
        filename, _buff = QFileDialog.getSaveFileName(self, '另存为', './', 'Python文件 (*.py)')
        if filename:
            self.name = filename
            return self.save()
        return False

    def newfile(self):
        if self.mod:
            if not self.askforsave():
                return -1
        self.editor.clear()
        self.mod = False
        self.name = ''
        self.setWindowTitle('未命名')

    def fileopen(self):
        if self.mod:
            if not self.askforsave():
                return -1
        filename, _buff = QFileDialog.getOpenFileName(self, '另存为', './', 'Python文件 (*.py)')
        if filename:
            self.name = filename
            obj = open(self.name, 'r+', encoding='utf-8')
            try:
                self.editor.setText(obj.read())
            except Exception as e:
                self.editor.setText("Can't read this file!Error:" + str(e))
            obj.close()
            self.setWindowTitle(self.name)
            self.mod = False

    def closeEvent(self, event):
        if not self.askforsave():
            event.ignore()
        event.accept()

    def findtext(self):
        pass


def main():
    import sys
    from os import path
    app = QApplication(sys.argv)
    fname = '未命名'
    if len(sys.argv) > 1:
        if path.isfile(sys.argv[1]):
            fname = sys.argv[1]
    form = MainWindow(None, fname, fname if fname != '未命名' else None)
    form.show()
    app.exec_()


main()

TIM截图20190129171700.png

0x02.代码2

# !/usr/bin/env python3
import os
import sys
from PyQt5.QtCore import (
    QEvent, QFile, QFileInfo, QIODevice, QRegExp, QTextStream, Qt)
from PyQt5.QtWidgets import (
    QAction, QApplication, QFileDialog, QMainWindow, QMessageBox, QTextEdit)
from PyQt5.QtGui import QFont, QIcon, QColor, QKeySequence, QSyntaxHighlighter, \
    QTextCharFormat, QTextCursor

# import qrc_resources

# 原址:http://blog.sina.com.cn/s/blog_c22e36090102x2zk.html

__version__ = "1.1.0"


class PythonHighlighter(QSyntaxHighlighter):
    Rules = []
    Formats = {}

    def __init__(self, parent=None):
        super(PythonHighlighter, self).__init__(parent)

        self.initializeFormats()

        KEYWORDS = [
            "and", "as", "assert", "break", "class",
            "continue", "def", "del", "elif", "else", "except",
            "exec", "finally", "for", "from", "global", "if",
            "import", "in", "is", "lambda", "not", "or", "pass",
            "print", "raise", "return", "try", "while", "with",
            "yield"]
        BUILTINS = [
            "abs", "all", "any", "basestring", "bool",
            "callable", "chr", "classmethod", "cmp", "compile",
            "complex", "delattr", "dict", "dir", "divmod",
            "enumerate", "eval", "execfile", "exit", "file",
            "filter", "float", "frozenset", "getattr", "globals",
            "hasattr", "hex", "id", "int", "isinstance",
            "issubclass", "iter", "len", "list", "locals", "map",
            "max", "min", "object", "oct", "open", "ord", "pow",
            "property", "range", "reduce", "repr", "reversed",
            "round", "set", "setattr", "slice", "sorted",
            "staticmethod", "str", "sum", "super", "tuple", "type",
            "vars", "zip"]
        CONSTANTS = ["False", "True", "None", "NotImplemented",
                     "Ellipsis"]

        PythonHighlighter.Rules.append((QRegExp(
            "|".join([r"\b%s\b" % keyword for keyword in KEYWORDS])),
                                        "keyword"))
        PythonHighlighter.Rules.append((QRegExp(
            "|".join([r"\b%s\b" % builtin for builtin in BUILTINS])),
                                        "builtin"))
        PythonHighlighter.Rules.append((QRegExp(
            "|".join([r"\b%s\b" % constant
                      for constant in CONSTANTS])), "constant"))
        PythonHighlighter.Rules.append((QRegExp(
            r"\b[+-]?[0-9]+[lL]?\b"
            r"|\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b"
            r"|\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b"),
                                        "number"))
        PythonHighlighter.Rules.append((QRegExp(
            r"\bPyQt4\b|\bQt?[A-Z][a-z]\w+\b"), "pyqt"))
        PythonHighlighter.Rules.append((QRegExp(r"\b@\w+\b"),
                                        "decorator"))
        stringRe = QRegExp(r"""(?:'[^']*'|"[^"]*")""")
        stringRe.setMinimal(True)
        PythonHighlighter.Rules.append((stringRe, "string"))
        self.stringRe = QRegExp(r"""(:?"["]".*"["]"|'''.*''')""")
        self.stringRe.setMinimal(True)
        PythonHighlighter.Rules.append((self.stringRe, "string"))
        self.tripleSingleRe = QRegExp(r"""'''(?!")""")
        self.tripleDoubleRe = QRegExp(r'''"""(?!')''')

    @staticmethod
    def initializeFormats():
        baseFormat = QTextCharFormat()
        baseFormat.setFontFamily("courier")
        baseFormat.setFontPointSize(12)
        for name, color in (
                ("normal", Qt.black),
                ("keyword", Qt.darkBlue),
                ("builtin", Qt.darkRed),
                ("constant", Qt.darkGreen),
                ("decorator", Qt.darkBlue),
                ("comment", Qt.darkGreen),
                ("string", Qt.darkYellow),
                ("number", Qt.darkMagenta),
                ("error", Qt.darkRed),
                ("pyqt", Qt.darkCyan)):
            format = QTextCharFormat(baseFormat)
            format.setForeground(QColor(color))
            if name in ("keyword", "decorator"):
                format.setFontWeight(QFont.Bold)
            if name == "comment":
                format.setFontItalic(True)
            PythonHighlighter.Formats[name] = format

    def highlightBlock(self, text):
        NORMAL, TRIPLESINGLE, TRIPLEDOUBLE, ERROR = range(4)

        textLength = len(text)
        prevState = self.previousBlockState()

        self.setFormat(0, textLength,
                       PythonHighlighter.Formats["normal"])

        if text.startswith("Traceback") or text.startswith("Error: "):
            self.setCurrentBlockState(ERROR)
            self.setFormat(0, textLength,
                           PythonHighlighter.Formats["error"])
            return
        if (prevState == ERROR and
                not (text.startswith(sys.ps1) or text.startswith("#"))):
            self.setCurrentBlockState(ERROR)
            self.setFormat(0, textLength,
                           PythonHighlighter.Formats["error"])
            return

        for regex, format in PythonHighlighter.Rules:
            i = regex.indexIn(text)
            while i >= 0:
                length = regex.matchedLength()
                self.setFormat(i, length,
                               PythonHighlighter.Formats[format])
                i = regex.indexIn(text, i + length)

        # Slow but good quality highlighting for comments. For more
        # speed, comment this out and add the following to __init__:
        # PythonHighlighter.Rules.append((QRegExp(r"#.*"), "comment"))
        if not text:
            pass
        elif text[0] == "#":
            self.setFormat(0, len(text),
                           PythonHighlighter.Formats["comment"])
        else:
            stack = []
            for i, c in enumerate(text):
                if c in ('"', "'"):
                    if stack and stack[-1] == c:
                        stack.pop()
                    else:
                        stack.append(c)
                elif c == "#" and len(stack) == 0:
                    self.setFormat(i, len(text),
                                   PythonHighlighter.Formats["comment"])
                    break

        self.setCurrentBlockState(NORMAL)

        if self.stringRe.indexIn(text) != -1:
            return
        # This is fooled by triple quotes inside single quoted strings
        for i, state in ((self.tripleSingleRe.indexIn(text),
                          TRIPLESINGLE),
                         (self.tripleDoubleRe.indexIn(text),
                          TRIPLEDOUBLE)):
            if self.previousBlockState() == state:
                if i == -1:
                    i = text.length()
                    self.setCurrentBlockState(state)
                self.setFormat(0, i + 3,
                               PythonHighlighter.Formats["string"])
            elif i > -1:
                self.setCurrentBlockState(state)
                self.setFormat(i, text.length(),
                               PythonHighlighter.Formats["string"])

    def rehighlight(self):
        QApplication.setOverrideCursor(QCursor(
            Qt.WaitCursor))
        QSyntaxHighlighter.rehighlight(self)
        QApplication.restoreOverrideCursor()


class TextEdit(QTextEdit):

    def __init__(self, parent=None):
        super(TextEdit, self).__init__(parent)

    def event(self, event):
        if (event.type() == QEvent.KeyPress and
                event.key() == Qt.Key_Tab):
            cursor = self.textCursor()
            cursor.insertText("    ")
            return True
        return QTextEdit.event(self, event)


class MainWindow(QMainWindow):

    def __init__(self, filename=None, parent=None):
        super(MainWindow, self).__init__(parent)

        font = QFont("Courier", 11)
        font.setFixedPitch(True)
        self.editor = TextEdit()
        self.editor.setFont(font)
        self.highlighter = PythonHighlighter(self.editor.document())
        self.setCentralWidget(self.editor)

        status = self.statusBar()
        status.setSizeGripEnabled(False)
        status.showMessage("Ready", 5000)

        fileNewAction = self.createAction(
            "&New...", self.fileNew, QKeySequence.New, "filenew",
            "Create a Python file")
        fileOpenAction = self.createAction(
            "&Open...", self.fileOpen, QKeySequence.Open, "fileopen",
            "Open an existing Python file")
        self.fileSaveAction = self.createAction(
            "&Save", self.fileSave, QKeySequence.Save, "filesave", "Save the file")
        self.fileSaveAsAction = self.createAction(
            "Save &As...", self.fileSaveAs, icon="filesaveas",
            tip="Save the file using a new name")
        fileQuitAction = self.createAction(
            "&Quit", self.close, "Ctrl+Q", "filequit", "Close the application")
        self.editCopyAction = self.createAction(
            "&Copy", self.editor.copy, QKeySequence.Copy, "editcopy",
            "Copy text to the clipboard")
        self.editCutAction = self.createAction(
            "Cu&t", self.editor.cut, QKeySequence.Cut, "editcut",
            "Cut text to the clipboard")
        self.editPasteAction = self.createAction(
            "&Paste", self.editor.paste, QKeySequence.Paste, "editpaste",
            "Paste in the clipboard's text")
        self.editIndentAction = self.createAction(
            "&Indent", self.editIndent, "Ctrl+]", "editindent",
            "Indent the current line or selection")
        self.editUnindentAction = self.createAction(
            "&Unindent", self.editUnindent, "Ctrl+[", "editunindent",
            "Unindent the current line or selection")

        fileMenu = self.menuBar().addMenu("&File")
        self.addActions(
            fileMenu, (
                fileNewAction, fileOpenAction,
                self.fileSaveAction, self.fileSaveAsAction, None,
                fileQuitAction))
        editMenu = self.menuBar().addMenu("&Edit")
        self.addActions(
            editMenu, (
                self.editCopyAction,
                self.editCutAction, self.editPasteAction, None,
                self.editIndentAction, self.editUnindentAction))
        fileToolbar = self.addToolBar("File")
        fileToolbar.setObjectName("FileToolBar")
        self.addActions(
            fileToolbar, (
                fileNewAction, fileOpenAction,
                self.fileSaveAction))
        editToolbar = self.addToolBar("Edit")
        editToolbar.setObjectName("EditToolBar")
        self.addActions(
            editToolbar, (
                self.editCopyAction,
                self.editCutAction, self.editPasteAction, None,
                self.editIndentAction, self.editUnindentAction))

        self.editor.selectionChanged.connect(self.updateUi)
        self.editor.document().modificationChanged.connect(self.updateUi)
        QApplication.clipboard().dataChanged.connect(self.updateUi)

        self.resize(800, 600)
        self.setWindowTitle("Python Editor")
        self.filename = filename
        if self.filename is not None:
            self.loadFile()
        self.updateUi()

    def updateUi(self, arg=None):
        self.fileSaveAction.setEnabled(
            self.editor.document().isModified())
        enable = not self.editor.document().isEmpty()
        self.fileSaveAsAction.setEnabled(enable)
        self.editIndentAction.setEnabled(enable)
        self.editUnindentAction.setEnabled(enable)
        enable = self.editor.textCursor().hasSelection()
        self.editCopyAction.setEnabled(enable)
        self.editCutAction.setEnabled(enable)
        self.editPasteAction.setEnabled(self.editor.canPaste())

    def createAction(self, text, slot=None, shortcut=None, icon=None,
                     tip=None, checkable=False, signal="triggered()"):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon("icon/{0}.png".format(icon)))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            action.triggered.connect(slot)
        if checkable:
            action.setCheckable(True)
        return action

    def addActions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def closeEvent(self, event):
        if not self.okToContinue():
            event.ignore()

    def okToContinue(self):
        if self.editor.document().isModified():
            reply = QMessageBox.question(
                self,
                "Python Editor - Unsaved Changes",
                "Save unsaved changes?",
                QMessageBox.Yes | QMessageBox.No |
                QMessageBox.Cancel)
            if reply == QMessageBox.Cancel:
                return False
            elif reply == QMessageBox.Yes:
                return self.fileSave()
        return True

    def fileNew(self):
        if not self.okToContinue():
            return
        document = self.editor.document()
        document.clear()
        document.setModified(False)
        self.filename = None
        self.setWindowTitle("Python Editor - Unnamed")
        self.updateUi()

    def fileOpen(self):
        if not self.okToContinue():
            return
        dir = (os.path.dirname(self.filename)
               if self.filename is not None else ".")
        fname = str(QFileDialog.getOpenFileName(
            self, "Python Editor - Choose File", dir,
            "Python files (*.py *.pyw)")[0])
        if fname:
            self.filename = fname
            self.loadFile()

    def loadFile(self):
        fh = None
        try:
            fh = QFile(self.filename)
            if not fh.open(QIODevice.ReadOnly):
                raise IOError(str(fh.errorString()))
            stream = QTextStream(fh)
            stream.setCodec("UTF-8")
            self.editor.setPlainText(stream.readAll())
            self.editor.document().setModified(False)
        except EnvironmentError as e:
            QMessageBox.warning(
                self, "Python Editor -- Load Error",
                "Failed to load {0}: {1}".format(self.filename, e))
        finally:
            if fh is not None:
                fh.close()
        self.setWindowTitle("Python Editor - {0}".format(
            QFileInfo(self.filename).fileName()))

    def fileSave(self):
        if self.filename is None:
            return self.fileSaveAs()
        fh = None
        try:
            fh = QFile(self.filename)
            if not fh.open(QIODevice.WriteOnly):
                raise IOError(str(fh.errorString()))
            stream = QTextStream(fh)
            stream.setCodec("UTF-8")
            stream << self.editor.toPlainText()
            self.editor.document().setModified(False)
        except EnvironmentError as e:
            QMessageBox.warning(
                self, "Python Editor -- Save Error",
                "Failed to save {0}: {1}".format(self.filename, e))
            return False
        finally:
            if fh is not None:
                fh.close()
        return True

    def fileSaveAs(self):
        filename = self.filename if self.filename is not None else "."
        filename, filetype = QFileDialog.getSaveFileName(
            self, "Python Editor -- Save File As", filename,
            "Python files (*.py *.pyw)")
        if filename:
            self.filename = filename
            self.setWindowTitle("Python Editor - {0}".format(
                QFileInfo(self.filename).fileName()))
            return self.fileSave()
        return False

    def editIndent(self):
        cursor = self.editor.textCursor()
        cursor.beginEditBlock()
        if cursor.hasSelection():
            start = pos = cursor.anchor()
            end = cursor.position()
            if start > end:
                start, end = end, start
                pos = start
            cursor.clearSelection()
            cursor.setPosition(pos)
            cursor.movePosition(QTextCursor.StartOfLine)
            while pos <= end:
                cursor.insertText("    ")
                cursor.movePosition(QTextCursor.Down)
                cursor.movePosition(QTextCursor.StartOfLine)
                pos = cursor.position()
            cursor.setPosition(start)
            cursor.movePosition(QTextCursor.NextCharacter,
                                QTextCursor.KeepAnchor, end - start)
        else:
            pos = cursor.position()
            cursor.movePosition(QTextCursor.StartOfBlock)
            cursor.insertText("    ")
            cursor.setPosition(pos + 4)
        cursor.endEditBlock()

    def editUnindent(self):
        cursor = self.editor.textCursor()
        cursor.beginEditBlock()
        if cursor.hasSelection():
            start = pos = cursor.anchor()
            end = cursor.position()
            if start > end:
                start, end = end, start
                pos = start
            cursor.setPosition(pos)
            cursor.movePosition(QTextCursor.StartOfLine)
            while pos <= end:
                cursor.clearSelection()
                cursor.movePosition(QTextCursor.NextCharacter,
                                    QTextCursor.KeepAnchor, 4)
                if cursor.selectedText() == "    ":
                    cursor.removeSelectedText()
                cursor.movePosition(QTextCursor.Down)
                cursor.movePosition(QTextCursor.StartOfLine)
                pos = cursor.position()
            cursor.setPosition(start)
            cursor.movePosition(QTextCursor.NextCharacter,
                                QTextCursor.KeepAnchor, end - start)
        else:
            cursor.clearSelection()
            cursor.movePosition(QTextCursor.StartOfBlock)
            cursor.movePosition(QTextCursor.NextCharacter,
                                QTextCursor.KeepAnchor, 4)
            if cursor.selectedText() == "    ":
                cursor.removeSelectedText()
        cursor.endEditBlock()


def main():
    app = QApplication(sys.argv)
    app.setWindowIcon(QIcon(":/icon.png"))
    fname = None
    if len(sys.argv) > 1:
        fname = sys.argv[1]
    form = MainWindow(fname)
    form.show()
    app.exec_()


main()

TIM截图20190129171802.png

« 上一篇 下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。