From d834af98a75123a51776e758a77db7a11707312a Mon Sep 17 00:00:00 2001 From: deltragon Date: Wed, 3 Jul 2024 02:03:40 +0200 Subject: [PATCH] Remove uses of deprecated gtk3 apis (#560) * fix deprecations * port to Gtk.Application Gtk.main() and Gtk.main_quit() are dropped in gtk4 in favor of subclassing Gtk.Application. This commit also moves argument handling from a separate thread to GtkApplication.do_startup(). * fix deprecations in settings dialog --- safeeyes/__main__.py | 25 +----------------------- safeeyes/safeeyes.py | 35 ++++++++++++++++++++++++++++------ safeeyes/ui/break_screen.py | 18 +++++++++-------- safeeyes/ui/settings_dialog.py | 32 +++++++++++++++++-------------- 4 files changed, 58 insertions(+), 52 deletions(-) diff --git a/safeeyes/__main__.py b/safeeyes/__main__.py index 2eab4cd..a3c1171 100755 --- a/safeeyes/__main__.py +++ b/safeeyes/__main__.py @@ -25,9 +25,7 @@ import locale import logging import signal import sys -from threading import Timer -import gi import psutil from safeeyes import utility from safeeyes.model import Config @@ -35,9 +33,6 @@ from safeeyes.safeeyes import SafeEyes from safeeyes.safeeyes import SAFE_EYES_VERSION from safeeyes.rpc import RPCClient -gi.require_version('Gtk', '3.0') -from gi.repository import Gtk - gettext.install('safeeyes', utility.LOCALE_PATH) @@ -68,22 +63,6 @@ def __running(): return False -def __evaluate_arguments(args, safe_eyes): - """ - Evaluate the arguments and execute the operations. - """ - if args.about: - utility.execute_main_thread(safe_eyes.show_about) - elif args.disable: - utility.execute_main_thread(safe_eyes.disable_safeeyes) - elif args.enable: - utility.execute_main_thread(safe_eyes.enable_safeeyes) - elif args.settings: - utility.execute_main_thread(safe_eyes.show_settings) - elif args.take_break: - utility.execute_main_thread(safe_eyes.take_break) - - def main(): """ Start the Safe Eyes. @@ -147,10 +126,8 @@ def main(): sys.exit(0) elif not args.quit: logging.info("Starting Safe Eyes") - safe_eyes = SafeEyes(system_locale, config) + safe_eyes = SafeEyes(system_locale, config, args) safe_eyes.start() - Timer(1.0, lambda: __evaluate_arguments(args, safe_eyes)).start() - Gtk.main() if __name__ == '__main__': diff --git a/safeeyes/safeeyes.py b/safeeyes/safeeyes.py index f9b8bf4..144181b 100644 --- a/safeeyes/safeeyes.py +++ b/safeeyes/safeeyes.py @@ -38,17 +38,21 @@ from safeeyes.core import SafeEyesCore from safeeyes.ui.settings_dialog import SettingsDialog gi.require_version('Gtk', '3.0') -from gi.repository import Gtk +from gi.repository import Gtk, Gio SAFE_EYES_VERSION = "2.1.9" -class SafeEyes: +class SafeEyes(Gtk.Application): """ This class represents a runnable Safe Eyes instance. """ - def __init__(self, system_locale, config): + def __init__(self, system_locale, config, cli_args): + super().__init__( + application_id="io.github.slgobinath.SafeEyes", + flags=Gio.ApplicationFlags.IS_SERVICE + ) self.active = False self.break_screen = None self.safe_eyes_core = None @@ -58,6 +62,7 @@ class SafeEyes: self.settings_dialog_active = False self.rpc_server = None self._status = '' + self.cli_args = cli_args # Initialize the Safe Eyes Context self.context['version'] = SAFE_EYES_VERSION @@ -98,6 +103,9 @@ class SafeEyes: self.context['api']['postpone'] = self.safe_eyes_core.postpone self.context['api']['get_break_time'] = self.safe_eyes_core.get_break_time self.plugins_manager.init(self.context, self.config) + + self.hold() + atexit.register(self.persist_session) def start(self): @@ -114,6 +122,22 @@ class SafeEyes: self.safe_eyes_core.start() self.handle_system_suspend() + self.run() + + def do_startup(self): + Gtk.Application.do_startup(self) + + if self.cli_args.about: + self.show_about() + elif self.cli_args.disable: + self.disable_safeeyes() + elif self.cli_args.enable: + self.enable_safeeyes() + elif self.cli_args.settings: + self.show_settings() + elif self.cli_args.take_break: + self.take_break() + def show_settings(self): """ Listen to tray icon Settings action and send the signal to Settings dialog. @@ -144,9 +168,8 @@ class SafeEyes: self.plugins_manager.exit() self.__stop_rpc_server() self.persist_session() - Gtk.main_quit() - # Exit all threads - os._exit(0) + + super().quit() def handle_suspend_callback(self, sleeping): """ diff --git a/safeeyes/ui/break_screen.py b/safeeyes/ui/break_screen.py index d1a2c25..cce0674 100644 --- a/safeeyes/ui/break_screen.py +++ b/safeeyes/ui/break_screen.py @@ -151,12 +151,14 @@ class BreakScreen: # Lock the keyboard utility.start_thread(self.__lock_keyboard) - screen = Gtk.Window().get_screen() - no_of_monitors = screen.get_n_monitors() + display = Gdk.Display.get_default() + screen = display.get_default_screen() + no_of_monitors = display.get_n_monitors() logging.info("Show break screens in %d display(s)", no_of_monitors) - for monitor in range(no_of_monitors): - monitor_gemoetry = screen.get_monitor_geometry(monitor) + for monitor_num in range(no_of_monitors): + monitor = display.get_monitor(monitor_num) + monitor_gemoetry = monitor.get_geometry() x = monitor_gemoetry.x y = monitor_gemoetry.y @@ -165,7 +167,7 @@ class BreakScreen: builder.connect_signals(self) window = builder.get_object("window_main") - window.set_title("SafeEyes-" + str(monitor)) + window.set_title("SafeEyes-" + str(monitor_num)) lbl_message = builder.get_object("lbl_message") lbl_count = builder.get_object("lbl_count") lbl_widget = builder.get_object("lbl_widget") @@ -188,7 +190,7 @@ class BreakScreen: # Add the buttons if self.enable_postpone: # Add postpone button - btn_postpone = Gtk.Button(_('Postpone')) + btn_postpone = Gtk.Button.new_with_label(_('Postpone')) btn_postpone.get_style_context().add_class('btn_postpone') btn_postpone.connect('clicked', self.on_postpone_clicked) btn_postpone.set_visible(True) @@ -196,7 +198,7 @@ class BreakScreen: if not self.strict_break: # Add the skip button - btn_skip = Gtk.Button(_('Skip')) + btn_skip = Gtk.Button.new_with_label(_('Skip')) btn_skip.get_style_context().add_class('btn_skip') btn_skip.connect('clicked', self.on_skip_clicked) btn_skip.set_visible(True) @@ -222,7 +224,7 @@ class BreakScreen: window.resize(monitor_gemoetry.width, monitor_gemoetry.height) window.stick() window.set_keep_above(True) - window.fullscreen() + window.fullscreen_on_monitor(screen, monitor_num) window.present() # In other desktop environments, move the window after present window.move(x, y) diff --git a/safeeyes/ui/settings_dialog.py b/safeeyes/ui/settings_dialog.py index b8ef8e9..f4bc4e3 100644 --- a/safeeyes/ui/settings_dialog.py +++ b/safeeyes/ui/settings_dialog.py @@ -170,14 +170,16 @@ class SettingsDialog: self.__initialize(self.config) widget.destroy() - messagedialog = Gtk.MessageDialog(parent=self.window, - flags=Gtk.DialogFlags.MODAL, - type=Gtk.MessageType.WARNING, - buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, - _("Reset"), Gtk.ResponseType.OK), - message_format=_("Are you sure you want to reset all settings to default?")) + messagedialog = Gtk.MessageDialog() + messagedialog.set_modal(True) + messagedialog.set_transient_for(self.window) + messagedialog.set_property('message_type', Gtk.MessageType.WARNING) + messagedialog.set_property('text', _("Are you sure you want to reset all settings to default?")) + messagedialog.set_property('secondary-text', _("You can't undo this action.")) + messagedialog.add_button('_Cancel', Gtk.ResponseType.CANCEL) + messagedialog.add_button(_("Reset"), Gtk.ResponseType.OK) + messagedialog.connect("response", __confirmation_dialog_response) - messagedialog.format_secondary_text(_("You can't undo this action.")) messagedialog.show() def __delete_break(self, break_config, is_short, on_remove): @@ -194,14 +196,16 @@ class SettingsDialog: on_remove() widget.destroy() - messagedialog = Gtk.MessageDialog(parent=self.window, - flags=Gtk.DialogFlags.MODAL, - type=Gtk.MessageType.WARNING, - buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, - _("Delete"), Gtk.ResponseType.OK), - message_format=_("Are you sure you want to delete this break?")) + messagedialog = Gtk.MessageDialog() + messagedialog.set_modal(True) + messagedialog.set_transient_for(self.window) + messagedialog.set_property('message_type', Gtk.MessageType.WARNING) + messagedialog.set_property('text', _("Are you sure you want to delete this break?")) + messagedialog.set_property('secondary-text', _("You can't undo this action.")) + messagedialog.add_button('_Cancel', Gtk.ResponseType.CANCEL) + messagedialog.add_button(_("Delete"), Gtk.ResponseType.OK) + messagedialog.connect("response", __confirmation_dialog_response) - messagedialog.format_secondary_text(_("You can't undo this action.")) messagedialog.show() def __create_plugin_item(self, plugin_config):