diff --git a/src/vocalinux/ui/settings_dialog.py b/src/vocalinux/ui/settings_dialog.py index 093e0c2..eb744a5 100644 --- a/src/vocalinux/ui/settings_dialog.py +++ b/src/vocalinux/ui/settings_dialog.py @@ -7320,7 +7320,16 @@ class SettingsDialog(Gtk.Dialog): text_injection_settings = self.config_manager.get_settings().get("text_injection", {}) history_settings = self.config_manager.get_settings().get("history", {}) - autostart_enabled = general_settings.get("autostart", False) + # The login desktop entry can be added or removed outside the app; the + # real file state wins over the stored preference (previously synced by + # the tray menu's Start on Login item). + from . import autostart_manager + + autostart_enabled = autostart_manager.is_autostart_enabled() + if autostart_enabled != general_settings.get("autostart", False): + self.config_manager.set("general", "autostart", autostart_enabled) + self.config_manager.save_settings() + start_minimized = ui_settings.get("start_minimized", False) show_missing_tray_warning = ui_settings.get("show_missing_tray_warning", True) show_overlay = ui_settings.get("show_overlay", True) diff --git a/src/vocalinux/ui/tray_indicator.py b/src/vocalinux/ui/tray_indicator.py index a5abe1e..3bf517d 100644 --- a/src/vocalinux/ui/tray_indicator.py +++ b/src/vocalinux/ui/tray_indicator.py @@ -179,7 +179,6 @@ class TrayIndicator: # settings toggle, resume) must keep honoring the fallback rather # than reapplying a disable_internal_hotkey setting D-Bus cannot serve. self._external_activation_unavailable = False - self._syncing_autostart_menu = False self._history_menu_item = None # Refresh the history submenu whenever the history changes. The change @@ -584,12 +583,6 @@ class TrayIndicator: self._refresh_history_menu() self._add_menu_separator() - self._autostart_menu_item = self._add_menu_checkbox( - "Start on Login", self._on_autostart_toggled - ) - self._update_autostart_checkbox() - - self._add_menu_separator() if self.dictation_pad is not None: self._add_menu_item("Dictation Pad", self._on_dictation_pad_clicked) self._add_menu_item("Settings", self._on_settings_clicked) @@ -606,7 +599,6 @@ class TrayIndicator: ) self._update_menu_item.set_no_show_all(True) self._update_menu_item.hide() - self._add_menu_item("About", self._on_about_clicked) self._add_menu_item("Quit", self._on_quit_clicked) # Set the indicator menu @@ -827,56 +819,6 @@ class TrayIndicator: separator = Gtk.SeparatorMenuItem() self.menu.append(separator) - def _add_menu_checkbox(self, label: str, callback: Callable) -> Gtk.CheckMenuItem: - """ - Add a checkbox menu item to the indicator menu. - - Args: - label: The label for the menu item - callback: The callback function to call when the item is toggled - - Returns: - The checkbox menu item - """ - item = Gtk.CheckMenuItem.new_with_label(label) - item.connect("toggled", callback) - self.menu.append(item) - return item - - def _update_autostart_checkbox(self): - """Update the autostart checkbox state based on current config.""" - from . import autostart_manager - - autostart_enabled = autostart_manager.is_autostart_enabled() - config_enabled = self.config_manager.get_bool("general", "autostart", False) - if config_enabled != autostart_enabled: - self.config_manager.set("general", "autostart", autostart_enabled) - self.config_manager.save_settings() - - self._syncing_autostart_menu = True - self._autostart_menu_item.set_active(autostart_enabled) - self._syncing_autostart_menu = False - - def _on_autostart_toggled(self, widget): - """Handle toggle of the Start on Login menu item.""" - if self._syncing_autostart_menu: - return - - enabled = widget.get_active() - logger.info(f"Autostart toggled: {enabled}") - - from . import autostart_manager - - if autostart_manager.set_autostart(enabled): - self.config_manager.set("general", "autostart", enabled) - self.config_manager.save_settings() - status = "enabled" if enabled else "disabled" - logger.info(f"Autostart {status}") - else: - self._syncing_autostart_menu = True - widget.set_active(not enabled) - self._syncing_autostart_menu = False - def _on_recognition_state_changed(self, state: RecognitionState): """ Handle changes in the speech recognition state. @@ -1552,11 +1494,6 @@ class TrayIndicator: logger.debug("No changes needed - shortcut and mode unchanged") return True - def _on_about_clicked(self, widget): - """Handle click on the About menu item.""" - logger.debug("About clicked") - self._show_settings_page("about") - def _get_auto_pause_config(self): """Return (enabled, apps, poll_interval_seconds) for AutoPauseMonitor.""" enabled = self.config_manager.get_bool("auto_pause", "enabled", False) diff --git a/tests/test_tray_indicator.py b/tests/test_tray_indicator.py index 8c9a032..5104364 100644 --- a/tests/test_tray_indicator.py +++ b/tests/test_tray_indicator.py @@ -280,8 +280,8 @@ class TestTrayIndicator(unittest.TestCase): mock_dialog_instance.present_with_time.assert_called_once() mock_dialog_instance.navigate_to_page.assert_not_called() - def test_about_reuses_open_settings_dialog(self): - """About focuses the existing Settings window and switches to the About page.""" + def test_update_available_reuses_open_settings_dialog(self): + """Update Available focuses the existing Settings window on the About page.""" import vocalinux.ui.tray_indicator as tray_module mock_dialog_instance = MagicMock() @@ -289,7 +289,7 @@ class TestTrayIndicator(unittest.TestCase): with patch.object(tray_module, "SettingsDialog", mock_dialog_class): self.tray_indicator._on_settings_clicked(None) - self.tray_indicator._on_about_clicked(None) + self.tray_indicator._on_update_available_clicked(None) mock_dialog_class.assert_called_once() mock_dialog_instance.navigate_to_page.assert_called_once_with("about") @@ -312,13 +312,13 @@ class TestTrayIndicator(unittest.TestCase): second_dialog.show.assert_called_once() first_dialog.present_with_time.assert_not_called() - def test_about_dialog(self): - """Test About opens Settings focused on the About page.""" + def test_update_available_opens_about_page(self): + """Test Update Available opens Settings focused on the About page.""" with patch("vocalinux.ui.tray_indicator.SettingsDialog") as mock_dialog_class: mock_dialog_instance = MagicMock() mock_dialog_class.return_value = mock_dialog_instance - self.tray_indicator._on_about_clicked(None) + self.tray_indicator._on_update_available_clicked(None) mock_dialog_class.assert_called_once() kwargs = mock_dialog_class.call_args.kwargs @@ -661,13 +661,13 @@ class TestTrayIndicator(unittest.TestCase): self.tray_indicator.run() mock_quit.assert_called_once() - def test_about_opens_settings_without_raising(self): - """Test About menu item opens settings even if dialog construction is mocked.""" + def test_update_available_opens_settings_without_raising(self): + """Test Update Available opens settings even if dialog construction is mocked.""" with patch("vocalinux.ui.tray_indicator.SettingsDialog") as mock_dialog_class: mock_dialog_instance = MagicMock() mock_dialog_class.return_value = mock_dialog_instance - self.tray_indicator._on_about_clicked(None) + self.tray_indicator._on_update_available_clicked(None) mock_dialog_instance.connect.assert_called() mock_dialog_instance.show.assert_called_once() diff --git a/tests/test_tray_indicator_ext.py b/tests/test_tray_indicator_ext.py index 41c6f02..f91ed04 100644 --- a/tests/test_tray_indicator_ext.py +++ b/tests/test_tray_indicator_ext.py @@ -112,7 +112,6 @@ class TestTrayIndicatorInitialization(unittest.TestCase): assert indicator.text_injector == mock_text_injector assert indicator.config_manager == mock_config_inst assert indicator.shortcut_manager == mock_keyboard_inst - assert indicator._syncing_autostart_menu is False # Verify that idle_add was called to initialize the indicator mock_glib.idle_add.assert_called()