Files
archived-Reclass/tools/test_hover.py
IChooseYou 7efe740ec1 fix: hover invisible when theme.hover == background, remove CSS on QMenuBar
Move hover color fixup into Theme::fromJson so all consumers get a
visible hover automatically. Remove duplicate lighter(130) fallback
from applyGlobalTheme. Replace QMenuBar CSS with QPalette so
MenuBarStyle QProxyStyle is not bypassed. Add PE_PanelMenuBar and
CE_MenuBarEmptyArea suppression so Fusion never paints over the
title bar background.
2026-02-22 08:58:57 -07:00

160 lines
4.9 KiB
Python

"""
Structural hover test: validate that all themes produce visible hover colors
and that the QProxyStyle code handles the required control elements.
No pixel sampling — checks theme JSON values and source code patterns.
"""
import json
import os
import re
import sys
def hex_to_rgb(h):
h = h.lstrip('#')
return tuple(int(h[i:i+2], 16) for i in (0, 2, 4))
def color_dist(c1, c2):
return sum(abs(a - b) for a, b in zip(c1, c2))
def lighter_130(rgb):
"""Approximate Qt's QColor::lighter(130) for dark grays."""
r, g, b = rgb
return (min(255, int(r * 1.3) + 1),
min(255, int(g * 1.3) + 1),
min(255, int(b * 1.3) + 1))
def load_themes():
themes = {}
theme_dir = os.path.join(os.path.dirname(__file__),
'..', 'src', 'themes', 'defaults')
if not os.path.isdir(theme_dir):
return themes
for name in os.listdir(theme_dir):
if name.endswith('.json'):
with open(os.path.join(theme_dir, name)) as f:
themes[name] = json.load(f)
return themes
def test_hover_visibility(themes):
"""Every theme must have hover visually distinct from background.
If raw values are identical, Theme::fromJson applies lighter(130)."""
ok = True
for name, data in sorted(themes.items()):
bg = hex_to_rgb(data['background'])
hover = hex_to_rgb(data['hover'])
dist = color_dist(bg, hover)
if dist < 20:
# fromJson will fix this — verify the fix produces sufficient contrast
fixed = lighter_130(bg)
fixed_dist = color_dist(bg, fixed)
if fixed_dist < 15:
print(f" FAIL: {name}: hover==bg and lighter(130) still too close "
f"(dist={fixed_dist})")
ok = False
else:
print(f" OK: {name}: hover==bg, fromJson fixup -> "
f"dist {dist}->{fixed_dist}")
else:
print(f" OK: {name}: hover distinct (dist={dist})")
return ok
def test_proxystyle_handlers():
"""Verify MenuBarStyle handles CE_MenuBarItem, CE_MenuItem, CE_MenuBarEmptyArea."""
src = os.path.join(os.path.dirname(__file__), '..', 'src', 'main.cpp')
with open(src) as f:
code = f.read()
required = {
'CE_MenuBarItem': r'element\s*==\s*CE_MenuBarItem',
'CE_MenuItem': r'element\s*==\s*CE_MenuItem',
'CE_MenuBarEmptyArea': r'element\s*==\s*CE_MenuBarEmptyArea',
'State_Selected': r'State_Selected',
'QPalette::Mid': r'QPalette::Mid',
}
ok = True
for label, pattern in required.items():
if re.search(pattern, code):
print(f" OK: MenuBarStyle handles {label}")
else:
print(f" FAIL: MenuBarStyle missing {label}")
ok = False
return ok
def test_no_menubar_css():
"""Verify no CSS stylesheet is set on QMenuBar (would bypass QProxyStyle)."""
src_dir = os.path.join(os.path.dirname(__file__), '..', 'src')
ok = True
for root, _, files in os.walk(src_dir):
for fname in files:
if not fname.endswith('.cpp'):
continue
path = os.path.join(root, fname)
with open(path, encoding='utf-8', errors='replace') as f:
for i, line in enumerate(f, 1):
# Check for menuBar/m_menuBar stylesheet calls
if ('menuBar' in line or 'm_menuBar' in line) and \
'setStyleSheet' in line:
print(f" FAIL: CSS on QMenuBar at {fname}:{i}: "
f"{line.strip()}")
ok = False
if ok:
print(" OK: No CSS on QMenuBar")
return ok
def test_hover_fixup_in_fromjson():
"""Verify Theme::fromJson applies the hover fixup."""
src = os.path.join(os.path.dirname(__file__),
'..', 'src', 'themes', 'theme.cpp')
with open(src) as f:
code = f.read()
if 'lighter(130)' in code and 't.hover' in code:
print(" OK: Theme::fromJson has hover fixup")
return True
else:
print(" FAIL: Theme::fromJson missing hover fixup")
return False
def main():
themes = load_themes()
if not themes:
print("FAIL: No theme files found")
return 1
all_ok = True
print("--- Test 1: Hover visibility across themes ---")
all_ok &= test_hover_visibility(themes)
print("\n--- Test 2: QProxyStyle handles required elements ---")
all_ok &= test_proxystyle_handlers()
print("\n--- Test 3: No CSS on QMenuBar ---")
all_ok &= test_no_menubar_css()
print("\n--- Test 4: Theme::fromJson hover fixup ---")
all_ok &= test_hover_fixup_in_fromjson()
print(f"\n{'='*50}")
if all_ok:
print("ALL HOVER TESTS PASSED")
return 0
else:
print("SOME HOVER TESTS FAILED")
return 1
if __name__ == '__main__':
sys.exit(main())