gui: improve usability in dark mode (bug 1719424) (#1290)
This commit is contained in:
Родитель
2911cbc8d4
Коммит
08255e7cde
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 4.4 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 4.6 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 4.8 KiB |
|
@ -1,7 +1,8 @@
|
|||
from tempfile import mkdtemp
|
||||
|
||||
import mozfile
|
||||
from PySide6.QtCore import QSettings, Slot
|
||||
from PySide6.QtCore import QEvent, QSettings, Slot
|
||||
from PySide6.QtGui import QIcon
|
||||
from PySide6.QtWidgets import QMainWindow, QMessageBox
|
||||
|
||||
from mozregression import __version__ as mozregression_version
|
||||
|
@ -11,6 +12,7 @@ from mozregui.global_prefs import change_prefs_dialog, get_prefs
|
|||
from mozregui.report_delegate import ReportItemDelegate
|
||||
from mozregui.single_runner import SingleBuildRunner
|
||||
from mozregui.ui.mainwindow import Ui_MainWindow
|
||||
from mozregui.utils import is_dark_mode_enabled
|
||||
from mozregui.wizard import BisectionWizard, SingleRunWizard
|
||||
|
||||
ABOUT_TEXT = """\
|
||||
|
@ -39,6 +41,7 @@ class MainWindow(QMainWindow):
|
|||
MainWindow.INSTANCE = self
|
||||
self.ui = Ui_MainWindow()
|
||||
self.ui.setupUi(self)
|
||||
self._update_palette()
|
||||
|
||||
self.bisect_runner = BisectRunner(self)
|
||||
self.single_runner = SingleBuildRunner(self)
|
||||
|
@ -101,6 +104,16 @@ class MainWindow(QMainWindow):
|
|||
|
||||
runner.start(*wizard.options())
|
||||
|
||||
def _update_palette(self):
|
||||
if is_dark_mode_enabled():
|
||||
self.ui.actionRun_a_single_build.setIcon(QIcon(":/s_white.png"))
|
||||
self.ui.actionStart_a_new_bisection.setIcon(QIcon(":/cutting_white.png"))
|
||||
self.ui.actionStop_the_bisection.setIcon(QIcon(":/stop_white.png"))
|
||||
else:
|
||||
self.ui.actionRun_a_single_build.setIcon(QIcon(":/s.png"))
|
||||
self.ui.actionStart_a_new_bisection.setIcon(QIcon(":/cutting.png"))
|
||||
self.ui.actionStop_the_bisection.setIcon(QIcon(":/stop.png"))
|
||||
|
||||
@Slot()
|
||||
def start_bisection_wizard(self):
|
||||
self._start_runner(BisectionWizard, self.bisect_runner)
|
||||
|
@ -122,3 +135,10 @@ class MainWindow(QMainWindow):
|
|||
@Slot()
|
||||
def edit_global_prefs(self):
|
||||
change_prefs_dialog(self)
|
||||
|
||||
def event(self, event: QEvent) -> bool:
|
||||
if event.type() == QEvent.PaletteChange:
|
||||
self._update_palette()
|
||||
return True
|
||||
|
||||
return super().event(event)
|
||||
|
|
|
@ -3,14 +3,20 @@ from PySide6.QtGui import QColor, QDesktopServices
|
|||
from PySide6.QtWidgets import QTableView, QTextBrowser
|
||||
|
||||
from mozregression.bisector import NightlyHandler
|
||||
from mozregui.utils import is_dark_mode_enabled
|
||||
|
||||
# Custom colors
|
||||
GRAY_WHITE = QColor(243, 243, 243)
|
||||
DARK_GRAY = QColor(28, 28, 28)
|
||||
VERDICT_TO_ROW_COLORS = {
|
||||
"g": QColor(152, 251, 152), # light green
|
||||
"b": QColor(250, 113, 113), # light red
|
||||
"s": QColor(253, 248, 107), # light yellow
|
||||
"r": QColor(225, 225, 225), # light gray
|
||||
"g_dark": QColor(48, 209, 88), # green
|
||||
"b_dark": QColor(255, 70, 58), # red
|
||||
"s_dark": QColor(160, 90, 0), # yellow
|
||||
"r_dark": QColor(45, 45, 45), # gray
|
||||
}
|
||||
|
||||
|
||||
|
@ -167,7 +173,12 @@ class ReportModel(QAbstractTableModel):
|
|||
return item.status_text()
|
||||
elif role == Qt.BackgroundRole:
|
||||
if isinstance(item, StepItem) and item.verdict:
|
||||
return VERDICT_TO_ROW_COLORS.get(str(item.verdict), GRAY_WHITE)
|
||||
if is_dark_mode_enabled():
|
||||
return VERDICT_TO_ROW_COLORS.get(str(item.verdict) + "_dark", DARK_GRAY)
|
||||
else:
|
||||
return VERDICT_TO_ROW_COLORS.get(str(item.verdict), GRAY_WHITE)
|
||||
elif is_dark_mode_enabled():
|
||||
return DARK_GRAY
|
||||
else:
|
||||
return GRAY_WHITE
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from PySide6.QtCore import QRect, Qt, Signal
|
||||
from PySide6.QtGui import QIcon, QPainter, QPixmap
|
||||
from PySide6.QtCore import QEvent, QRect, Qt, Signal
|
||||
from PySide6.QtGui import QIcon, QPainter, QPen, QPixmap
|
||||
from PySide6.QtWidgets import (
|
||||
QApplication,
|
||||
QStyle,
|
||||
|
@ -10,6 +10,7 @@ from PySide6.QtWidgets import (
|
|||
|
||||
from mozregui.report import VERDICT_TO_ROW_COLORS
|
||||
from mozregui.ui.ask_verdict import Ui_AskVerdict
|
||||
from mozregui.utils import is_dark_mode_enabled
|
||||
|
||||
VERDICTS = ("good", "bad", "skip", "retry", "other...")
|
||||
|
||||
|
@ -25,17 +26,7 @@ class AskVerdict(QWidget):
|
|||
self.ui.setupUi(self)
|
||||
# build verdict icons
|
||||
if not AskVerdict.icons_cache:
|
||||
for text in VERDICTS:
|
||||
color = VERDICT_TO_ROW_COLORS.get(text[0])
|
||||
pixmap = QPixmap(16, 16)
|
||||
pixmap.fill(Qt.transparent)
|
||||
if color:
|
||||
painter = QPainter(pixmap)
|
||||
painter.setPen(Qt.black)
|
||||
painter.setBrush(color)
|
||||
painter.drawEllipse(0, 0, 15, 15)
|
||||
painter.end()
|
||||
AskVerdict.icons_cache[text] = QIcon(pixmap)
|
||||
self._build_icon_cache()
|
||||
|
||||
# set combo verdict
|
||||
for text in ("other...", "skip", "retry"):
|
||||
|
@ -51,6 +42,29 @@ class AskVerdict(QWidget):
|
|||
self.ui.badVerdict.clicked.connect(self.on_good_bad_button_clicked)
|
||||
self.ui.badVerdict.setIcon(AskVerdict.icons_cache["bad"])
|
||||
|
||||
def _build_icon_cache(self):
|
||||
for text in VERDICTS:
|
||||
if is_dark_mode_enabled():
|
||||
color = VERDICT_TO_ROW_COLORS.get(text[0] + "_dark")
|
||||
else:
|
||||
color = VERDICT_TO_ROW_COLORS.get(text[0])
|
||||
pixmap = QPixmap(16, 16)
|
||||
pixmap.fill(Qt.transparent)
|
||||
if color:
|
||||
painter = QPainter(pixmap)
|
||||
painter.setPen(QPen(self.palette().windowText().color()))
|
||||
painter.setBrush(color)
|
||||
painter.drawEllipse(0, 0, 15, 15)
|
||||
painter.end()
|
||||
AskVerdict.icons_cache[text] = QIcon(pixmap)
|
||||
|
||||
def _update_icons(self):
|
||||
self.ui.goodVerdict.setIcon(AskVerdict.icons_cache["good"])
|
||||
self.ui.badVerdict.setIcon(AskVerdict.icons_cache["bad"])
|
||||
for i in range(self.ui.comboVerdict.count()):
|
||||
text = str(self.ui.comboVerdict.itemText(i))
|
||||
self.ui.comboVerdict.setItemIcon(i, AskVerdict.icons_cache[text])
|
||||
|
||||
def on_dropdown_item_activated(self):
|
||||
self.delegate.got_verdict.emit(str(self.ui.comboVerdict.currentText())[0].lower())
|
||||
self.emitted = True
|
||||
|
@ -59,6 +73,13 @@ class AskVerdict(QWidget):
|
|||
self.delegate.got_verdict.emit(str(self.sender().text())[0].lower())
|
||||
self.emitted = True
|
||||
|
||||
def event(self, event: QEvent) -> bool:
|
||||
if event.type() == QEvent.PaletteChange:
|
||||
self._build_icon_cache()
|
||||
self._update_icons()
|
||||
return True
|
||||
return super().event(event)
|
||||
|
||||
|
||||
class ReportItemDelegate(QStyledItemDelegate):
|
||||
got_verdict = Signal(str)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from PySide6.QtCore import Qt, Signal
|
||||
from PySide6.QtGui import QBrush
|
||||
from PySide6.QtCore import QEvent, Qt, Signal
|
||||
from PySide6.QtGui import QBrush, QPen
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog,
|
||||
QGraphicsRectItem,
|
||||
|
@ -53,8 +53,22 @@ class SkipChooserScene(QGraphicsScene):
|
|||
self.mid_build = item
|
||||
elif i in bounds:
|
||||
item.setBrush(QBrush(Qt.lightGray))
|
||||
|
||||
pen = QPen(self.palette().windowText().color())
|
||||
item.setPen(pen)
|
||||
self.addItem(item)
|
||||
|
||||
def _update_palette(self):
|
||||
for item in self.items():
|
||||
pen = QPen(self.palette().windowText().color())
|
||||
item.setPen(pen)
|
||||
|
||||
def event(self, event: QEvent) -> bool:
|
||||
if event.type() == QEvent.PaletteChange:
|
||||
self._update_palette()
|
||||
return True
|
||||
return super().event(event)
|
||||
|
||||
|
||||
class SkipChooserView(QGraphicsView):
|
||||
build_choosen = Signal()
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from PySide6.QtCore import QDir
|
||||
from PySide6.QtGui import QGuiApplication, QPalette
|
||||
from PySide6.QtWidgets import (
|
||||
QCompleter,
|
||||
QFileDialog,
|
||||
|
@ -85,3 +86,10 @@ class BuildSelection(QWidget):
|
|||
raise DateFormatError(buildid, "Not a valid build id: `%s`")
|
||||
elif currentw == self.ui.s_changeset:
|
||||
return self.ui.changeset.text().strip()
|
||||
|
||||
|
||||
def is_dark_mode_enabled():
|
||||
"""
|
||||
Return True if dark mode is being used.
|
||||
"""
|
||||
return QGuiApplication.palette().color(QPalette.Window).lightness() < 128
|
||||
|
|
|
@ -4,5 +4,8 @@
|
|||
<file alias="stop.png">icons/cross106.png</file>
|
||||
<file alias="cutting.png">icons/cutting10.png</file>
|
||||
<file alias="s.png">icons/letter52.png</file>
|
||||
<file alias="stop_white.png">icons/cross106_white.png</file>
|
||||
<file alias="cutting_white.png">icons/cutting10_white.png</file>
|
||||
<file alias="s_white.png">icons/letter52_white.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
Загрузка…
Ссылка в новой задаче