diff --git a/README.md b/README.md index ab61e6c..1a7d1c2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -Qt-Material -=========== +# Qt-Material + This is another stylesheet for **PySide6**, **PySide2**, **PyQt5** and **PyQt6**, which looks like Material Design (close enough). ![GitHub top language](https://img.shields.io/github/languages/top/un-gcpds/qt-material) @@ -32,6 +32,7 @@ And light: * [Change theme in runtime](#change-theme-in-runtime) * [Export theme](#export-theme) * [Density scale](#density-scale) + * [Troubleshoots](#troubleshoots) ## Install @@ -200,8 +201,13 @@ Then, the current stylesheet can be extended just with: ```python -apply_stylesheet(app, theme='light_blue.xml') +apply_stylesheet(app, theme='light_blue.xml', css_file='custom.css') +``` +The stylesheet can also be changed on runtime by: + + +```python stylesheet = app.styleSheet() with open('custom.css') as file: app.setStyleSheet(stylesheet + file.read().format(**os.environ)) @@ -382,7 +388,7 @@ apply_stylesheet(app, 'default', invert_secondary=False, extra=extra) ### QMenu -`QMenu` has multiple rendering for each Qt backend, and for each operating system. Even can be related with the style, like [fusion](https://doc.qt.io/qt-5/qtquickcontrols2-fusion.html). Then, the `extra` argument also supports`QMenu` parameters to configure this widgest for specific combinations. +`QMenu` has multiple rendering for each Qt backend, and for each operating system. Even can be related with the style, like [fusion](https://doc.qt.io/qt-5/qtquickcontrols2-fusion.html). Then, the `extra` argument also supports`QMenu` parameters to configure this widgest for specific combinations. This options are not affected by **density scale**. ```python diff --git a/docs/source/notebooks/readme.ipynb b/docs/source/notebooks/readme.ipynb index 9c7b352..6eefbd6 100644 --- a/docs/source/notebooks/readme.ipynb +++ b/docs/source/notebooks/readme.ipynb @@ -4,8 +4,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Qt-Material\n", - "===========\n", + "# Qt-Material\n", + "\n", "This is another stylesheet for **PySide6**, **PySide2**, **PyQt5** and **PyQt6**, which looks like Material Design (close enough).\n", "\n", "![GitHub top language](https://img.shields.io/github/languages/top/un-gcpds/qt-material)\n", diff --git a/docs/source/notebooks/readme.rst b/docs/source/notebooks/readme.rst index c6c6727..6c0a449 100644 --- a/docs/source/notebooks/readme.rst +++ b/docs/source/notebooks/readme.rst @@ -41,6 +41,7 @@ Navigation - `Change theme in runtime <#change-theme-in-runtime>`__ - `Export theme <#export-theme>`__ - `Density scale <#density-scale>`__ +- `Troubleshoots <#troubleshoots>`__ Install ------- @@ -238,8 +239,12 @@ Then, the current stylesheet can be extended just with: .. code:: ipython3 - apply_stylesheet(app, theme='light_blue.xml') - + apply_stylesheet(app, theme='light_blue.xml', css_file='custom.css') + +The stylesheet can also be changed on runtime by: + +.. code:: ipython3 + stylesheet = app.styleSheet() with open('custom.css') as file: app.setStyleSheet(stylesheet + file.read().format(**os.environ)) @@ -456,7 +461,8 @@ QMenu operating system. Even can be related with the style, like `fusion `__. Then, the ``extra`` argument also supports\ ``QMenu`` parameters to configure -this widgest for specific combinations. +this widgest for specific combinations. This options are not affected by +**density scale**. .. code:: ipython3 diff --git a/examples/full_features/main.py b/examples/full_features/main.py index 0c7eebf..546b8de 100644 --- a/examples/full_features/main.py +++ b/examples/full_features/main.py @@ -69,6 +69,7 @@ extra = { # 'padding': '50px 50px 50px 50px', # top, right, bottom, left # } + ######################################################################## class RuntimeStylesheets(QMainWindow, QtStyleTools): # ---------------------------------------------------------------------- diff --git a/examples/full_features/main_window.ui b/examples/full_features/main_window.ui index 8c290b6..127af0c 100644 --- a/examples/full_features/main_window.ui +++ b/examples/full_features/main_window.ui @@ -21,7 +21,7 @@ QTabWidget::West - 0 + 1 @@ -2980,6 +2980,115 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
QtWebEngineWidgets/QWebEngineView
+ + tabWidget_4 + groupBox + pushButton + pushButton_3 + pushButton_6 + pushButton_7 + pushButton_11 + pushButton_5 + pushButton_4 + groupBox_2 + groupBox_3 + radioButton + radioButton_4 + radioButton_2 + radioButton_3 + checkBox + checkBox_3 + checkBox_4 + checkBox_2 + pushButton_file_dialog + pushButton_folder_dialog + tabWidget_3 + tabWidget + horizontalSlider_2 + verticalSlider_2 + treeWidget + listWidget_2 + tableWidget + tabWidget_2 + pushButton_18 + pushButton_20 + pushButton_19 + pushButton_23 + pushButton_22 + pushButton_21 + comboBox + comboBox_7 + comboBox_5 + comboBox_2 + spinBox + doubleSpinBox + lineEdit + lineEdit_3 + comboBox_3 + comboBox_6 + comboBox_4 + spinBox_2 + doubleSpinBox_2 + lineEdit_2 + dateEdit_2 + listWidget + textEdit + plainTextEdit + pushButton_2 + pushButton_12 + pushButton_13 + pushButton_14 + pushButton_15 + pushButton_16 + pushButton_17 + radioButton_7 + radioButton_5 + radioButton_6 + radioButton_8 + checkBox_5 + checkBox_6 + checkBox_7 + checkBox_8 + pushButton_8 + pushButton_9 + pushButton_10 + pushButton_24 + pushButton_25 + pushButton_26 + pushButton_27 + radioButton_12 + radioButton_10 + radioButton_11 + radioButton_9 + checkBox_10 + checkBox_11 + checkBox_12 + checkBox_9 + timeEdit + dateEdit + dateTimeEdit + keySequenceEdit + calendarWidget + groupBox_7 + pushButton_28 + pushButton_32 + lineEdit_4 + pushButton_30 + pushButton_33 + pushButton_29 + pushButton_31 + doubleSpinBox_3 + timeEdit_2 + dateTimeEdit_2 + comboBox_8 + tabWidget_6 + fontComboBox + tabWidget_5 + tabWidget_7 + spinBox_3 + tableWidget_2 + lineEdit_5 + diff --git a/examples/full_features/my_theme.xml b/examples/full_features/my_theme.xml index 70d5bb3..09d02a5 100644 --- a/examples/full_features/my_theme.xml +++ b/examples/full_features/my_theme.xml @@ -1,9 +1,9 @@ - #ff4081 - #ff79b0 + #00bcd4 + #62efff #f5f5f5 - #ffffff - #e6e6e6 + #e6e6e6 + #ffffff #3c3c3c #555555 diff --git a/examples/full_features/screenshots/dark.gif b/examples/full_features/screenshots/dark.gif new file mode 100644 index 0000000..0ad284b Binary files /dev/null and b/examples/full_features/screenshots/dark.gif differ diff --git a/examples/full_features/screenshots/dark_amber.png b/examples/full_features/screenshots/dark_amber.png new file mode 100644 index 0000000..380be9d Binary files /dev/null and b/examples/full_features/screenshots/dark_amber.png differ diff --git a/examples/full_features/screenshots/dark_blue.png b/examples/full_features/screenshots/dark_blue.png new file mode 100644 index 0000000..4245725 Binary files /dev/null and b/examples/full_features/screenshots/dark_blue.png differ diff --git a/examples/full_features/screenshots/dark_cyan.png b/examples/full_features/screenshots/dark_cyan.png new file mode 100644 index 0000000..f566d3d Binary files /dev/null and b/examples/full_features/screenshots/dark_cyan.png differ diff --git a/examples/full_features/screenshots/dark_lightgreen.png b/examples/full_features/screenshots/dark_lightgreen.png new file mode 100644 index 0000000..077fedd Binary files /dev/null and b/examples/full_features/screenshots/dark_lightgreen.png differ diff --git a/examples/full_features/screenshots/dark_pink.png b/examples/full_features/screenshots/dark_pink.png new file mode 100644 index 0000000..ea84fe8 Binary files /dev/null and b/examples/full_features/screenshots/dark_pink.png differ diff --git a/examples/full_features/screenshots/dark_purple.png b/examples/full_features/screenshots/dark_purple.png new file mode 100644 index 0000000..c4c6984 Binary files /dev/null and b/examples/full_features/screenshots/dark_purple.png differ diff --git a/examples/full_features/screenshots/dark_red.png b/examples/full_features/screenshots/dark_red.png new file mode 100644 index 0000000..0a2008e Binary files /dev/null and b/examples/full_features/screenshots/dark_red.png differ diff --git a/examples/full_features/screenshots/dark_teal.png b/examples/full_features/screenshots/dark_teal.png new file mode 100644 index 0000000..f5ad8f4 Binary files /dev/null and b/examples/full_features/screenshots/dark_teal.png differ diff --git a/examples/full_features/screenshots/dark_yellow.png b/examples/full_features/screenshots/dark_yellow.png new file mode 100644 index 0000000..96f4620 Binary files /dev/null and b/examples/full_features/screenshots/dark_yellow.png differ diff --git a/examples/full_features/screenshots/light.gif b/examples/full_features/screenshots/light.gif new file mode 100644 index 0000000..5681298 Binary files /dev/null and b/examples/full_features/screenshots/light.gif differ diff --git a/examples/full_features/screenshots/light_amber.png b/examples/full_features/screenshots/light_amber.png new file mode 100644 index 0000000..41c7a32 Binary files /dev/null and b/examples/full_features/screenshots/light_amber.png differ diff --git a/examples/full_features/screenshots/light_blue.png b/examples/full_features/screenshots/light_blue.png new file mode 100644 index 0000000..c3713a0 Binary files /dev/null and b/examples/full_features/screenshots/light_blue.png differ diff --git a/examples/full_features/screenshots/light_blue_500.png b/examples/full_features/screenshots/light_blue_500.png new file mode 100644 index 0000000..1b4c727 Binary files /dev/null and b/examples/full_features/screenshots/light_blue_500.png differ diff --git a/examples/full_features/screenshots/light_cyan.png b/examples/full_features/screenshots/light_cyan.png new file mode 100644 index 0000000..b2d6642 Binary files /dev/null and b/examples/full_features/screenshots/light_cyan.png differ diff --git a/examples/full_features/screenshots/light_cyan_500.png b/examples/full_features/screenshots/light_cyan_500.png new file mode 100644 index 0000000..0f29412 Binary files /dev/null and b/examples/full_features/screenshots/light_cyan_500.png differ diff --git a/examples/full_features/screenshots/light_lightgreen.png b/examples/full_features/screenshots/light_lightgreen.png new file mode 100644 index 0000000..daa40ac Binary files /dev/null and b/examples/full_features/screenshots/light_lightgreen.png differ diff --git a/examples/full_features/screenshots/light_lightgreen_500.png b/examples/full_features/screenshots/light_lightgreen_500.png new file mode 100644 index 0000000..b704070 Binary files /dev/null and b/examples/full_features/screenshots/light_lightgreen_500.png differ diff --git a/examples/full_features/screenshots/light_orange.png b/examples/full_features/screenshots/light_orange.png new file mode 100644 index 0000000..bed3808 Binary files /dev/null and b/examples/full_features/screenshots/light_orange.png differ diff --git a/examples/full_features/screenshots/light_pink.png b/examples/full_features/screenshots/light_pink.png new file mode 100644 index 0000000..fb58ac1 Binary files /dev/null and b/examples/full_features/screenshots/light_pink.png differ diff --git a/examples/full_features/screenshots/light_pink_500.png b/examples/full_features/screenshots/light_pink_500.png new file mode 100644 index 0000000..d474001 Binary files /dev/null and b/examples/full_features/screenshots/light_pink_500.png differ diff --git a/examples/full_features/screenshots/light_purple.png b/examples/full_features/screenshots/light_purple.png new file mode 100644 index 0000000..62c0533 Binary files /dev/null and b/examples/full_features/screenshots/light_purple.png differ diff --git a/examples/full_features/screenshots/light_purple_500.png b/examples/full_features/screenshots/light_purple_500.png new file mode 100644 index 0000000..7e91e1d Binary files /dev/null and b/examples/full_features/screenshots/light_purple_500.png differ diff --git a/examples/full_features/screenshots/light_red.png b/examples/full_features/screenshots/light_red.png new file mode 100644 index 0000000..38a8da4 Binary files /dev/null and b/examples/full_features/screenshots/light_red.png differ diff --git a/examples/full_features/screenshots/light_red_500.png b/examples/full_features/screenshots/light_red_500.png new file mode 100644 index 0000000..b968f63 Binary files /dev/null and b/examples/full_features/screenshots/light_red_500.png differ diff --git a/examples/full_features/screenshots/light_teal.png b/examples/full_features/screenshots/light_teal.png new file mode 100644 index 0000000..d414fcd Binary files /dev/null and b/examples/full_features/screenshots/light_teal.png differ diff --git a/examples/full_features/screenshots/light_teal_500.png b/examples/full_features/screenshots/light_teal_500.png new file mode 100644 index 0000000..d8c1fba Binary files /dev/null and b/examples/full_features/screenshots/light_teal_500.png differ diff --git a/examples/full_features/screenshots/light_yellow.png b/examples/full_features/screenshots/light_yellow.png new file mode 100644 index 0000000..a7a5c68 Binary files /dev/null and b/examples/full_features/screenshots/light_yellow.png differ diff --git a/qt_material/__init__.py b/qt_material/__init__.py index d1f4609..b2c5be5 100644 --- a/qt_material/__init__.py +++ b/qt_material/__init__.py @@ -344,7 +344,9 @@ def opacity(theme, value=0.5): # ---------------------------------------------------------------------- -def density(value, density_scale, border=0, scale=1, density_interval=4): +def density( + value, density_scale, border=0, scale=1, density_interval=4, min_=4 +): """""" # https://material.io/develop/web/supporting/density if isinstance(value, str) and value.startswith('@'): @@ -360,8 +362,8 @@ def density(value, density_scale, border=0, scale=1, density_interval=4): value + (density_interval * int(density_scale)) - (border * 2) ) * scale - if density < 0: - density = 0 + if density <= 0: + density = min_ return density diff --git a/qt_material/material.css.template b/qt_material/material.css.template index b473f5e..3841d9a 100644 --- a/qt_material/material.css.template +++ b/qt_material/material.css.template @@ -140,14 +140,16 @@ QTreeView, QListView, QLineEdit, QComboBox { + color: {{primaryTextColor}}; padding-left: {{16|density(density_scale)}}px; border-radius: 0px; - background-color: {{secondaryColor}}; - border-width: 0 0 2px 0; border-radius: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; height: {{36|density(density_scale, border=2)}}px; + background-color: {{secondaryColor|opacity(0.75)}}; + border: 2px solid {{secondaryTextColor|opacity(0.2)}}; + border-width: 0 0 2px 0; } QPlainTextEdit { @@ -168,9 +170,9 @@ QSpinBox:disabled, QDoubleSpinBox:disabled, QTextEdit:disabled, QLineEdit:disabled { - color: {{primaryColor|opacity(0.2)}}; - background-color: {{secondaryColor|opacity(0.75)}}; - border: 2px solid {{primaryColor|opacity(0.2)}}; + color: {{secondaryTextColor|opacity(0.2)}}; + background-color: {{secondaryColor|opacity(0.3)}}; + border: 2px solid {{secondaryColor}}; border-width: 0 0 2px 0; padding: 0px {{16|density(density_scale)}}px; border-radius: 0px; @@ -183,20 +185,21 @@ QLineEdit:disabled { /* QComboBox */ QComboBox { - color: {{primaryColor}}; - border: 1px solid {{primaryColor}}; - border-width: 0 0 2px 0; - background-color: {{secondaryColor}}; + color: {{primaryTextColor}}; + border: 2px solid {{primaryColor}}; border-radius: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px; height: {{36|density(density_scale, border=2)}}px; + background-color: {{secondaryColor|opacity(0.75)}}; + border: 2px solid {{secondaryTextColor|opacity(0.2)}}; + border-width: 0 0 2px 0; } QComboBox:disabled { - color: {{primaryColor|opacity(0.2)}}; - background-color: {{secondaryColor|opacity(0.75)}}; - border-bottom: 2px solid {{primaryColor|opacity(0.2)}}; + color: {{secondaryTextColor|opacity(0.2)}}; + background-color: {{secondaryColor|opacity(0.3)}}; + border-bottom: 2px solid {{secondaryColor}}; } QComboBox::drop-down { @@ -206,6 +209,10 @@ QComboBox::drop-down { } QComboBox::down-arrow { + image: url(icon:/active/downarrow.svg); + margin-right: {{12|density(density_scale)}}px; +} +QComboBox::down-arrow:focus { image: url(icon:/primary/downarrow.svg); margin-right: {{12|density(density_scale)}}px; } @@ -222,12 +229,12 @@ QComboBox QAbstractItemView { } QComboBox[frame='false'] { - color: {{primaryColor}}; + color: {{secondaryTextColor}}; background-color: transparent; border: 1px solid transparent; } QComboBox[frame='false']:disabled { - color: {{primaryColor|opacity(0.2)}}; + color: {{secondaryTextColor|opacity(0.2)}}; } /* ------------------------------------------------------------------------ */ @@ -239,7 +246,7 @@ QSpinBox::up-button { subcontrol-origin: border; subcontrol-position: top right; width: 20px; - image: url(icon:/primary/uparrow.svg); + image: url(icon:/active/uparrow.svg); border-width: 0px; margin-right: 5px; } @@ -256,7 +263,7 @@ QSpinBox::down-button { subcontrol-origin: border; subcontrol-position: bottom right; width: 20px; - image: url(icon:/primary/downarrow.svg); + image: url(icon:/active/downarrow.svg); border-width: 0px; border-top-width: 0; margin-right: 5px; @@ -283,8 +290,6 @@ QPushButton { {% elif button_shape=='rounded' %} border-radius: {{36|density(density_scale, border=2, scale=0.5)}}px; {% endif %} - - } QPushButton:checked, @@ -301,7 +306,7 @@ QPushButton:flat { } QPushButton:flat:hover { - background-color: {{primaryColor|opacity(0.2)}}; + background-color: {{primaryColor|opacity(0.1)}}; } QPushButton:flat:pressed, @@ -331,6 +336,22 @@ QPushButton:checked:disabled { border-color: {{secondaryLightColor}}; } +QToolButton:focus, +QPushButton:focus { + background-color: {{primaryColor|opacity(0.2)}}; +} + +QPushButton:checked:focus, +QPushButton:pressed:focus { + background-color: {{primaryColor|opacity(0.8)}}; +} + +QPushButton:flat:focus { + border: none; + background-color: {{primaryColor|opacity(0.2)}}; +} + + /* ------------------------------------------------------------------------ */ /* QTabBar */ @@ -1327,3 +1348,41 @@ QMenuBar QToolButton { border-image: url(icon:/primary/rightarrow2.svg); background-color: transparent; } + +/* ------------------------------------------------------------------------ */ +/* Focus */ + +QDateTimeEdit:focus, +QSpinBox:focus, +QDoubleSpinBox:focus, +QLineEdit:focus, +QComboBox:focus { + color: {{primaryColor}}; + border: 2px solid {{primaryColor}}; + border-width: 0 0 2px 0; + +} + +QDateTimeEdit::up-button:focus, +QDoubleSpinBox::up-button:focus, +QSpinBox::up-button:focus { + image: url(icon:/primary/uparrow.svg); +} + +QDateTimeEdit::down-button:focus, +QDoubleSpinBox::down-button:focus, +QSpinBox::down-button:focus { + image: url(icon:/primary/downarrow.svg); +} + +QMenu::indicator:focus, +QListView::indicator:focus, +QTableWidget::indicator:focus, +QRadioButton::indicator:focus { + background-color: {{primaryColor|opacity(0.2)}}; + border-radius: {{14|density(density_scale)}}px; + } + +QCheckBox::indicator:focus { + background-color: {{primaryColor|opacity(0.2)}}; + } diff --git a/qt_material/resources/generate.py b/qt_material/resources/generate.py index e4b25cb..623bcbf 100644 --- a/qt_material/resources/generate.py +++ b/qt_material/resources/generate.py @@ -11,7 +11,14 @@ class ResourseGenerator: """""" # ---------------------------------------------------------------------- - def __init__(self, primary, secondary, disabled, source, parent='theme'): + def __init__( + self, + primary, + secondary, + disabled, + source, + parent='theme', + ): """Constructor""" if parent.startswith('/'): @@ -21,9 +28,12 @@ class ResourseGenerator: else: self.index = os.path.join(RESOURCES_PATH, parent) + active = '#707070' + self.contex = [ (os.path.join(self.index, 'disabled'), disabled), (os.path.join(self.index, 'primary'), primary), + (os.path.join(self.index, 'active'), active), ] self.source = source @@ -47,7 +57,8 @@ class ResourseGenerator: for folder, color in self.contex: new_content = self.replace_color(content_original, color) new_content = self.replace_color( - new_content, self.secondary, '#ff0000') + new_content, self.secondary, '#ff0000' + ) file_to_write = os.path.join(folder, icon) with open(file_to_write, 'w') as file_output: @@ -56,15 +67,19 @@ class ResourseGenerator: # ---------------------------------------------------------------------- def replace_color(self, content, replace, color='#0000ff'): """""" - colors = [color] + [''.join(list(color)[:i] + - ['\\\n'] + list(color)[i:]) for i in range(1, 7)] + colors = [color] + [ + ''.join(list(color)[:i] + ['\\\n'] + list(color)[i:]) + for i in range(1, 7) + ] for c in colors: content = content.replace(c, replace) replace = '#ffffff00' color = '#000000' - colors = [color] + [''.join(list(color)[:i] + - ['\\\n'] + list(color)[i:]) for i in range(1, 7)] + colors = [color] + [ + ''.join(list(color)[:i] + ['\\\n'] + list(color)[i:]) + for i in range(1, 7) + ] for c in colors: content = content.replace(c, replace)