Refresh StatusLEDs when theme changes (#1906)
This commit is contained in:
@@ -25,44 +25,50 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from typing import Literal
|
|
||||||
|
|
||||||
from PyQt5.QtGui import QColor, QPainter, QPaintEvent
|
from PyQt5.QtGui import QColor, QPainter, QPaintEvent
|
||||||
from PyQt5.QtWidgets import QAbstractButton, QWidget
|
from PyQt5.QtWidgets import QAbstractButton, QWidget
|
||||||
|
|
||||||
from novelwriter.types import QtPaintAnitAlias
|
from novelwriter.enum import nwTrinary
|
||||||
|
from novelwriter.types import QtBlack, QtPaintAnitAlias
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class StatusLED(QAbstractButton):
|
class StatusLED(QAbstractButton):
|
||||||
|
|
||||||
S_NONE = 0
|
def __init__(self, sW: int, sH: int, parent: QWidget | None = None) -> None:
|
||||||
S_BAD = 1
|
|
||||||
S_GOOD = 2
|
|
||||||
|
|
||||||
def __init__(self, colNone: QColor, colGood: QColor, colBad: QColor,
|
|
||||||
sW: int, sH: int, parent: QWidget | None = None) -> None:
|
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
|
self._neutral = QtBlack
|
||||||
self._colNone = colNone
|
self._postitve = QtBlack
|
||||||
self._colGood = colGood
|
self._negative = QtBlack
|
||||||
self._colBad = colBad
|
self._color = QtBlack
|
||||||
self._theCol = colNone
|
self._state = nwTrinary.NEUTRAL
|
||||||
|
|
||||||
self.setFixedWidth(sW)
|
self.setFixedWidth(sW)
|
||||||
self.setFixedHeight(sH)
|
self.setFixedHeight(sH)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def setState(self, state: Literal[0, 1, 2]) -> None:
|
@property
|
||||||
|
def state(self) -> nwTrinary:
|
||||||
|
"""The current state of the LED."""
|
||||||
|
return self._state
|
||||||
|
|
||||||
|
def setColors(self, neutral: QColor, positive: QColor, negative: QColor) -> None:
|
||||||
|
"""Set the three colours for the status values."""
|
||||||
|
self._neutral = neutral
|
||||||
|
self._postitve = positive
|
||||||
|
self._negative = negative
|
||||||
|
self.setState(self._state)
|
||||||
|
return
|
||||||
|
|
||||||
|
def setState(self, state: nwTrinary) -> None:
|
||||||
"""Set the colour state."""
|
"""Set the colour state."""
|
||||||
if state == self.S_GOOD:
|
if state == nwTrinary.POSITIVE:
|
||||||
self._theCol = self._colGood
|
self._color = self._postitve
|
||||||
elif state == self.S_BAD:
|
elif state == nwTrinary.NEGATIVE:
|
||||||
self._theCol = self._colBad
|
self._color = self._negative
|
||||||
else:
|
else:
|
||||||
self._theCol = self._colNone
|
self._color = self._neutral
|
||||||
|
self._state = state
|
||||||
self.update()
|
self.update()
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -71,7 +77,7 @@ class StatusLED(QAbstractButton):
|
|||||||
painter = QPainter(self)
|
painter = QPainter(self)
|
||||||
painter.setRenderHint(QtPaintAnitAlias, True)
|
painter.setRenderHint(QtPaintAnitAlias, True)
|
||||||
painter.setPen(self.palette().dark().color())
|
painter.setPen(self.palette().dark().color())
|
||||||
painter.setBrush(self._theCol)
|
painter.setBrush(self._color)
|
||||||
painter.setOpacity(1.0)
|
painter.setOpacity(1.0)
|
||||||
painter.drawEllipse(1, 1, self.width() - 2, self.height() - 2)
|
painter.drawEllipse(1, 1, self.width() - 2, self.height() - 2)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import logging
|
|||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from time import time
|
from time import time
|
||||||
from typing import Literal
|
|
||||||
|
|
||||||
from PyQt5.QtCore import QLocale, pyqtSlot
|
from PyQt5.QtCore import QLocale, pyqtSlot
|
||||||
from PyQt5.QtWidgets import QApplication, QLabel, QStatusBar, QWidget
|
from PyQt5.QtWidgets import QApplication, QLabel, QStatusBar, QWidget
|
||||||
@@ -35,6 +34,7 @@ from PyQt5.QtWidgets import QApplication, QLabel, QStatusBar, QWidget
|
|||||||
from novelwriter import CONFIG, SHARED
|
from novelwriter import CONFIG, SHARED
|
||||||
from novelwriter.common import formatTime
|
from novelwriter.common import formatTime
|
||||||
from novelwriter.constants import nwConst
|
from novelwriter.constants import nwConst
|
||||||
|
from novelwriter.enum import nwTrinary
|
||||||
from novelwriter.extensions.statusled import StatusLED
|
from novelwriter.extensions.statusled import StatusLED
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -51,10 +51,6 @@ class GuiMainStatus(QStatusBar):
|
|||||||
self._userIdle = False
|
self._userIdle = False
|
||||||
self._debugInfo = False
|
self._debugInfo = False
|
||||||
|
|
||||||
colNone = SHARED.theme.statNone
|
|
||||||
colSaved = SHARED.theme.statSaved
|
|
||||||
colUnsaved = SHARED.theme.statUnsaved
|
|
||||||
|
|
||||||
iPx = SHARED.theme.baseIconHeight
|
iPx = SHARED.theme.baseIconHeight
|
||||||
|
|
||||||
# Permanent Widgets
|
# Permanent Widgets
|
||||||
@@ -71,7 +67,7 @@ class GuiMainStatus(QStatusBar):
|
|||||||
self.addPermanentWidget(self.langText)
|
self.addPermanentWidget(self.langText)
|
||||||
|
|
||||||
# The Editor Status
|
# The Editor Status
|
||||||
self.docIcon = StatusLED(colNone, colSaved, colUnsaved, iPx, iPx, self)
|
self.docIcon = StatusLED(iPx, iPx, self)
|
||||||
self.docText = QLabel(self.tr("Editor"), self)
|
self.docText = QLabel(self.tr("Editor"), self)
|
||||||
self.docIcon.setContentsMargins(0, 0, 0, 0)
|
self.docIcon.setContentsMargins(0, 0, 0, 0)
|
||||||
self.docText.setContentsMargins(0, 0, xM, 0)
|
self.docText.setContentsMargins(0, 0, xM, 0)
|
||||||
@@ -79,7 +75,7 @@ class GuiMainStatus(QStatusBar):
|
|||||||
self.addPermanentWidget(self.docText)
|
self.addPermanentWidget(self.docText)
|
||||||
|
|
||||||
# The Project Status
|
# The Project Status
|
||||||
self.projIcon = StatusLED(colNone, colSaved, colUnsaved, iPx, iPx, self)
|
self.projIcon = StatusLED(iPx, iPx, self)
|
||||||
self.projText = QLabel(self.tr("Project"), self)
|
self.projText = QLabel(self.tr("Project"), self)
|
||||||
self.projIcon.setContentsMargins(0, 0, 0, 0)
|
self.projIcon.setContentsMargins(0, 0, 0, 0)
|
||||||
self.projText.setContentsMargins(0, 0, xM, 0)
|
self.projText.setContentsMargins(0, 0, xM, 0)
|
||||||
@@ -120,8 +116,8 @@ class GuiMainStatus(QStatusBar):
|
|||||||
self.setRefTime(-1.0)
|
self.setRefTime(-1.0)
|
||||||
self.setLanguage(*SHARED.spelling.describeDict())
|
self.setLanguage(*SHARED.spelling.describeDict())
|
||||||
self.setProjectStats(0, 0)
|
self.setProjectStats(0, 0)
|
||||||
self.setProjectStatus(StatusLED.S_NONE)
|
self.setProjectStatus(nwTrinary.NEUTRAL)
|
||||||
self.setDocumentStatus(StatusLED.S_NONE)
|
self.setDocumentStatus(nwTrinary.NEUTRAL)
|
||||||
self.updateTime()
|
self.updateTime()
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -133,6 +129,13 @@ class GuiMainStatus(QStatusBar):
|
|||||||
self.timePixmap = SHARED.theme.getPixmap("status_time", (iPx, iPx))
|
self.timePixmap = SHARED.theme.getPixmap("status_time", (iPx, iPx))
|
||||||
self.idlePixmap = SHARED.theme.getPixmap("status_idle", (iPx, iPx))
|
self.idlePixmap = SHARED.theme.getPixmap("status_idle", (iPx, iPx))
|
||||||
self.timeIcon.setPixmap(self.timePixmap)
|
self.timeIcon.setPixmap(self.timePixmap)
|
||||||
|
|
||||||
|
colNone = SHARED.theme.statNone
|
||||||
|
colSaved = SHARED.theme.statSaved
|
||||||
|
colUnsaved = SHARED.theme.statUnsaved
|
||||||
|
self.docIcon.setColors(colNone, colSaved, colUnsaved)
|
||||||
|
self.projIcon.setColors(colNone, colSaved, colUnsaved)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -144,12 +147,12 @@ class GuiMainStatus(QStatusBar):
|
|||||||
self._refTime = refTime
|
self._refTime = refTime
|
||||||
return
|
return
|
||||||
|
|
||||||
def setProjectStatus(self, state: Literal[0, 1, 2]) -> None:
|
def setProjectStatus(self, state: nwTrinary) -> None:
|
||||||
"""Set the project status colour icon."""
|
"""Set the project status colour icon."""
|
||||||
self.projIcon.setState(state)
|
self.projIcon.setState(state)
|
||||||
return
|
return
|
||||||
|
|
||||||
def setDocumentStatus(self, state: Literal[0, 1, 2]) -> None:
|
def setDocumentStatus(self, state: nwTrinary) -> None:
|
||||||
"""Set the document status colour icon."""
|
"""Set the document status colour icon."""
|
||||||
self.docIcon.setState(state)
|
self.docIcon.setState(state)
|
||||||
return
|
return
|
||||||
@@ -212,13 +215,13 @@ class GuiMainStatus(QStatusBar):
|
|||||||
@pyqtSlot(bool)
|
@pyqtSlot(bool)
|
||||||
def updateProjectStatus(self, status: bool) -> None:
|
def updateProjectStatus(self, status: bool) -> None:
|
||||||
"""Update the project status."""
|
"""Update the project status."""
|
||||||
self.setProjectStatus(StatusLED.S_BAD if status else StatusLED.S_GOOD)
|
self.setProjectStatus(nwTrinary.NEGATIVE if status else nwTrinary.POSITIVE)
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(bool)
|
@pyqtSlot(bool)
|
||||||
def updateDocumentStatus(self, status: bool) -> None:
|
def updateDocumentStatus(self, status: bool) -> None:
|
||||||
"""Update the document status."""
|
"""Update the document status."""
|
||||||
self.setDocumentStatus(StatusLED.S_BAD if status else StatusLED.S_GOOD)
|
self.setDocumentStatus(nwTrinary.NEGATIVE if status else nwTrinary.POSITIVE)
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import time
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from novelwriter import CONFIG, SHARED
|
from novelwriter import CONFIG, SHARED
|
||||||
from novelwriter.extensions.statusled import StatusLED
|
from novelwriter.enum import nwTrinary
|
||||||
|
|
||||||
from tests.tools import C, buildTestProject
|
from tests.tools import C, buildTestProject
|
||||||
|
|
||||||
@@ -46,20 +46,20 @@ def testGuiStatusBar_Main(qtbot, nwGUI, projPath, mockRnd):
|
|||||||
assert nwGUI.mainStatus._refTime == refTime
|
assert nwGUI.mainStatus._refTime == refTime
|
||||||
|
|
||||||
# Project Status
|
# Project Status
|
||||||
nwGUI.mainStatus.setProjectStatus(StatusLED.S_NONE)
|
nwGUI.mainStatus.setProjectStatus(nwTrinary.NEUTRAL)
|
||||||
assert nwGUI.mainStatus.projIcon._theCol == nwGUI.mainStatus.projIcon._colNone
|
assert nwGUI.mainStatus.projIcon.state == nwTrinary.NEUTRAL
|
||||||
nwGUI.mainStatus.setProjectStatus(StatusLED.S_BAD)
|
nwGUI.mainStatus.setProjectStatus(nwTrinary.NEGATIVE)
|
||||||
assert nwGUI.mainStatus.projIcon._theCol == nwGUI.mainStatus.projIcon._colBad
|
assert nwGUI.mainStatus.projIcon.state == nwTrinary.NEGATIVE
|
||||||
nwGUI.mainStatus.setProjectStatus(StatusLED.S_GOOD)
|
nwGUI.mainStatus.setProjectStatus(nwTrinary.POSITIVE)
|
||||||
assert nwGUI.mainStatus.projIcon._theCol == nwGUI.mainStatus.projIcon._colGood
|
assert nwGUI.mainStatus.projIcon.state == nwTrinary.POSITIVE
|
||||||
|
|
||||||
# Document Status
|
# Document Status
|
||||||
nwGUI.mainStatus.setDocumentStatus(StatusLED.S_NONE)
|
nwGUI.mainStatus.setDocumentStatus(nwTrinary.NEUTRAL)
|
||||||
assert nwGUI.mainStatus.docIcon._theCol == nwGUI.mainStatus.docIcon._colNone
|
assert nwGUI.mainStatus.docIcon.state == nwTrinary.NEUTRAL
|
||||||
nwGUI.mainStatus.setDocumentStatus(StatusLED.S_BAD)
|
nwGUI.mainStatus.setDocumentStatus(nwTrinary.NEGATIVE)
|
||||||
assert nwGUI.mainStatus.docIcon._theCol == nwGUI.mainStatus.docIcon._colBad
|
assert nwGUI.mainStatus.docIcon.state == nwTrinary.NEGATIVE
|
||||||
nwGUI.mainStatus.setDocumentStatus(StatusLED.S_GOOD)
|
nwGUI.mainStatus.setDocumentStatus(nwTrinary.POSITIVE)
|
||||||
assert nwGUI.mainStatus.docIcon._theCol == nwGUI.mainStatus.docIcon._colGood
|
assert nwGUI.mainStatus.docIcon.state == nwTrinary.POSITIVE
|
||||||
|
|
||||||
# Idle Status
|
# Idle Status
|
||||||
CONFIG.stopWhenIdle = False
|
CONFIG.stopWhenIdle = False
|
||||||
|
|||||||
Reference in New Issue
Block a user