Example #1
0
    def fixUpLine(self, line: int, newText: str, data: int):
        """ The receiver of the 'fixupText' signal should invoke this method
        to replace the line with the cleaned text and the model's
        matching row """

        block = self.document().findBlockByLineNumber(line)
        if block.isValid():
            if block.userData() is None:
                block.setUserData(self._UserData(data))
            else:
                block.userData().row = data

            text = newText.strip()
            if not text:
                block.setUserState(self._State.Blank)
            elif data < 0:
                block.setUserState(self._State.Error)
            else:
                block.setUserState(self._State.Fixup)

            cursor = QTextCursor(block)
            cursor.beginEditBlock()
            cursor.movePosition(QTextCursor.StartOfLine)
            cursor.select(QTextCursor.LineUnderCursor)
            cursor.removeSelectedText()
            cursor.insertText(text)
            cursor.endEditBlock()
Example #2
0
 def _update_text(self, changes):
     """Apply the changes to our QTextDocument."""
     c = QTextCursor(self.document())
     c.beginEditBlock()
     for start, end, text in reversed(changes):
         c.setPosition(end)
         if start != end:
             c.setPosition(start, QTextCursor.KeepAnchor)
         c.insertText(text)
     c.endEditBlock()
Example #3
0
    def keywordHighlight(self, doc):
        cursor = QTextCursor(doc)
        cursor.beginEditBlock()
        fmt = QTextCharFormat()
        fmt.setBackground(Qt.darkYellow)

        highlightCursor = QTextCursor(doc)
        while not highlightCursor.isNull() and not highlightCursor.atEnd():
            highlightCursor = doc.find(self.keyword, highlightCursor)
            if not highlightCursor.isNull():
                highlightCursor.mergeCharFormat(fmt)
        cursor.endEditBlock()
Example #4
0
    async def __readAndPrintStream(self, sr: asyncio.StreamReader,
                                   text_cursor: QTextCursor):
        leftover_data = bytearray()
        while not sr.at_eof() or len(leftover_data) > 0:
            separator_encountered = False
            meaningful_data = None
            cr_found = False
            lf_found = False
            while not separator_encountered:
                leftover_data += await sr.read(64)
                separator_index = -1
                for index, b in enumerate(leftover_data):
                    if b == ord(b'\r'):
                        separator_index = index
                        cr_found = True
                        break
                    elif b == ord(b'\n'):
                        separator_index = index
                        lf_found = True
                        break
                if separator_index != -1:
                    separator_encountered = True
                    meaningful_data = leftover_data[0:separator_index]
                    leftover_data = leftover_data[separator_index + 1:]
                else:
                    leftover_data += leftover_data[separator_index + 1:]

            text = meaningful_data.decode(
            ) if meaningful_data is not None else ''

            text_cursor.beginEditBlock()

            if cr_found:
                text_cursor.movePosition(QTextCursor.StartOfLine)
                text_cursor.insertText(text)
                i = 1
                count = len(text)
                while i <= count:
                    text_cursor.deleteChar()
                    i += 1
            elif lf_found:
                text_cursor.insertText(text + '\n')
            else:
                text_cursor.insertText(text)

            text_cursor.endEditBlock()
            self.__ui.terminalLogWindow.ensureCursorVisible()
Example #5
0
    def set_bytes(self, bs):
        self.pretty_mode = False
        self.data = bs
        chunks = HextEditor._split_by_printables(bs)
        self.clear()
        cursor = QTextCursor(self.textedit.document())
        cursor.beginEditBlock()

        cursor.select(QTextCursor.Document)
        cursor.setCharFormat(QTextCharFormat())
        cursor.clearSelection()

        for chunk in chunks:
            if chr(chunk[0]) in qtprintable:
                cursor.insertText(chunk.decode())
            else:
                for b in chunk:
                    self._insert_byte(cursor, b)
        cursor.endEditBlock()
Example #6
0
    def on_findButton_clicked(self):

        search_string = self.ui_line_edit.text()
        document = self.ui_text_edit.document()

        self.found = False

        document.undo()

        if not search_string:
            QMessageBox.information(self, "Empty Search Field", 'Please enter a word')

        else:
            highlight_cursor = QTextCursor(document)
            cursor = QTextCursor(document)

            cursor.beginEditBlock()

            plain_format = QTextCharFormat(highlight_cursor.charFormat())
            color_format = plain_format
            color_format.setForeground(Qt.red)

            while not highlight_cursor.isNull() and not highlight_cursor.atEnd():
                highlight_cursor = document.find(
                    search_string,
                    highlight_cursor,
                    QTextDocument.FindWholeWords
                )

                if not highlight_cursor.isNull():
                    self.found = True
                    highlight_cursor.movePosition(QTextCursor.WordRight, QTextCursor.KeepAnchor)
                    highlight_cursor.mergeCharFormat(color_format)

            cursor.endEditBlock()

            if not self.found:
                QMessageBox.information(self, "Word not found", "Sorry, the word coannot be found")
Example #7
0
 def apply_changes(self):
     """Apply the changes and update the tokens."""
     c = QTextCursor(self._d)
     # record a sensible position for undo
     c.setPosition(self._changes_list[-1][0])
     c.joinPreviousEditBlock() if self.combine_undo else c.beginEditBlock()
     try:
         for start, end, text in self._changes_list:
             c.movePosition(QTextCursor.End) if end is None else c.setPosition(end)
             c.setPosition(start, QTextCursor.KeepAnchor)
             c.insertText(text)
     finally:
         c.endEditBlock()
         if self.combine_undo is None:
             self.combine_undo = True
Example #8
0
 def apply_changes(self):
     """Apply the changes and update the tokens."""
     c = QTextCursor(self._d)
     # record a sensible position for undo
     c.setPosition(self._changes_list[-1][0])
     c.joinPreviousEditBlock() if self.combine_undo else c.beginEditBlock()
     try:
         for start, end, text in self._changes_list:
             c.movePosition(
                 QTextCursor.End) if end is None else c.setPosition(end)
             c.setPosition(start, QTextCursor.KeepAnchor)
             c.insertText(text)
     finally:
         c.endEditBlock()
         if self.combine_undo is None:
             self.combine_undo = True
Example #9
0
class TextSectionEditor(QTextDocument):
    def __init__(self,
                 sectionId: str,
                 content="",
                 pos=0,
                 selectionStart=0,
                 selectionEnd=0):
        super().__init__()
        self.dtb = DTB()
        self.sectionId = sectionId
        self.setDefaultStyleSheet(CSS)
        self.setHtml(content)
        self.s_start = selectionStart
        self.s_end = selectionEnd

        self.cur = QTextCursor(self)
        self.cur.setPosition(pos)
        self.result = {
            "text": "",
            "cursorPosition": self.pos,
            "eventAccepted": False
        }
        self.pending = False

    @property
    def len(self):
        return self.characterCount()

    @property
    def s_len(self):
        return abs(self.s_end - self.s_start)

    @property
    def pos(self):
        return self.cur.position()

    def onChange(self):

        self._update_ddb()
        self.setResponse(True)
        return self.result

    def onLoad(self):
        item = self.dtb.getDB("Section", self.sectionId)
        self.setHtml(item["text"])
        self.setResponse(True, cur=self.len)
        return self.result

    def onMenu(self, style={}, **kwargs):
        backup = [self.pos, self.s_start, self.s_end]

        for k, v in style.items():
            # un peut répétition mais uniquement sur des if alors ...
            if k == "fgColor":
                self._set_fg_color(v)
            elif k == "underline":  # pragma: no branch
                self._set_underline(style["underline"])

            self.cur.setPosition(backup[0])
            self.s_start = backup[1]
            self.s_end = backup[2]

        if self.pending:
            # else:
            self._update_ddb()
        else:
            self.setResponse(False)
        return self.result

    def onKey(self, event):
        # on met en premier ceux à qui il faut passer l'event
        if event["key"] == Qt.Key_Return:
            self.do_key_return(event)

        elif event["modifiers"] == Qt.ControlModifier:
            self.do_control_modifier(event)

        else:
            self.setResponse(False)

        if self.pending:
            self._update_ddb()
        return self.result

    def do_control_modifier(self, event):

        if event == KeyW.KEY_1:
            self.do_key_1()

        elif event == KeyW.KEY_2:
            self.do_key_2()

        elif event == KeyW.KEY_3:
            self.do_key_3()

        elif event == KeyW.KEY_4:
            self.do_key_4()

        elif event["key"] == Qt.Key_U:  # pragma: no branch
            self.do_key_u()

    def do_key_1(self):
        self._set_fg_color(BLACK)

    def do_key_2(self):
        self._set_fg_color(BLUE)

    def do_key_3(self):
        self._set_fg_color(GREEN)

    def do_key_4(self):
        self._set_fg_color(RED)

    def do_key_return(self, event):
        block = self.findBlock(self.pos)
        if event["modifiers"] == Qt.ControlModifier:
            self._appendEmptyBlock()
        elif event["modifiers"] == Qt.ShiftModifier:
            self._insertEmptyBlock()
        elif block.blockFormat().headingLevel():
            self._appendEmptyBlock()
        else:
            if self._headerAutoFormat():
                return
            else:
                self.setResponse(False)

    def do_key_u(self):
        self._set_underline("toggle")

    def setResponse(self, accepted, text=None, cur=None):
        self.result["text"] = text or self.toHtml()
        self.result["cursorPosition"] = cur or self.cur.position()
        self.result["eventAccepted"] = accepted

    def _appendEmptyBlock(self,
                          section="p",
                          pre_move=QTextCursor.EndOfBlock,
                          set_response=True):
        self.cur.movePosition(pre_move)
        self.cur.insertBlock(blockFormat[section], blockCharFormat[section])
        self.cur.insertFragment(QTextDocumentFragment.fromPlainText(""))
        self.pending = True
        if set_response:
            self.setResponse(True)

    def _insertEmptyBlock(self,
                          section="p",
                          pre_move=QTextCursor.StartOfBlock,
                          set_response=True):
        old = self.cur.blockFormat().headingLevel()
        self._appendEmptyBlock(pre_move=pre_move, set_response=False)
        self._set_block_style(old)
        self.cur.movePosition(QTextCursor.PreviousBlock)
        self._set_block_style(section)
        self.pending = True
        if set_response:  # pragma: no branch
            self.setResponse(True)

    def _headerAutoFormat(self):

        # on check les expressions régulières suivantes:
        #   #, ##, ###, ####, #####
        line = self.cur.block().text()
        matched = RE_AUTOPARAGRAPH_DEBUT.search(line)
        matched_at_start = False
        if not matched:
            matched = RE_AUTOPARAGRAPH_FIN.search(line)
            if not matched:
                return False
        else:
            matched_at_start = True

        # strip les # et applique les styles par défault
        level = len(matched.groups()[0])
        if matched_at_start:
            text = self.cur.block().text()[level + 1:]
        else:
            text = self.cur.block().text()[:-(level + 1)]

        self.cur.beginEditBlock()
        self.cur.select(QTextCursor.LineUnderCursor)
        self.cur.setCharFormat(blockCharFormat[level])
        self.cur.insertText(text)
        self.cur.setBlockFormat(blockFormat[level])
        self.cur.endEditBlock()

        self._appendEmptyBlock()
        self.pending = True
        self.setResponse(True)
        return True

    @contextmanager
    def _merge_char_format(self):
        self._select_word_or_selection()
        f: QTextCharFormat = QTextCharFormat()
        yield f
        self.cur.mergeCharFormat(f)
        self.pending = True
        self.setResponse(True, cur=max(self.pos, self.s_start, self.s_end))

    def _select_word_or_selection(self):
        if self.s_start < self.pos:
            self.cur.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor,
                                  self.s_len)
        elif self.s_end > self.pos:
            self.cur.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor,
                                  self.s_len)
        else:
            self.cur.select(QTextCursor.WordUnderCursor)

    def _set_block_style(self, level):
        self.cur.setBlockFormat(blockFormat[level])
        self.cur.setBlockCharFormat(blockCharFormat[level])

    def _set_fg_color(self, color):
        with self._merge_char_format() as f:
            f.setForeground(QBrush(QColor(color)))

    def _set_underline(self, value):
        with self._merge_char_format() as f:
            if value == "toggle":
                value = not self.cur.charFormat().fontUnderline()
            f.setFontUnderline(value)

    def _update_ddb(self):
        new_body = TextSectionFormatter(self.toHtml()).build_body()
        self.dtb.setDB("Section", self.sectionId, {"text": new_body})
        return new_body