feat(tray): remove Start on Login and About from the tray menu (#905)
* feat(tray): remove Start on Login and About from the tray menu
Both entries already live in Settings: the autostart switch is in the
general page and About is a dedicated sidebar page, so the tray items
are redundant. View Logs stays.
Removes the Start on Login checkbox item along with its
_update_autostart_checkbox/_on_autostart_toggled wiring and the now
unused _add_menu_checkbox helper, plus the About item and
_on_about_clicked. _show_settings_page("about") stays for the Update
Available item. autostart_manager is untouched since Settings uses it.
Fixes #654
* fix(settings): sync autostart switch with the real desktop entry
The tray's removed _update_autostart_checkbox also reconciled
general.autostart with the actual login desktop entry at startup. Move
that check into the settings load so the Start on Login switch still
reflects reality when the entry changes outside the app.
---------
Co-authored-by: Jatin K Malik <jatinkrmalik@gmail.com>
This commit is contained in:
co-authored by
Jatin K Malik
parent
26c4f9052b
commit
6a6cc93919
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user