pycforge-sdk 0.6.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pycforge_sdk/__init__.py +6 -0
- pycforge_sdk/__main__.py +3 -0
- pycforge_sdk/catalogue.py +287 -0
- pycforge_sdk/cli.py +114 -0
- pycforge_sdk/connection.py +136 -0
- pycforge_sdk/discovery.py +227 -0
- pycforge_sdk/editing.py +84 -0
- pycforge_sdk/engine_launch.py +45 -0
- pycforge_sdk/engine_worker.py +53 -0
- pycforge_sdk/gui/__init__.py +1 -0
- pycforge_sdk/gui/__main__.py +3 -0
- pycforge_sdk/gui/app.py +36 -0
- pycforge_sdk/gui/dialogs.py +310 -0
- pycforge_sdk/gui/editor.py +412 -0
- pycforge_sdk/gui/help/index.html +9 -0
- pycforge_sdk/gui/identity.py +139 -0
- pycforge_sdk/gui/jobs.py +146 -0
- pycforge_sdk/gui/reference.py +39 -0
- pycforge_sdk/gui/resources/sdk-mark.png +0 -0
- pycforge_sdk/gui/scanner.py +134 -0
- pycforge_sdk/gui/startup.py +118 -0
- pycforge_sdk/gui/visual/__init__.py +1 -0
- pycforge_sdk/gui/visual/action_contract.py +550 -0
- pycforge_sdk/gui/visual/icons.py +117 -0
- pycforge_sdk/gui/visual/qt_actions.py +501 -0
- pycforge_sdk/gui/visual/qt_branding.py +47 -0
- pycforge_sdk/gui/visual/qt_dialog_chrome.py +337 -0
- pycforge_sdk/gui/visual/qt_file_icons.py +130 -0
- pycforge_sdk/gui/visual/qt_icons.py +80 -0
- pycforge_sdk/gui/visual/qt_screen_geometry.py +166 -0
- pycforge_sdk/gui/visual/qt_title_controls.py +333 -0
- pycforge_sdk/gui/visual/qt_window_chrome.py +314 -0
- pycforge_sdk/gui/visual/qt_window_resize.py +93 -0
- pycforge_sdk/gui/visual/qt_workspace_widgets.py +448 -0
- pycforge_sdk/gui/visual/resources/icons/128/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/128/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/16/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/20/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/24/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/256/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/32/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/48/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/64/whitespace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/add-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/brand-mark.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/bundle-search.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/cancel.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/check.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/chevron-right.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/close.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/collapse-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/command-palette.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/convert.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/copy.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/cut.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/decision-trace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/details.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/diagnostics.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/duplicate-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/exit.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/expand-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/export.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/find.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/go-to-line.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/go-to-output.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/go-to-source.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/help.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/history.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/indent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/link-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/mappings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/move-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/move-line-down.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/move-line-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/move-up.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/next.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/open.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/outdent.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/outline.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/paste.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/previous.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/primary-module.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/redo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/remove-document.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/replace.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/save-as.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/save.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/select-all.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/settings.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/show-c.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/split-view.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/summary.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/telemetry.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/toggle-comment.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/toggle-fold.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/tools.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/undo.png +0 -0
- pycforge_sdk/gui/visual/resources/icons/96/whitespace.png +0 -0
- pycforge_sdk/gui/visual/theme.py +204 -0
- pycforge_sdk/gui/visual/theme_steel_stylesheet.py +901 -0
- pycforge_sdk/gui/visual/theme_stylesheet.py +597 -0
- pycforge_sdk/gui/visual/theme_workspace_stylesheet.py +169 -0
- pycforge_sdk/gui/visual/visual_tokens.py +146 -0
- pycforge_sdk/gui/widgets.py +68 -0
- pycforge_sdk/gui/window.py +559 -0
- pycforge_sdk/native.py +42 -0
- pycforge_sdk/package_metadata.py +21 -0
- pycforge_sdk/process.py +58 -0
- pycforge_sdk/project.py +143 -0
- pycforge_sdk/readiness.py +106 -0
- pycforge_sdk/results.py +45 -0
- pycforge_sdk/service.py +454 -0
- pycforge_sdk/workbench.py +88 -0
- pycforge_sdk-0.6.3.dist-info/METADATA +221 -0
- pycforge_sdk-0.6.3.dist-info/RECORD +559 -0
- pycforge_sdk-0.6.3.dist-info/WHEEL +5 -0
- pycforge_sdk-0.6.3.dist-info/entry_points.txt +5 -0
- pycforge_sdk-0.6.3.dist-info/licenses/LICENSE +674 -0
- pycforge_sdk-0.6.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"""Headless-safe catalogue for PyCForge's packaged raster iconography."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from types import MappingProxyType
|
|
7
|
+
from typing import Mapping
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
PYCFORGE_ICON_SIZES = (16, 20, 24, 32, 48, 64, 96, 128, 256)
|
|
11
|
+
|
|
12
|
+
PYCFORGE_ICON_FILES: Mapping[str, str] = MappingProxyType(
|
|
13
|
+
{
|
|
14
|
+
"add-document": "add-document.png",
|
|
15
|
+
"brand-mark": "brand-mark.png",
|
|
16
|
+
"cancel": "cancel.png",
|
|
17
|
+
"check": "check.png",
|
|
18
|
+
"chevron-right": "chevron-right.png",
|
|
19
|
+
"close": "close.png",
|
|
20
|
+
"collapse-all": "collapse-all.png",
|
|
21
|
+
"command-palette": "command-palette.png",
|
|
22
|
+
"convert": "convert.png",
|
|
23
|
+
"copy": "copy.png",
|
|
24
|
+
"cut": "cut.png",
|
|
25
|
+
"decision-trace": "decision-trace.png",
|
|
26
|
+
"details": "details.png",
|
|
27
|
+
"diagnostics": "diagnostics.png",
|
|
28
|
+
"duplicate-line": "duplicate-line.png",
|
|
29
|
+
"exit": "exit.png",
|
|
30
|
+
"expand-all": "expand-all.png",
|
|
31
|
+
"find": "find.png",
|
|
32
|
+
"bundle-search": "bundle-search.png",
|
|
33
|
+
"go-to-line": "go-to-line.png",
|
|
34
|
+
"go-to-output": "go-to-output.png",
|
|
35
|
+
"go-to-source": "go-to-source.png",
|
|
36
|
+
"history": "history.png",
|
|
37
|
+
"help": "help.png",
|
|
38
|
+
"indent": "indent.png",
|
|
39
|
+
"link-c": "link-c.png",
|
|
40
|
+
"mappings": "mappings.png",
|
|
41
|
+
"module": "module.png",
|
|
42
|
+
"move-down": "move-down.png",
|
|
43
|
+
"move-line-down": "move-line-down.png",
|
|
44
|
+
"move-line-up": "move-line-up.png",
|
|
45
|
+
"move-up": "move-up.png",
|
|
46
|
+
"next-match": "next.png",
|
|
47
|
+
"open": "open.png",
|
|
48
|
+
"outline": "outline.png",
|
|
49
|
+
"outdent": "outdent.png",
|
|
50
|
+
"paste": "paste.png",
|
|
51
|
+
"previous-match": "previous.png",
|
|
52
|
+
"primary-module": "primary-module.png",
|
|
53
|
+
"redo": "redo.png",
|
|
54
|
+
"remove-document": "remove-document.png",
|
|
55
|
+
"replace": "replace.png",
|
|
56
|
+
"save-as": "save-as.png",
|
|
57
|
+
"save-c": "export.png",
|
|
58
|
+
"save-python": "save.png",
|
|
59
|
+
"select-all": "select-all.png",
|
|
60
|
+
"settings": "settings.png",
|
|
61
|
+
"split-view": "split-view.png",
|
|
62
|
+
"summary": "summary.png",
|
|
63
|
+
"telemetry": "telemetry.png",
|
|
64
|
+
"tools": "tools.png",
|
|
65
|
+
"toggle-comment": "toggle-comment.png",
|
|
66
|
+
"toggle-fold": "toggle-fold.png",
|
|
67
|
+
"undo": "undo.png",
|
|
68
|
+
"view-c": "show-c.png",
|
|
69
|
+
"whitespace": "whitespace.png",
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def pycforge_icon_root() -> Path:
|
|
75
|
+
"""Return the packaged multi-resolution raster-resource directory."""
|
|
76
|
+
|
|
77
|
+
return Path(__file__).parent / "resources" / "icons"
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def pycforge_brand_icon_path() -> Path:
|
|
81
|
+
"""Return the canonical 24-pixel PyCForge brand mark."""
|
|
82
|
+
|
|
83
|
+
return pycforge_icon_path("brand-mark")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def pycforge_icon_path(name: str, size: int = 24) -> Path:
|
|
87
|
+
"""Return one exact packaged PNG for a stable logical icon name."""
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
filename = PYCFORGE_ICON_FILES[name]
|
|
91
|
+
except KeyError as exc:
|
|
92
|
+
raise KeyError(f"unknown PyCForge icon: {name}") from exc
|
|
93
|
+
if isinstance(size, bool) or size not in PYCFORGE_ICON_SIZES:
|
|
94
|
+
raise ValueError(
|
|
95
|
+
"icon size must be one of "
|
|
96
|
+
+ ", ".join(str(item) for item in PYCFORGE_ICON_SIZES)
|
|
97
|
+
)
|
|
98
|
+
return pycforge_icon_root() / str(size) / filename
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def pycforge_icon_paths(name: str) -> tuple[tuple[int, Path], ...]:
|
|
102
|
+
"""Return every packaged resolution for one logical icon."""
|
|
103
|
+
|
|
104
|
+
return tuple(
|
|
105
|
+
(size, pycforge_icon_path(name, size))
|
|
106
|
+
for size in PYCFORGE_ICON_SIZES
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
__all__ = [
|
|
111
|
+
"PYCFORGE_ICON_FILES",
|
|
112
|
+
"PYCFORGE_ICON_SIZES",
|
|
113
|
+
"pycforge_brand_icon_path",
|
|
114
|
+
"pycforge_icon_path",
|
|
115
|
+
"pycforge_icon_paths",
|
|
116
|
+
"pycforge_icon_root",
|
|
117
|
+
]
|
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
"""Optional Qt materialization of the declared PyCForge action contract."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable, Mapping
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from .action_contract import (
|
|
9
|
+
ACTION_SPECS,
|
|
10
|
+
DYNAMIC_ACTION_GROUPS,
|
|
11
|
+
ActionSpec,
|
|
12
|
+
ActionState,
|
|
13
|
+
DynamicActionEntry,
|
|
14
|
+
validated_dynamic_entries,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
from PySide6.QtCore import QObject, QSignalBlocker, Qt
|
|
20
|
+
from PySide6.QtGui import QAction, QActionGroup, QIcon, QKeySequence
|
|
21
|
+
from PySide6.QtWidgets import QToolButton, QWidget
|
|
22
|
+
except (ImportError, ModuleNotFoundError) as exc:
|
|
23
|
+
QT_ACTIONS_AVAILABLE = False
|
|
24
|
+
_QT_ERROR = exc
|
|
25
|
+
else:
|
|
26
|
+
QT_ACTIONS_AVAILABLE = True
|
|
27
|
+
_QT_ERROR = None
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
ActionHandler = Callable[..., Any]
|
|
31
|
+
ActionStateProvider = Callable[
|
|
32
|
+
[str | None, object | None],
|
|
33
|
+
Mapping[str, ActionState],
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
if QT_ACTIONS_AVAILABLE:
|
|
38
|
+
from .qt_icons import load_pycforge_icon
|
|
39
|
+
|
|
40
|
+
_STANDARD_KEYS = {
|
|
41
|
+
"Open": QKeySequence.StandardKey.Open,
|
|
42
|
+
"New": QKeySequence.StandardKey.New,
|
|
43
|
+
"Save": QKeySequence.StandardKey.Save,
|
|
44
|
+
"SaveAs": QKeySequence.StandardKey.SaveAs,
|
|
45
|
+
"Undo": QKeySequence.StandardKey.Undo,
|
|
46
|
+
"Redo": QKeySequence.StandardKey.Redo,
|
|
47
|
+
"Cut": QKeySequence.StandardKey.Cut,
|
|
48
|
+
"Copy": QKeySequence.StandardKey.Copy,
|
|
49
|
+
"Paste": QKeySequence.StandardKey.Paste,
|
|
50
|
+
"SelectAll": QKeySequence.StandardKey.SelectAll,
|
|
51
|
+
"Find": QKeySequence.StandardKey.Find,
|
|
52
|
+
"Replace": QKeySequence.StandardKey.Replace,
|
|
53
|
+
"FindNext": QKeySequence.StandardKey.FindNext,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
class QtActionRegistry(QObject):
|
|
57
|
+
"""Own exactly one QAction per declared non-parameterized action."""
|
|
58
|
+
|
|
59
|
+
def __init__(
|
|
60
|
+
self,
|
|
61
|
+
owner: QWidget,
|
|
62
|
+
handlers: Mapping[str, ActionHandler] | None = None,
|
|
63
|
+
*,
|
|
64
|
+
state_provider: ActionStateProvider | None = None,
|
|
65
|
+
action_specs: Mapping[str, ActionSpec] = ACTION_SPECS,
|
|
66
|
+
) -> None:
|
|
67
|
+
if owner is None:
|
|
68
|
+
raise TypeError("owner must be a QWidget")
|
|
69
|
+
super().__init__(owner)
|
|
70
|
+
self._owner = owner
|
|
71
|
+
self._specs = dict(action_specs)
|
|
72
|
+
self._handlers = dict(handlers or {})
|
|
73
|
+
self._state_provider = state_provider
|
|
74
|
+
self._actions: dict[str, QAction] = {}
|
|
75
|
+
self._exclusive_groups: list[QActionGroup] = []
|
|
76
|
+
self._dynamic_actions: dict[str, tuple[QAction, ...]] = {}
|
|
77
|
+
self._last_states: dict[str, ActionState] = {}
|
|
78
|
+
self._active_surface_id: str | None = None
|
|
79
|
+
self._active_target: object | None = None
|
|
80
|
+
for action_id, spec in self._specs.items():
|
|
81
|
+
if spec.dynamic:
|
|
82
|
+
continue
|
|
83
|
+
action = self._materialize(spec)
|
|
84
|
+
self._actions[action_id] = action
|
|
85
|
+
if spec.shortcut_context == "window":
|
|
86
|
+
owner.addAction(action)
|
|
87
|
+
self.refresh()
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def active_surface_id(self) -> str | None:
|
|
91
|
+
return self._active_surface_id
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def active_target(self) -> object | None:
|
|
95
|
+
return self._active_target
|
|
96
|
+
|
|
97
|
+
def action(self, action_id: str) -> QAction:
|
|
98
|
+
"""Return the sole QAction for a declared static action."""
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
return self._actions[action_id]
|
|
102
|
+
except KeyError as exc:
|
|
103
|
+
if action_id in self._specs:
|
|
104
|
+
raise KeyError(
|
|
105
|
+
f"dynamic action has no static instance: {action_id}"
|
|
106
|
+
) from exc
|
|
107
|
+
raise KeyError(f"unknown PyCForge action: {action_id}") from exc
|
|
108
|
+
|
|
109
|
+
def spec(self, action_id: str) -> ActionSpec:
|
|
110
|
+
try:
|
|
111
|
+
return self._specs[action_id]
|
|
112
|
+
except KeyError as exc:
|
|
113
|
+
raise KeyError(
|
|
114
|
+
f"unknown PyCForge action: {action_id}"
|
|
115
|
+
) from exc
|
|
116
|
+
|
|
117
|
+
def static_action_ids(self) -> tuple[str, ...]:
|
|
118
|
+
return tuple(self._actions)
|
|
119
|
+
|
|
120
|
+
def is_disabled_window_shortcut(
|
|
121
|
+
self,
|
|
122
|
+
key: int,
|
|
123
|
+
modifiers: int,
|
|
124
|
+
) -> bool:
|
|
125
|
+
"""Return whether a reserved disabled shortcut must be consumed."""
|
|
126
|
+
|
|
127
|
+
modifier_value = getattr(modifiers, "value", modifiers)
|
|
128
|
+
key_value = getattr(key, "value", key)
|
|
129
|
+
sequence = QKeySequence(
|
|
130
|
+
int(modifier_value) | int(key_value)
|
|
131
|
+
)
|
|
132
|
+
for action_id, action in self._actions.items():
|
|
133
|
+
shortcut = action.shortcut()
|
|
134
|
+
if (
|
|
135
|
+
self._specs[action_id].shortcut_context == "window"
|
|
136
|
+
and not action.isEnabled()
|
|
137
|
+
and not shortcut.isEmpty()
|
|
138
|
+
and sequence.matches(shortcut)
|
|
139
|
+
== QKeySequence.SequenceMatch.ExactMatch
|
|
140
|
+
):
|
|
141
|
+
return True
|
|
142
|
+
return False
|
|
143
|
+
|
|
144
|
+
def make_exclusive(self, action_ids: tuple[str, ...]) -> None:
|
|
145
|
+
"""Keep one checked choice across menu and command-palette actions."""
|
|
146
|
+
|
|
147
|
+
actions = tuple(self.action(action_id) for action_id in action_ids)
|
|
148
|
+
if not actions or any(not action.isCheckable() for action in actions):
|
|
149
|
+
raise ValueError("exclusive choices must be checkable actions")
|
|
150
|
+
group = QActionGroup(self)
|
|
151
|
+
group.setExclusive(True)
|
|
152
|
+
for action in actions:
|
|
153
|
+
group.addAction(action)
|
|
154
|
+
self._exclusive_groups.append(group)
|
|
155
|
+
|
|
156
|
+
def register_handler(
|
|
157
|
+
self, action_id: str, handler: ActionHandler
|
|
158
|
+
) -> None:
|
|
159
|
+
if action_id not in self._actions:
|
|
160
|
+
raise KeyError(f"unknown static action: {action_id}")
|
|
161
|
+
if not callable(handler):
|
|
162
|
+
raise TypeError("action handler must be callable")
|
|
163
|
+
self._handlers[action_id] = handler
|
|
164
|
+
self.refresh()
|
|
165
|
+
|
|
166
|
+
def unregister_handler(self, action_id: str) -> None:
|
|
167
|
+
self._handlers.pop(action_id, None)
|
|
168
|
+
self.refresh()
|
|
169
|
+
|
|
170
|
+
def set_state_provider(
|
|
171
|
+
self, provider: ActionStateProvider | None
|
|
172
|
+
) -> None:
|
|
173
|
+
if provider is not None and not callable(provider):
|
|
174
|
+
raise TypeError("state provider must be callable")
|
|
175
|
+
self._state_provider = provider
|
|
176
|
+
self.refresh()
|
|
177
|
+
|
|
178
|
+
def set_active_context(
|
|
179
|
+
self, surface_id: str | None, target: object | None
|
|
180
|
+
) -> None:
|
|
181
|
+
self._active_surface_id = surface_id
|
|
182
|
+
self._active_target = target
|
|
183
|
+
self.refresh()
|
|
184
|
+
|
|
185
|
+
def clear_active_context(self) -> None:
|
|
186
|
+
self.set_active_context(None, None)
|
|
187
|
+
|
|
188
|
+
def refresh(
|
|
189
|
+
self,
|
|
190
|
+
states: Mapping[str, ActionState] | None = None,
|
|
191
|
+
) -> None:
|
|
192
|
+
"""Project bounded application state onto every static action."""
|
|
193
|
+
|
|
194
|
+
if states is None and self._state_provider is not None:
|
|
195
|
+
states = self._state_provider(
|
|
196
|
+
self._active_surface_id,
|
|
197
|
+
self._active_target,
|
|
198
|
+
)
|
|
199
|
+
if states is not None:
|
|
200
|
+
unknown = set(states).difference(self._actions)
|
|
201
|
+
if unknown:
|
|
202
|
+
raise KeyError(
|
|
203
|
+
f"state supplied for unknown actions: {sorted(unknown)}"
|
|
204
|
+
)
|
|
205
|
+
if any(
|
|
206
|
+
not isinstance(value, ActionState)
|
|
207
|
+
for value in states.values()
|
|
208
|
+
):
|
|
209
|
+
raise TypeError("action states must be ActionState values")
|
|
210
|
+
self._last_states = dict(states)
|
|
211
|
+
for action_id, action in self._actions.items():
|
|
212
|
+
state = self._last_states.get(action_id, ActionState())
|
|
213
|
+
enabled = state.enabled and action_id in self._handlers
|
|
214
|
+
# QAction changes are observed by every materialized menu and
|
|
215
|
+
# toolbar button. Re-applying an identical value needlessly
|
|
216
|
+
# invalidates their styles and can visibly flash busy chrome
|
|
217
|
+
# while the editor publishes rapid, unrelated snapshots.
|
|
218
|
+
if action.isEnabled() != enabled:
|
|
219
|
+
action.setEnabled(enabled)
|
|
220
|
+
if action.isVisible() != state.visible:
|
|
221
|
+
action.setVisible(state.visible)
|
|
222
|
+
if (
|
|
223
|
+
action.isCheckable()
|
|
224
|
+
and state.checked is not None
|
|
225
|
+
and action.isChecked() != bool(state.checked)
|
|
226
|
+
):
|
|
227
|
+
blocker = QSignalBlocker(action)
|
|
228
|
+
action.setChecked(bool(state.checked))
|
|
229
|
+
del blocker
|
|
230
|
+
|
|
231
|
+
def set_enabled(self, action_id: str, enabled: bool) -> None:
|
|
232
|
+
current = self._last_states.get(action_id, ActionState())
|
|
233
|
+
self._last_states[action_id] = ActionState(
|
|
234
|
+
enabled=bool(enabled),
|
|
235
|
+
checked=current.checked,
|
|
236
|
+
visible=current.visible,
|
|
237
|
+
)
|
|
238
|
+
self.refresh(self._last_states)
|
|
239
|
+
|
|
240
|
+
def set_checked(self, action_id: str, checked: bool) -> None:
|
|
241
|
+
action = self.action(action_id)
|
|
242
|
+
if not action.isCheckable():
|
|
243
|
+
raise ValueError(f"action is not checkable: {action_id}")
|
|
244
|
+
current = self._last_states.get(action_id, ActionState())
|
|
245
|
+
self._last_states[action_id] = ActionState(
|
|
246
|
+
enabled=current.enabled,
|
|
247
|
+
checked=bool(checked),
|
|
248
|
+
visible=current.visible,
|
|
249
|
+
)
|
|
250
|
+
self.refresh(self._last_states)
|
|
251
|
+
|
|
252
|
+
def attach_to_widget(
|
|
253
|
+
self, action_id: str, widget: QWidget
|
|
254
|
+
) -> QAction:
|
|
255
|
+
"""Attach a widget-scoped shortcut to its intended owner."""
|
|
256
|
+
|
|
257
|
+
action = self.action(action_id)
|
|
258
|
+
if self.spec(action_id).shortcut_context != "widget":
|
|
259
|
+
raise ValueError(
|
|
260
|
+
f"action is not widget-scoped: {action_id}"
|
|
261
|
+
)
|
|
262
|
+
widget.addAction(action)
|
|
263
|
+
return action
|
|
264
|
+
|
|
265
|
+
def bind_tool_button(
|
|
266
|
+
self,
|
|
267
|
+
action_id: str,
|
|
268
|
+
button: QToolButton,
|
|
269
|
+
*,
|
|
270
|
+
accessible_description: str | None = None,
|
|
271
|
+
) -> None:
|
|
272
|
+
"""Bind a button without duplicating labels, icons, or callbacks."""
|
|
273
|
+
|
|
274
|
+
if not isinstance(button, QToolButton):
|
|
275
|
+
raise TypeError("button must be a QToolButton")
|
|
276
|
+
spec = self.spec(action_id)
|
|
277
|
+
button.setDefaultAction(self.action(action_id))
|
|
278
|
+
button.setAccessibleName(spec.accessible_name)
|
|
279
|
+
if accessible_description:
|
|
280
|
+
button.setAccessibleDescription(accessible_description)
|
|
281
|
+
|
|
282
|
+
def replace_dynamic(
|
|
283
|
+
self,
|
|
284
|
+
group_id: str,
|
|
285
|
+
entries: tuple[DynamicActionEntry, ...] | list[DynamicActionEntry],
|
|
286
|
+
handler: Callable[[str], Any],
|
|
287
|
+
) -> tuple[QAction, ...]:
|
|
288
|
+
"""Replace a bounded parameterized group owned by this registry."""
|
|
289
|
+
|
|
290
|
+
if group_id not in DYNAMIC_ACTION_GROUPS:
|
|
291
|
+
raise KeyError(f"unknown dynamic action group: {group_id}")
|
|
292
|
+
if not callable(handler):
|
|
293
|
+
raise TypeError("dynamic action handler must be callable")
|
|
294
|
+
records = validated_dynamic_entries(entries)
|
|
295
|
+
if not records:
|
|
296
|
+
records = (
|
|
297
|
+
DynamicActionEntry(
|
|
298
|
+
key="empty",
|
|
299
|
+
label="No recent Python documents",
|
|
300
|
+
tooltip="No recent Python documents are available",
|
|
301
|
+
accessible_name="No recent Python documents",
|
|
302
|
+
payload="",
|
|
303
|
+
enabled=False,
|
|
304
|
+
),
|
|
305
|
+
)
|
|
306
|
+
for action in self._dynamic_actions.get(group_id, ()):
|
|
307
|
+
action.setParent(None)
|
|
308
|
+
action.deleteLater()
|
|
309
|
+
template = self.spec(DYNAMIC_ACTION_GROUPS[group_id])
|
|
310
|
+
actions = tuple(
|
|
311
|
+
self._materialize_dynamic(
|
|
312
|
+
group_id, template, entry, handler, index
|
|
313
|
+
)
|
|
314
|
+
for index, entry in enumerate(records)
|
|
315
|
+
)
|
|
316
|
+
self._dynamic_actions[group_id] = actions
|
|
317
|
+
return actions
|
|
318
|
+
|
|
319
|
+
def dynamic_actions(self, group_id: str) -> tuple[QAction, ...]:
|
|
320
|
+
if group_id not in DYNAMIC_ACTION_GROUPS:
|
|
321
|
+
raise KeyError(f"unknown dynamic action group: {group_id}")
|
|
322
|
+
return self._dynamic_actions.get(group_id, ())
|
|
323
|
+
|
|
324
|
+
def _materialize(self, spec: ActionSpec) -> QAction:
|
|
325
|
+
icon = (
|
|
326
|
+
load_pycforge_icon(spec.icon_name)
|
|
327
|
+
if spec.icon_name else QIcon()
|
|
328
|
+
)
|
|
329
|
+
action = QAction(icon, spec.menu_text, self._owner)
|
|
330
|
+
action.setObjectName(
|
|
331
|
+
"pycforgeAction__" + spec.action_id.replace(".", "__")
|
|
332
|
+
)
|
|
333
|
+
action.setData(spec.action_id)
|
|
334
|
+
action.setIconText(spec.toolbar_text)
|
|
335
|
+
action.setCheckable(spec.checkable)
|
|
336
|
+
action.setAutoRepeat(False)
|
|
337
|
+
action.setProperty("pycforgeActionId", spec.action_id)
|
|
338
|
+
action.setProperty("pycforgeTone", spec.tone)
|
|
339
|
+
action.setProperty(
|
|
340
|
+
"pycforgeAccessibleName", spec.accessible_name
|
|
341
|
+
)
|
|
342
|
+
sequence = self._shortcut(spec)
|
|
343
|
+
if sequence is not None:
|
|
344
|
+
action.setShortcut(sequence)
|
|
345
|
+
context = (
|
|
346
|
+
Qt.ShortcutContext.WidgetWithChildrenShortcut
|
|
347
|
+
if spec.shortcut_context == "widget"
|
|
348
|
+
else Qt.ShortcutContext.WindowShortcut
|
|
349
|
+
)
|
|
350
|
+
action.setShortcutContext(context)
|
|
351
|
+
tooltip = self._tooltip(spec.tooltip, sequence)
|
|
352
|
+
action.setToolTip(tooltip)
|
|
353
|
+
action.setWhatsThis(spec.tooltip)
|
|
354
|
+
action.triggered.connect(
|
|
355
|
+
lambda checked=False, action_id=spec.action_id:
|
|
356
|
+
self._invoke(action_id, checked)
|
|
357
|
+
)
|
|
358
|
+
return action
|
|
359
|
+
|
|
360
|
+
def _materialize_dynamic(
|
|
361
|
+
self,
|
|
362
|
+
group_id: str,
|
|
363
|
+
template: ActionSpec,
|
|
364
|
+
entry: DynamicActionEntry,
|
|
365
|
+
handler: Callable[[str], Any],
|
|
366
|
+
index: int,
|
|
367
|
+
) -> QAction:
|
|
368
|
+
icon = (
|
|
369
|
+
load_pycforge_icon(template.icon_name)
|
|
370
|
+
if template.icon_name else QIcon()
|
|
371
|
+
)
|
|
372
|
+
action = QAction(
|
|
373
|
+
icon, entry.label.replace("&", "&&"), self._owner
|
|
374
|
+
)
|
|
375
|
+
action.setObjectName(
|
|
376
|
+
f"pycforgeDynamic__{group_id}__{index}"
|
|
377
|
+
)
|
|
378
|
+
action.setData((group_id, entry.key))
|
|
379
|
+
action.setEnabled(entry.enabled)
|
|
380
|
+
action.setToolTip(entry.tooltip)
|
|
381
|
+
action.setProperty("pycforgeActionId", template.action_id)
|
|
382
|
+
action.setProperty("pycforgeTone", template.tone)
|
|
383
|
+
action.setProperty(
|
|
384
|
+
"pycforgeAccessibleName", entry.accessible_name
|
|
385
|
+
)
|
|
386
|
+
if entry.enabled:
|
|
387
|
+
action.triggered.connect(
|
|
388
|
+
lambda checked=False, payload=entry.payload:
|
|
389
|
+
handler(payload)
|
|
390
|
+
)
|
|
391
|
+
return action
|
|
392
|
+
|
|
393
|
+
def _invoke(self, action_id: str, checked: bool) -> None:
|
|
394
|
+
handler = self._handlers.get(action_id)
|
|
395
|
+
if handler is None:
|
|
396
|
+
return
|
|
397
|
+
if self._specs[action_id].checkable:
|
|
398
|
+
handler(bool(checked))
|
|
399
|
+
else:
|
|
400
|
+
handler()
|
|
401
|
+
|
|
402
|
+
@staticmethod
|
|
403
|
+
def _shortcut(spec: ActionSpec) -> QKeySequence | None:
|
|
404
|
+
if spec.standard_shortcut:
|
|
405
|
+
try:
|
|
406
|
+
return QKeySequence(
|
|
407
|
+
_STANDARD_KEYS[spec.standard_shortcut]
|
|
408
|
+
)
|
|
409
|
+
except KeyError as exc:
|
|
410
|
+
raise ValueError(
|
|
411
|
+
"unknown standard shortcut: "
|
|
412
|
+
f"{spec.standard_shortcut}"
|
|
413
|
+
) from exc
|
|
414
|
+
if spec.shortcut:
|
|
415
|
+
return QKeySequence(spec.shortcut)
|
|
416
|
+
return None
|
|
417
|
+
|
|
418
|
+
@staticmethod
|
|
419
|
+
def _tooltip(
|
|
420
|
+
tooltip: str, sequence: QKeySequence | None
|
|
421
|
+
) -> str:
|
|
422
|
+
if sequence is None or sequence.isEmpty():
|
|
423
|
+
return tooltip
|
|
424
|
+
rendered = sequence.toString(
|
|
425
|
+
QKeySequence.SequenceFormat.NativeText
|
|
426
|
+
)
|
|
427
|
+
return f"{tooltip} ({rendered})" if rendered else tooltip
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def build_window_system_actions(
|
|
431
|
+
owner: QWidget,
|
|
432
|
+
handlers: Mapping[str, ActionHandler],
|
|
433
|
+
) -> dict[str, QAction]:
|
|
434
|
+
"""Create the bounded frameless-window commands at the action seam.
|
|
435
|
+
|
|
436
|
+
These four platform-window commands are not workspace actions and do
|
|
437
|
+
not expand the frozen declarative action contract. Their QAction
|
|
438
|
+
construction still remains singly owned by this module.
|
|
439
|
+
"""
|
|
440
|
+
|
|
441
|
+
if owner is None:
|
|
442
|
+
raise TypeError("owner must be a QWidget")
|
|
443
|
+
specifications = (
|
|
444
|
+
("restore", "&Restore", "Restore window", None),
|
|
445
|
+
("minimize", "Mi&nimize", "Minimize window", None),
|
|
446
|
+
("maximize", "Ma&ximize", "Maximize window", None),
|
|
447
|
+
("close", "&Close", "Close window", "Alt+F4"),
|
|
448
|
+
)
|
|
449
|
+
required = {key for key, *_remainder in specifications}
|
|
450
|
+
if set(handlers) != required or any(
|
|
451
|
+
not callable(handlers[key]) for key in required
|
|
452
|
+
):
|
|
453
|
+
raise ValueError(
|
|
454
|
+
"window system handlers must be exactly restore, minimize, "
|
|
455
|
+
"maximize, and close"
|
|
456
|
+
)
|
|
457
|
+
|
|
458
|
+
actions: dict[str, QAction] = {}
|
|
459
|
+
for key, label, description, shortcut in specifications:
|
|
460
|
+
action = QAction(label, owner)
|
|
461
|
+
action.setObjectName(f"pycforgeWindowAction__{key}")
|
|
462
|
+
action.setData(("window-system", key))
|
|
463
|
+
action.setAutoRepeat(False)
|
|
464
|
+
action.setProperty("pycforgeWindowCommand", key)
|
|
465
|
+
action.setProperty("pycforgeAccessibleName", description)
|
|
466
|
+
action.setToolTip(description)
|
|
467
|
+
if shortcut is not None:
|
|
468
|
+
action.setShortcut(QKeySequence(shortcut))
|
|
469
|
+
action.setShortcutContext(
|
|
470
|
+
Qt.ShortcutContext.WindowShortcut
|
|
471
|
+
)
|
|
472
|
+
action.triggered.connect(
|
|
473
|
+
lambda _checked=False, callback=handlers[key]: callback()
|
|
474
|
+
)
|
|
475
|
+
actions[key] = action
|
|
476
|
+
return actions
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
else:
|
|
480
|
+
class QtActionRegistry:
|
|
481
|
+
"""Import-safe placeholder for a damaged installation without PySide6."""
|
|
482
|
+
|
|
483
|
+
def __init__(self, *_args, **_kwargs) -> None:
|
|
484
|
+
raise RuntimeError(
|
|
485
|
+
"PySide6 is required for the PyCForge action registry"
|
|
486
|
+
) from _QT_ERROR
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
def build_window_system_actions(*_args, **_kwargs):
|
|
490
|
+
raise RuntimeError(
|
|
491
|
+
"PySide6 is required for PyCForge window actions"
|
|
492
|
+
) from _QT_ERROR
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
__all__ = [
|
|
496
|
+
"ActionHandler",
|
|
497
|
+
"ActionStateProvider",
|
|
498
|
+
"QT_ACTIONS_AVAILABLE",
|
|
499
|
+
"QtActionRegistry",
|
|
500
|
+
"build_window_system_actions",
|
|
501
|
+
]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Accessible PyCForge lettering with a consistent steel-blue C."""
|
|
2
|
+
from html import escape
|
|
3
|
+
|
|
4
|
+
from PySide6.QtCore import Qt
|
|
5
|
+
from PySide6.QtWidgets import QLabel
|
|
6
|
+
|
|
7
|
+
from .qt_workspace_widgets import ElidedLabel
|
|
8
|
+
from .visual_tokens import PYCFORGE_COLORS
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def brand_html(text: str) -> str:
|
|
12
|
+
"""Escape arbitrary titles before adding the single brand accent."""
|
|
13
|
+
return escape(text).replace(
|
|
14
|
+
'PyCForge', f'Py<span style="color:{PYCFORGE_COLORS.blue}">C</span>Forge'
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class BrandLabel(QLabel):
|
|
19
|
+
"""Keep plain semantic text available while painting the brand accent."""
|
|
20
|
+
def __init__(self, text='', parent=None):
|
|
21
|
+
super().__init__(parent)
|
|
22
|
+
self.setTextFormat(Qt.TextFormat.RichText)
|
|
23
|
+
self.setText(text)
|
|
24
|
+
|
|
25
|
+
def setText(self, text):
|
|
26
|
+
self._plain_text = str(text)
|
|
27
|
+
super().setText(brand_html(self._plain_text))
|
|
28
|
+
self.setAccessibleName(self._plain_text)
|
|
29
|
+
|
|
30
|
+
def text(self):
|
|
31
|
+
return self._plain_text
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class BrandElidedLabel(ElidedLabel):
|
|
35
|
+
"""Elide plain title text first; markup never affects width or identity."""
|
|
36
|
+
_displayed_plain = ""
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def displayed_text(self):
|
|
40
|
+
return self._displayed_plain
|
|
41
|
+
|
|
42
|
+
def _refresh_elision(self):
|
|
43
|
+
self._displayed_plain = self.fontMetrics().elidedText(
|
|
44
|
+
self._full_text, self._elide_mode, max(0, self.contentsRect().width() - 2)
|
|
45
|
+
)
|
|
46
|
+
self.setTextFormat(Qt.TextFormat.RichText)
|
|
47
|
+
QLabel.setText(self, brand_html(self._displayed_plain))
|