From 110f86dfca3372804edceb76f74d9a4c99c3c18f Mon Sep 17 00:00:00 2001 From: Theophile Gilgien Date: Mon, 29 Jun 2026 16:52:00 +0200 Subject: [PATCH] make tab bar text follow the application theme --- typstwriter/editor.py | 57 +++++++++++++++++++++++++++++++++++++------ typstwriter/enums.py | 1 + 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/typstwriter/editor.py b/typstwriter/editor.py index 0b2e823..66298c7 100644 --- a/typstwriter/editor.py +++ b/typstwriter/editor.py @@ -71,7 +71,7 @@ def new_file(self): icon = QtGui.QIcon.fromTheme(QtGui.QIcon.DocumentNew, QtGui.QIcon(util.icon_path("newFile.svg"))) self.TabWidget.addTab(editorpage, icon, name) self.TabWidget.setCurrentIndex(self.TabWidget.count() - 1) - self.TabWidget.tabBar().setTabTextColor(self.TabWidget.count() - 1, QtGui.QColor("green")) + self.update_tab_color(self.TabWidget.count() - 1) editorpage.edit.textChanged.connect(self.childtext_changed) editorpage.savestatechanged.connect(self.childsavedstate_changed) @@ -85,7 +85,7 @@ def open_file(self, path): icon = util.FileIconProvider().icon(QtCore.QFileInfo(path)) self.TabWidget.addTab(editorpage, icon, name) self.TabWidget.setCurrentIndex(self.TabWidget.count() - 1) - self.TabWidget.tabBar().setTabTextColor(self.TabWidget.count() - 1, QtGui.QColor("black")) + self.update_tab_color(self.TabWidget.count() - 1) editorpage.edit.textChanged.connect(self.childtext_changed) editorpage.savestatechanged.connect(self.childsavedstate_changed) @@ -138,7 +138,7 @@ def welcome(self): icon = QtGui.QIcon() self.TabWidget.addTab(welcomepage, icon, "Welcome") self.TabWidget.setCurrentIndex(self.TabWidget.count() - 1) - self.TabWidget.tabBar().setTabTextColor(self.TabWidget.count() - 1, QtGui.QColor("blue")) + self.update_tab_color(self.TabWidget.count() - 1) welcomepage.button_NewFile.pressed.connect(self.new_file) welcomepage.button_OpenFile.pressed.connect(self.open_file_dialog) welcomepage.open_file.connect(self.open_file) @@ -161,6 +161,40 @@ def tryclose(self): self.recentFiles.write() return True + def update_tab_color(self, i): + """Update the text color of the tab with index i.""" + textcolor = self.palette().buttonText().color() + coloredtextbase = self.palette().link().color() + if self.TabWidget.widget(i).tab_status() == enums.tab_status.standard: + self.TabWidget.tabBar().setTabTextColor(i, textcolor) + elif self.TabWidget.widget(i).tab_status() == enums.tab_status.new: + # boost contrast on light themes + value = ( + coloredtextbase.value() + if self.palette().button().color().value() < textcolor.value() + else max(100, coloredtextbase.value() - 80) + ) + self.TabWidget.tabBar().setTabTextColor( + i, QtGui.QColor.fromHsv(120, coloredtextbase.saturation(), value, coloredtextbase.alpha()) + ) # green + elif self.TabWidget.widget(i).tab_status() == enums.tab_status.welcome: + self.TabWidget.tabBar().setTabTextColor( + i, QtGui.QColor.fromHsv(240, coloredtextbase.saturation(), coloredtextbase.value(), coloredtextbase.alpha()) + ) # blue + elif self.TabWidget.widget(i).tab_status() == enums.tab_status.not_saved: + self.TabWidget.tabBar().setTabTextColor( + i, QtGui.QColor.fromHsv(0, coloredtextbase.saturation(), coloredtextbase.value(), coloredtextbase.alpha()) + ) # red + + def changeEvent(self, event): # noqa: N802 + """Acts on PaletteChange events, otherwise passes on to parent implementation.""" + if event.type() == QtCore.QEvent.PaletteChange: + for i in range(self.TabWidget.count()): + self.update_tab_color(i) + event.accept() + else: + super().changeEvent(event) + @QtCore.Slot() def save_all(self): """Save all tabs.""" @@ -207,10 +241,7 @@ def childtext_changed(self): def childsavedstate_changed(self, savestate): """Trigger textChanged.""" i = self.TabWidget.indexOf(self.sender()) - if savestate: - self.TabWidget.tabBar().setTabTextColor(i, QtGui.QColor("black")) - else: - self.TabWidget.tabBar().setTabTextColor(i, QtGui.QColor("red")) + self.update_tab_color(i) @QtCore.Slot(str) def childpath_changed(self, path): @@ -488,6 +519,14 @@ def modified(self): self.issaved = False self.savestatechanged.emit(self.issaved) + def tab_status(self): + """Return the status indicated by tab name color.""" + if not self.path: + return enums.tab_status.new + if not self.issaved: + return enums.tab_status.not_saved + return enums.tab_status.standard + @QtCore.Slot(str) def show_file_changed_warning(self, path): """Show the file changed warning.""" @@ -778,6 +817,10 @@ def tryclose(self): """Close page.""" return True + def tab_status(self): + """Return status indicated by tab name color.""" + return enums.tab_status.welcome + class CodeEdit(QtWidgets.QPlainTextEdit): """A code editor widget.""" diff --git a/typstwriter/enums.py b/typstwriter/enums.py index 3286056..b39aad2 100644 --- a/typstwriter/enums.py +++ b/typstwriter/enums.py @@ -3,3 +3,4 @@ compiler_mode = enum.Enum("compiler_mode", ["on_demand", "live"]) search_mode = enum.Enum("search_mode", ["case_insensitive", "case_sensitive", "whole_words", "regex"]) search_direction = enum.Enum("search_direction", ["next", "previous"]) +tab_status = enum.Enum("tab_status", ["standard", "new", "welcome", "not_saved"])