Skip to content

Commit 0bfb40c

Browse files
committed
feat(param editor): Only display derived parameters on normal GUI complexity
1 parent 89d45ac commit 0bfb40c

2 files changed

Lines changed: 110 additions & 9 deletions

File tree

ardupilot_methodic_configurator/frontend_tkinter_parameter_editor_table.py

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ def repopulate(self, selected_file: str, fc_parameters: dict[str, float], show_o
129129
self.parameter_editor.on_skip_click(force_focus_out_event=False)
130130
return
131131
else:
132+
# Use all parameters - don't filter by complexity here so they're processed for upload and save
133+
# The filtering for display will happen in __update_table
132134
self.__update_table(self.local_filesystem.file_parameters[selected_file], fc_parameters)
133135
# Scroll to the top of the parameter table
134136
self.canvas.yview("moveto", 0)
@@ -179,9 +181,30 @@ def rename_fc_connection(self, selected_file: str) -> None:
179181

180182
def __update_table(self, params: dict[str, Par], fc_parameters: dict[str, float]) -> None:
181183
current_param_name: str = ""
184+
displayed_row_count = 0
182185
try:
183-
for i, (param_name, param) in enumerate(params.items(), 1):
186+
for __, (param_name, param) in enumerate(params.items(), 1):
184187
current_param_name = param_name
188+
189+
# Create upload checkbutton variable for all parameters (even if not displayed)
190+
# so they can be uploaded to the flight controller
191+
self.upload_checkbutton_var[param_name] = tk.BooleanVar(value=bool(fc_parameters))
192+
193+
# Check if parameter should be displayed based on GUI complexity
194+
if self.parameter_editor.gui_complexity == "simple":
195+
# Do not display forced and derived parameters in simple mode
196+
if (
197+
self.current_file in self.local_filesystem.forced_parameters
198+
and param_name in self.local_filesystem.forced_parameters[self.current_file]
199+
):
200+
continue
201+
if (
202+
self.current_file in self.local_filesystem.derived_parameters
203+
and param_name in self.local_filesystem.derived_parameters[self.current_file]
204+
):
205+
continue
206+
207+
displayed_row_count += 1
185208
param_metadata = self.local_filesystem.doc_dict.get(param_name, {})
186209
param_default = self.local_filesystem.param_default_dict.get(param_name, None)
187210
doc_tooltip = param_metadata.get(
@@ -198,21 +221,21 @@ def __update_table(self, params: dict[str, Par], fc_parameters: dict[str, float]
198221
# workaround a mypy issue
199222
column.append(self.__create_change_reason_entry(param_name, param, column[3])) # type: ignore[arg-type]
200223

201-
column[0].grid(row=i, column=0, sticky="w", padx=0)
202-
column[1].grid(row=i, column=1, sticky="w", padx=0)
203-
column[2].grid(row=i, column=2, sticky="e", padx=0)
204-
column[3].grid(row=i, column=3, sticky="e", padx=0)
205-
column[4].grid(row=i, column=4, sticky="e", padx=0)
206-
column[5].grid(row=i, column=5, sticky="e", padx=0)
207-
column[6].grid(row=i, column=6, sticky="ew", padx=(0, 5))
224+
column[0].grid(row=displayed_row_count, column=0, sticky="w", padx=0)
225+
column[1].grid(row=displayed_row_count, column=1, sticky="w", padx=0)
226+
column[2].grid(row=displayed_row_count, column=2, sticky="e", padx=0)
227+
column[3].grid(row=displayed_row_count, column=3, sticky="e", padx=0)
228+
column[4].grid(row=displayed_row_count, column=4, sticky="e", padx=0)
229+
column[5].grid(row=displayed_row_count, column=5, sticky="e", padx=0)
230+
column[6].grid(row=displayed_row_count, column=6, sticky="ew", padx=(0, 5))
208231

209232
# Add the "Add" button at the bottom of the table
210233
add_button = ttk.Button(
211234
self.view_port, text=_("Add"), style="narrow.TButton", command=lambda: self.__on_parameter_add(fc_parameters)
212235
)
213236
tooltip_msg = _("Add a parameter to the {self.current_file} file")
214237
show_tooltip(add_button, tooltip_msg.format(**locals()))
215-
add_button.grid(row=len(params) + 2, column=0, sticky="w", padx=0)
238+
add_button.grid(row=displayed_row_count + 2, column=0, sticky="w", padx=0)
216239

217240
except KeyError as e:
218241
logging_critical(

tests/test_frontend_tkinter_parameter_editor_table.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,4 +276,82 @@ def test_repopulate_show_only_differences(parameter_editor_table: ParameterEdito
276276
# assert parameter_editor_table.add_parameter_row.call_count == 2
277277

278278

279+
def test_repopulate_filter_by_gui_complexity(
280+
parameter_editor_table: ParameterEditorTable, mock_parameter_editor: MagicMock
281+
) -> None:
282+
"""Test that forced and derived parameters are calculated but filtered from display in simple mode."""
283+
# Setup
284+
test_file = "test_file.param"
285+
parameter_editor_table.current_file = test_file
286+
parameter_editor_table.parameter_editor = mock_parameter_editor
287+
mock_parameter_editor.gui_complexity = "simple" # Set to simple mode
288+
289+
# Create test parameters
290+
parameter_editor_table.local_filesystem.file_parameters = {
291+
test_file: {
292+
"PARAM1": Par(1.0, "normal parameter"),
293+
"PARAM2": Par(2.0, "forced parameter"),
294+
"PARAM3": Par(3.0, "derived parameter"),
295+
}
296+
}
297+
298+
# Set up forced parameters
299+
parameter_editor_table.local_filesystem.forced_parameters = {
300+
test_file: {
301+
"PARAM2": Par(2.0, "forced parameter"),
302+
}
303+
}
304+
305+
# Set up derived parameters
306+
parameter_editor_table.local_filesystem.derived_parameters = {
307+
test_file: {
308+
"PARAM3": Par(3.0, "derived parameter"),
309+
}
310+
}
311+
312+
# Setup required metadata
313+
parameter_editor_table.local_filesystem.doc_dict = {
314+
"PARAM1": {"units": "none"},
315+
"PARAM2": {"units": "none"},
316+
"PARAM3": {"units": "none"},
317+
}
318+
parameter_editor_table.local_filesystem.param_default_dict = {
319+
"PARAM1": Par(0.0, "default"),
320+
"PARAM2": Par(0.0, "default"),
321+
"PARAM3": Par(0.0, "default"),
322+
}
323+
324+
fc_parameters = {
325+
"PARAM1": 1.0,
326+
"PARAM2": 2.0,
327+
"PARAM3": 3.0,
328+
}
329+
330+
# Patch the update_table method to check parameters passed to it
331+
with patch.object(parameter_editor_table, "_ParameterEditorTable__update_table") as mock_update:
332+
parameter_editor_table.repopulate(test_file, fc_parameters, show_only_differences=False)
333+
334+
# In simple mode, all parameters should be passed to update_table for processing
335+
# but the filtering of display happens inside update_table
336+
mock_update.assert_called_once()
337+
params_dict = mock_update.call_args[0][0]
338+
assert len(params_dict) == 3
339+
assert "PARAM1" in params_dict
340+
assert "PARAM2" in params_dict
341+
assert "PARAM3" in params_dict
342+
343+
# Now test with normal complexity
344+
mock_parameter_editor.gui_complexity = "normal"
345+
with patch.object(parameter_editor_table, "_ParameterEditorTable__update_table") as mock_update:
346+
parameter_editor_table.repopulate(test_file, fc_parameters, show_only_differences=False)
347+
348+
# In normal mode, all parameters should be passed to update_table
349+
mock_update.assert_called_once()
350+
params_dict = mock_update.call_args[0][0]
351+
assert len(params_dict) == 3
352+
assert "PARAM1" in params_dict
353+
assert "PARAM2" in params_dict
354+
assert "PARAM3" in params_dict
355+
356+
279357
# pylint: enable=redefined-outer-name

0 commit comments

Comments
 (0)