statable 3.1.0__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.
- codegen/__init__.py +38 -0
- codegen/c_code_generator.py +1752 -0
- codegen/code_merger.py +371 -0
- codegen/code_templates.py +509 -0
- codegen/config.py +167 -0
- codegen/enum_generator.py +377 -0
- codegen/event_queue_generator.py +303 -0
- codegen/interrupt_generator.py +345 -0
- codegen/naming_convention.py +171 -0
- codegen/osal_generator.py +282 -0
- codegen/role_function_generator.py +1244 -0
- codegen/sample_data.py +269 -0
- codegen/state_actions_generator.py +395 -0
- codegen/struct_generator.py +721 -0
- codegen/timer_generator.py +299 -0
- codegen/transition_generator.py +907 -0
- codegen/type_mapper.py +69 -0
- codegen/validate/__init__.py +38 -0
- codegen/validate/change_actions.py +90 -0
- codegen/validate/change_applier.py +416 -0
- codegen/validate/clipboard_manager.py +47 -0
- codegen/validate/data/__init__.py +30 -0
- codegen/validate/data/action_definitions.py +200 -0
- codegen/validate/data/keywords.py +46 -0
- codegen/validate/data/prompt_templates.py +176 -0
- codegen/validate/data/validation_rules.py +205 -0
- codegen/validate/items/__init__.py +30 -0
- codegen/validate/items/base_validator.py +25 -0
- codegen/validate/items/cell_validator.py +275 -0
- codegen/validate/items/custom_type_validator.py +75 -0
- codegen/validate/items/event_validator.py +78 -0
- codegen/validate/items/flag_validator.py +74 -0
- codegen/validate/items/interrupt_validator.py +75 -0
- codegen/validate/items/queue_validator.py +73 -0
- codegen/validate/items/role_function_validator.py +175 -0
- codegen/validate/items/state_validator.py +88 -0
- codegen/validate/items/timer_validator.py +120 -0
- codegen/validate/items/transition_validator.py +113 -0
- codegen/validate/items/variable_validator.py +132 -0
- codegen/validate/logger.py +52 -0
- codegen/validate/models.py +177 -0
- codegen/validate/prompt_generator.py +724 -0
- codegen/validate/response_parser.py +154 -0
- codegen/validate/response_validator.py +275 -0
- codegen/validate/validation_dialog.py +322 -0
- codegen/validate/validator.py +94 -0
- codegen/variable_generator.py +419 -0
- statable/__init__.py +71 -0
- statable/__main__.py +49 -0
- statable/cli.py +251 -0
- statable/global_defs.py +256 -0
- statable/mermaid_gen.py +144 -0
- statable/model.py +426 -0
- statable/parser.py +64 -0
- statable/sample_data.py +435 -0
- statable/shared/__init__.py +24 -0
- statable/shared/condition_library.py +63 -0
- statable/shared/literal_library.py +66 -0
- statable/shared/role_function_library.py +150 -0
- statable/state_machine.py +121 -0
- statable/xml_io.py +1164 -0
- statable-3.1.0.dist-info/METADATA +151 -0
- statable-3.1.0.dist-info/RECORD +117 -0
- statable-3.1.0.dist-info/WHEEL +5 -0
- statable-3.1.0.dist-info/entry_points.txt +2 -0
- statable-3.1.0.dist-info/top_level.txt +3 -0
- statable_gui/__init__.py +23 -0
- statable_gui/action_edit_dialog.py +214 -0
- statable_gui/code_generation_dialog.py +486 -0
- statable_gui/code_generation_settings_dialog.py +522 -0
- statable_gui/common_widgets.py +537 -0
- statable_gui/condition_builder_dialog.py +500 -0
- statable_gui/condition_edit_dialog.py +123 -0
- statable_gui/condition_template_dialog.py +58 -0
- statable_gui/config.py +21 -0
- statable_gui/dialogs.py +439 -0
- statable_gui/event_definition_dialog.py +605 -0
- statable_gui/event_delivery_settings_dialog.py +191 -0
- statable_gui/event_queue_dialog.py +245 -0
- statable_gui/global_defs.py +167 -0
- statable_gui/global_defs_dialog.py +796 -0
- statable_gui/i18n/__init__.py +118 -0
- statable_gui/interrupt_handler_edit_dialog.py +810 -0
- statable_gui/layer_settings_dialog.py +180 -0
- statable_gui/libcntrl/__init__.py +23 -0
- statable_gui/libcntrl/condition_library.py +13 -0
- statable_gui/libcntrl/literal_library.py +13 -0
- statable_gui/libcntrl/literal_management_dialog.py +185 -0
- statable_gui/libcntrl/role_function_edit_dialog.py +145 -0
- statable_gui/libcntrl/role_function_library.py +13 -0
- statable_gui/literal_definition_dialog.py +62 -0
- statable_gui/logger.py +83 -0
- statable_gui/main_window.py +1380 -0
- statable_gui/matrix_table.py +413 -0
- statable_gui/preference_keys.py +18 -0
- statable_gui/preferences.py +74 -0
- statable_gui/role_function_dialog.py +244 -0
- statable_gui/sample_data.py +11 -0
- statable_gui/state_actions_dialog.py +398 -0
- statable_gui/symbol_picker.py +170 -0
- statable_gui/traceball.py +37 -0
- statable_gui/transition_editor_direct/__init__.py +15 -0
- statable_gui/transition_editor_direct/actions_tab.py +856 -0
- statable_gui/transition_editor_direct/code_widget.py +344 -0
- statable_gui/transition_editor_direct/coverage_analyzer.py +163 -0
- statable_gui/transition_editor_direct/dialog.py +335 -0
- statable_gui/transition_editor_direct/draft.py +270 -0
- statable_gui/transition_editor_direct/edit_dialogs.py +160 -0
- statable_gui/transition_editor_direct/overview_tab.py +173 -0
- statable_gui/transition_editor_direct/palette_widget.py +233 -0
- statable_gui/transition_editor_direct/relations_edit_dialog.py +156 -0
- statable_gui/transition_editor_direct/relations_tab.py +230 -0
- statable_gui/transition_editor_direct/system_global_dialog.py +52 -0
- statable_gui/transition_editor_direct/transition_actions_dialog.py +109 -0
- statable_gui/transition_editor_direct/transitions_tab.py +620 -0
- statable_gui/validation_dialog.py +285 -0
- statable_gui/widgets.py +1315 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
from PySide6.QtCore import Qt, Signal
|
|
2
|
+
from PySide6.QtWidgets import (
|
|
3
|
+
QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QListWidget,
|
|
4
|
+
QListWidgetItem, QPushButton, QLabel, QDialog
|
|
5
|
+
)
|
|
6
|
+
from PySide6.QtGui import QFont
|
|
7
|
+
|
|
8
|
+
from statable.global_defs import GlobalDefinitions
|
|
9
|
+
from .global_defs_dialog import VariableEditDialog, FlagEditDialog, GlobalDefinitionsDialog
|
|
10
|
+
from .logger import StaTableLogger
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SymbolPickerWidget(QWidget):
|
|
14
|
+
"""Common widget for selecting global variables, event flags, and role function return values"""
|
|
15
|
+
|
|
16
|
+
insert_requested = Signal(str)
|
|
17
|
+
|
|
18
|
+
def __init__(self, parent=None, global_defs=None, role_functions=None):
|
|
19
|
+
super().__init__(parent)
|
|
20
|
+
self.global_defs = global_defs if global_defs else GlobalDefinitions()
|
|
21
|
+
self.role_functions = role_functions if role_functions is not None else {}
|
|
22
|
+
|
|
23
|
+
layout = QVBoxLayout(self)
|
|
24
|
+
|
|
25
|
+
# Title
|
|
26
|
+
title = QLabel(self.tr("Global variables, event flags, and return values"))
|
|
27
|
+
title.setFont(QFont("sans-serif", 10, QFont.Bold))
|
|
28
|
+
layout.addWidget(title)
|
|
29
|
+
|
|
30
|
+
# Search
|
|
31
|
+
search_label = QLabel(self.tr("Search (prefix match):"))
|
|
32
|
+
layout.addWidget(search_label)
|
|
33
|
+
self.search_edit = QLineEdit()
|
|
34
|
+
self.search_edit.setPlaceholderText(self.tr("Enter title, member name, and group name"))
|
|
35
|
+
self.search_edit.textChanged.connect(self.refresh_list)
|
|
36
|
+
layout.addWidget(self.search_edit)
|
|
37
|
+
|
|
38
|
+
# List
|
|
39
|
+
self.list_widget = QListWidget()
|
|
40
|
+
self.list_widget.itemDoubleClicked.connect(self._on_item_double_clicked)
|
|
41
|
+
layout.addWidget(self.list_widget, stretch=1)
|
|
42
|
+
|
|
43
|
+
# Register button
|
|
44
|
+
btn_layout = QHBoxLayout()
|
|
45
|
+
add_var_btn = QPushButton(self.tr("Register variable..."))
|
|
46
|
+
add_var_btn.clicked.connect(self.register_variable)
|
|
47
|
+
btn_layout.addWidget(add_var_btn)
|
|
48
|
+
|
|
49
|
+
add_flag_btn = QPushButton(self.tr("Register flag..."))
|
|
50
|
+
add_flag_btn.clicked.connect(self.register_flag)
|
|
51
|
+
btn_layout.addWidget(add_flag_btn)
|
|
52
|
+
layout.addLayout(btn_layout)
|
|
53
|
+
|
|
54
|
+
# Open global definitions
|
|
55
|
+
open_defs_btn = QPushButton(self.tr("Open global definitions..."))
|
|
56
|
+
open_defs_btn.clicked.connect(self.open_global_definitions)
|
|
57
|
+
layout.addWidget(open_defs_btn)
|
|
58
|
+
|
|
59
|
+
self.refresh_list()
|
|
60
|
+
StaTableLogger.debug("SymbolPickerWidget initialized")
|
|
61
|
+
|
|
62
|
+
# ------------------------------------------------------------------
|
|
63
|
+
# Refresh list
|
|
64
|
+
# ------------------------------------------------------------------
|
|
65
|
+
def refresh_list(self):
|
|
66
|
+
query = self.search_edit.text().strip().lower() if hasattr(self, 'search_edit') else ""
|
|
67
|
+
StaTableLogger.debug(f"SymbolPickerWidget.refresh_list: query='{query}'")
|
|
68
|
+
|
|
69
|
+
self.list_widget.clear()
|
|
70
|
+
|
|
71
|
+
# Global variables
|
|
72
|
+
for var in self.global_defs.variables:
|
|
73
|
+
if self._matches(var.title, var.name, var.group, query):
|
|
74
|
+
item = QListWidgetItem(f"Variable: {var.title}")
|
|
75
|
+
item.setData(Qt.UserRole, var.name)
|
|
76
|
+
item.setToolTip(
|
|
77
|
+
f"Kind: Global variable\n"
|
|
78
|
+
f"Title: {var.title}\n"
|
|
79
|
+
f"Name: {var.name}\n"
|
|
80
|
+
f"Type: {var.type}\n"
|
|
81
|
+
f"Unit: {var.unit}\n"
|
|
82
|
+
f"Initial value: {var.default_value}\n"
|
|
83
|
+
f"Group: {var.group}\n"
|
|
84
|
+
f"Description: {var.description}"
|
|
85
|
+
)
|
|
86
|
+
self.list_widget.addItem(item)
|
|
87
|
+
|
|
88
|
+
# Event flags
|
|
89
|
+
for flag in self.global_defs.flags:
|
|
90
|
+
if self._matches(flag.title, flag.name, flag.group, query):
|
|
91
|
+
item = QListWidgetItem(f"Flag: {flag.title}")
|
|
92
|
+
item.setData(Qt.UserRole, flag.name)
|
|
93
|
+
item.setToolTip(
|
|
94
|
+
f"Kind: Event flag\n"
|
|
95
|
+
f"Title: {flag.title}\n"
|
|
96
|
+
f"Name: {flag.name}\n"
|
|
97
|
+
f"Min value: {flag.min_value}\n"
|
|
98
|
+
f"Max value: {flag.max_value}\n"
|
|
99
|
+
f"Bit width: {flag.bit_width} bit\n"
|
|
100
|
+
f"Group: {flag.group}\n"
|
|
101
|
+
f"Description: {flag.description}"
|
|
102
|
+
)
|
|
103
|
+
self.list_widget.addItem(item)
|
|
104
|
+
|
|
105
|
+
# Role function return value (temp variable)
|
|
106
|
+
for func_name in self.role_functions.keys():
|
|
107
|
+
temp_var = f"rv_{func_name}"
|
|
108
|
+
if self._matches(temp_var, func_name, "", query):
|
|
109
|
+
item = QListWidgetItem(f"Return value: {temp_var}")
|
|
110
|
+
item.setData(Qt.UserRole, temp_var)
|
|
111
|
+
item.setToolTip(
|
|
112
|
+
f"Kind: Role function return value\n"
|
|
113
|
+
f"Function: {func_name}\n"
|
|
114
|
+
f"Temp variable: {temp_var}"
|
|
115
|
+
)
|
|
116
|
+
self.list_widget.addItem(item)
|
|
117
|
+
|
|
118
|
+
StaTableLogger.debug(f"SymbolPickerWidget: {self.list_widget.count()} items displayed")
|
|
119
|
+
|
|
120
|
+
def _matches(self, title: str, name: str, group: str, query: str) -> bool:
|
|
121
|
+
if not query:
|
|
122
|
+
return True
|
|
123
|
+
q = query.lower()
|
|
124
|
+
return (
|
|
125
|
+
title.lower().startswith(q) or
|
|
126
|
+
name.lower().startswith(q) or
|
|
127
|
+
group.lower().startswith(q)
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# ------------------------------------------------------------------
|
|
131
|
+
# Double-click
|
|
132
|
+
# ------------------------------------------------------------------
|
|
133
|
+
def _on_item_double_clicked(self, item: QListWidgetItem):
|
|
134
|
+
insertion_text = item.data(Qt.UserRole)
|
|
135
|
+
StaTableLogger.debug(f"SymbolPickerWidget double-click: '{insertion_text}'")
|
|
136
|
+
if insertion_text:
|
|
137
|
+
self.insert_requested.emit(insertion_text)
|
|
138
|
+
|
|
139
|
+
# ------------------------------------------------------------------
|
|
140
|
+
# Register
|
|
141
|
+
# ------------------------------------------------------------------
|
|
142
|
+
def register_variable(self):
|
|
143
|
+
StaTableLogger.debug("SymbolPickerWidget.register_variable called")
|
|
144
|
+
dlg = VariableEditDialog(self, groups=self.global_defs.variable_groups())
|
|
145
|
+
if dlg.exec() == QDialog.Accepted:
|
|
146
|
+
var = dlg.get_variable()
|
|
147
|
+
if not var.name:
|
|
148
|
+
return
|
|
149
|
+
if any(v.name == var.name for v in self.global_defs.variables):
|
|
150
|
+
return
|
|
151
|
+
self.global_defs.variables.append(var)
|
|
152
|
+
self.refresh_list()
|
|
153
|
+
|
|
154
|
+
def register_flag(self):
|
|
155
|
+
StaTableLogger.debug("SymbolPickerWidget.register_flag called")
|
|
156
|
+
dlg = FlagEditDialog(self, groups=self.global_defs.flag_groups())
|
|
157
|
+
if dlg.exec() == QDialog.Accepted:
|
|
158
|
+
flag = dlg.get_flag()
|
|
159
|
+
if not flag.name:
|
|
160
|
+
return
|
|
161
|
+
if any(f.name == flag.name for f in self.global_defs.flags):
|
|
162
|
+
return
|
|
163
|
+
self.global_defs.flags.append(flag)
|
|
164
|
+
self.refresh_list()
|
|
165
|
+
|
|
166
|
+
def open_global_definitions(self):
|
|
167
|
+
StaTableLogger.debug("SymbolPickerWidget.open_global_definitions called")
|
|
168
|
+
dlg = GlobalDefinitionsDialog(self.global_defs, self)
|
|
169
|
+
dlg.exec()
|
|
170
|
+
self.refresh_list()
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from PySide6.QtWidgets import QDockWidget, QPlainTextEdit, QWidget, QVBoxLayout
|
|
2
|
+
from PySide6.QtCore import Qt
|
|
3
|
+
|
|
4
|
+
from .logger import StaTableLogger
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TraceBallWidget(QDockWidget):
|
|
8
|
+
def __init__(self, parent=None):
|
|
9
|
+
super().__init__("TraceBall", parent)
|
|
10
|
+
self.setObjectName("TraceBall")
|
|
11
|
+
self.setAllowedAreas(Qt.AllDockWidgetAreas)
|
|
12
|
+
self.setFeatures(
|
|
13
|
+
QDockWidget.DockWidgetFloatable |
|
|
14
|
+
QDockWidget.DockWidgetMovable |
|
|
15
|
+
QDockWidget.DockWidgetClosable
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
container = QWidget()
|
|
19
|
+
layout = QVBoxLayout(container)
|
|
20
|
+
self.text_view = QPlainTextEdit()
|
|
21
|
+
self.text_view.setReadOnly(True)
|
|
22
|
+
self.text_view.setMaximumBlockCount(1000)
|
|
23
|
+
layout.addWidget(self.text_view)
|
|
24
|
+
self.setWidget(container)
|
|
25
|
+
|
|
26
|
+
logger = StaTableLogger()
|
|
27
|
+
logger.set_log_callback(self.append_log)
|
|
28
|
+
|
|
29
|
+
self.append_log("TraceBall ready.")
|
|
30
|
+
|
|
31
|
+
def append_log(self, message: str):
|
|
32
|
+
self.text_view.appendPlainText(message)
|
|
33
|
+
scrollbar = self.text_view.verticalScrollBar()
|
|
34
|
+
scrollbar.setValue(scrollbar.maximum())
|
|
35
|
+
|
|
36
|
+
def clear(self):
|
|
37
|
+
self.text_view.clear()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# statable_gui/transition_editor_direct/__init__.py
|
|
2
|
+
"""
|
|
3
|
+
Action edit D&D package
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .draft import FlowItem, TransitionParams, ActionDraft, SystemGlobal
|
|
7
|
+
from .dialog import ActionEditorDialog
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
'FlowItem',
|
|
11
|
+
'TransitionParams',
|
|
12
|
+
'ActionDraft',
|
|
13
|
+
'SystemGlobal',
|
|
14
|
+
'ActionEditorDialog',
|
|
15
|
+
]
|