summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Soriano <csoriano@gnome.org>2015-07-14 19:46:21 +0200
committerCarlos Soriano <csoriano@gnome.org>2015-07-17 00:42:05 +0200
commit9bea0f6f801195716c3627d27eb3fda451ff78d7 (patch)
treed23f2f84acda97f5cf43799383a3072c41f43cc2
parent6c576b9266ee223075c08b2441b675ac7c1aef07 (diff)
downloadnautilus-9bea0f6f801195716c3627d27eb3fda451ff78d7.tar.gz
operations: show a notification when operation finishes
When the operations popover is not visible, we have to give feedback to the user about if an operation finished. For that, show a in-app notification in case the operation popover is closed and a operation finishes. Also, to link the notification with the operation button, make the button pulse for a second. The code interaction between nautilus-file-operations and nautilus-progress-info start to get crowed. At some point, the best we can do is delegate all the progress UI part to nautilus-progress-info, providing all the needed information like the CommonJob, TransferInfo and SourceInfo; so we avoid the current odd interaction between them. This is a future work.
-rw-r--r--libnautilus-private/nautilus-file-operations.c21
-rw-r--r--libnautilus-private/nautilus-progress-info.c25
-rw-r--r--libnautilus-private/nautilus-progress-info.h4
-rw-r--r--src/nautilus-toolbar.c50
-rw-r--r--src/nautilus-window.c171
-rw-r--r--src/nautilus-window.h4
-rw-r--r--src/nautilus-window.ui69
7 files changed, 300 insertions, 44 deletions
diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c
index 38bdf3977..4b5b8539b 100644
--- a/libnautilus-private/nautilus-file-operations.c
+++ b/libnautilus-private/nautilus-file-operations.c
@@ -4910,6 +4910,9 @@ nautilus_file_operations_copy_file (GFile *source_file,
job->done_callback_data = done_callback_data;
job->files = g_list_append (NULL, g_object_ref (source_file));
job->destination = g_object_ref (target_dir);
+ /* Need to indicate the destination for the operation notification open
+ * button. */
+ nautilus_progress_info_set_destination (((CommonJob *)job)->progress, target_dir);
job->target_name = g_strdup (new_name);
job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL);
@@ -4947,6 +4950,9 @@ nautilus_file_operations_copy (GList *files,
job->done_callback_data = done_callback_data;
job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL);
job->destination = g_object_ref (target_dir);
+ /* Need to indicate the destination for the operation notification open
+ * button. */
+ nautilus_progress_info_set_destination (((CommonJob *)job)->progress, target_dir);
if (relative_item_points != NULL &&
relative_item_points->len > 0) {
job->icon_positions =
@@ -5485,6 +5491,9 @@ nautilus_file_operations_move (GList *files,
job->done_callback_data = done_callback_data;
job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL);
job->destination = g_object_ref (target_dir);
+ /* Need to indicate the destination for the operation notification open
+ * button. */
+ nautilus_progress_info_set_destination (((CommonJob *)job)->progress, target_dir);
if (relative_item_points != NULL &&
relative_item_points->len > 0) {
job->icon_positions =
@@ -5811,6 +5820,9 @@ nautilus_file_operations_link (GList *files,
job->done_callback_data = done_callback_data;
job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL);
job->destination = g_object_ref (target_dir);
+ /* Need to indicate the destination for the operation notification open
+ * button. */
+ nautilus_progress_info_set_destination (((CommonJob *)job)->progress, target_dir);
if (relative_item_points != NULL &&
relative_item_points->len > 0) {
job->icon_positions =
@@ -5846,12 +5858,19 @@ nautilus_file_operations_duplicate (GList *files,
gpointer done_callback_data)
{
CopyMoveJob *job;
+ GFile *parent;
job = op_job_new (CopyMoveJob, parent_window);
job->done_callback = done_callback;
job->done_callback_data = done_callback_data;
job->files = g_list_copy_deep (files, (GCopyFunc) g_object_ref, NULL);
job->destination = NULL;
+ /* Duplicate files doesn't have a destination, since is the same as source.
+ * For that set as destination the source parent folder */
+ parent = g_file_get_parent (files->data);
+ /* Need to indicate the destination for the operation notification open
+ * button. */
+ nautilus_progress_info_set_destination (((CommonJob *)job)->progress, parent);
if (relative_item_points != NULL &&
relative_item_points->len > 0) {
job->icon_positions =
@@ -5877,6 +5896,8 @@ nautilus_file_operations_duplicate (GList *files,
NULL, /* destroy notify */
0,
job->common.cancellable);
+
+ g_object_unref (parent);
}
static gboolean
diff --git a/libnautilus-private/nautilus-progress-info.c b/libnautilus-private/nautilus-progress-info.c
index ddec24896..24988991b 100644
--- a/libnautilus-private/nautilus-progress-info.c
+++ b/libnautilus-private/nautilus-progress-info.c
@@ -68,6 +68,8 @@ struct _NautilusProgressInfo
gboolean cancel_at_idle;
gboolean changed_at_idle;
gboolean progress_at_idle;
+
+ GFile *destination;
};
struct _NautilusProgressInfoClass
@@ -92,6 +94,7 @@ nautilus_progress_info_finalize (GObject *object)
g_object_unref (info->cancellable);
g_cancellable_cancel (info->details_in_thread_cancellable);
g_clear_object (&info->details_in_thread_cancellable);
+ g_clear_object (&info->destination);
if (G_OBJECT_CLASS (nautilus_progress_info_parent_class)->finalize) {
(*G_OBJECT_CLASS (nautilus_progress_info_parent_class)->finalize) (object);
@@ -687,3 +690,25 @@ nautilus_progress_info_get_elapsed_time (NautilusProgressInfo *info)
return elapsed_time;
}
+
+void
+nautilus_progress_info_set_destination (NautilusProgressInfo *info,
+ GFile *file)
+{
+ G_LOCK (progress_info);
+ g_clear_object (&info->destination);
+ info->destination = g_object_ref (file);
+ G_UNLOCK (progress_info);
+}
+
+GFile *
+nautilus_progress_info_get_destination (NautilusProgressInfo *info)
+{
+ GFile *destination;
+
+ G_LOCK (progress_info);
+ destination = g_object_ref (info->destination);
+ G_UNLOCK (progress_info);
+
+ return destination;
+}
diff --git a/libnautilus-private/nautilus-progress-info.h b/libnautilus-private/nautilus-progress-info.h
index 44b812c57..cf0daebac 100644
--- a/libnautilus-private/nautilus-progress-info.h
+++ b/libnautilus-private/nautilus-progress-info.h
@@ -86,6 +86,10 @@ void nautilus_progress_info_set_elapsed_time (NautilusProgressInfo *inf
gdouble time);
gdouble nautilus_progress_info_get_elapsed_time (NautilusProgressInfo *info);
+void nautilus_progress_info_set_destination (NautilusProgressInfo *info,
+ GFile *file);
+GFile *nautilus_progress_info_get_destination (NautilusProgressInfo *info);
+
#endif /* NAUTILUS_PROGRESS_INFO_H */
diff --git a/src/nautilus-toolbar.c b/src/nautilus-toolbar.c
index 0b85ed0ed..b4934fe9f 100644
--- a/src/nautilus-toolbar.c
+++ b/src/nautilus-toolbar.c
@@ -61,6 +61,7 @@ struct _NautilusToolbarPrivate {
guint popup_timeout_id;
guint start_operations_timeout_id;
guint remove_finished_operations_timeout_id;
+ guint operations_button_attention_timeout_id;
GtkWidget *operations_button;
GtkWidget *view_button;
@@ -492,6 +493,19 @@ schedule_remove_finished_operations (NautilusToolbar *self)
}
}
+static gboolean
+remove_operations_button_attention_style (NautilusToolbar *self)
+{
+ GtkStyleContext *style_context;
+
+ style_context = gtk_widget_get_style_context (self->priv->operations_button);
+ gtk_style_context_remove_class (style_context,
+ "suggested-action");
+ self->priv->operations_button_attention_timeout_id = 0;
+
+ return G_SOURCE_REMOVE;
+}
+
static void
on_progress_info_cancelled (NautilusToolbar *self)
{
@@ -510,14 +524,40 @@ on_progress_info_progress_changed (NautilusToolbar *self)
}
static void
-on_progress_info_finished (NautilusToolbar *self)
+on_progress_info_finished (NautilusToolbar *self,
+ NautilusProgressInfo *info)
{
+ GtkStyleContext *style_context;
+ gchar *main_label;
+ GFile *folder_to_open;
+
/* Update the pie chart progress */
gtk_widget_queue_draw (self->priv->operations_icon);
if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->priv->operations_button))) {
schedule_remove_finished_operations (self);
}
+
+ folder_to_open = nautilus_progress_info_get_destination (info);
+ /* If destination is null, don't show a notification. This happens when the
+ * operation is a trash operation, which we already show a diferent kind of
+ * notification */
+ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->priv->operations_button)) &&
+ folder_to_open != NULL) {
+ style_context = gtk_widget_get_style_context (self->priv->operations_button);
+ gtk_style_context_add_class (style_context,
+ "suggested-action");
+ self->priv->operations_button_attention_timeout_id = g_timeout_add_seconds (1,
+ (GSourceFunc) remove_operations_button_attention_style,
+ self);
+ main_label = nautilus_progress_info_get_status (info);
+ nautilus_window_show_operation_notification (self->priv->window,
+ main_label,
+ folder_to_open);
+ g_free (main_label);
+ }
+
+ g_clear_object (&folder_to_open);
}
static void
@@ -594,9 +634,6 @@ on_progress_info_started_timeout (NautilusToolbar *self)
return G_SOURCE_CONTINUE;
} else {
self->priv->start_operations_timeout_id = 0;
- if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->priv->operations_button))) {
- schedule_remove_finished_operations (self);
- }
return G_SOURCE_REMOVE;
}
}
@@ -827,6 +864,11 @@ nautilus_toolbar_dispose (GObject *obj)
unschedule_remove_finished_operations (self);
unschedule_operations_start (self);
+ if (self->priv->operations_button_attention_timeout_id != 0) {
+ g_source_remove (self->priv->operations_button_attention_timeout_id);
+ self->priv->operations_button_attention_timeout_id = 0;
+ }
+
g_signal_handlers_disconnect_by_data (self->priv->progress_manager, self);
g_clear_object (&self->priv->progress_manager);
diff --git a/src/nautilus-window.c b/src/nautilus-window.c
index d315316ab..748e91c09 100644
--- a/src/nautilus-window.c
+++ b/src/nautilus-window.c
@@ -120,6 +120,12 @@ struct _NautilusWindowPrivate {
GtkWidget *notification_delete_close;
GtkWidget *notification_delete_undo;
guint notification_delete_timeout_id;
+ GtkWidget *notification_operation;
+ GtkWidget *notification_operation_label;
+ GtkWidget *notification_operation_close;
+ GtkWidget *notification_operation_open;
+ guint notification_operation_timeout_id;
+ GFile *folder_to_open;
/* Toolbar */
GtkWidget *toolbar;
@@ -1488,30 +1494,39 @@ nautilus_window_ensure_location_entry (NautilusWindow *window)
}
static void
-nautilus_window_on_notification_delete_undo_clicked (GtkWidget *notification,
- gpointer user_data)
+remove_notifications (NautilusWindow *window)
{
- NautilusWindow *window;
-
- window = NAUTILUS_WINDOW (user_data);
+ GtkRevealerTransitionType transition_type;
- if (window->priv->notification_delete_timeout_id != 0) {
- g_source_remove (window->priv->notification_delete_timeout_id);
- window->priv->notification_delete_timeout_id = 0;
+ /* Hide it inmediatily so we can animate the new notification. */
+ transition_type = gtk_revealer_get_transition_type (GTK_REVEALER (window->priv->notification_delete));
+ gtk_revealer_set_transition_type (GTK_REVEALER (window->priv->notification_delete),
+ GTK_REVEALER_TRANSITION_TYPE_NONE);
+ gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->notification_delete),
+ FALSE);
+ gtk_revealer_set_transition_type (GTK_REVEALER (window->priv->notification_delete),
+ transition_type);
+ if (window->priv->notification_delete_timeout_id != 0) {
+ g_source_remove (window->priv->notification_delete_timeout_id);
+ window->priv->notification_delete_timeout_id = 0;
}
- gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->notification_delete), FALSE);
- nautilus_file_undo_manager_undo (GTK_WINDOW (window));
+ transition_type = gtk_revealer_get_transition_type (GTK_REVEALER (window->priv->notification_operation));
+ gtk_revealer_set_transition_type (GTK_REVEALER (window->priv->notification_operation),
+ GTK_REVEALER_TRANSITION_TYPE_NONE);
+ gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->notification_operation),
+ FALSE);
+ gtk_revealer_set_transition_type (GTK_REVEALER (window->priv->notification_operation),
+ transition_type);
+ if (window->priv->notification_operation_timeout_id != 0) {
+ g_source_remove (window->priv->notification_operation_timeout_id);
+ window->priv->notification_operation_timeout_id = 0;
+ }
}
static void
-nautilus_window_on_notification_delete_close_clicked (GtkWidget *notification,
- gpointer user_data)
+hide_notification_delete (NautilusWindow *window)
{
- NautilusWindow *window;
-
- window = NAUTILUS_WINDOW (user_data);
-
if (window->priv->notification_delete_timeout_id != 0) {
g_source_remove (window->priv->notification_delete_timeout_id);
window->priv->notification_delete_timeout_id = 0;
@@ -1520,19 +1535,26 @@ nautilus_window_on_notification_delete_close_clicked (GtkWidget *notification,
gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->notification_delete), FALSE);
}
-static gboolean
-nautilus_window_on_notification_delete_timeout (gpointer user_data)
+static void
+nautilus_window_on_notification_delete_undo_clicked (GtkWidget *notification,
+ NautilusWindow *window)
{
- NautilusWindow *window;
+ hide_notification_delete (window);
- window = NAUTILUS_WINDOW (user_data);
+ nautilus_file_undo_manager_undo (GTK_WINDOW (window));
+}
- if (window->priv->notification_delete_timeout_id != 0) {
- g_source_remove (window->priv->notification_delete_timeout_id);
- window->priv->notification_delete_timeout_id = 0;
- }
+static void
+nautilus_window_on_notification_delete_close_clicked (GtkWidget *notification,
+ NautilusWindow *window)
+{
+ hide_notification_delete (window);
+}
- gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->notification_delete), FALSE);
+static gboolean
+nautilus_window_on_notification_delete_timeout (NautilusWindow *window)
+{
+ hide_notification_delete (window);
return FALSE;
}
@@ -1566,20 +1588,9 @@ nautilus_window_on_undo_changed (NautilusFileUndoManager *manager,
{
NautilusFileUndoInfo *undo_info;
NautilusFileUndoManagerState state;
- int transition_durantion;
gchar *label;
GList *files;
- /* Hide it inmediatily so we can animate the new notification. */
- transition_durantion = gtk_revealer_get_transition_duration (GTK_REVEALER (window->priv->notification_delete));
- gtk_revealer_set_transition_duration (GTK_REVEALER (window->priv->notification_delete), 0);
- gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->notification_delete), FALSE);
- gtk_revealer_set_transition_duration (GTK_REVEALER (window->priv->notification_delete), transition_durantion);
- if (window->priv->notification_delete_timeout_id != 0) {
- g_source_remove (window->priv->notification_delete_timeout_id);
- window->priv->notification_delete_timeout_id = 0;
- }
-
undo_info = nautilus_file_undo_manager_get_action ();
state = nautilus_file_undo_manager_get_state ();
@@ -1597,7 +1608,7 @@ nautilus_window_on_undo_changed (NautilusFileUndoManager *manager,
gtk_label_set_markup (GTK_LABEL (window->priv->notification_delete_label), label);
gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->notification_delete), TRUE);
window->priv->notification_delete_timeout_id = g_timeout_add_seconds (NOTIFICATION_TIMEOUT,
- nautilus_window_on_notification_delete_timeout,
+ (GSourceFunc) nautilus_window_on_notification_delete_timeout,
window);
g_free (label);
}
@@ -1606,6 +1617,74 @@ nautilus_window_on_undo_changed (NautilusFileUndoManager *manager,
}
static void
+hide_notification_operation (NautilusWindow *window)
+{
+ if (window->priv->notification_operation_timeout_id != 0) {
+ g_source_remove (window->priv->notification_operation_timeout_id);
+ window->priv->notification_operation_timeout_id = 0;
+ }
+
+ gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->notification_operation), FALSE);
+ g_clear_object (&window->priv->folder_to_open);
+}
+
+static void
+on_notification_operation_open_clicked (GtkWidget *notification,
+ NautilusWindow *window)
+{
+ nautilus_window_slot_open_location (window->priv->active_slot,
+ window->priv->folder_to_open,
+ 0);
+ hide_notification_operation (window);
+}
+
+static void
+on_notification_operation_close_clicked (GtkWidget *notification,
+ NautilusWindow *window)
+{
+ hide_notification_operation (window);
+}
+
+static gboolean
+on_notification_operation_timeout (NautilusWindow *window)
+{
+ hide_notification_operation (window);
+
+ return FALSE;
+}
+
+void
+nautilus_window_show_operation_notification (NautilusWindow *window,
+ gchar *main_label,
+ GFile *folder_to_open)
+{
+ gchar *button_label;
+ gchar *folder_name;
+ NautilusFile *folder;
+
+ if (gtk_window_has_toplevel_focus (GTK_WINDOW (window)) &&
+ !NAUTILUS_IS_DESKTOP_WINDOW (window)) {
+ remove_notifications (window);
+ window->priv->folder_to_open = g_object_ref (folder_to_open);
+ folder = nautilus_file_get (folder_to_open);
+ folder_name = nautilus_file_get_display_name (folder);
+ button_label = g_strdup_printf (_("Open %s"), folder_name);
+ gtk_label_set_text (GTK_LABEL (window->priv->notification_operation_label),
+ main_label);
+ gtk_button_set_label (GTK_BUTTON (window->priv->notification_operation_open),
+ button_label);
+ gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->notification_operation), TRUE);
+ window->priv->notification_operation_timeout_id = g_timeout_add_seconds (NOTIFICATION_TIMEOUT,
+ (GSourceFunc) on_notification_operation_timeout,
+ window);
+ g_object_unref (folder);
+ g_free (folder_name);
+ g_free (button_label);
+ }
+
+}
+
+static void
path_bar_location_changed_callback (GtkWidget *widget,
GFile *location,
NautilusWindow *window)
@@ -2104,9 +2183,14 @@ nautilus_window_finalize (GObject *object)
window->priv->sidebar_width_handler_id = 0;
}
- if (window->priv->notification_delete_timeout_id != 0) {
- g_source_remove (window->priv->notification_delete_timeout_id);
- window->priv->notification_delete_timeout_id = 0;
+ if (window->priv->notification_delete_timeout_id != 0) {
+ g_source_remove (window->priv->notification_delete_timeout_id);
+ window->priv->notification_delete_timeout_id = 0;
+ }
+
+ if (window->priv->notification_operation_timeout_id != 0) {
+ g_source_remove (window->priv->notification_operation_timeout_id);
+ window->priv->notification_operation_timeout_id = 0;
}
g_signal_handlers_disconnect_by_func (nautilus_file_undo_manager_get (),
@@ -2508,6 +2592,10 @@ nautilus_window_class_init (NautilusWindowClass *class)
gtk_widget_class_bind_template_child_private (wclass, NautilusWindow, notification_delete_label);
gtk_widget_class_bind_template_child_private (wclass, NautilusWindow, notification_delete_undo);
gtk_widget_class_bind_template_child_private (wclass, NautilusWindow, notification_delete_close);
+ gtk_widget_class_bind_template_child_private (wclass, NautilusWindow, notification_operation);
+ gtk_widget_class_bind_template_child_private (wclass, NautilusWindow, notification_operation_label);
+ gtk_widget_class_bind_template_child_private (wclass, NautilusWindow, notification_operation_open);
+ gtk_widget_class_bind_template_child_private (wclass, NautilusWindow, notification_operation_close);
properties[PROP_DISABLE_CHROME] =
g_param_spec_boolean ("disable-chrome",
@@ -2558,6 +2646,9 @@ nautilus_window_class_init (NautilusWindowClass *class)
G_CALLBACK(use_extra_mouse_buttons_changed),
NULL);
+ gtk_widget_class_bind_template_callback (wclass, on_notification_operation_open_clicked);
+ gtk_widget_class_bind_template_callback (wclass, on_notification_operation_close_clicked);
+
g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
}
diff --git a/src/nautilus-window.h b/src/nautilus-window.h
index 1612145d1..4b16bf752 100644
--- a/src/nautilus-window.h
+++ b/src/nautilus-window.h
@@ -146,4 +146,8 @@ void nautilus_window_sync_allow_stop (NautilusWindow *window,
NautilusWindowSlot *slot);
void nautilus_window_sync_title (NautilusWindow *window,
NautilusWindowSlot *slot);
+
+void nautilus_window_show_operation_notification (NautilusWindow *window,
+ gchar *main_label,
+ GFile *folder_to_open);
#endif
diff --git a/src/nautilus-window.ui b/src/nautilus-window.ui
index 5205ced76..2a8c439c9 100644
--- a/src/nautilus-window.ui
+++ b/src/nautilus-window.ui
@@ -123,6 +123,75 @@
</child>
</object>
</child>
+ <child type="overlay">
+ <object class="GtkRevealer" id="notification_operation">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="valign">start</property>
+ <property name="transition_duration">100</property>
+ <child>
+ <object class="GtkFrame">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_start">12</property>
+ <property name="margin_end">4</property>
+ <child>
+ <object class="GtkLabel" id="notification_operation_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="max_width_chars">50</property>
+ <property name="ellipsize">middle</property>
+ <property name="margin_end">30</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="notification_operation_open">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="no_show_all">True</property>
+ <property name="margin_end">6</property>
+ <signal name="clicked" handler="on_notification_operation_open_clicked" object="NautilusWindow" swapped="no"/>
+ <style>
+ <class name="text-button"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="notification_operation_close">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="relief">none</property>
+ <property name="focus_on_click">False</property>
+ <signal name="clicked" handler="on_notification_operation_close_clicked" object="NautilusWindow" swapped="no"/>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">window-close-symbolic</property>
+ <property name="icon_size">2</property>
+ </object>
+ </child>
+ <style>
+ <class name="image-button"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <style>
+ <class name="app-notification"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
</object>
</child>
</object>