Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/instructions/pytest_testing_instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ class TestTemplateSelection:

1. **Run tests**: `pytest tests/ -v`
2. **Check coverage**: `pytest --cov=ardupilot_methodic_configurator --cov-report=term-missing`
3. **Format with ruff**: `ruff formal`
3. **Format with ruff**: `ruff format`
4. **Lint with ruff**: `ruff check --fix`
5. **Type check with mypy**: `mypy`
6. **Advanced type check with pyright**: `pyright`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def __init__(self) -> None:
pass

@classmethod
def _get_settings_defaults(cls) -> dict[str, Union[int, bool, str, float, dict]]:
def _get_settings_defaults(cls) -> dict[str, Union[int, bool, str, float, dict, list]]:
"""
Get the default settings dictionary with dynamically computed paths.

Expand All @@ -89,6 +89,7 @@ def _get_settings_defaults(cls) -> dict[str, Union[int, bool, str, float, dict]]
return {
"Format version": 1,
"display_usage_popup": dict.fromkeys(USAGE_POPUP_WINDOWS, True),
"connection_history": [],
"directory_selection": {
"template_dir": os_path.join(cls.get_templates_base_dir(), "ArduCopter", "empty_4.6.x"),
"new_base_dir": os_path.join(settings_directory, "vehicles"),
Expand Down Expand Up @@ -455,3 +456,60 @@ def motor_diagram_exists(frame_class: int, frame_type: int) -> bool:
"""
filepath, _error_msg = ProgramSettings.motor_diagram_filepath(frame_class, frame_type)
return filepath != "" and os_path.exists(filepath)

@staticmethod
def get_connection_history() -> list[str]:
"""
Get the list of previously used connection strings.

Returns the connection history from settings, filtering out any invalid entries.
Only valid string entries are returned.

Returns:
List of connection strings in most-recent-first order (up to 10 items).

"""
settings = ProgramSettings._get_settings_as_dict()
history = settings.get("connection_history", [])

if not isinstance(history, list):
return []

return [item for item in history if isinstance(item, str)]

@staticmethod
def store_connection(connection_string: str) -> None:
"""
Save a new connection string to history.

The history maintains up to 10 most recent connections in chronological order.
If the connection already exists, it's moved to the top of the list.
Empty strings, whitespace-only strings, and strings longer than 200 characters
are ignored.

Args:
connection_string: The connection string to store (max 200 characters).

"""
if not connection_string or not connection_string.strip():
return

connection_string = connection_string.strip()

# Reject connection strings that are too long
if len(connection_string) > 200:
return

settings = ProgramSettings._get_settings_as_dict()
history = settings.get("connection_history", [])

if connection_string in history:
history.remove(connection_string)

history.insert(0, connection_string)

if len(history) > 10:
history = history[:10]

settings["connection_history"] = history
ProgramSettings._set_settings_from_dict(settings)
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from typing import Union

from ardupilot_methodic_configurator import _, __version__
from ardupilot_methodic_configurator.backend_filesystem_program_settings import ProgramSettings
from ardupilot_methodic_configurator.backend_flightcontroller import SUPPORTED_BAUDRATES, FlightController
from ardupilot_methodic_configurator.common_arguments import add_common_arguments
from ardupilot_methodic_configurator.frontend_tkinter_base_window import BaseWindow
Expand Down Expand Up @@ -73,6 +74,9 @@ def __init__( # pylint: disable=too-many-arguments, too-many-positional-argumen
# Create a label for port
port_label = ttk.Label(selection_frame, text=_("Port:"))
port_label.pack(side=tk.LEFT, padx=(0, 5))
# Load saved connection history from ProgramSettings
for conn in ProgramSettings.get_connection_history():
self.flight_controller.add_connection(conn)

# Create a read-only combobox for flight controller connection selection
self.conn_selection_combobox = PairTupleCombobox(
Expand Down Expand Up @@ -157,6 +161,7 @@ def add_connection(self) -> str:
),
)
if selected_connection:
ProgramSettings.store_connection(selected_connection)
error_msg = _("Will add new connection: {selected_connection} if not duplicated")
logging_debug(error_msg.format(**locals()))
self.flight_controller.add_connection(selected_connection)
Expand Down
Loading