Update Screen: Cong cu, settings, them/Chinh sua task
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -38,6 +38,42 @@ from dataclasses import dataclass, asdict
|
||||
from string import Template
|
||||
|
||||
|
||||
def _chevron_asset(direction: str, color: str) -> str:
|
||||
"""Render (and cache on disk) a small chevron PNG for QComboBox/QSpinBox
|
||||
arrow subcontrols. QSS's ``image:`` property only accepts a resource or
|
||||
file path, never a live QPixmap — and once ``::drop-down``/``::up-button``/
|
||||
``::down-button`` are styled at all, Qt stops drawing its own built-in
|
||||
arrow, so without this the controls show no affordance whatsoever."""
|
||||
import hashlib
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
key = hashlib.md5(f"{direction}-{color}".encode()).hexdigest()[:10]
|
||||
path = Path(tempfile.gettempdir()) / "cowork_local_theme" / f"chevron_{key}.png"
|
||||
if not path.exists():
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
from PySide6.QtCore import QPointF, Qt
|
||||
from PySide6.QtGui import QColor, QPainter, QPixmap
|
||||
|
||||
size = 12
|
||||
pm = QPixmap(size, size)
|
||||
pm.fill(Qt.transparent)
|
||||
p = QPainter(pm)
|
||||
p.setRenderHint(QPainter.Antialiasing)
|
||||
pen = p.pen()
|
||||
pen.setColor(QColor(color))
|
||||
pen.setWidthF(1.6)
|
||||
pen.setCapStyle(Qt.RoundCap)
|
||||
pen.setJoinStyle(Qt.RoundJoin)
|
||||
p.setPen(pen)
|
||||
pts = ([QPointF(2.5, 4.5), QPointF(6, 8), QPointF(9.5, 4.5)] if direction == "down"
|
||||
else [QPointF(2.5, 7.5), QPointF(6, 4), QPointF(9.5, 7.5)])
|
||||
p.drawPolyline(pts)
|
||||
p.end()
|
||||
pm.save(str(path))
|
||||
return path.as_posix()
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Palette:
|
||||
"""Every colour and shape value the interface is allowed to use."""
|
||||
@@ -574,6 +610,27 @@ QSpinBox:focus, QDoubleSpinBox:focus { border: 1px solid $focus_ring; }
|
||||
QLineEdit:disabled, QPlainTextEdit:disabled, QTextEdit:disabled {
|
||||
background: $surface; color: $text_disabled;
|
||||
}
|
||||
/* Explicit up/down button geometry: once ANY spin-box subcontrol is styled,
|
||||
Qt uses exactly this rect for both painting AND hit-testing, so the
|
||||
clickable area can no longer drift from what's drawn (the previous
|
||||
unstyled default arrows misaligned their own click region at 125%/150%
|
||||
Windows display scaling — this pins both to the same rect instead). */
|
||||
QSpinBox::up-button, QDoubleSpinBox::up-button {
|
||||
subcontrol-origin: border; subcontrol-position: top right;
|
||||
width: 18px; height: 15px; border: none; background: transparent;
|
||||
}
|
||||
QSpinBox::down-button, QDoubleSpinBox::down-button {
|
||||
subcontrol-origin: border; subcontrol-position: bottom right;
|
||||
width: 18px; height: 15px; border: none; background: transparent;
|
||||
}
|
||||
QSpinBox::up-button:hover, QDoubleSpinBox::up-button:hover,
|
||||
QSpinBox::down-button:hover, QDoubleSpinBox::down-button:hover { background: $hover; }
|
||||
QSpinBox::up-button:pressed, QDoubleSpinBox::up-button:pressed,
|
||||
QSpinBox::down-button:pressed, QDoubleSpinBox::down-button:pressed { background: $active; }
|
||||
QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { image: url($chevron_up); width: 9px; height: 9px; }
|
||||
QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { image: url($chevron_down); width: 9px; height: 9px; }
|
||||
QSpinBox::up-arrow:disabled, QSpinBox::down-arrow:disabled,
|
||||
QDoubleSpinBox::up-arrow:disabled, QDoubleSpinBox::down-arrow:disabled { image: none; }
|
||||
|
||||
QTreeView::item, QListView::item, QTableView::item { padding: 4px 3px; border-radius: ${radius_sm}px; }
|
||||
QTreeView::item:hover, QListView::item:hover { background: $hover; }
|
||||
@@ -639,6 +696,8 @@ QComboBox:hover { background: $hover; }
|
||||
QComboBox:focus { border-color: $focus_ring; }
|
||||
QComboBox:disabled { color: $text_disabled; background: $surface; border-color: $border; }
|
||||
QComboBox::drop-down { border: none; width: 20px; }
|
||||
QComboBox::down-arrow { image: url($chevron_down); width: 10px; height: 10px; }
|
||||
QComboBox::down-arrow:disabled { image: none; }
|
||||
QComboBox QAbstractItemView {
|
||||
background: $overlay; color: $text; border: 1px solid $border_strong;
|
||||
border-radius: ${radius}px; padding: 4px; outline: none;
|
||||
@@ -825,7 +884,11 @@ def current_palette() -> Palette:
|
||||
|
||||
def stylesheet(theme: str) -> str:
|
||||
"""The application-wide Qt style sheet for ``theme``."""
|
||||
return _TEMPLATE.substitute(asdict(palette(theme)))
|
||||
p = palette(theme)
|
||||
values = asdict(p)
|
||||
values["chevron_down"] = _chevron_asset("down", p.text_muted)
|
||||
values["chevron_up"] = _chevron_asset("up", p.text_muted)
|
||||
return _TEMPLATE.substitute(values)
|
||||
|
||||
|
||||
def role_colors(theme: str) -> dict[str, str]:
|
||||
|
||||
Reference in New Issue
Block a user