from PyQt6.QtWidgets import QTextEdit from PyQt6.QtCore import QTimer, QDir, QUrl, QVariant, Qt from PyQt6.QtGui import QTextCharFormat, QFont, QTextCursor, QTextImageFormat, QImage, QTextDocument, QTextBlockFormat from .header_formatter import HeaderFormatter from .text_style_formatter import TextStyleFormatter class TextFormatter: def __init__(self, text_edit: QTextEdit): self.text_edit = text_edit self.timer = QTimer() self.timer.setSingleShot(True) self.timer.timeout.connect(self.process_text_changes) self.text_edit.textChanged.connect(self.delay_text) self.header_formatter = HeaderFormatter() self.text_style_formatter = TextStyleFormatter() def delay_text(self): self.timer.start(500) def process_text_changes(self): cursor = self.text_edit.textCursor() cursor.beginEditBlock() cursor.select(QTextCursor.SelectionType.Document) cursor.setCharFormat(QTextCharFormat()) self.header_formatter.process_headers(self.text_edit) self.text_style_formatter.apply_text_formatting(cursor, self.text_edit.toPlainText()) self.process_markdown_images(cursor, self.text_edit.toPlainText()) cursor.endEditBlock() def toggle_special_symbols(self, symbol_start, symbol_end=None): cursor = self.text_edit.textCursor() if cursor.hasSelection(): selected_text = cursor.selectedText() full_text = self.text_edit.toPlainText() start = cursor.selectionStart() end = cursor.selectionEnd() corrected_text, new_start, new_end = self._toggle_special_symbols_in_selection(full_text, start, end, symbol_start, symbol_end) self.text_edit.setPlainText(corrected_text) cursor.setPosition(new_start) cursor.setPosition(new_end, QTextCursor.MoveMode.KeepAnchor) self.text_edit.setTextCursor(cursor) else: cursor.select(QTextCursor.SelectionType.WordUnderCursor) word = cursor.selectedText() full_text = self.text_edit.toPlainText() start = cursor.selectionStart() end = cursor.selectionEnd() corrected_text, new_start, new_end = self._toggle_special_symbols_in_selection(full_text, start, end, symbol_start, symbol_end) self.text_edit.setPlainText(corrected_text) cursor.setPosition(new_start) cursor.setPosition(new_end, QTextCursor.MoveMode.KeepAnchor) self.text_edit.setTextCursor(cursor) def _toggle_special_symbols_in_selection(self, text, start, end, symbol_start, symbol_end=None): if symbol_end is None: symbol_end = symbol_start if text[start - len(symbol_start):start] == symbol_start and text[end:end + len(symbol_end)] == symbol_end: corrected_text = text[:start - len(symbol_start)] + text[start:end] + text[end + len(symbol_end):] new_start = start - len(symbol_start) new_end = end - len(symbol_start) return corrected_text, new_start, new_end else: corrected_text = text[:start] + symbol_start + text[start:end] + symbol_end + text[end:] new_start = start + len(symbol_start) new_end = end + len(symbol_end) return corrected_text, new_start, new_end