From 2b9f6c871aa2a34c771331538d7f031da6252528 Mon Sep 17 00:00:00 2001 From: deltragon Date: Tue, 2 Jan 2024 13:36:41 +0100 Subject: [PATCH 01/11] gtk4: simple changes --- safeeyes/platform/io.github.slgobinath.SafeEyes.desktop | 2 +- safeeyes/plugins/donotdisturb/plugin.py | 2 +- safeeyes/plugins/mediacontrol/plugin.py | 2 +- safeeyes/plugins/screensaver/plugin.py | 2 +- safeeyes/plugins/trayicon/plugin.py | 2 +- safeeyes/safeeyes.py | 2 +- safeeyes/ui/break_screen.py | 2 +- safeeyes/ui/settings_dialog.py | 2 +- safeeyes/utility.py | 4 ++-- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/safeeyes/platform/io.github.slgobinath.SafeEyes.desktop b/safeeyes/platform/io.github.slgobinath.SafeEyes.desktop index e3561a4..9b21223 100644 --- a/safeeyes/platform/io.github.slgobinath.SafeEyes.desktop +++ b/safeeyes/platform/io.github.slgobinath.SafeEyes.desktop @@ -25,7 +25,7 @@ Comment[tr]=Gözünüzü yorgunluğa karşı koruyun Comment[uk]=Захистіть свої очі від втоми Comment[vi]=Bảo vệ đôi mắt của bạn khỏi sự mệt mỏi GenericName=RSI Prevention -Exec=env GDK_BACKEND=x11 safeeyes +Exec=safeeyes Icon=io.github.slgobinath.SafeEyes Terminal=false Type=Application diff --git a/safeeyes/plugins/donotdisturb/plugin.py b/safeeyes/plugins/donotdisturb/plugin.py index 0fdefa5..7d5e045 100644 --- a/safeeyes/plugins/donotdisturb/plugin.py +++ b/safeeyes/plugins/donotdisturb/plugin.py @@ -27,7 +27,7 @@ import re import subprocess import gi -gi.require_version('Gdk', '3.0') +gi.require_version('Gdk', '4.0') from gi.repository import Gdk from gi.repository import GdkX11 # noqa F401 from gi.repository import Gio diff --git a/safeeyes/plugins/mediacontrol/plugin.py b/safeeyes/plugins/mediacontrol/plugin.py index 5c43ac3..b9161ec 100644 --- a/safeeyes/plugins/mediacontrol/plugin.py +++ b/safeeyes/plugins/mediacontrol/plugin.py @@ -25,7 +25,7 @@ import os import re import gi from safeeyes.model import TrayAction -gi.require_version('Gtk', '3.0') +gi.require_version('Gtk', '4.0') from gi.repository import Gtk, Gio tray_icon_path = None diff --git a/safeeyes/plugins/screensaver/plugin.py b/safeeyes/plugins/screensaver/plugin.py index e8e5e3b..cc49c04 100644 --- a/safeeyes/plugins/screensaver/plugin.py +++ b/safeeyes/plugins/screensaver/plugin.py @@ -26,7 +26,7 @@ import os from safeeyes import utility from safeeyes.model import TrayAction -gi.require_version('Gtk', '3.0') +gi.require_version('Gtk', '4.0') from gi.repository import Gtk context = None diff --git a/safeeyes/plugins/trayicon/plugin.py b/safeeyes/plugins/trayicon/plugin.py index 42b309a..3c4f04a 100644 --- a/safeeyes/plugins/trayicon/plugin.py +++ b/safeeyes/plugins/trayicon/plugin.py @@ -19,7 +19,7 @@ import datetime from safeeyes.model import BreakType import gi -gi.require_version('Gtk', '3.0') +gi.require_version('Gtk', '4.0') from gi.repository import Gio, GLib import logging from safeeyes import utility diff --git a/safeeyes/safeeyes.py b/safeeyes/safeeyes.py index 0fb9a9b..ab60537 100644 --- a/safeeyes/safeeyes.py +++ b/safeeyes/safeeyes.py @@ -36,7 +36,7 @@ from safeeyes.plugin_manager import PluginManager from safeeyes.core import SafeEyesCore from safeeyes.ui.settings_dialog import SettingsDialog -gi.require_version('Gtk', '3.0') +gi.require_version('Gtk', '4.0') from gi.repository import Gtk, Gio, GLib SAFE_EYES_VERSION = "2.2.2" diff --git a/safeeyes/ui/break_screen.py b/safeeyes/ui/break_screen.py index 7546fd8..69959b0 100644 --- a/safeeyes/ui/break_screen.py +++ b/safeeyes/ui/break_screen.py @@ -27,7 +27,7 @@ from safeeyes import utility from Xlib.display import Display from Xlib.display import X -gi.require_version('Gtk', '3.0') +gi.require_version('Gtk', '4.0') from gi.repository import Gdk from gi.repository import GLib from gi.repository import Gtk diff --git a/safeeyes/ui/settings_dialog.py b/safeeyes/ui/settings_dialog.py index 62f54f4..cae0c8b 100644 --- a/safeeyes/ui/settings_dialog.py +++ b/safeeyes/ui/settings_dialog.py @@ -23,7 +23,7 @@ import gi from safeeyes import utility from safeeyes.model import Config, PluginDependency -gi.require_version('Gtk', '3.0') +gi.require_version('Gtk', '4.0') from gi.repository import Gtk from gi.repository import GdkPixbuf diff --git a/safeeyes/utility.py b/safeeyes/utility.py index bcb0fc2..6eeb177 100644 --- a/safeeyes/utility.py +++ b/safeeyes/utility.py @@ -38,13 +38,13 @@ from pathlib import Path import babel.core import babel.dates import gi -gi.require_version('Gtk', '3.0') +gi.require_version('Gtk', '4.0') from gi.repository import Gtk from gi.repository import GLib from gi.repository import GdkPixbuf from packaging.version import parse -gi.require_version('Gdk', '3.0') +gi.require_version('Gdk', '4.0') BIN_DIRECTORY = os.path.dirname(os.path.realpath(__file__)) HOME_DIRECTORY = os.environ.get('HOME') or os.path.expanduser('~') From 3d287754799f0a6ca7adba594ceb5201318de004 Mon Sep 17 00:00:00 2001 From: deltragon Date: Tue, 2 Jan 2024 13:36:43 +0100 Subject: [PATCH 02/11] gtk4: get break screen ui running --- safeeyes/glade/break_screen.glade | 159 ++++++++---------------- safeeyes/model.py | 7 +- safeeyes/plugins/mediacontrol/plugin.py | 2 +- safeeyes/plugins/screensaver/plugin.py | 2 +- safeeyes/ui/break_screen.py | 48 +++---- 5 files changed, 78 insertions(+), 140 deletions(-) diff --git a/safeeyes/glade/break_screen.glade b/safeeyes/glade/break_screen.glade index 277ef4a..23b1e45 100644 --- a/safeeyes/glade/break_screen.glade +++ b/safeeyes/glade/break_screen.glade @@ -1,5 +1,4 @@ - - + - False - center - True safeeyes - True - True - False - False - False - center - + 0 + 0 - + - True - False - True - True + 1 + 1 - True - False vertical 10 - True - False center center 10 - True - False + + 0 + 0 + - - 0 - 0 - - True - False center center - True + 1 15 - True - False Hello World center + + 0 + 0 + 3 + - - 0 - 0 - 3 - - - True - False + center - 0.20000000298023224 - - - True - False - 00 - - - + 00 + + + 1 + 2 + - - 1 - 1 - - True - False center 50 - True + 1 + + 1 + 3 + - - 1 - 3 - @@ -151,89 +119,62 @@ + + 0 + 1 + 3 + - - 0 - 1 - 3 - - - False - True - 0 - - True - False + 1 Widget 0.25 - - True - True - end - 1 - + + 0 + 1 + 2 + - - 0 - 1 - 2 - - True - False vertical - - True - False + + toolbar + 0 end start - icons - 2 - - False - True - 0 - - True - False + 1 - - True - True - 1 - + + 0 + 0 + - - 0 - 0 - - + diff --git a/safeeyes/model.py b/safeeyes/model.py index 2f8f9b8..6d9dd4c 100644 --- a/safeeyes/model.py +++ b/safeeyes/model.py @@ -27,6 +27,10 @@ from dataclasses import dataclass from packaging.version import parse +import gi +gi.require_version('Gtk', '4.0') +from gi.repository import Gtk + from safeeyes import utility @@ -399,7 +403,8 @@ class TrayAction: def get_icon(self): if self.system_icon: - return self.__icon + image = Gtk.Image.new_from_icon_name(self.__icon) + return image else: image = utility.load_and_scale_image(self.__icon, 16, 16) image.show() diff --git a/safeeyes/plugins/mediacontrol/plugin.py b/safeeyes/plugins/mediacontrol/plugin.py index b9161ec..deacfb9 100644 --- a/safeeyes/plugins/mediacontrol/plugin.py +++ b/safeeyes/plugins/mediacontrol/plugin.py @@ -90,5 +90,5 @@ def get_tray_action(break_obj): if players: return TrayAction.build("Pause media", tray_icon_path, - Gtk.STOCK_MEDIA_PAUSE, + "media-playback-pause", lambda: __pause_players(players)) diff --git a/safeeyes/plugins/screensaver/plugin.py b/safeeyes/plugins/screensaver/plugin.py index cc49c04..2351f8e 100644 --- a/safeeyes/plugins/screensaver/plugin.py +++ b/safeeyes/plugins/screensaver/plugin.py @@ -131,5 +131,5 @@ def on_stop_break(): def get_tray_action(break_obj): return TrayAction.build("Lock screen", tray_icon_path, - Gtk.STOCK_DIALOG_AUTHENTICATION, + "dialog-password", __lock_screen) diff --git a/safeeyes/ui/break_screen.py b/safeeyes/ui/break_screen.py index 69959b0..1db98d5 100644 --- a/safeeyes/ui/break_screen.py +++ b/safeeyes/ui/break_screen.py @@ -59,7 +59,9 @@ class BreakScreen: # Initialize the theme css_provider = Gtk.CssProvider() css_provider.load_from_path(style_sheet_path) - Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) + + display = Gdk.Display.get_default() + Gtk.StyleContext.add_provider_for_display(display, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) def initialize(self, config): """ @@ -152,25 +154,25 @@ class BreakScreen: utility.start_thread(self.__lock_keyboard) 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) + monitors = display.get_monitors() + logging.info("Show break screens in %d display(s)", len(monitors)) skip_button_disabled = self.context.get('skip_button_disabled', False) postpone_button_disabled = self.context.get('postpone_button_disabled', False) - for monitor_num in range(no_of_monitors): - monitor = display.get_monitor(monitor_num) + i = 0 + + for monitor in monitors: monitor_gemoetry = monitor.get_geometry() x = monitor_gemoetry.x y = monitor_gemoetry.y builder = Gtk.Builder() builder.add_from_file(BREAK_SCREEN_GLADE) - builder.connect_signals(self) window = builder.get_object("window_main") - window.set_title("SafeEyes-" + str(monitor_num)) + window.connect("close-request", self.on_window_delete) + window.set_title("SafeEyes-" + str(i)) lbl_message = builder.get_object("lbl_message") lbl_count = builder.get_object("lbl_count") lbl_widget = builder.get_object("lbl_widget") @@ -179,15 +181,14 @@ class BreakScreen: toolbar = builder.get_object("toolbar") for tray_action in tray_actions: - toolbar_button = None - if tray_action.system_icon: - toolbar_button = Gtk.ToolButton.new_from_stock(tray_action.get_icon()) - else: - toolbar_button = Gtk.ToolButton.new(tray_action.get_icon(), tray_action.name) + # TODO: apparently, this would be better served with an icon theme + Gtk.button.new_from_icon_name + icon = tray_action.get_icon() + toolbar_button = Gtk.Button() + toolbar_button.set_child(icon) tray_action.add_toolbar_button(toolbar_button) toolbar_button.connect("clicked", lambda button, action: self.__tray_action(button, action), tray_action) toolbar_button.set_tooltip_text(_(tray_action.name)) - toolbar.add(toolbar_button) + toolbar.append(toolbar_button) toolbar_button.show() # Add the buttons @@ -197,7 +198,7 @@ class BreakScreen: btn_postpone.get_style_context().add_class('btn_postpone') btn_postpone.connect('clicked', self.on_postpone_clicked) btn_postpone.set_visible(True) - box_buttons.pack_start(btn_postpone, True, True, 0) + box_buttons.append(btn_postpone) if not self.strict_break and not skip_button_disabled: # Add the skip button @@ -205,7 +206,7 @@ class BreakScreen: btn_skip.get_style_context().add_class('btn_skip') btn_skip.connect('clicked', self.on_skip_clicked) btn_skip.set_visible(True) - box_buttons.pack_start(btn_skip, True, True, 0) + box_buttons.append(btn_skip) # Set values if image_path: @@ -216,23 +217,14 @@ class BreakScreen: self.windows.append(window) self.count_labels.append(lbl_count) - # Set visual to apply css theme. It should be called before show method. - window.set_visual(window.get_screen().get_rgba_visual()) if self.context['desktop'] == 'kde': # Fix flickering screen in KDE by setting opacity to 1 window.set_opacity(0.9) - # In Unity, move the window before present - window.move(x, y) - window.resize(monitor_gemoetry.width, monitor_gemoetry.height) - window.stick() - window.set_keep_above(True) - window.fullscreen_on_monitor(screen, monitor_num) + window.fullscreen_on_monitor(monitor) window.present() - # In other desktop environments, move the window after present - window.move(x, y) - window.resize(monitor_gemoetry.width, monitor_gemoetry.height) - logging.info("Moved break screen to Display[%d, %d]", x, y) + + i = i + 1 def __update_count_down(self, count): """ From be614316a969b555ac5854a5fd0e400d9b026172 Mon Sep 17 00:00:00 2001 From: deltragon Date: Tue, 2 Jan 2024 13:36:44 +0100 Subject: [PATCH 03/11] gtk4: about dialog --- safeeyes/glade/about_dialog.glade | 140 +++++++++--------------------- safeeyes/ui/about_dialog.py | 7 +- safeeyes/utility.py | 2 +- 3 files changed, 46 insertions(+), 103 deletions(-) diff --git a/safeeyes/glade/about_dialog.glade b/safeeyes/glade/about_dialog.glade index 055b18a..dd37809 100644 --- a/safeeyes/glade/about_dialog.glade +++ b/safeeyes/glade/about_dialog.glade @@ -20,7 +20,7 @@ ~ along with this program. If not, see . --> - + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,176 +36,121 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. - False Safe Eyes - False - center-always + 0 safeeyes - dialog - center - - True - False - 5 - 5 + 1 + 5 + 5 5 5 - True - True + 1 + 1 vertical top - True - False + 1 start - True + 1 vertical - True - False + 1 center center 10 10 Safe Eyes 2.2.2 center + 1 + 1 - - True - True - 0 - - True - False + 1 4 - Safe Eyes protects your eyes from eye strain (asthenopia) by reminding you to take breaks while you're working long hours at the computer + Safe Eyes protects your eyes from eye strain (asthenopia) by reminding you to take breaks while you're working long hours at the computer fill - True + 1 60 60 - - False - True - 1 - - True - False + 1 start center 10 License: - - False - True - 2 - - True - True - True - True - False + 1 + 1 + 1 + 1 + 0 word text_buffer_license - False + 0 - - True - True - 3 - https://slgobinath.github.io/SafeEyes - True - True - False - True + 1 + 1 + 0 + 1 center - none + 0 https://slgobinath.github.io/SafeEyes - - False - True - 4 - - - False - True - 0 - - True - False + 1 5 5 - - False - True - 1 - - - True - False + + 1 start - 5 + 5 List of Contributors - True - True - False - True + 1 + 1 + 0 + 1 center - none https://github.com/slgobinath/SafeEyes/graphs/contributors?type=a - - False - True - 0 - Close - True - True - True - + 1 + 1 + 1 + 1 + 1 - - True - True - 1 - @@ -225,11 +170,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. - - False - True - 2 - diff --git a/safeeyes/ui/about_dialog.py b/safeeyes/ui/about_dialog.py index 39362b0..8107f56 100644 --- a/safeeyes/ui/about_dialog.py +++ b/safeeyes/ui/about_dialog.py @@ -35,8 +35,11 @@ class AboutDialog: def __init__(self, version): builder = utility.create_gtk_builder(ABOUT_DIALOG_GLADE) - builder.connect_signals(self) self.window = builder.get_object('window_about') + + self.window.connect("close-request", self.on_window_delete) + builder.get_object('btn_close').connect('clicked', self.on_close_clicked) + builder.get_object('lbl_decription').set_label(_("Safe Eyes protects your eyes from eye strain (asthenopia) by reminding you to take breaks while you're working long hours at the computer")) builder.get_object('lbl_license').set_label(_('License') + ':') @@ -47,7 +50,7 @@ class AboutDialog: """ Show the About dialog. """ - self.window.show_all() + self.window.present() def on_window_delete(self, *args): """ diff --git a/safeeyes/utility.py b/safeeyes/utility.py index 6eeb177..97292f3 100644 --- a/safeeyes/utility.py +++ b/safeeyes/utility.py @@ -654,7 +654,7 @@ def create_gtk_builder(glade_file): builder.add_from_file(glade_file) # Tranlslate all sub components for obj in builder.get_objects(): - if (not isinstance(obj, Gtk.SeparatorMenuItem)) and hasattr(obj, "get_label"): + if hasattr(obj, "get_label"): label = obj.get_label() if label is not None: obj.set_label(_(label)) From e40b081eb19d91bc32735d7519ec4ceb0ce87380 Mon Sep 17 00:00:00 2001 From: deltragon Date: Tue, 2 Jan 2024 13:36:45 +0100 Subject: [PATCH 04/11] gtk4: settings dialog --- safeeyes/glade/item_break.glade | 61 +- safeeyes/glade/item_plugin.glade | 90 +-- safeeyes/glade/settings_dialog.glade | 1029 ++++++++------------------ safeeyes/ui/settings_dialog.py | 35 +- 4 files changed, 361 insertions(+), 854 deletions(-) diff --git a/safeeyes/glade/item_break.glade b/safeeyes/glade/item_break.glade index fd7e747..17d01a0 100644 --- a/safeeyes/glade/item_break.glade +++ b/safeeyes/glade/item_break.glade @@ -20,76 +20,49 @@ ~ along with this program. If not, see . --> - - - True - False - gtk-properties - - - True - False - gtk-delete - + - True - False - 5 - 5 - 5 - 5 + 1 + 5 + 5 + 5 + 5 3 + 0 - True - False + 1 center label 0 + 1 + 1 - - True - True - 0 - - True - True - True + 1 + 1 + 1 center center - img_properties - True + gtk-properties - - False - True - 1 - - True - True - False + 1 + 1 center center - img_delete - True + edit-delete - - False - True - 2 - diff --git a/safeeyes/glade/item_plugin.glade b/safeeyes/glade/item_plugin.glade index af01c8b..6edf781 100644 --- a/safeeyes/glade/item_plugin.glade +++ b/safeeyes/glade/item_plugin.glade @@ -20,81 +20,58 @@ ~ along with this program. If not, see . --> - - - True - False - gtk-properties - - - True - False - _Cancel - + - True - False - 5 - 5 - 5 - 5 + 1 + 5 + 5 + 5 + 5 + 0 - True - False + 1 center center - gtk-about + gtk-about - - False - True - 0 - - True - False - 5 + 1 + 5 vertical + 1 + 1 - True - False + 1 start end Plugin Name 0.05000000074505806 1 + 1 + 1 - - True - True - 0 - - True - False + 1 start start Plugin Description 0.05000000074505806 0 + 1 + 1 - - True - True - 1 - @@ -111,21 +88,15 @@ - - True - True - 1 - - True - False + 1 5 - True - True + 1 + 1 end center @@ -135,9 +106,8 @@ False center center - img_disable + gtk-cancel Disable permanently - True @@ -145,24 +115,18 @@ - True - True - True + 1 + 1 + 1 center center - img_properties - True + gtk-properties - - False - True - 2 - diff --git a/safeeyes/glade/settings_dialog.glade b/safeeyes/glade/settings_dialog.glade index c4a3fa0..43ab9a5 100644 --- a/safeeyes/glade/settings_dialog.glade +++ b/safeeyes/glade/settings_dialog.glade @@ -20,7 +20,7 @@ ~ along with this program. If not, see . --> - + 15 1 @@ -61,1103 +61,666 @@ 1 5 - - True - False - gtk-add - - False 128 - True - False + 1 vertical 5 - True + 1 - + Reset - True - True - True - + 1 + 1 + 1 + 1 + 1 - - True - True - 0 - - False Safe Eyes - center 450 650 io.github.slgobinath.SafeEyes - center - - True - False - True + 1 + 1 - - True - True - never - in - - - True - False - none + + Settings + Settings + + + 1 + 1 + never + 1 - - True - False - 5 - 5 - vertical - 15 + + 1 - - True - False - 0 - in + + 1 + 5 + 5 + vertical + 15 - - True - False - 12 + + 1 - True - False - 10 + 1 + 12 + 10 10 10 vertical 15 - True + 1 - True - False + 1 5 + 1 - True - False + start + 1 Interval between two breaks (in minutes) - - False - True - 0 - - True - True + 1 + 1 end center 1 - number adjust_short_break_interval 1 - True + 1 if-valid 1 - - - False - False - end - 1 - - - False - True - 0 - - True - False + 1 5 + 1 - True - False + start + 1 Break duration (in seconds) - - False - True - 0 - - True - True + 1 + 1 end center 1 - number adjust_short_break_duration 1 - True + 1 if-valid 1 - - False - False - end - 1 - - - False - True - 1 - + + + 1 + Short Breaks + + - - - True - False - Short Breaks - - - - - False - True - 0 - - - - - True - False - 0 - in - - True - False - 12 + + 1 - True - False - 10 + 1 + 12 + 10 10 10 vertical 15 - True + 1 - True - False - True - True - - - - - False - 6 - start - - - - - - False - False - 0 - - - + 0 + 1 + 1 + 1 + - False 16 - True - False - gtk-info + 1 + dialog-information - - False - True - 0 - - True - False + 1 Long break interval must be a multiple of short break interval 0 - - False - True - 1 - - - False - False - 0 - - - - - - True - True - 0 - - True - False + 1 5 + 1 - True - False + start + 1 Interval between two breaks (in minutes) - - False - True - 0 - - True - True + 1 + 1 end center 1 - number adjust_long_break_interval 1 - True - True - True + 1 + 1 + 1 if-valid 1 - - - False - False - end - 1 - - - False - True - 1 - - True - False + 1 5 + 1 - True - False + 1 + start Break duration (in seconds) - - False - True - 0 - - True - True + 1 + 1 end center 1 - number adjust_long_break_duration 1 - True + 1 if-valid 1 - - False - False - end - 1 - - - False - True - 2 - + + + 1 + Long Breaks + + - - - True - False - Long Breaks - - - - - False - True - 1 - - - - - True - False - 0 - in - - True - False - 12 + + 1 - True - False - 10 + 1 + 12 + 10 10 10 vertical 15 - True + 1 - True - False + 1 5 + 1 - True - False + 1 + start Time to prepare for a break (in seconds) - - False - True - 0 - - True - True + 1 + 1 end center 1 - number adjust_time_to_prepare 1 - True + 1 if-valid 1 - - False - False - end - 1 - - - False - True - 0 - - True - False + 1 5 + 1 - True - False + 1 + start Show breaks in random order - - False - True - 0 - - True - True + 1 + 1 end center - - False - False - end - 1 - - - False - True - 1 - - True - False + 1 5 + 1 - True - False + 1 + start Strict break (No way to skip breaks) - - False - True - 0 - - True - True + 1 + 1 end center - - False - False - end - 1 - - - False - True - 2 - - True - False + 1 5 + 1 - True - False + 1 + start Allow postponing breaks - - False - True - 0 - - True - True + 1 + 1 end center - - False - False - end - 1 - - - False - True - 3 - - True - False + 1 5 + 1 - True - False + 1 + start Postponement duration (in minutes) - - False - True - 0 - - True - True + 1 + 1 end center 1 - number adjust_postpone_duration 1 - True + 1 if-valid 1 - - False - False - end - 1 - - - False - True - 4 - - True - False + 1 5 + 1 - True - False + 1 + start Keyboard shortcuts disabled period (in seconds) - - False - True - 0 - - True - True + 1 + 1 end center 1 - number adjust_disable_keyboard_shortcut_duration 1 - True + 1 if-valid 1 - - False - False - end - 1 - - - False - True - 5 - - True - False + 1 5 + 1 - True - False + 1 + start Persist the internal state - - False - True - 0 - - True - True + 1 + 1 end center - - False - False - end - 1 - - - False - True - 6 - - True - False - True + 0 warning - True - - - - - False - - - False - False - 0 - - - - - False - - - False - False - 0 - - - - - + 1 + 1 + 1 - - True - True - 7 - - True - False + 1 5 + 1 - True - False + 1 + start Use RPC server to receive runtime commands - - False - True - 0 - - True - True + 1 + 1 end center - - False - False - end - 1 - - - False - True - 8 - + + + + + + 1 + Options + + + + + + + + + + + + + + + page1 + Breaks + + + 1 + 5 + 5 + vertical + + + 1 + 1 + 1 + 1 + never + 1 + + + 1 + + + 1 + 10 + 10 + vertical + + + 1 + vertical + 1 + 1 + + + 1 + 1 + 1 + + + 1 + vertical + 5 + + + + + 1 + Short Breaks + + + + + + + 1 + 10 + + + + + 1 + 1 + + + 1 + vertical + 5 + + + + + 1 + Long Breaks + + + - - - True - False - Options - - - - False - True - 2 - + + + 1 + 10 + 10 + end + end + + + 1 + 1 + 1 + end + gtk-add + + + + + + + 1 + 10 + + - + - - Settings - Settings - - - True - False - 5 - 5 - vertical - - - True - True + + page2 + Plugins + + + 1 + 1 never + 1 - - True - False - none + + 1 - - True - False + + 1 10 10 vertical - - - True - False - vertical - - - True - True - True - - - True - False - vertical - 5 - - - - - - - - - - - - - - True - False - Short Breaks - - - - - False - True - 0 - - - - - True - False - 10 - - - False - True - 1 - - - - - True - True - - - True - False - vertical - 5 - - - - - - - - - - - - - - True - False - Long Breaks - - - - - False - True - 2 - - - - - True - True - 0 - - + 5 - - True - True - 0 - - - - - True - False - 10 - 10 - end - - - True - True - True - end - img_add - - - - True - True - 1 - - - - - False - True - end - 1 - - - - - True - False - 10 - - - False - True - 2 - - + - - page1 - Breaks - 1 - - - - - True - True - never - in - - - True - False - - - True - False - 10 - 10 - vertical - 5 - - - - - - - - - - - - - - - - - - - - - - page2 - Plugins - 2 - - True - False - Safe Eyes - 91 - True + 1 + 1 menu:close - True - False + 1 vertical - True - False + 1 5 Safe Eyes - - False - True - 0 - - True - False + 1 stack - - False - True - 1 - - True - True - True + 1 + 1 + 1 center center popover - True - False + 1 io.github.slgobinath.SafeEyes - 1 + 1 diff --git a/safeeyes/ui/settings_dialog.py b/safeeyes/ui/settings_dialog.py index cae0c8b..3c804d9 100644 --- a/safeeyes/ui/settings_dialog.py +++ b/safeeyes/ui/settings_dialog.py @@ -55,7 +55,6 @@ class SettingsDialog: self.warn_bar_rpc_server_shown = False builder = utility.create_gtk_builder(SETTINGS_DIALOG_GLADE) - builder.connect_signals(self) self.window = builder.get_object('window_settings') self.box_short_breaks = builder.get_object('box_short_breaks') @@ -80,18 +79,26 @@ class SettingsDialog: self.info_bar_long_break.hide() self.warn_bar_rpc_server.hide() + self.window.connect("close-request", self.on_window_delete) + builder.get_object('reset_menu').connect('clicked', self.on_reset_menu_clicked) + self.spin_short_break_interval.connect('value-changed', self.on_spin_short_break_interval_change) + self.info_bar_long_break.connect('close', self.on_info_bar_long_break_close) + self.info_bar_long_break.connect('response', self.on_info_bar_long_break_close) + self.spin_long_break_interval.connect('value-changed', self.on_spin_long_break_interval_change) + self.warn_bar_rpc_server.connect('close', self.on_warn_bar_rpc_server_close) + self.warn_bar_rpc_server.connect('response', self.on_warn_bar_rpc_server_close) + builder.get_object('btn_add_break').connect('clicked', self.add_break) + # Set the current values of input fields self.__initialize(config) - # Update relative states - # GtkSwitch state-set signal is available only from 3.14 - if Gtk.get_minor_version() >= 14: - # Add event listener to postpone switch - self.switch_postpone.connect('state-set', self.on_switch_postpone_activate) - self.on_switch_postpone_activate(self.switch_postpone, self.switch_postpone.get_active()) - # Add event listener to RPC server switch - self.switch_rpc_server.connect('state-set', self.on_switch_rpc_server_activate) - self.on_switch_rpc_server_activate(self.switch_rpc_server, self.switch_rpc_server.get_active()) + # Add event listener to postpone switch + self.switch_postpone.connect('state-set', self.on_switch_postpone_activate) + self.on_switch_postpone_activate(self.switch_postpone, self.switch_postpone.get_active()) + # Add event listener to RPC server switch + self.switch_rpc_server.connect('state-set', self.on_switch_rpc_server_activate) + self.on_switch_rpc_server_activate(self.switch_rpc_server, self.switch_rpc_server.get_active()) + self.initializing = False def __initialize(self, config): @@ -103,8 +110,8 @@ class SettingsDialog: self.__create_break_item(long_break, False) for plugin_config in utility.load_plugins_config(config): - self.box_plugins.pack_start(self.__create_plugin_item(plugin_config), False, False, 0) - + self.box_plugins.append(self.__create_plugin_item(plugin_config)) + self.spin_short_break_duration.set_value(config.get('short_break_duration')) self.spin_long_break_duration.set_value(config.get('long_break_duration')) self.spin_short_break_interval.set_value(config.get('short_break_interval')) @@ -152,7 +159,7 @@ class SettingsDialog: ) ) box.set_visible(True) - parent_box.pack_start(box, False, False, 0) + parent_box.append(box) return box def on_reset_menu_clicked(self, button): @@ -279,7 +286,7 @@ class SettingsDialog: """ Show the SettingsDialog. """ - self.window.show() + self.window.present() def on_switch_postpone_activate(self, switch, state): """ From 8a509a94d678aecf91f2a135ed89ceddd76f149c Mon Sep 17 00:00:00 2001 From: deltragon Date: Tue, 2 Jan 2024 13:36:45 +0100 Subject: [PATCH 05/11] gtk4: break settings --- safeeyes/glade/settings_break.glade | 489 ++++++++-------------------- safeeyes/ui/settings_dialog.py | 66 ++-- 2 files changed, 170 insertions(+), 385 deletions(-) diff --git a/safeeyes/glade/settings_break.glade b/safeeyes/glade/settings_break.glade index 37b44e7..df2ecd7 100644 --- a/safeeyes/glade/settings_break.glade +++ b/safeeyes/glade/settings_break.glade @@ -20,23 +20,18 @@ ~ along with this program. If not, see . --> - + 1 3600 - 1 - 10 + 1 + 10 1 120 - 1 - 10 - - - True - False - gtk-missing-image + 1 + 10 @@ -53,152 +48,93 @@ - False Break Settings - False - True - center-on-parent - 500 - 50 - True - safeeyes - dialog - True - center - - - - + 0 + 1 + 500 + 50 + 1 + safeeyes - True - False - 10 - 10 - 10 - 10 + 1 + 10 + 10 + 10 + 10 vertical 5 - True - False - 0 + 1 - - True - False - 12 + + 1 + 12 + 10 + 5 + 10 + vertical + 3 - - True - False - 10 - 5 - 10 - vertical - 3 + + 1 + 1 + center + + + + + 1 + 10 + 1 - - True - True + + 1 + start center + Type - - False - True - 0 - - - True - False - 10 + + 1 + lst_break_types + 0 + 0 + end - - True - False - start - center - Type - - - False - True - 0 - - - - - True - False - lst_break_types - 0 - 0 - - - - 0 - - - - - False - True - end - 1 - + + + 0 + - - False - True - 1 - + + + + + + 1 + 10 + 1 + + + 1 + start + center + Image + - - True - False - 10 - - - True - False - start - center - Image - - - False - True - 0 - - - - - Select - True - True - True - img_break - True - - - - False - True - end - 1 - - + + end + Select + 1 + 1 + 1 + gtk-missing-image - - False - True - 2 - @@ -206,377 +142,208 @@ - True - False + 1 Break - - False - False - 0 - - True - False - 0 + 1 - - True - False - 12 - - True - False - 10 - 5 - 10 + 1 + 12 + 10 + 5 + 10 vertical 3 - True - False + 1 10 + 1 - True - False + 1 start center Override - - False - True - 0 - - True - True + 1 + 1 end center - - False - True - end - 1 - - - False - True - 0 - - True - False + 1 100 + 1 - True - False + 1 start center Time (in minutes) - - False - True - 0 - - True - True + 1 + 1 end center 0 adjustment_interval - True + 1 - - False - True - end - 1 - - - False - True - 1 - - - - True - False + 1 Time to wait - - False - False - 1 - - True - False - 0 + 1 - - True - False - 12 - - True - False - 10 - 5 - 10 + 1 + 12 + 10 + 5 + 10 vertical 3 - True - False + 1 10 + 1 - True - False + 1 start center Override - - False - True - 0 - - True - True + 1 + 1 end center - - False - True - end - 1 - - - False - True - 0 - - True - False + 1 100 + 1 - True - False + 1 start center Time (in seconds) - - False - True - 0 - - True - True + 1 + 1 end center adjustment_duration - True + 1 - - False - True - end - 1 - - - False - True - 1 - - - - True - False + 1 Duration - - False - False - 2 - - True - False - 0 + 1 - - True - False - 12 - - True - False - 5 - 10 + 1 + 12 + 5 + 10 vertical 3 - True - False - 10 - 5 - 10 + 1 + 10 + 5 + 10 10 + 1 - True - False + 1 start center Override - - False - True - 0 - - True - True + 1 + 1 end center - - False - True - end - 1 - - - False - True - 0 - - True - False - 10 - 10 - True - True - - - - - - - - - - - - - - - - - - - - - - - - - - - + 1 + 10 + 10 + 1 + 1 - - False - True - 1 - - - - True - False + 1 Plugins - - False - False - 3 - diff --git a/safeeyes/ui/settings_dialog.py b/safeeyes/ui/settings_dialog.py index 3c804d9..b972c22 100644 --- a/safeeyes/ui/settings_dialog.py +++ b/safeeyes/ui/settings_dialog.py @@ -24,8 +24,8 @@ from safeeyes import utility from safeeyes.model import Config, PluginDependency gi.require_version('Gtk', '4.0') -from gi.repository import Gtk -from gi.repository import GdkPixbuf +from gi.repository import Gtk, Gio +from gi.repository import GdkPixbuf, Gdk SETTINGS_DIALOG_GLADE = os.path.join(utility.BIN_DIRECTORY, "glade/settings_dialog.glade") @@ -463,7 +463,6 @@ class BreakSettingsDialog: self.on_remove = on_remove builder = utility.create_gtk_builder(SETTINGS_DIALOG_BREAK_GLADE) - builder.connect_signals(self) self.window = builder.get_object('dialog_settings_break') self.txt_break = builder.get_object('txt_break') self.switch_override_interval = builder.get_object('switch_override_interval') @@ -471,7 +470,7 @@ class BreakSettingsDialog: self.switch_override_plugins = builder.get_object('switch_override_plugins') self.spin_interval = builder.get_object('spin_interval') self.spin_duration = builder.get_object('spin_duration') - self.img_break = builder.get_object('img_break') + self.btn_image = builder.get_object('btn_image') self.cmb_type = builder.get_object('cmb_type') grid_plugins = builder.get_object('grid_plugins') @@ -509,7 +508,7 @@ class BreakSettingsDialog: row = 0 col = 0 for plugin_id in plugin_map.keys(): - chk_button = Gtk.CheckButton(_(plugin_map[plugin_id])) + chk_button = Gtk.CheckButton.new_with_label(_(plugin_map[plugin_id])) self.plugin_check_buttons[plugin_id] = chk_button grid_plugins.attach(chk_button, row, col, 1, 1) if plugins_overriden: @@ -520,14 +519,21 @@ class BreakSettingsDialog: if row > 2: col += 1 row = 0 - # GtkSwitch state-set signal is available only from 3.14 - if Gtk.get_minor_version() >= 14: - self.switch_override_interval.connect('state-set', self.on_switch_override_interval_activate) - self.switch_override_duration.connect('state-set', self.on_switch_override_duration_activate) - self.switch_override_plugins.connect('state-set', self.on_switch_override_plugins_activate) - self.on_switch_override_interval_activate(self.switch_override_interval, self.switch_override_interval.get_active()) - self.on_switch_override_duration_activate(self.switch_override_duration, self.switch_override_duration.get_active()) - self.on_switch_override_plugins_activate(self.switch_override_plugins, self.switch_override_plugins.get_active()) + + if 'image' in self.break_config: + pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(self.break_config['image'], 16, 16, True) + image = Gtk.Image.new_from_pixbuf(pixbuf) + self.btn_image.set_child(image) + + self.window.connect("close-request", self.on_window_delete) + self.btn_image.connect('clicked', self.select_image) + + self.switch_override_interval.connect('state-set', self.on_switch_override_interval_activate) + self.switch_override_duration.connect('state-set', self.on_switch_override_duration_activate) + self.switch_override_plugins.connect('state-set', self.on_switch_override_plugins_activate) + self.on_switch_override_interval_activate(self.switch_override_interval, self.switch_override_interval.get_active()) + self.on_switch_override_duration_activate(self.switch_override_duration, self.switch_override_duration.get_active()) + self.on_switch_override_plugins_activate(self.switch_override_plugins, self.switch_override_plugins.get_active()) def on_switch_override_interval_activate(self, switch_button, state): """ @@ -552,24 +558,36 @@ class BreakSettingsDialog: """ Show a file chooser dialog and let the user to select an image. """ - dialog = Gtk.FileChooserDialog(_('Please select an image'), self.window, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) + dialog = Gtk.FileDialog() + dialog.set_title(_('Please select an image')) png_filter = Gtk.FileFilter() png_filter.set_name("PNG files") png_filter.add_mime_type("image/png") png_filter.add_pattern("*.png") - dialog.add_filter(png_filter) + filters = Gio.ListStore.new(Gtk.FileFilter) + filters.append(png_filter) + dialog.set_filters(filters) - response = dialog.run() - if response == Gtk.ResponseType.OK: - self.break_config['image'] = dialog.get_filename() + dialog.open(self.window, None, self.select_image_callback) + + def select_image_callback(self, dialog, result): + response = None + + try: + response = dialog.open_finish(result) + except Exception: + # user pressing "Cancel" throws a generic exception here + pass + + if response is not None: + self.break_config['image'] = response.get_path() pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(self.break_config['image'], 16, 16, True) - self.img_break.set_from_pixbuf(pixbuf) - elif response == Gtk.ResponseType.CANCEL: + image = Gtk.Image.new_from_pixbuf(pixbuf) + self.btn_image.set_child(image) + else: self.break_config.pop('image', None) - self.img_break.set_from_stock('gtk-missing-image', Gtk.IconSize.BUTTON) - - dialog.destroy() + self.btn_image.set_icon_name('gtk-missing-image') def on_window_delete(self, *args): """ @@ -615,7 +633,7 @@ class BreakSettingsDialog: """ Show the Properties dialog. """ - self.window.show_all() + self.window.present() class NewBreakDialog: From 9b41e57abd353b88f9e8ab6d330264141e232ee4 Mon Sep 17 00:00:00 2001 From: deltragon Date: Tue, 2 Jan 2024 13:36:46 +0100 Subject: [PATCH 06/11] gtk4: new break --- safeeyes/glade/new_break.glade | 188 +++++++++++---------------------- safeeyes/ui/settings_dialog.py | 10 +- 2 files changed, 67 insertions(+), 131 deletions(-) diff --git a/safeeyes/glade/new_break.glade b/safeeyes/glade/new_break.glade index 21e3f52..a379c6e 100644 --- a/safeeyes/glade/new_break.glade +++ b/safeeyes/glade/new_break.glade @@ -20,11 +20,11 @@ ~ along with this program. If not, see . --> - + 100 - 1 - 10 + 1 + 10 @@ -41,110 +41,69 @@ - False New Break - False - True - center-on-parent - 500 - 50 - True - safeeyes - dialog - True - center - + 0 + 1 + 500 + 50 + 1 + safeeyes - True - False - 10 - 10 - 10 - 10 + 1 + 10 + 10 + 10 + 10 vertical 5 - True - False - 0 + 1 - - True - False - 12 + + 1 + 12 + 10 + 5 + 10 + vertical + 3 - - True - False - 10 - 5 - 10 - vertical - 3 + + 1 + 1 + center + 64 + + + + + 1 + 10 + 1 - - True - True + + 1 + start center - 64 + Type - - False - True - 0 - - - True - False - 10 + + end + 1 + lst_break_types + 0 + 0 - - True - False - start - center - Type - - - False - True - 0 - - - - - True - False - lst_break_types - 0 - 0 - - - - 0 - - - - - False - True - end - 1 - + + + 0 + - - False - True - 1 - - - - @@ -152,61 +111,36 @@ - True - False + 1 Break - - False - False - 0 - - - True - False + + 1 10 - True - top - end + 1 + top + end Discard - True - True - True - + 1 + 1 + 1 - - True - True - 0 - Save - True - True - True - True - + 1 + 1 + 1 - - True - True - 1 - - - False - False - 3 - diff --git a/safeeyes/ui/settings_dialog.py b/safeeyes/ui/settings_dialog.py index b972c22..01e9399 100644 --- a/safeeyes/ui/settings_dialog.py +++ b/safeeyes/ui/settings_dialog.py @@ -381,7 +381,6 @@ class PluginSettingsDialog: self.property_controls = [] builder = utility.create_gtk_builder(SETTINGS_DIALOG_PLUGIN_GLADE) - builder.connect_signals(self) self.window = builder.get_object('dialog_settings_plugin') box_settings = builder.get_object('box_settings') self.window.set_title(_('Plugin Settings')) @@ -445,7 +444,7 @@ class PluginSettingsDialog: """ Show the Properties dialog. """ - self.window.show_all() + self.window.present() class BreakSettingsDialog: @@ -646,7 +645,6 @@ class NewBreakDialog: self.on_add = on_add builder = utility.create_gtk_builder(SETTINGS_DIALOG_NEW_BREAK_GLADE) - builder.connect_signals(self) self.window = builder.get_object('dialog_new_break') self.txt_break = builder.get_object('txt_break') self.cmb_type = builder.get_object('cmb_type') @@ -655,6 +653,10 @@ class NewBreakDialog: list_types[0][0] = _(list_types[0][0]) list_types[1][0] = _(list_types[1][0]) + self.window.connect("close-request", self.on_window_delete) + builder.get_object('btn_discard').connect('clicked', self.discard) + builder.get_object('btn_save').connect('clicked', self.save) + # Set the values self.window.set_title(_('New Break')) @@ -688,4 +690,4 @@ class NewBreakDialog: """ Show the Properties dialog. """ - self.window.show_all() + self.window.present() From 3e59d9535a2f0a4db4c02b4b54baded98b840fef Mon Sep 17 00:00:00 2001 From: deltragon Date: Tue, 2 Jan 2024 13:36:47 +0100 Subject: [PATCH 07/11] gtk4: plugin settings --- safeeyes/glade/item_bool.glade | 33 ++++++++---------------- safeeyes/glade/item_int.glade | 36 ++++++++++---------------- safeeyes/glade/item_text.glade | 32 ++++++++--------------- safeeyes/glade/settings_plugin.glade | 38 ++++++++-------------------- safeeyes/ui/settings_dialog.py | 8 +++--- 5 files changed, 51 insertions(+), 96 deletions(-) diff --git a/safeeyes/glade/item_bool.glade b/safeeyes/glade/item_bool.glade index f755943..799ed20 100644 --- a/safeeyes/glade/item_bool.glade +++ b/safeeyes/glade/item_bool.glade @@ -20,42 +20,31 @@ ~ along with this program. If not, see . --> - + - True - False - 5 - 5 - 5 - 5 + 1 + 5 + 5 + 5 + 5 10 + 1 - True - False + 1 center + start label 0 - - True - True - 0 - - True - True + 1 + 1 end center - - False - False - end - 1 - diff --git a/safeeyes/glade/item_int.glade b/safeeyes/glade/item_int.glade index 3843dc2..31cd858 100644 --- a/safeeyes/glade/item_int.glade +++ b/safeeyes/glade/item_int.glade @@ -20,47 +20,37 @@ ~ along with this program. If not, see . --> - + 100 - 1 - 10 + 1 + 10 - True - False - 5 - 5 - 5 - 5 + 1 + 5 + 5 + 5 + 5 10 + 1 - True - False + start + 1 center label 0 - - True - True - 0 - - True - True + 1 + 1 end center adjustment_value - - False - True - 1 - diff --git a/safeeyes/glade/item_text.glade b/safeeyes/glade/item_text.glade index 07fa88b..aad81a1 100644 --- a/safeeyes/glade/item_text.glade +++ b/safeeyes/glade/item_text.glade @@ -20,41 +20,31 @@ ~ along with this program. If not, see . --> - + - True - False - 5 - 5 - 5 - 5 + 1 + 5 + 5 + 5 + 5 10 + 1 - True - False + 1 center + start label 0 - - True - True - 0 - - True - True + 1 + 1 end center - - False - True - 1 - diff --git a/safeeyes/glade/settings_plugin.glade b/safeeyes/glade/settings_plugin.glade index 848583c..d946089 100644 --- a/safeeyes/glade/settings_plugin.glade +++ b/safeeyes/glade/settings_plugin.glade @@ -20,39 +20,23 @@ ~ along with this program. If not, see . --> - + - False Plugin Settings - False - True - center-on-parent - 400 - 10 - True - safeeyes - dialog - True - center - + 0 + 1 + 400 + 10 + 1 + safeeyes - True - False - 10 - 10 + 1 + 10 + 10 vertical 15 - True - - - - - - - - - + 1 diff --git a/safeeyes/ui/settings_dialog.py b/safeeyes/ui/settings_dialog.py index 01e9399..3b95e44 100644 --- a/safeeyes/ui/settings_dialog.py +++ b/safeeyes/ui/settings_dialog.py @@ -386,11 +386,13 @@ class PluginSettingsDialog: self.window.set_title(_('Plugin Settings')) for setting in config.get('settings'): if setting['type'].upper() == 'INT': - box_settings.pack_start(self.__load_int_item(setting['label'], setting['id'], setting['safeeyes_config'], setting.get('min', 0), setting.get('max', 120)), False, False, 0) + box_settings.append(self.__load_int_item(setting['label'], setting['id'], setting['safeeyes_config'], setting.get('min', 0), setting.get('max', 120))) elif setting['type'].upper() == 'TEXT': - box_settings.pack_start(self.__load_text_item(setting['label'], setting['id'], setting['safeeyes_config']), False, False, 0) + box_settings.append(self.__load_text_item(setting['label'], setting['id'], setting['safeeyes_config'])) elif setting['type'].upper() == 'BOOL': - box_settings.pack_start(self.__load_bool_item(setting['label'], setting['id'], setting['safeeyes_config']), False, False, 0) + box_settings.append(self.__load_bool_item(setting['label'], setting['id'], setting['safeeyes_config'])) + + self.window.connect("close-request", self.on_window_delete) def __load_int_item(self, name, key, settings, min_value, max_value): """ From 1df85dfa4a172f6b3f79b502fec42292f0bcbec0 Mon Sep 17 00:00:00 2001 From: deltragon Date: Wed, 6 Mar 2024 21:06:41 +0100 Subject: [PATCH 08/11] fixup confirmation dialogs for gtk4 --- safeeyes/ui/settings_dialog.py | 57 +++++++++++++++++----------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/safeeyes/ui/settings_dialog.py b/safeeyes/ui/settings_dialog.py index 3b95e44..38ec263 100644 --- a/safeeyes/ui/settings_dialog.py +++ b/safeeyes/ui/settings_dialog.py @@ -164,56 +164,57 @@ class SettingsDialog: def on_reset_menu_clicked(self, button): self.popover.hide() - def __confirmation_dialog_response(widget, response_id): - if response_id == Gtk.ResponseType.OK: + def __confirmation_dialog_response(dialog, result): + response_id = dialog.choose_finish(result) + if response_id == 1: utility.reset_config() self.config = Config() # Remove breaks from the container - self.box_short_breaks.foreach(lambda element: self.box_short_breaks.remove(element)) - self.box_long_breaks.foreach(lambda element: self.box_long_breaks.remove(element)) - # Remove plugins from the container - self.box_plugins.foreach(lambda element: self.box_plugins.remove(element)) + self.__clear_children(self.box_short_breaks) + self.__clear_children(self.box_long_breaks) + self.__clear_children(self.box_plugins) # Initialize again self.__initialize(self.config) - widget.destroy() - messagedialog = Gtk.MessageDialog() + messagedialog = Gtk.AlertDialog() 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.set_buttons(['_Cancel', _("Reset")]) + messagedialog.set_message(_("Are you sure you want to reset all settings to default?")) + messagedialog.set_detail(_("You can't undo this action.")) - messagedialog.connect("response", __confirmation_dialog_response) - messagedialog.show() + messagedialog.set_cancel_button(0) + messagedialog.set_default_button(0) + + messagedialog.choose(self.window, None, __confirmation_dialog_response) + + def __clear_children(self, widget): + while widget.get_last_child() is not None: + widget.remove(widget.get_last_child()) def __delete_break(self, break_config, is_short, on_remove): """ Remove the break after a confirmation. """ - def __confirmation_dialog_response(widget, response_id): - if response_id == Gtk.ResponseType.OK: + def __confirmation_dialog_response(dialog, result): + response_id = dialog.choose_finish(result) + if response_id == 1: if is_short: self.config.get('short_breaks').remove(break_config) else: self.config.get('long_breaks').remove(break_config) on_remove() - widget.destroy() - messagedialog = Gtk.MessageDialog() + messagedialog = Gtk.AlertDialog() 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.set_buttons(['_Cancel', _("Delete")]) + messagedialog.set_message(_("Are you sure you want to delete this break?")) + messagedialog.set_detail(_("You can't undo this action.")) - messagedialog.connect("response", __confirmation_dialog_response) - messagedialog.show() + messagedialog.set_cancel_button(0) + messagedialog.set_default_button(0) + + messagedialog.choose(self.window, None, __confirmation_dialog_response) def __create_plugin_item(self, plugin_config): """ From 8228fc4282c779f41741212933ada80719d01413 Mon Sep 17 00:00:00 2001 From: deltragon Date: Sat, 28 Sep 2024 18:41:18 +0200 Subject: [PATCH 09/11] more glade fixes for gtk4 --- safeeyes/glade/about_dialog.glade | 7 +------ safeeyes/glade/required_plugin_dialog.glade | 7 +++++-- safeeyes/ui/required_plugin_dialog.py | 4 ++-- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/safeeyes/glade/about_dialog.glade b/safeeyes/glade/about_dialog.glade index dd37809..83523ee 100644 --- a/safeeyes/glade/about_dialog.glade +++ b/safeeyes/glade/about_dialog.glade @@ -160,14 +160,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.False True center - none + 0 https://github.com/slgobinath/SafeEyes?tab=readme-ov-file#how-you-can-help-improving-translation-of-safe-eyes - - False - True - 2 - diff --git a/safeeyes/glade/required_plugin_dialog.glade b/safeeyes/glade/required_plugin_dialog.glade index 2a28837..d9c0595 100644 --- a/safeeyes/glade/required_plugin_dialog.glade +++ b/safeeyes/glade/required_plugin_dialog.glade @@ -20,7 +20,7 @@ ~ along with this program. If not, see . --> - + Safe Eyes - Error 0 @@ -71,7 +71,10 @@ - 5 + 5 + 5 + 5 + 5 1 center 60 diff --git a/safeeyes/ui/required_plugin_dialog.py b/safeeyes/ui/required_plugin_dialog.py index debe53b..e1c5692 100644 --- a/safeeyes/ui/required_plugin_dialog.py +++ b/safeeyes/ui/required_plugin_dialog.py @@ -40,7 +40,7 @@ class RequiredPluginDialog: builder = utility.create_gtk_builder(REQUIRED_PLUGIN_DIALOG_GLADE) self.window = builder.get_object('window_required_plugin') - self.window.connect("delete-event", self.on_window_delete) + self.window.connect("close-request", self.on_window_delete) builder.get_object('btn_close').connect('clicked', self.on_close_clicked) builder.get_object('btn_disable_plugin').connect('clicked', self.on_disable_plugin_clicked) @@ -64,7 +64,7 @@ class RequiredPluginDialog: """ Show the dialog. """ - self.window.show_all() + self.window.present() def on_window_delete(self, *args): """ From d497da24ae44d5eace92c3654c918cb170b34acd Mon Sep 17 00:00:00 2001 From: deltragon Date: Wed, 24 Jan 2024 18:55:44 +0100 Subject: [PATCH 10/11] dont call x11 methods on wayland --- safeeyes/ui/break_screen.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/safeeyes/ui/break_screen.py b/safeeyes/ui/break_screen.py index 1db98d5..13dca36 100644 --- a/safeeyes/ui/break_screen.py +++ b/safeeyes/ui/break_screen.py @@ -44,7 +44,10 @@ class BreakScreen: def __init__(self, context, on_skipped, on_postponed, style_sheet_path): self.context = context self.count_labels = [] - self.display = Display() + + if not self.context['is_wayland']: + self.x11_display = Display() + self.enable_postpone = False self.enable_shortcut = False self.is_pretified = False @@ -133,7 +136,9 @@ class BreakScreen: Hide the break screen from active window and destroy all other windows """ logging.info("Close the break screen(s)") - self.__release_keyboard() + + if not self.context['is_wayland']: + self.__release_keyboard() # Destroy other windows if exists GLib.idle_add(lambda: self.__destroy_all_screens()) @@ -151,7 +156,8 @@ class BreakScreen: Show an empty break screen on all screens. """ # Lock the keyboard - utility.start_thread(self.__lock_keyboard) + if not self.context['is_wayland']: + utility.start_thread(self.__lock_keyboard_x11) display = Gdk.Display.get_default() monitors = display.get_monitors() @@ -233,7 +239,7 @@ class BreakScreen: for label in self.count_labels: label.set_text(count) - def __lock_keyboard(self): + def __lock_keyboard_x11(self): """ Lock the keyboard to prevent the user from using keyboard shortcuts """ @@ -241,15 +247,15 @@ class BreakScreen: self.lock_keyboard = True # Grab the keyboard - root = self.display.screen().root + root = self.x11_display.screen().root root.change_attributes(event_mask=X.KeyPressMask | X.KeyReleaseMask) root.grab_keyboard(True, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime) # Consume keyboard events while self.lock_keyboard: - if self.display.pending_events() > 0: + if self.x11_display.pending_events() > 0: # Avoid waiting for next event by checking pending events - event = self.display.next_event() + event = self.x11_display.next_event() if self.enable_shortcut and event.type == X.KeyPress: if event.detail == self.keycode_shortcut_skip and not self.strict_break: self.skip_break() @@ -261,14 +267,14 @@ class BreakScreen: # Reduce the CPU usage by sleeping for a second time.sleep(1) - def __release_keyboard(self): + def __release_keyboard_x11(self): """ Release the locked keyboard. """ logging.info("Unlock the keyboard") self.lock_keyboard = False - self.display.ungrab_keyboard(X.CurrentTime) - self.display.flush() + self.x11_display.ungrab_keyboard(X.CurrentTime) + self.x11_display.flush() def __destroy_all_screens(self): """ From 480a1d273efdc3ac58be321da82009b5d377b6a9 Mon Sep 17 00:00:00 2001 From: deltragon Date: Wed, 24 Jan 2024 18:56:16 +0100 Subject: [PATCH 11/11] lock keyboard on wayland --- safeeyes/ui/break_screen.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/safeeyes/ui/break_screen.py b/safeeyes/ui/break_screen.py index 13dca36..d5361ed 100644 --- a/safeeyes/ui/break_screen.py +++ b/safeeyes/ui/break_screen.py @@ -230,6 +230,10 @@ class BreakScreen: window.fullscreen_on_monitor(monitor) window.present() + if self.context['is_wayland']: + # this may or may not be granted by the window system + window.get_surface().inhibit_system_shortcuts(None) + i = i + 1 def __update_count_down(self, count):