[PATCH 6 of 8 DarkThemeSeries 1] fileview: apply dark theme to HgFileView editor and fix white margin stripe

0 views
Skip to first unread message

Peter Demcak

unread,
Mar 7, 2026, 1:27:02 PM (3 days ago) Mar 7
to thg...@googlegroups.com
# HG changeset patch
# User Peter Demcak <majs...@gmail.com>
# Date 1772737022 -3600
# Thu Mar 05 19:57:02 2026 +0100
# Node ID 850aefde16bddd4e7fc59327e62edd433d78efcf
# Parent 10a94641ed6c10d352cee52f7a02b0f40d35ba23
fileview: apply dark theme to HgFileView editor and fix white margin stripe

- Apply THEME colors to the Scintilla editor widget and all view margins
(diff, file, annotate).
- Fix the white stripe artifact in the margin area by deferring viewport
palette and Scintilla style updates via _forceDarkViewportLater().
- Add _resetMargins() to clear margin widths on mode switch

diff -r 10a94641ed6c -r 850aefde16bd tortoisehg/hgqt/fileview.py
--- a/tortoisehg/hgqt/fileview.py Thu Mar 05 19:56:36 2026 +0100
+++ b/tortoisehg/hgqt/fileview.py Thu Mar 05 19:57:02 2026 +0100
@@ -78,6 +78,8 @@
Optional,
)

+from .theme import THEME
+
qsci = qscilib.Scintilla

# _NullMode is the fallback mode to display error message or repository history
@@ -162,6 +164,22 @@
self.blk = blockmatcher.BlockList(self)
self.blksearch = blockmatcher.BlockList(self)
self.sci = qscilib.Scintilla(self)
+
+ if THEME.enabled:
+ self.sci.setPaper(THEME.background)
+ self.sci.setColor(THEME.text)
+
+ self.sci.setSelectionBackgroundColor(THEME.selection_background)
+ self.sci.setSelectionForegroundColor(THEME.selection_text)
+
+ self.sci.setCaretForegroundColor(THEME.caret_foreground)
+
+ self.sci.setMarginsBackgroundColor(THEME.backgroundLighter)
+ self.sci.setMarginsForegroundColor(THEME.text_margin)
+
+ self.sci.setWhitespaceBackgroundColor(THEME.background)
+ self.sci.setWhitespaceForegroundColor(THEME.text_margin)
+
hbox.addWidget(self.blk)
hbox.addWidget(self.sci, 1)
hbox.addWidget(self.blksearch)
@@ -297,6 +315,10 @@
repoagent.configChanged.connect(self._applyRepoConfig)
self._applyRepoConfig()

+ def _resetMargins(self):
+ for m in (_LineNumberMargin, _AnnotateMargin, _ChunkSelectionMargin):
+ self.sci.setMarginWidth(m, 0)
+
@property
def repo(self):
return self._repoagent.rawRepo()
@@ -378,6 +400,10 @@
for c in reversed(self._activeViewControls):
if c not in newcontrols:
c.close()
+
+ if THEME.enabled:
+ self._resetMargins()
+
for c in newcontrols:
if c not in self._activeViewControls:
c.open()
@@ -728,6 +754,35 @@
assert p is None or isinstance(p, QWidget)
return p

+ def _forceDarkViewportLater(self):
+ if not THEME.enabled:
+ return
+
+ self._sci.setPaper(THEME.background)
+ self._sci.setMarginsBackgroundColor(THEME.backgroundLighter)
+ self._sci.setMarginsForegroundColor(THEME.text_margin)
+
+ QTimer.singleShot(0, self._applyDarkFixes)
+
+
+ def _applyDarkFixes(self):
+ if not THEME.enabled:
+ return
+
+ sci = self._sci
+
+ # viewport background
+ vp = sci.viewport()
+ vp.setAutoFillBackground(True)
+ pal = vp.palette()
+ pal.setColor(qtlib.QtPaletteRole.Window, THEME.background)
+ vp.setPalette(pal)
+
+ # selection (compatible with old Scintilla)
+ sci.SendScintilla(qsci.SCI_SETSELBACK, 1, THEME.selection_background)
+ sci.SendScintilla(qsci.SCI_SETSELFORE, 1, THEME.selection_text)
+
+ sci.setCaretForegroundColor(THEME.caret_foreground)

_diffHeaderRegExp = re.compile(r"^@@ -[0-9]+,[0-9]+ \+[0-9]+,[0-9]+ @@")

@@ -754,6 +809,25 @@
_ChunkStartMarker)
self._sci.setLexer(lexers.difflexer(self))

+ if THEME.enabled:
+ self._sci.setMarginType(_ChunkSelectionMargin, qsci.MarginType.SymbolMargin)
+ self._sci.setMarginWidth(_ChunkSelectionMargin, 14)
+ self._sci.setMarginMarkerMask(_ChunkSelectionMargin, _ChunkSelectionMarkerMask)
+ self._sci.setMarginSensitivity(_ChunkSelectionMargin, True)
+
+ # LEXER - controls text colors
+ lexer = lexers.difflexer(self)
+ self._sci.setLexer(lexer)
+
+ self._sci.SendScintilla(qsci.SCI_STYLESETBACK, qsci.STYLE_DEFAULT, THEME.background)
+ self._sci.SendScintilla(qsci.SCI_STYLESETFORE, _ChunkStartMarker, THEME.diff_text) # color of unmodified text
+ self._sci.SendScintilla(qsci.SCI_STYLESETFORE, _ReplacedLineMarker, THEME.diff_start) # @@
+ self._sci.SendScintilla(qsci.SCI_STYLESETFORE, _ExcludedLineMarker, THEME.diff_removed)
+ self._sci.SendScintilla(qsci.SCI_STYLESETFORE, _FirstAnnotateLineMarker, THEME.diff_added) # color of added text
+
+ # CRITICAL - must be called after setLexer to fix white stripe
+ self._forceDarkViewportLater()
+
def close(self):
self._sci.markerDefine(qsci.MarkerSymbol.Invisible, _ChunkStartMarker)
self._sci.setLexer(None)
@@ -831,6 +905,23 @@
self._blk.setVisible(True)
self._actionGotoLine.setEnabled(True)

+ if THEME.enabled:
+ # to skip white strip
+ self._forceDarkViewportLater()
+
+ # This controls the color of margin text
+ self._sci.SendScintilla(qsci.SCI_STYLESETFORE, qsci.STYLE_LINENUMBER, THEME.text_margin)
+ self._sci.SendScintilla(qsci.SCI_STYLESETBACK, qsci.STYLE_LINENUMBER, THEME.backgroundLighter)
+
+ # dark theme - global, not for margin
+ self._sci.setMarginsBackgroundColor(THEME.backgroundLighter)
+ self._sci.setMarginsForegroundColor(THEME.text_margin)
+
+ # width by number of lines
+ width = len(str(self._sci.lines())) + 2
+ self._sci.setMarginLineNumbers(_LineNumberMargin, True)
+ self._sci.setMarginWidth(_LineNumberMargin, 'M' * width)
+
def close(self):
self._blk.setVisible(False)
self._sci.setMarginWidth(_LineNumberMargin, 0)
@@ -860,6 +951,17 @@
else:
self._buildtimer.stop() # in case previous request not finished

+ if THEME.enabled:
+ self._forceDarkViewportLater() # fixes ocasional white strip for FileView
+
+ @util.propertycache
+ def _margin_style(self):
+ s = Qsci.QsciStyle(qscilib.STYLE_FILEVIEW_MARGIN)
+ s.setPaper(THEME.backgroundLighter)
+ s.setColor(THEME.text_margin)
+ s.setFont(self._sci.font())
+ return s
+
def _startBuildMarker(self, fd):
# use the difflib.SequenceMatcher, which returns a set of opcodes
# that must be parsed
@@ -1003,6 +1105,8 @@

def open(self):
self._sci.viewport().installEventFilter(self)
+ if THEME.enabled:
+ self._forceDarkViewportLater()

def close(self):
self._sci.viewport().removeEventFilter(self)
@@ -1199,7 +1303,12 @@
def _margin_style(self):
"""Style for margin area"""
s = Qsci.QsciStyle(qscilib.STYLE_FILEVIEW_MARGIN)
- s.setPaper(QApplication.palette().color(QPalette.ColorRole.Window))
+
+ if THEME.enabled:
+ s.setPaper(THEME.backgroundLighter)
+ else:
+ s.setPaper(QApplication.palette().color(QPalette.ColorRole.Window))
+
s.setFont(self._sci.font())
return s


Reply all
Reply to author
Forward
0 new messages