Ejemplo n.º 1
0
 def in_image():
     c = QTextCursor(doc.text)
     c.movePosition(QTextCursor.Start)
     while c.movePosition(QTextCursor.NextCharacter,
                          QTextCursor.KeepAnchor):
         if doc.in_image():
             break
Ejemplo n.º 2
0
    def __init__(self, config):
        super(Doc, self).__init__()
        self._text = QTextDocument()
        self._cfg = config
        self._text_edit_cursor = QTextCursor(self._text)
        self._text.setIndentWidth(self._cfg.get("TextEditor/IndentWidth", 24))

        self.set_default_font()
Ejemplo n.º 3
0
 def in_table():
     c = QTextCursor(doc.text)
     c.movePosition(QTextCursor.Start)
     while c.movePosition(QTextCursor.NextCharacter,
                          QTextCursor.KeepAnchor):
         if doc.in_table():
             cc = doc.table().cellAt(2, 1)
             cc.firstCursorPosition().insertText("Hello")
             doc.change(cc.firstCursorPosition())
Ejemplo n.º 4
0
 def in_table():
     c = QTextCursor(doc.text)
     c.movePosition(QTextCursor.Start)
     while c.movePosition(QTextCursor.NextCharacter,
                          QTextCursor.KeepAnchor):
         if doc.in_table():
             doc.text_align(Qt.AlignRight, QTextCharFormat.AlignBottom)
             a = doc._text_edit_cursor.charFormat().verticalAlignment()
             self.assertEqual(a, QTextCharFormat.AlignBottom)
             break
Ejemplo n.º 5
0
 def in_table():
     # is exists table in document ?
     c = QTextCursor(doc.text)
     c.movePosition(QTextCursor.Start)
     _in_table = False
     while c.movePosition(QTextCursor.NextCharacter,
                          QTextCursor.KeepAnchor):
         if doc.in_table():
             _in_table = True
             break
     return _in_table
    def createDocument(self, rootFrame):

        # Create empty document
        self.document = QTextDocument()
        self.document.setUndoRedoEnabled(False)
        self.document.setIndentWidth(20)

        # Register a renderer for custom text objects
        mo = CustomObjectRenderer()
        mo.setParent(self.document)
        self.document.documentLayout().registerHandler(QTextCharFormat.UserObject+1, mo);

        self.cursor = QTextCursor(self.document)
        self.listLevel = 0
        self.paraFormat = None

        # add all root paragraphs
        for n in rootFrame.children:
            self.addNode(n)

        # Clean up the first paragraph if document is not empty
        self.cursor.movePosition(QTextCursor.Start)
        b = self.cursor.block()
        if b.length() == 1:
            cursor = QTextCursor(self.document.findBlockByLineNumber(0))
            cursor.select(QTextCursor.BlockUnderCursor)
            cursor.deleteChar()

        return self.document
Ejemplo n.º 7
0
 def do_test(self):
     selections = []
     self.match_locs = []
     if self.regex_valid():
         text = unicode_type(self.preview.toPlainText())
         regex = unicode_type(self.regex.text())
         cursor = QTextCursor(self.preview.document())
         extsel = QTextEdit.ExtraSelection()
         extsel.cursor = cursor
         extsel.format.setBackground(QBrush(Qt.yellow))
         try:
             for match in compile_regular_expression(regex).finditer(text):
                 es = QTextEdit.ExtraSelection(extsel)
                 es.cursor.setPosition(match.start(),
                                       QTextCursor.MoveAnchor)
                 es.cursor.setPosition(match.end(), QTextCursor.KeepAnchor)
                 selections.append(es)
                 self.match_locs.append((match.start(), match.end()))
         except:
             pass
     self.preview.setExtraSelections(selections)
     if self.match_locs:
         self.next.setEnabled(True)
         self.previous.setEnabled(True)
     self.occurrences.setText(unicode_type(len(self.match_locs)))
Ejemplo n.º 8
0
    def reformat_blocks(self, position, removed, added):
        doc = self.doc
        if doc is None or self.ignore_requests or not hasattr(self, 'state_map'):
            return

        block = doc.findBlock(position)
        if not block.isValid():
            return
        start_cursor = QTextCursor(block)
        last_block = doc.findBlock(position + added + (1 if removed > 0 else 0))
        if not last_block.isValid():
            last_block = doc.lastBlock()
        end_cursor = QTextCursor(last_block)
        end_cursor.movePosition(end_cursor.EndOfBlock)
        self.requests.append((start_cursor, end_cursor))
        QTimer.singleShot(0, self.do_one_block)
Ejemplo n.º 9
0
    def reformat_blocks(self, position, removed, added):
        doc = self.doc
        if doc is None or self.ignore_requests or not hasattr(self, 'state_map'):
            return

        block = doc.findBlock(position)
        if not block.isValid():
            return
        start_cursor = QTextCursor(block)
        last_block = doc.findBlock(position + added + (1 if removed > 0 else 0))
        if not last_block.isValid():
            last_block = doc.lastBlock()
        end_cursor = QTextCursor(last_block)
        end_cursor.movePosition(end_cursor.EndOfBlock)
        self.requests.append((start_cursor, end_cursor))
        QTimer.singleShot(0, self.do_one_block)
Ejemplo n.º 10
0
 def in_table():
     # is exists table in document ?
     c = QTextCursor(doc.text)
     c.movePosition(QTextCursor.Start)
     _in_table = False
     while c.movePosition(QTextCursor.NextCharacter,
                          QTextCursor.KeepAnchor):
         if doc.in_table():
             _in_table = True
             doc.background_color("blue")
             cc = doc._text_edit_cursor
             cell = cc.currentTable().cellAt(cc).format()
             clr = cell.background().color().name()
             self.assertEqual(clr, QColor("blue").name())
             break
     return _in_table
Ejemplo n.º 11
0
 def set_document(self, doc, doc_name=None):
     old_doc = self.doc
     if old_doc is not None:
         old_doc.contentsChange.disconnect(self.reformat_blocks)
         c = QTextCursor(old_doc)
         c.beginEditBlock()
         blk = old_doc.begin()
         while blk.isValid():
             blk.layout().clearAdditionalFormats()
             blk = blk.next()
         c.endEditBlock()
     self.doc = self.doc_name = None
     if doc is not None:
         self.doc = doc
         self.doc_name = doc_name
         doc.contentsChange.connect(self.reformat_blocks)
         self.rehighlight()
Ejemplo n.º 12
0
 def copy_lines(self, lo, hi, cursor):
     ''' Copy specified lines from the syntax highlighted buffer into the
     destination cursor, preserving all formatting created by the syntax
     highlighter. '''
     self.highlighter.join()
     num = hi - lo
     if num > 0:
         block = self.findBlockByNumber(lo)
         while num > 0:
             num -= 1
             cursor.insertText(block.text())
             dest_block = cursor.block()
             c = QTextCursor(dest_block)
             try:
                 afs = block.layout().additionalFormats()
             except AttributeError:
                 afs = ()
             for af in afs:
                 start = dest_block.position() + af.start
                 c.setPosition(start), c.setPosition(
                     start + af.length, c.KeepAnchor)
                 c.setCharFormat(af.format)
             cursor.insertBlock()
             cursor.setCharFormat(NULL_FMT)
             block = next(block)
Ejemplo n.º 13
0
    def search_log_area(self):
        """ Search a word in log area.
        Keep last cursor and word used for iteration
        in the document.
        """

        cursor: QTextCursor
        doc: QTextDocument
        text: str
        search_format: QTextCharFormat

        text = self.log_filters.filter_line.text()
        doc = self.log_area.document()

        search_format = QTextCharFormat()
        color = QColor("yellow")
        color.setAlpha(255)
        search_format.setBackground(color)

        # remove the previous search highlight
        if not self.last_search_cursor.isNull():
            self.last_search_cursor.setCharFormat(QTextCharFormat())

        # if search word changed or erased, reset cursor and last_search
        if len(text) == 0 or text != self.last_search:
            self.last_search_cursor = QTextCursor()
            self.last_search = text
            self.log_area.unsetCursor()
        # if has no word to search, just return
        if len(text) == 0:
            return

        cursor = self.last_search_cursor if not self.last_search_cursor.isNull(
        ) else QTextCursor(doc)
        cursor = doc.find(text, cursor)
        if not cursor.isNull():
            self.log_area.setTextCursor(cursor)
            cursor.setCharFormat(search_format)
        else:
            self.log_area.unsetCursor()
        self.last_search_cursor = cursor
Ejemplo n.º 14
0
    def __init__(self):
        super(MainWindow, self).__init__()

        self.log_area = None  # :type QPlainTextEdit
        self.main_document = None  # :type QTextDocument
        self.highlight_options_dialog = None  # :type HighlightOptionsDialog
        self.serial_dialog = None  # :type SerialDialog
        self.serial_menu = None  # :type QMenu
        self.highlight_options_menu = None  # :type QMenu
        self.help_menu = None  # :type QMenu
        self.log_filter_widget = None  # :type QWidget
        self.log_filters = None  # :type FilterPanel
        self.last_search = str()
        self.last_search_cursor = QTextCursor()

        container = QWidget()
        self.setup_menu()
        self.setup_text_area()
        self.setup_footer_panel()
        self.setup_serial_dialog()
        self.setup_highlight_options_dialog()

        self.first_search_flag = False

        self.serial_worker = SerialListenerWorker()
        self.serial_worker.signal.connect(self.add_line_to_log_area)

        self.log_area_layout = QVBoxLayout()
        self.log_area_layout.setContentsMargins(0, 0, 0, 0)
        self.log_area_layout.addWidget(self.log_area)
        self.log_area_layout.addWidget(self.log_filter_widget)
        container.setLayout(self.log_area_layout)

        self.setCentralWidget(container)

        self.setWindowTitle(APP_NAME)
        self.setGeometry(QRect(100, 100, 800, 600))
Ejemplo n.º 15
0
 def goto_loc(self,
              loc,
              operation=QTextCursor.Right,
              mode=QTextCursor.KeepAnchor,
              n=0):
     cursor = QTextCursor(self.preview.document())
     cursor.setPosition(loc)
     if n:
         cursor.movePosition(operation, mode, n)
     self.preview.setTextCursor(cursor)
Ejemplo n.º 16
0
        def in_table():
            c = QTextCursor(doc.text)
            c.movePosition(QTextCursor.Start)
            while c.movePosition(QTextCursor.NextCharacter,
                                 QTextCursor.KeepAnchor):
                if doc.in_table():
                    cc = doc.table().cellAt(2, 2)
                    cc.firstCursorPosition().insertText("Hello1")

                    cc = doc.table().cellAt(2, 1)
                    cc.firstCursorPosition().insertText("Hello")

                    c.movePosition(QTextCursor.EndOfBlock,
                                   QTextCursor.KeepAnchor)
                    break
Ejemplo n.º 17
0
 def set_document(self, doc, doc_name=None):
     old_doc = self.doc
     if old_doc is not None:
         old_doc.contentsChange.disconnect(self.reformat_blocks)
         c = QTextCursor(old_doc)
         c.beginEditBlock()
         blk = old_doc.begin()
         while blk.isValid():
             blk.layout().clearAdditionalFormats()
             blk = blk.next()
         c.endEditBlock()
     self.doc = self.doc_name = None
     if doc is not None:
         self.doc = doc
         self.doc_name = doc_name
         doc.contentsChange.connect(self.reformat_blocks)
         self.rehighlight()
Ejemplo n.º 18
0
 def copy_lines(self, lo, hi, cursor):
     ''' Copy specified lines from the syntax highlighted buffer into the
     destination cursor, preserving all formatting created by the syntax
     highlighter. '''
     num = hi - lo
     if num > 0:
         block = self.findBlockByNumber(lo)
         while num > 0:
             num -= 1
             cursor.insertText(block.text())
             dest_block = cursor.block()
             c = QTextCursor(dest_block)
             for af in block.layout().additionalFormats():
                 start = dest_block.position() + af.start
                 c.setPosition(start), c.setPosition(start + af.length, c.KeepAnchor)
                 c.setCharFormat(af.format)
             cursor.insertBlock()
             cursor.setCharFormat(NULL_FMT)
             block = block.next()
Ejemplo n.º 19
0
    def find_text(self, pat, cursor):
        from calibre.gui2.tweak_book.text_search import find_text_in_chunks
        chunks = []

        cstart = min(cursor.position(), cursor.anchor())
        cend = max(cursor.position(), cursor.anchor())
        c = QTextCursor(cursor)
        c.setPosition(cstart)
        block = c.block()
        in_text = find_tag_definition(block, 0)[0] is None

        def append(text, start):
            after = start + len(text)
            if start <= cend and cstart < after:
                extra = after - (cend + 1)
                if extra > 0:
                    text = text[:-extra]
                extra = cstart - start
                if extra > 0:
                    text = text[extra:]
                chunks.append((text, start + max(extra, 0)))

        while block.isValid() and block.position() <= cend:
            boundaries = sorted(block.userData().tags, key=get_offset)
            if not boundaries:
                # Add the whole line
                if in_text:
                    text = block.text()
                    if text:
                        append(text, block.position())
            else:
                start = block.position()
                c.setPosition(start)
                for b in boundaries:
                    if in_text:
                        c.setPosition(start + b.offset, c.KeepAnchor)
                        if c.hasSelection():
                            append(c.selectedText(), c.anchor())
                    in_text = not b.is_start
                    c.setPosition(start + b.offset + 1)
                if in_text:
                    # Add remaining text in block
                    c.setPosition(block.position() + boundaries[-1].offset + 1)
                    c.movePosition(c.EndOfBlock, c.KeepAnchor)
                    if c.hasSelection():
                        append(c.selectedText(), c.anchor())
            block = block.next()
        s, e = find_text_in_chunks(pat, chunks)
        return s != -1 and e != -1, s, e
Ejemplo n.º 20
0
    def resized(self):
        ' Resize images to fit in new view size and adjust all line number references accordingly '
        for v in (self.left, self.right):
            changes = []
            for i, (top, bot, kind) in enumerate(v.changes):
                if top in v.images:
                    img, oldw, oldlines = v.images[top]
                    lines, w = self.get_lines_for_image(img, v)
                    if lines != oldlines:
                        changes.append((i, lines, lines - oldlines, img, w))

            for i, lines, delta, img, w in changes:
                top, bot, kind = v.changes[i]
                c = QTextCursor(v.document().findBlockByNumber(top+1))
                c.beginEditBlock()
                c.movePosition(c.StartOfBlock)
                if delta > 0:
                    for _ in xrange(delta):
                        c.insertBlock()
                else:
                    c.movePosition(c.NextBlock, c.KeepAnchor, -delta)
                    c.removeSelectedText()
                c.endEditBlock()
                v.images[top] = (img, w, lines)

                def mapnum(x):
                    return x if x <= top else x + delta
                lnm = LineNumberMap()
                lnm.max_width = v.line_number_map.max_width
                for x, val in v.line_number_map.iteritems():
                    dict.__setitem__(lnm, mapnum(x), val)
                v.line_number_map = lnm
                v.changes = [(mapnum(t), mapnum(b), k) for t, b, k in v.changes]
                v.headers = [(mapnum(x), name) for x, name in v.headers]
                v.images = OrderedDict((mapnum(x), v) for x, v in v.images.iteritems())
            v.viewport().update()
Ejemplo n.º 21
0
 def search(self, query, reverse=False):
     ''' Search for query, also searching the headers. Matches in headers
     are not highlighted as managing the highlight is too much of a pain.'''
     if not query.strip():
         return
     c = self.textCursor()
     lnum = c.block().blockNumber()
     cpos = c.positionInBlock()
     headers = dict(self.headers)
     if lnum in headers:
         cpos = self.search_header_pos
     lines = unicode(self.toPlainText()).splitlines()
     for hn, text in self.headers:
         lines[hn] = text
     prefix, postfix = lines[lnum][:cpos], lines[lnum][cpos:]
     before, after = enumerate(lines[0:lnum]), ((lnum+1+i, x) for i, x in enumerate(lines[lnum+1:]))
     if reverse:
         sl = chain([(lnum, prefix)], reversed(tuple(before)), reversed(tuple(after)), [(lnum, postfix)])
     else:
         sl = chain([(lnum, postfix)], after, before, [(lnum, prefix)])
     flags = regex.REVERSE if reverse else 0
     pat = regex.compile(regex.escape(query, special_only=True), flags=regex.UNICODE|regex.IGNORECASE|flags)
     for num, text in sl:
         try:
             m = next(pat.finditer(text))
         except StopIteration:
             continue
         start, end = m.span()
         length = end - start
         if text is postfix:
             start += cpos
         c = QTextCursor(self.document().findBlockByNumber(num))
         c.setPosition(c.position() + start)
         if num in headers:
             self.search_header_pos = start + length
         else:
             c.setPosition(c.position() + length, c.KeepAnchor)
             self.search_header_pos = 0
         if reverse:
             pos, anchor = c.position(), c.anchor()
             c.setPosition(pos), c.setPosition(anchor, c.KeepAnchor)
         self.setTextCursor(c)
         self.centerCursor()
         self.scrolled.emit()
         break
     else:
         info_dialog(self, _('No matches found'), _(
             'No matches found for query: %s' % query), show=True)
Ejemplo n.º 22
0
    def resized(self):
        ' Resize images to fit in new view size and adjust all line number references accordingly '
        for v in (self.left, self.right):
            changes = []
            for i, (top, bot, kind) in enumerate(v.changes):
                if top in v.images:
                    img, oldw, oldlines = v.images[top]
                    lines, w = self.get_lines_for_image(img, v)
                    if lines != oldlines:
                        changes.append((i, lines, lines - oldlines, img, w))

            for i, lines, delta, img, w in changes:
                top, bot, kind = v.changes[i]
                c = QTextCursor(v.document().findBlockByNumber(top+1))
                c.beginEditBlock()
                c.movePosition(c.StartOfBlock)
                if delta > 0:
                    for _ in xrange(delta):
                        c.insertBlock()
                else:
                    c.movePosition(c.NextBlock, c.KeepAnchor, -delta)
                    c.removeSelectedText()
                c.endEditBlock()
                v.images[top] = (img, w, lines)
                def mapnum(x):
                    return x if x <= top else x + delta
                lnm = LineNumberMap()
                lnm.max_width = v.line_number_map.max_width
                for x, val in v.line_number_map.iteritems():
                    dict.__setitem__(lnm, mapnum(x), val)
                v.line_number_map = lnm
                v.changes = [(mapnum(t), mapnum(b), k) for t, b, k in v.changes]
                v.headers = [(mapnum(x), name) for x, name in v.headers]
                v.images = OrderedDict((mapnum(x), v) for x, v in v.images.iteritems())
            v.viewport().update()
Ejemplo n.º 23
0
 def search(self, query, reverse=False):
     ''' Search for query, also searching the headers. Matches in headers
     are not highlighted as managing the highlight is too much of a pain.'''
     if not query.strip():
         return
     c = self.textCursor()
     lnum = c.block().blockNumber()
     cpos = c.positionInBlock()
     headers = dict(self.headers)
     if lnum in headers:
         cpos = self.search_header_pos
     lines = unicode(self.toPlainText()).splitlines()
     for hn, text in self.headers:
         lines[hn] = text
     prefix, postfix = lines[lnum][:cpos], lines[lnum][cpos:]
     before, after = enumerate(lines[0:lnum]), ((lnum+1+i, x) for i, x in enumerate(lines[lnum+1:]))
     if reverse:
         sl = chain([(lnum, prefix)], reversed(tuple(before)), reversed(tuple(after)), [(lnum, postfix)])
     else:
         sl = chain([(lnum, postfix)], after, before, [(lnum, prefix)])
     flags = regex.REVERSE if reverse else 0
     pat = regex.compile(regex.escape(query, special_only=True), flags=regex.UNICODE|regex.IGNORECASE|flags)
     for num, text in sl:
         try:
             m = next(pat.finditer(text))
         except StopIteration:
             continue
         start, end = m.span()
         length = end - start
         if text is postfix:
             start += cpos
         c = QTextCursor(self.document().findBlockByNumber(num))
         c.setPosition(c.position() + start)
         if num in headers:
             self.search_header_pos = start + length
         else:
             c.setPosition(c.position() + length, c.KeepAnchor)
             self.search_header_pos = 0
         if reverse:
             pos, anchor = c.position(), c.anchor()
             c.setPosition(pos), c.setPosition(anchor, c.KeepAnchor)
         self.setTextCursor(c)
         self.centerCursor()
         self.scrolled.emit()
         break
     else:
         info_dialog(self, _('No matches found'), _(
             'No matches found for query: %s' % query), show=True)
Ejemplo n.º 24
0
class MainWindow(QMainWindow):
    """ Create the main
        Create the main window and setup all
        widgets needed.
     """

    log_area: QPlainTextEdit
    main_document: QTextDocument
    serial_dialog: SerialDialog
    serial_menu: QMenu
    help_menu: QMenu
    log_filter_widget: QWidget
    log_filters: FilterPanel

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

        self.log_area = None  # :type QPlainTextEdit
        self.main_document = None  # :type QTextDocument
        self.highlight_options_dialog = None  # :type HighlightOptionsDialog
        self.serial_dialog = None  # :type SerialDialog
        self.serial_menu = None  # :type QMenu
        self.highlight_options_menu = None  # :type QMenu
        self.help_menu = None  # :type QMenu
        self.log_filter_widget = None  # :type QWidget
        self.log_filters = None  # :type FilterPanel
        self.last_search = str()
        self.last_search_cursor = QTextCursor()

        container = QWidget()
        self.setup_menu()
        self.setup_text_area()
        self.setup_footer_panel()
        self.setup_serial_dialog()
        self.setup_highlight_options_dialog()

        self.first_search_flag = False

        self.serial_worker = SerialListenerWorker()
        self.serial_worker.signal.connect(self.add_line_to_log_area)

        self.log_area_layout = QVBoxLayout()
        self.log_area_layout.setContentsMargins(0, 0, 0, 0)
        self.log_area_layout.addWidget(self.log_area)
        self.log_area_layout.addWidget(self.log_filter_widget)
        container.setLayout(self.log_area_layout)

        self.setCentralWidget(container)

        self.setWindowTitle(APP_NAME)
        self.setGeometry(QRect(100, 100, 800, 600))

    def closeEvent(self, event):
        self.serial_dialog.serial_handler.close()
        del self.serial_worker

    def setup_serial_dialog(self):
        """Setup the Serial Dialog interface"""
        self.serial_dialog = SerialDialog(self)

    def setup_highlight_options_dialog(self):
        """Setup the highlighting options dialog interface"""
        self.highlight_options_dialog = HighlightOptionsDialog(self)

    def setup_menu(self):
        """Setup the menu"""
        self.serial_menu = self.menuBar().addMenu("Serial")
        self.highlight_options_menu = self.menuBar().addMenu(
            "Highlight Options")
        self.help_menu = self.menuBar().addMenu("Help")

        action_serial_setup = QAction("Setup", self)
        action_serial_setup.triggered.connect(self.serial_setup)
        self.serial_menu.addAction(action_serial_setup)

        action_highlight_options = QAction("Highlight Options", self)
        action_highlight_options.triggered.connect(
            self.highlight_options_setup)
        self.highlight_options_menu.addAction(action_highlight_options)

        action_about_box = QAction("About", self)
        action_about_box.triggered.connect(self.about_box_show)
        self.help_menu.addAction(action_about_box)

    def setup_text_area(self):
        """Setup the log text area and the highlighter class"""
        self.log_area = QPlainTextEdit()
        self.log_area.setReadOnly(True)
        self.log_area.centerOnScroll()

        self.main_document = self.log_area.document()
        HighlighterTag(self.log_area.document())

    def setup_footer_panel(self):
        """Setup the footer area"""
        self.log_filter_widget = QWidget()
        self.log_filters = FilterPanel(self.log_filter_widget)
        self.log_filters.filter_changed.connect(self.filter_document)
        self.log_filters.filter_clear_button.clicked.connect(
            self.clear_log_area)
        self.log_filters.filter_search_button.clicked.connect(
            self.search_log_area)

    @pyqtSlot(str)
    def filter_document(self, msg: str):
        """Filter the log area with the selected tag.
           The log area will show only the lines with the selected tag
           or untagged lines.
        :type msg: str (ALL|DEBUG|INFO|ERROR|CRITICAL|FATAL)
        """
        tag = find_tag_by_name(msg)
        log_filter_by_tag(self.main_document, tag)
        self.update()

    def highlight_options_setup(self):
        apply = self.highlight_options_dialog.exec()

    def serial_setup(self):
        """
            Execute the serial dialog interface.
            If the the result (:type dialog_result : int)== 0 and the
            connection is successfully done, start the serial_worker thread
            If the the result (:type dialog_result : int) == 1, disconnection
            was requested, the worker is closed and the serial connection are closed
        """
        dialog_result = self.serial_dialog.exec()
        logger.debug("SerialDialog result : " + str(dialog_result))
        if dialog_result == 0:
            if self.serial_dialog.serial_handler.isOpen():
                self.serial_worker.serial_handler = self.serial_dialog.serial_handler
                self.serial_worker.start()
        elif dialog_result == 1:
            self.serial_worker.terminate()
            self.serial_dialog.serial_handler.close()

    def about_box_show(self):
        about_msg_box = QMessageBox(self)
        about_msg_box.setGeometry(QRect(100, 100, 240, 360))
        about_msg_box.addButton(QPushButton("OK"), QMessageBox.YesRole)
        about_msg_box.setWindowTitle(APP_NAME)

        about_msg_box.setText("{0}\n"
                              "Verion : {1}\n"
                              "Author : {2}\n"
                              "Email : {3}".format(APP_NAME, APP_VERSION,
                                                   APP_AUTHOR,
                                                   APP_AUTHOR_EMAIL))
        about_msg_box.exec()

    @pyqtSlot(str)
    def add_line_to_log_area(self, log):
        """
        Add a string to the log area
        :param log: str
        """
        self.log_area.appendPlainText(log)

    def clear_log_area(self):
        """
        clear the log area
        """
        self.log_area.clear()

    def search_log_area(self):
        """ Search a word in log area.
        Keep last cursor and word used for iteration
        in the document.
        """

        cursor: QTextCursor
        doc: QTextDocument
        text: str
        search_format: QTextCharFormat

        text = self.log_filters.filter_line.text()
        doc = self.log_area.document()

        search_format = QTextCharFormat()
        color = QColor("yellow")
        color.setAlpha(255)
        search_format.setBackground(color)

        # remove the previous search highlight
        if not self.last_search_cursor.isNull():
            self.last_search_cursor.setCharFormat(QTextCharFormat())

        # if search word changed or erased, reset cursor and last_search
        if len(text) == 0 or text != self.last_search:
            self.last_search_cursor = QTextCursor()
            self.last_search = text
            self.log_area.unsetCursor()
        # if has no word to search, just return
        if len(text) == 0:
            return

        cursor = self.last_search_cursor if not self.last_search_cursor.isNull(
        ) else QTextCursor(doc)
        cursor = doc.find(text, cursor)
        if not cursor.isNull():
            self.log_area.setTextCursor(cursor)
            cursor.setCharFormat(search_format)
        else:
            self.log_area.unsetCursor()
        self.last_search_cursor = cursor
Ejemplo n.º 25
0
    def find_text(self, pat, cursor):
        from calibre.gui2.tweak_book.text_search import find_text_in_chunks
        chunks = []

        cstart = min(cursor.position(), cursor.anchor())
        cend = max(cursor.position(), cursor.anchor())
        c = QTextCursor(cursor)
        c.setPosition(cstart)
        block = c.block()
        in_text = find_tag_definition(block, 0)[0] is None

        def append(text, start):
            after = start + len(text)
            if start <= cend and cstart < after:
                extra = after - (cend + 1)
                if extra > 0:
                    text = text[:-extra]
                extra = cstart - start
                if extra > 0:
                    text = text[extra:]
                chunks.append((text, start + max(extra, 0)))

        while block.isValid() and block.position() <= cend:
            boundaries = sorted(block.userData().tags, key=get_offset)
            if not boundaries:
                # Add the whole line
                if in_text:
                    text = block.text()
                    if text:
                        append(text, block.position())
            else:
                start = block.position()
                c.setPosition(start)
                for b in boundaries:
                    if in_text:
                        c.setPosition(start + b.offset, c.KeepAnchor)
                        if c.hasSelection():
                            append(c.selectedText(), c.anchor())
                    in_text = not b.is_start
                    c.setPosition(start + b.offset + 1)
                if in_text:
                    # Add remaining text in block
                    c.setPosition(block.position() + boundaries[-1].offset + 1)
                    c.movePosition(c.EndOfBlock, c.KeepAnchor)
                    if c.hasSelection():
                        append(c.selectedText(), c.anchor())
            block = block.next()
        s, e = find_text_in_chunks(pat, chunks)
        return s != -1 and e != -1, s, e
Ejemplo n.º 26
0
    def show_context_menu(self, pos):
        m = QMenu(self)
        a = m.addAction
        c = self.editor.cursorForPosition(pos)
        origc = QTextCursor(c)
        current_cursor = self.editor.textCursor()
        r = origr = self.editor.syntax_range_for_cursor(c)
        if (r is None or not r.format.property(SPELL_PROPERTY)) and c.positionInBlock() > 0 and not current_cursor.hasSelection():
            c.setPosition(c.position() - 1)
            r = self.editor.syntax_range_for_cursor(c)

        if r is not None and r.format.property(SPELL_PROPERTY):
            word = self.editor.text_for_range(c.block(), r)
            locale = self.editor.spellcheck_locale_for_cursor(c)
            orig_pos = c.position()
            c.setPosition(orig_pos - utf16_length(word))
            found = False
            self.editor.setTextCursor(c)
            if self.editor.find_spell_word([word], locale.langcode, center_on_cursor=False):
                found = True
                fc = self.editor.textCursor()
                if fc.position() < c.position():
                    self.editor.find_spell_word([word], locale.langcode, center_on_cursor=False)
            spell_cursor = self.editor.textCursor()
            if current_cursor.hasSelection():
                # Restore the current cursor so that any selection is preserved
                # for the change case actions
                self.editor.setTextCursor(current_cursor)
            if found:
                suggestions = dictionaries.suggestions(word, locale)[:7]
                if suggestions:
                    for suggestion in suggestions:
                        ac = m.addAction(suggestion, partial(self.editor.simple_replace, suggestion, cursor=spell_cursor))
                        f = ac.font()
                        f.setBold(True), ac.setFont(f)
                    m.addSeparator()
                m.addAction(actions['spell-next'])
                m.addAction(_('Ignore this word'), partial(self._nuke_word, None, word, locale))
                dics = dictionaries.active_user_dictionaries
                if len(dics) > 0:
                    if len(dics) == 1:
                        m.addAction(_('Add this word to the dictionary: {0}').format(dics[0].name), partial(
                            self._nuke_word, dics[0].name, word, locale))
                    else:
                        ac = m.addAction(_('Add this word to the dictionary'))
                        dmenu = QMenu(m)
                        ac.setMenu(dmenu)
                        for dic in dics:
                            dmenu.addAction(dic.name, partial(self._nuke_word, dic.name, word, locale))
                m.addSeparator()

        if origr is not None and origr.format.property(LINK_PROPERTY):
            href = self.editor.text_for_range(origc.block(), origr)
            m.addAction(_('Open %s') % href, partial(self.link_clicked.emit, href))

        if origr is not None and (origr.format.property(TAG_NAME_PROPERTY) or origr.format.property(CSS_PROPERTY)):
            word = self.editor.text_for_range(origc.block(), origr)
            item_type = 'tag_name' if origr.format.property(TAG_NAME_PROPERTY) else 'css_property'
            url = help_url(word, item_type, self.editor.highlighter.doc_name, extra_data=current_container().opf_version)
            if url is not None:
                m.addAction(_('Show help for: %s') % word, partial(open_url, url))

        for x in ('undo', 'redo'):
            ac = actions['editor-%s' % x]
            if ac.isEnabled():
                a(ac)
        m.addSeparator()
        for x in ('cut', 'copy', 'paste'):
            ac = actions['editor-' + x]
            if ac.isEnabled():
                a(ac)
        m.addSeparator()
        m.addAction(_('&Select all'), self.editor.select_all)
        if self.selected_text or self.has_marked_text:
            update_mark_text_action(self)
            m.addAction(actions['mark-selected-text'])
        if self.syntax != 'css' and actions['editor-cut'].isEnabled():
            cm = QMenu(_('Change &case'), m)
            for ac in 'upper lower swap title capitalize'.split():
                cm.addAction(actions['transform-case-' + ac])
            m.addMenu(cm)
        if self.syntax == 'html':
            m.addAction(actions['multisplit'])
        m.exec_(self.editor.viewport().mapToGlobal(pos))
Ejemplo n.º 27
0
    def find_text(self, pat, cursor):
        from calibre.gui2.tweak_book.text_search import find_text_in_chunks
        chunks = []

        cstart = min(cursor.position(), cursor.anchor())
        cend = max(cursor.position(), cursor.anchor())
        c = QTextCursor(cursor)
        c.setPosition(cstart)
        block = c.block()
        in_text = find_tag_definition(block, 0)[0] is None
        if in_text:
            # Check if we are in comment/PI/etc.
            pb = block.previous()
            while pb.isValid():
                boundaries = pb.userData().non_tag_structures
                if boundaries:
                    if boundaries[-1].is_start:
                        in_text = False
                    break
                pb = pb.previous()

        def append(text, start):
            text = text.replace(PARAGRAPH_SEPARATOR, '\n')
            after = start + len(text)
            if start <= cend and cstart < after:
                extra = after - (cend + 1)
                if extra > 0:
                    text = text[:-extra]
                extra = cstart - start
                if extra > 0:
                    text = text[extra:]
                chunks.append((text, start + max(extra, 0)))

        while block.isValid() and block.position() <= cend:
            ud = block.userData()
            boundaries = sorted(chain(ud.tags, ud.non_tag_structures),
                                key=get_offset)
            if not boundaries:
                # Add the whole line
                if in_text:
                    text = block.text() + '\n'
                    append(text, block.position())
            else:
                start = block.position()
                c.setPosition(start)
                for b in boundaries:
                    if in_text:
                        c.setPosition(start + b.offset, c.KeepAnchor)
                        if c.hasSelection():
                            append(c.selectedText(), c.anchor())
                    in_text = not b.is_start
                    c.setPosition(start + b.offset + 1)
                if in_text:
                    # Add remaining text in block
                    c.setPosition(block.position() + boundaries[-1].offset + 1)
                    c.movePosition(c.EndOfBlock, c.KeepAnchor)
                    if c.hasSelection():
                        append(c.selectedText() + '\n', c.anchor())
            block = block.next()
        s, e = find_text_in_chunks(pat, chunks)
        return s != -1 and e != -1, s, e
Ejemplo n.º 28
0
    def find_text(self, pat, cursor):
        from calibre.gui2.tweak_book.text_search import find_text_in_chunks
        chunks = []

        cstart = min(cursor.position(), cursor.anchor())
        cend = max(cursor.position(), cursor.anchor())
        c = QTextCursor(cursor)
        c.setPosition(cstart)
        block = c.block()
        in_text = find_tag_definition(block, 0)[0] is None
        if in_text:
            # Check if we are in comment/PI/etc.
            pb = block.previous()
            while pb.isValid():
                boundaries = pb.userData().non_tag_structures
                if boundaries:
                    if boundaries[-1].is_start:
                        in_text = False
                    break
                pb = pb.previous()

        def append(text, start):
            text = text.replace(PARAGRAPH_SEPARATOR, '\n')
            after = start + len(text)
            if start <= cend and cstart < after:
                extra = after - (cend + 1)
                if extra > 0:
                    text = text[:-extra]
                extra = cstart - start
                if extra > 0:
                    text = text[extra:]
                chunks.append((text, start + max(extra, 0)))

        while block.isValid() and block.position() <= cend:
            ud = block.userData()
            boundaries = sorted(chain(ud.tags, ud.non_tag_structures), key=get_offset)
            if not boundaries:
                # Add the whole line
                if in_text:
                    text = block.text() + '\n'
                    append(text, block.position())
            else:
                start = block.position()
                c.setPosition(start)
                for b in boundaries:
                    if in_text:
                        c.setPosition(start + b.offset, c.KeepAnchor)
                        if c.hasSelection():
                            append(c.selectedText(), c.anchor())
                    in_text = not b.is_start
                    c.setPosition(start + b.offset + 1)
                if in_text:
                    # Add remaining text in block
                    c.setPosition(block.position() + boundaries[-1].offset + 1)
                    c.movePosition(c.EndOfBlock, c.KeepAnchor)
                    if c.hasSelection():
                        append(c.selectedText() + '\n', c.anchor())
            block = block.next()
        s, e = find_text_in_chunks(pat, chunks)
        return s != -1 and e != -1, s, e
Ejemplo n.º 29
0
class Doc(QObject):

    changed_status = pyqtSignal(dict)  # for update the status bar
    changed_bold = pyqtSignal(bool)  # for update button "Bold"
    enabled_save = pyqtSignal(bool)  # for update button "Save"

    # -------------------------------------------------------------------------
    def __init__(self, config):
        super(Doc, self).__init__()
        self._text = QTextDocument()
        self._cfg = config
        self._text_edit_cursor = QTextCursor(self._text)
        self._text.setIndentWidth(self._cfg.get("TextEditor/IndentWidth", 24))

        self.set_default_font()

    # -------------------------------------------------------------------------
    @property
    def text(self):
        return self._text

    # -------------------------------------------------------------------------
    def is_modified(self):
        return self._text.isModified()

    # -------------------------------------------------------------------------
    def in_table(self):
        return bool(self._text_edit_cursor.currentTable())

    # -------------------------------------------------------------------------
    def set_default_font(self, set_modified=False):
        font_name = self._cfg.get("TextEditor/Font", "Mono", system=True)
        sz = self._cfg.get("TextEditor/FontSize", 10, system=True)
        font = QFont(font_name, sz)
        self._text.setDefaultFont(font)
        if set_modified:
            self._text.setModified(True)
            self.change(self._text_edit_cursor)

    # -------------------------------------------------------------------------
    def change(self, text_cursor: QTextCursor = None):
        """
        Called (from QTextEdit event) with changed text or position of cursor
        """
        if text_cursor:
            self._text_edit_cursor = text_cursor

        # refresh data on statusbar
        y = self._text_edit_cursor.blockNumber() + 1
        cnt = self._text.lineCount()
        x = self._text_edit_cursor.columnNumber() + 1
        chg = (self.tr("The document is not saved")
               if self._text.isModified() else "")
        xy = f"{y} : {x} [{cnt}]"
        self.changed_status.emit({"left": chg, "right": xy})
        self.enabled_save.emit(self.is_modified())

    # -------------------------------------------------------------------------
    def bold(self):
        """
        Set/unset bold font
        """
        fmt = self._text_edit_cursor.charFormat()
        typ = QFont.Normal if fmt.fontWeight() == QFont.Bold else QFont.Bold
        fmt.setFontWeight(typ)
        self._text_edit_cursor.setCharFormat(fmt)
        self.change(self._text_edit_cursor)
        self.changed_bold.emit(typ == QFont.Bold)

    # -------------------------------------------------------------------------
    def color(self, color):
        fmt = self._text_edit_cursor.charFormat()
        fmt.setForeground(QColor(color))
        self._text_edit_cursor.setCharFormat(fmt)

    # -------------------------------------------------------------------------
    def background_color(self, color):
        fmt = self._text_edit_cursor.charFormat()
        if self.in_table():
            table = self._text_edit_cursor.currentTable()
            cell = table.cellAt(self._text_edit_cursor)
            cell_format = cell.format()
            cell_format.setBackground(QColor(color))
            cell.setFormat(cell_format)
        else:
            fmt.setBackground(QColor(color))
        self._text_edit_cursor.setCharFormat(fmt)

    # -------------------------------------------------------------------------
    def font(self, font):
        fmt = self._text_edit_cursor.charFormat()
        fmt.setFont(font)
        self._text_edit_cursor.setCharFormat(fmt)

    # -------------------------------------------------------------------------
    def font_size(self, font_size):
        fmt = self._text_edit_cursor.charFormat()
        fmt.setFontPointSize(font_size)
        self._text_edit_cursor.setCharFormat(fmt)

    # -------------------------------------------------------------------------
    def hline(self):
        """
        Insert horizontal line
        """
        # Tag HR is not correctly displayed  in QTextview
        cur_char_fmt = self._text_edit_cursor.charFormat()
        cur_block_fmt = self._text_edit_cursor.blockFormat()
        if bool(self._text_edit_cursor.currentTable()):
            self._text_edit_cursor.insertBlock(cur_block_fmt, cur_char_fmt)

        block_fmt = QTextBlockFormat()
        block_fmt.setTopMargin(5)
        block_fmt.setBottomMargin(5)
        block_fmt.setAlignment(Qt.AlignLeft)
        block_fmt.setBackground(QBrush(QColor("#C1C1C1")))

        char_format = QTextCharFormat()
        char_format.setFont(QFont("Arial", 1))

        self._text_edit_cursor.insertBlock(block_fmt, char_format)
        self._text_edit_cursor.insertText(" ")

        self._text_edit_cursor.insertBlock(cur_block_fmt, cur_char_fmt)

        self.change(self._text_edit_cursor)

    # -------------------------------------------------------------------------
    def show_hide_hidden_char(self, show: bool):
        if show:
            # show hidden char
            option = self._text.defaultTextOption()
            option.setFlags(
                option.flags() | QTextOption.ShowTabsAndSpaces
                | QTextOption.ShowLineAndParagraphSeparators
                | QTextOption.AddSpaceForLineAndParagraphSeparators)
            self._text.setDefaultTextOption(option)
        else:
            # remove hidden char
            option = self._text.defaultTextOption()
            stas = ~QTextOption.ShowTabsAndSpaces
            slaps = ~QTextOption.ShowLineAndParagraphSeparators
            asflaps = ~QTextOption.AddSpaceForLineAndParagraphSeparators
            option.setFlags(option.flags() & stas & slaps & asflaps)
            self._text.setDefaultTextOption(option)

    # -------------------------------------------------------------------------
    def blist(self):
        self._text_edit_cursor.insertList(QTextListFormat.ListDisc)

    # -------------------------------------------------------------------------
    def nlist(self):
        self._text_edit_cursor.insertList(QTextListFormat.ListDecimal)

    # -------------------------------------------------------------------------
    def copy_format(self, fmt):
        self._text_edit_cursor.setCharFormat(fmt)

    # -------------------------------------------------------------------------
    def clear_format(self):
        txt = self._text.toPlainText()
        self._text_edit_cursor.beginEditBlock()  # ----  begin -------
        self._text_edit_cursor.select(QTextCursor.Document)
        self._text_edit_cursor.removeSelectedText()
        fmt = QTextBlockFormat()
        self._text_edit_cursor.setBlockFormat(fmt)
        self._text_edit_cursor.insertText(txt)
        self._text_edit_cursor.endEditBlock()  # ----  end ---------

    # -------------------------------------------------------------------------
    def text_align(self, horiz, vert):

        fmt = QTextBlockFormat()
        fmt.setAlignment(horiz)
        self._text_edit_cursor.mergeBlockFormat(fmt)

        if self.in_table():
            table = self._text_edit_cursor.currentTable()
            cell = table.cellAt(self._text_edit_cursor)
            cell_format = cell.format()
            cell_format.setVerticalAlignment(vert)
            cell.setFormat(cell_format)

    # -------------------------------------------------------------------------
    def insert_table(self, table_params):
        fmt = QTextTableFormat()
        fmt.setCellPadding(table_params["padding"])
        fmt.setCellSpacing(table_params["space"])
        return self._text_edit_cursor.insertTable(table_params["rows"],
                                                  table_params["cols"], fmt)

    # -------------------------------------------------------------------------
    def table(self):
        """
        Current table if cursor in table
        """
        return self._text_edit_cursor.currentTable()

    # -------------------------------------------------------------------------
    def cell(self):
        """
        Cell in current table
        """
        return self.table().cellAt(self._text_edit_cursor)

    # -------------------------------------------------------------------------
    def add_row(self):
        self.table().appendRows(1)

    # -------------------------------------------------------------------------
    def add_col(self):
        self.table().appendColumns(1)

    # -------------------------------------------------------------------------
    def del_row(self):
        self.table().removeRows(self.cell().row(), 1)

    # -------------------------------------------------------------------------
    def del_col(self):
        self.table().removeColumns(self.cell().column(), 1)

    # -------------------------------------------------------------------------
    def ins_row(self):
        self.table().insertRows(self.cell().row(), 1)

    # -------------------------------------------------------------------------
    def ins_col(self):
        self.table().insertColumns(self.cell().column(), 1)

    # -------------------------------------------------------------------------
    def merge_cells(self):
        self.table().mergeCells(self._text_edit_cursor)

    # -------------------------------------------------------------------------
    def split_cells(self):
        self.table().splitCell(self.cell().row(), self.cell().column(), 1, 1)

    # -------------------------------------------------------------------------
    def replace(self, replace_text):
        self._text_edit_cursor.insertText(replace_text)

    # -------------------------------------------------------------------------
    def ins_date(self):
        self._text_edit_cursor.insertText(
            datetime.datetime.now().strftime("%d.%m.%Y "))

    # -------------------------------------------------------------------------
    def ins_time(self):
        self._text_edit_cursor.insertText(
            datetime.datetime.now().strftime("%d.%m.%Y %H:%M:%S "))

    # -------------------------------------------------------------------------
    def in_image(self):
        return self._text_edit_cursor.charFormat().isImageFormat()

    # -------------------------------------------------------------------------
    def ins_image(self, image, fmt, width, height, insert_space=True):
        bytes_ = QByteArray()
        buffer = QBuffer(bytes_)
        buffer.open(QIODevice.WriteOnly)
        image.save(buffer, fmt)
        buffer.close()

        base64 = bytes_.toBase64().data().decode(encoding="utf-8")

        s = (f'<img width="{width}" height="{height}" '
             f'src="data:image/{fmt};base64,{base64}"')

        self._text_edit_cursor.insertHtml(s)

        if insert_space:
            self._text_edit_cursor.insertText(" ")

    # -------------------------------------------------------------------------
    @staticmethod
    def get_image(html):
        image, width, height, fmt = None, -1, -1, "png"
        if "<img" in html:
            raw = html[html.index("<img"):].split(">")[0].split('"')
            for i, r in enumerate(raw):
                if "base64" in r:
                    img_txt = r.split(",")[-1].encode(encoding="utf-8")
                    image = QPixmap()
                    image.width()
                    image.height()
                    image.loadFromData(QByteArray.fromBase64(img_txt))
                    fmt = r.split("image/")[1].split(";")[0]
                if "width" in r and i + 1 < len(raw):
                    width = int(raw[i + 1])
                if "height" in r and i + 1 < len(raw):
                    height = int(raw[i + 1])
        return image, width, height, fmt

    # -------------------------------------------------------------------------
    def save(self, save_proc):
        if self._text.isModified():
            self._text.setModified(False)
            if self._cfg.get("TextEditor/PlainText", 0):
                txt = str(self._text.toPlainText())
                if self._cfg.get("TextEditor/ReplaceTabWithSpace", 0):
                    cnt = self._cfg.get("TextEditor/CountSpaceInTab", 1)
                    txt = txt.replace("\t", " " * cnt)
                res = save_proc(txt)
            else:
                res = save_proc(str(self._text.toHtml(encoding=QByteArray())))
            if res is not None:
                self._text.setModified(True)

        self.change(self._text_edit_cursor)

    # -------------------------------------------------------------------------
    def load(self, load_proc):
        self._text.clear()
        if self._cfg.get("TextEditor/PlainText", 0):
            self._text.setPlainText(load_proc())
        else:
            self._text.setHtml(load_proc())
        self._text.setModified(False)

    # -------------------------------------------------------------------------
    def get_text(self):
        if self._cfg.get("TextEditor/PlainText", 0):
            return str(self._text.toPlainText())
        else:
            return str(self._text.toHtml(encoding=QByteArray()))

    # -------------------------------------------------------------------------
    def is_empty(self):
        return not bool(len(self._text.toPlainText().strip()))
Ejemplo n.º 30
0
def apply_smart_comment(editor, opening='/*', closing='*/', line_comment=None):
    doc = editor.document()
    c = QTextCursor(editor.textCursor())
    c.clearSelection()
    before_opening = doc.find(opening, c,
                              doc.FindBackward | doc.FindCaseSensitively)
    before_closing = doc.find(closing, c,
                              doc.FindBackward | doc.FindCaseSensitively)
    after_opening = doc.find(opening, c, doc.FindCaseSensitively)
    after_closing = doc.find(closing, c, doc.FindCaseSensitively)
    in_block_comment = (not before_opening.isNull() and (before_closing.isNull() or before_opening.position() >= before_closing.position())) and \
        (not after_closing.isNull() and (after_opening.isNull() or after_closing.position() <= after_opening.position()))
    if in_block_comment:
        before_opening.removeSelectedText(), after_closing.removeSelectedText()
        return
    c = QTextCursor(editor.textCursor())
    left, right = min(c.position(), c.anchor()), max(c.position(), c.anchor())
    c.beginEditBlock()
    c.setPosition(right), c.insertText(closing)
    c.setPosition(left), c.insertText(opening)
    c.endEditBlock()
Ejemplo n.º 31
0
    def show_context_menu(self, pos):
        m = QMenu(self)
        a = m.addAction
        c = self.editor.cursorForPosition(pos)
        origc = QTextCursor(c)
        current_cursor = self.editor.textCursor()
        r = origr = self.editor.syntax_range_for_cursor(c)
        if (
                r is None or not r.format.property(SPELL_PROPERTY)
        ) and c.positionInBlock() > 0 and not current_cursor.hasSelection():
            c.setPosition(c.position() - 1)
            r = self.editor.syntax_range_for_cursor(c)

        if r is not None and r.format.property(SPELL_PROPERTY):
            word = self.editor.text_for_range(c.block(), r)
            locale = self.editor.spellcheck_locale_for_cursor(c)
            orig_pos = c.position()
            c.setPosition(orig_pos - utf16_length(word))
            found = False
            self.editor.setTextCursor(c)
            if self.editor.find_spell_word([word],
                                           locale.langcode,
                                           center_on_cursor=False):
                found = True
                fc = self.editor.textCursor()
                if fc.position() < c.position():
                    self.editor.find_spell_word([word],
                                                locale.langcode,
                                                center_on_cursor=False)
            spell_cursor = self.editor.textCursor()
            if current_cursor.hasSelection():
                # Restore the current cursor so that any selection is preserved
                # for the change case actions
                self.editor.setTextCursor(current_cursor)
            if found:
                suggestions = dictionaries.suggestions(word, locale)[:7]
                if suggestions:
                    for suggestion in suggestions:
                        ac = m.addAction(
                            suggestion,
                            partial(self.editor.simple_replace,
                                    suggestion,
                                    cursor=spell_cursor))
                        f = ac.font()
                        f.setBold(True), ac.setFont(f)
                    m.addSeparator()
                m.addAction(actions['spell-next'])
                m.addAction(_('Ignore this word'),
                            partial(self._nuke_word, None, word, locale))
                dics = dictionaries.active_user_dictionaries
                if len(dics) > 0:
                    if len(dics) == 1:
                        m.addAction(
                            _('Add this word to the dictionary: {0}').format(
                                dics[0].name),
                            partial(self._nuke_word, dics[0].name, word,
                                    locale))
                    else:
                        ac = m.addAction(_('Add this word to the dictionary'))
                        dmenu = QMenu(m)
                        ac.setMenu(dmenu)
                        for dic in dics:
                            dmenu.addAction(
                                dic.name,
                                partial(self._nuke_word, dic.name, word,
                                        locale))
                m.addSeparator()

        if origr is not None and origr.format.property(LINK_PROPERTY):
            href = self.editor.text_for_range(origc.block(), origr)
            m.addAction(
                _('Open %s') % href, partial(self.link_clicked.emit, href))

        if origr is not None and (origr.format.property(TAG_NAME_PROPERTY)
                                  or origr.format.property(CSS_PROPERTY)):
            word = self.editor.text_for_range(origc.block(), origr)
            item_type = 'tag_name' if origr.format.property(
                TAG_NAME_PROPERTY) else 'css_property'
            url = help_url(word,
                           item_type,
                           self.editor.highlighter.doc_name,
                           extra_data=current_container().opf_version)
            if url is not None:
                m.addAction(
                    _('Show help for: %s') % word, partial(open_url, url))

        for x in ('undo', 'redo'):
            ac = actions['editor-%s' % x]
            if ac.isEnabled():
                a(ac)
        m.addSeparator()
        for x in ('cut', 'copy', 'paste'):
            ac = actions['editor-' + x]
            if ac.isEnabled():
                a(ac)
        m.addSeparator()
        m.addAction(_('&Select all'), self.editor.select_all)
        if self.selected_text or self.has_marked_text:
            update_mark_text_action(self)
            m.addAction(actions['mark-selected-text'])
        if self.syntax != 'css' and actions['editor-cut'].isEnabled():
            cm = QMenu(_('Change &case'), m)
            for ac in 'upper lower swap title capitalize'.split():
                cm.addAction(actions['transform-case-' + ac])
            m.addMenu(cm)
        if self.syntax == 'html':
            m.addAction(actions['multisplit'])
        m.exec_(self.editor.viewport().mapToGlobal(pos))
Ejemplo n.º 32
0
class DocumentFactory:
    
    def __init__(self, contentPath, formatManager):
        self.formatManager = formatManager
        self.contentPath = contentPath


    def createDocument(self, rootFrame):

        # Create empty document
        self.document = QTextDocument()
        self.document.setUndoRedoEnabled(False)
        self.document.setIndentWidth(20)

        # Register a renderer for custom text objects
        mo = CustomObjectRenderer()
        mo.setParent(self.document)
        self.document.documentLayout().registerHandler(QTextCharFormat.UserObject+1, mo);

        self.cursor = QTextCursor(self.document)
        self.listLevel = 0
        self.paraFormat = None

        # add all root paragraphs
        for n in rootFrame.children:
            self.addNode(n)

        # Clean up the first paragraph if document is not empty
        self.cursor.movePosition(QTextCursor.Start)
        b = self.cursor.block()
        if b.length() == 1:
            cursor = QTextCursor(self.document.findBlockByLineNumber(0))
            cursor.select(QTextCursor.BlockUnderCursor)
            cursor.deleteChar()

        return self.document


    def addNode(self, node):
        if type(node) == Paragraph:
            self.paraFormat = self.formatManager.getFormat(node.style)

            # NOTE: "The block char format is the format used when inserting 
            #        text at the beginning of an empty block."
            #       See also below.
            self.cursor.insertBlock(self.paraFormat.getBlockFormat(), self.paraFormat.getCharFormat())
            # self.cursor.insertFragment(QTextDocumentFragment.fromPlainText(''))

            if self.listLevel > 0:
                # TODO: use list style from list node - requires a stack, though ...
                listStyle = ('itemizedlist', 'level', str(self.listLevel))
                newList = self.cursor.createList(self.formatManager.getFormat(listStyle).getListFormat())
            for n in node.children:
                self.addNode(n)

        elif type(node) == List:
            self.listLevel += 1
            for n in node.children:
                self.addNode(n)
            self.listLevel -= 1

        elif type(node) is ImageFragment:
            imageObject = ImageObject()
            imagePath = os.path.join(self.contentPath, node.image)
            imageObject.setName(imagePath)

            imageObjectFormat = QTextCharFormat()
            imageObjectFormat.setObjectType(QTextFormat.UserObject + 1)
            imageObjectFormat.setProperty(QTextFormat.UserProperty + 1, imageObject)
            self.cursor.insertText('\ufffc', imageObjectFormat);

        elif type(node) is MathFragment:
            mathFormula = MathFormulaObject()
            mathFormula.setFormula(node.text)
            mathFormula.image = node.image #  renderFormula()

            mathObjectFormat = QTextCharFormat()
            mathObjectFormat.setObjectType(QTextFormat.UserObject + 1)
            mathObjectFormat.setVerticalAlignment(QTextCharFormat.AlignMiddle)
            mathObjectFormat.setProperty(QTextFormat.UserProperty + 1, mathFormula)
            self.cursor.insertText('\ufffc', mathObjectFormat);
        elif type(node) is TextFragment:
            text = node.text.replace('\n', '\u2028')
            if node.href is not None:
                fmt = self.formatManager.getFormat(('link', None, None))   # TODO!
                charFmt = fmt.getCharFormat()
                charFmt.setAnchorHref(node.href)
                self.cursor.insertText(text, charFmt)
            else:
                # "The block char format is the format used when inserting text at the beginning of an empty block.
                # Hence, the block char format is only useful for the first fragment -
                # once a fragment is inserted with a different style, and afterwards
                # another fragment is inserted with no specific style, we need to reset
                # the char format to the block's char format explicitly!
    
                if node.style is not None:
                    fmt = self.formatManager.getFormat(node.style)
                else:
                    fmt = self.paraFormat

                self.cursor.insertText(text, fmt.getCharFormat())
Ejemplo n.º 33
0
def apply_smart_comment(editor, opening='/*', closing='*/', line_comment=None):
    doc = editor.document()
    c = QTextCursor(editor.textCursor())
    c.clearSelection()
    before_opening = doc.find(opening, c, doc.FindBackward | doc.FindCaseSensitively)
    before_closing = doc.find(closing, c, doc.FindBackward | doc.FindCaseSensitively)
    after_opening = doc.find(opening, c, doc.FindCaseSensitively)
    after_closing = doc.find(closing, c, doc.FindCaseSensitively)
    in_block_comment = (not before_opening.isNull() and (before_closing.isNull() or before_opening.position() >= before_closing.position())) and \
        (not after_closing.isNull() and (after_opening.isNull() or after_closing.position() <= after_opening.position()))
    if in_block_comment:
        before_opening.removeSelectedText(), after_closing.removeSelectedText()
        return
    c = QTextCursor(editor.textCursor())
    left, right = min(c.position(), c.anchor()), max(c.position(), c.anchor())
    c.beginEditBlock()
    c.setPosition(right), c.insertText(closing)
    c.setPosition(left), c.insertText(opening)
    c.endEditBlock()
Ejemplo n.º 34
0
 def goto_loc(self, loc, operation=QTextCursor.Right, mode=QTextCursor.KeepAnchor, n=0):
     cursor = QTextCursor(self.preview.document())
     cursor.setPosition(loc)
     if n:
         cursor.movePosition(operation, mode, n)
     self.preview.setTextCursor(cursor)