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
Alex Huszagh 2021-07-15 21:09:27 -05:00
parent 491e693237
commit e4d4e54ef5
8 changed files with 2535 additions and 2446 deletions

View File

@ -86,7 +86,46 @@ For an extensive view of screenshots of the theme, see the [gallery](assets/gall
# Customization # 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. # TOOD(ahuszagh) Add documentation.

File diff suppressed because it is too large Load Diff

View File

@ -6,50 +6,17 @@
''' '''
import glob import glob
import json
import os import os
home = os.path.dirname(os.path.realpath(__file__)) home = os.path.dirname(os.path.realpath(__file__))
# TODO(ahuszagh) Need a script to generate the qrc # TODO(ahuszagh) Need a script to generate the qrc
# Should be easy: styles.qss + assets. # Should be easy: styles.qss + assets.
# Assets should be easy. # List of all icons to configure.
# TODO(ahuszagh) Change this to use templates
colors_map = { # Should just be a list inside each key.
'light': {}, # Replace ^0^ with ^foreground^, etc.
'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',
},
}
icons = { icons = {
# Arrows # Arrows
'down_arrow': { 'down_arrow': {
@ -163,10 +130,9 @@ def replace(contents, colors, color_map):
contents = contents.replace(sub, color_map[color]) contents = contents.replace(sub, color_map[color])
return contents return contents
def configure_icons(style): def configure_icons(style, color_map):
'''Configure icons for a given style.''' '''Configure icons for a given style.'''
color_map = colors_map[style]
for icon, extensions in icons.items(): for icon, extensions in icons.items():
template = f'{home}/template/{icon}.svg.in' template = f'{home}/template/{icon}.svg.in'
template_contents = open(template).read() template_contents = open(template).read()
@ -179,10 +145,9 @@ def configure_icons(style):
with open(filename, 'w') as file: with open(filename, 'w') as file:
file.write(contents) file.write(contents)
def configure_stylesheet(style): def configure_stylesheet(style, color_map):
'''Configure the stylesheet for a given style.''' '''Configure the stylesheet for a given style.'''
color_map = colors_map[style]
contents = open(f'{home}/template/stylesheet.qss.in').read() contents = open(f'{home}/template/stylesheet.qss.in').read()
for key, color in color_map.items(): for key, color in color_map.items():
contents = contents.replace(f'^{key}^', color) contents = contents.replace(f'^{key}^', color)
@ -190,18 +155,27 @@ def configure_stylesheet(style):
with open(f'{home}/{style}/stylesheet.qss', 'w') as file: with open(f'{home}/{style}/stylesheet.qss', 'w') as file:
file.write(contents) file.write(contents)
def configure_style(style): def configure_style(style, color_map):
'''Configure the icons and stylesheet for a given style.''' '''Configure the icons and stylesheet for a given style.'''
os.makedirs(f'{home}/{style}', exist_ok=True) os.makedirs(f'{home}/{style}', exist_ok=True)
configure_icons(style) configure_icons(style, color_map)
configure_stylesheet(style) configure_stylesheet(style, color_map)
def configure(styles, resource): def configure(styles, resource):
'''Configure all styles and write the files to a QRC file.''' '''Configure all styles and write the files to a QRC file.'''
for style in styles: 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__': if __name__ == '__main__':
# TODO(ahuszagh) Replace with argparse values. # TODO(ahuszagh) Replace with argparse values.

View File

@ -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"
}

View File

@ -107,20 +107,25 @@ QGroupBox::title
padding-right: 0.2em; padding-right: 0.2em;
} }
QCheckBox::indicator QCheckBox::indicator,
QTreeView::indicator
{ {
width: 1em; width: 1em;
height: 1em; height: 1em;
} }
QCheckBox::indicator:unchecked, 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); border-image: url(:/dark/checkbox_unchecked_disabled.svg);
} }
QCheckBox::indicator:unchecked:hover, QCheckBox::indicator:unchecked:hover,
QCheckBox::indicator:unchecked:pressed, QCheckBox::indicator:unchecked:pressed,
QTreeView::indicator:unchecked:hover,
QTreeView::indicator:unchecked:pressed,
QGroupBox::indicator:unchecked, QGroupBox::indicator:unchecked,
QGroupBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:hover,
QGroupBox::indicator:unchecked:focus, QGroupBox::indicator:unchecked:focus,
@ -131,6 +136,7 @@ QGroupBox::indicator:unchecked:pressed
} }
QCheckBox::indicator:checked, QCheckBox::indicator:checked,
QTreeView::indicator:checked,
QGroupBox::indicator:checked QGroupBox::indicator:checked
{ {
border-image: url(:/dark/checkbox_checked.svg); border-image: url(:/dark/checkbox_checked.svg);
@ -139,6 +145,9 @@ QGroupBox::indicator:checked
QCheckBox::indicator:checked:hover, QCheckBox::indicator:checked:hover,
QCheckBox::indicator:checked:focus, QCheckBox::indicator:checked:focus,
QCheckBox::indicator:checked:pressed, QCheckBox::indicator:checked:pressed,
QTreeView::indicator:checked:hover,
QTreeView::indicator:checked:focus,
QTreeView::indicator:checked:pressed,
QGroupBox::indicator:checked:hover, QGroupBox::indicator:checked:hover,
QGroupBox::indicator:checked:focus, QGroupBox::indicator:checked:focus,
QGroupBox::indicator:checked:pressed QGroupBox::indicator:checked:pressed
@ -147,30 +156,37 @@ QGroupBox::indicator:checked:pressed
border-image: url(:/dark/checkbox_checked.svg); border-image: url(:/dark/checkbox_checked.svg);
} }
QCheckBox::indicator:indeterminate QCheckBox::indicator:indeterminate,
QTreeView::indicator:indeterminate
{ {
border-image: url(:/dark/checkbox_indeterminate.svg); border-image: url(:/dark/checkbox_indeterminate.svg);
} }
QCheckBox::indicator:indeterminate:focus, QCheckBox::indicator:indeterminate:focus,
QCheckBox::indicator:indeterminate:hover, 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); 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); border-image: url(:/dark/checkbox_indeterminate_disabled.svg);
} }
QCheckBox::indicator:checked:disabled, QCheckBox::indicator:checked:disabled,
QTreeView::indicator:checked:disabled,
QGroupBox::indicator:checked:disabled QGroupBox::indicator:checked:disabled
{ {
border-image: url(:/dark/checkbox_checked_disabled.svg); border-image: url(:/dark/checkbox_checked_disabled.svg);
} }
QCheckBox::indicator:unchecked:disabled, QCheckBox::indicator:unchecked:disabled,
QTreeView::indicator:unchecked:disabled,
QGroupBox::indicator:unchecked:disabled QGroupBox::indicator:unchecked:disabled
{ {
border-image: url(:/dark/checkbox_unchecked_disabled.svg); border-image: url(:/dark/checkbox_unchecked_disabled.svg);
@ -1577,7 +1593,7 @@ QAbstractItemView::item
QAbstractItemView::item:pressed QAbstractItemView::item:pressed
{ {
background: #3daee9; background: #2a79a3;
color: #eff0f1; color: #eff0f1;
} }
@ -1603,8 +1619,8 @@ QAbstractItemView::item:selected:hover
background: qlineargradient( background: qlineargradient(
x1: 0.5, y1: 0.5 x1: 0.5, y1: 0.5
x2: 0.5, y2: 1, x2: 0.5, y2: 1,
stop: 0 #369cd1, stop: 0 #2F88B7,
stop: 1 #369cd1 stop: 1 #2F88B7
); );
color: #eff0f1; color: #eff0f1;
} }

View File

@ -206,11 +206,17 @@ class Ui:
item_2 = QtWidgets.QTreeWidgetItem(item_1) item_2 = QtWidgets.QTreeWidgetItem(item_1)
item_2.setText(0, 'subitem') item_2.setText(0, 'subitem')
item_3 = QtWidgets.QTreeWidgetItem(item_2, ['Row 2.1']) 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_4 = QtWidgets.QTreeWidgetItem(item_2, ['Row 2.2'])
item_5 = QtWidgets.QTreeWidgetItem(item_4, ['Row 2.2.1']) item_5 = QtWidgets.QTreeWidgetItem(item_4, ['Row 2.2.1'])
item_6 = QtWidgets.QTreeWidgetItem(item_5, ['Row 2.2.1.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 = 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 = 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_9 = QtWidgets.QTreeWidgetItem(self.treeWidget, ['Row 3'])
item_10 = QtWidgets.QTreeWidgetItem(item_9, ['Row 3.1']) item_10 = QtWidgets.QTreeWidgetItem(item_9, ['Row 3.1'])
item_11 = QtWidgets.QTreeWidgetItem(self.treeWidget, ['Row 4']) item_11 = QtWidgets.QTreeWidgetItem(self.treeWidget, ['Row 4'])

View File

@ -107,20 +107,25 @@ QGroupBox::title
padding-right: 0.2em; padding-right: 0.2em;
} }
QCheckBox::indicator QCheckBox::indicator,
QTreeView::indicator
{ {
width: 1em; width: 1em;
height: 1em; height: 1em;
} }
QCheckBox::indicator:unchecked, 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); border-image: url(:/^style^/checkbox_unchecked_disabled.svg);
} }
QCheckBox::indicator:unchecked:hover, QCheckBox::indicator:unchecked:hover,
QCheckBox::indicator:unchecked:pressed, QCheckBox::indicator:unchecked:pressed,
QTreeView::indicator:unchecked:hover,
QTreeView::indicator:unchecked:pressed,
QGroupBox::indicator:unchecked, QGroupBox::indicator:unchecked,
QGroupBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:hover,
QGroupBox::indicator:unchecked:focus, QGroupBox::indicator:unchecked:focus,
@ -131,6 +136,7 @@ QGroupBox::indicator:unchecked:pressed
} }
QCheckBox::indicator:checked, QCheckBox::indicator:checked,
QTreeView::indicator:checked,
QGroupBox::indicator:checked QGroupBox::indicator:checked
{ {
border-image: url(:/^style^/checkbox_checked.svg); border-image: url(:/^style^/checkbox_checked.svg);
@ -139,6 +145,9 @@ QGroupBox::indicator:checked
QCheckBox::indicator:checked:hover, QCheckBox::indicator:checked:hover,
QCheckBox::indicator:checked:focus, QCheckBox::indicator:checked:focus,
QCheckBox::indicator:checked:pressed, QCheckBox::indicator:checked:pressed,
QTreeView::indicator:checked:hover,
QTreeView::indicator:checked:focus,
QTreeView::indicator:checked:pressed,
QGroupBox::indicator:checked:hover, QGroupBox::indicator:checked:hover,
QGroupBox::indicator:checked:focus, QGroupBox::indicator:checked:focus,
QGroupBox::indicator:checked:pressed QGroupBox::indicator:checked:pressed
@ -147,30 +156,37 @@ QGroupBox::indicator:checked:pressed
border-image: url(:/^style^/checkbox_checked.svg); border-image: url(:/^style^/checkbox_checked.svg);
} }
QCheckBox::indicator:indeterminate QCheckBox::indicator:indeterminate,
QTreeView::indicator:indeterminate
{ {
border-image: url(:/^style^/checkbox_indeterminate.svg); border-image: url(:/^style^/checkbox_indeterminate.svg);
} }
QCheckBox::indicator:indeterminate:focus, QCheckBox::indicator:indeterminate:focus,
QCheckBox::indicator:indeterminate:hover, 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); 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); border-image: url(:/^style^/checkbox_indeterminate_disabled.svg);
} }
QCheckBox::indicator:checked:disabled, QCheckBox::indicator:checked:disabled,
QTreeView::indicator:checked:disabled,
QGroupBox::indicator:checked:disabled QGroupBox::indicator:checked:disabled
{ {
border-image: url(:/^style^/checkbox_checked_disabled.svg); border-image: url(:/^style^/checkbox_checked_disabled.svg);
} }
QCheckBox::indicator:unchecked:disabled, QCheckBox::indicator:unchecked:disabled,
QTreeView::indicator:unchecked:disabled,
QGroupBox::indicator:unchecked:disabled QGroupBox::indicator:unchecked:disabled
{ {
border-image: url(:/^style^/checkbox_unchecked_disabled.svg); border-image: url(:/^style^/checkbox_unchecked_disabled.svg);
@ -1577,7 +1593,7 @@ QAbstractItemView::item
QAbstractItemView::item:pressed QAbstractItemView::item:pressed
{ {
background: ^highlight^; background: ^highlight-dark^;
color: ^foreground^; color: ^foreground^;
} }

View File

@ -491,11 +491,17 @@ def main(argv=None):
item1 = QtWidgets.QTreeWidgetItem(tree1, ['Row 1']) item1 = QtWidgets.QTreeWidgetItem(tree1, ['Row 1'])
item2 = QtWidgets.QTreeWidgetItem(tree1, ['Row 2']) item2 = QtWidgets.QTreeWidgetItem(tree1, ['Row 2'])
item3 = QtWidgets.QTreeWidgetItem(item2, ['Row 2.1']) 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']) item4 = QtWidgets.QTreeWidgetItem(item2, ['Row 2.2'])
item5 = QtWidgets.QTreeWidgetItem(item4, ['Row 2.2.1']) item5 = QtWidgets.QTreeWidgetItem(item4, ['Row 2.2.1'])
item6 = QtWidgets.QTreeWidgetItem(item5, ['Row 2.2.1.1']) item6 = QtWidgets.QTreeWidgetItem(item5, ['Row 2.2.1.1'])
item7 = QtWidgets.QTreeWidgetItem(item5, ['Row 2.2.1.2']) 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 = 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']) item9 = QtWidgets.QTreeWidgetItem(tree1, ['Row 3'])
item10 = QtWidgets.QTreeWidgetItem(item9, ['Row 3.1']) item10 = QtWidgets.QTreeWidgetItem(item9, ['Row 3.1'])
item11 = QtWidgets.QTreeWidgetItem(tree1, ['Row 4']) item11 = QtWidgets.QTreeWidgetItem(tree1, ['Row 4'])