[gnome-music/wip/mschraal/gtk4-toasts: 2/2] Use Adwaita Toast for notifications




commit 5126d8364de7eb8c8bf443167f9d79de605c391a
Author: Marinus Schraal <mschraal gnome org>
Date:   Tue Feb 15 13:52:51 2022 +0100

    Use Adwaita Toast for notifications
    
    Remove the in-house notification solution.

 data/org.gnome.Music.gresource.xml       |   2 -
 data/ui/NotificationsPopup.ui            |  20 ----
 data/ui/PlaylistNotification.ui          |  26 -----
 data/ui/Window.ui                        |  61 +++++------
 gnomemusic/playlisttoast.py              |  75 +++++++++++++
 gnomemusic/songtoast.py                  |  85 ++++++++++++++
 gnomemusic/widgets/notificationspopup.py | 183 -------------------------------
 gnomemusic/widgets/playlistcontrols.py   |   6 +-
 gnomemusic/widgets/songwidgetmenu.py     |   8 +-
 gnomemusic/window.py                     |   3 +-
 po/POTFILES.in                           |   4 +-
 11 files changed, 197 insertions(+), 276 deletions(-)
---
diff --git a/data/org.gnome.Music.gresource.xml b/data/org.gnome.Music.gresource.xml
index af573f539..0b20f1289 100644
--- a/data/org.gnome.Music.gresource.xml
+++ b/data/org.gnome.Music.gresource.xml
@@ -18,12 +18,10 @@
     <file preprocess="xml-stripblanks">ui/EmptyView.ui</file>
     <file preprocess="xml-stripblanks">ui/HeaderBar.ui</file>
     <file preprocess="xml-stripblanks">ui/LastfmDialog.ui</file>
-    <file preprocess="xml-stripblanks">ui/NotificationsPopup.ui</file>
     <file preprocess="xml-stripblanks">ui/PlayerToolbar.ui</file>
     <file preprocess="xml-stripblanks">ui/PlaylistControls.ui</file>
     <file preprocess="xml-stripblanks">ui/PlaylistDialog.ui</file>
     <file preprocess="xml-stripblanks">ui/PlaylistDialogRow.ui</file>
-    <file preprocess="xml-stripblanks">ui/PlaylistNotification.ui</file>
     <file preprocess="xml-stripblanks">ui/PlaylistsView.ui</file>
     <file preprocess="xml-stripblanks">ui/PlaylistsWidget.ui</file>
     <file preprocess="xml-stripblanks">ui/PlaylistTile.ui</file>
diff --git a/data/ui/Window.ui b/data/ui/Window.ui
index e767ae0cd..9c9b80bc9 100644
--- a/data/ui/Window.ui
+++ b/data/ui/Window.ui
@@ -10,47 +10,44 @@
       </object>
     </child>
     <child>
-      <object class="GtkBox">
-        <property name="orientation">vertical</property>
+      <object class="AdwToastOverlay" id="_toast_overlay">
         <child>
-          <object class="GtkStack" id="_headerbar_stack">
-            <property name="transition-type">crossfade</property>
-          </object>
-        </child>
-        <child>
-          <object class="GtkOverlay" id="_overlay">
-            <property name="vexpand">True</property>
+          <object class="GtkBox">
+            <property name="orientation">vertical</property>
             <child>
-              <object class="AdwViewStack" id="_stack">
-                <property name="focusable">False</property>
-                <property name="hhomogeneous">False</property>
-                <property name="vhomogeneous">False</property>
+              <object class="GtkStack" id="_headerbar_stack">
+                <property name="transition-type">crossfade</property>
               </object>
             </child>
-            <child type="overlay">
-              <object class="GtkProgressBar" id="_loading_progress">
-                <property name="valign">start</property>
-                <property name="visible">False</property>
-                <style>
-                  <class name="osd"/>
-                </style>
+            <child>
+              <object class="GtkOverlay" id="_overlay">
+                <property name="vexpand">True</property>
+                <child>
+                  <object class="AdwViewStack" id="_stack">
+                    <property name="focusable">False</property>
+                    <property name="hhomogeneous">False</property>
+                    <property name="vhomogeneous">False</property>
+                  </object>
+                </child>
+                <child type="overlay">
+                  <object class="GtkProgressBar" id="_loading_progress">
+                    <property name="valign">start</property>
+                    <property name="visible">False</property>
+                    <style>
+                      <class name="osd"/>
+                    </style>
+                  </object>
+                </child>
               </object>
             </child>
-            <child type="overlay">
-              <object class="NotificationsPopup" id="notifications_popup">
-                <property name="halign">center</property>
-                <property name="transition-type">slide-down</property>
-                <property name="valign">start</property>
-              </object>
+            <child>
+              <object class="SelectionToolbar" id="_selection_toolbar"/>
+            </child>
+            <child>
+              <object class="PlayerToolbar" id="_player_toolbar"/>
             </child>
           </object>
         </child>
-        <child>
-          <object class="SelectionToolbar" id="_selection_toolbar"/>
-        </child>
-        <child>
-          <object class="PlayerToolbar" id="_player_toolbar"/>
-        </child>
       </object>
     </child>
   </template>
diff --git a/gnomemusic/playlisttoast.py b/gnomemusic/playlisttoast.py
new file mode 100644
index 000000000..3de4b268e
--- /dev/null
+++ b/gnomemusic/playlisttoast.py
@@ -0,0 +1,75 @@
+# Copyright 2022 The GNOME Music Developers
+#
+# GNOME Music is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GNOME Music is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with GNOME Music; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# The GNOME Music authors hereby grant permission for non-GPL compatible
+# GStreamer plugins to be used and distributed together with GStreamer
+# and GNOME Music.  This permission is above and beyond the permissions
+# granted by the GPL license by which GNOME Music is covered.  If you
+# modify this code, you may extend this exception to your version of the
+# code, but you are not obligated to do so.  If you do not wish to do so,
+# delete this exception statement from your version.
+
+from __future__ import annotations
+from typing import Optional
+import typing
+
+from gettext import gettext as _
+from gi.repository import Adw, GLib, GObject, Gio, Gtk
+if typing.TYPE_CHECKING:
+    from gnomemusic.application import Application
+    from gnomemusic.grilowrappers.grltrackerplaylists import Playlist
+
+
+class PlaylistToast(GObject.Object):
+    """Toast for playlist deletion, including undo
+    """
+
+    __gtype_name__ = "PlaylistToast"
+
+    def __init__(self, application: Application, playlist: Playlist) -> None:
+        """Initialize the toast for song deletion
+
+        :param Application application: Application object
+        :param Playlist playlist: The playlist that contains the song
+        """
+        super().__init__()
+
+        self._coregrilo = application.props.coregrilo
+        self._playlist = playlist
+        self._undo = False
+
+        toast = Adw.Toast.new(
+            _("Playlist {} removed".format(self._playlist.props.title)))
+        toast.set_button_label(_("Undo"))
+
+        toast.set_action_name("toast.undo")
+        application.props.window.install_action(
+            "toast.undo", None, self._toast_undo_cb)
+
+        toast.connect("dismissed", self._on_dismissed)
+        self._coregrilo.stage_playlist_deletion(self._playlist)
+
+        application.props.window._toast_overlay.add_toast(toast)
+
+    def _toast_undo_cb(
+            self, widget: Gtk.Widget, action: Gio.Action,
+            param: Optional[GLib.Variant]) -> None:
+        self._undo = True
+        self._coregrilo.finish_playlist_deletion(self._playlist, False)
+
+    def _on_dismissed(self, widget: Gtk.Widget) -> None:
+        if not self._undo:
+            self._coregrilo.finish_playlist_deletion(self._playlist, True)
diff --git a/gnomemusic/songtoast.py b/gnomemusic/songtoast.py
new file mode 100644
index 000000000..084acc220
--- /dev/null
+++ b/gnomemusic/songtoast.py
@@ -0,0 +1,85 @@
+# Copyright 2022 The GNOME Music Developers
+#
+# GNOME Music is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GNOME Music is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with GNOME Music; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# The GNOME Music authors hereby grant permission for non-GPL compatible
+# GStreamer plugins to be used and distributed together with GStreamer
+# and GNOME Music.  This permission is above and beyond the permissions
+# granted by the GPL license by which GNOME Music is covered.  If you
+# modify this code, you may extend this exception to your version of the
+# code, but you are not obligated to do so.  If you do not wish to do so,
+# delete this exception statement from your version.
+
+from __future__ import annotations
+from typing import Optional
+import typing
+
+from gettext import gettext as _
+from gi.repository import Adw, GLib, GObject, Gio, Gtk
+if typing.TYPE_CHECKING:
+    from gnomemusic.application import Application
+    from gnomemusic.grilowrappers.grltrackerplaylists import Playlist
+    from gnomemusic.coresong import CoreSong
+
+
+class SongToast(GObject.Object):
+    """Toast for song deletion, including undo
+    """
+
+    __gtype_name__ = "SongToast"
+
+    def __init__(
+            self, application: Application, playlist: Playlist, position: int,
+            coresong: CoreSong) -> None:
+        """Initialize the toast for song deletion
+
+        :param Application application: Application object
+        :param Playlist playlist: The playlist that contains the song
+        :param int position: The song position in the playlist
+        :param CoreSong coresong: The coresong to be deleted
+        """
+        super().__init__()
+
+        self._coregrilo = application.props.coregrilo
+        self._coresong = coresong
+        self._playlist = playlist
+        self._position = position
+        self._undo = False
+
+        playlist_title = self._playlist.props.title
+        song_title = self._coresong.props.title
+        toast = Adw.Toast.new(
+            _("{} removed from {}".format(song_title, playlist_title)))
+        toast.set_button_label(_("Undo"))
+
+        toast.set_action_name("toast.undo")
+        application.props.window.install_action(
+            "toast.undo", None, self._toast_undo_cb)
+
+        toast.connect("dismissed", self._on_dismissed)
+        playlist.stage_song_deletion(self._coresong, position)
+
+        application.props.window._toast_overlay.add_toast(toast)
+
+    def _toast_undo_cb(
+            self, widget: Gtk.Widget, action: Gio.Action,
+            param: Optional[GLib.Variant]) -> None:
+        self._undo = True
+        self._playlist.undo_pending_song_deletion(
+            self._coresong, self._position)
+
+    def _on_dismissed(self, widget: Gtk.Widget) -> None:
+        if not self._undo:
+            self._playlist.finish_song_deletion(self._coresong, self._position)
diff --git a/gnomemusic/widgets/playlistcontrols.py b/gnomemusic/widgets/playlistcontrols.py
index 0637082a9..46432024b 100644
--- a/gnomemusic/widgets/playlistcontrols.py
+++ b/gnomemusic/widgets/playlistcontrols.py
@@ -27,7 +27,7 @@ import gettext
 from gi.repository import Gdk, GObject, Gio, Gtk
 
 from gnomemusic.grilowrappers.grltrackerplaylists import Playlist
-from gnomemusic.widgets.notificationspopup import PlaylistNotification
+from gnomemusic.playlisttoast import PlaylistToast
 
 
 @Gtk.Template(resource_path='/org/gnome/Music/ui/PlaylistControls.ui')
@@ -99,9 +99,7 @@ class PlaylistControls(Gtk.Box):
             self._player.stop()
             self._window.set_player_visible(False)
 
-        PlaylistNotification(
-            self._window.notifications_popup, self._application,
-            PlaylistNotification.Type.PLAYLIST, self.props.playlist)
+        PlaylistToast(self._application, self.props.playlist)
 
     @Gtk.Template.Callback()
     def _on_play_button_clicked(self, button: Gtk.Button) -> None:
diff --git a/gnomemusic/widgets/songwidgetmenu.py b/gnomemusic/widgets/songwidgetmenu.py
index 2eddd7a72..4f6bad2c0 100644
--- a/gnomemusic/widgets/songwidgetmenu.py
+++ b/gnomemusic/widgets/songwidgetmenu.py
@@ -29,7 +29,7 @@ import typing
 from gi.repository import Gio, Gtk
 
 from gnomemusic.grilowrappers.grltrackerplaylists import Playlist
-from gnomemusic.widgets.notificationspopup import PlaylistNotification
+from gnomemusic.songtoast import SongToast
 from gnomemusic.widgets.playlistdialog import PlaylistDialog
 from gnomemusic.widgets.songwidget import SongWidget
 if typing.TYPE_CHECKING:
@@ -124,7 +124,5 @@ class SongWidgetMenu(Gtk.PopoverMenu):
     def _remove_from_playlist(self, action: Gio.Simple, param: Any) -> None:
         self.popdown()
         position = self._song_widget.get_index()
-        notification = PlaylistNotification(  # noqa: F841
-            self._window.notifications_popup, self._application,
-            PlaylistNotification.Type.SONG, self._coreobject, position,
-            self._coresong)
+        SongToast(
+            self._application, self._coreobject, position, self._coresong)
diff --git a/gnomemusic/window.py b/gnomemusic/window.py
index fedbd9203..0c6d00da2 100644
--- a/gnomemusic/window.py
+++ b/gnomemusic/window.py
@@ -39,7 +39,6 @@ from gnomemusic.views.searchview import SearchView
 from gnomemusic.views.songsview import SongsView
 from gnomemusic.views.playlistsview import PlaylistsView
 from gnomemusic.widgets.headerbar import HeaderBar
-from gnomemusic.widgets.notificationspopup import NotificationsPopup  # noqa
 from gnomemusic.widgets.playertoolbar import PlayerToolbar  # noqa: F401
 from gnomemusic.widgets.playlistdialog import PlaylistDialog
 from gnomemusic.widgets.searchheaderbar import SearchHeaderBar
@@ -56,13 +55,13 @@ class Window(Adw.ApplicationWindow):
     selected_songs_count = GObject.Property(type=int, default=0, minimum=0)
     selection_mode = GObject.Property(type=bool, default=False)
 
-    notifications_popup = Gtk.Template.Child()
     _headerbar_stack = Gtk.Template.Child()
     _loading_progress = Gtk.Template.Child()
     _overlay = Gtk.Template.Child()
     _player_toolbar = Gtk.Template.Child()
     _selection_toolbar = Gtk.Template.Child()
     _stack = Gtk.Template.Child()
+    _toast_overlay = Gtk.Template.Child()
 
     def __init__(self, app):
         """Initialize the main window.
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f5b2bf5d0..2c2cbc253 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -13,7 +13,6 @@ data/ui/LastfmDialog.ui
 data/ui/PlayerToolbar.ui
 data/ui/PlaylistControls.ui
 data/ui/PlaylistDialog.ui
-data/ui/PlaylistNotification.ui
 data/ui/SearchHeaderBar.ui
 data/ui/SearchView.ui
 data/ui/SelectionBarMenuButton.ui
@@ -26,6 +25,8 @@ gnomemusic/gstplayer.py
 gnomemusic/inhibitsuspend.py
 gnomemusic/mpris.py
 gnomemusic/player.py
+gnomemusic/playlisttoast.py
+gnomemusic/songtoast.py
 gnomemusic/utils.py
 gnomemusic/views/albumsview.py
 gnomemusic/views/artistsview.py
@@ -37,7 +38,6 @@ gnomemusic/widgets/albumwidget.py
 gnomemusic/widgets/discbox.py
 gnomemusic/widgets/headerbar.py
 gnomemusic/widgets/lastfmdialog.py
-gnomemusic/widgets/notificationspopup.py
 gnomemusic/widgets/playertoolbar.py
 gnomemusic/widgets/playlistcontrols.py
 gnomemusic/widgets/playlistdialog.py


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]