From cbb0fe2fad90818c959fd46976e0ee382f2b2276 Mon Sep 17 00:00:00 2001 From: Franco Battista Date: Mon, 6 May 2024 22:25:49 -0300 Subject: [PATCH 1/4] Keyboard shortcuts added: -Open settings, -Open locations, -Refresh weather, using keyboard library --- src/mousam.py | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/mousam.py b/src/mousam.py index 26d51c2..7cd7cdf 100644 --- a/src/mousam.py +++ b/src/mousam.py @@ -2,10 +2,11 @@ import time import threading import gettext +import keyboard gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") -from gi.repository import Gtk, Adw, Gio +from gi.repository import Gtk, Adw, Gio, GLib from gettext import gettext as _, pgettext as C_ @@ -114,6 +115,11 @@ def __init__(self, *args, **kwargs): thread = threading.Thread(target=self._load_weather_data, name="load_data") thread.start() + #Set key listeners + keyboard_thread = threading.Thread(target=self.listen_to_keyboard_events) + keyboard_thread.start() + + # =========== Create Loader ============= def show_loader(self): # Loader container @@ -358,3 +364,32 @@ def _on_preferences_clicked(self, *args, **kwargs): def _on_locations_clicked(self, *args, **kwargs): adw_preferences_window = WeatherLocations(self.main_window) adw_preferences_window.show() + + + #Exec shortcut method + def on_hotkey_pressed(self,event): + match event: + #Create a new thread if shortcut need a new window + case "location": + GLib.idle_add(self._on_locations_clicked) + case "weather": + self._refresh_weather(None) + case "preferences": + GLib.idle_add(self._on_preferences_clicked) + case _: + return "" + + + #Def shortcuts key listeners + def listen_to_keyboard_events(self): + + #Listeners + keyboard.add_hotkey('ctrl+l', lambda: self.on_hotkey_pressed("location")) + keyboard.add_hotkey('ctrl+r', lambda: self.on_hotkey_pressed("weather")) + keyboard.add_hotkey('ctrl+comma', lambda: self.on_hotkey_pressed("preferences")) + + #Wait empty key. None key stop de listener + keyboard.wait("") + + #Free hooks + keyboard.unhook_all() From f52ad0b0e8920ec8346051a3d584eba62fa0683d Mon Sep 17 00:00:00 2001 From: Franco Battista Date: Tue, 7 May 2024 19:06:20 -0300 Subject: [PATCH 2/4] Refactor shortcuts using GTK --- src/mousam.py | 38 +++++++++++--------------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/src/mousam.py b/src/mousam.py index 7cd7cdf..d80a0ad 100644 --- a/src/mousam.py +++ b/src/mousam.py @@ -2,11 +2,10 @@ import time import threading import gettext -import keyboard gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") -from gi.repository import Gtk, Adw, Gio, GLib +from gi.repository import Gtk, Adw, Gio, GLib, Gdk from gettext import gettext as _, pgettext as C_ @@ -116,8 +115,9 @@ def __init__(self, *args, **kwargs): thread.start() #Set key listeners - keyboard_thread = threading.Thread(target=self.listen_to_keyboard_events) - keyboard_thread.start() + keycont = Gtk.EventControllerKey() + keycont.connect('key-pressed', self.on_key_press) + self.add_controller(keycont) # =========== Create Loader ============= @@ -366,30 +366,14 @@ def _on_locations_clicked(self, *args, **kwargs): adw_preferences_window.show() - #Exec shortcut method - def on_hotkey_pressed(self,event): - match event: - #Create a new thread if shortcut need a new window - case "location": - GLib.idle_add(self._on_locations_clicked) - case "weather": + #Def shortcuts key listeners + def on_key_press(self, key_controller, keyval, keycode, state,*args): + if state & Gdk.ModifierType.CONTROL_MASK: + if keyval == Gdk.KEY_r: self._refresh_weather(None) - case "preferences": + if keyval == Gdk.KEY_l: + GLib.idle_add(self._on_locations_clicked) + if keyval == Gdk.KEY_comma: GLib.idle_add(self._on_preferences_clicked) - case _: - return "" - #Def shortcuts key listeners - def listen_to_keyboard_events(self): - - #Listeners - keyboard.add_hotkey('ctrl+l', lambda: self.on_hotkey_pressed("location")) - keyboard.add_hotkey('ctrl+r', lambda: self.on_hotkey_pressed("weather")) - keyboard.add_hotkey('ctrl+comma', lambda: self.on_hotkey_pressed("preferences")) - - #Wait empty key. None key stop de listener - keyboard.wait("") - - #Free hooks - keyboard.unhook_all() From 13a92aa45fd88fb7d6566050be86b369a7184410 Mon Sep 17 00:00:00 2001 From: Amit Chaudhary Date: Wed, 8 May 2024 14:04:36 +0530 Subject: [PATCH 3/4] improve shortcuts, menu-item and search city page improved ui of search city dialog Added - press enter to search city now menu items also shows shortcut keys Added keyboard shortcuts dialog updated mousam.pot file --- po/POTFILES | 2 + po/mousam.pot | 117 ++++++++++++++++++++++++--------------- src/main.py | 4 ++ src/meson.build | 3 +- src/mousam.gresource.xml | 1 + src/mousam.py | 14 ++++- src/shortcutsDialog.py | 10 ++++ src/shortcutsDialog.ui | 71 ++++++++++++++++++++++++ src/windowLocations.py | 27 +++++++-- 9 files changed, 197 insertions(+), 52 deletions(-) create mode 100644 src/shortcutsDialog.py create mode 100644 src/shortcutsDialog.ui diff --git a/po/POTFILES b/po/POTFILES index 5e20254..8773d93 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -26,3 +26,5 @@ src/weatherData.py src/windowAbout.py src/windowLocations.py src/windowPreferences.py +src/shortcutsDialog.py +src/shortcutsDialog.ui diff --git a/po/mousam.pot b/po/mousam.pot index cf86f69..f419836 100644 --- a/po/mousam.pot +++ b/po/mousam.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-03-15 15:53+0100\n" +"POT-Creation-Date: 2024-05-08 13:57+0530\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -238,15 +238,15 @@ msgstr "" msgid "United States AQI standard" msgstr "" -#: src/frontendCardDayNight.py:73 +#: src/frontendCardDayNight.py:77 msgid "Sunrise & Sunset" msgstr "" -#: src/frontendCardDayNight.py:84 +#: src/frontendCardDayNight.py:88 msgid "Sunrise" msgstr "" -#: src/frontendCardDayNight.py:97 +#: src/frontendCardDayNight.py:101 msgid "Sunset" msgstr "" @@ -278,11 +278,11 @@ msgstr "" msgid "West" msgstr "" -#: src/frontendCardSquare.py:169 src/mousam.py:250 +#: src/frontendCardSquare.py:169 src/mousam.py:274 msgid "Northwest" msgstr "" -#: src/frontendCardSquare.py:179 src/frontendHourlyDetails.py:58 +#: src/frontendCardSquare.py:179 src/frontendHourlyDetails.py:59 msgid "Wind" msgstr "" @@ -303,7 +303,7 @@ msgstr "" msgid "Feels Like • {0} {1}" msgstr "" -#: src/frontendForecast.py:36 src/frontendForecast.py:127 +#: src/frontendForecast.py:36 src/frontendForecast.py:130 msgid "Tomorrow" msgstr "" @@ -311,134 +311,146 @@ msgstr "" msgid "Weekly" msgstr "" -#: src/frontendForecast.py:125 +#: src/frontendForecast.py:128 msgid "Today" msgstr "" -#: src/frontendHourlyDetails.py:50 +#: src/frontendHourlyDetails.py:51 msgid "Hourly" msgstr "" -#: src/frontendHourlyDetails.py:66 +#: src/frontendHourlyDetails.py:67 msgid "Precipitation" msgstr "" -#: src/frontendHourlyDetails.py:95 +#: src/frontendHourlyDetails.py:96 msgctxt "wind" msgid "Day High" msgstr "" -#: src/frontendHourlyDetails.py:111 +#: src/frontendHourlyDetails.py:112 msgctxt "temperature" msgid "Day Max" msgstr "" -#: src/frontendHourlyDetails.py:126 +#: src/frontendHourlyDetails.py:127 msgctxt "precipitation" msgid "Day High" msgstr "" -#: src/frontendHourlyDetails.py:164 +#: src/frontendHourlyDetails.py:165 msgid "No precipitation today !" msgstr "" -#: src/frontendHourlyDetails.py:165 +#: src/frontendHourlyDetails.py:166 msgid "No precipitation expected today!" msgstr "" -#: src/frontendHourlyDetails.py:166 +#: src/frontendHourlyDetails.py:167 msgid "Anticipate a precipitation-free day !" msgstr "" -#: src/frontendHourlyDetails.py:167 +#: src/frontendHourlyDetails.py:168 msgid "Enjoy a rain-free day today!" msgstr "" -#: src/frontendHourlyDetails.py:168 +#: src/frontendHourlyDetails.py:169 msgid "Umbrella status: resting. No precipitation in sight !" msgstr "" -#: src/frontendHourlyDetails.py:169 +#: src/frontendHourlyDetails.py:170 msgid "No rain in sight today!" msgstr "" -#: src/frontendHourlyDetails.py:198 +#: src/frontendHourlyDetails.py:199 msgid "Now" msgstr "" -#: src/frontendUiDrawDayNight.py:89 +#: src/frontendUiDrawDayNight.py:98 msgid "Horizon" msgstr "" -#: src/frontendUiDrawDayNight.py:99 +#: src/frontendUiDrawDayNight.py:108 msgid "Midnight" msgstr "" -#: src/mousam.py:76 +#: src/mousam.py:70 +msgid "Refresh" +msgstr "" + +#: src/mousam.py:79 src/shortcutsDialog.ui:45 msgid "Preferences" msgstr "" -#: src/mousam.py:84 +#: src/mousam.py:84 src/shortcutsDialog.ui:63 +msgid "Keyboard Shortcuts" +msgstr "" + +#: src/mousam.py:90 msgid "About Mousam" msgstr "" -#: src/mousam.py:126 +#: src/mousam.py:92 src/shortcutsDialog.ui:57 +msgid "Quit" +msgstr "" + +#: src/mousam.py:150 msgid "Getting Weather Data" msgstr "" -#: src/mousam.py:137 +#: src/mousam.py:161 msgid "No Internet" msgstr "" -#: src/mousam.py:141 +#: src/mousam.py:165 msgid "Could not fetch data from API" msgstr "" -#: src/mousam.py:249 +#: src/mousam.py:273 msgid "From" msgstr "" -#: src/mousam.py:251 +#: src/mousam.py:275 msgid "N" msgstr "" -#: src/mousam.py:261 +#: src/mousam.py:285 msgid "Dewpoint" msgstr "" -#: src/mousam.py:277 +#: src/mousam.py:301 msgctxt "pressure card" msgid "High" msgstr "" -#: src/mousam.py:278 +#: src/mousam.py:302 msgctxt "pressure card" msgid "Low" msgstr "" -#: src/mousam.py:287 +#: src/mousam.py:311 msgctxt "uvindex card" msgid "High" msgstr "" -#: src/mousam.py:288 +#: src/mousam.py:312 msgctxt "uvindex card" msgid "Low" msgstr "" -#: src/mousam.py:304 +#: src/mousam.py:328 msgid "Switched to {}" msgstr "" -#: src/mousam.py:307 +#: src/mousam.py:331 msgid "Refreshed Successfully" msgstr "" -#: src/mousam.py:317 +#: src/mousam.py:341 msgid "Refresh within 5 seconds is ignored!" msgstr "" -#: src/mousam.py:322 +#: src/mousam.py:346 msgid "Refreshing..." msgstr "" @@ -564,6 +576,7 @@ msgid "translator_credits" msgstr "" #: src/windowLocations.py:19 src/windowLocations.py:35 +#: src/shortcutsDialog.ui:39 msgid "Locations" msgstr "" @@ -587,18 +600,14 @@ msgstr "" msgid "Add New Location" msgstr "" -#: src/windowLocations.py:142 +#: src/windowLocations.py:143 msgid "Search for a city" msgstr "" -#: src/windowLocations.py:148 src/windowLocations.py:150 +#: src/windowLocations.py:149 src/windowLocations.py:151 msgid "Search" msgstr "" -#: src/windowLocations.py:205 -msgid "No results found !" -msgstr "" - #: src/windowLocations.py:229 #, python-brace-format msgid "Added - {0}" @@ -617,6 +626,14 @@ msgstr "" msgid "Deleted - {0}" msgstr "" +#: src/windowLocations.py:266 +msgid "Press enter to search" +msgstr "" + +#: src/windowLocations.py:269 +msgid "No results found!" +msgstr "" + #: src/windowPreferences.py:34 msgid "Appearance" msgstr "" @@ -673,3 +690,15 @@ msgstr "" #: src/windowPreferences.py:132 msgid "Switched to - {}" msgstr "" + +#: src/shortcutsDialog.ui:29 +msgid "General" +msgstr "" + +#: src/shortcutsDialog.ui:33 +msgid "Refresh Weather" +msgstr "" + +#: src/shortcutsDialog.ui:53 +msgid "Navigation" +msgstr "" diff --git a/src/main.py b/src/main.py index 3f0b663..dbd70f1 100644 --- a/src/main.py +++ b/src/main.py @@ -37,6 +37,10 @@ def __init__(self): self.settings = Gio.Settings(schema_id="io.github.amit9838.mousam") self.main_window = None + self.set_accels_for_action(f"win.preferences", ['comma']) + self.set_accels_for_action(f"win.shortcuts", ['question']) + + def do_activate(self): win = self.props.active_window global css_provider diff --git a/src/meson.build b/src/meson.build index 289b560..2337e58 100644 --- a/src/meson.build +++ b/src/meson.build @@ -54,7 +54,8 @@ mousam_sources = [ 'utils.py', 'windowAbout.py', 'windowPreferences.py', - 'windowLocations.py' + 'windowLocations.py', + 'shortcutsDialog.py' ] install_emptydir(moduledir / 'css') diff --git a/src/mousam.gresource.xml b/src/mousam.gresource.xml index 70b702c..5ac390d 100644 --- a/src/mousam.gresource.xml +++ b/src/mousam.gresource.xml @@ -2,6 +2,7 @@ css/style.css + shortcuts_dialog.ui diff --git a/src/mousam.py b/src/mousam.py index d80a0ad..3344340 100644 --- a/src/mousam.py +++ b/src/mousam.py @@ -14,6 +14,7 @@ from .constants import bg_css from .windowAbout import AboutWindow from .windowPreferences import WeatherPreferences +from .shortcutsDialog import ShortcutsDialog from .windowLocations import WeatherLocations from .frontendCurrentCond import CurrentCondition from .frontendHourlyDetails import HourlyDetails @@ -66,7 +67,7 @@ def __init__(self, *args, **kwargs): self.header.pack_end(self.hamburger) # Create a menu button - self.location_button = Gtk.Button(label="Open") + self.location_button = Gtk.Button(label=_("Refresh")) self.header.pack_end(self.location_button) self.location_button.set_icon_name("find-location-symbolic") self.location_button.connect("clicked", self._on_locations_clicked) @@ -77,13 +78,18 @@ def __init__(self, *args, **kwargs): self.add_action(action) menu.append(_("Preferences"), "win.preferences") - # menu.append("Help", "help") + action = Gio.SimpleAction.new("shortcuts", None) + action.connect("activate", self._show_shortcuts_dialog) + self.add_action(action) + menu.append(_("Keyboard Shortcuts"), "win.shortcuts") # Add about option action = Gio.SimpleAction.new("about", None) action.connect("activate", self._on_about_clicked) self.add_action(action) menu.append(_("About Mousam"), "win.about") + + menu.append(_("Quit"), "app.quit") @@ -365,6 +371,9 @@ def _on_locations_clicked(self, *args, **kwargs): adw_preferences_window = WeatherLocations(self.main_window) adw_preferences_window.show() + def _show_shortcuts_dialog(self,*args, **kwargs): + dialog = ShortcutsDialog(self) + dialog.show() #Def shortcuts key listeners def on_key_press(self, key_controller, keyval, keycode, state,*args): @@ -376,4 +385,3 @@ def on_key_press(self, key_controller, keyval, keycode, state,*args): if keyval == Gdk.KEY_comma: GLib.idle_add(self._on_preferences_clicked) - diff --git a/src/shortcutsDialog.py b/src/shortcutsDialog.py new file mode 100644 index 0000000..d05d218 --- /dev/null +++ b/src/shortcutsDialog.py @@ -0,0 +1,10 @@ +from gi.repository import Gtk + + +@Gtk.Template(resource_path='/io/github/amit9838/mousam/shortcuts_dialog.ui') +class ShortcutsDialog(Gtk.ShortcutsWindow): + __gtype_name__ = 'MousamShortcutsDialog' + + def __init__(self, parent): + super().__init__() + self.set_transient_for(parent) diff --git a/src/shortcutsDialog.ui b/src/shortcutsDialog.ui new file mode 100644 index 0000000..0beda12 --- /dev/null +++ b/src/shortcutsDialog.ui @@ -0,0 +1,71 @@ + + + + + + diff --git a/src/windowLocations.py b/src/windowLocations.py index 34c6e0e..76b8f3d 100644 --- a/src/windowLocations.py +++ b/src/windowLocations.py @@ -138,6 +138,7 @@ def _add_location_dialog(self,application): self._dialog.group.add(search_box) self.search_entry = Gtk.Entry() + self.search_entry.connect("activate", self._on_find_city_clicked) self.search_entry.set_icon_from_icon_name(Gtk.EntryIconPosition(1),'edit-clear-symbolic') self.search_entry.set_placeholder_text(_("Search for a city")) self.search_entry.set_hexpand(True) @@ -152,6 +153,7 @@ def _add_location_dialog(self,application): self._dialog.serach_res_grp = Adw.PreferencesGroup() self._dialog.serach_res_grp.set_hexpand(True) + self._blank_search_page('start') self._dialog.group.add(self._dialog.serach_res_grp) button.connect("clicked", self._on_find_city_clicked) @@ -172,6 +174,7 @@ def _find_city(self,widget): # Matched city from api city_data = find_city(text,5) + self._dialog.serach_res_grp.remove(self.search_page_start) if len(self._dialog.search_results)>0: for action_row in self._dialog.search_results: @@ -201,10 +204,7 @@ def _find_city(self,widget): # If no search result is found else: - res_row = Adw.ActionRow.new() - res_row.set_title(_("No results found !")) - self._dialog.search_results.append(res_row) - self._dialog.serach_res_grp.add(res_row) + self._blank_search_page(status="no_res") # =========== Add City on selection =========== @@ -261,3 +261,22 @@ def _remove_city(self,btn,widget): pass # self.application.refresh_main_ui() self.add_toast(create_toast(_("Deleted - {0}".format(widget.get_title())),1)) + + def _blank_search_page(self,status): + text = _("Press enter to search") + icon ="system-search-symbolic" + if status == 'no_res': + text = _("No results found!") + icon ="system-search-symbolic" + + self.search_page_start = Gtk.Box(orientation=Gtk.Orientation.VERTICAL,halign=Gtk.Align.CENTER, spacing = 6, margin_top=60,) + search_icon = Gtk.Image.new_from_icon_name(icon) + search_icon.set_pixel_size(48) + search_icon.set_margin_top(10) + search_icon.set_css_classes(["light-4"]) + search_page_start_text = Gtk.Label(label = text) + search_page_start_text.set_css_classes(["text-3", "bold-3", "light-5"]) + self.search_page_start.append(search_icon) + self.search_page_start.append(search_page_start_text) + self._dialog.serach_res_grp.add(self.search_page_start) + From e2531ed02a3080dbc379cae322bbb28ce40de388 Mon Sep 17 00:00:00 2001 From: Amit Chaudhary Date: Wed, 8 May 2024 14:11:52 +0530 Subject: [PATCH 4/4] fix filename --- src/mousam.gresource.xml | 2 +- src/shortcutsDialog.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mousam.gresource.xml b/src/mousam.gresource.xml index 5ac390d..5c3fdca 100644 --- a/src/mousam.gresource.xml +++ b/src/mousam.gresource.xml @@ -2,7 +2,7 @@ css/style.css - shortcuts_dialog.ui + shortcutsDialog.ui diff --git a/src/shortcutsDialog.py b/src/shortcutsDialog.py index d05d218..7b81e80 100644 --- a/src/shortcutsDialog.py +++ b/src/shortcutsDialog.py @@ -1,7 +1,7 @@ from gi.repository import Gtk -@Gtk.Template(resource_path='/io/github/amit9838/mousam/shortcuts_dialog.ui') +@Gtk.Template(resource_path='/io/github/amit9838/mousam/shortcutsDialog.ui') class ShortcutsDialog(Gtk.ShortcutsWindow): __gtype_name__ = 'MousamShortcutsDialog'