mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
Add stylesheet for QMenu (#2122)
* Give QMenu cursor: pointer
* Darken border colors in dark theme
* Refactor cursor: pointer event filter
* Add QMenu stylesheet
* Remove min-width for QMenu item
* Add QMenuBar styles
with increased height for touchscreen users and more visible highlight color.
* Fix type
* Revert "Add QMenuBar styles"
This reverts commit 6ae405a073
.
* Remove strong border from QMenu checkbox style
* Keep highlight color consistent
* Adjust highlight-bg
* Increase horizontal padding and adjust checkbox margin
* Introduce border-faint var and make default border brighter in dark mode
* Fix 1px move on hover and make highlight color more subtle
* Remove win10 styles
because the properties are set in the other stylesheets anyway.
* Fix bottom border of QMenuBar not showing underneath entries
* Remove unused import
* Make border-faint one shade darker in light theme
This commit is contained in:
parent
3d47c9547a
commit
dc67ed9952
5 changed files with 89 additions and 69 deletions
|
@ -345,26 +345,19 @@ class AnkiApp(QApplication):
|
||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
def eventFilter(self, src: Any, evt: QEvent) -> bool:
|
def eventFilter(self, src: Any, evt: QEvent) -> bool:
|
||||||
if evt.type() == QEvent.Type.HoverEnter:
|
pointer_classes = (
|
||||||
if (
|
QPushButton,
|
||||||
(
|
QCheckBox,
|
||||||
isinstance(
|
QRadioButton,
|
||||||
src,
|
QMenu,
|
||||||
(
|
# classes with PyQt5 compatibility proxy
|
||||||
QPushButton,
|
without_qt5_compat_wrapper(QToolButton),
|
||||||
QCheckBox,
|
without_qt5_compat_wrapper(QTabBar),
|
||||||
QRadioButton,
|
)
|
||||||
# classes with PyQt5 compatibility proxy
|
if evt.type() in [QEvent.Type.Enter, QEvent.Type.HoverEnter]:
|
||||||
without_qt5_compat_wrapper(QToolButton),
|
if (isinstance(src, pointer_classes) and src.isEnabled()) or (
|
||||||
without_qt5_compat_wrapper(QTabBar),
|
isinstance(src, without_qt5_compat_wrapper(QComboBox))
|
||||||
),
|
and not src.isEditable()
|
||||||
)
|
|
||||||
)
|
|
||||||
and src.isEnabled()
|
|
||||||
or (
|
|
||||||
isinstance(src, without_qt5_compat_wrapper(QComboBox))
|
|
||||||
and not src.isEditable()
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
self.setOverrideCursor(QCursor(Qt.CursorShape.PointingHandCursor))
|
self.setOverrideCursor(QCursor(Qt.CursorShape.PointingHandCursor))
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -16,7 +16,7 @@ a.deck:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.deck td {
|
tr.deck td {
|
||||||
border-bottom: 1px solid var(--border-subtle);
|
border-bottom: 1px solid var(--border-faint);
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.top-level-drag-row td {
|
tr.top-level-drag-row td {
|
||||||
|
|
|
@ -28,7 +28,8 @@ qlineargradient(
|
||||||
|
|
||||||
def general_styles(tm: ThemeManager) -> str:
|
def general_styles(tm: ThemeManager) -> str:
|
||||||
return f"""
|
return f"""
|
||||||
QFrame {{
|
QFrame,
|
||||||
|
QWidget {{
|
||||||
background: none;
|
background: none;
|
||||||
}}
|
}}
|
||||||
QPushButton,
|
QPushButton,
|
||||||
|
@ -38,7 +39,7 @@ QLineEdit,
|
||||||
QListWidget,
|
QListWidget,
|
||||||
QTreeWidget,
|
QTreeWidget,
|
||||||
QListView {{
|
QListView {{
|
||||||
border: 1px solid {tm.var(colors.BORDER)};
|
border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
|
||||||
border-radius: {tm.var(props.BORDER_RADIUS)};
|
border-radius: {tm.var(props.BORDER_RADIUS)};
|
||||||
}}
|
}}
|
||||||
QLineEdit {{
|
QLineEdit {{
|
||||||
|
@ -58,6 +59,47 @@ QSpinBox {{
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def menu_styles(tm: ThemeManager) -> str:
|
||||||
|
return f"""
|
||||||
|
QMenuBar {{
|
||||||
|
border-bottom: 1px solid {tm.var(colors.BORDER_FAINT)};
|
||||||
|
}}
|
||||||
|
QMenuBar::item {{
|
||||||
|
background-color: transparent;
|
||||||
|
padding: 2px 4px;
|
||||||
|
border-radius: {tm.var(props.BORDER_RADIUS)};
|
||||||
|
}}
|
||||||
|
QMenuBar::item:selected {{
|
||||||
|
background-color: {tm.var(colors.CANVAS_ELEVATED)};
|
||||||
|
}}
|
||||||
|
QMenu {{
|
||||||
|
background-color: {tm.var(colors.CANVAS_OVERLAY)};
|
||||||
|
border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
|
||||||
|
padding: 4px;
|
||||||
|
}}
|
||||||
|
QMenu::item {{
|
||||||
|
background-color: transparent;
|
||||||
|
padding: 3px 14px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}}
|
||||||
|
QMenu::item:selected {{
|
||||||
|
background-color: {tm.var(colors.CANVAS_INSET)};
|
||||||
|
color: {tm.var(colors.HIGHLIGHT_FG)};
|
||||||
|
border-radius: {tm.var(props.BORDER_RADIUS)};
|
||||||
|
}}
|
||||||
|
QMenu::separator {{
|
||||||
|
height: 1px;
|
||||||
|
background: {tm.var(colors.BORDER_SUBTLE)};
|
||||||
|
margin: 0 8px 4px 8px;
|
||||||
|
}}
|
||||||
|
QMenu::indicator {{
|
||||||
|
border: 1px solid {tm.var(colors.BORDER)};
|
||||||
|
margin-left: 6px;
|
||||||
|
margin-right: -6px;
|
||||||
|
}}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def button_styles(tm: ThemeManager) -> str:
|
def button_styles(tm: ThemeManager) -> str:
|
||||||
return f"""
|
return f"""
|
||||||
QPushButton {{
|
QPushButton {{
|
||||||
|
@ -184,7 +226,7 @@ QTabWidget::pane {{
|
||||||
top: -15px;
|
top: -15px;
|
||||||
padding-top: 1em;
|
padding-top: 1em;
|
||||||
background: {tm.var(colors.CANVAS_ELEVATED)};
|
background: {tm.var(colors.CANVAS_ELEVATED)};
|
||||||
border: 1px solid {tm.var(colors.BORDER)};
|
border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
|
||||||
border-radius: {tm.var(props.BORDER_RADIUS)};
|
border-radius: {tm.var(props.BORDER_RADIUS)};
|
||||||
}}
|
}}
|
||||||
QTabWidget::tab-bar {{
|
QTabWidget::tab-bar {{
|
||||||
|
@ -196,7 +238,7 @@ QTabBar::tab {{
|
||||||
min-width: 8ex;
|
min-width: 8ex;
|
||||||
}}
|
}}
|
||||||
QTabBar::tab {{
|
QTabBar::tab {{
|
||||||
border: 1px solid {tm.var(colors.BORDER)};
|
border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
|
||||||
}}
|
}}
|
||||||
QTabBar::tab:first {{
|
QTabBar::tab:first {{
|
||||||
border-top-{tm.left()}-radius: {tm.var(props.BORDER_RADIUS)};
|
border-top-{tm.left()}-radius: {tm.var(props.BORDER_RADIUS)};
|
||||||
|
@ -225,7 +267,7 @@ def table_styles(tm: ThemeManager) -> str:
|
||||||
return f"""
|
return f"""
|
||||||
QTableView {{
|
QTableView {{
|
||||||
border-radius: {tm.var(props.BORDER_RADIUS)};
|
border-radius: {tm.var(props.BORDER_RADIUS)};
|
||||||
gridline-color: {tm.var(colors.BORDER)};
|
gridline-color: {tm.var(colors.BORDER_SUBTLE)};
|
||||||
selection-background-color: {tm.var(colors.SELECTION_BG)};
|
selection-background-color: {tm.var(colors.SELECTION_BG)};
|
||||||
selection-color: {tm.var(colors.SELECTION_FG)};
|
selection-color: {tm.var(colors.SELECTION_FG)};
|
||||||
}}
|
}}
|
||||||
|
@ -233,7 +275,7 @@ QHeaderView {{
|
||||||
background: {tm.var(colors.CANVAS)};
|
background: {tm.var(colors.CANVAS)};
|
||||||
}}
|
}}
|
||||||
QHeaderView::section {{
|
QHeaderView::section {{
|
||||||
border: 1px solid {tm.var(colors.BORDER)};
|
border: 1px solid {tm.var(colors.BORDER_SUBTLE)};
|
||||||
background: {
|
background: {
|
||||||
button_gradient(
|
button_gradient(
|
||||||
tm.var(colors.BUTTON_GRADIENT_START),
|
tm.var(colors.BUTTON_GRADIENT_START),
|
||||||
|
@ -261,19 +303,19 @@ QHeaderView::section:hover {{
|
||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
QHeaderView::section:first {{
|
QHeaderView::section:first {{
|
||||||
border-left: 1px solid {tm.var(colors.BORDER)};
|
border-left: 1px solid {tm.var(colors.BORDER_SUBTLE)};
|
||||||
border-top-left-radius: {tm.var(props.BORDER_RADIUS)};
|
border-top-left-radius: {tm.var(props.BORDER_RADIUS)};
|
||||||
}}
|
}}
|
||||||
QHeaderView::section:!first {{
|
QHeaderView::section:!first {{
|
||||||
border-left: none;
|
border-left: none;
|
||||||
}}
|
}}
|
||||||
QHeaderView::section:last {{
|
QHeaderView::section:last {{
|
||||||
border-right: 1px solid {tm.var(colors.BORDER)};
|
border-right: 1px solid {tm.var(colors.BORDER_SUBTLE)};
|
||||||
border-top-right-radius: {tm.var(props.BORDER_RADIUS)};
|
border-top-right-radius: {tm.var(props.BORDER_RADIUS)};
|
||||||
}}
|
}}
|
||||||
QHeaderView::section:only-one {{
|
QHeaderView::section:only-one {{
|
||||||
border-left: 1px solid {tm.var(colors.BORDER)};
|
border-left: 1px solid {tm.var(colors.BORDER_SUBTLE)};
|
||||||
border-right: 1px solid {tm.var(colors.BORDER)};
|
border-right: 1px solid {tm.var(colors.BORDER_SUBTLE)};
|
||||||
border-top-left-radius: {tm.var(props.BORDER_RADIUS)};
|
border-top-left-radius: {tm.var(props.BORDER_RADIUS)};
|
||||||
border-top-right-radius: {tm.var(props.BORDER_RADIUS)};
|
border-top-right-radius: {tm.var(props.BORDER_RADIUS)};
|
||||||
}}
|
}}
|
||||||
|
@ -374,16 +416,16 @@ QRadioButton {{
|
||||||
margin: 2px 0;
|
margin: 2px 0;
|
||||||
}}
|
}}
|
||||||
QCheckBox::indicator,
|
QCheckBox::indicator,
|
||||||
QRadioButton::indicator {{
|
QRadioButton::indicator,
|
||||||
|
QMenu::indicator {{
|
||||||
border: 1px solid {tm.var(colors.BUTTON_BORDER)};
|
border: 1px solid {tm.var(colors.BUTTON_BORDER)};
|
||||||
|
border-radius: {tm.var(props.BORDER_RADIUS)};
|
||||||
background: {tm.var(colors.CANVAS_INSET)};
|
background: {tm.var(colors.CANVAS_INSET)};
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
}}
|
}}
|
||||||
QCheckBox::indicator {{
|
QRadioButton::indicator,
|
||||||
border-radius: {tm.var(props.BORDER_RADIUS)};
|
QMenu::indicator:exclusive {{
|
||||||
}}
|
|
||||||
QRadioButton::indicator {{
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}}
|
}}
|
||||||
QCheckBox::indicator:hover,
|
QCheckBox::indicator:hover,
|
||||||
|
@ -395,7 +437,8 @@ QRadioButton::indicator:checked:hover {{
|
||||||
height: 14px;
|
height: 14px;
|
||||||
}}
|
}}
|
||||||
QCheckBox::indicator:checked,
|
QCheckBox::indicator:checked,
|
||||||
QRadioButton::indicator:checked {{
|
QRadioButton::indicator:checked,
|
||||||
|
QMenu::indicator:checked {{
|
||||||
image: url({tm.themed_icon("mdi:check")});
|
image: url({tm.themed_icon("mdi:check")});
|
||||||
}}
|
}}
|
||||||
QCheckBox::indicator:indeterminate {{
|
QCheckBox::indicator:indeterminate {{
|
||||||
|
@ -445,20 +488,3 @@ QScrollBar::sub-line {{
|
||||||
background: none;
|
background: none;
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def win10_styles(tm: ThemeManager) -> str:
|
|
||||||
return f"""
|
|
||||||
/* day mode is missing a bottom border; background must be
|
|
||||||
also set for border to apply */
|
|
||||||
QMenuBar {{
|
|
||||||
border-bottom: 1px solid {tm.var(colors.BORDER)};
|
|
||||||
background: {tm.var(colors.CANVAS) if tm.night_mode else "white"};
|
|
||||||
}}
|
|
||||||
|
|
||||||
/* qt bug? setting the above changes the browser sidebar
|
|
||||||
to white as well, so set it back */
|
|
||||||
QTreeWidget {{
|
|
||||||
background: {tm.var(colors.CANVAS)};
|
|
||||||
}}
|
|
||||||
"""
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ from __future__ import annotations
|
||||||
|
|
||||||
import enum
|
import enum
|
||||||
import os
|
import os
|
||||||
import platform
|
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
@ -229,29 +228,27 @@ class ThemeManager:
|
||||||
checkbox_styles,
|
checkbox_styles,
|
||||||
combobox_styles,
|
combobox_styles,
|
||||||
general_styles,
|
general_styles,
|
||||||
|
menu_styles,
|
||||||
scrollbar_styles,
|
scrollbar_styles,
|
||||||
spinbox_styles,
|
spinbox_styles,
|
||||||
table_styles,
|
table_styles,
|
||||||
tabwidget_styles,
|
tabwidget_styles,
|
||||||
win10_styles,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
buf += "".join(
|
buf += "".join(
|
||||||
[
|
[
|
||||||
general_styles(self),
|
general_styles(self),
|
||||||
button_styles(self),
|
button_styles(self),
|
||||||
|
checkbox_styles(self),
|
||||||
|
menu_styles(self),
|
||||||
combobox_styles(self),
|
combobox_styles(self),
|
||||||
tabwidget_styles(self),
|
tabwidget_styles(self),
|
||||||
table_styles(self),
|
table_styles(self),
|
||||||
spinbox_styles(self),
|
spinbox_styles(self),
|
||||||
checkbox_styles(self),
|
|
||||||
scrollbar_styles(self),
|
scrollbar_styles(self),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
if is_win and platform.release() == "10":
|
|
||||||
buf += win10_styles(self)
|
|
||||||
|
|
||||||
# allow addons to modify the styling
|
# allow addons to modify the styling
|
||||||
buf = gui_hooks.style_did_init(buf)
|
buf = gui_hooks.style_did_init(buf)
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,8 @@ $vars: (
|
||||||
dark: palette(darkgray, 6),
|
dark: palette(darkgray, 6),
|
||||||
),
|
),
|
||||||
overlay: (
|
overlay: (
|
||||||
light: white,
|
light: palette(lightgray, 0),
|
||||||
dark: black,
|
dark: palette(darkgray, 5),
|
||||||
),
|
),
|
||||||
code: (
|
code: (
|
||||||
light: white,
|
light: white,
|
||||||
|
@ -67,16 +67,20 @@ $vars: (
|
||||||
border: (
|
border: (
|
||||||
default: (
|
default: (
|
||||||
light: palette(lightgray, 6),
|
light: palette(lightgray, 6),
|
||||||
dark: palette(darkgray, 7),
|
dark: palette(darkgray, 4),
|
||||||
),
|
|
||||||
subtle: (
|
|
||||||
light: palette(lightgray, 5),
|
|
||||||
dark: palette(darkgray, 6),
|
|
||||||
),
|
),
|
||||||
strong: (
|
strong: (
|
||||||
light: palette(lightgray, 9),
|
light: palette(lightgray, 9),
|
||||||
dark: palette(darkgray, 1),
|
dark: palette(darkgray, 1),
|
||||||
),
|
),
|
||||||
|
subtle: (
|
||||||
|
light: palette(lightgray, 5),
|
||||||
|
dark: palette(darkgray, 7),
|
||||||
|
),
|
||||||
|
faint: (
|
||||||
|
light: palette(lightgray, 4),
|
||||||
|
dark: palette(darkgray, 6),
|
||||||
|
),
|
||||||
focus: (
|
focus: (
|
||||||
light: palette(blue, 5),
|
light: palette(blue, 5),
|
||||||
dark: palette(blue, 5),
|
dark: palette(blue, 5),
|
||||||
|
@ -269,8 +273,8 @@ $vars: (
|
||||||
),
|
),
|
||||||
highlight: (
|
highlight: (
|
||||||
bg: (
|
bg: (
|
||||||
light: palette(blue, 3),
|
light: color.scale(palette(blue, 3), $alpha: -33%),
|
||||||
dark: palette(blue, 4),
|
dark: color.scale(palette(blue, 4), $alpha: -33%),
|
||||||
),
|
),
|
||||||
fg: (
|
fg: (
|
||||||
light: black,
|
light: black,
|
||||||
|
|
Loading…
Reference in a new issue