Moved everything to templates.
- Fixed bug with QTreeView with checkable items. - Added JSON configurations for configurations. - Added tests for QTreeView. - Created a limited set of data.main
parent
491e693237
commit
e4d4e54ef5
41
README.md
41
README.md
|
@ -86,7 +86,46 @@ For an extensive view of screenshots of the theme, see the [gallery](assets/gall
|
|||
|
||||
# Customization
|
||||
|
||||
It's easy to design your own themes using `configure.py`. First, add the styles you want into [configure](/configure/), run configure with a list of styles you want to include...
|
||||
It's easy to design your own themes using `configure.py`. First, add the styles you want into [configure](/configure/), run configure with a list of styles you want to include.
|
||||
|
||||
**Template File**
|
||||
|
||||
```jsonc
|
||||
// NOTE: This is a custom JSON file, where lines leading
|
||||
// with `//` are removed. No other comments are valid.
|
||||
{
|
||||
// Main foreground color.
|
||||
"foreground": "#eff0f1",
|
||||
"foreground-light": "#ffffff",
|
||||
// Main background color.
|
||||
"background": "#31363b",
|
||||
"alternate-background": "#3b4045",
|
||||
// Lighter background color.
|
||||
"background-light": "#454a4f",
|
||||
"highlight": "#3daee9",
|
||||
"highlight-light": "#58d3ff",
|
||||
"highlight-dark": "#2a79a3",
|
||||
"alternate-hover": "#369cd1",
|
||||
"midtone": "#76797c",
|
||||
"midtone-light": "#b0b0b0",
|
||||
"midtone-dark": "#626568",
|
||||
"midtone:hover": "#8a8d8f", #9ea0a3
|
||||
"view:border": "#3A3939",
|
||||
// Color for checked widgets in QAbstractItemViews.
|
||||
"view:checked": "#334e5e",
|
||||
// Hover background color in QAbstractItemViews.
|
||||
"view:hover": "rgba(61, 173, 232, 0.1)",
|
||||
// Default background color inQAbstractItemViews.
|
||||
"view:background": "#232629",
|
||||
"tab:background": "#54575B",
|
||||
"tree": "#afafaf",
|
||||
"checkbox:disabled": "#c8c9ca",
|
||||
"button:disabled": "#454545",
|
||||
"close:hover": "#b37979",
|
||||
"close:pressed": "#b33e3e",
|
||||
"dock:float": "#a2a2a2"
|
||||
}
|
||||
```
|
||||
|
||||
# TOOD(ahuszagh) Add documentation.
|
||||
|
||||
|
|
4774
breeze_resources.py
4774
breeze_resources.py
File diff suppressed because it is too large
Load Diff
66
configure.py
66
configure.py
|
@ -6,50 +6,17 @@
|
|||
'''
|
||||
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
|
||||
home = os.path.dirname(os.path.realpath(__file__))
|
||||
# TODO(ahuszagh) Need a script to generate the qrc
|
||||
# Should be easy: styles.qss + assets.
|
||||
|
||||
# Assets should be easy.
|
||||
|
||||
colors_map = {
|
||||
'light': {},
|
||||
'dark': {
|
||||
# Might want to change the icon names as well to include the color changes.
|
||||
# First we need to stabilize the names.
|
||||
# Main theme colors.
|
||||
# -----------------
|
||||
# Note: these colors are inversed for light
|
||||
# themes.
|
||||
'foreground': '#eff0f1',
|
||||
'foreground-light': '#ffffff',
|
||||
'background': '#31363b',
|
||||
'alternate-background': '#3b4045',
|
||||
'background-light': '#454a4f',
|
||||
'highlight': '#3daee9',
|
||||
'highlight-light': '#58d3ff',
|
||||
'highlight-dark': '#2a79a3',
|
||||
'alternate-hover': '#369cd1',
|
||||
'midtone': '#76797c',
|
||||
'midtone-light': '#b0b0b0',
|
||||
'midtone-dark': '#626568',
|
||||
'midtone:hover': '#8a8d8f', #9ea0a3
|
||||
'view:border': '#3A3939',
|
||||
'view:checked': '#334e5e',
|
||||
'view:hover': 'rgba(61, 173, 232, 0.1)',
|
||||
'view:background': '#232629',
|
||||
'tab:background': '#54575B',
|
||||
'tree': '#afafaf',
|
||||
'checkbox:disabled': '#c8c9ca',
|
||||
'button:disabled': '#454545',
|
||||
'close:hover': '#b37979',
|
||||
'close:pressed': '#b33e3e',
|
||||
'dock:float': '#a2a2a2',
|
||||
},
|
||||
}
|
||||
|
||||
# List of all icons to configure.
|
||||
# TODO(ahuszagh) Change this to use templates
|
||||
# Should just be a list inside each key.
|
||||
# Replace ^0^ with ^foreground^, etc.
|
||||
icons = {
|
||||
# Arrows
|
||||
'down_arrow': {
|
||||
|
@ -163,10 +130,9 @@ def replace(contents, colors, color_map):
|
|||
contents = contents.replace(sub, color_map[color])
|
||||
return contents
|
||||
|
||||
def configure_icons(style):
|
||||
def configure_icons(style, color_map):
|
||||
'''Configure icons for a given style.'''
|
||||
|
||||
color_map = colors_map[style]
|
||||
for icon, extensions in icons.items():
|
||||
template = f'{home}/template/{icon}.svg.in'
|
||||
template_contents = open(template).read()
|
||||
|
@ -179,10 +145,9 @@ def configure_icons(style):
|
|||
with open(filename, 'w') as file:
|
||||
file.write(contents)
|
||||
|
||||
def configure_stylesheet(style):
|
||||
def configure_stylesheet(style, color_map):
|
||||
'''Configure the stylesheet for a given style.'''
|
||||
|
||||
color_map = colors_map[style]
|
||||
contents = open(f'{home}/template/stylesheet.qss.in').read()
|
||||
for key, color in color_map.items():
|
||||
contents = contents.replace(f'^{key}^', color)
|
||||
|
@ -190,18 +155,27 @@ def configure_stylesheet(style):
|
|||
with open(f'{home}/{style}/stylesheet.qss', 'w') as file:
|
||||
file.write(contents)
|
||||
|
||||
def configure_style(style):
|
||||
def configure_style(style, color_map):
|
||||
'''Configure the icons and stylesheet for a given style.'''
|
||||
|
||||
os.makedirs(f'{home}/{style}', exist_ok=True)
|
||||
configure_icons(style)
|
||||
configure_stylesheet(style)
|
||||
configure_icons(style, color_map)
|
||||
configure_stylesheet(style, color_map)
|
||||
|
||||
def configure(styles, resource):
|
||||
'''Configure all styles and write the files to a QRC file.'''
|
||||
|
||||
for style in styles:
|
||||
configure_style(style)
|
||||
# Note: we need comments for maintainability, so we
|
||||
# can annotate what works and the rationale, but
|
||||
# we don't want to prevent code from working without
|
||||
# a complex parser, so we do something very simple:
|
||||
# only remove lines starting with '//'.
|
||||
with open(f'{home}/configure/{style}.json') as file:
|
||||
lines = file.read().splitlines()
|
||||
lines = [i for i in lines if not i.strip().startswith('//')]
|
||||
color_map = json.loads('\n'.join(lines))
|
||||
configure_style(style, color_map)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# TODO(ahuszagh) Replace with argparse values.
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// NOTE: This is a custom JSON file, where lines leading
|
||||
// with `//` are removed. No other comments are valid.
|
||||
{
|
||||
"foreground": "#eff0f1",
|
||||
"foreground-light": "#ffffff",
|
||||
"background": "#31363b",
|
||||
"alternate-background": "#3b4045",
|
||||
"background-light": "#454a4f",
|
||||
"highlight": "#3daee9",
|
||||
"highlight-light": "#58d3ff",
|
||||
"highlight-dark": "#2a79a3",
|
||||
"alternate-hover": "#2F88B7",
|
||||
"midtone": "#76797c",
|
||||
"midtone-light": "#b0b0b0",
|
||||
"midtone-dark": "#626568",
|
||||
"midtone:hover": "#8a8d8f",
|
||||
"view:border": "#3A3939",
|
||||
"view:checked": "#334e5e",
|
||||
"view:hover": "rgba(61, 173, 232, 0.1)",
|
||||
"view:background": "#232629",
|
||||
"tab:background": "#54575B",
|
||||
"tree": "#afafaf",
|
||||
"checkbox:disabled": "#c8c9ca",
|
||||
"button:disabled": "#454545",
|
||||
"close:hover": "#b37979",
|
||||
"close:pressed": "#b33e3e",
|
||||
"dock:float": "#a2a2a2"
|
||||
}
|
|
@ -107,20 +107,25 @@ QGroupBox::title
|
|||
padding-right: 0.2em;
|
||||
}
|
||||
|
||||
QCheckBox::indicator
|
||||
QCheckBox::indicator,
|
||||
QTreeView::indicator
|
||||
{
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
QCheckBox::indicator:unchecked,
|
||||
QCheckBox::indicator:unchecked:focus
|
||||
QCheckBox::indicator:unchecked:focus,
|
||||
QTreeView::indicator:unchecked,
|
||||
QTreeView::indicator:unchecked:focus
|
||||
{
|
||||
border-image: url(:/dark/checkbox_unchecked_disabled.svg);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:unchecked:hover,
|
||||
QCheckBox::indicator:unchecked:pressed,
|
||||
QTreeView::indicator:unchecked:hover,
|
||||
QTreeView::indicator:unchecked:pressed,
|
||||
QGroupBox::indicator:unchecked,
|
||||
QGroupBox::indicator:unchecked:hover,
|
||||
QGroupBox::indicator:unchecked:focus,
|
||||
|
@ -131,6 +136,7 @@ QGroupBox::indicator:unchecked:pressed
|
|||
}
|
||||
|
||||
QCheckBox::indicator:checked,
|
||||
QTreeView::indicator:checked,
|
||||
QGroupBox::indicator:checked
|
||||
{
|
||||
border-image: url(:/dark/checkbox_checked.svg);
|
||||
|
@ -139,6 +145,9 @@ QGroupBox::indicator:checked
|
|||
QCheckBox::indicator:checked:hover,
|
||||
QCheckBox::indicator:checked:focus,
|
||||
QCheckBox::indicator:checked:pressed,
|
||||
QTreeView::indicator:checked:hover,
|
||||
QTreeView::indicator:checked:focus,
|
||||
QTreeView::indicator:checked:pressed,
|
||||
QGroupBox::indicator:checked:hover,
|
||||
QGroupBox::indicator:checked:focus,
|
||||
QGroupBox::indicator:checked:pressed
|
||||
|
@ -147,30 +156,37 @@ QGroupBox::indicator:checked:pressed
|
|||
border-image: url(:/dark/checkbox_checked.svg);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:indeterminate
|
||||
QCheckBox::indicator:indeterminate,
|
||||
QTreeView::indicator:indeterminate
|
||||
{
|
||||
border-image: url(:/dark/checkbox_indeterminate.svg);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:indeterminate:focus,
|
||||
QCheckBox::indicator:indeterminate:hover,
|
||||
QCheckBox::indicator:indeterminate:pressed
|
||||
QCheckBox::indicator:indeterminate:pressed,
|
||||
QTreeView::indicator:indeterminate:focus,
|
||||
QTreeView::indicator:indeterminate:hover,
|
||||
QTreeView::indicator:indeterminate:pressed
|
||||
{
|
||||
border-image: url(:/dark/checkbox_indeterminate.svg);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:indeterminate:disabled
|
||||
QCheckBox::indicator:indeterminate:disabled,
|
||||
QTreeView::indicator:indeterminate:disabled
|
||||
{
|
||||
border-image: url(:/dark/checkbox_indeterminate_disabled.svg);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:checked:disabled,
|
||||
QTreeView::indicator:checked:disabled,
|
||||
QGroupBox::indicator:checked:disabled
|
||||
{
|
||||
border-image: url(:/dark/checkbox_checked_disabled.svg);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:unchecked:disabled,
|
||||
QTreeView::indicator:unchecked:disabled,
|
||||
QGroupBox::indicator:unchecked:disabled
|
||||
{
|
||||
border-image: url(:/dark/checkbox_unchecked_disabled.svg);
|
||||
|
@ -1577,7 +1593,7 @@ QAbstractItemView::item
|
|||
|
||||
QAbstractItemView::item:pressed
|
||||
{
|
||||
background: #3daee9;
|
||||
background: #2a79a3;
|
||||
color: #eff0f1;
|
||||
}
|
||||
|
||||
|
@ -1603,8 +1619,8 @@ QAbstractItemView::item:selected:hover
|
|||
background: qlineargradient(
|
||||
x1: 0.5, y1: 0.5
|
||||
x2: 0.5, y2: 1,
|
||||
stop: 0 #369cd1,
|
||||
stop: 1 #369cd1
|
||||
stop: 0 #2F88B7,
|
||||
stop: 1 #2F88B7
|
||||
);
|
||||
color: #eff0f1;
|
||||
}
|
||||
|
|
|
@ -206,11 +206,17 @@ class Ui:
|
|||
item_2 = QtWidgets.QTreeWidgetItem(item_1)
|
||||
item_2.setText(0, 'subitem')
|
||||
item_3 = QtWidgets.QTreeWidgetItem(item_2, ['Row 2.1'])
|
||||
item_3.setFlags(item_3.flags() | QtCore.Qt.ItemIsUserCheckable)
|
||||
item_3.setCheckState(0, QtCore.Qt.Unchecked)
|
||||
item_4 = QtWidgets.QTreeWidgetItem(item_2, ['Row 2.2'])
|
||||
item_5 = QtWidgets.QTreeWidgetItem(item_4, ['Row 2.2.1'])
|
||||
item_6 = QtWidgets.QTreeWidgetItem(item_5, ['Row 2.2.1.1'])
|
||||
item_7 = QtWidgets.QTreeWidgetItem(item_5, ['Row 2.2.1.2'])
|
||||
item_7.setFlags(item_7.flags() | QtCore.Qt.ItemIsUserCheckable)
|
||||
item_7.setCheckState(0, QtCore.Qt.Checked)
|
||||
item_8 = QtWidgets.QTreeWidgetItem(item_2, ['Row 2.3'])
|
||||
item_8.setFlags(item_8.flags() | QtCore.Qt.ItemIsUserTristate)
|
||||
item_8.setCheckState(0, QtCore.Qt.PartiallyChecked)
|
||||
item_9 = QtWidgets.QTreeWidgetItem(self.treeWidget, ['Row 3'])
|
||||
item_10 = QtWidgets.QTreeWidgetItem(item_9, ['Row 3.1'])
|
||||
item_11 = QtWidgets.QTreeWidgetItem(self.treeWidget, ['Row 4'])
|
||||
|
|
|
@ -107,20 +107,25 @@ QGroupBox::title
|
|||
padding-right: 0.2em;
|
||||
}
|
||||
|
||||
QCheckBox::indicator
|
||||
QCheckBox::indicator,
|
||||
QTreeView::indicator
|
||||
{
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
QCheckBox::indicator:unchecked,
|
||||
QCheckBox::indicator:unchecked:focus
|
||||
QCheckBox::indicator:unchecked:focus,
|
||||
QTreeView::indicator:unchecked,
|
||||
QTreeView::indicator:unchecked:focus
|
||||
{
|
||||
border-image: url(:/^style^/checkbox_unchecked_disabled.svg);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:unchecked:hover,
|
||||
QCheckBox::indicator:unchecked:pressed,
|
||||
QTreeView::indicator:unchecked:hover,
|
||||
QTreeView::indicator:unchecked:pressed,
|
||||
QGroupBox::indicator:unchecked,
|
||||
QGroupBox::indicator:unchecked:hover,
|
||||
QGroupBox::indicator:unchecked:focus,
|
||||
|
@ -131,6 +136,7 @@ QGroupBox::indicator:unchecked:pressed
|
|||
}
|
||||
|
||||
QCheckBox::indicator:checked,
|
||||
QTreeView::indicator:checked,
|
||||
QGroupBox::indicator:checked
|
||||
{
|
||||
border-image: url(:/^style^/checkbox_checked.svg);
|
||||
|
@ -139,6 +145,9 @@ QGroupBox::indicator:checked
|
|||
QCheckBox::indicator:checked:hover,
|
||||
QCheckBox::indicator:checked:focus,
|
||||
QCheckBox::indicator:checked:pressed,
|
||||
QTreeView::indicator:checked:hover,
|
||||
QTreeView::indicator:checked:focus,
|
||||
QTreeView::indicator:checked:pressed,
|
||||
QGroupBox::indicator:checked:hover,
|
||||
QGroupBox::indicator:checked:focus,
|
||||
QGroupBox::indicator:checked:pressed
|
||||
|
@ -147,30 +156,37 @@ QGroupBox::indicator:checked:pressed
|
|||
border-image: url(:/^style^/checkbox_checked.svg);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:indeterminate
|
||||
QCheckBox::indicator:indeterminate,
|
||||
QTreeView::indicator:indeterminate
|
||||
{
|
||||
border-image: url(:/^style^/checkbox_indeterminate.svg);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:indeterminate:focus,
|
||||
QCheckBox::indicator:indeterminate:hover,
|
||||
QCheckBox::indicator:indeterminate:pressed
|
||||
QCheckBox::indicator:indeterminate:pressed,
|
||||
QTreeView::indicator:indeterminate:focus,
|
||||
QTreeView::indicator:indeterminate:hover,
|
||||
QTreeView::indicator:indeterminate:pressed
|
||||
{
|
||||
border-image: url(:/^style^/checkbox_indeterminate.svg);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:indeterminate:disabled
|
||||
QCheckBox::indicator:indeterminate:disabled,
|
||||
QTreeView::indicator:indeterminate:disabled
|
||||
{
|
||||
border-image: url(:/^style^/checkbox_indeterminate_disabled.svg);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:checked:disabled,
|
||||
QTreeView::indicator:checked:disabled,
|
||||
QGroupBox::indicator:checked:disabled
|
||||
{
|
||||
border-image: url(:/^style^/checkbox_checked_disabled.svg);
|
||||
}
|
||||
|
||||
QCheckBox::indicator:unchecked:disabled,
|
||||
QTreeView::indicator:unchecked:disabled,
|
||||
QGroupBox::indicator:unchecked:disabled
|
||||
{
|
||||
border-image: url(:/^style^/checkbox_unchecked_disabled.svg);
|
||||
|
@ -1577,7 +1593,7 @@ QAbstractItemView::item
|
|||
|
||||
QAbstractItemView::item:pressed
|
||||
{
|
||||
background: ^highlight^;
|
||||
background: ^highlight-dark^;
|
||||
color: ^foreground^;
|
||||
}
|
||||
|
||||
|
|
6
test.py
6
test.py
|
@ -491,11 +491,17 @@ def main(argv=None):
|
|||
item1 = QtWidgets.QTreeWidgetItem(tree1, ['Row 1'])
|
||||
item2 = QtWidgets.QTreeWidgetItem(tree1, ['Row 2'])
|
||||
item3 = QtWidgets.QTreeWidgetItem(item2, ['Row 2.1'])
|
||||
item3.setFlags(item3.flags() | QtCore.Qt.ItemIsUserCheckable)
|
||||
item3.setCheckState(0, QtCore.Qt.Unchecked)
|
||||
item4 = QtWidgets.QTreeWidgetItem(item2, ['Row 2.2'])
|
||||
item5 = QtWidgets.QTreeWidgetItem(item4, ['Row 2.2.1'])
|
||||
item6 = QtWidgets.QTreeWidgetItem(item5, ['Row 2.2.1.1'])
|
||||
item7 = QtWidgets.QTreeWidgetItem(item5, ['Row 2.2.1.2'])
|
||||
item7.setFlags(item7.flags() | QtCore.Qt.ItemIsUserCheckable)
|
||||
item7.setCheckState(0, QtCore.Qt.Checked)
|
||||
item8 = QtWidgets.QTreeWidgetItem(item2, ['Row 2.3'])
|
||||
item8.setFlags(item8.flags() | QtCore.Qt.ItemIsUserTristate)
|
||||
item8.setCheckState(0, QtCore.Qt.PartiallyChecked)
|
||||
item9 = QtWidgets.QTreeWidgetItem(tree1, ['Row 3'])
|
||||
item10 = QtWidgets.QTreeWidgetItem(item9, ['Row 3.1'])
|
||||
item11 = QtWidgets.QTreeWidgetItem(tree1, ['Row 4'])
|
||||
|
|
Loading…
Reference in New Issue