├── .github └── workflows │ ├── python-publish-to-pypi.yml │ └── python-publish-to-test-pypi.yml ├── .gitignore ├── LICENSE ├── MANIFEST.in ├── README.md ├── pyside6_utils ├── __init__.py ├── classes │ ├── __init__.py │ ├── constraints.py │ └── serializable.py ├── constants.py ├── examples │ ├── __init__.py │ ├── example_dataclass.py │ ├── images │ │ ├── Qt_designer_loaded_widgets_example.png │ │ ├── collapsible_group_box_collapsed.png │ │ ├── collapsible_group_box_open.png │ │ ├── console_widget.png │ │ ├── dataclass_view.png │ │ ├── extended_mdi_area.png │ │ ├── file_explorer_view.png │ │ ├── overlay_widget.png │ │ ├── pandas_table_view.png │ │ ├── range_selector.png │ │ ├── square_widget.png │ │ ├── string_float_list_example.png │ │ ├── widget_list.png │ │ └── widget_switcher.png │ ├── run_qt_designer.py │ └── run_widgets_example_app.py ├── icons │ ├── __init__.py │ ├── actions │ │ ├── address-book-new.png │ │ ├── appointment-new.png │ │ ├── bookmark-new.png │ │ ├── contact-new.png │ │ ├── document-new.png │ │ ├── document-open.png │ │ ├── document-print-preview.png │ │ ├── document-print.png │ │ ├── document-properties.png │ │ ├── document-save-as.png │ │ ├── document-save.png │ │ ├── edit-clear.png │ │ ├── edit-copy.png │ │ ├── edit-cut.png │ │ ├── edit-delete.png │ │ ├── edit-find-replace.png │ │ ├── edit-find.png │ │ ├── edit-paste.png │ │ ├── edit-redo.png │ │ ├── edit-select-all.png │ │ ├── edit-undo.png │ │ ├── folder-new.png │ │ ├── format-indent-less.png │ │ ├── format-indent-more.png │ │ ├── format-justify-center.png │ │ ├── format-justify-fill.png │ │ ├── format-justify-left.png │ │ ├── format-justify-right.png │ │ ├── format-text-bold.png │ │ ├── format-text-italic.png │ │ ├── format-text-strikethrough.png │ │ ├── format-text-underline.png │ │ ├── go-bottom.png │ │ ├── go-down.png │ │ ├── go-first.png │ │ ├── go-home.png │ │ ├── go-jump.png │ │ ├── go-last.png │ │ ├── go-next.png │ │ ├── go-previous.png │ │ ├── go-top.png │ │ ├── go-up.png │ │ ├── list-add.png │ │ ├── list-remove.png │ │ ├── mail-forward.png │ │ ├── mail-mark-junk.png │ │ ├── mail-mark-not-junk.png │ │ ├── mail-message-new.png │ │ ├── mail-reply-all.png │ │ ├── mail-reply-sender.png │ │ ├── mail-send-receive.png │ │ ├── media-eject.png │ │ ├── media-playback-pause.png │ │ ├── media-playback-start.png │ │ ├── media-playback-stop.png │ │ ├── media-record.png │ │ ├── media-seek-backward.png │ │ ├── media-seek-forward.png │ │ ├── media-skip-backward.png │ │ ├── media-skip-forward.png │ │ ├── process-stop.png │ │ ├── system-lock-screen.png │ │ ├── system-log-out.png │ │ ├── system-search.png │ │ ├── system-shutdown.png │ │ ├── tab-new.png │ │ ├── view-fullscreen.png │ │ ├── view-refresh.png │ │ └── window-new.png │ ├── app_resources.qrc │ ├── app_resources_rc.py │ ├── apps │ │ ├── accessories-calculator.png │ │ ├── accessories-character-map.png │ │ ├── accessories-text-editor.png │ │ ├── help-browser.png │ │ ├── internet-group-chat.png │ │ ├── internet-mail.png │ │ ├── internet-news-reader.png │ │ ├── internet-web-browser.png │ │ ├── office-calendar.png │ │ ├── preferences-desktop-accessibility.png │ │ ├── preferences-desktop-assistive-technology.png │ │ ├── preferences-desktop-font.png │ │ ├── preferences-desktop-keyboard-shortcuts.png │ │ ├── preferences-desktop-locale.png │ │ ├── preferences-desktop-multimedia.png │ │ ├── preferences-desktop-remote-desktop.png │ │ ├── preferences-desktop-screensaver.png │ │ ├── preferences-desktop-theme.png │ │ ├── preferences-desktop-wallpaper.png │ │ ├── preferences-system-network-proxy.png │ │ ├── preferences-system-session.png │ │ ├── preferences-system-windows.png │ │ ├── system-file-manager.png │ │ ├── system-installer.png │ │ ├── system-software-update.png │ │ ├── system-users.png │ │ ├── utilities-system-monitor.png │ │ └── utilities-terminal.png │ ├── categories │ │ ├── applications-accessories.png │ │ ├── applications-development.png │ │ ├── applications-games.png │ │ ├── applications-graphics.png │ │ ├── applications-internet.png │ │ ├── applications-multimedia.png │ │ ├── applications-office.png │ │ ├── applications-other.png │ │ ├── applications-system.png │ │ ├── preferences-desktop-peripherals.png │ │ ├── preferences-desktop.png │ │ └── preferences-system.png │ ├── devices │ │ ├── audio-card.png │ │ ├── audio-input-microphone.png │ │ ├── battery.png │ │ ├── camera-photo.png │ │ ├── camera-video.png │ │ ├── computer.png │ │ ├── drive-harddisk.png │ │ ├── drive-optical.png │ │ ├── drive-removable-media.png │ │ ├── input-gaming.png │ │ ├── input-keyboard.png │ │ ├── input-mouse.png │ │ ├── media-flash.png │ │ ├── media-floppy.png │ │ ├── media-optical.png │ │ ├── multimedia-player.png │ │ ├── network-wired.png │ │ ├── network-wireless.png │ │ ├── printer.png │ │ └── video-display.png │ ├── emblems │ │ ├── emblem-favorite.png │ │ ├── emblem-important.png │ │ ├── emblem-photos.png │ │ ├── emblem-readonly.png │ │ ├── emblem-symbolic-link.png │ │ ├── emblem-system.png │ │ └── emblem-unreadable.png │ ├── emotes │ │ ├── face-angel.png │ │ ├── face-crying.png │ │ ├── face-devilish.png │ │ ├── face-glasses.png │ │ ├── face-grin.png │ │ ├── face-kiss.png │ │ ├── face-monkey.png │ │ ├── face-plain.png │ │ ├── face-sad.png │ │ ├── face-smile-big.png │ │ ├── face-smile.png │ │ ├── face-surprise.png │ │ └── face-wink.png │ ├── mimetypes │ │ ├── application-certificate.png │ │ ├── application-x-executable.png │ │ ├── audio-x-generic.png │ │ ├── font-x-generic.png │ │ ├── image-x-generic.png │ │ ├── package-x-generic.png │ │ ├── text-html.png │ │ ├── text-x-generic-template.png │ │ ├── text-x-generic.png │ │ ├── text-x-script.png │ │ ├── video-x-generic.png │ │ ├── x-office-address-book.png │ │ ├── x-office-calendar.png │ │ ├── x-office-document-template.png │ │ ├── x-office-document.png │ │ ├── x-office-drawing-template.png │ │ ├── x-office-drawing.png │ │ ├── x-office-presentation-template.png │ │ ├── x-office-presentation.png │ │ ├── x-office-spreadsheet-template.png │ │ └── x-office-spreadsheet.png │ ├── places │ │ ├── folder-remote.png │ │ ├── folder-saved-search.png │ │ ├── folder.png │ │ ├── network-server.png │ │ ├── network-workgroup.png │ │ ├── start-here.png │ │ ├── user-desktop.png │ │ ├── user-home.png │ │ └── user-trash.png │ └── status │ │ ├── audio-volume-high.png │ │ ├── audio-volume-low.png │ │ ├── audio-volume-medium.png │ │ ├── audio-volume-muted.png │ │ ├── battery-caution.png │ │ ├── dialog-error.png │ │ ├── dialog-information.png │ │ ├── dialog-warning.png │ │ ├── folder-drag-accept.png │ │ ├── folder-open.png │ │ ├── folder-visiting.png │ │ ├── image-loading.png │ │ ├── image-missing.png │ │ ├── mail-attachment.png │ │ ├── network-error.png │ │ ├── network-idle.png │ │ ├── network-offline.png │ │ ├── network-receive.png │ │ ├── network-transmit-receive.png │ │ ├── network-transmit.png │ │ ├── network-wireless-encrypted.png │ │ ├── printer-error.png │ │ ├── software-update-available.png │ │ ├── software-update-urgent.png │ │ ├── user-trash-full.png │ │ ├── weather-clear-night.png │ │ ├── weather-clear.png │ │ ├── weather-few-clouds-night.png │ │ ├── weather-few-clouds.png │ │ ├── weather-overcast.png │ │ ├── weather-severe-alert.png │ │ ├── weather-showers-scattered.png │ │ ├── weather-showers.png │ │ ├── weather-snow.png │ │ └── weather-storm.png ├── models │ ├── __init__.py │ ├── console_widget_models │ │ ├── __init__.py │ │ ├── console_from_file_item.py │ │ └── console_model.py │ ├── dataclass_model.py │ ├── dataclass_tree_item.py │ ├── extended_sort_filter_proxy_model.py │ ├── file_explorer_model.py │ └── pandas_table_model.py ├── registrars │ ├── __init__.py │ ├── register_collapsible_group_box.py │ ├── register_console_widget.py │ ├── register_extended_mdi_area.py │ ├── register_file_explorer_view.py │ ├── register_overlay_widget.py │ ├── register_pandas_table.py │ ├── register_range_selector.py │ ├── register_square_frame.py │ ├── register_widget_list.py │ └── register_widget_switcher.py ├── ui │ ├── AllWidgets.ui │ ├── ConsoleWidget.ui │ ├── ConsoleWidget_ui.py │ ├── FramelessMdiWindow.ui │ ├── FramelessMdiWindow_ui.py │ ├── __init__.py │ └── allWidgets_ui.py ├── utility │ ├── __init__.py │ ├── catch_show_exception_in_popup_decorator.py │ ├── signal_blocker.py │ └── utility_functions.py └── widgets │ ├── __init__.py │ ├── collapsible_group_box.py │ ├── console_widget.py │ ├── dataclass_tree_view.py │ ├── delegates │ ├── __init__.py │ ├── console_widget_delegate.py │ └── dataclass_editors_delegate.py │ ├── extended_mdi_area.py │ ├── file_explorer_view.py │ ├── frameless_mdi_window.py │ ├── overlay_widget.py │ ├── pandas_table_view.py │ ├── range_selector.py │ ├── square_frame.py │ ├── widget_list.py │ └── widget_switcher.py ├── requirements.txt └── setup.py /.github/workflows/python-publish-to-pypi.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Upload Python Package to mypi.org 10 | 11 | on: 12 | release: 13 | types: [published] 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | deploy: #Uses trusted publishing (https://github.com/pypa/gh-action-pypi-publish) - make sure publisher is added in pypi-project 20 | runs-on: ubuntu-latest 21 | environment: 22 | name: pypi 23 | url: https://pypi.org/p/pyside6-utils 24 | permissions: 25 | id-token: write # IMPORTANT: this permission is mandatory for trusted publishing 26 | 27 | steps: 28 | - uses: actions/checkout@v3 29 | - name: Set up Python 30 | uses: actions/setup-python@v3 31 | with: 32 | python-version: '3.x' 33 | - name: Install dependencies 34 | run: | 35 | python -m pip install --upgrade pip 36 | pip install build 37 | - name: Build package 38 | run: python -m build 39 | - name: Publish the built release/package distribution to test.pypi.org 40 | uses: pypa/gh-action-pypi-publish@release/v1 41 | -------------------------------------------------------------------------------- /.github/workflows/python-publish-to-test-pypi.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Upload Python Package to test.mypi.org 10 | 11 | on: 12 | release: 13 | types: [published] 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | deploy: #Uses trusted publishing (https://github.com/pypa/gh-action-pypi-publish) - make sure publisher is added in pypi-project 20 | runs-on: ubuntu-latest 21 | environment: 22 | name: pypi 23 | url: https://pypi.org/p/pyside6-utils 24 | permissions: 25 | id-token: write # IMPORTANT: this permission is mandatory for trusted publishing 26 | 27 | steps: 28 | - uses: actions/checkout@v3 29 | - name: Set up Python 30 | uses: actions/setup-python@v3 31 | with: 32 | python-version: '3.x' 33 | - name: Install dependencies 34 | run: | 35 | python -m pip install --upgrade pip 36 | pip install build 37 | - name: Build package 38 | run: python -m build 39 | - name: Publish the built release/package distribution to test.pypi.org 40 | uses: pypa/gh-action-pypi-publish@release/v1 41 | with: 42 | repository-url: https://test.pypi.org/legacy/ 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | *.code-workspace 3 | __pycache__/ 4 | 5 | # Byte-compiled / optimized / DLL files 6 | __pycache__/ 7 | *.py[cod] 8 | *$py.class 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Distribution / packaging 14 | .Python 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | wheels/ 27 | share/python-wheels/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | MANIFEST 32 | 33 | # PyInstaller 34 | # Usually these files are written by a python script from a template 35 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 36 | *.manifest 37 | *.spec 38 | 39 | # Installer logs 40 | pip-log.txt 41 | pip-delete-this-directory.txt 42 | 43 | # Unit test / coverage reports 44 | htmlcov/ 45 | .tox/ 46 | .nox/ 47 | .coverage 48 | .coverage.* 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | *.cover 53 | *.py,cover 54 | .hypothesis/ 55 | .pytest_cache/ 56 | cover/ 57 | 58 | # Translations 59 | *.mo 60 | *.pot 61 | 62 | # Django stuff: 63 | *.log 64 | local_settings.py 65 | db.sqlite3 66 | db.sqlite3-journal 67 | 68 | # Flask stuff: 69 | instance/ 70 | .webassets-cache 71 | 72 | # Scrapy stuff: 73 | .scrapy 74 | 75 | # Sphinx documentation 76 | docs/_build/ 77 | 78 | # PyBuilder 79 | .pybuilder/ 80 | target/ 81 | 82 | # Jupyter Notebook 83 | .ipynb_checkpoints 84 | 85 | # IPython 86 | profile_default/ 87 | ipython_config.py 88 | 89 | # pyenv 90 | # For a library or package, you might want to ignore these files since the code is 91 | # intended to run in multiple environments; otherwise, check them in: 92 | # .python-version 93 | 94 | # pipenv 95 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 96 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 97 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 98 | # install all needed dependencies. 99 | #Pipfile.lock 100 | 101 | # poetry 102 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 103 | # This is especially recommended for binary packages to ensure reproducibility, and is more 104 | # commonly ignored for libraries. 105 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 106 | #poetry.lock 107 | 108 | # pdm 109 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 110 | #pdm.lock 111 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 112 | # in version control. 113 | # https://pdm.fming.dev/#use-with-ide 114 | .pdm.toml 115 | 116 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 117 | __pypackages__/ 118 | 119 | # Celery stuff 120 | celerybeat-schedule 121 | celerybeat.pid 122 | 123 | # SageMath parsed files 124 | *.sage.py 125 | 126 | # Environments 127 | .env 128 | .venv 129 | env/ 130 | venv/ 131 | ENV/ 132 | env.bak/ 133 | venv.bak/ 134 | 135 | # Spyder project settings 136 | .spyderproject 137 | .spyproject 138 | 139 | # Rope project settings 140 | .ropeproject 141 | 142 | # mkdocs documentation 143 | /site 144 | 145 | # mypy 146 | .mypy_cache/ 147 | .dmypy.json 148 | dmypy.json 149 | 150 | # Pyre type checker 151 | .pyre/ 152 | 153 | # pytype static type analyzer 154 | .pytype/ 155 | 156 | # Cython debug symbols 157 | cython_debug/ 158 | 159 | # PyCharm 160 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 161 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 162 | # and can be added to the global gitignore or merged into this file. For a more nuclear 163 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 164 | #.idea/ 165 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md 2 | include LICENSE -------------------------------------------------------------------------------- /pyside6_utils/__init__.py: -------------------------------------------------------------------------------- 1 | """Make all submodule available""" 2 | -------------------------------------------------------------------------------- /pyside6_utils/classes/__init__.py: -------------------------------------------------------------------------------- 1 | from .serializable import Serializable -------------------------------------------------------------------------------- /pyside6_utils/classes/serializable.py: -------------------------------------------------------------------------------- 1 | """ 2 | Helper class to serialize and deserialize objects 3 | for now, only json is supported, but more formats can be added. 4 | """ 5 | import json 6 | 7 | class Serializable(): 8 | """Generic class to serialize and deserialize objects to/from files""" 9 | def to_file(self, path : str, filetype = "json", ignore_private = False, use_encoding="utf-8"): 10 | """Trioes to find the correct function to save this object to a file, then saves it to the passed path 11 | 12 | Args: 13 | path (str): The path to save the file to 14 | filetype (str, optional): What filetype to save to. Defaults to "json". 15 | ignore_private (bool, optional): Whether to ignore private attributes. Defaults to True. 16 | use_encoding (str, optional): What encoding to use. Defaults to "utf-8". 17 | 18 | Raises: 19 | NotImplementedError: _description_ 20 | """ 21 | func = getattr(self, "to_"+filetype) 22 | if func is None: 23 | raise NotImplementedError(f"Could not save to passed filetype ({filetype}), this filetype is not implemented") 24 | else: 25 | output = func(ignore_private=ignore_private) 26 | with open(path, "w", encoding=use_encoding) as file: 27 | file.write(output) 28 | 29 | def from_file(self, path : str, filetype = "json", use_encoding="utf-8"): 30 | """ 31 | Load this class from a file 32 | Args: 33 | path (str): The path to load the file from 34 | filetype (str, optional): What filetype to load from. Defaults to "json". 35 | use_encoding (str, optional): What encoding to use - if applicable. Defaults to "utf-8". 36 | """ 37 | # if filetype == "json": 38 | # with open(path, "w") as file: 39 | # file.write(self.tojson()) 40 | 41 | func = getattr(self, "from_"+filetype) 42 | 43 | if func is None or filetype == "to_": 44 | raise NotImplementedError(f"Could not save to passed filetype ({filetype}), this filetype is not implemented") 45 | else: 46 | with open(path, "r", encoding=use_encoding) as file: 47 | func(file.read()) 48 | 49 | # self.copy_from_dict(dict) 50 | 51 | 52 | def copy_from_dict(self, copy_from_dict : dict, ignore_new_attributes = False): 53 | """ Copies all attributes from a dict to this object 54 | 55 | Args: 56 | copy_from_dict (dict): Dictionary to copy from 57 | ignore_new_attributes (bool, optional): If True, will ignore attributes that are not already present in this 58 | object. Defaults to False. 59 | 60 | Returns: 61 | list: list of items that were in the copy dict, but no attribute of this object 62 | list: list of items that were in this item, but not in the copy dict 63 | """ 64 | problem_list = set([]) 65 | if ignore_new_attributes: 66 | for key in copy_from_dict: 67 | if not hasattr(self, key): 68 | problem_list.add(key) 69 | 70 | for key in copy_from_dict: 71 | if ignore_new_attributes and key in problem_list: 72 | continue 73 | setattr(self, key, copy_from_dict[key]) 74 | 75 | missing_keys = set([key for key in self.__dict__ if key not in copy_from_dict]) 76 | 77 | return list(problem_list), list(missing_keys) #Return list of attributes that were not set 78 | 79 | 80 | def to_json(self, ignore_private = False): 81 | """Returns a json string representation of this object when converted to a dict""" 82 | if ignore_private: 83 | raise NotImplementedError("Ignore-private json conversion not implemented yet") 84 | return json.dumps(self, default=lambda o: o.__dict__, 85 | sort_keys=True, indent=4) 86 | 87 | def from_json(self, json_string): 88 | """Loads this object from a json string - all attributes present in the json string will be set on this object""" 89 | load_dict = json.loads(json_string) 90 | for key in load_dict: 91 | setattr(self, key, load_dict[key]) #Try to set all attributes from json 92 | -------------------------------------------------------------------------------- /pyside6_utils/constants.py: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | Defines some constants used in the package. 4 | """ 5 | from enum import Enum 6 | 7 | class Paths(str, Enum): 8 | """Paths to the package's subfolders. Used for the registrars""" 9 | PACKAGE_NAME = "pyside6_utils" 10 | WIDGETS_SUBPATH = "widgets" 11 | MODELS_SUBPATH = "models" 12 | EXAMPLES_SUBPATH = "examples" 13 | -------------------------------------------------------------------------------- /pyside6_utils/examples/__init__.py: -------------------------------------------------------------------------------- 1 | """Make it so we can directly import the examples.""" 2 | 3 | # from .run_widgets_example_app import run_widgets_example_app #Work in progres... 4 | from .run_qt_designer import run_qt_designer 5 | from .example_dataclass import ExampleDataClass -------------------------------------------------------------------------------- /pyside6_utils/examples/example_dataclass.py: -------------------------------------------------------------------------------- 1 | """An example dataclass to show functionality of automatic GUI generation.""" 2 | 3 | import typing 4 | from dataclasses import dataclass, field 5 | from datetime import datetime 6 | 7 | from pyside6_utils.classes.constraints import (Interval, ConstrainedList, 8 | StrOptions) 9 | 10 | LITERAL_EXAMPLE = typing.Literal["testliteral1", "testliteral2", "testliteral3"] #pylint: disable=invalid-name 11 | 12 | @dataclass 13 | class ExampleDataClass: 14 | """ 15 | This is an example dataclass to test automatic GUI generation - shows the functionality of all types. 16 | """ 17 | 18 | test_parent_with_property: str = field( 19 | default="testparentwithpropertystr", 20 | metadata=dict( 21 | display_name="Test Parent With Value", 22 | help= "This is a parent with an unsettable property", 23 | # display_path="Test Parent With Value", #Always from base 24 | editable=False 25 | ) 26 | ) 27 | 28 | test_str: str = field( 29 | default="teststr", 30 | metadata=dict( 31 | display_name="Test str", 32 | help= "This is a test", 33 | display_path="test_parent_with_property/Dummy Parent", #Always from base 34 | ) 35 | ) 36 | 37 | test_int: int | None = field( 38 | default=None, 39 | metadata=dict( 40 | display_name="Test int/none", 41 | help= "This is a test that can also be none", 42 | changed=True 43 | ) 44 | ) 45 | 46 | test_literal: typing.Literal["testliteral1", "testliteral2", "testliteral3"] = field( 47 | default="testliteral1", 48 | metadata=dict( 49 | display_name="Test literal", 50 | help= "This is a test", 51 | changed=True 52 | ) 53 | ) 54 | 55 | test_required_int: int | None = field( 56 | default=None, 57 | metadata=dict( 58 | display_name="Test required int", 59 | help= "This is a test int that is required", 60 | changed=True, 61 | required=True 62 | ) 63 | ) 64 | 65 | test_int_literal : typing.Literal[1, 2, 3] = field( 66 | default=1, 67 | metadata=dict( 68 | display_name="Test int literal", 69 | help= "This is a test", 70 | changed=True 71 | ) 72 | ) 73 | 74 | test_int_options : int = field( 75 | default=1, 76 | metadata=dict( 77 | display_name="Test int options", 78 | help= "This is a test that stays within 0-10 interval", 79 | changed=True, 80 | constraints = [Interval(int, 0,10, closed='both')] 81 | ) 82 | ) 83 | 84 | test_intlist : typing.List[int] = field( 85 | default_factory=list, 86 | metadata=dict( 87 | display_name="Test intlist", 88 | help= "This is a test", 89 | changed=True, 90 | constraints = [ConstrainedList([Interval(int, 0,10, closed='both')]), None] 91 | ) 92 | ) 93 | 94 | test_int_or_none_list : typing.List[int | None] = field( 95 | default_factory=list, 96 | metadata=dict( 97 | display_name="Test int 0<->10 or None list", 98 | help= "This is a test", 99 | changed=True, 100 | constraints = [ 101 | ConstrainedList([Interval(int, 0,10, closed='both'), None]) 102 | ] 103 | ) 104 | ) 105 | 106 | 107 | test_float_or_option : typing.List[float | str] = field( 108 | default_factory=list, 109 | metadata=dict( 110 | display_name="Either 0-1 float or 'string1' or 'string2'", 111 | help= "This is a test", 112 | changed=True, 113 | constraints = [ 114 | ConstrainedList([Interval(float, 0,1, closed='both'), StrOptions({"string1", "string2"})]) 115 | ] 116 | ) 117 | ) 118 | 119 | test_float_or_int_list : typing.List[float | int] = field( 120 | default_factory=list, 121 | metadata=dict( 122 | display_name="Test List[float|int]", 123 | help= "This is a test using only typing.List[float|int], no constraints", 124 | changed=True, 125 | ) 126 | ) 127 | 128 | test_stroptions_property : typing.Literal["Option 1/10", "Option 2/10"] = field( 129 | default="Option 1/10", 130 | metadata=dict( 131 | display_name="Test stroptions", 132 | help= "This is a test (stroptions)", 133 | changed=True, 134 | constraints = [StrOptions({f"Option {i}/10" for i in range(10)}), None], #Similar to literal, but we can 135 | #create additional options dynamically using constraints 136 | constraints_help= { f"Option {i}/10" : f"This is help for option {i}/10" for i in range(10) } #This option 137 | #allows us to add a "help" popup when hovering over individual options in a combobox 138 | ) 139 | ) 140 | 141 | 142 | test_float_range_0_1_property: float = field( 143 | default=0.001, 144 | metadata=dict( 145 | display_name="Test float range 0-1", 146 | help= "This is a test float", 147 | changed=True, 148 | constraints = [Interval(float, 0,1, closed='both'), None] 149 | ) 150 | ) 151 | 152 | test_bool_property: bool = field( 153 | default=False, 154 | metadata=dict( 155 | display_name="Test bool", 156 | help= "This is a test bool", 157 | changed=True 158 | ) 159 | ) 160 | 161 | test_datetime_property: datetime = field( 162 | default=datetime(2050,1,1), 163 | metadata=dict( 164 | display_name="Test datetime", 165 | help= "This is a test datetime", 166 | changed=True 167 | ) 168 | ) 169 | -------------------------------------------------------------------------------- /pyside6_utils/examples/images/Qt_designer_loaded_widgets_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/examples/images/Qt_designer_loaded_widgets_example.png -------------------------------------------------------------------------------- /pyside6_utils/examples/images/collapsible_group_box_collapsed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/examples/images/collapsible_group_box_collapsed.png -------------------------------------------------------------------------------- /pyside6_utils/examples/images/collapsible_group_box_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/examples/images/collapsible_group_box_open.png -------------------------------------------------------------------------------- /pyside6_utils/examples/images/console_widget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/examples/images/console_widget.png -------------------------------------------------------------------------------- /pyside6_utils/examples/images/dataclass_view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/examples/images/dataclass_view.png -------------------------------------------------------------------------------- /pyside6_utils/examples/images/extended_mdi_area.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/examples/images/extended_mdi_area.png -------------------------------------------------------------------------------- /pyside6_utils/examples/images/file_explorer_view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/examples/images/file_explorer_view.png -------------------------------------------------------------------------------- /pyside6_utils/examples/images/overlay_widget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/examples/images/overlay_widget.png -------------------------------------------------------------------------------- /pyside6_utils/examples/images/pandas_table_view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/examples/images/pandas_table_view.png -------------------------------------------------------------------------------- /pyside6_utils/examples/images/range_selector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/examples/images/range_selector.png -------------------------------------------------------------------------------- /pyside6_utils/examples/images/square_widget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/examples/images/square_widget.png -------------------------------------------------------------------------------- /pyside6_utils/examples/images/string_float_list_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/examples/images/string_float_list_example.png -------------------------------------------------------------------------------- /pyside6_utils/examples/images/widget_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/examples/images/widget_list.png -------------------------------------------------------------------------------- /pyside6_utils/examples/images/widget_switcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/examples/images/widget_switcher.png -------------------------------------------------------------------------------- /pyside6_utils/examples/run_qt_designer.py: -------------------------------------------------------------------------------- 1 | """ 2 | 2023 3 | This example will run QT Designer, also setting the PYSIDE_DESIGNER_PLUGINS path to the appropriate location, 4 | which should make all widgets in this package available in QT Designer. 5 | """ 6 | import os 7 | import pathlib 8 | import sys 9 | 10 | from PySide6.QtCore import QProcess, QProcessEnvironment 11 | from PySide6.QtWidgets import QApplication, QMessageBox 12 | 13 | 14 | def run_qt_designer(): 15 | """Runs qt designer, first setting the path to all registrars such that all custom widgets are loaded""" 16 | #Get path 1 folder up from this file 17 | main_path = pathlib.Path(__file__).parent.parent.absolute() 18 | env = QProcessEnvironment.systemEnvironment() 19 | env.insert('PYSIDE_DESIGNER_PLUGINS', os.path.join(main_path, "registrars")) 20 | 21 | 22 | app = QApplication(sys.argv) #pylint: disable=unused-variable 23 | QMessageBox.information( 24 | None, #type: ignore 25 | "PySide6 Designer", 26 | f"""
This example will attempt to run Qt Designer, including the PySide6 widgets.
27 |After clicking OK, Qt Designer should be started.
28 |This example assumes that you are using the right python environment in which PySide6 is installed. 29 | This means that Qt Designer can be launched by running: pyside6-designer - 30 | if not, this example will not work.
31 |This script automatically sets the PYSIDE_DESIGNER_PLUGINS environment variable to ./Registrars 32 | so that all of the widgets in this repository should appear in the widget box in the PySide2 Widgets 33 | group-box.
34 | 35 |Currently looking for Widgets/Registrars using path: {main_path}
36 | """ 37 | ) 38 | 39 | designer_process = QProcess() 40 | designer_process.setProcessEnvironment(env) 41 | designer_process.setProcessChannelMode(QProcess.ProcessChannelMode.ForwardedChannels) #Show output in console 42 | designer_process.start("pyside6-designer", [os.path.join(main_path, "ui", "AllWidgets.ui")]) #Start Qt Designer, 43 | #opening the example UI file 44 | 45 | #Check if designer is running 46 | if not designer_process.waitForStarted(): 47 | print("Designer process failed to start") 48 | #Create message box with reason why designer is not running 49 | QMessageBox.critical( 50 | None, #type: ignore 51 | "PySide6 Designer", 52 | f"Qt Designer (pyside6-designer) could not be started. Please check that it is " 53 | f"installed and that the designer executable is in your " 54 | f"path.
" 55 | f"The error message returned was:
" 56 | f"{designer_process.errorString()}
" 57 | ) 58 | sys.exit(1) 59 | 60 | designer_process.waitForFinished(-1) #-1 otherwise we will quit after 30 seconds 61 | sys.exit(designer_process.exitCode()) 62 | 63 | 64 | 65 | if __name__ == "__main__": 66 | run_qt_designer() 67 | -------------------------------------------------------------------------------- /pyside6_utils/examples/run_widgets_example_app.py: -------------------------------------------------------------------------------- 1 | """Run a window with examples for the widgets in this package.""" 2 | 3 | import sys 4 | 5 | import pandas as pd 6 | from PySide6.QtWidgets import QApplication, QMainWindow 7 | 8 | from pyside6_utils.models.pandas_table_model import PandasTableModel 9 | from pyside6_utils.ui.allWidgets_ui import Ui_MainWindow 10 | 11 | 12 | def run_widgets_example_app(): 13 | """Creates a qt app and shows a window with all a couple of small widgets in this package. 14 | TODO: create buttons for the large widgets? 15 | """ 16 | app = QApplication(sys.argv) 17 | example_window = QMainWindow() 18 | example_ui = Ui_MainWindow() 19 | example_ui.setupUi(example_window) 20 | 21 | #====== Example df for PandasTableView ====== 22 | example_df = pd.DataFrame({ 23 | "Column 1": [1, 2, 3, 4, 5], 24 | "Column 2": [10, 20, 30, 40, 50], 25 | "Column 3": [100, 200, 300, 400, 500], 26 | "Column 4": [1000, 2000, 3000, 4000, 5000], 27 | "Column 5": [10000, 20000, 30000, 40000, 50000], 28 | }) 29 | example_df_model = PandasTableModel(example_df) 30 | example_ui.pandasTableView.setModel(example_df_model) 31 | example_ui.pandasTableView.set_status_bar(example_window.statusBar()) 32 | 33 | example_window.show() 34 | sys.exit(app.exec()) 35 | 36 | 37 | if __name__ == "__main__": 38 | run_widgets_example_app() 39 | -------------------------------------------------------------------------------- /pyside6_utils/icons/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/__init__.py -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/address-book-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/address-book-new.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/appointment-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/appointment-new.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/bookmark-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/bookmark-new.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/contact-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/contact-new.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/document-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/document-new.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/document-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/document-open.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/document-print-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/document-print-preview.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/document-print.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/document-print.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/document-properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/document-properties.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/document-save-as.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/document-save-as.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/document-save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/document-save.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/edit-clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/edit-clear.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/edit-copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/edit-copy.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/edit-cut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/edit-cut.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/edit-delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/edit-delete.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/edit-find-replace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/edit-find-replace.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/edit-find.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/edit-find.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/edit-paste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/edit-paste.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/edit-redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/edit-redo.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/edit-select-all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/edit-select-all.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/edit-undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/edit-undo.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/folder-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/folder-new.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/format-indent-less.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/format-indent-less.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/format-indent-more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/format-indent-more.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/format-justify-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/format-justify-center.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/format-justify-fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/format-justify-fill.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/format-justify-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/format-justify-left.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/format-justify-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/format-justify-right.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/format-text-bold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/format-text-bold.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/format-text-italic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/format-text-italic.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/format-text-strikethrough.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/format-text-strikethrough.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/format-text-underline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/format-text-underline.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/go-bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/go-bottom.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/go-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/go-down.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/go-first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/go-first.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/go-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/go-home.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/go-jump.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/go-jump.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/go-last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/go-last.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/go-next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/go-next.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/go-previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/go-previous.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/go-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/go-top.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/go-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/go-up.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/list-add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/list-add.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/list-remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/list-remove.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/mail-forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/mail-forward.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/mail-mark-junk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/mail-mark-junk.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/mail-mark-not-junk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/mail-mark-not-junk.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/mail-message-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/mail-message-new.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/mail-reply-all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/mail-reply-all.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/mail-reply-sender.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/mail-reply-sender.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/mail-send-receive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/mail-send-receive.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/media-eject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/media-eject.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/media-playback-pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/media-playback-pause.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/media-playback-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/media-playback-start.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/media-playback-stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/media-playback-stop.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/media-record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/media-record.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/media-seek-backward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/media-seek-backward.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/media-seek-forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/media-seek-forward.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/media-skip-backward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/media-skip-backward.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/media-skip-forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/media-skip-forward.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/process-stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/process-stop.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/system-lock-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/system-lock-screen.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/system-log-out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/system-log-out.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/system-search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/system-search.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/system-shutdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/system-shutdown.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/tab-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/tab-new.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/view-fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/view-fullscreen.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/view-refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/view-refresh.png -------------------------------------------------------------------------------- /pyside6_utils/icons/actions/window-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/actions/window-new.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/accessories-calculator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/accessories-calculator.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/accessories-character-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/accessories-character-map.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/accessories-text-editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/accessories-text-editor.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/help-browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/help-browser.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/internet-group-chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/internet-group-chat.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/internet-mail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/internet-mail.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/internet-news-reader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/internet-news-reader.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/internet-web-browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/internet-web-browser.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/office-calendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/office-calendar.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/preferences-desktop-accessibility.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/preferences-desktop-accessibility.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/preferences-desktop-assistive-technology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/preferences-desktop-assistive-technology.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/preferences-desktop-font.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/preferences-desktop-font.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/preferences-desktop-keyboard-shortcuts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/preferences-desktop-keyboard-shortcuts.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/preferences-desktop-locale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/preferences-desktop-locale.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/preferences-desktop-multimedia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/preferences-desktop-multimedia.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/preferences-desktop-remote-desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/preferences-desktop-remote-desktop.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/preferences-desktop-screensaver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/preferences-desktop-screensaver.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/preferences-desktop-theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/preferences-desktop-theme.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/preferences-desktop-wallpaper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/preferences-desktop-wallpaper.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/preferences-system-network-proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/preferences-system-network-proxy.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/preferences-system-session.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/preferences-system-session.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/preferences-system-windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/preferences-system-windows.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/system-file-manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/system-file-manager.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/system-installer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/system-installer.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/system-software-update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/system-software-update.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/system-users.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/system-users.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/utilities-system-monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/utilities-system-monitor.png -------------------------------------------------------------------------------- /pyside6_utils/icons/apps/utilities-terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/apps/utilities-terminal.png -------------------------------------------------------------------------------- /pyside6_utils/icons/categories/applications-accessories.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/categories/applications-accessories.png -------------------------------------------------------------------------------- /pyside6_utils/icons/categories/applications-development.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/categories/applications-development.png -------------------------------------------------------------------------------- /pyside6_utils/icons/categories/applications-games.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/categories/applications-games.png -------------------------------------------------------------------------------- /pyside6_utils/icons/categories/applications-graphics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/categories/applications-graphics.png -------------------------------------------------------------------------------- /pyside6_utils/icons/categories/applications-internet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/categories/applications-internet.png -------------------------------------------------------------------------------- /pyside6_utils/icons/categories/applications-multimedia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/categories/applications-multimedia.png -------------------------------------------------------------------------------- /pyside6_utils/icons/categories/applications-office.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/categories/applications-office.png -------------------------------------------------------------------------------- /pyside6_utils/icons/categories/applications-other.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/categories/applications-other.png -------------------------------------------------------------------------------- /pyside6_utils/icons/categories/applications-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/categories/applications-system.png -------------------------------------------------------------------------------- /pyside6_utils/icons/categories/preferences-desktop-peripherals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/categories/preferences-desktop-peripherals.png -------------------------------------------------------------------------------- /pyside6_utils/icons/categories/preferences-desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/categories/preferences-desktop.png -------------------------------------------------------------------------------- /pyside6_utils/icons/categories/preferences-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/categories/preferences-system.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/audio-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/audio-card.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/audio-input-microphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/audio-input-microphone.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/battery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/battery.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/camera-photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/camera-photo.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/camera-video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/camera-video.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/computer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/computer.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/drive-harddisk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/drive-harddisk.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/drive-optical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/drive-optical.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/drive-removable-media.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/drive-removable-media.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/input-gaming.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/input-gaming.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/input-keyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/input-keyboard.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/input-mouse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/input-mouse.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/media-flash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/media-flash.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/media-floppy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/media-floppy.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/media-optical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/media-optical.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/multimedia-player.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/multimedia-player.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/network-wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/network-wired.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/network-wireless.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/network-wireless.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/printer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/printer.png -------------------------------------------------------------------------------- /pyside6_utils/icons/devices/video-display.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/devices/video-display.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emblems/emblem-favorite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emblems/emblem-favorite.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emblems/emblem-important.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emblems/emblem-important.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emblems/emblem-photos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emblems/emblem-photos.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emblems/emblem-readonly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emblems/emblem-readonly.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emblems/emblem-symbolic-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emblems/emblem-symbolic-link.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emblems/emblem-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emblems/emblem-system.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emblems/emblem-unreadable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emblems/emblem-unreadable.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emotes/face-angel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emotes/face-angel.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emotes/face-crying.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emotes/face-crying.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emotes/face-devilish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emotes/face-devilish.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emotes/face-glasses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emotes/face-glasses.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emotes/face-grin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emotes/face-grin.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emotes/face-kiss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emotes/face-kiss.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emotes/face-monkey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emotes/face-monkey.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emotes/face-plain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emotes/face-plain.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emotes/face-sad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emotes/face-sad.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emotes/face-smile-big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emotes/face-smile-big.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emotes/face-smile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emotes/face-smile.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emotes/face-surprise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emotes/face-surprise.png -------------------------------------------------------------------------------- /pyside6_utils/icons/emotes/face-wink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/emotes/face-wink.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/application-certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/application-certificate.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/application-x-executable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/application-x-executable.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/audio-x-generic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/audio-x-generic.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/font-x-generic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/font-x-generic.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/image-x-generic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/image-x-generic.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/package-x-generic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/package-x-generic.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/text-html.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/text-html.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/text-x-generic-template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/text-x-generic-template.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/text-x-generic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/text-x-generic.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/text-x-script.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/text-x-script.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/video-x-generic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/video-x-generic.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/x-office-address-book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/x-office-address-book.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/x-office-calendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/x-office-calendar.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/x-office-document-template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/x-office-document-template.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/x-office-document.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/x-office-document.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/x-office-drawing-template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/x-office-drawing-template.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/x-office-drawing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/x-office-drawing.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/x-office-presentation-template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/x-office-presentation-template.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/x-office-presentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/x-office-presentation.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/x-office-spreadsheet-template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/x-office-spreadsheet-template.png -------------------------------------------------------------------------------- /pyside6_utils/icons/mimetypes/x-office-spreadsheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/mimetypes/x-office-spreadsheet.png -------------------------------------------------------------------------------- /pyside6_utils/icons/places/folder-remote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/places/folder-remote.png -------------------------------------------------------------------------------- /pyside6_utils/icons/places/folder-saved-search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/places/folder-saved-search.png -------------------------------------------------------------------------------- /pyside6_utils/icons/places/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/places/folder.png -------------------------------------------------------------------------------- /pyside6_utils/icons/places/network-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/places/network-server.png -------------------------------------------------------------------------------- /pyside6_utils/icons/places/network-workgroup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/places/network-workgroup.png -------------------------------------------------------------------------------- /pyside6_utils/icons/places/start-here.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/places/start-here.png -------------------------------------------------------------------------------- /pyside6_utils/icons/places/user-desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/places/user-desktop.png -------------------------------------------------------------------------------- /pyside6_utils/icons/places/user-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/places/user-home.png -------------------------------------------------------------------------------- /pyside6_utils/icons/places/user-trash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/places/user-trash.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/audio-volume-high.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/audio-volume-high.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/audio-volume-low.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/audio-volume-low.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/audio-volume-medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/audio-volume-medium.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/audio-volume-muted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/audio-volume-muted.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/battery-caution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/battery-caution.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/dialog-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/dialog-error.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/dialog-information.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/dialog-information.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/dialog-warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/dialog-warning.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/folder-drag-accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/folder-drag-accept.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/folder-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/folder-open.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/folder-visiting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/folder-visiting.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/image-loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/image-loading.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/image-missing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/image-missing.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/mail-attachment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/mail-attachment.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/network-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/network-error.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/network-idle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/network-idle.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/network-offline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/network-offline.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/network-receive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/network-receive.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/network-transmit-receive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/network-transmit-receive.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/network-transmit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/network-transmit.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/network-wireless-encrypted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/network-wireless-encrypted.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/printer-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/printer-error.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/software-update-available.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/software-update-available.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/software-update-urgent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/software-update-urgent.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/user-trash-full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/user-trash-full.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/weather-clear-night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/weather-clear-night.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/weather-clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/weather-clear.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/weather-few-clouds-night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/weather-few-clouds-night.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/weather-few-clouds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/weather-few-clouds.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/weather-overcast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/weather-overcast.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/weather-severe-alert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/weather-severe-alert.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/weather-showers-scattered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/weather-showers-scattered.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/weather-showers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/weather-showers.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/weather-snow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/weather-snow.png -------------------------------------------------------------------------------- /pyside6_utils/icons/status/weather-storm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/icons/status/weather-storm.png -------------------------------------------------------------------------------- /pyside6_utils/models/__init__.py: -------------------------------------------------------------------------------- 1 | """Init""" 2 | from .dataclass_model import DataclassModel 3 | from .dataclass_tree_item import DataclassTreeItem 4 | from .extended_sort_filter_proxy_model import ExtendedSortFilterProxyModel 5 | from .file_explorer_model import FileExplorerModel 6 | from .pandas_table_model import PandasTableModel 7 | 8 | from . import console_widget_models as console_widget_models 9 | 10 | -------------------------------------------------------------------------------- /pyside6_utils/models/console_widget_models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/models/console_widget_models/__init__.py -------------------------------------------------------------------------------- /pyside6_utils/models/console_widget_models/console_from_file_item.py: -------------------------------------------------------------------------------- 1 | """Implements the model needed to sync to a file and dynamically display the contents to a widget""" 2 | import os 3 | import time 4 | import typing 5 | 6 | from PySide6 import QtCore, QtWidgets 7 | 8 | from pyside6_utils.models.console_widget_models.console_model import \ 9 | BaseConsoleItem 10 | 11 | 12 | class FileCheckerWorker(QtCore.QObject): 13 | """A class that continuously checks a file path for changes in file size, if so, it emits a simple signal, 14 | indicating that the file has changed, used by ConsoleFromFileItem to check for changes in the file. 15 | 16 | TODO: file polling might not be the best approach, especially when using multiple files. 17 | """ 18 | fileChanged = QtCore.Signal() #Emitted when the file has changed 19 | 20 | def __init__(self, path, polling_interval : float = 0.2, *args, **kwargs) -> None: #pylint: disable=W1113 21 | super().__init__(*args, **kwargs) 22 | self._path = path 23 | self.run_flag = True #Keep track of whether the thread should keep running 24 | self._polling_interval = polling_interval #The interval in seconds to check the file for changes 25 | #TODO: make parameter 26 | self._last_size = 0 27 | 28 | def do_work(self): 29 | """Continuously check the file for changes in size, if so, emit the fileChanged signal.""" 30 | self._last_size = -1 #File doesnt exist 31 | while self.run_flag: 32 | time.sleep(self._polling_interval) 33 | 34 | if not os.path.exists(self._path): #If file does not exist, clear the text edit 35 | if self._last_size != -1: 36 | self._last_size = -1 37 | self.fileChanged.emit() 38 | continue 39 | 40 | cur_size = os.path.getsize(self._path) 41 | 42 | if cur_size != self._last_size: 43 | self._last_size = cur_size 44 | self.fileChanged.emit() 45 | 46 | 47 | class ConsoleFromFileItem(BaseConsoleItem): 48 | """An item that represents a single row in the console widget. 49 | Continually monitors the passed path for changes, and emits the current text when the file changes. 50 | E.g. we can monitor the output of a running program by calling: 51 | sys.stdout = LoggerWriter(log.info) 52 | Inside of a running process. Where LoggerWriter is an object that outputs to a file monitored by a ConsoleFromFileItem. 53 | 54 | TODO: file polling might not be the best approach, especially when using a lot of files. 55 | """ 56 | loadedLinesChanged = QtCore.Signal(list, int) #Emits all lines that have been changed, together with the line-index 57 | emitDataChanged = QtCore.Signal() #Emitted when the data of the item changes 58 | 59 | def __init__(self, name : str, path : str, *args, **kwargs): 60 | super().__init__(*args, **kwargs) 61 | self._console_pixmap = QtWidgets.QStyle.StandardPixmap.SP_TitleBarMaxButton 62 | self._console_icon = QtWidgets.QApplication.style().standardIcon(self._console_pixmap) 63 | 64 | self._name = name 65 | self._path = path 66 | 67 | # self._current_text : str = "" #The current text in the file #TODO: probably list of lines works better... 68 | self._current_line_list : list[str] = [] #List of lines 69 | self._cur_lines = [0, 0] #What lines are currently loaded 70 | self._last_edited = QtCore.QDateTime.fromSecsSinceEpoch(0) #Set to 0 so that it is always updated on first change 71 | self._current_seek : int = 0 #The current seek position in the current file 72 | 73 | 74 | #Check if file exists 75 | if self._path is None or not os.path.exists(self._path): 76 | raise ValueError(f"File {self._path} does not exist - Console Item will not be able to initiate a" 77 | "file-watcher so updates will not be shown.") 78 | 79 | 80 | #Align contents bottom 81 | self._polling_interval = 0.2 #The interval in seconds to poll the file for changes #TODO: make parameter 82 | 83 | self._current_seek : int = 0 #The current seek position in the current file 84 | self._on_content_changes_selected_file() #Call this method once to get the initial text 85 | 86 | self._file_monitor_worker = FileCheckerWorker(self._path) 87 | self._worker_thread = QtCore.QThread() 88 | self._worker_thread.started.connect(self._file_monitor_worker.do_work) 89 | self._file_monitor_worker.moveToThread(self._worker_thread) 90 | #Connect deleteLater to the finished signal of the thread 91 | self._file_monitor_worker.fileChanged.connect(self._on_content_changes_selected_file) 92 | 93 | #Connect doWork to the started signal of the thread 94 | self._worker_thread.start() 95 | 96 | 97 | def get_current_line_list(self) -> tuple[list[str], int]: 98 | """Retrieves the current text in the watched file - as currently known to the item. 99 | ICW the start-index of this buffer. When the full file is loaded, this will be 0. 100 | """ 101 | # return self._current_text, 0 #TODO: No limit implemented yet 102 | return self._current_line_list, self._cur_lines[0] 103 | 104 | 105 | def data(self, role : QtCore.Qt.ItemDataRole, column : int = 0): 106 | """Retrieve the data for the given role for this item.""" 107 | if column == 0 : 108 | return self._name 109 | elif column == 1 : 110 | return self._last_edited 111 | elif column == 2 : 112 | return self._path 113 | raise ValueError(f"Invalid role for ConsoleStandardItem: {role}") 114 | # return super().data(role) 115 | 116 | def _on_content_changes_selected_file(self, encoding="utf-8") -> None: 117 | """ 118 | When the contents of selected file changes, this method is called 119 | """ 120 | 121 | if not os.path.exists(self._path): #If file does not exist, clear the text edit 122 | self._current_line_list = [] 123 | self._current_seek = 0 124 | self.loadedLinesChanged.emit([], 0) 125 | return 126 | 127 | cur_size = os.path.getsize(self._path) 128 | 129 | #First check is size is lower than the current seek position, if so, reset the seek position (assume file reset) 130 | if cur_size < self._current_seek: 131 | # self.ui.consoleTextEdit.clear() #Also clear the text edit 132 | self._current_seek = 0 133 | self._current_text = "" #Reset the current text 134 | 135 | if cur_size <= self._current_seek: #If file size is equal to the current seek position, do nothing 136 | return 137 | 138 | cur_line = len(self._current_line_list)+1 #Get the current line number 139 | new_line_list : typing.List[str]= [] #List of new lines 140 | 141 | #Open the file and seek to the current seek position 142 | with open(self._path, "r", encoding=encoding) as in_file: 143 | in_file.seek(self._current_seek) 144 | if len(self._current_line_list) > 0 and not self._current_line_list[-1].endswith("\n"): #TODO os.linesep? 145 | self._current_line_list[-1] += in_file.readline() 146 | new_line_list.append(self._current_line_list[-1]) 147 | cur_line -= 1 #Also update the last line number 148 | for line in in_file: #Read the new lines #TODO: maybe make a bit more efficient? 149 | self._current_line_list.append(line) 150 | new_line_list.append(line) 151 | self._current_seek = in_file.tell() #Make the current seek position the end of the file 152 | 153 | #Retrieve the last edit date 154 | self._last_edited = os.path.getmtime(self._path) 155 | # self.currentTextChanged.emit(self._current_text, 0) #Emit the current text 156 | self.loadedLinesChanged.emit(new_line_list, cur_line) #Emit the current text 157 | -------------------------------------------------------------------------------- /pyside6_utils/models/console_widget_models/console_model.py: -------------------------------------------------------------------------------- 1 | """Implements the base-model for the console widget. 2 | We can then choose to implement custom sub-class of this model. 3 | """ 4 | 5 | import typing 6 | from abc import abstractmethod 7 | 8 | from PySide6 import QtCore, QtWidgets 9 | 10 | 11 | class BaseConsoleItem(QtCore.QObject): #TODO: AbstractQObjectMeta 12 | """Base-class for console items. All user-defined console items should inherit from this class. 13 | """ 14 | loadedLinesChanged = QtCore.Signal(list, int) #Emits all lines that have been changed, together with the start 15 | # line-index 16 | dataChanged = QtCore.Signal() #When the metadata of the item changes (e.g. last-edit-date, name, running-state) 17 | 18 | @abstractmethod 19 | def data(self, role : QtCore.Qt.ItemDataRole, column : int = 0): 20 | "Get the data for the passed role at the passed column" 21 | raise NotImplementedError() 22 | 23 | @abstractmethod 24 | def get_current_line_list(self) -> typing.Tuple[list[str], int]: 25 | """Get the current text (str) of this console-item 26 | 27 | Retuns: 28 | Tuple[str, int]: The current text and the start-index of this buffer 29 | """ 30 | raise NotImplementedError() 31 | 32 | 33 | class ConsoleModel(QtCore.QAbstractItemModel): 34 | """Small class to overload data-representation of the file-selection treeview based on recency 35 | and to add icons to the first column 36 | 37 | Is compatible with ConsoleFromFileItems 38 | 39 | NOTE: this model does not seem to work with treeviews, only tableviews 40 | """ 41 | def __init__(self, *args, **kwargs): 42 | super().__init__(*args, **kwargs) 43 | self._console_pixmap = QtWidgets.QStyle.StandardPixmap.SP_TitleBarMaxButton 44 | self._console_icon = QtWidgets.QApplication.style().standardIcon(self._console_pixmap) 45 | self._item_list = [] #List of ConsoleStandardItem's 46 | 47 | def columnCount(self, parent : QtCore.QModelIndex = QtCore.QModelIndex()) -> int: #pylint: disable=unused-argument 48 | return 3 49 | 50 | def removeRow(self, row: int, parent : QtCore.QModelIndex) -> bool: 51 | self.beginRemoveRows(parent, row, row) 52 | # self._item_list.pop(row) 53 | del self._item_list[row] 54 | self.endRemoveRows() 55 | self.modelReset.emit() #Why is this needed? 56 | return True 57 | 58 | def rowCount(self, parent : QtCore.QModelIndex = QtCore.QModelIndex()) -> int: 59 | if not parent.isValid(): #If model index is not valid -> top level item -> so all items 60 | return len(self._item_list) 61 | else: #If one of the sub-items 62 | return 0 63 | 64 | def parent(self, index : QtCore.QModelIndex) -> QtCore.QModelIndex: #pylint: disable=unused-argument 65 | return QtCore.QModelIndex() #No parents 66 | 67 | def index(self, row : int, column : int, parent : QtCore.QModelIndex = QtCore.QModelIndex()) -> QtCore.QModelIndex: 68 | """Return the index of the item in the model specified by the given row, column and parent index. 69 | 70 | Args: 71 | row (int): The row of the item 72 | column (int): The column of the item 73 | parent (QtCore.QModelIndex, optional): The parent index. Defaults to QtCore.QModelIndex(). 74 | 75 | Returns: 76 | QtCore.QModelIndex: The index of the item 77 | """ 78 | if not parent.isValid(): #If top-level item (should be all items actually) 79 | return self.createIndex(row, column, self._item_list[row]) 80 | else: #If item -> no children 81 | return QtCore.QModelIndex() 82 | 83 | 84 | 85 | def append_row(self, item : BaseConsoleItem): 86 | """Append a row to the model - consisting of a single ConsoleStandardItem 87 | 88 | """ 89 | self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount()) 90 | self._item_list.append(item) 91 | item.dataChanged.connect( 92 | lambda *_ : self.dataChanged.emit(self.index(self.rowCount()-1, 0), self.index(self.rowCount()-1, 2))) 93 | 94 | self.endInsertRows() 95 | 96 | def add_item (self, item : BaseConsoleItem): 97 | """Add an item to the model, same as append_row 98 | 99 | Args: 100 | item (ConsoleStandardItem): The item to add 101 | """ 102 | self.append_row(item) 103 | 104 | #Overload the data method to return bold text if changes have been made in the past x seconds 105 | def data(self, index : QtCore.QModelIndex, role : QtCore.Qt.ItemDataRole = QtCore.Qt.ItemDataRole.DisplayRole): 106 | #Check if index is valid 107 | if not index.isValid(): #if index is not valid, return None 108 | return None 109 | 110 | #Get the item from the index 111 | item = index.internalPointer() 112 | 113 | assert isinstance(item, BaseConsoleItem) 114 | 115 | if role == QtCore.Qt.ItemDataRole.DisplayRole or role == QtCore.Qt.ItemDataRole.EditRole: 116 | return item.data(role=role, column=index.column()) #Return the data (str) of the item 117 | elif role == QtCore.Qt.ItemDataRole.DecorationRole: 118 | return self._console_icon 119 | elif role == QtCore.Qt.ItemDataRole.UserRole + 1: 120 | return item 121 | else: 122 | return None 123 | # return super().data(index, role) 124 | -------------------------------------------------------------------------------- /pyside6_utils/models/dataclass_tree_item.py: -------------------------------------------------------------------------------- 1 | """Implements a single item in a dataclass-tree, representing a variable with its value""" 2 | import typing 3 | from dataclasses import Field 4 | 5 | 6 | class DataclassTreeItem(object): 7 | """ 8 | This class represents a single item in a dataclass-tree (attribute). 9 | """ 10 | def __init__(self, 11 | name : str, 12 | item_data: typing.Any, 13 | field : Field | None, 14 | parent: typing.Optional["DataclassTreeItem"] = None 15 | ) -> None: 16 | self.name = name 17 | self.item_data = item_data 18 | self.field = field 19 | self.parent_item = parent 20 | self.child_items = [] 21 | 22 | def append_child(self, item: "DataclassTreeItem") -> None: 23 | """Appends a child to this item (of same type).""" 24 | self.child_items.append(item) 25 | 26 | def child(self, row: int) -> "DataclassTreeItem": 27 | """Returns the child at the given row.""" 28 | return self.child_items[row] 29 | 30 | def child_count(self) -> int: 31 | """Returns the number of children.""" 32 | return len(self.child_items) 33 | 34 | def column_count(self) -> int: 35 | """Returns the number of columns.""" 36 | return 2 37 | 38 | def data(self) -> typing.Any: 39 | """Returns the data stored in this item.""" 40 | return self.item_data 41 | 42 | def get_field(self) -> Field | None: 43 | """Returns the field associated with this item.""" 44 | return self.field 45 | 46 | def parent(self) -> "DataclassTreeItem | None": 47 | """Returns the parent of this item.""" 48 | return self.parent_item 49 | 50 | def row(self) -> int: 51 | """Returns the row of this item.""" 52 | if self.parent_item: 53 | return self.parent_item.child_items.index(self) 54 | return 0 55 | 56 | def print(self, indent: int = 0) -> None: 57 | """Prints the tree to the console.""" 58 | print("-" * indent, self.item_data) 59 | for child in self.child_items: 60 | assert isinstance(child, DataclassTreeItem) 61 | child.print(indent + 1) 62 | -------------------------------------------------------------------------------- /pyside6_utils/models/extended_sort_filter_proxy_model.py: -------------------------------------------------------------------------------- 1 | """Implements and extended version of QSortFIlterProxyModel with extra functionality (see class docstring)""" 2 | 3 | import logging 4 | import math 5 | import numbers 6 | import typing 7 | 8 | from PySide6 import QtCore 9 | 10 | log = logging.getLogger(__name__) 11 | 12 | 13 | 14 | FilterFunctionType =\ 15 | typing.Callable[[int, QtCore.QModelIndex | QtCore.QPersistentModelIndex, QtCore.QAbstractItemModel], bool] #Filter 16 | #function => source_row, source_parent (index), source_model 17 | 18 | class ExtendedSortFilterProxyModel(QtCore.QSortFilterProxyModel): 19 | """ 20 | Wrapper around the QSortFilterProxyModel which enables the use of multiple sort-columns instead of just one. 21 | If 2 items are not-sortable by column 1, we sort by column 2, then 3 etc. etc. 22 | 23 | Also implements a function-list based custom filtering system. 24 | Using setFilterFunction, the user can add a function that is used to AND-filter the rows. 25 | Filter-functions take a row as argument and return a bool. If the function returns True, the row is accepted. 26 | 27 | NOTE: Filtering is AND-ed with the default filterAcceptsRow function, so we can still use the default functionality 28 | in addition to the custom functions. 29 | """ 30 | 31 | def __init__(self, parent: QtCore.QObject | None = ...) -> None: 32 | super().__init__(parent) 33 | self._sort_columns : list[int] = [] 34 | self._sort_orders : list[QtCore.Qt.SortOrder] = [] 35 | self._filter_functions : typing.Dict[str, FilterFunctionType] = {} 36 | 37 | 38 | def _val_less_than(self, leftval, rightval): 39 | if leftval is None or (isinstance(leftval, numbers.Number) and math.isnan(leftval)): #type: ignore 40 | return True 41 | elif rightval is None or (isinstance(rightval, numbers.Number) and math.isnan(rightval)): #type: ignore 42 | return False 43 | return leftval < rightval #type: ignore 44 | 45 | def lessThan(self, left: QtCore.QModelIndex, right: QtCore.QModelIndex) -> bool: 46 | """ 47 | Reimplemented from QSortFilterProxyModel. 48 | """ 49 | 50 | if len(self._sort_columns) == 0: #If using default behaviour, use the default implementation 51 | return super().lessThan(left, right) 52 | else: 53 | for column, order in zip(self._sort_columns, self._sort_orders): 54 | left = self.sourceModel().index(left.row(), column) 55 | right = self.sourceModel().index(right.row(), column) 56 | leftval = left.data(role=QtCore.Qt.ItemDataRole.EditRole) 57 | rightval = right.data(role=QtCore.Qt.ItemDataRole.EditRole) 58 | if self._val_less_than(leftval, rightval) == self._val_less_than(leftval=rightval, rightval=leftval): 59 | #If the values are equal, continue to the next column 60 | continue 61 | else: 62 | return self._val_less_than(leftval, rightval) if \ 63 | order == QtCore.Qt.SortOrder.AscendingOrder else self._val_less_than(leftval, rightval) 64 | 65 | return False #If we can't differentiate the rows, return False (i.e. don't swap them) 66 | 67 | 68 | def sort_by_columns(self, columns: list[int], orders: list[QtCore.Qt.SortOrder] | None = None) -> None: 69 | """ 70 | Sets the sort-columns and their respective sort-orders. 71 | 72 | :param columns: The columns to sort by. 73 | :param orders: The sort-orders to use for the columns. If None, the default sort-order is used. 74 | """ 75 | if orders is None or orders == []: #If no orders are specified, use the default order 76 | orders = [QtCore.Qt.SortOrder.AscendingOrder] * len(columns) 77 | self._sort_columns = columns 78 | self._sort_orders = orders 79 | self.invalidate() 80 | 81 | def set_filter_function(self, 82 | function_name : str, 83 | function : FilterFunctionType 84 | ): 85 | """ 86 | Adds a filter function to the proxy model. All filter-functions together are AND-ed with the default 87 | filterAcceptsRow function to determine if a row is accepted. 88 | 89 | NOTE: overwrites any existing filter function with the same name, if it does, filters are invalidated 90 | 91 | Args: 92 | function_name (str): The name of the filter function (used to identify it) 93 | function (FILTER_FUNCTION_TYPE): The filter function to add 94 | """ 95 | invalidate = False 96 | if function_name in self._filter_functions: 97 | invalidate = True 98 | self._filter_functions[function_name] = function 99 | if invalidate: 100 | self.invalidateFilter() 101 | 102 | 103 | def clear_function_filters(self): 104 | """Clear all filter functions""" 105 | self._filter_functions = {} 106 | self.invalidateFilter() 107 | 108 | def get_filter_functions(self) -> typing.Dict[str, FilterFunctionType]: 109 | """Returns a dict of all filter functions""" 110 | return self._filter_functions 111 | 112 | def filterAcceptsRow(self, 113 | source_row: int, 114 | source_parent: QtCore.QModelIndex | QtCore.QPersistentModelIndex 115 | ) -> bool: 116 | """Calls QSortFilterProxyModel.filterAcceptsRow and ANDs the result with all filter functions 117 | 118 | NOTE: if any filter function raises an exception on a row, the row is not accepted and the error is logged. 119 | All filter functions are "AND-ed" together with the default filterAcceptsRow function. 120 | """ 121 | if not super().filterAcceptsRow(source_row, source_parent): 122 | return False 123 | for function in self._filter_functions.values(): 124 | try: 125 | if not function(source_row, source_parent, self.sourceModel()): 126 | return False 127 | except Exception as exception: #pylint: disable=broad-except 128 | log.error(f"Error while filtering row {exception} - {type(exception).__name__}: {exception}") 129 | return False 130 | return True 131 | -------------------------------------------------------------------------------- /pyside6_utils/models/file_explorer_model.py: -------------------------------------------------------------------------------- 1 | """ 2 | Implements QFileSystemModel with the added ability to highlight a single file - which puts an icon next to the file 3 | and sets it to bold. 4 | """ 5 | import logging 6 | import os 7 | import typing 8 | 9 | from PySide6 import QtCore, QtGui, QtWidgets 10 | 11 | log = logging.getLogger(__name__) 12 | 13 | class FileExplorerModel(QtWidgets.QFileSystemModel): 14 | """A QFileSystemModel that also allows for highlighting of a single file, for example when selecting a file for 15 | editing purposes. 16 | """ 17 | highlightPathChanged = QtCore.Signal(str) 18 | 19 | def __init__(self, parent: typing.Optional[QtCore.QObject] = None, allow_select_files_only=True) -> None: 20 | super().__init__(parent) 21 | self._selected_path = None 22 | 23 | self._selection_pixmap = QtWidgets.QStyle.StandardPixmap.SP_DialogApplyButton #Checkmark 24 | self._selection_icon = QtWidgets.QApplication.style().standardIcon(self._selection_pixmap) 25 | self._prev_selection = None 26 | 27 | if allow_select_files_only: 28 | self._allow_select_files_only = True 29 | 30 | def reset_highlight(self) -> None: 31 | """Reset the highlight""" 32 | self._selected_path = None 33 | if self._prev_selection: 34 | self.dataChanged.emit(self._prev_selection, self._prev_selection) #Update the icon of prev. highlighted item 35 | self._prev_selection = None 36 | self.highlightPathChanged.emit(None) 37 | 38 | def get_highlight_path(self) -> str | None: 39 | """Get the currently highlighted path""" 40 | return self._selected_path 41 | 42 | def set_highlight_using_path(self, path: str | None) -> None: 43 | """Set the current highlight to the given path 44 | 45 | Args: 46 | path (str | None): The path to highlight (or None to reset) 47 | """ 48 | self._selected_path = path 49 | self.highlightPathChanged.emit(self._selected_path) 50 | 51 | def set_highlight_using_index(self, selection: QtCore.QModelIndex | QtCore.QPersistentModelIndex) -> None: 52 | """Set the current selection to the model""" 53 | log.info(f"Trying to set model selection to: {self.filePath(selection)}") 54 | 55 | if self._allow_select_files_only and not os.path.isfile(self.filePath(selection)): #Skip selection if only 56 | #files are allowed and the selection is not a file 57 | log.warning(f"Selection is not a file, skipping selection: {self.filePath(selection)}") 58 | return 59 | 60 | self._selected_path = self.filePath(selection) 61 | 62 | if self._prev_selection: 63 | log.debug(f"Updating previous selection: {self.filePath(self._prev_selection)}") 64 | self.dataChanged.emit( 65 | self._prev_selection, 66 | self.index( 67 | self._prev_selection.row(), 68 | self.columnCount(self._prev_selection), 69 | self._prev_selection.parent() 70 | )) #Update the icon of prev. highlighted item 71 | 72 | new_selection = self.index(selection.row(), 0, selection.parent()) #Get index of first column (icon) 73 | self._prev_selection = QtCore.QPersistentModelIndex(new_selection) 74 | self.dataChanged.emit( 75 | new_selection, 76 | self.index( 77 | new_selection.row(), 78 | self.columnCount(new_selection), 79 | new_selection.parent() 80 | ) 81 | ) 82 | self.highlightPathChanged.emit(self._selected_path) 83 | 84 | 85 | 86 | def data(self, 87 | index: QtCore.QModelIndex, 88 | role: int = QtCore.Qt.ItemDataRole.DisplayRole) -> typing.Any: 89 | 90 | #TODO: what if highlighted file changed? (e.g. file renamed/removed) 91 | 92 | #If first column and fileIconRole, return selection icon 93 | if role == QtWidgets.QFileSystemModel.Roles.FileIconRole \ 94 | and index.column() == 0 \ 95 | and self._selected_path \ 96 | and (self.filePath(index) == self._selected_path): 97 | #Return arrow icon if selected 98 | return self._selection_icon 99 | elif role == QtCore.Qt.ItemDataRole.FontRole \ 100 | and self._selected_path \ 101 | and (self.filePath(index) == self._selected_path): #Enbolden whole selected column 102 | font = QtGui.QFont() 103 | font.setBold(True) 104 | return font 105 | 106 | 107 | return super().data(index, role) 108 | 109 | 110 | 111 | if __name__ == "__main__": 112 | print("Testing FileExplorerModel") 113 | app = QtWidgets.QApplication([]) 114 | # model = FileExplorerModel() 115 | model = QtWidgets.QFileSystemModel() 116 | 117 | #Get the current path 118 | current_path = os.path.dirname(os.path.realpath(__file__)) 119 | 120 | #Set editable 121 | model.setReadOnly(False) 122 | print(current_path) 123 | model.setRootPath(current_path) 124 | 125 | 126 | view = QtWidgets.QTreeView() 127 | view.setModel(model) 128 | view.setRootIndex(model.index(current_path)) 129 | view.show() 130 | 131 | app.exec() 132 | 133 | 134 | print("Done testing FileExplorerModel") 135 | -------------------------------------------------------------------------------- /pyside6_utils/models/pandas_table_model.py: -------------------------------------------------------------------------------- 1 | """Implements the a Qt-Model for pandas dataframes, so we can display them as a table in Qt-Widgets""" 2 | import logging 3 | from numbers import Number 4 | 5 | import pandas as pd 6 | from PySide6.QtCore import QAbstractTableModel, QModelIndex, Qt 7 | 8 | log = logging.getLogger(__name__) 9 | 10 | 11 | class PandasTableModel(QAbstractTableModel): 12 | """ A model-wrapper around a pandas dataframe to use with a QTableView 13 | NOTE: editing is not supported (yet) 14 | """ 15 | 16 | def __init__(self, dataframe: pd.DataFrame, parent=None): 17 | QAbstractTableModel.__init__(self, parent) 18 | self._dataframe = dataframe 19 | 20 | def rowCount(self, parent=QModelIndex()) -> int: 21 | if parent == QModelIndex(): 22 | return len(self._dataframe) 23 | return 0 24 | 25 | def columnCount(self, parent=QModelIndex()) -> int: 26 | if parent == QModelIndex(): 27 | return len(self._dataframe.columns) 28 | return 0 29 | 30 | def data(self, index: QModelIndex, role=Qt.ItemDataRole): 31 | if not index.isValid(): 32 | return None 33 | 34 | if role == Qt.ItemDataRole.DisplayRole: 35 | data = self._dataframe.iloc[index.row(), index.column()] 36 | if data is None or (isinstance(data, Number) and pd.isnull(data)): 37 | return "" 38 | #TODO: Convert item to qt-equivalent instead of string? 39 | return str(data) 40 | elif role == Qt.ItemDataRole.EditRole: 41 | return self._dataframe.iloc[index.row(), index.column()] 42 | elif role == Qt.ItemDataRole.BackgroundRole: 43 | return None 44 | 45 | return None 46 | 47 | 48 | def headerData( 49 | self, section: int, orientation: Qt.Orientation, role: Qt.ItemDataRole 50 | ): 51 | if role == Qt.ItemDataRole.DisplayRole: 52 | if orientation == Qt.Orientation.Horizontal: 53 | return str(self._dataframe.columns[section]) 54 | 55 | if orientation == Qt.Orientation.Vertical: 56 | return str(self._dataframe.index[section]) 57 | return None 58 | -------------------------------------------------------------------------------- /pyside6_utils/registrars/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Woutah/pyside6-utils/0230a1380966edd95d3cd746233b35c56e7bf7ee/pyside6_utils/registrars/__init__.py -------------------------------------------------------------------------------- /pyside6_utils/registrars/register_collapsible_group_box.py: -------------------------------------------------------------------------------- 1 | """For use by QtDesigner. If this folder is passed to Qt-Designer by using the environment variable 2 | PYSIDE_DESIGNER_PLUGINS=