diff --git a/src/Widgets/AppEntry.vala b/src/Widgets/AppEntry.vala index 5476b56d..a35ab38a 100644 --- a/src/Widgets/AppEntry.vala +++ b/src/Widgets/AppEntry.vala @@ -74,8 +74,6 @@ public class Notifications.AppEntry : Gtk.ListBoxRow { box.append (expander); box.append (clear_btn_entry); - margin_start = 12; - margin_end = 12; margin_bottom = 3; margin_top = 6; can_focus = false; diff --git a/src/Widgets/NotificationEntry.vala b/src/Widgets/NotificationEntry.vala index fc59d8f0..2ec4d0b8 100644 --- a/src/Widgets/NotificationEntry.vala +++ b/src/Widgets/NotificationEntry.vala @@ -4,7 +4,7 @@ */ public class Notifications.NotificationEntry : Gtk.ListBoxRow { - public signal void remove (); + public signal void remove (Notification notification); public Notification notification { get; private set; } @@ -261,11 +261,12 @@ public class Notifications.NotificationEntry : Gtk.ListBoxRow { new Variant.string (notification.desktop_id), null ); - notification.notify["server-id"].connect (() => { - if (notification.server_id == 0) { - dismiss (); - } - }); + notification.notify["server-id"].connect (dismiss_if_stale); + } + + public void unbind () { + notification.notify.disconnect (dismiss_if_stale); + Settings.unbind (settings, "headers"); } private static bool get_bind_func (Value value, Variant variant, void* user_data) { @@ -277,11 +278,11 @@ public class Notifications.NotificationEntry : Gtk.ListBoxRow { private void dismiss () { if (!revealer.child_revealed) { - remove (); + remove (notification); } else { revealer.notify["child-revealed"].connect (() => { if (!revealer.child_revealed) { - remove (); + remove (notification); } }); revealer.reveal_child = false; @@ -295,6 +296,12 @@ public class Notifications.NotificationEntry : Gtk.ListBoxRow { } } + private void dismiss_if_stale () { + if (notification.server_id == 0) { + dismiss (); + } + } + private class DeleteAffordance : Granite.Bin { public Gtk.Align alignment { get; construct; } diff --git a/src/Widgets/NotificationsList.vala b/src/Widgets/NotificationsList.vala index 2b1bde1c..5e269fec 100644 --- a/src/Widgets/NotificationsList.vala +++ b/src/Widgets/NotificationsList.vala @@ -10,8 +10,6 @@ public class Notifications.NotificationsList : Granite.Bin { public const string ACTION_GROUP_PREFIX = "notifications-list"; public const string ACTION_PREFIX = ACTION_GROUP_PREFIX + "."; - private static GLib.HashTable app_datetime; - private ListStore list_store; public ListModel notification_items { get { @@ -19,12 +17,16 @@ public class Notifications.NotificationsList : Granite.Bin { } } + private static GLib.HashTable app_datetime; + private Gtk.SortListModel sort_list_model; private Gtk.Stack stack; - construct { + static construct { app_datetime = new GLib.HashTable (str_hash, str_equal); + } + construct { var placeholder = new Gtk.Label (_("No Notifications")) { margin_top = 24, margin_bottom = 24, @@ -41,15 +43,23 @@ public class Notifications.NotificationsList : Granite.Bin { section_sorter = new Gtk.CustomSorter ((GLib.CompareDataFunc) section_compare) }; - var listbox = new Gtk.ListBox () { - activate_on_single_click = true, - selection_mode = NONE + var item_factory = new Gtk.SignalListItemFactory (); + item_factory.setup.connect (setup_factory); + item_factory.bind.connect (bind_factory); + item_factory.unbind.connect (unbind_factory); + + var header_factory = new Gtk.SignalListItemFactory (); + header_factory.setup.connect (setup_header_factory); + header_factory.bind.connect (bind_header_factory); + + var list_view = new Gtk.ListView (new Gtk.NoSelection (sort_list_model), item_factory) { + header_factory = header_factory, + single_click_activate = true }; - listbox.bind_model (sort_list_model, create_widget_func); - listbox.set_header_func (header_func); + list_view.remove_css_class (Granite.STYLE_CLASS_VIEW); var scrolled = new Gtk.ScrolledWindow () { - child = listbox, + child = list_view, hscrollbar_policy = NEVER, max_content_height = 500, propagate_natural_height = true @@ -63,7 +73,7 @@ public class Notifications.NotificationsList : Granite.Bin { insert_action_group (ACTION_GROUP_PREFIX, new NotificationsMonitor ().notifications_action_group); - listbox.row_activated.connect (on_row_activated); + list_view.activate.connect (on_row_activated); list_store.items_changed.connect (on_items_changed); @@ -80,33 +90,41 @@ public class Notifications.NotificationsList : Granite.Bin { return app_datetime[b.desktop_id].compare (app_datetime[a.desktop_id]); } - private void header_func (Gtk.ListBoxRow row, Gtk.ListBoxRow? before) { - unowned var row_entry = (NotificationEntry) row; - unowned NotificationEntry? before_entry = (NotificationEntry) before; - unowned string row_app_id = row_entry.notification.desktop_id; + private void setup_factory (Object item) { + var notification_entry = new NotificationEntry (); + notification_entry.remove.connect (remove_notification); - if (before != null && row_app_id == before_entry.notification.desktop_id) { - row.set_header (null); - return; - } + ((Gtk.ListItem) item).child = notification_entry; + } - var app_entry = new AppEntry () { - app_name = row_entry.notification.app_name, - app_id = row_app_id - }; - app_entry.clear.connect (clear_app_entry); + private void bind_factory (Object item) { + var list_item = (Gtk.ListItem) item; - row.set_header (app_entry); + var notification_entry = (NotificationEntry) list_item.child; + notification_entry.bind ((Notification) list_item.item); } - private Gtk.Widget create_widget_func (Object item) { - var notification = (Notification) item; + private void unbind_factory (Object item) { + var list_item = (Gtk.ListItem) item; - var notification_entry = new NotificationEntry (); - notification_entry.bind (notification); - notification_entry.remove.connect (() => remove_notification (notification)); + var notification_entry = (NotificationEntry) list_item.child; + notification_entry.unbind (); + } + + private void setup_header_factory (Object item) { + var app_entry = new AppEntry (); + app_entry.clear.connect (clear_app_entry); - return notification_entry; + ((Gtk.ListHeader) item).child = app_entry; + } + + private void bind_header_factory (Object item) { + var list_item = (Gtk.ListHeader) item; + var notification = (Notification) list_item.item; + + var app_entry = (AppEntry) list_item.child; + app_entry.app_name = notification.app_name; + app_entry.app_id = notification.desktop_id; } public async void add_entry (Notification notification) { @@ -187,25 +205,22 @@ public class Notifications.NotificationsList : Granite.Bin { } } - private void on_row_activated (Gtk.ListBoxRow row) { - if (row is NotificationEntry) { - unowned var notification_entry = (NotificationEntry) row; - - if (notification_entry.notification.default_action != null) { - activate_action ( - ACTION_PREFIX + notification_entry.notification.default_action, - null - ); + private void on_row_activated (uint pos) { + var notification = (Notification) sort_list_model.get_item (pos); + if (notification.default_action != null) { + activate_action ( + ACTION_PREFIX + notification.default_action, + null + ); + close_popover (); + } else { + try { + var context = get_display ().get_app_launch_context (); + notification.app_info.launch (null, context); + notification.server_id = 0; close_popover (); - } else { - try { - var context = notification_entry.get_display ().get_app_launch_context (); - notification_entry.notification.app_info.launch (null, context); - notification_entry.notification.server_id = 0; - close_popover (); - } catch (Error e) { - warning ("Unable to launch app: %s", e.message); - } + } catch (Error e) { + warning ("Unable to launch app: %s", e.message); } } }