def show(self): super(EncodingPanel, self).show() self.editor.selectAll() self._deco = TextDecoration(self.editor.textCursor()) self._deco.set_background(QtCore.Qt.red) self._deco.set_foreground(QtCore.Qt.black) self.editor.decorations.append(self._deco) cursor = self.editor.textCursor() cursor.clearSelection() cursor.setPosition(0) self.editor.setTextCursor(cursor) self.editor.setReadOnly(True)
def _create_decoration(self, selection_start, selection_end): """ Creates the text occurences decoration """ deco = TextDecoration(self.editor.document(), selection_start, selection_end) deco.set_background(QtGui.QBrush(self.background)) deco.set_outline(self._outline) deco.set_foreground(QtCore.Qt.black) deco.draw_order = 1 return deco
def refresh(self): """ Updates the current line decoration """ if self.enabled and self.line: self._clear_deco() brush = QtGui.QBrush(self._color) self._decoration = TextDecoration(self.editor.textCursor(), start_line=self.line) self._decoration.set_background(brush) self._decoration.set_full_width() self._decoration.draw_order = 255 self.editor.decorations.append(self._decoration)
def refresh(self): """ Updates the current line decoration """ if self.enabled: self._clear_deco() if self._color: color = self._color else: color = drift_color(self.editor.background, 110) brush = QtGui.QBrush(color) self._decoration = TextDecoration(self.editor.textCursor()) self._decoration.set_background(brush) self._decoration.set_full_width() self.editor.decorations.append(self._decoration)
def _add_decoration(self, cursor): """ Adds a decoration for the word under ``cursor``. """ if self._deco is None: if cursor.selectedText(): self._deco = TextDecoration(cursor) if self.editor.background.lightness() < 128: self._deco.set_foreground(QtGui.QColor('#0681e0')) else: self._deco.set_foreground(QtCore.Qt.blue) self._deco.set_as_underlined() self.editor.decorations.append(self._deco) self.editor.set_mouse_cursor(QtCore.Qt.PointingHandCursor) else: self.editor.set_mouse_cursor(QtCore.Qt.IBeamCursor)
def refresh(self): """ Updates the current line decoration """ if self.enabled and self.line: self._clear_deco() brush = QtGui.QBrush(self._color) self._decoration = TextDecoration( self.editor.textCursor(), start_line=self.line) self._decoration.set_background(brush) self._decoration.set_full_width() self._decoration.draw_order = 255 self.editor.decorations.append(self._decoration)
def _add_batch(self): if self.editor is None: return for i in range(10): if not len(self._pending_msg): # all pending message added self._finished = True _logger(self.__class__).log(5, 'finished') self.editor.repaint() return False message = self._pending_msg.pop(0) if message.line >= 0: try: usd = message.block.userData() except AttributeError: message.block = self.editor.document().findBlockByNumber( message.line) usd = message.block.userData() if usd is None: usd = TextBlockUserData() message.block.setUserData(usd) # check if the same message already exists if message in usd.messages: continue self._messages.append(message) usd.messages.append(message) tooltip = None if self._show_tooltip: tooltip = message.description message.decoration = TextDecoration(self.editor.textCursor(), start_line=message.line, tooltip=tooltip, draw_order=3) message.decoration.set_full_width() message.decoration.set_as_error( color=QtGui.QColor(message.color)) self.editor.decorations.append(message.decoration) QtCore.QTimer.singleShot(1, self._add_batch) self.editor.repaint() return True
class EncodingPanel(Panel): """ Displays a warning when an encoding error occured and let you reload. This panel display a warning in case encoding/decoding error and give the user the possibility to try out another encoding, to edit any way or to close the editor. The panel is automatically shown by :class:`pyqode.core.managers.FileManager` in case of error so that you don't have to worry about encoding issues. The only think you might do is to provide to your user a way to specify the default encoding, i.e. the one that is tried before showing this panel. The panel is a simple widget with a label describing the error, an encoding menu and 3 buttons: ``Retry``, ``Edit`` anyway and ``Cancel``. It is strongly inspired by the GEdit encoding panel. You can change the background color and the label foreground color by setting up the ``color`` and ``foreground`` properties. It's up to the client code to handle cancel requests. To do that simply connect ``cancel_requested`` signal to remove the editor from your application. """ #: Signal emitted when the user pressed on cancel. It is up to the client #: code to handle this event. cancel_requested = QtCore.Signal(object) _description = ('<html><head/><body><p><span style=" font-weight:600;">%s' '</span></p><p><span style=" font-size:9pt;">' 'The file you opened has some invalid characters. ' 'If you continue editing this file you could corrupt this ' 'document. You can also choose another character encoding ' 'and try again.</span></p></body></html>') @property def color(self): """ Returns the panel color. """ return self._color @color.setter def color(self, value): self._color = value self._refresh_stylesheet() if self.editor: # propagate changes to every clone for clone in self.editor.clones: try: clone.modes.get(self.__class__).color = value except KeyError: # this should never happen since we're working with clones pass @property def foreground(self): return self._foreground @foreground.setter def foreground(self, value): self._foreground = value self._refresh_stylesheet() # propagate changes to every clone if self.editor: for clone in self.editor.clones: try: clone.modes.get(self.__class__).foreground = value except KeyError: # this should never happen since we're working with clones pass def _refresh_stylesheet(self): try: self._lbl_stylesheet = ( 'color: %s;background: %s' % (self._foreground.name(), self._color.name())) for lbl in self._labels: lbl.setStyleSheet(self._lbl_stylesheet) except AttributeError: pass def __init__(self, add_context_menu=True): super(EncodingPanel, self).__init__(dynamic=True) # leave it here otherwise you will have circular import errors from pyqode.core._forms.pnl_encoding_ui import Ui_Form self.ui = Ui_Form() self.ui.setupUi(self) self.__add_ctx_mnu = add_context_menu self._labels = [self.ui.label, self.ui.lblDescription] self._color = None self.color = QtGui.QColor('#8AADD4') self._foreground = None self.foreground = QtGui.QColor('#FFFFFF') self._deco = None self.ui.pushButtonRetry.clicked.connect(self._reload) self.ui.pushButtonEdit.clicked.connect(self._edit_anyway) self.ui.pushButtonCancel.clicked.connect(self.cancel) self.hide() def enable_caret_line(self, value=True): try: from pyqode.core.modes import CaretLineHighlighterMode mode = self.editor.modes.get(CaretLineHighlighterMode) except KeyError: pass else: mode.enabled = value def on_open_failed(self, path, encoding): self.enable_caret_line(False) self.ui.comboBoxEncodings.current_encoding = encoding self.ui.lblDescription.setText( self._description % (_('There was a problem opening the file %r') % path)) # load text as binary and mark it as red, user might make use the # binary to recognize the original encoding try: with open(path, 'rb') as file: content = str(file.read(16)) except OSError: content = '' # set plain text self.editor.setPlainText(content, self.editor.file.get_mimetype(path), self.editor.file.encoding) self.editor.setDocumentTitle(self.editor.file.name) self.editor.setWindowTitle(self.editor.file.name) # Delay because the editor might not have been shown yet QtCore.QTimer.singleShot(1, self.show) def on_save_failed(self, path, encoding): pass def show(self): super(EncodingPanel, self).show() self.editor.selectAll() self._deco = TextDecoration(self.editor.textCursor()) self._deco.set_background(QtCore.Qt.red) self._deco.set_foreground(QtCore.Qt.black) self.editor.decorations.append(self._deco) cursor = self.editor.textCursor() cursor.clearSelection() cursor.setPosition(0) self.editor.setTextCursor(cursor) self.editor.setReadOnly(True) def paintEvent(self, event): """ Fills the panel background. """ super(EncodingPanel, self).paintEvent(event) if self.isVisible(): # fill background painter = QtGui.QPainter(self) self._background_brush = QtGui.QBrush(self._color) painter.fillRect(event.rect(), self._background_brush) def on_install(self, editor): super(EncodingPanel, self).on_install(editor) if self.__add_ctx_mnu: # add context menu from pyqode.core.widgets import EncodingsContextMenu EncodingsContextMenu(parent=editor) def _reload(self): self.hide() self._rm_deco() self.editor.setReadOnly(False) self.enable_caret_line(True) self.editor.file.reload(self.ui.comboBoxEncodings.current_encoding) def _edit_anyway(self): self._rm_deco() self.editor.setReadOnly(False) self.enable_caret_line(True) self.hide() def _rm_deco(self): if self._deco: self.editor.decorations.remove(self._deco) self._deco = None def cancel(self): if self.sender(): self.editor.clear() self.close_panel() def close_panel(self): self._rm_deco() self.enable_caret_line(True) self.cancel_requested.emit(self.editor) self.hide() def clone_settings(self, original): self.color = original.color self.foreground = original.foreground
class WordClickMode(Mode, QtCore.QObject): """ Adds support for word click events. It will highlight the click-able word when the user press control and move the mouse over a word. Detecting whether a word is click-able is the responsability of the subclasses. You must override ``_check_word_cursor`` and call ``_select_word_cursor`` if this is a click-able word (this process might be asynchrone) otherwise _clear_selection. :attr:`pyqode.core.modes.WordClickMode.word_clicked` is emitted when the word is clicked by the user (while keeping control pressed). """ #: Signal emitted when a word is clicked. The parameter is a #: QTextCursor with the clicked word set as the selected text. word_clicked = QtCore.Signal(QtGui.QTextCursor) def __init__(self): QtCore.QObject.__init__(self) Mode.__init__(self) self._previous_cursor_start = -1 self._previous_cursor_end = -1 self._deco = None self._cursor = None self._timer = DelayJobRunner(delay=200) def on_state_changed(self, state): if state: self.editor.mouse_moved.connect(self._on_mouse_moved) self.editor.mouse_pressed.connect(self._on_mouse_pressed) self.editor.key_released.connect(self._on_key_released) self.editor.mouse_double_clicked.connect( self._on_mouse_double_clicked) else: self.editor.mouse_moved.disconnect(self._on_mouse_moved) self.editor.mouse_pressed.disconnect(self._on_mouse_pressed) self.editor.key_released.disconnect(self._on_key_released) self.editor.mouse_double_clicked.disconnect( self._on_mouse_double_clicked) def _on_mouse_double_clicked(self): self._timer.cancel_requests() def _on_key_released(self, event): if event.key() == QtCore.Qt.Key_Control: self._clear_selection() self._cursor = None def _select_word_cursor(self): """ Selects the word under the mouse cursor. """ cursor = TextHelper(self.editor).word_under_mouse_cursor() if (self._previous_cursor_start != cursor.selectionStart() and self._previous_cursor_end != cursor.selectionEnd()): self._remove_decoration() self._add_decoration(cursor) self._previous_cursor_start = cursor.selectionStart() self._previous_cursor_end = cursor.selectionEnd() def _clear_selection(self): try: self._remove_decoration() except ValueError: pass self.editor.set_mouse_cursor(QtCore.Qt.IBeamCursor) self._previous_cursor_start = -1 self._previous_cursor_end = -1 def _on_mouse_moved(self, event): """ mouse moved callback """ if event.modifiers() & QtCore.Qt.ControlModifier: cursor = TextHelper(self.editor).word_under_mouse_cursor() if (not self._cursor or cursor.position() != self._cursor.position()): self._check_word_cursor(cursor) self._cursor = cursor else: self._cursor = None self._clear_selection() def _check_word_cursor(self, cursor): pass def _on_mouse_pressed(self, event): """ mouse pressed callback """ if event.button() == 1 and self._deco: cursor = TextHelper(self.editor).word_under_mouse_cursor() if cursor and cursor.selectedText(): self._timer.request_job(self.word_clicked.emit, cursor) def _add_decoration(self, cursor): """ Adds a decoration for the word under ``cursor``. """ if self._deco is None: if cursor.selectedText(): self._deco = TextDecoration(cursor) if self.editor.background.lightness() < 128: self._deco.set_foreground(QtGui.QColor('#0681e0')) else: self._deco.set_foreground(QtCore.Qt.blue) self._deco.set_as_underlined() self.editor.decorations.append(self._deco) self.editor.set_mouse_cursor(QtCore.Qt.PointingHandCursor) else: self.editor.set_mouse_cursor(QtCore.Qt.IBeamCursor) def _remove_decoration(self): """ Removes the word under cursor's decoration """ if self._deco is not None: self.editor.decorations.remove(self._deco) self._deco = None
def _create_decoration(self, pos, match=True): cursor = self.editor.textCursor() cursor.setPosition(pos) cursor.movePosition(cursor.NextCharacter, cursor.KeepAnchor) deco = TextDecoration(cursor, draw_order=10) deco.line = cursor.blockNumber() deco.column = cursor.columnNumber() deco.character = cursor.selectedText() deco.match = match if match: deco.set_foreground(self._match_foreground) deco.set_background(self._match_background) else: deco.set_foreground(self._unmatch_foreground) deco.set_background(self._unmatch_background) self._decorations.append(deco) self.editor.decorations.append(deco) return cursor
class EncodingPanel(Panel): """ Displays a warning when an encoding error occured and let you reload. This panel display a warning in case encoding/decoding error and give the user the possibility to try out another encoding, to edit any way or to close the editor. The panel is automatically shown by :class:`pyqode.core.managers.FileManager` in case of error so that you don't have to worry about encoding issues. The only think you might do is to provide to your user a way to specify the default encoding, i.e. the one that is tried before showing this panel. The panel is a simple widget with a label describing the error, an encoding menu and 3 buttons: ``Retry``, ``Edit`` anyway and ``Cancel``. It is strongly inspired by the GEdit encoding panel. You can change the background color and the label foreground color by setting up the ``color`` and ``foreground`` properties. It's up to the client code to handle cancel requests. To do that simply connect ``cancel_requested`` signal to remove the editor from your application. """ #: Signal emitted when the user pressed on cancel. It is up to the client #: code to handle this event. cancel_requested = QtCore.Signal(object) _description = ('<html><head/><body><p><span style=" font-weight:600;">%s' '</span></p><p><span style=" font-size:9pt;">' 'The file you opened has some invalid characters. ' 'If you continue editing this file you could corrupt this ' 'document. You can also choose another character encoding ' 'and try again.</span></p></body></html>') @property def color(self): """ Returns the panel color. """ return self._color @color.setter def color(self, value): self._color = value self._refresh_stylesheet() if self.editor: # propagate changes to every clone for clone in self.editor.clones: try: clone.modes.get(self.__class__).color = value except KeyError: # this should never happen since we're working with clones pass @property def foreground(self): return self._foreground @foreground.setter def foreground(self, value): self._foreground = value self._refresh_stylesheet() # propagate changes to every clone if self.editor: for clone in self.editor.clones: try: clone.modes.get(self.__class__).foreground = value except KeyError: # this should never happen since we're working with clones pass def _refresh_stylesheet(self): try: self._lbl_stylesheet = ('color: %s;background: %s' % (self._foreground.name(), self._color.name())) for lbl in self._labels: lbl.setStyleSheet(self._lbl_stylesheet) except AttributeError: pass def __init__(self, add_context_menu=True): super(EncodingPanel, self).__init__(dynamic=True) # leave it here otherwise you will have circular import errors from pyqode.core._forms.pnl_encoding_ui import Ui_Form self.ui = Ui_Form() self.ui.setupUi(self) self.__add_ctx_mnu = add_context_menu self._labels = [self.ui.label, self.ui.lblDescription] self._color = None self.color = QtGui.QColor('#8AADD4') self._foreground = None self.foreground = QtGui.QColor('#FFFFFF') self._deco = None self.ui.pushButtonRetry.clicked.connect(self._reload) self.ui.pushButtonEdit.clicked.connect(self._edit_anyway) self.ui.pushButtonCancel.clicked.connect(self.cancel) self.hide() def enable_caret_line(self, value=True): try: from pyqode.core.modes import CaretLineHighlighterMode mode = self.editor.modes.get(CaretLineHighlighterMode) except KeyError: pass else: mode.enabled = value def on_open_failed(self, path, encoding): self.enable_caret_line(False) self.ui.comboBoxEncodings.current_encoding = encoding self.ui.lblDescription.setText( self._description % (_('There was a problem opening the file %r') % path)) # load text as binary and mark it as red, user might make use the # binary to recognize the original encoding with open(path, 'rb') as file: content = str(file.read(16)) # set plain text self.editor.setPlainText( content, self.editor.file.get_mimetype(path), self.editor.file.encoding) self.editor.setDocumentTitle(self.editor.file.name) self.editor.setWindowTitle(self.editor.file.name) # Delay because the editor might not have been shown yet QtCore.QTimer.singleShot(1, self.show) def show(self): super(EncodingPanel, self).show() self.editor.selectAll() self._deco = TextDecoration(self.editor.textCursor()) self._deco.set_background(QtCore.Qt.red) self._deco.set_foreground(QtCore.Qt.black) self.editor.decorations.append(self._deco) cursor = self.editor.textCursor() cursor.clearSelection() cursor.setPosition(0) self.editor.setTextCursor(cursor) self.editor.setReadOnly(True) def paintEvent(self, event): """ Fills the panel background. """ super(EncodingPanel, self).paintEvent(event) if self.isVisible(): # fill background painter = QtGui.QPainter(self) self._background_brush = QtGui.QBrush(self._color) painter.fillRect(event.rect(), self._background_brush) def on_install(self, editor): super(EncodingPanel, self).on_install(editor) if self.__add_ctx_mnu: # add context menu from pyqode.core.widgets import EncodingsContextMenu EncodingsContextMenu(parent=editor) def _reload(self): self.hide() self._rm_deco() self.editor.setReadOnly(False) self.enable_caret_line(True) self.editor.file.reload(self.ui.comboBoxEncodings.current_encoding) def _edit_anyway(self): self._rm_deco() self.editor.setReadOnly(False) self.enable_caret_line(True) self.hide() def _rm_deco(self): if self._deco: self.editor.decorations.remove(self._deco) self._deco = None def cancel(self): if self.sender(): self.editor.clear() self._rm_deco() self.enable_caret_line(True) self.cancel_requested.emit(self.editor) self.hide() def clone_settings(self, original): self.color = original.color self.foreground = original.foreground
class WordClickMode(Mode, QtCore.QObject): """ Adds support for word click events. It will highlight the click-able word when the user press control and move the mouse over a word. Detecting whether a word is click-able is the responsability of the subclasses. You must override ``_check_word_cursor`` and call ``_select_word_cursor`` if this is a click-able word (this process might be asynchrone) otherwise _clear_selection. :attr:`pyqode.core.modes.WordClickMode.word_clicked` is emitted when the word is clicked by the user (while keeping control pressed). """ #: Signal emitted when a word is clicked. The parameter is a #: QTextCursor with the clicked word set as the selected text. word_clicked = QtCore.Signal(QtGui.QTextCursor) def __init__(self): QtCore.QObject.__init__(self) Mode.__init__(self) self._previous_cursor_start = -1 self._previous_cursor_end = -1 self._deco = None self._cursor = None self._timer = DelayJobRunner(delay=200) def on_state_changed(self, state): if state: self.editor.mouse_moved.connect(self._on_mouse_moved) self.editor.mouse_released.connect(self._on_mouse_released) self.editor.key_released.connect(self._on_key_released) self.editor.mouse_double_clicked.connect( self._on_mouse_double_clicked) else: self.editor.mouse_moved.disconnect(self._on_mouse_moved) self.editor.mouse_released.disconnect(self._on_mouse_released) self.editor.key_released.disconnect(self._on_key_released) self.editor.mouse_double_clicked.disconnect( self._on_mouse_double_clicked) def _on_mouse_double_clicked(self): self._timer.cancel_requests() def _on_key_released(self, event): if event.key() == QtCore.Qt.Key_Control: self._clear_selection() self._cursor = None def _select_word_cursor(self): """ Selects the word under the mouse cursor. """ cursor = TextHelper(self.editor).word_under_mouse_cursor() if (self._previous_cursor_start != cursor.selectionStart() and self._previous_cursor_end != cursor.selectionEnd()): self._remove_decoration() self._add_decoration(cursor) self._previous_cursor_start = cursor.selectionStart() self._previous_cursor_end = cursor.selectionEnd() def _clear_selection(self): try: self._remove_decoration() except ValueError: pass self.editor.set_mouse_cursor(QtCore.Qt.IBeamCursor) self._previous_cursor_start = -1 self._previous_cursor_end = -1 def _on_mouse_moved(self, event): """ mouse moved callback """ if event.modifiers() & QtCore.Qt.ControlModifier: cursor = TextHelper(self.editor).word_under_mouse_cursor() if (not self._cursor or cursor.position() != self._cursor.position()): self._check_word_cursor(cursor) self._cursor = cursor else: self._cursor = None self._clear_selection() def _check_word_cursor(self, cursor): pass def _on_mouse_released(self, event): """ mouse pressed callback """ if event.button() == 1 and self._deco: cursor = TextHelper(self.editor).word_under_mouse_cursor() if cursor and cursor.selectedText(): self._timer.request_job( self.word_clicked.emit, cursor) def _add_decoration(self, cursor): """ Adds a decoration for the word under ``cursor``. """ if self._deco is None: if cursor.selectedText(): self._deco = TextDecoration(cursor) if self.editor.background.lightness() < 128: self._deco.set_foreground(QtGui.QColor('#0681e0')) else: self._deco.set_foreground(QtCore.Qt.blue) self._deco.set_as_underlined() self.editor.decorations.append(self._deco) self.editor.set_mouse_cursor(QtCore.Qt.PointingHandCursor) else: self.editor.set_mouse_cursor(QtCore.Qt.IBeamCursor) def _remove_decoration(self): """ Removes the word under cursor's decoration """ if self._deco is not None: self.editor.decorations.remove(self._deco) self._deco = None
class LineHighlighterMode(Mode): """ Highlights a line in the editor.""" @property def background(self): """ Background color of the highlighted line. """ return self._color @background.setter def background(self, value): self._color = value self.refresh() # propagate changes to every clone if self.editor: for clone in self.editor.clones: try: clone.modes.get(self.__class__).background = value except KeyError: # this should never happen since we're working with clones pass @property def line(self): if self._block: return self._block.blockNumber() else: return self._block @line.setter def line(self, value): if value is None: self._block = value self._clear_deco() else: self._block = self.editor.document().findBlockByNumber(value) self.refresh() def __init__(self): super(LineHighlighterMode, self).__init__() self._decoration = None self._block = None self._color = QtGui.QColor('#DD8080') def on_state_changed(self, state): if state: self.editor.new_text_set.connect(self.refresh) self.refresh() else: self.editor.new_text_set.disconnect(self.refresh) self._clear_deco() def on_install(self, editor): super(LineHighlighterMode, self).on_install(editor) self.refresh() def _clear_deco(self): """ Clear line decoration """ if self._decoration: self.editor.decorations.remove(self._decoration) self._decoration = None def refresh(self): """ Updates the current line decoration """ if self.enabled and self.line: self._clear_deco() brush = QtGui.QBrush(self._color) self._decoration = TextDecoration(self.editor.textCursor(), start_line=self.line) self._decoration.set_background(brush) self._decoration.set_full_width() self._decoration.draw_order = 255 self.editor.decorations.append(self._decoration) def clone_settings(self, original): self.background = original.background
class CaretLineHighlighterMode(Mode): """ Highlights the caret line """ @property def background(self): """ Background color of the caret line. Default is to use a color slightly darker/lighter than the background color. You can override the automatic color by setting up this property """ if self._color or not self.editor: return self._color else: return drift_color(self.editor.background, 110) @background.setter def background(self, value): self._color = value self.refresh() # propagate changes to every clone if self.editor: for clone in self.editor.clones: try: clone.modes.get(self.__class__).background = value except KeyError: # this should never happen since we're working with clones pass def __init__(self): super(CaretLineHighlighterMode, self).__init__() self._decoration = None self._pos = -1 self._color = None def on_state_changed(self, state): if state: self.editor.cursorPositionChanged.connect(self.refresh) self.editor.new_text_set.connect(self.refresh) self.refresh() else: self.editor.cursorPositionChanged.disconnect( self.refresh) self.editor.new_text_set.disconnect(self.refresh) self._clear_deco() def on_install(self, editor): super(CaretLineHighlighterMode, self).on_install(editor) self.refresh() def _clear_deco(self): """ Clear line decoration """ if self._decoration: self.editor.decorations.remove(self._decoration) self._decoration = None def refresh(self): """ Updates the current line decoration """ if self.enabled: self._clear_deco() if self._color: color = self._color else: color = drift_color(self.editor.background, 110) brush = QtGui.QBrush(color) self._decoration = TextDecoration(self.editor.textCursor()) self._decoration.set_background(brush) self._decoration.set_full_width() self.editor.decorations.append(self._decoration) def clone_settings(self, original): self.background = original.background
class LineHighlighterMode(Mode): """ Highlights a line in the editor.""" @property def background(self): """ Background color of the highlighted line. """ return self._color @background.setter def background(self, value): self._color = value self.refresh() # propagate changes to every clone if self.editor: for clone in self.editor.clones: try: clone.modes.get(self.__class__).background = value except KeyError: # this should never happen since we're working with clones pass @property def line(self): if self._block: return self._block.blockNumber() else: return self._block @line.setter def line(self, value): if value is None: self._block = value self._clear_deco() else: self._block = self.editor.document().findBlockByNumber(value) self.refresh() def __init__(self): super(LineHighlighterMode, self).__init__() self._decoration = None self._block = None self._color = QtGui.QColor('#DD8080') def on_state_changed(self, state): if state: self.editor.new_text_set.connect(self.refresh) self.refresh() else: self.editor.new_text_set.disconnect(self.refresh) self._clear_deco() def on_install(self, editor): super(LineHighlighterMode, self).on_install(editor) self.refresh() def _clear_deco(self): """ Clear line decoration """ if self._decoration: self.editor.decorations.remove(self._decoration) self._decoration = None def refresh(self): """ Updates the current line decoration """ if self.enabled and self.line: self._clear_deco() brush = QtGui.QBrush(self._color) self._decoration = TextDecoration( self.editor.textCursor(), start_line=self.line) self._decoration.set_background(brush) self._decoration.set_full_width() self._decoration.draw_order = 255 self.editor.decorations.append(self._decoration) def clone_settings(self, original): self.background = original.background