Skip to content

PlainTextEditMixin

Base classes

Name Children Inherits
AbstractScrollAreaMixin
prettyqt.widgets.abstractscrollarea

Subclasses

Class Module Description
PlainTextEdit prettyqt.widgets.plaintextedit

â‹” Inheritance diagram

graph TD
  1473296321280["widgets.PlainTextEditMixin"]
  1473293679456["widgets.AbstractScrollAreaMixin"]
  1473293662864["widgets.FrameMixin"]
  1473293688240["widgets.WidgetMixin"]
  1473299815024["core.ObjectMixin"]
  140713234304496["builtins.object"]
  1473245548480["gui.PaintDeviceMixin"]
  1473293679456 --> 1473296321280
  1473293662864 --> 1473293679456
  1473293688240 --> 1473293662864
  1473299815024 --> 1473293688240
  140713234304496 --> 1473299815024
  1473245548480 --> 1473293688240
  140713234304496 --> 1473245548480

🛈 DocStrings

Bases: AbstractScrollAreaMixin

Source code in prettyqt\widgets\plaintextedit.py
class PlainTextEditMixin(widgets.AbstractScrollAreaMixin):
    value_changed = core.Signal(str)

    def __init__(self, text: str = "", **kwargs):
        super().__init__(**kwargs)
        self._allow_wheel_zoom = False
        self._hl = None
        self._current_line_color = gui.Color(0, 0, 0, 0)
        self._validation_color = gui.Color("orange")
        self.selecter = texteditselecter.TextEditSelecter(self)
        self.validator: gui.QValidator | None = None
        self.textChanged.connect(self._on_value_change)
        doc = gui.TextDocument(self)
        layout = widgets.PlainTextDocumentLayout(doc)
        doc.setDocumentLayout(layout)
        self.setDocument(doc)
        self.set_text(text)

    def __add__(self, other: str):
        self.append_text(other)
        return self

    def wheelEvent(self, event):
        """Handle wheel event for zooming."""
        if not self._allow_wheel_zoom:
            return super().wheelEvent(event)
        if event.modifiers() & constants.CTRL_MOD:
            self.zoomIn() if event.angleDelta().y() > 0 else self.zoomOut()
            event.accept()
        else:
            super().wheelEvent(event)

    def _get_map(self):
        maps = super()._get_map()
        maps |= {
            "lineWrapMode": LINE_WRAP_MODE,
            "wordWrapMode": gui.textoption.WORD_WRAP_MODE,
        }
        return maps

    def allow_wheel_zoom(self, do_zoom: bool = True):
        self._allow_wheel_zoom = do_zoom

    def append_text(
        self,
        text: str,
        newline: bool = True,
        ensure_visible: Literal["always", "when_bottom", "never"] = "always",
    ):
        scrollbar = self.verticalScrollBar()
        at_bottom = scrollbar.value() >= (scrollbar.maximum() - 4)
        prev_val = scrollbar.value()
        if newline:
            self.appendPlainText(text)
        else:
            self.selecter.move_cursor("end")
            self.insertPlainText(text)
            self.selecter.move_cursor("end")
        match ensure_visible:
            case "always":
                self.ensureCursorVisible()
            case "when_bottom":
                if at_bottom:
                    self.ensureCursorVisible()
            case "never":
                scrollbar.setValue(prev_val)

    def set_text(self, text: str):
        self.setPlainText(text)

    def set_syntaxhighlighter(
        self, syntax: str | gui.QSyntaxHighlighter, style: str | None = None
    ):
        if isinstance(syntax, gui.QSyntaxHighlighter):
            self._hl = syntax
        else:
            self._hl = syntaxhighlighters.PygmentsHighlighter(
                self.document(), syntax, style
            )

    def text(self) -> str:
        return self.toPlainText()

    def set_read_only(self, value: bool = True):
        """Make the PlainTextEdit read-only.

        Args:
            value: True, for read-only, otherwise False
        """
        self.setReadOnly(value)

    def show_whitespace_and_tabs(self, show: bool):
        """Set show white spaces flag."""
        doc = self.document()
        options = doc.defaultTextOption()
        flag = gui.QTextOption.Flag.ShowTabsAndSpaces
        if show:
            options.setFlags(options.flags() | flag)  # type: ignore
        else:
            options.setFlags(options.flags() & ~flag)  # type: ignore
        doc.setDefaultTextOption(options)

    def paintEvent(self, event: gui.QPaintEvent):
        if self._current_line_color:
            with gui.Painter(self.viewport()) as painter:
                cursor_rect = self.cursorRect()
                r = core.QRect(0, cursor_rect.top(), self.width(), cursor_rect.height())
                painter.set_pen(None)
                painter.setBrush(gui.Color(self._current_line_color))
                painter.drawRect(r)
        super().paintEvent(event)

    def set_word_wrap_mode(
        self, mode: gui.textoption.WordWrapModeStr | gui.QTextOption.WrapMode
    ):
        """Set word wrap mode.

        Args:
            mode: word wrap mode to use
        """
        self.setWordWrapMode(gui.textoption.WORD_WRAP_MODE.get_enum_value(mode))

    def get_word_wrap_mode(self) -> gui.textoption.WordWrapModeStr:
        """Get the current word wrap mode.

        Returns:
            Word wrap mode
        """
        return gui.textoption.WORD_WRAP_MODE.inverse[self.wordWrapMode()]

    def set_line_wrap_mode(
        self, mode: LineWrapModeStr | widgets.QPlainTextEdit.LineWrapMode
    ):
        """Set line wrap mode.

        Args:
            mode: line wrap mode to use
        """
        self.setLineWrapMode(LINE_WRAP_MODE.get_enum_value(mode))

    def get_line_wrap_mode(self) -> LineWrapModeStr:
        """Get the current wrap mode.

        Returns:
            Wrap mode
        """
        return LINE_WRAP_MODE.inverse[self.lineWrapMode()]

    def _on_value_change(self):
        self.value_changed.emit(self.text())
        if self.validator is not None:
            self._update_background()

    def _update_background(self):
        color = None if self.is_valid() else self._validation_color
        self.set_background_color(color)

    def set_validation_color(self, color: datatypes.ColorType):
        self._validation_color = colors.get_color(color).as_qt()

    def get_validation_color(self) -> gui.QColor:
        return self._validation_color

    def set_validator(
        self, validator: gui.QValidator | widgets.lineedit.ValidatorStr | None, **kwargs
    ) -> gui.QValidator:
        if isinstance(validator, str):
            ValidatorClass = classhelpers.get_class_for_id(gui.ValidatorMixin, validator)
            validator = ValidatorClass(**kwargs)
        self.validator = validator
        self._update_background()
        return validator

    def set_regex_validator(self, regex: str, flags=0) -> gui.RegularExpressionValidator:
        validator = gui.RegularExpressionValidator(self)
        validator.set_regex(regex, flags)
        self.set_validator(validator)
        return validator

    def is_valid(self) -> bool:
        if self.validator is None:
            return True
        val = self.validator.validate(self.text(), 0)
        return val[0] == self.validator.State.Acceptable

    def set_value(self, value: str):
        self.setPlainText(value)

    def get_value(self) -> str:
        return self.text()

    def set_current_line_color(self, color: datatypes.ColorType):
        if self._current_line_color is None:
            self.cursorPositionChanged.connect(self.selecter._update_on_block_change)
        if color is None:
            self.cursorPositionChanged.disconnect(self.selecter._update_on_block_change)
        self._current_line_color = colors.get_color(color) if color else None

    def get_current_line_color(self) -> gui.Color:
        return self._current_line_color

    current_line_color = core.Property(
        gui.QColor,
        get_current_line_color,
        set_current_line_color,
        doc="Color to use for current line highlighting",
    )

    def get_visible_line_span(self) -> tuple[int, int]:
        block = self.firstVisibleBlock()
        start = block.blockNumber()
        page_step = self.v_scrollbar.pageStep()
        end = min(start + page_step, self.blockCount())
        return (start, end)

    def get_pixel_height(self, exact: bool = True) -> int:
        """Returns the pixel height of the text area."""
        widget_margins = self.contentsMargins()
        doc_height = self.document().get_pixel_height(exact=exact)
        return widget_margins.top() + doc_height + widget_margins.bottom()

    validation_color = core.Property(
        gui.QColor,
        get_validation_color,
        set_validation_color,
        doc="Color to use for invalid text",
    )

get_line_wrap_mode() -> LineWrapModeStr

Get the current wrap mode.

Source code in prettyqt\widgets\plaintextedit.py
def get_line_wrap_mode(self) -> LineWrapModeStr:
    """Get the current wrap mode.

    Returns:
        Wrap mode
    """
    return LINE_WRAP_MODE.inverse[self.lineWrapMode()]

get_pixel_height(exact: bool = True) -> int

Returns the pixel height of the text area.

Source code in prettyqt\widgets\plaintextedit.py
def get_pixel_height(self, exact: bool = True) -> int:
    """Returns the pixel height of the text area."""
    widget_margins = self.contentsMargins()
    doc_height = self.document().get_pixel_height(exact=exact)
    return widget_margins.top() + doc_height + widget_margins.bottom()

get_word_wrap_mode() -> gui.textoption.WordWrapModeStr

Get the current word wrap mode.

Source code in prettyqt\widgets\plaintextedit.py
def get_word_wrap_mode(self) -> gui.textoption.WordWrapModeStr:
    """Get the current word wrap mode.

    Returns:
        Word wrap mode
    """
    return gui.textoption.WORD_WRAP_MODE.inverse[self.wordWrapMode()]

set_line_wrap_mode(mode: LineWrapModeStr | widgets.QPlainTextEdit.LineWrapMode)

Set line wrap mode.

Parameters:

Name Type Description Default
mode LineWrapModeStr | LineWrapMode

line wrap mode to use

required
Source code in prettyqt\widgets\plaintextedit.py
def set_line_wrap_mode(
    self, mode: LineWrapModeStr | widgets.QPlainTextEdit.LineWrapMode
):
    """Set line wrap mode.

    Args:
        mode: line wrap mode to use
    """
    self.setLineWrapMode(LINE_WRAP_MODE.get_enum_value(mode))

set_read_only(value: bool = True)

Make the PlainTextEdit read-only.

Parameters:

Name Type Description Default
value bool

True, for read-only, otherwise False

True
Source code in prettyqt\widgets\plaintextedit.py
def set_read_only(self, value: bool = True):
    """Make the PlainTextEdit read-only.

    Args:
        value: True, for read-only, otherwise False
    """
    self.setReadOnly(value)

set_word_wrap_mode(mode: gui.textoption.WordWrapModeStr | gui.QTextOption.WrapMode)

Set word wrap mode.

Parameters:

Name Type Description Default
mode WordWrapModeStr | WrapMode

word wrap mode to use

required
Source code in prettyqt\widgets\plaintextedit.py
def set_word_wrap_mode(
    self, mode: gui.textoption.WordWrapModeStr | gui.QTextOption.WrapMode
):
    """Set word wrap mode.

    Args:
        mode: word wrap mode to use
    """
    self.setWordWrapMode(gui.textoption.WORD_WRAP_MODE.get_enum_value(mode))

show_whitespace_and_tabs(show: bool)

Set show white spaces flag.

Source code in prettyqt\widgets\plaintextedit.py
def show_whitespace_and_tabs(self, show: bool):
    """Set show white spaces flag."""
    doc = self.document()
    options = doc.defaultTextOption()
    flag = gui.QTextOption.Flag.ShowTabsAndSpaces
    if show:
        options.setFlags(options.flags() | flag)  # type: ignore
    else:
        options.setFlags(options.flags() & ~flag)  # type: ignore
    doc.setDefaultTextOption(options)

wheelEvent(event)

Handle wheel event for zooming.

Source code in prettyqt\widgets\plaintextedit.py
def wheelEvent(self, event):
    """Handle wheel event for zooming."""
    if not self._allow_wheel_zoom:
        return super().wheelEvent(event)
    if event.modifiers() & constants.CTRL_MOD:
        self.zoomIn() if event.angleDelta().y() > 0 else self.zoomOut()
        event.accept()
    else:
        super().wheelEvent(event)