diff --git a/assets/breeze_dark_branchless.png b/assets/breeze_dark_branchless.png new file mode 100644 index 0000000..c52b2e1 Binary files /dev/null and b/assets/breeze_dark_branchless.png differ diff --git a/assets/breeze_light_branchless.png b/assets/breeze_light_branchless.png new file mode 100644 index 0000000..89b1139 Binary files /dev/null and b/assets/breeze_light_branchless.png differ diff --git a/example/branchless/README.md b/example/branchless/README.md new file mode 100644 index 0000000..56d2f01 --- /dev/null +++ b/example/branchless/README.md @@ -0,0 +1,29 @@ +branchless +========== + +This contains an example widget for a `QTreeView` where the branch indicators are hidden. In order to add these branchless indicators to your project, copy this directory into the [extension](/extension) folder, and then configure with (adding any additional resources or styles as you see fit): + +```bash +python configure.py --extensions=branchless --resource custom.qrc +``` + +## Example + +

Dark

+
+ Breeze Dark theme using branchless indicators for Windows +
+ + +

Light

+
+ Breeze Light theme using branchless indicators for Windows +
diff --git a/example/branchless/application.py b/example/branchless/application.py new file mode 100644 index 0000000..deccd06 --- /dev/null +++ b/example/branchless/application.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python +# +# The MIT License (MIT) +# +# Copyright (c) <2022-Present> +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the 'Software'), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import os +import sys + +HOME = os.path.dirname(os.path.realpath(__file__)) +sys.path.insert(0, os.path.dirname(HOME)) + +import widgets +import shared + +parser = shared.create_parser() +args, unknown = shared.parse_args(parser) +QtCore, QtGui, QtWidgets = shared.import_qt(args) +compat = shared.get_compat_definitions(args) +ICON_MAP = shared.get_icon_map(args, compat) + + +def set_stylesheet(args, app, compat): + '''Set the application stylesheet.''' + + if args.stylesheet != 'native': + resource_format = shared.get_resources(args) + qt_path = shared.get_stylesheet(resource_format) + ext_path = os.path.join(HOME, 'stylesheet.qss.in') + stylesheet = shared.read_qtext_file(qt_path, compat) + stylesheet += '\n' + open(ext_path, 'r').read() + app.setStyleSheet(stylesheet) + + +def get_treeviews(parent, depth=1000): + for child in parent.children(): + if isinstance(child, QtWidgets.QTreeView): + yield child + elif depth > 0: + yield from get_treeviews(child, depth - 1) + + +def main(): + 'Application entry point' + + # this is mostly a hack to get simplify using the same UI but with + # minimal additions to modify the stylesheet + app, window = shared.setup_app(args, unknown, compat) + + # setup ui + ui = widgets.Ui() + ui.setup(window) + ui.bt_delay_popup.addActions([ + ui.actionAction, + ui.actionAction_C + ]) + ui.bt_instant_popup.addActions([ + ui.actionAction, + ui.actionAction_C + ]) + ui.bt_menu_button_popup.addActions([ + ui.actionAction, + ui.actionAction_C + ]) + window.setWindowTitle('Sample BreezeStyleSheets application.') + + # Add event triggers + ui.actionAction.triggered.connect(ui.about) + ui.actionAction_C.triggered.connect(ui.critical) + + # tabify dock widgets to show bug #6 + window.tabifyDockWidget(ui.dockWidget1, ui.dockWidget2) + + # add object names to all the widgets so we don't have to recreate a UI + for tree in get_treeviews(window): + tree.setObjectName("branchless") + + set_stylesheet(args, app, compat) + return shared.exec_app(args, app, window, compat) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/example/branchless/stylesheet.qss.in b/example/branchless/stylesheet.qss.in new file mode 100644 index 0000000..0c7185c --- /dev/null +++ b/example/branchless/stylesheet.qss.in @@ -0,0 +1,43 @@ +/** + * BRANCHLESS QTREEVIEW STYLESHEET + * ------------------------------- + */ + +/** + * We disable all the border images for the branch indicators, while + * keeping the images for the branch closed/open and hover variants + * the default. + */ +QTreeView[objectName="branchless"]::branch:has-siblings +{ + border-image: none; + image: none; +} + +QTreeView[objectName="branchless"]::branch:!has-siblings +{ + border-image: none; + image: none; +} + +QTreeView[objectName="branchless"]::branch:has-siblings:adjoins-item +{ + border-image: none; +} + +QTreeView[objectName="branchless"]::branch:!has-children:!has-siblings:adjoins-item +{ + border-image: none; +} + +QTreeView[objectName="branchless"]::branch:has-children:!has-siblings:closed, +QTreeView[objectName="branchless"]::branch:open:has-children:!has-siblings +{ + border-image: none; +} + +QTreeView[objectName="branchless"]::branch:closed:has-children:has-siblings, +QTreeView[objectName="branchless"]::branch:open:has-children:has-siblings +{ + border-image: none; +} diff --git a/example/shared.py b/example/shared.py index af7c7d4..b17d55a 100644 --- a/example/shared.py +++ b/example/shared.py @@ -912,16 +912,19 @@ def setup_app(args, unknown, compat, style_class=None, window_class=None): return app, window +def read_qtext_file(path, compat): + file = compat.QtCore.QFile(path) + file.open(compat.ReadOnly | compat.Text) + stream = compat.QtCore.QTextStream(file) + return stream.readAll() + def set_stylesheet(args, app, compat): '''Set the application stylesheet.''' if args.stylesheet != 'native': resource_format = get_resources(args) stylesheet = get_stylesheet(resource_format) - file = compat.QtCore.QFile(stylesheet) - file.open(compat.ReadOnly | compat.Text) - stream = compat.QtCore.QTextStream(file) - app.setStyleSheet(stream.readAll()) + app.setStyleSheet(read_qtext_file(stylesheet, compat)) def exec_app(args, app, window, compat): '''Show and execute the Qt application.'''