v0.46.0: scrollbars lose their arrows; the thumb is embossed like a button
The app style now paints the scrollbars itself: the trough runs the full length with no arrow buttons, and the thumb gets the buttons' 4 px corners and emboss, with rims as tall in pixels as a button's however long the thumb. Bar thickness moved from QSS to the style's pixel metric, since any QSS rule on a scrollbar part makes Qt draw the whole bar, arrows included.
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
"""Round 80: scrollbars lose their arrow buttons, and the thumb is a button.
|
||||
|
||||
- No arrows: the trough runs the bar's full length and the arrow rects are
|
||||
empty, so nothing paints or hit-tests there.
|
||||
- The thumb gets the buttons' corner radius and emboss, with rims as tall in
|
||||
pixels as a button's, however long the thumb.
|
||||
- The bar's thickness comes from the UI scale through the style, not QSS
|
||||
(any QSS rule on a scrollbar part makes Qt draw the arrows itself).
|
||||
"""
|
||||
from PyQt6.QtCore import Qt
|
||||
from PyQt6.QtGui import QColor
|
||||
from PyQt6.QtWidgets import QPushButton, QScrollBar, QStyle, QStyleOptionSlider
|
||||
|
||||
from lintunes import theme
|
||||
from lintunes.gui.track_table import ClickToJumpScrollStyle
|
||||
|
||||
SC = QStyle.SubControl
|
||||
|
||||
|
||||
def _option(bar):
|
||||
opt = QStyleOptionSlider()
|
||||
bar.initStyleOption(opt)
|
||||
return opt
|
||||
|
||||
|
||||
def _bar(qapp, orientation=Qt.Orientation.Vertical):
|
||||
bar = QScrollBar(orientation)
|
||||
bar.setStyle(ClickToJumpScrollStyle())
|
||||
bar.setRange(0, 900)
|
||||
bar.setPageStep(100)
|
||||
bar.resize(14, 400) if orientation == Qt.Orientation.Vertical \
|
||||
else bar.resize(400, 14)
|
||||
return bar
|
||||
|
||||
|
||||
def test_no_arrow_buttons(qapp):
|
||||
bar = _bar(qapp)
|
||||
style, opt = bar.style(), _option(bar)
|
||||
cc = QStyle.ComplexControl.CC_ScrollBar
|
||||
assert style.subControlRect(cc, opt, SC.SC_ScrollBarAddLine, bar).isEmpty()
|
||||
assert style.subControlRect(cc, opt, SC.SC_ScrollBarSubLine, bar).isEmpty()
|
||||
assert style.subControlRect(cc, opt, SC.SC_ScrollBarGroove, bar) == opt.rect
|
||||
|
||||
|
||||
def test_thumb_spans_the_full_trough(qapp):
|
||||
for orientation in (Qt.Orientation.Vertical, Qt.Orientation.Horizontal):
|
||||
bar = _bar(qapp, orientation)
|
||||
style, cc = bar.style(), QStyle.ComplexControl.CC_ScrollBar
|
||||
bar.setValue(0)
|
||||
top = style.subControlRect(cc, _option(bar), SC.SC_ScrollBarSlider, bar)
|
||||
bar.setValue(900)
|
||||
end = style.subControlRect(cc, _option(bar), SC.SC_ScrollBarSlider, bar)
|
||||
if orientation == Qt.Orientation.Vertical:
|
||||
assert top.top() == 0 and end.bottom() == 399
|
||||
assert top.height() == 40 # 100 / (900 + 100) of 400
|
||||
else:
|
||||
assert top.left() == 0 and end.right() == 399
|
||||
|
||||
|
||||
def test_tiny_page_keeps_a_grabbable_thumb(qapp):
|
||||
bar = _bar(qapp)
|
||||
bar.setRange(0, 100000)
|
||||
rect = bar.style().subControlRect(QStyle.ComplexControl.CC_ScrollBar,
|
||||
_option(bar), SC.SC_ScrollBarSlider, bar)
|
||||
assert rect.height() == ClickToJumpScrollStyle.extent * 2
|
||||
|
||||
|
||||
def test_thickness_follows_ui_scale(qapp):
|
||||
class Prefs(dict):
|
||||
def get(self, key, default=None):
|
||||
return "large" if key == "ui_scale" else default
|
||||
before = ClickToJumpScrollStyle.extent
|
||||
try:
|
||||
theme.apply_theme(qapp, Prefs())
|
||||
assert ClickToJumpScrollStyle.extent == theme.UI_SCALES["large"]["scrollbar"]
|
||||
assert "QScrollBar" not in qapp.styleSheet()
|
||||
finally:
|
||||
ClickToJumpScrollStyle.extent = before
|
||||
|
||||
|
||||
def test_thumb_rims_match_a_real_button(qapp):
|
||||
qapp.setStyleSheet(theme.button_emboss_qss(QColor("#d0d0d0")))
|
||||
try:
|
||||
button = QPushButton("OK")
|
||||
height = button.sizeHint().height()
|
||||
assert abs(theme.button_rim_px(button.fontMetrics())
|
||||
- theme.EMBOSS_RIM_WIDTH * height) < 1
|
||||
finally:
|
||||
qapp.setStyleSheet("")
|
||||
|
||||
|
||||
def test_thumb_paints(qapp):
|
||||
bar = _bar(qapp)
|
||||
bar.setValue(450)
|
||||
image = bar.grab().toImage()
|
||||
thumb = bar.style().subControlRect(QStyle.ComplexControl.CC_ScrollBar,
|
||||
_option(bar), SC.SC_ScrollBarSlider, bar)
|
||||
trough = image.pixelColor(7, 5)
|
||||
middle = image.pixelColor(7, thumb.center().y())
|
||||
assert middle != trough
|
||||
Reference in New Issue
Block a user