Exemplo n.º 1
0
class Editor(QPlainTextEdit):
    def __init__(self, parent):
        super().__init__(parent)
        self.lineNumberArea = QLineNumberArea(self)
        self.blockCountChanged.connect(self.updateLineNumberAreaWidth)
        self.updateRequest.connect(self.updateLineNumberArea)
        self.cursorPositionChanged.connect(self.highlightCurrentLine)
        self.updateLineNumberAreaWidth(0)
        self.parent = parent
        self.font = QFont()
        self.size = 12
        self.dialog = MessageBox(self)
        self.menu_font = QFont()
        self.menu_font.setFamily("Iosevka")
        self.menu_font.setPointSize(10)
        self.font.setFamily(editor["editorFont"])
        self.font.setPointSize(editor["editorFontSize"])
        self.focused = None
        self.text = None
        self.replace_tabs = 4
        self.setWordWrapMode(4)
        self.setFont(self.font)
        self.l = 0
        self.highlightingRules = []
        self.indexes = None

        self.setTabStopWidth(editor["TabWidth"])
        self.createStandardContextMenu()
        self.setWordWrapMode(QTextOption.NoWrap)

    def getTextCursor(self):
        textCursor = self.textCursor()
        textCursorPos = textCursor.position()

        return textCursor, textCursorPos

    def get_linenumbers(self):
        return self.blockCount()

    def check(self):
        cursor = self.textCursor()
        b = cursor.block()
        extraSelections = []
        if len(b.text()) > 120:
            selection = QTextEdit.ExtraSelection()
            # TODO: implement something using flake8
            selection.format.setFontUnderline(True)
            selection.format.setUnderlineColor(QColor("#FF0000"))

            selection.format.setUnderlineStyle(
                QTextCharFormat.SpellCheckUnderline)
            selection.format.setProperty(QTextFormat.FullWidthSelection, True)

            selection.cursor = self.textCursor()
            selection.cursor.clearSelection()

            extraSelections.append(selection)
            self.setExtraSelections(extraSelections)

            font = QFont()
            font.setFamily("Iosevka")
            font.setPointSize(10)

            QToolTip.setFont(font)
            cursor = self.textCursor()
            current_line = cursor.positionInBlock()
            QToolTip.showText(
                QCursor.pos(), "Line too long (" + str(current_line) +
                "> 120) | violation on line: " + str(b.blockNumber() + 1))

    def newFile(self):
        """This is a wrapper for the function defined in Main"""

        self.new_action = QAction("New")
        self.new_action.triggered.connect(self.parent.parent.newFile)

    def lineNumberAreaWidth(self):
        digits = 1
        max_value = max(1, self.blockCount())
        while max_value >= 10:
            max_value /= 10
            digits += 1
        space = 10 + self.fontMetrics().width('9') * digits
        return space

    def updateLineNumberAreaWidth(self, _):
        self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0)

    def updateLineNumberArea(self, rect, dy):
        if dy:
            self.lineNumberArea.scroll(0, dy)
        else:
            self.lineNumberArea.update(0, rect.y(),
                                       self.lineNumberArea.width(),
                                       rect.height())
        if rect.contains(self.viewport().rect()):
            self.updateLineNumberAreaWidth(0)

    def resizeEvent(self, event):
        super().resizeEvent(event)
        cr = self.contentsRect()
        self.lineNumberArea.setGeometry(
            QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(),
                  cr.height()))

    def highlightCurrentLine(self):
        extraSelections = []
        if not self.isReadOnly():
            selection = QTextEdit.ExtraSelection()
            lineColor = QColor("#434343")
            selection.format.setBackground(lineColor)
            selection.format.setProperty(QTextFormat.FullWidthSelection, True)
            selection.cursor = self.textCursor()
            selection.cursor.clearSelection()
            extraSelections.append(selection)
        self.setExtraSelections(extraSelections)
        self.check()

    def lineNumberAreaPaintEvent(self, event):
        painter = QPainter(self.lineNumberArea)

        painter.fillRect(event.rect(), QColor("#303030"))

        block = self.firstVisibleBlock()
        blockNumber = block.blockNumber()
        top = self.blockBoundingGeometry(block).translated(
            self.contentOffset()).top()
        bottom = top + self.blockBoundingRect(block).height()

        # Just to make sure I use the right font
        height = self.fontMetrics().height()

        while block.isValid() and (top <= event.rect().bottom()):
            if block.isVisible() and (bottom >= event.rect().top()):
                number = str(blockNumber + 1)
                painter.setPen(Qt.white)
                painter.drawText(0, top, self.lineNumberArea.width(), height,
                                 Qt.AlignCenter, number)

            block = block.next()
            top = bottom
            bottom = top + self.blockBoundingRect(block).height()
            blockNumber += 1

    def openFile(self):

        self.open_action = QAction("Open")
        self.open_action.triggered.connect(self.parent.parent.openFileFromMenu)

    def runFile(self):

        self.run_action = QAction("Run")
        self.run_action.triggered.connect(self.parent.parent.terminal)

    def textUnderCursor(self):
        textCursor = self.textCursor()
        textCursor.select(QTextCursor.WordUnderCursor)

        return textCursor.selectedText()

    def contextMenuEvent(self, event):

        menu = QMenu()
        """Initializing actions"""
        self.newFile()
        self.openFile()
        self.runFile()
        menu.addAction(self.new_action)
        menu.addAction(self.open_action)
        menu.addAction(self.run_action)

        menu.setFont(self.menu_font)

        menu.exec(event.globalPos())
        del menu

    def moveCursorPosBack(self):
        textCursor = self.textCursor()
        textCursorPos = textCursor.position()

        textCursor.setPosition(textCursorPos - 1)
        self.setTextCursor(textCursor)

    def mousePressEvent(self, e):

        self.check()
        if QApplication.queryKeyboardModifiers() == Qt.ControlModifier:
            if self.text is not None:
                self.check_func("lol")
                url = "https://docs.python.org/3/library/functions.html#" + self.text
                word = self.text
                self.parent.parent.showBrowser(url, word)
        QApplication.restoreOverrideCursor()
        super().mousePressEvent(e)

    def check_func(self, word):
        funcs = [
            "abs", "all", "any", "ascii", "bin", "bool", "breakpoint",
            "bytearray", "bytes", "callable", "chr", "classmethod", "compile",
            "complex", "delattr", "dict", "dir", "divmod", "enumerate", "eval",
            "exec", "filter", "float", "format", "frozenset", "getattr",
            "globals", "hasattr", "hash", "help", "hex", "id", "input", "int",
            "isinstance", "issubclass", "iter", "len", "list", "locals", "map",
            "max", "memoryview", "min", "next", "object", "oct", "open", "ord",
            "pow", "print", "property", "range", "repr", "reversed", "round",
            "set", "setattr", "slice", "sorted", "staticmethod", "str", "sum",
            "super", "tuple", "type", "vars", "zip", "__import__"
        ]
        word_array = list(word)
        for wo in word_array:
            if wo in ["{", "}", "'", '"', "[", "]", "(", ")"]:
                word_array.remove(wo)
        for w in funcs:
            if w == "".join(word_array):
                print("".join(word_array))
                return True

    def mouseReleaseEvent(self, e):

        self.check()
        super().mouseReleaseEvent(e)

    def keyPressEvent(self, e):
        textCursor = self.textCursor()
        key = e.key()
        if key == Qt.Key_H:
            # self.parent.completer.wordList
            # TODO: implement dynamic completion
            pass

        if e.modifiers(
        ) == Qt.ControlModifier and key == 16777217:  # that key code stands for tab
            self.parent.parent.switchTabs()

        isSearch = (e.modifiers() == Qt.ControlModifier
                    and e.key() == Qt.Key_F)

        if isSearch:
            try:
                currentWidget = self.parent
                currentFile = currentWidget.fileName
                currentEditor = currentWidget.editor

                textCursor = currentEditor.textCursor()
                textCursorPos = textCursor.position()

            except (AttributeError, UnboundLocalError) as E:
                print(E, " on line 228 in the file Editor.py")

            if currentWidget is not None:
                text, okPressed = QInputDialog.getText(self, 'Find',
                                                       'Find what: ')
                if okPressed:
                    if text == "":
                        text = " "
                        self.dialog.noMatch(text)
                    self.searchtext = text
                    try:
                        with open(currentFile, 'r') as file:
                            contents = file.read()
                            self.indexes = list(find_all(contents, text))
                            if len(self.indexes) == 0:
                                self.dialog.noMatch(text)

                    except FileNotFoundError as E:
                        print(E, " on line 245 in the file Editor.py")

        if key == Qt.Key_QuoteDbl:
            self.insertPlainText('"')
            self.moveCursorPosBack()

        if key == 16777249:  # This code stands for CTRL
            if self.check_func(self.textUnderCursor()):
                extraSelections = []
                selection = QTextEdit.ExtraSelection()
                selection.format.setFontUnderline(True)
                selection.format.setUnderlineColor(QColor("#00d2ff"))
                selection.format.setBackground(QColor("#00d2ff"))
                selection.format.setProperty(QTextFormat.FullWidthSelection,
                                             True)

                selection.cursor = self.textCursor()
                selection.cursor.clearSelection()
                selection.cursor.select(QTextCursor.WordUnderCursor)
                extraSelections.append(selection)
                self.setExtraSelections(extraSelections)
                self.text = self.textUnderCursor()
                QApplication.setOverrideCursor(Qt.PointingHandCursor)
            else:
                self.text = None

        if e.modifiers() == Qt.ControlModifier and e.key(
        ) == 61:  # Press Ctrl+Equal key to make font bigger

            self.font.setPointSize(self.size + 1)
            self.font.setFamily(editor["editorFont"])
            self.setFont(self.font)
            self.size += 1

        if e.modifiers() == Qt.ControlModifier and e.key() == 16777217:
            return

        if e.modifiers() == Qt.ControlModifier and e.key(
        ) == 45:  # Press Ctrl+Minus key to make font smaller

            self.font.setPointSize(self.size - 1)

            self.font.setFamily(editor["editorFont"])
            self.setFont(self.font)
            self.size -= 1

        if key == Qt.Key_F3:
            try:
                index = self.indexes[0 + self.l]
                currentWidget = self.parent
                currentFile = currentWidget.fileName
                currentEditor = currentWidget.editor
                textCursor.setPosition(index)
                textCursor.movePosition(textCursor.Right,
                                        textCursor.KeepAnchor,
                                        len(self.searchtext))
                currentEditor.setTextCursor(textCursor)
                self.l += 1
            except IndexError:
                self.l = 0

        if key == 39:
            self.insertPlainText("'")
            self.moveCursorPosBack()

        if key == Qt.Key_BraceLeft:
            self.insertPlainText("}")
            self.moveCursorPosBack()

        if key == Qt.Key_BracketLeft:
            self.insertPlainText("]")
            self.moveCursorPosBack()

        if key == Qt.Key_ParenLeft:
            self.insertPlainText(")")
            self.moveCursorPosBack()

        if key == Qt.Key_ParenRight:
            textCursor = self.textCursor()
            textCursor.select(QTextCursor.WordUnderCursor)
            if textCursor.selectedText(
            ) == "()" or "()" in textCursor.selectedText():
                return

        if key == Qt.Key_BraceRight:
            textCursor = self.textCursor()
            textCursor.select(QTextCursor.WordUnderCursor)
            if textCursor.selectedText == "":
                return
        if key == 16777219:
            if self.textUnderCursor() in ['""', '()', '[]', "''", "{}"]:
                textCursor = self.textCursor()
                textCursorPos = textCursor.position()

                textCursor.setPosition(textCursorPos + 1)
                textCursor.deletePreviousChar()
                self.setTextCursor(textCursor)
        if key not in [16777217, 16777219, 16777220]:
            super().keyPressEvent(e)
            return

        e.accept()
        cursor = self.textCursor()
        if key == 16777217:  # and self.replace_tabs:
            amount = 4 - self.textCursor().positionInBlock() % 4
            self.insertPlainText(' ' * amount)

        elif key == 16777219 and cursor.selectionStart() == cursor.selectionEnd() and self.replace_tabs and \
                cursor.positionInBlock():
            position = cursor.positionInBlock()
            end = cursor.position()
            start = end - (position % 4)

            if start == end and position >= 4:
                start -= 4

            string = self.toPlainText()[start:end]
            if not len(string.strip()
                       ):  # if length is 0 which is binary for false
                for i in range(end - start):
                    cursor.deletePreviousChar()
            else:
                super().keyPressEvent(e)

        elif key == 16777220:
            end = cursor.position()
            start = end - cursor.positionInBlock()
            line = self.toPlainText()[start:end]
            indentation = len(line) - len(line.lstrip())

            chars = '\t'
            if self.replace_tabs:
                chars = '    '
                indentation /= self.replace_tabs

            if line.endswith(':'):
                if self.replace_tabs:
                    indentation += 1

            super().keyPressEvent(e)
            self.insertPlainText(chars * int(indentation))

        else:
            super().keyPressEvent(e)
Exemplo n.º 2
0
class Editor(QPlainTextEdit):
    def __init__(self, parent):
        super().__init__(parent)
        self.lineNumberArea = QLineNumberArea(self)
        self.blockCountChanged.connect(self.updateLineNumberAreaWidth)
        self.updateRequest.connect(self.updateLineNumberArea)
        self.textChanged.connect(self.check)
        self.cursorPositionChanged.connect(self.highlightCurrentLine)
        self.updateLineNumberAreaWidth(0)
        self.parent = parent
        self.font = QFont()
        self.size = 12
        self.dialog = MessageBox()
        self.menu_font = QFont()
        self.menu_font.setFamily("Iosevka")
        self.menu_font.setPointSize(10)
        self.font.setFamily(editor["editorFont"])
        self.font.setPointSize(editor["editorFontSize"])
        self.focused = None

        self.replace_tabs = 4
        self.setWordWrapMode(4)
        self.setFont(self.font)
        self.l = 0
        self.highlightingRules = []
        self.indexes = None

        self.setTabStopWidth(editor["TabWidth"])
        self.createStandardContextMenu()
        self.setWordWrapMode(QTextOption.NoWrap)

    def get_linenumbers(self):
        return self.blockCount()

    def check(self):
        cursor = self.textCursor()
        b = cursor.block()
        if len(b.text()) >= 79:
            print("pep 8 violation on line: " + str(b.blockNumber() + 1))

    def newFile(self):
        """This and most of the functions below will just be wrappers for the functions defined in Main"""
        self.new_action = QAction("New")
        self.new_action.triggered.connect(self.parent.parent.newFile)

    def lineNumberAreaWidth(self):
        digits = 1
        max_value = max(1, self.blockCount())
        while max_value >= 10:
            max_value /= 10
            digits += 1
        space = 10 + self.fontMetrics().width('9') * digits
        return space

    def updateLineNumberAreaWidth(self, _):
        self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0)

    def updateLineNumberArea(self, rect, dy):
        if dy:
            self.lineNumberArea.scroll(0, dy)
        else:
            self.lineNumberArea.update(0, rect.y(),
                                       self.lineNumberArea.width(),
                                       rect.height())
        if rect.contains(self.viewport().rect()):
            self.updateLineNumberAreaWidth(0)

    def resizeEvent(self, event):
        super().resizeEvent(event)
        cr = self.contentsRect()
        self.lineNumberArea.setGeometry(
            QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(),
                  cr.height()))

    def highlightCurrentLine(self):
        extraSelections = []
        if not self.isReadOnly():
            selection = QTextEdit.ExtraSelection()
            lineColor = QColor("#434343")
            selection.format.setBackground(lineColor)
            selection.format.setProperty(QTextFormat.FullWidthSelection, True)
            selection.cursor = self.textCursor()
            selection.cursor.clearSelection()
            extraSelections.append(selection)
        self.setExtraSelections(extraSelections)

    def lineNumberAreaPaintEvent(self, event):
        painter = QPainter(self.lineNumberArea)

        painter.fillRect(event.rect(), QColor("#303030"))

        block = self.firstVisibleBlock()
        blockNumber = block.blockNumber()
        top = self.blockBoundingGeometry(block).translated(
            self.contentOffset()).top()
        bottom = top + self.blockBoundingRect(block).height()

        # Just to make sure I use the right font
        height = self.fontMetrics().height()

        while block.isValid() and (top <= event.rect().bottom()):
            if block.isVisible() and (bottom >= event.rect().top()):
                number = str(blockNumber + 1)
                painter.setPen(Qt.white)
                painter.drawText(0, top, self.lineNumberArea.width(), height,
                                 Qt.AlignCenter, number)

            block = block.next()
            top = bottom
            bottom = top + self.blockBoundingRect(block).height()
            blockNumber += 1

    def openFile(self):

        self.open_action = QAction("Open")
        self.open_action.triggered.connect(self.parent.parent.openFileFromMenu)

    def runFile(self):

        self.run_action = QAction("Run")
        self.run_action.triggered.connect(self.parent.parent.terminal)

    def contextMenuEvent(self, event):

        menu = QMenu()
        """Initializing actions"""
        self.newFile()
        self.openFile()
        self.runFile()
        print("aa")
        menu.addAction(self.new_action)
        menu.addAction(self.open_action)
        menu.addAction(self.run_action)

        menu.setFont(self.menu_font)

        menu.exec(event.globalPos())
        del menu

    def moveCursorPosBack(self):
        textCursor = self.textCursor()
        textCursorPos = textCursor.position()

        textCursor.setPosition(textCursorPos - 1)
        self.setTextCursor(textCursor)

    def keyPressEvent(self, e):
        textCursor = self.textCursor()
        key = e.key()

        if key == Qt.Key_H:
            # self.parent.completer.wordList
            # TODO: implement dynamic completion
            pass

        textCursorPos = textCursor.position()
        isSearch = (e.modifiers() == Qt.ControlModifier
                    and e.key() == Qt.Key_F)

        if isSearch:
            try:
                currentWidget = self.parent
                currentFile = currentWidget.fileName
                currentEditor = currentWidget.editor

                textCursor = currentEditor.textCursor()
                textCursorPos = textCursor.position()

            except (AttributeError, UnboundLocalError) as E:
                print(E)

            if currentWidget is not None:
                text, okPressed = QInputDialog.getText(self, 'Find',
                                                       'Find what: ')
                if okPressed:
                    if text == "":
                        text = " "
                        self.dialog.noMatch(text)
                    self.searchtext = text
                    try:
                        with open(currentFile, 'r') as file:
                            contents = file.read()
                            self.indexes = list(find_all(contents, text))
                            if len(self.indexes) == 0:
                                self.dialog.noMatch(text)

                    except FileNotFoundError as E:
                        print(E)

        if key == Qt.Key_QuoteDbl:
            self.insertPlainText('"')
            self.moveCursorPosBack()

        if e.modifiers() == Qt.ControlModifier and e.key(
        ) == 61:  # Press Ctrl+Equal key to make font bigger

            self.font.setPointSize(self.size + 1)
            self.font.setFamily(editor["editorFont"])
            self.setFont(self.font)
            self.size += 1
        if e.modifiers() == Qt.ControlModifier and e.key() == 16777217:
            return

        if e.modifiers() == Qt.ControlModifier and e.key(
        ) == 45:  # Press Ctrl+Minus key to make font smaller

            self.font.setPointSize(self.size - 1)

            self.font.setFamily(editor["editorFont"])
            self.setFont(self.font)
            self.size -= 1

        if key == Qt.Key_F3:
            try:
                index = self.indexes[0 + self.l]
                currentWidget = self.parent
                currentFile = currentWidget.fileName
                currentEditor = currentWidget.editor
                textCursor.setPosition(index)
                textCursor.movePosition(textCursor.Right,
                                        textCursor.KeepAnchor,
                                        len(self.searchtext))
                currentEditor.setTextCursor(textCursor)
                self.l += 1
            except IndexError:
                self.l = 0

        if key == 39:
            self.insertPlainText("'")
            self.moveCursorPosBack()

        if key == Qt.Key_BraceLeft:
            self.insertPlainText("}")
            self.moveCursorPosBack()

        if key == Qt.Key_BracketLeft:
            self.insertPlainText("]")
            self.moveCursorPosBack()

        if key == Qt.Key_ParenLeft:
            self.insertPlainText(")")
            self.moveCursorPosBack()

        if key == Qt.Key_ParenRight:
            textCursor = self.textCursor()
            textCursor.select(QTextCursor.WordUnderCursor)
            if textCursor.selectedText(
            ) == "()" or "()" in textCursor.selectedText():
                return

        if key == Qt.Key_BraceRight:
            textCursor = self.textCursor()
            textCursor.select(QTextCursor.WordUnderCursor)
            if textCursor.selectedText == "":
                return

        if key not in [16777217, 16777219, 16777220]:
            super().keyPressEvent(e)
            return

        e.accept()
        cursor = self.textCursor()
        if key == 16777217:  # and self.replace_tabs:
            amount = 4 - self.textCursor().positionInBlock() % 4
            self.insertPlainText(' ' * amount)

        elif key == 16777219 and cursor.selectionStart() == cursor.selectionEnd() and self.replace_tabs and \
                cursor.positionInBlock():
            position = cursor.positionInBlock()
            end = cursor.position()
            start = end - (position % 4)

            if start == end and position >= 4:
                start -= 4

            string = self.toPlainText()[start:end]
            if not len(string.strip()
                       ):  # if length is 0 which is binary for false
                for i in range(end - start):
                    cursor.deletePreviousChar()
            else:
                super().keyPressEvent(e)

        elif key == 16777220:
            end = cursor.position()
            start = end - cursor.positionInBlock()
            line = self.toPlainText()[start:end]
            indentation = len(line) - len(line.lstrip())

            chars = '\t'
            if self.replace_tabs:
                chars = '    '
                indentation /= self.replace_tabs

            if line.endswith(':'):
                if self.replace_tabs:
                    indentation += 1

            super().keyPressEvent(e)
            self.insertPlainText(chars * int(indentation))

        else:
            super().keyPressEvent(e)
Exemplo n.º 3
0
class Editor(QPlainTextEdit):

    def __init__(self, parent):
        super().__init__(parent)

        self.parent = parent
        self.font = QFont()
        self.size = 12
        self.dialog = MessageBox()
        self.menu_font = QFont()
        self.menu_font.setFamily("Iosevka")
        self.menu_font.setPointSize(10)
        self.font.setFamily(editor["editorFont"])
        self.font.setPointSize(editor["editorFontSize"])
        self.focused = None

        self.replace_tabs = 4
        self.setWordWrapMode(4)
        self.setFont(self.font)
        self.l = 0
        self.highlightingRules = []
        self.indexes = None

        self.setTabStopWidth(editor["TabWidth"])
        self.createStandardContextMenu()
        self.setWordWrapMode(QTextOption.NoWrap)

    def newFile(self):
        """This and most of the functions below will just be wrappers for the functions defined in Main"""
        self.new_action = QAction("New")
        self.new_action.triggered.connect(self.parent.parent.newFile)

    def openFile(self):

        self.open_action = QAction("Open")
        self.open_action.triggered.connect(self.parent.parent.openFileFromMenu)

    def runFile(self):

        self.run_action = QAction("Run")
        self.run_action.triggered.connect(self.parent.parent.Terminal)

    def contextMenuEvent(self, event):

        menu = QMenu()
        """Initializing actions"""
        self.newFile()
        self.openFile()
        self.runFile()

        menu.addAction(self.new_action)
        menu.addAction(self.open_action)
        menu.addAction(self.run_action)

        menu.setFont(self.menu_font)

        menu.exec(event.globalPos())
        del menu

    def moveCursorPosBack(self):
        textCursor = self.textCursor()
        textCursorPos = textCursor.position()

        textCursor.setPosition(textCursorPos - 1)
        self.setTextCursor(textCursor)

    def keyPressEvent(self, e):
        textCursor = self.textCursor()
        key = e.key()

        if key == Qt.Key_H:
            # self.parent.completer.wordList
            # TODO: implement dynamic completion
            pass

        textCursorPos = textCursor.position()
        isSearch = (e.modifiers() == Qt.ControlModifier and e.key() == Qt.Key_F)

        if isSearch:
            try:
                currentWidget = self.parent
                currentFile =  currentWidget.fileName
                currentEditor = currentWidget.editor

                textCursor = currentEditor.textCursor()
                textCursorPos = textCursor.position()

            except (AttributeError, UnboundLocalError) as E:
                print(E)

            if currentWidget is not None:
                text, okPressed = QInputDialog.getText(self, 'Find', 'Find what: ')
                if okPressed:
                    if text == "":
                        text = " "
                        self.dialog.noMatch(text)
                    self.searchtext = text
                    try:
                        with open(currentFile, 'r') as file:
                            contents = file.read()
                            self.indexes = list(find_all(contents, text))
                            if len(self.indexes) == 0:
                                self.dialog.noMatch(text)

                    except FileNotFoundError as E:
                        print(E)

        if key == Qt.Key_QuoteDbl:
            self.insertPlainText('"')
            self.moveCursorPosBack()

        if (e.modifiers() == Qt.ControlModifier and e.key() == 61):  # Press Ctrl+Equal key to make font bigger

            self.font.setPointSize(self.size + 1)
            self.font.setFamily(editor["editorFont"])
            self.setFont(self.font)
            self.size += 1

        if (e.modifiers() == Qt.ControlModifier and e.key() == 45): # Press Ctrl+Minus key to make font smaller

            self.font.setPointSize(self.size - 1)

            self.font.setFamily(editor["editorFont"])
            self.setFont(self.font)
            self.size -= 1

        if key == Qt.Key_F3:
            try:
                index = self.indexes[0 + self.l]
                currentWidget = self.parent
                currentFile =  currentWidget.fileName
                currentEditor = currentWidget.editor
                textCursor.setPosition(index)
                textCursor.movePosition(textCursor.Right, textCursor.KeepAnchor, len(self.searchtext))
                currentEditor.setTextCursor(textCursor)
                self.l += 1
            except IndexError:
                self.l = 0

        if key == 39:
            self.insertPlainText("'")
            self.moveCursorPosBack()

        if key == Qt.Key_BraceLeft:
            self.insertPlainText("}")
            self.moveCursorPosBack()

        if key == Qt.Key_BracketLeft:
            self.insertPlainText("]")
            self.moveCursorPosBack()

        if key == Qt.Key_ParenLeft:

            self.insertPlainText(")")
            self.moveCursorPosBack()

        if key == Qt.Key_ParenRight:
            textCursor = self.textCursor()
            textCursor.select(QTextCursor.WordUnderCursor)
            if textCursor.selectedText() == "()" or "()" in textCursor.selectedText():
                return

        if key == Qt.Key_BraceRight:
            textCursor = self.textCursor()
            textCursor.select(QTextCursor.WordUnderCursor)
            if textCursor.selectedText == "":
                return

        if key not in [16777217, 16777219, 16777220]:

            super().keyPressEvent(e)
            return

        e.accept()
        cursor = self.textCursor()
        if key == 16777217: # and self.replace_tabs:
            amount = 4 - self.textCursor().positionInBlock() % 4
            self.insertPlainText(' ' * amount)

        elif key == 16777219 and cursor.selectionStart() == cursor.selectionEnd() and self.replace_tabs and \
                cursor.positionInBlock():
            position = cursor.positionInBlock()
            end = cursor.position()
            start = end - (position % 4)

            if start == end and position >= 4:
                start -= 4

            string = self.toPlainText()[start:end]
            if not len(string.strip()): # if length is 0 which is binary for false
                for i in range(end - start):
                    cursor.deletePreviousChar()
            else:
                super().keyPressEvent(e)

        elif key == 16777220:
            end = cursor.position()
            start = end - cursor.positionInBlock()
            line = self.toPlainText()[start:end]
            indentation = len(line) - len(line.lstrip())

            chars = '\t'
            if self.replace_tabs:
                chars = '    '
                indentation /= self.replace_tabs

            if line.endswith(':'):
                if self.replace_tabs:
                    indentation += 1

            super().keyPressEvent(e)
            self.insertPlainText(chars * int(indentation))

        else:
            super().keyPressEvent(e)
Exemplo n.º 4
0
class Editor(QsciScintilla):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.fileName = None
        self.parent = parent
        self.debugging = False
        self.line = None
        self.column = None

        self.wordlist = []
        self.searchtext = None

        self.font = QFont()
        self.font.setFamily("Inconsolata")
        self.pointSize = 12  # TODO: Make this customizable
        self.tabWidth = 4  # TODO: Make this customizable
        self.font.setPointSize(self.pointSize)
        self.dialog = MessageBox(self)
        self.verticalScrollBar().setStyleSheet("""
            background-color: transparent;
            """)

        self.horizontalScrollBar().setStyleSheet("""
            background-color: transparent;
            """)

        self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCaretForegroundColor(QColor("#FFFFFF"))
        self.setEdgeColumn(121)
        self.setEdgeMode(1)
        self.setEdgeColor(QColor("#8c8c8c"))
        self.setFont(self.font)
        self.setMarginSensitivity(1, True)
        self.markerDefine(QsciScintilla.RightArrow, 8)
        self.setMarkerBackgroundColor(QColor('#FF0000'), 8)
        self.indicator_number = 0
        self.indicator_value = 222
        self.indicator_color = QColor("#FF0000")
        self.draw_under_text = True
        # Initializing some stuff
        self.set_brace_colors(QColor("#98b4f9"), QColor("#edf40e"),
                              QColor("#98b4f9"), QColor("red"))

        self.cursorPositionChanged.connect(self.change_col)
        self.textChanged.connect(self.check_lines)

        self.set_linenumbers(QFontMetrics(self.font))
        self.setFoldMarginColors(QColor("#212121"), QColor("#212121"))
        self.set_indentation_settings(self.tabWidth)

    def set_up_tooltips(self):
        self.setCallTipsStyle(QsciScintilla.CallTipsNoContext)
        self.setCallTipsVisible(0)

        self.setCallTipsPosition(QsciScintilla.CallTipsAboveText)
        self.setCallTipsBackgroundColor(QColor("#FF0000"))

        self.setCallTipsForegroundColor(QColor("#FF0000"))
        self.setCallTipsHighlightColor(QColor("#FF0000"))

    def set_brace_colors(self,
                         matched_B=None,
                         matched_F=None,
                         unmatched_B=None,
                         unmatched_F=None):

        self.setMatchedBraceBackgroundColor(matched_B)
        self.setMatchedBraceForegroundColor(matched_F)
        self.setUnmatchedBraceBackgroundColor(unmatched_B)
        self.setUnmatchedBraceForegroundColor(unmatched_F)

        self.setBraceMatching(QsciScintilla.SloppyBraceMatch)

    def set_linenumbers(self, fontmetrics):
        self.setMarginsFont(self.font)

        self.setMarginWidth(0, fontmetrics.width("00000"))
        self.setMarginLineNumbers(0, True)

        self.setMarginsBackgroundColor(QColor("#212121"))
        self.setMarginsForegroundColor(QColor("#FFFFFF"))

    def set_indentation_settings(self, tab_width):
        self.setIndentationsUseTabs(False)

        self.setTabWidth(tab_width)

        self.SendScintilla(QsciScintilla.SCI_SETUSETABS, False)

        self.setAutoIndent(True)
        self.setTabIndents(True)

    def check_lines(self):
        line_n = self.lines()
        for i in range(line_n):
            if self.lineLength(i) > 121:
                # TODO: Make a character format or something
                pass
                #  print("Line over 121 characters on line", str(i+1))
                # self.setCursorPosition(i, 120)

    def python_highlighter(self):
        self.lexer = PythonLexer()
        self.lexer.setFoldComments(True)
        self.setCaretLineVisible(True)

        self.setDefaultSettings(self.lexer)
        self.setPythonAutocomplete()
        self.setFold()

    def json_highlighter(self):
        lexer = QsciLexerJSON()
        self.setDefaultSettings(lexer)

    def c_highlighter(self):
        lexer = QsciLexerCPP()

        self.setDefaultSettings(lexer)

    def setDefaultSettings(self, lexer):
        self.setAutoIndent(True)
        lexer.setFont(self.font)

        lexer.setColor(QColor('white'), 0)  # default
        lexer.setColor(QColor('#6B6E6C'), PythonLexer.Comment)  # = 1
        lexer.setColor(QColor('#ADD4FF'), 2)  # Number = 2
        lexer.setColor(QColor('#38ef7d'), 3)  # DoubleQuotedString
        lexer.setColor(QColor('#38ef7d'), 4)  # SingleQuotedString
        lexer.setColor(QColor('#F6DC74'), 5)  # Keyword
        lexer.setColor(QColor('#38ef7d'), 6)  # TripleSingleQuotedString
        lexer.setColor(QColor('#38ef7d'), 7)  # TripleDoubleQuotedString
        lexer.setColor(QColor('#74F6C3'), 8)  # ClassName
        lexer.setColor(QColor('#FF6666'), 9)  # FunctionMethodName
        lexer.setColor(QColor('magenta'), 10)  # Operator
        lexer.setColor(QColor('white'), 11)  # Identifier
        lexer.setColor(QColor('gray'), 12)  # CommentBlock
        lexer.setColor(QColor('#a8ff78'), 13)  # UnclosedString
        lexer.setColor(QColor('gray'), 14)  # HighlightedIdentifier
        lexer.setColor(QColor('#FF00E7'), 15)  # Decorator

        lexer.setFont(QFont("Iosevka", weight=QFont.Bold), 5)
        self.setCaretLineBackgroundColor(QColor("#3C3B3F"))
        self.setLexer(lexer)

    def setPythonAutocomplete(self):
        self.autocomplete = QsciAPIs(self.lexer)
        self.keywords = wordList

        for word in self.keywords:
            self.autocomplete.add(word)

        self.setAutoCompletionThreshold(2)

        self.setAutoCompletionSource(QsciScintilla.AcsAPIs)
        self.updateAutoComplete(self.parent.fileName)

        self.autocomplete.prepare()

    def setFold(self):
        # setup Fold Styles for classes and functions ...
        x = self.FoldStyle(self.FoldStyle(5))
        # self.textPad.folding()
        if not x:
            self.foldAll(False)

        self.setFolding(x)
        # self.textPad.folding()

    def unsetFold(self):
        self.setFolding(0)

    def updateAutoComplete(self, file_path=None):

        for i in tokenize(file_path):
            for j in i:
                if j not in self.wordlist:
                    self.wordlist.append(j)
        for word in self.wordlist:
            self.autocomplete.add(word)

        self.autocomplete.prepare()

    def change_col(self, line,
                   column):  # Responsible for changing the column bar.
        self.line = line
        self.column = column

    def check_if_func(self, word):  # Checks if a word is a built in function
        word_array = list(word)
        for wo in word_array:
            if wo in ["{", "}", "'", '"', "[", "]", "(", ")"]:
                word_array.remove(wo)
        for w in funcList:
            if w == "".join(word_array):
                return True

    def check_if_error(self, word):
        if word in errorList:  # This is the list where all possible errors are defined
            return True

    def keyReleaseEvent(self, e):
        if e.key() == Qt.Key_Return:
            try:
                self.updateAutoComplete(self.parent.fileName)
            except AttributeError as E:
                print(E, "on line 210 in TextEditor.py")

        if e.key() == Qt.Key_Backspace:
            pass

    def mousePressEvent(self, e):
        super().mousePressEvent(e)

        if QGuiApplication.queryKeyboardModifiers() == Qt.ControlModifier:
            word = self.wordAtLineIndex(self.getCursorPosition()[0],
                                        self.getCursorPosition()[1])
            print(word)
            if self.check_if_func(word):
                url = "https://docs.python.org/3/library/functions.html#" + word
                self.parent.parent.openBrowser(
                    url, word)  # Runs the openBrowser function in Main class
            elif self.check_if_error(word):
                url = "https://docs.python.org/3/library/exceptions.html#" + word
                print(url)

                self.parent.parent.openBrowser(url, word)

    def keyPressEvent(self, e):
        if e.modifiers() == Qt.ControlModifier and e.key() == Qt.Key_F:
            text, okPressed = QInputDialog.getText(self, 'Find', 'Find what: ')

            self.setSelectionBackgroundColor(QColor("#6be585"))

            if okPressed:
                if text == "":
                    text = " "
                    self.dialog.noMatch(text)

                self.searchtext = text
                """
                This is the way to implement a search function using QScintilla 
                http://pyqt.sourceforge.net/Docs/QScintilla2/classQsciScintilla.html#a37ac2bea94eafcfa639173557a821200
                """

                if self.findFirst(self.searchtext, False, True, False, True,
                                  True, -1, -1, True, False):
                    pass
                else:
                    self.dialog.noMatch(self.searchtext)

        if e.key() == Qt.Key_F3:
            self.findNext()
            self.setSelectionBackgroundColor(QColor("#6be585"))

        if e.modifiers() == Qt.ControlModifier and e.key() == Qt.Key_L:
            self.setCursorPosition(self.line, self.column + 1)
            return
        if e.modifiers() == Qt.ControlModifier and e.key() == 77:

            self.setCursorPosition(self.line + 1, self.column)
            return
        if e.modifiers() == Qt.ControlModifier and e.key() == Qt.Key_J:
            self.setCursorPosition(self.line, self.column - 1)

        if e.modifiers() == Qt.ControlModifier and e.key() == Qt.Key_I:
            self.setCursorPosition(self.line - 1, self.column)

        if e.modifiers() == Qt.ControlModifier and e.key() == Qt.Key_T:
            self.parent.parent.realterminal()
            return

        super().keyPressEvent(e)