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,412 @@
|
|
|
1
|
+
"""Explained project forms. Engine reference data supplies operation choices."""
|
|
2
|
+
import copy
|
|
3
|
+
import json
|
|
4
|
+
from PySide6.QtCore import Signal, Qt
|
|
5
|
+
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QFormLayout,
|
|
6
|
+
QTabWidget, QScrollArea, QLineEdit, QPlainTextEdit, QComboBox, QSpinBox,
|
|
7
|
+
QGroupBox, QListWidget, QSplitter, QDialog, QCheckBox)
|
|
8
|
+
from ..project import parse
|
|
9
|
+
from ..results import SDKError
|
|
10
|
+
from .widgets import label, button
|
|
11
|
+
from .dialogs import Dialog
|
|
12
|
+
from .jobs import JobRunner
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DraftDialog(Dialog):
|
|
16
|
+
close_pending = False
|
|
17
|
+
def reject(self):
|
|
18
|
+
if self.runner.busy:
|
|
19
|
+
self.close_pending = True
|
|
20
|
+
self.runner.cancel()
|
|
21
|
+
self.problem.setText("Canceling draft validation…")
|
|
22
|
+
return
|
|
23
|
+
super().reject()
|
|
24
|
+
|
|
25
|
+
def closeEvent(self, event):
|
|
26
|
+
event.ignore(); self.reject()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def pointer(parts):
|
|
30
|
+
return "/" + "/".join(str(p).replace("~", "~0").replace("/", "~1") for p in parts)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ProjectEditor(QWidget):
|
|
34
|
+
changed = Signal()
|
|
35
|
+
source_requested = Signal(str)
|
|
36
|
+
|
|
37
|
+
def __init__(self, parent=None):
|
|
38
|
+
super().__init__(parent)
|
|
39
|
+
self.layout = QVBoxLayout(self)
|
|
40
|
+
self.layout.setContentsMargins(0, 0, 0, 0)
|
|
41
|
+
self.tabs = QTabWidget()
|
|
42
|
+
self.layout.addWidget(self.tabs)
|
|
43
|
+
self.fields = {}
|
|
44
|
+
self.draft = None
|
|
45
|
+
self.methods, self.operations = [], []
|
|
46
|
+
self.workbench = None
|
|
47
|
+
|
|
48
|
+
def load(self, document, *, methods=(), operations=(), workbench=None):
|
|
49
|
+
self.draft = copy.deepcopy(document)
|
|
50
|
+
self.methods, self.operations = methods, operations
|
|
51
|
+
self.workbench = workbench
|
|
52
|
+
self.fields = {}
|
|
53
|
+
while self.tabs.count():
|
|
54
|
+
page = self.tabs.widget(0); self.tabs.removeTab(0); page.deleteLater()
|
|
55
|
+
self.project_page()
|
|
56
|
+
self.function_page()
|
|
57
|
+
self.help_page()
|
|
58
|
+
self.fixtures_page()
|
|
59
|
+
|
|
60
|
+
def page(self, title, description):
|
|
61
|
+
body = QWidget(); layout = QVBoxLayout(body)
|
|
62
|
+
layout.addWidget(label(description, muted=True))
|
|
63
|
+
scroll = QScrollArea(); scroll.setWidgetResizable(True); scroll.setWidget(body)
|
|
64
|
+
self.tabs.addTab(scroll, title)
|
|
65
|
+
return layout, scroll
|
|
66
|
+
|
|
67
|
+
def get(self, parts):
|
|
68
|
+
value = self.draft
|
|
69
|
+
for part in parts: value = value[part]
|
|
70
|
+
return value
|
|
71
|
+
|
|
72
|
+
def put(self, parts, value):
|
|
73
|
+
target = self.draft
|
|
74
|
+
for part in parts[:-1]: target = target[part]
|
|
75
|
+
target[parts[-1]] = value
|
|
76
|
+
self.changed.emit()
|
|
77
|
+
|
|
78
|
+
def field(self, form, title, parts, description="", *, choices=None, multiline=False, page=None):
|
|
79
|
+
value = self.get(parts)
|
|
80
|
+
if choices:
|
|
81
|
+
edit = QComboBox()
|
|
82
|
+
for choice in choices: edit.addItem(str(choice), choice)
|
|
83
|
+
index = next((i for i in range(edit.count()) if type(edit.itemData(i)) is type(value) and edit.itemData(i) == value), -1)
|
|
84
|
+
if index < 0: edit.addItem(str(value), value); index = edit.count()-1
|
|
85
|
+
edit.setCurrentIndex(index)
|
|
86
|
+
edit.currentIndexChanged.connect(lambda _i: self.put(parts, edit.currentData()))
|
|
87
|
+
elif type(value) is int:
|
|
88
|
+
edit = QSpinBox(); edit.setRange(-2147483647, 2147483647); edit.setValue(value)
|
|
89
|
+
edit.valueChanged.connect(lambda v: self.put(parts, v))
|
|
90
|
+
elif multiline:
|
|
91
|
+
edit = QPlainTextEdit(str(value)); edit.setMinimumHeight(86); edit.setMaximumHeight(150)
|
|
92
|
+
edit.textChanged.connect(lambda: self.put(parts, edit.toPlainText()))
|
|
93
|
+
else:
|
|
94
|
+
edit = QLineEdit(str(value))
|
|
95
|
+
edit.textChanged.connect(lambda v: self.put(parts, v))
|
|
96
|
+
edit.setAccessibleName(title)
|
|
97
|
+
edit.setAccessibleDescription(description)
|
|
98
|
+
edit.setToolTip(description)
|
|
99
|
+
caption = label(title); caption.setBuddy(edit)
|
|
100
|
+
form.addRow(caption, edit)
|
|
101
|
+
if description:
|
|
102
|
+
hint = label(description, muted=True)
|
|
103
|
+
form.addRow("", hint)
|
|
104
|
+
self.fields[pointer(parts)] = (edit, page)
|
|
105
|
+
return edit
|
|
106
|
+
|
|
107
|
+
def reference(self, name):
|
|
108
|
+
return next((e for e in self.methods if e["id"].endswith("." + name)), {})
|
|
109
|
+
|
|
110
|
+
def profile(self):
|
|
111
|
+
schema = self.draft.get("declaration", {}).get("schema")
|
|
112
|
+
return next((p for p in (self.workbench or {}).get("profiles", []) if p["declaration_schema"] == schema), None)
|
|
113
|
+
|
|
114
|
+
def engine_field(self, form, definition, parts, page):
|
|
115
|
+
"""Render inert field metadata; never import a renderer from the engine."""
|
|
116
|
+
title, kind = definition["title"], definition["kind"]
|
|
117
|
+
description = definition.get("description", "")
|
|
118
|
+
value = self.get(parts)
|
|
119
|
+
if kind == "boolean" and type(value) is bool:
|
|
120
|
+
control = QCheckBox(title); control.setChecked(value)
|
|
121
|
+
control.toggled.connect(lambda checked: self.put(parts, checked))
|
|
122
|
+
form.addRow(control)
|
|
123
|
+
elif kind == "json" or (kind != "choice" and type(value) is not str):
|
|
124
|
+
control = button("Edit value…", "details", lambda: self.edit_value(parts, title, control))
|
|
125
|
+
control.setToolTip(json.dumps(value, ensure_ascii=False))
|
|
126
|
+
form.addRow(label(title), control)
|
|
127
|
+
else:
|
|
128
|
+
options = definition.get("options", [])
|
|
129
|
+
control = self.field(form, title, parts, description,
|
|
130
|
+
choices=[o["value"] for o in options] if options else None,
|
|
131
|
+
multiline=kind == "multiline", page=page)
|
|
132
|
+
if isinstance(control, QComboBox):
|
|
133
|
+
for row in range(control.count()):
|
|
134
|
+
option = next((o for o in options if o["value"] == control.itemData(row)), None)
|
|
135
|
+
if option:
|
|
136
|
+
control.setItemText(row, option["title"])
|
|
137
|
+
control.setItemData(row, option.get("description", ""), Qt.ItemDataRole.ToolTipRole)
|
|
138
|
+
return control
|
|
139
|
+
control.setAccessibleName(title); control.setAccessibleDescription(description)
|
|
140
|
+
if description: form.addRow("", label(description, muted=True))
|
|
141
|
+
self.fields[pointer(parts)] = (control, page)
|
|
142
|
+
return control
|
|
143
|
+
|
|
144
|
+
def edit_value(self, parts, title, control):
|
|
145
|
+
dlg = Dialog(title, self)
|
|
146
|
+
dlg.body.addWidget(label("Edit this value as JSON. The connected engine validates its conversion meaning when you scan."))
|
|
147
|
+
source = QPlainTextEdit(json.dumps(self.get(parts), indent=2)); source.setAccessibleName(title)
|
|
148
|
+
dlg.body.addWidget(source, 1); problem = label(""); dlg.body.addWidget(problem)
|
|
149
|
+
def apply():
|
|
150
|
+
try:
|
|
151
|
+
if len(source.toPlainText().encode('utf-8')) > 256 * 1024:
|
|
152
|
+
raise SDKError("SDK_LIMIT", "The value exceeds the editor size budget.")
|
|
153
|
+
value = parse(source.toPlainText())
|
|
154
|
+
except SDKError as exc:
|
|
155
|
+
problem.setText(str(exc)); return
|
|
156
|
+
self.put(parts, value); control.setToolTip(json.dumps(value, ensure_ascii=False)); dlg.accept()
|
|
157
|
+
row = QHBoxLayout(); row.addWidget(button("Apply", "check", apply)); row.addWidget(button("Cancel", "cancel", dlg.reject))
|
|
158
|
+
dlg.body.addLayout(row); dlg.resize(650, 440); dlg.exec()
|
|
159
|
+
|
|
160
|
+
def project_page(self):
|
|
161
|
+
layout, page = self.page("Project", "Give this conversion extension a clear identity. Changing any saved field requires fresh verification.")
|
|
162
|
+
form = QFormLayout(); layout.addLayout(form)
|
|
163
|
+
descriptions = {
|
|
164
|
+
"package_id": "Stable package identity, for example org.example.vectors.",
|
|
165
|
+
"namespace": "The name used in the editor after *import.",
|
|
166
|
+
"version": "The version you intend to package. Publishing remains your separate decision.",
|
|
167
|
+
"author": "The person or organization responsible for this extension.",
|
|
168
|
+
"description": "A short explanation of what this extension provides.",
|
|
169
|
+
"created": "Creation date recorded in the package metadata.", "license": "The license for your extension."}
|
|
170
|
+
profile = self.profile()
|
|
171
|
+
if profile:
|
|
172
|
+
for definition in profile["fields"]:
|
|
173
|
+
key = definition["name"]
|
|
174
|
+
if key in self.draft.get("declaration", {}):
|
|
175
|
+
self.engine_field(form, definition, ["declaration", key], page)
|
|
176
|
+
else:
|
|
177
|
+
for key in ("package_id", "namespace", "version"):
|
|
178
|
+
if key in self.draft.get("declaration", {}):
|
|
179
|
+
self.field(form, key.replace("_", " ").title(), ["declaration", key], descriptions[key], page=page)
|
|
180
|
+
for key in ("author", "description", "created", "license"):
|
|
181
|
+
self.field(form, key.title(), ["metadata", key], descriptions[key], multiline=key=="description", page=page)
|
|
182
|
+
layout.addWidget(button("Advanced project data…", "details", self.advanced,
|
|
183
|
+
"Edit the complete JSON project. Keep normal work in the explained forms."))
|
|
184
|
+
layout.addStretch()
|
|
185
|
+
|
|
186
|
+
def function_page(self):
|
|
187
|
+
layout, page = self.page("Functions", "Choose a function to explain its conversion contract. The connected engine defines the available operations.")
|
|
188
|
+
self.function_choice = QComboBox()
|
|
189
|
+
for f in self.draft.get("declaration", {}).get("functions", []):
|
|
190
|
+
self.function_choice.addItem(f.get("export", "Unnamed function"))
|
|
191
|
+
self.function_choice.setAccessibleName("Function")
|
|
192
|
+
layout.addWidget(self.function_choice)
|
|
193
|
+
self.function_holder = QWidget(); self.function_layout = QVBoxLayout(self.function_holder)
|
|
194
|
+
self.function_layout.setContentsMargins(0, 0, 0, 0)
|
|
195
|
+
layout.addWidget(self.function_holder); layout.addStretch()
|
|
196
|
+
self.function_tab = page
|
|
197
|
+
self.function_choice.currentIndexChanged.connect(self.show_function)
|
|
198
|
+
self.show_function(0)
|
|
199
|
+
|
|
200
|
+
def clear(self, layout, prefix):
|
|
201
|
+
for key in list(self.fields):
|
|
202
|
+
if key.startswith(prefix): del self.fields[key]
|
|
203
|
+
while layout.count():
|
|
204
|
+
item = layout.takeAt(0)
|
|
205
|
+
if item.widget(): item.widget().hide(); item.widget().deleteLater()
|
|
206
|
+
|
|
207
|
+
def show_function(self, index):
|
|
208
|
+
self.clear(self.function_layout, "/declaration/functions/")
|
|
209
|
+
functions = self.draft.get("declaration", {}).get("functions", [])
|
|
210
|
+
if not 0 <= index < len(functions): return
|
|
211
|
+
function = functions[index]
|
|
212
|
+
if self.workbench is not None:
|
|
213
|
+
self.show_engine_function(index, function)
|
|
214
|
+
return
|
|
215
|
+
array = self.draft["declaration"].get("schema", "").startswith("crucible.array-")
|
|
216
|
+
ref = self.reference("ArrayFunction" if array else "ScalarFunction")
|
|
217
|
+
params = {p["name"]: p for p in ref.get("parameters", [])}
|
|
218
|
+
body = QWidget(); form = QFormLayout(body); self.function_layout.addWidget(body)
|
|
219
|
+
for key in ("operation_id", "export", "operation", "summary") if array else ("operation_id", "export", "native_symbol", "summary"):
|
|
220
|
+
if key not in function: continue
|
|
221
|
+
choices = [o["id"] for o in self.operations] if key == "operation" else None
|
|
222
|
+
control = self.field(form, {"operation_id": "Stable identity", "export": "Editor name", "operation": "Operation", "native_symbol": "Native symbol", "summary": "Summary"}[key],
|
|
223
|
+
["declaration", "functions", index, key], params.get(key, {}).get("description", ""),
|
|
224
|
+
choices=choices, multiline=key=="summary", page=self.function_tab)
|
|
225
|
+
if key == "summary": control.setMaximumHeight(96)
|
|
226
|
+
if key == "operation" and isinstance(control, QComboBox):
|
|
227
|
+
for row in range(control.count()):
|
|
228
|
+
choice = next((o for o in self.operations if o["id"] == control.itemData(row)), None)
|
|
229
|
+
if choice: control.setItemText(row, choice["title"])
|
|
230
|
+
if array:
|
|
231
|
+
self.contract = label("")
|
|
232
|
+
self.function_layout.addWidget(self.contract)
|
|
233
|
+
def explain():
|
|
234
|
+
value = function.get("operation")
|
|
235
|
+
operation = next((o for o in self.operations if o["id"] == value), {})
|
|
236
|
+
signature = operation.get("signature", "").replace("function(", function.get("export", "function") + "(", 1)
|
|
237
|
+
self.contract.setText(signature + "\n" + operation.get("description", "") +
|
|
238
|
+
"\nThe engine owns array type, storage and cleanup.")
|
|
239
|
+
field = self.fields.get(pointer(["declaration", "functions", index, "operation"]))
|
|
240
|
+
if field and isinstance(field[0], QComboBox): field[0].currentIndexChanged.connect(explain)
|
|
241
|
+
explain()
|
|
242
|
+
else:
|
|
243
|
+
advanced = QGroupBox("More contract settings")
|
|
244
|
+
advanced.setCheckable(True); advanced.setChecked(False)
|
|
245
|
+
outer = QVBoxLayout(advanced); details = QWidget(); detail_form = QFormLayout(details)
|
|
246
|
+
outer.addWidget(details); details.setVisible(False); advanced.toggled.connect(details.setVisible)
|
|
247
|
+
for key, value in function.items():
|
|
248
|
+
if key in ("operation_id", "export", "native_symbol", "summary"): continue
|
|
249
|
+
if isinstance(value, (dict, list)):
|
|
250
|
+
detail_form.addRow(label(key.title() + ": " + json.dumps(value)),
|
|
251
|
+
button("Edit data…", "details", self.advanced))
|
|
252
|
+
else:
|
|
253
|
+
self.field(detail_form, key.replace("_", " ").title(), ["declaration", "functions", index, key],
|
|
254
|
+
params.get(key, {}).get("description", ""), choices=params.get(key, {}).get("choices"), page=self.function_tab)
|
|
255
|
+
self.function_layout.addWidget(advanced)
|
|
256
|
+
|
|
257
|
+
def show_engine_function(self, index, function):
|
|
258
|
+
profile = self.profile()
|
|
259
|
+
if profile is None:
|
|
260
|
+
self.function_layout.addWidget(label("The engine does not advertise a form for this declaration. Use Advanced project data, then Scan to check it."))
|
|
261
|
+
return
|
|
262
|
+
self.function_layout.addWidget(label(profile.get("description", ""), muted=True))
|
|
263
|
+
body = QWidget(); form = QFormLayout(body); self.function_layout.addWidget(body)
|
|
264
|
+
advanced = QGroupBox("More contract settings"); advanced.setCheckable(True); advanced.setChecked(False)
|
|
265
|
+
outer = QVBoxLayout(advanced); details = QWidget(); detail_form = QFormLayout(details)
|
|
266
|
+
outer.addWidget(details); details.hide(); advanced.toggled.connect(details.setVisible)
|
|
267
|
+
has_advanced = False
|
|
268
|
+
for definition in profile["function_fields"]:
|
|
269
|
+
key = definition["name"]
|
|
270
|
+
if key not in function: continue
|
|
271
|
+
is_advanced = definition.get("advanced", False)
|
|
272
|
+
has_advanced |= is_advanced
|
|
273
|
+
self.engine_field(detail_form if is_advanced else form, definition,
|
|
274
|
+
["declaration", "functions", index, key], self.function_tab)
|
|
275
|
+
if has_advanced: self.function_layout.addWidget(advanced)
|
|
276
|
+
else: advanced.deleteLater()
|
|
277
|
+
self.contract = label(""); self.function_layout.addWidget(self.contract)
|
|
278
|
+
operation_field = profile.get("operation_field", "")
|
|
279
|
+
definition = next((f for f in profile["function_fields"] if f["name"] == operation_field), {})
|
|
280
|
+
def explain():
|
|
281
|
+
option = next((o for o in definition.get("options", []) if o["value"] == function.get(operation_field)), {})
|
|
282
|
+
signature = option.get("signature", "").replace("function(", function.get("export", "function") + "(", 1)
|
|
283
|
+
self.contract.setText("\n".join(part for part in (signature, option.get("description", ""), profile.get("contract_note", "")) if part))
|
|
284
|
+
selected = self.fields.get(pointer(["declaration", "functions", index, operation_field]))
|
|
285
|
+
if selected and isinstance(selected[0], QComboBox): selected[0].currentIndexChanged.connect(explain)
|
|
286
|
+
explain()
|
|
287
|
+
|
|
288
|
+
def help_page(self):
|
|
289
|
+
layout, page = self.page("Help", "Write the offline manual that ships inside the extension. Scanner findings take you directly to unfinished fields.")
|
|
290
|
+
self.help_tab = page
|
|
291
|
+
doc = self.draft.get("documentation")
|
|
292
|
+
if not isinstance(doc, dict):
|
|
293
|
+
layout.addWidget(label("This project needs Help fields. Choose Tools → Add missing Help fields, then fill in your explanations.")); return
|
|
294
|
+
form = QFormLayout(); layout.addLayout(form)
|
|
295
|
+
for key in ("overview", "usage", "limitations", "release_notes"):
|
|
296
|
+
if key in doc:
|
|
297
|
+
self.field(form, key.replace("_", " ").title(), ["documentation", key], multiline=True, page=page)
|
|
298
|
+
self.help_choice = QComboBox()
|
|
299
|
+
for name in doc.get("functions", {}): self.help_choice.addItem(name)
|
|
300
|
+
self.help_choice.setAccessibleName("Documented function")
|
|
301
|
+
layout.addWidget(label("Function explanations")); layout.addWidget(self.help_choice)
|
|
302
|
+
self.help_holder = QWidget(); self.help_layout = QVBoxLayout(self.help_holder)
|
|
303
|
+
self.help_layout.setContentsMargins(0, 0, 0, 0)
|
|
304
|
+
layout.addWidget(self.help_holder)
|
|
305
|
+
self.help_choice.currentTextChanged.connect(self.show_function_help)
|
|
306
|
+
self.show_function_help(self.help_choice.currentText())
|
|
307
|
+
constants = doc.get("constants", {})
|
|
308
|
+
if constants:
|
|
309
|
+
cform = QFormLayout(); layout.addLayout(cform)
|
|
310
|
+
for key in constants:
|
|
311
|
+
self.field(cform, "Constant: " + key, ["documentation", "constants", key], multiline=True, page=page)
|
|
312
|
+
layout.addStretch()
|
|
313
|
+
|
|
314
|
+
def show_function_help(self, name):
|
|
315
|
+
self.clear(self.help_layout, "/documentation/functions/")
|
|
316
|
+
function = self.draft.get("documentation", {}).get("functions", {}).get(name)
|
|
317
|
+
if not isinstance(function, dict): return
|
|
318
|
+
body = QWidget(); form = QFormLayout(body); self.help_layout.addWidget(body)
|
|
319
|
+
prefix = ["documentation", "functions", name]
|
|
320
|
+
for i, value in enumerate(function.get("parameters", [])):
|
|
321
|
+
self.field(form, f"Parameter {i+1}", prefix + ["parameters", i], multiline=True, page=self.help_tab)
|
|
322
|
+
for key in ("returns", "details", "example"):
|
|
323
|
+
if key not in function: continue
|
|
324
|
+
choices = [c["name"] for c in self.draft["cases"] if c["expect"]["kind"] == "run"] if key == "example" else None
|
|
325
|
+
self.field(form, "Native example" if key == "example" else key.title(), prefix+[key],
|
|
326
|
+
"Choose a passing native fixture containing this function." if key=="example" else "",
|
|
327
|
+
choices=choices, multiline=key != "example", page=self.help_tab)
|
|
328
|
+
|
|
329
|
+
def fixtures_page(self):
|
|
330
|
+
layout, page = self.page("Fixtures", "Expected results are your reference. Verify compiles and runs every native fixture, and checks every expected conversion rejection.")
|
|
331
|
+
self.fixture_tab = page
|
|
332
|
+
self.fixture_choice = QComboBox()
|
|
333
|
+
for case in self.draft.get("cases", []): self.fixture_choice.addItem(case["name"])
|
|
334
|
+
self.fixture_choice.setAccessibleName("Fixture")
|
|
335
|
+
layout.addWidget(self.fixture_choice)
|
|
336
|
+
self.fixture_holder = QWidget(); self.fixture_layout = QVBoxLayout(self.fixture_holder)
|
|
337
|
+
self.fixture_layout.setContentsMargins(0, 0, 0, 0)
|
|
338
|
+
layout.addWidget(self.fixture_holder); layout.addStretch()
|
|
339
|
+
self.fixture_choice.currentIndexChanged.connect(self.show_fixture)
|
|
340
|
+
self.show_fixture(0)
|
|
341
|
+
|
|
342
|
+
def show_fixture(self, index):
|
|
343
|
+
self.clear(self.fixture_layout, "/cases/")
|
|
344
|
+
cases = self.draft.get("cases", [])
|
|
345
|
+
if not 0 <= index < len(cases): return
|
|
346
|
+
case = cases[index]
|
|
347
|
+
body = QWidget(); form = QFormLayout(body); self.fixture_layout.addWidget(body)
|
|
348
|
+
self.fixture_layout.addWidget(label("Source: " + case["file"] + "\nExpected kind: " + case["expect"]["kind"]))
|
|
349
|
+
self.fixture_layout.addWidget(button("Edit fixture source…", "go-to-source", lambda: self.source_requested.emit(case["file"])))
|
|
350
|
+
for key in case["expect"]:
|
|
351
|
+
if key == "kind": continue
|
|
352
|
+
self.field(form, "Expected " + key.replace("_", " "), ["cases", index, "expect", key],
|
|
353
|
+
multiline=key in ("stdout", "stderr"), page=self.fixture_tab)
|
|
354
|
+
|
|
355
|
+
def focus_path(self, path):
|
|
356
|
+
parts = [p.replace("~1", "/").replace("~0", "~") for p in path.split("/")[1:]]
|
|
357
|
+
if len(parts) >= 3 and parts[:2] == ["documentation", "functions"] and hasattr(self, "help_choice"):
|
|
358
|
+
self.help_choice.setCurrentText(parts[2])
|
|
359
|
+
if len(parts) >= 3 and parts[:2] == ["declaration", "functions"] and parts[2].isdigit():
|
|
360
|
+
self.function_choice.setCurrentIndex(int(parts[2]))
|
|
361
|
+
if len(parts) >= 2 and parts[0] == "cases" and parts[1].isdigit():
|
|
362
|
+
self.fixture_choice.setCurrentIndex(int(parts[1]))
|
|
363
|
+
target = self.fields.get(path)
|
|
364
|
+
if target:
|
|
365
|
+
widget, page = target
|
|
366
|
+
self.tabs.setCurrentWidget(page)
|
|
367
|
+
ancestor = widget.parentWidget()
|
|
368
|
+
while ancestor and ancestor is not page:
|
|
369
|
+
if isinstance(ancestor, QGroupBox) and ancestor.isCheckable(): ancestor.setChecked(True)
|
|
370
|
+
ancestor = ancestor.parentWidget()
|
|
371
|
+
widget.setFocus(); page.ensureWidgetVisible(widget)
|
|
372
|
+
return True
|
|
373
|
+
if parts and parts[0] == "cases":
|
|
374
|
+
self.tabs.setCurrentWidget(self.fixture_tab); self.fixture_choice.setFocus(); return True
|
|
375
|
+
if parts[:2] == ["declaration", "functions"]:
|
|
376
|
+
self.tabs.setCurrentWidget(self.function_tab); self.function_choice.setFocus(); return True
|
|
377
|
+
if parts and parts[0] == "documentation":
|
|
378
|
+
self.tabs.setCurrentWidget(self.help_tab); return True
|
|
379
|
+
if parts and parts[0] == "metadata":
|
|
380
|
+
self.tabs.setCurrentIndex(0); return True
|
|
381
|
+
return False
|
|
382
|
+
|
|
383
|
+
def advanced(self):
|
|
384
|
+
dlg = DraftDialog("Advanced project data", self)
|
|
385
|
+
dlg.body.addWidget(label("Edit declaration details or fixture definitions as JSON. The scanner checks the saved result through the selected engine. New fixture files must already exist in the project."))
|
|
386
|
+
source = QPlainTextEdit(json.dumps(self.draft, indent=2)); source.setAccessibleName("Project JSON")
|
|
387
|
+
dlg.body.addWidget(source, 1)
|
|
388
|
+
problem = label(""); dlg.problem = problem; dlg.body.addWidget(problem)
|
|
389
|
+
dlg.runner = JobRunner(dlg)
|
|
390
|
+
# Validate JSON before accepting. Engine validation remains in Scan.
|
|
391
|
+
def apply():
|
|
392
|
+
try:
|
|
393
|
+
draft = parse(source.toPlainText())
|
|
394
|
+
if type(draft) is not dict or not {"declaration", "metadata", "cases"} <= draft.keys():
|
|
395
|
+
raise SDKError("SDK_PROJECT", "Keep the project declaration, metadata and cases.")
|
|
396
|
+
except (SDKError, TypeError, ValueError) as exc:
|
|
397
|
+
problem.setText(str(exc)); return
|
|
398
|
+
source.setReadOnly(True); apply_button.setEnabled(False)
|
|
399
|
+
dlg.runner.start(self.configuration, "validate_project", (self.directory, draft),
|
|
400
|
+
{"expected_sha256": self.expected_sha256})
|
|
401
|
+
def validated(method, result, revision):
|
|
402
|
+
source.setReadOnly(False); apply_button.setEnabled(True)
|
|
403
|
+
if dlg.close_pending:
|
|
404
|
+
dlg.reject(); return
|
|
405
|
+
if result["status"] != "succeeded":
|
|
406
|
+
problem.setText("\n".join(d["message"] for d in result["diagnostics"])); return
|
|
407
|
+
self.load(result["data"]["document"], methods=self.methods, operations=self.operations, workbench=self.workbench)
|
|
408
|
+
self.changed.emit(); dlg.accept()
|
|
409
|
+
dlg.runner.finished.connect(validated)
|
|
410
|
+
row = QHBoxLayout(); apply_button = button("Apply draft", "check", apply)
|
|
411
|
+
row.addWidget(apply_button); row.addWidget(button("Cancel", "cancel", dlg.reject))
|
|
412
|
+
dlg.body.addLayout(row); dlg.resize(900, 650); dlg.exec()
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<!doctype html><html lang="en"><head><meta charset="utf-8"><title>PyCForge SDK — Getting started</title></head><body>
|
|
2
|
+
<h1>PyCForge SDK</h1><p>Create conversion extensions using the installed PyCForge engine. This short guide is available before an engine is connected.</p>
|
|
3
|
+
<h2>Find PyCForge</h2><p>The startup panel searches your saved connection and common Python installations. Choose among several engines, or use Locate PyCForge if it cannot be found. Select the installation, Python environment, installed Crucible support folder or Python interpreter. The custom picker has drive shortcuts. A source folder alone needs a working installed engine.</p>
|
|
4
|
+
<p>Continue offline opens local projects and any cached reference. Engine and tools exposes advanced interpreter and compiler settings. This Python selects the SDK interpreter; Refresh checks it. PyCForge’s About → Distribution → SDK Python shows its exact interpreter.</p>
|
|
5
|
+
<h2>Learn from your engine</h2><p>After connection, the Help topic selector offers the SDK guide and conversion-import manuals supplied by PyCForge’s Crucible folder. Authoring forms, operation choices and starter projects also come from that installation. Refresh after updating PyCForge. Cached guides remain readable offline; their engine and connection state are displayed above.</p>
|
|
6
|
+
<h2>Author and check</h2><p>Choose New or Open, edit the declaration and Help, save, then Scan. Verify fixtures explicitly converts, compiles and runs the saved examples. <b>Ready to package</b> means the current saved project matches passing evidence for its declared fixtures and recorded environment. Package and registration are separate actions. Changes to projects or tools require fresh verification.</p>
|
|
7
|
+
<h2>Recovery</h2><p>Activity contains diagnostics. Unsaved edits and outside file changes clear readiness. A failed refresh preserves compatible cached reference; it cannot authorize execution. Closing during work requests cancellation and waits for the worker. Windows direct-process termination does not supervise arbitrary descendant process trees.</p>
|
|
8
|
+
<h2>Keyboard</h2><p>Ctrl+N: New; Ctrl+O: Open; Ctrl+S: Save; F5: Scan; F6: Verify fixtures; Ctrl+B: Package; F1: Help.</p>
|
|
9
|
+
</body></html>
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""SDK-only copper accents over the preserved PyCForge presentation layer."""
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from PySide6.QtCore import Qt, QSize
|
|
4
|
+
from PySide6.QtGui import QIcon
|
|
5
|
+
from PySide6.QtWidgets import QFrame, QHBoxLayout, QLabel, QSizePolicy, QVBoxLayout
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
COPPER = "#D99B6B"
|
|
9
|
+
COPPER_BRIGHT = "#F0BB91"
|
|
10
|
+
COPPER_SURFACE = "#3B3028"
|
|
11
|
+
|
|
12
|
+
# Applied to SDK windows, never to QApplication or the shared visual modules.
|
|
13
|
+
# Brand emphasis is separate from success/warning/error status colors.
|
|
14
|
+
SDK_QSS = """
|
|
15
|
+
QFrame#SDKEngineLink {
|
|
16
|
+
background: #262D34; border: 1px solid #4C5965;
|
|
17
|
+
border-left: 4px solid #D99B6B; border-radius: 6px;
|
|
18
|
+
}
|
|
19
|
+
QLabel#SDKConnectionTitle { color: #E0E5E9; font-size: 15px; font-weight: 700; }
|
|
20
|
+
QLabel#SDKConnectionTag { color: #F0BB91; font-size: 11px; font-weight: 700; }
|
|
21
|
+
QLabel#SDKWelcomeTitle { color: #F0BB91; font-size: 24px; font-weight: 600; }
|
|
22
|
+
QLabel#SDKConnectionPath { color: #A7B4BE; }
|
|
23
|
+
QWidget#SDKConnectionSettings { border: none; }
|
|
24
|
+
QDialog#SDKStartup { background: #1B2127; }
|
|
25
|
+
QFrame#SDKBrand {
|
|
26
|
+
background: #262D34;
|
|
27
|
+
border: 1px solid #4C5965;
|
|
28
|
+
border-top: 2px solid #D99B6B;
|
|
29
|
+
border-radius: 5px;
|
|
30
|
+
}
|
|
31
|
+
QLabel#SDKProductName { color: #E0E5E9; font-size: 16px; font-weight: 700; }
|
|
32
|
+
QLabel#SDKBadge {
|
|
33
|
+
color: #F0BB91; background: #3B3028;
|
|
34
|
+
border: 1px solid #A5714C; border-radius: 4px;
|
|
35
|
+
font-weight: 700; padding: 3px 6px;
|
|
36
|
+
}
|
|
37
|
+
QLabel#SDKBrandCaption { color: #A7B4BE; font-size: 11px; }
|
|
38
|
+
QListWidget#DocumentList:focus { border-color: #D99B6B; border-bottom-color: #D99B6B; }
|
|
39
|
+
QListWidget#DocumentList::item:selected {
|
|
40
|
+
color: #F0BB91; background: #3B3028;
|
|
41
|
+
border: 1px solid #A5714C; border-left: 3px solid #D99B6B;
|
|
42
|
+
}
|
|
43
|
+
QListWidget#DocumentList::item:selected:hover { background: #49382B; }
|
|
44
|
+
QTabBar::tab:selected, QTabBar::tab:hover:enabled {
|
|
45
|
+
border-bottom: 2px solid #D99B6B;
|
|
46
|
+
}
|
|
47
|
+
QMenuBar::item:selected, QMenuBar::item:pressed { border-bottom: 2px solid #D99B6B; }
|
|
48
|
+
QMenu#PyCForgeMenu::item:selected:enabled {
|
|
49
|
+
background: #3B3028; border-left: 3px solid #D99B6B;
|
|
50
|
+
}
|
|
51
|
+
QMenu#PyCForgeMenu::item:pressed:enabled {
|
|
52
|
+
background: #49382B; border-left: 3px solid #D99B6B; border-bottom: 2px solid #D99B6B;
|
|
53
|
+
}
|
|
54
|
+
QPushButton[sdkAccent="true"]:enabled, QToolButton[sdkAccent="true"]:enabled {
|
|
55
|
+
color: #F0BB91; border-bottom: 2px solid #D99B6B;
|
|
56
|
+
}
|
|
57
|
+
QPushButton[sdkAccent="true"]:hover:enabled, QToolButton[sdkAccent="true"]:hover:enabled {
|
|
58
|
+
background: #3B3028; border-color: #D99B6B;
|
|
59
|
+
}
|
|
60
|
+
QPushButton[sdkAccent="true"]:pressed:enabled, QToolButton[sdkAccent="true"]:pressed:enabled {
|
|
61
|
+
background: #49382B; border-color: #F0BB91;
|
|
62
|
+
}
|
|
63
|
+
QPushButton[sdkAccent="true"]:disabled, QToolButton[sdkAccent="true"]:disabled {
|
|
64
|
+
color: #95A1AB; background: #262D34;
|
|
65
|
+
border-color: #4C5965; border-bottom: 1px solid #4C5965;
|
|
66
|
+
}
|
|
67
|
+
QLineEdit:focus, QPlainTextEdit:focus, QComboBox:focus,
|
|
68
|
+
QPushButton[sdkAccent="true"]:focus, QToolButton[sdkAccent="true"]:focus {
|
|
69
|
+
border-color: #D99B6B;
|
|
70
|
+
}
|
|
71
|
+
QFrame#DialogTitleBar { border-bottom: 2px solid #D99B6B; }
|
|
72
|
+
QProgressBar::chunk { background: #87502D; }
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class PathLabel(QLabel):
|
|
77
|
+
"""An exact path in the tooltip, elided in layouts instead of widening them."""
|
|
78
|
+
def __init__(self, parent=None):
|
|
79
|
+
super().__init__(parent)
|
|
80
|
+
self.full_text = ""
|
|
81
|
+
self.setObjectName("SDKConnectionPath")
|
|
82
|
+
self.setTextFormat(Qt.TextFormat.PlainText)
|
|
83
|
+
self.setMinimumWidth(0)
|
|
84
|
+
self.setSizePolicy(QSizePolicy.Policy.Ignored, QSizePolicy.Policy.Preferred)
|
|
85
|
+
|
|
86
|
+
def setText(self, text):
|
|
87
|
+
self.full_text = text
|
|
88
|
+
self.setToolTip(text)
|
|
89
|
+
self.setAccessibleDescription(text)
|
|
90
|
+
self._elide()
|
|
91
|
+
|
|
92
|
+
def _elide(self):
|
|
93
|
+
super().setText(self.fontMetrics().elidedText(self.full_text, Qt.TextElideMode.ElideMiddle, max(0, self.width())))
|
|
94
|
+
|
|
95
|
+
def resizeEvent(self, event):
|
|
96
|
+
super().resizeEvent(event)
|
|
97
|
+
self._elide()
|
|
98
|
+
|
|
99
|
+
def minimumSizeHint(self):
|
|
100
|
+
return QSize(0, self.fontMetrics().height() + 4)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def sdk_icon():
|
|
104
|
+
"""The original code-bracket mark used by the approved SDK banner."""
|
|
105
|
+
return QIcon(str(Path(__file__).with_name("resources") / "sdk-mark.png"))
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def sdk_badge(parent=None):
|
|
109
|
+
badge = QLabel("SDK", parent)
|
|
110
|
+
badge.setObjectName("SDKBadge")
|
|
111
|
+
badge.setAccessibleName("PyCForge SDK")
|
|
112
|
+
badge.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
113
|
+
badge.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
|
|
114
|
+
return badge
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def brand_panel(parent=None):
|
|
118
|
+
panel = QFrame(parent)
|
|
119
|
+
panel.setObjectName("SDKBrand")
|
|
120
|
+
panel.setAccessibleName("PyCForge SDK — conversion extensions")
|
|
121
|
+
layout = QVBoxLayout(panel)
|
|
122
|
+
layout.setContentsMargins(10, 10, 10, 10)
|
|
123
|
+
layout.setSpacing(6)
|
|
124
|
+
row = QHBoxLayout()
|
|
125
|
+
row.setSpacing(6)
|
|
126
|
+
mark = QLabel()
|
|
127
|
+
mark.setFixedSize(28, 28)
|
|
128
|
+
mark.setPixmap(sdk_icon().pixmap(mark.size(), panel.devicePixelRatioF()))
|
|
129
|
+
row.addWidget(mark)
|
|
130
|
+
name = QLabel("PyCForge")
|
|
131
|
+
name.setObjectName("SDKProductName")
|
|
132
|
+
row.addWidget(name)
|
|
133
|
+
row.addWidget(sdk_badge(panel))
|
|
134
|
+
row.addStretch(1)
|
|
135
|
+
layout.addLayout(row)
|
|
136
|
+
caption = QLabel("Conversion extensions")
|
|
137
|
+
caption.setObjectName("SDKBrandCaption")
|
|
138
|
+
layout.addWidget(caption)
|
|
139
|
+
return panel
|