From 5032ffdfd446187f69b89b6d794aead0c0721da9 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 14 Jun 2025 16:44:51 +0200 Subject: [PATCH] Add current line highlight --- novelwriter/config.py | 22 +++++++++++++--------- novelwriter/gui/doceditor.py | 28 +++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/novelwriter/config.py b/novelwriter/config.py index 9258bcca..9f422b4d 100644 --- a/novelwriter/config.py +++ b/novelwriter/config.py @@ -77,15 +77,16 @@ class Config: "fmtSQuoteOpen", "focusWidth", "guiFont", "guiLocale", "hasEnchant", "hideFocusFooter", "hideHScroll", "hideVScroll", "highlightEmph", "hostName", "iconColDocs", "iconColTree", "iconTheme", "incNotesWCount", "isDebug", "kernelVer", "lastNotes", "lightTheme", - "mainPanePos", "mainWinSize", "memInfo", "narratorBreak", "narratorDialog", "nativeFont", - "osDarwin", "osLinux", "osType", "osUnknown", "osWindows", "outlinePanePos", - "prefsWinSize", "scrollPastEnd", "searchCase", "searchLoop", "searchMatchCap", - "searchNextFile", "searchProjCase", "searchProjRegEx", "searchProjWord", "searchRegEx", - "searchWord", "showEditToolBar", "showFullPath", "showLineEndings", "showMultiSpaces", - "showSessionTime", "showTabsNSpaces", "showViewerPanel", "spellLanguage", "stopWhenIdle", - "tabWidth", "textFont", "textMargin", "textWidth", "themeMode", "useCharCount", - "userIdleTime", "verPyQtString", "verPyQtValue", "verPyString", "verQtString", - "verQtValue", "viewComments", "viewPanePos", "viewSynopsis", "welcomeWinSize", + "lineHighlight", "mainPanePos", "mainWinSize", "memInfo", "narratorBreak", + "narratorDialog", "nativeFont", "osDarwin", "osLinux", "osType", "osUnknown", "osWindows", + "outlinePanePos", "prefsWinSize", "scrollPastEnd", "searchCase", "searchLoop", + "searchMatchCap", "searchNextFile", "searchProjCase", "searchProjRegEx", "searchProjWord", + "searchRegEx", "searchWord", "showEditToolBar", "showFullPath", "showLineEndings", + "showMultiSpaces", "showSessionTime", "showTabsNSpaces", "showViewerPanel", + "spellLanguage", "stopWhenIdle", "tabWidth", "textFont", "textMargin", "textWidth", + "themeMode", "useCharCount", "userIdleTime", "verPyQtString", "verPyQtValue", + "verPyString", "verQtString", "verQtValue", "viewComments", "viewPanePos", "viewSynopsis", + "welcomeWinSize", ) LANG_NW = 1 @@ -191,6 +192,7 @@ class Config: self.textMargin = 40 # Editor/viewer text margin self.tabWidth = 40 # Editor tabulator width self.cursorWidth = 1 # Editor cursor width + self.lineHighlight = False # Highlight current line in editor self.focusWidth = 800 # Focus Mode text width self.hideFocusFooter = False # Hide document footer in Focus Mode @@ -667,6 +669,7 @@ class Config: self.textMargin = conf.rdInt(sec, "margin", self.textMargin) self.tabWidth = conf.rdInt(sec, "tabwidth", self.tabWidth) self.cursorWidth = conf.rdInt(sec, "cursorwidth", self.cursorWidth) + self.lineHighlight = conf.rdBool(sec, "linehighlight", self.lineHighlight) self.focusWidth = conf.rdInt(sec, "focuswidth", self.focusWidth) self.hideFocusFooter = conf.rdBool(sec, "hidefocusfooter", self.hideFocusFooter) self.doJustify = conf.rdBool(sec, "justify", self.doJustify) @@ -793,6 +796,7 @@ class Config: "margin": str(self.textMargin), "tabwidth": str(self.tabWidth), "cursorwidth": str(self.cursorWidth), + "lineHighlight": str(self.lineHighlight), "focuswidth": str(self.focusWidth), "hidefocusfooter": str(self.hideFocusFooter), "justify": str(self.doJustify), diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py index 846b6317..4def208e 100644 --- a/novelwriter/gui/doceditor.py +++ b/novelwriter/gui/doceditor.py @@ -45,11 +45,11 @@ from PyQt6.QtCore import ( from PyQt6.QtGui import ( QAction, QCursor, QDragEnterEvent, QDragMoveEvent, QDropEvent, QKeyEvent, QKeySequence, QMouseEvent, QPalette, QPixmap, QResizeEvent, QShortcut, - QTextBlock, QTextCursor, QTextDocument, QTextOption + QTextBlock, QTextCursor, QTextDocument, QTextFormat, QTextOption ) from PyQt6.QtWidgets import ( QApplication, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QMenu, - QPlainTextEdit, QToolBar, QVBoxLayout, QWidget + QPlainTextEdit, QTextEdit, QToolBar, QVBoxLayout, QWidget ) from novelwriter import CONFIG, SHARED @@ -75,7 +75,8 @@ from novelwriter.tools.lipsum import GuiLipsum from novelwriter.types import ( QtAlignCenterTop, QtAlignJustify, QtAlignLeft, QtAlignLeftTop, QtAlignRight, QtKeepAnchor, QtModCtrl, QtModNone, QtModShift, QtMouseLeft, - QtMoveAnchor, QtMoveLeft, QtMoveRight, QtScrollAlwaysOff, QtScrollAsNeeded + QtMoveAnchor, QtMoveLeft, QtMoveRight, QtScrollAlwaysOff, QtScrollAsNeeded, + QtTransparent ) logger = logging.getLogger(__name__) @@ -145,6 +146,7 @@ class GuiDocEditor(QPlainTextEdit): self._lastActive = 0.0 # Timestamp of last activity self._lastFind = None # Position of the last found search word self._doReplace = False # Switch to temporarily disable auto-replace + self._lineColor = QtTransparent # Auto-Replace self._autoReplace = TextAutoReplace() @@ -231,6 +233,9 @@ class GuiDocEditor(QPlainTextEdit): self.updateSyntaxColors() self.initEditor() + # Connect Additional Signal + self.cursorPositionChanged.connect(self._highlightCurrentLine) + logger.debug("Ready: GuiDocEditor") return @@ -315,6 +320,9 @@ class GuiDocEditor(QPlainTextEdit): self.docHeader.matchColors() self.docFooter.matchColors() + self._lineColor = self.palette().alternateBase().color() + self._lineColor.setAlpha(160) + return def initEditor(self) -> None: @@ -372,6 +380,8 @@ class GuiDocEditor(QPlainTextEdit): # Refresh sizes self.setTabStopDistance(CONFIG.tabWidth) self.setCursorWidth(CONFIG.cursorWidth) + self.setExtraSelections([]) + self._highlightCurrentLine() # If we have a document open, we should refresh it in case the # font changed, otherwise we just clear the editor entirely, @@ -1301,6 +1311,18 @@ class GuiDocEditor(QPlainTextEdit): CONFIG.showEditToolBar = state return + @pyqtSlot() + def _highlightCurrentLine(self) -> None: + """Highlight the cursor line if setting is enabled.""" + if CONFIG.lineHighlight: + selection = QTextEdit.ExtraSelection() + selection.format.setBackground(self._lineColor) + selection.format.setProperty(QTextFormat.Property.FullWidthSelection, True) + selection.cursor = self.textCursor() + selection.cursor.clearSelection() + self.setExtraSelections([selection]) + return + ## # Search & Replace ##