statable 3.1.1__tar.gz → 3.2.0__tar.gz
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.
- {statable-3.1.1 → statable-3.2.0}/PKG-INFO +1 -1
- {statable-3.1.1 → statable-3.2.0}/codegen/__init__.py +1 -1
- {statable-3.1.1 → statable-3.2.0}/pyproject.toml +1 -1
- {statable-3.1.1 → statable-3.2.0}/statable/__init__.py +1 -1
- {statable-3.1.1 → statable-3.2.0}/statable/cli.py +1 -1
- {statable-3.1.1 → statable-3.2.0}/statable.egg-info/PKG-INFO +1 -1
- {statable-3.1.1 → statable-3.2.0}/statable.egg-info/SOURCES.txt +4 -1
- {statable-3.1.1 → statable-3.2.0}/statable_gui/i18n/__init__.py +11 -1
- {statable-3.1.1 → statable-3.2.0}/statable_gui/main_window.py +53 -15
- statable-3.2.0/statable_gui/new_project_templates.py +133 -0
- statable-3.2.0/statable_gui/new_project_wizard.py +551 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v3_0_s1_packaging.py +9 -9
- {statable-3.1.1 → statable-3.2.0}/tests/test_v3_0_s2_public_api.py +4 -4
- {statable-3.1.1 → statable-3.2.0}/tests/test_v3_0_s3_cli.py +4 -4
- {statable-3.1.1 → statable-3.2.0}/tests/test_v3_0_s4_docs.py +5 -5
- statable-3.2.0/tests/test_v3_2_s1_wizard.py +219 -0
- {statable-3.1.1 → statable-3.2.0}/README.md +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/c_code_generator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/code_merger.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/code_templates.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/config.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/enum_generator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/event_queue_generator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/interrupt_generator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/naming_convention.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/osal_generator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/role_function_generator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/sample_data.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/state_actions_generator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/struct_generator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/timer_generator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/transition_generator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/type_mapper.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/__init__.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/change_actions.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/change_applier.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/clipboard_manager.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/data/__init__.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/data/action_definitions.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/data/keywords.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/data/prompt_templates.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/data/validation_rules.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/items/__init__.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/items/base_validator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/items/cell_validator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/items/custom_type_validator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/items/event_validator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/items/flag_validator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/items/interrupt_validator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/items/queue_validator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/items/role_function_validator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/items/state_validator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/items/timer_validator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/items/transition_validator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/items/variable_validator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/logger.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/models.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/prompt_generator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/response_parser.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/response_validator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/validation_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/validate/validator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/codegen/variable_generator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/setup.cfg +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable/__main__.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable/global_defs.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable/mermaid_gen.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable/model.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable/parser.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable/sample_data.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable/shared/__init__.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable/shared/condition_library.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable/shared/literal_library.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable/shared/role_function_library.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable/state_machine.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable/xml_io.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable.egg-info/dependency_links.txt +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable.egg-info/entry_points.txt +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable.egg-info/requires.txt +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable.egg-info/top_level.txt +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/__init__.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/action_edit_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/code_generation_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/code_generation_settings_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/common_widgets.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/condition_builder_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/condition_edit_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/condition_template_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/config.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/dialogs.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/event_definition_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/event_delivery_settings_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/event_queue_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/global_defs.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/global_defs_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/interrupt_handler_edit_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/layer_settings_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/libcntrl/__init__.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/libcntrl/condition_library.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/libcntrl/literal_library.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/libcntrl/literal_management_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/libcntrl/role_function_edit_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/libcntrl/role_function_library.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/literal_definition_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/logger.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/matrix_table.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/preference_keys.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/preferences.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/role_function_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/sample_data.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/state_actions_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/symbol_picker.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/traceball.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/transition_editor_direct/__init__.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/transition_editor_direct/actions_tab.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/transition_editor_direct/code_widget.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/transition_editor_direct/coverage_analyzer.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/transition_editor_direct/dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/transition_editor_direct/draft.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/transition_editor_direct/edit_dialogs.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/transition_editor_direct/overview_tab.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/transition_editor_direct/palette_widget.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/transition_editor_direct/relations_edit_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/transition_editor_direct/relations_tab.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/transition_editor_direct/system_global_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/transition_editor_direct/transition_actions_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/transition_editor_direct/transitions_tab.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/validation_dialog.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/statable_gui/widgets.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_readme_consistency.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_2_p1.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_2_p12_10.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_2_p12_2.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_2_p12_5.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_2_p12_6.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_2_p12_7.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_2_p12_8.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_2_p12_9.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_2_p2.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_2_p3.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_2_p4a.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_2_p4b.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_3_p1.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_4_p1_merge.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_5_p1.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_5_p10.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_5_p11.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_5_p2.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_5_p3.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_5_p4.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_5_p5.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_5_p6.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_5_p8.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_5_p9.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_6_p1.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_6_p2.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_6_p3.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_7_p3.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_7_p4.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_7_p5_validation.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_8_p1_ai_prompt.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_8_p2_response_parser.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_8_p3_response_validator.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v2_8_p4_gui_integration.py +0 -0
- {statable-3.1.1 → statable-3.2.0}/tests/test_v3_0_g1_shared.py +0 -0
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "statable"
|
|
9
|
-
version = "3.
|
|
9
|
+
version = "3.2.0"
|
|
10
10
|
description = "MISRA C:2012-aware state machine design and C code generation for embedded systems"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
requires-python = ">=3.10"
|
|
@@ -88,6 +88,8 @@ statable_gui/literal_definition_dialog.py
|
|
|
88
88
|
statable_gui/logger.py
|
|
89
89
|
statable_gui/main_window.py
|
|
90
90
|
statable_gui/matrix_table.py
|
|
91
|
+
statable_gui/new_project_templates.py
|
|
92
|
+
statable_gui/new_project_wizard.py
|
|
91
93
|
statable_gui/preference_keys.py
|
|
92
94
|
statable_gui/preferences.py
|
|
93
95
|
statable_gui/role_function_dialog.py
|
|
@@ -157,4 +159,5 @@ tests/test_v3_0_g1_shared.py
|
|
|
157
159
|
tests/test_v3_0_s1_packaging.py
|
|
158
160
|
tests/test_v3_0_s2_public_api.py
|
|
159
161
|
tests/test_v3_0_s3_cli.py
|
|
160
|
-
tests/test_v3_0_s4_docs.py
|
|
162
|
+
tests/test_v3_0_s4_docs.py
|
|
163
|
+
tests/test_v3_2_s1_wizard.py
|
|
@@ -14,6 +14,7 @@ Usage in gui_main.py or statable_gui/main_window.py:
|
|
|
14
14
|
"""
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
+
import sys
|
|
17
18
|
from pathlib import Path
|
|
18
19
|
from typing import Optional
|
|
19
20
|
|
|
@@ -25,7 +26,16 @@ from PySide6.QtCore import (
|
|
|
25
26
|
)
|
|
26
27
|
from PySide6.QtWidgets import QApplication
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
# [v3.2] PyInstaller frozen support
|
|
30
|
+
if getattr(sys, "frozen", False):
|
|
31
|
+
# Bundled: resources are in sys._MEIPASS/statable_gui/i18n
|
|
32
|
+
_meipass = getattr(sys, "_MEIPASS", None)
|
|
33
|
+
if _meipass:
|
|
34
|
+
I18N_DIR = Path(_meipass) / "statable_gui" / "i18n"
|
|
35
|
+
else:
|
|
36
|
+
I18N_DIR = Path(__file__).parent
|
|
37
|
+
else:
|
|
38
|
+
I18N_DIR = Path(__file__).parent
|
|
29
39
|
DEFAULT_LANG = "en"
|
|
30
40
|
SUPPORTED_LANGUAGES = ["en", "zh_CN"]
|
|
31
41
|
LANG_DISPLAY = {
|
|
@@ -39,7 +39,7 @@ from pathlib import Path
|
|
|
39
39
|
from PySide6.QtCore import Qt
|
|
40
40
|
from PySide6.QtGui import QAction
|
|
41
41
|
from PySide6.QtWidgets import (
|
|
42
|
-
QMainWindow, QTabWidget, QToolButton, QMessageBox,
|
|
42
|
+
QMainWindow, QTabWidget, QToolButton, QMessageBox, QDialog,
|
|
43
43
|
QInputDialog, QFileDialog, QDialog, QToolBar
|
|
44
44
|
)
|
|
45
45
|
|
|
@@ -375,11 +375,11 @@ class MainWindow(QMainWindow):
|
|
|
375
375
|
|
|
376
376
|
file_menu = menubar.addMenu(self.tr("File"))
|
|
377
377
|
|
|
378
|
-
# [
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
file_menu.addAction(
|
|
378
|
+
# [v3.2] New Project Wizard (Ctrl+N)
|
|
379
|
+
new_wizard_action = QAction(self.tr("New Project..."), self)
|
|
380
|
+
new_wizard_action.setShortcut("Ctrl+N")
|
|
381
|
+
new_wizard_action.triggered.connect(self.new_project_wizard)
|
|
382
|
+
file_menu.addAction(new_wizard_action)
|
|
383
383
|
|
|
384
384
|
file_menu.addSeparator()
|
|
385
385
|
|
|
@@ -516,7 +516,12 @@ class MainWindow(QMainWindow):
|
|
|
516
516
|
self._restart_in_progress = True
|
|
517
517
|
|
|
518
518
|
exe = _sys.executable
|
|
519
|
-
|
|
519
|
+
# [v3.2] Frozen (PyInstaller) support: sys.executable is the
|
|
520
|
+
# bundled StaTable.exe, which does not accept "-m statable".
|
|
521
|
+
if getattr(_sys, "frozen", False):
|
|
522
|
+
args = [exe]
|
|
523
|
+
else:
|
|
524
|
+
args = [exe, "-m", "statable"]
|
|
520
525
|
cwd = os.getcwd()
|
|
521
526
|
|
|
522
527
|
# Disable UI to avoid double-clicks
|
|
@@ -805,7 +810,7 @@ class MainWindow(QMainWindow):
|
|
|
805
810
|
f"Failed to save project:\n{e}")
|
|
806
811
|
return False
|
|
807
812
|
|
|
808
|
-
def open_project(self):
|
|
813
|
+
def open_project(self, filepath: str = None):
|
|
809
814
|
"""Load the whole project"""
|
|
810
815
|
# [v2.3] Prompt to save before loading
|
|
811
816
|
if not self._maybe_save():
|
|
@@ -814,13 +819,14 @@ class MainWindow(QMainWindow):
|
|
|
814
819
|
StaTableLogger.debug(
|
|
815
820
|
"MainWindow.open_project called")
|
|
816
821
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
822
|
+
if filepath is None:
|
|
823
|
+
last_dir = self.prefs.last_project_dir
|
|
824
|
+
filepath, _ = QFileDialog.getOpenFileName(
|
|
825
|
+
self, "Open Project", last_dir,
|
|
826
|
+
"XML files (*.xml)")
|
|
827
|
+
if not filepath:
|
|
828
|
+
StaTableLogger.debug("Open cancelled")
|
|
829
|
+
return
|
|
824
830
|
try:
|
|
825
831
|
StaTableLogger.debug(
|
|
826
832
|
f"Calling project_from_xml: {filepath}")
|
|
@@ -1297,6 +1303,38 @@ class MainWindow(QMainWindow):
|
|
|
1297
1303
|
# New Project feature (v2.3 / F-15)
|
|
1298
1304
|
# ==================================================================
|
|
1299
1305
|
|
|
1306
|
+
def new_project_wizard(self) -> None:
|
|
1307
|
+
"""[v3.2] Launch the New Project Wizard."""
|
|
1308
|
+
if not self._maybe_save():
|
|
1309
|
+
return
|
|
1310
|
+
try:
|
|
1311
|
+
from statable_gui.new_project_wizard import NewProjectWizard
|
|
1312
|
+
except ImportError as e:
|
|
1313
|
+
QMessageBox.critical(
|
|
1314
|
+
self, "Wizard Error",
|
|
1315
|
+
f"Failed to import wizard module:\n{e}")
|
|
1316
|
+
return
|
|
1317
|
+
try:
|
|
1318
|
+
wiz = NewProjectWizard(self)
|
|
1319
|
+
if wiz.exec() != QDialog.Accepted:
|
|
1320
|
+
StaTableLogger.debug("New project wizard: cancelled")
|
|
1321
|
+
return
|
|
1322
|
+
xml_path = wiz.generate()
|
|
1323
|
+
if not xml_path:
|
|
1324
|
+
StaTableLogger.warning("Wizard returned no path")
|
|
1325
|
+
return
|
|
1326
|
+
StaTableLogger.info(f"New project generated: {xml_path}")
|
|
1327
|
+
self.open_project(filepath=xml_path)
|
|
1328
|
+
self.statusBar().showMessage(
|
|
1329
|
+
f"New project created: {xml_path}", 5000)
|
|
1330
|
+
except Exception as e:
|
|
1331
|
+
StaTableLogger.error(f"New project wizard failed: {e!r}")
|
|
1332
|
+
import traceback
|
|
1333
|
+
QMessageBox.critical(
|
|
1334
|
+
self, "Wizard Error",
|
|
1335
|
+
f"Failed to create project:\n{e}\n\n"
|
|
1336
|
+
f"{traceback.format_exc()}")
|
|
1337
|
+
|
|
1300
1338
|
def new_project(self) -> None:
|
|
1301
1339
|
"""Start a new empty project.
|
|
1302
1340
|
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# statable_gui/new_project_templates.py
|
|
2
|
+
"""Template definitions for the New Project Wizard."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
# Common events used across all layers
|
|
7
|
+
COMMON_EVENTS = [
|
|
8
|
+
{"name": "EV_INIT", "delivery": "queue", "kind": "signal", "description": "Initialization request"},
|
|
9
|
+
{"name": "EV_START", "delivery": "direct", "kind": "signal", "description": "Start request"},
|
|
10
|
+
{"name": "EV_STOP", "delivery": "direct", "kind": "signal", "description": "Stop request"},
|
|
11
|
+
{"name": "EV_ERROR", "delivery": "queue", "kind": "signal", "description": "Error notification"},
|
|
12
|
+
{"name": "EV_TIMEOUT", "delivery": "queue", "kind": "time", "description": "Timer expiry"},
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
# Global interrupts (shared across layers)
|
|
16
|
+
INTERRUPTS = [
|
|
17
|
+
{"name": "ISR_TIMER0", "description": "System tick timer"},
|
|
18
|
+
{"name": "ISR_UART_RX", "description": "UART receive complete"},
|
|
19
|
+
{"name": "ISR_UART_TX", "description": "UART transmit complete"},
|
|
20
|
+
{"name": "ISR_GPIO", "description": "GPIO edge detection"},
|
|
21
|
+
{"name": "ISR_ADC", "description": "ADC conversion complete"},
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
# Global variables (shared)
|
|
25
|
+
GLOBAL_VARIABLES = [
|
|
26
|
+
{"name": "g_counter", "type": "uint32_t", "description": "Loop counter"},
|
|
27
|
+
{"name": "g_error_code", "type": "int32_t", "description": "Last error code"},
|
|
28
|
+
{"name": "g_last_event", "type": "uint16_t", "description": "Last processed event ID"},
|
|
29
|
+
{"name": "g_timeout_ms", "type": "uint32_t", "description": "Timeout in milliseconds"},
|
|
30
|
+
{"name": "g_debug_level", "type": "uint8_t", "description": "Debug verbosity level"},
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
# Event flags (shared)
|
|
34
|
+
EVENT_FLAGS = [
|
|
35
|
+
{"name": "f_init_done", "description": "Initialization complete"},
|
|
36
|
+
{"name": "f_error", "description": "Error state active"},
|
|
37
|
+
{"name": "f_ready", "description": "Ready for operation"},
|
|
38
|
+
{"name": "f_busy", "description": "Operation in progress"},
|
|
39
|
+
{"name": "f_timeout", "description": "Timeout occurred"},
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
# Event queues (one per layer + 2 shared)
|
|
43
|
+
EVENT_QUEUES = [
|
|
44
|
+
{"name": "q_driver", "size": 16, "description": "Driver layer event queue"},
|
|
45
|
+
{"name": "q_middleware", "size": 16, "description": "Middleware layer event queue"},
|
|
46
|
+
{"name": "q_application", "size": 16, "description": "Application layer event queue"},
|
|
47
|
+
{"name": "q_system", "size": 32, "description": "System-wide event queue"},
|
|
48
|
+
{"name": "q_debug", "size": 8, "description": "Debug message queue"},
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# Layer templates
|
|
53
|
+
LAYERS_3LAYER = [
|
|
54
|
+
{
|
|
55
|
+
"name": "Driver",
|
|
56
|
+
"priority": 1,
|
|
57
|
+
"description": "Hardware abstraction layer",
|
|
58
|
+
"states": [
|
|
59
|
+
{"name": "Driver_Init", "type": "initial", "description": "Hardware initialization"},
|
|
60
|
+
{"name": "Driver_Idle", "type": "normal", "description": "Waiting for commands"},
|
|
61
|
+
{"name": "Driver_Active", "type": "normal", "description": "Hardware active"},
|
|
62
|
+
{"name": "Driver_Error", "type": "normal", "description": "Hardware error"},
|
|
63
|
+
{"name": "Driver_Recover", "type": "normal", "description": "Recovery in progress"},
|
|
64
|
+
],
|
|
65
|
+
"role_functions": [
|
|
66
|
+
{"name": "Driver_HwInit", "description": "Initialize hardware"},
|
|
67
|
+
{"name": "Driver_Start", "description": "Start hardware operation"},
|
|
68
|
+
{"name": "Driver_Stop", "description": "Stop hardware operation"},
|
|
69
|
+
{"name": "Driver_HandleError", "description": "Handle hardware error"},
|
|
70
|
+
{"name": "Driver_Cleanup", "description": "Cleanup resources"},
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"name": "Middleware",
|
|
75
|
+
"priority": 3,
|
|
76
|
+
"description": "Business logic layer",
|
|
77
|
+
"states": [
|
|
78
|
+
{"name": "Middleware_Init", "type": "initial", "description": "Middleware initialization"},
|
|
79
|
+
{"name": "Middleware_Standby", "type": "normal", "description": "Waiting"},
|
|
80
|
+
{"name": "Middleware_Processing","type": "normal", "description": "Processing data"},
|
|
81
|
+
{"name": "Middleware_Waiting", "type": "normal", "description": "Waiting for response"},
|
|
82
|
+
{"name": "Middleware_Error", "type": "normal", "description": "Middleware error"},
|
|
83
|
+
],
|
|
84
|
+
"role_functions": [
|
|
85
|
+
{"name": "Middleware_Init", "description": "Initialize middleware"},
|
|
86
|
+
{"name": "Middleware_Process", "description": "Process request"},
|
|
87
|
+
{"name": "Middleware_Commit", "description": "Commit result"},
|
|
88
|
+
{"name": "Middleware_Rollback", "description": "Rollback on error"},
|
|
89
|
+
{"name": "Middleware_Cleanup", "description": "Cleanup resources"},
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"name": "Application",
|
|
94
|
+
"priority": 5,
|
|
95
|
+
"description": "User-facing application layer",
|
|
96
|
+
"states": [
|
|
97
|
+
{"name": "Application_Boot", "type": "initial", "description": "Boot sequence"},
|
|
98
|
+
{"name": "Application_Ready", "type": "normal", "description": "Ready for user input"},
|
|
99
|
+
{"name": "Application_Running", "type": "normal", "description": "Main operation"},
|
|
100
|
+
{"name": "Application_Paused", "type": "normal", "description": "Paused state"},
|
|
101
|
+
{"name": "Application_Shutdown", "type": "normal", "description": "Shutdown sequence"},
|
|
102
|
+
],
|
|
103
|
+
"role_functions": [
|
|
104
|
+
{"name": "Application_Init", "description": "Initialize application"},
|
|
105
|
+
{"name": "Application_Start", "description": "Start main operation"},
|
|
106
|
+
{"name": "Application_Pause", "description": "Pause operation"},
|
|
107
|
+
{"name": "Application_Resume", "description": "Resume operation"},
|
|
108
|
+
{"name": "Application_Shutdown", "description": "Shutdown application"},
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
]
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
TEMPLATES = {
|
|
115
|
+
"blank": {
|
|
116
|
+
"id": "blank",
|
|
117
|
+
"name": "Empty Project",
|
|
118
|
+
"description": "One empty Application layer (existing behavior)",
|
|
119
|
+
"layers": [],
|
|
120
|
+
},
|
|
121
|
+
"basic": {
|
|
122
|
+
"id": "basic",
|
|
123
|
+
"name": "Basic (Single Layer)",
|
|
124
|
+
"description": "Application layer with 5 states + 5 events + 5 role functions",
|
|
125
|
+
"layers": [LAYERS_3LAYER[2]], # Application only
|
|
126
|
+
},
|
|
127
|
+
"three_layer": {
|
|
128
|
+
"id": "three_layer",
|
|
129
|
+
"name": "3-Layer (Driver / Middleware / Application) [Recommended]",
|
|
130
|
+
"description": "Full 3-layer structure with all placeholders",
|
|
131
|
+
"layers": LAYERS_3LAYER,
|
|
132
|
+
},
|
|
133
|
+
}
|