[gnome-software] gs-shell: Add an info bar about automatic updates
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] gs-shell: Add an info bar about automatic updates
- Date: Fri, 31 Jan 2020 19:50:03 +0000 (UTC)
commit 184ec1bf02d9ff45b818e39c6d99826a146de0eb
Author: Philip Withnall <withnall endlessm com>
Date: Thu May 3 17:43:50 2018 +0200
gs-shell: Add an info bar about automatic updates
If automatic updates are disabled due to being on a metered network,
inform the user using an info bar which is visible at the top of the
main window, regardless of which tab the user is on.
Give the user a button to open the control centre and adjust their
network settings to, for example, unmark the current network as metered.
The bar is hidden if automatic updates are enabled.
If Mogwai is used, the main gnome-software window will hold the Mogwai
daemon open while the window is visible, to ensure it gets updates on
whether automatic updates are enabled. That prevents the daemon
automatically exiting. The hold is released when the main window is
closed (and gnome-software continues to run in the background) and is
reinstated when the main window is next reopened.
The bar works regardless of whether Mogwai is used, but its criteria for
being shown differ slightly.
This is based on work originally done by Joaquim Rocha for the Endless
fork of gnome-software.
po/POTFILES.in | 1 +
src/gnome-software.gresource.xml | 1 +
src/gnome-software.ui | 190 ++++++++++++++++++++-----------
src/gs-metered-data-dialog.c | 68 +++++++++++
src/gs-metered-data-dialog.h | 22 ++++
src/gs-metered-data-dialog.ui | 69 +++++++++++
src/gs-shell.c | 240 +++++++++++++++++++++++++++++++++++++++
src/meson.build | 1 +
8 files changed, 525 insertions(+), 67 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f3fe65bf..7622db86 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -31,6 +31,7 @@ src/gs-installed-page.ui
src/gs-loading-page.c
src/gs-loading-page.ui
src/gs-main.c
+src/gs-metered-data-dialog.ui
src/gs-moderate-page.ui
src/gs-origin-popover-row.c
src/gs-origin-popover-row.ui
diff --git a/src/gnome-software.gresource.xml b/src/gnome-software.gresource.xml
index 01ba394d..3eaabca2 100644
--- a/src/gnome-software.gresource.xml
+++ b/src/gnome-software.gresource.xml
@@ -14,6 +14,7 @@
<file preprocess="xml-stripblanks">gs-info-bar.ui</file>
<file preprocess="xml-stripblanks">gs-installed-page.ui</file>
<file preprocess="xml-stripblanks">gs-loading-page.ui</file>
+ <file preprocess="xml-stripblanks">gs-metered-data-dialog.ui</file>
<file preprocess="xml-stripblanks">gs-moderate-page.ui</file>
<file preprocess="xml-stripblanks">gs-overview-page.ui</file>
<file preprocess="xml-stripblanks">gs-origin-popover-row.ui</file>
diff --git a/src/gnome-software.ui b/src/gnome-software.ui
index decb44e0..6646e092 100644
--- a/src/gnome-software.ui
+++ b/src/gnome-software.ui
@@ -438,85 +438,141 @@
</child>
<child>
- <object class="GtkStack" id="stack_main">
+ <object class="GtkBox">
<property name="visible">True</property>
- <property name="homogeneous">False</property>
- <child>
- <object class="GsOverviewPage" id="overview_page">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="name">overview</property>
- </packing>
- </child>
- <child>
- <object class="GsInstalledPage" id="installed_page">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="name">installed</property>
- </packing>
- </child>
- <child>
- <object class="GsModeratePage" id="moderate_page">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="name">moderate</property>
- </packing>
- </child>
- <child>
- <object class="GsLoadingPage" id="loading_page">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="name">loading</property>
- </packing>
- </child>
- <child>
- <object class="GsSearchPage" id="search_page">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="name">search</property>
- </packing>
- </child>
- <child>
- <object class="GsUpdatesPage" id="updates_page">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="name">updates</property>
- </packing>
- </child>
+ <property name="orientation">vertical</property>
<child>
- <object class="GsDetailsPage" id="details_page">
+ <object class="GtkInfoBar" id="metered_updates_bar">
<property name="visible">True</property>
+ <property name="orientation">horizontal</property>
+ <property name="spacing">12</property>
+ <property name="message-type">GTK_MESSAGE_INFO</property>
+ <property name="show-close-button">False</property>
+ <property name="revealed">False</property>
+ <child internal-child="content_area">
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_left">6</property>
+ <property name="margin_bottom">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Automatic Updates Paused</property>
+ <property name="xalign">0.0</property>
+ <attributes>
+ <attribute name="weight" value="PANGO_WEIGHT_BOLD"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="visible">True</property>
+ <property name="margin_right">6</property>
+ <child>
+ <object class="GtkButton" id="metered_updates_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="use_underline">True</property>
+ <property name="label" translatable="yes">Find Out _More</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="GTK_RESPONSE_OK">metered_updates_button</action-widget>
+ </action-widgets>
</object>
- <packing>
- <property name="name">details</property>
- </packing>
</child>
<child>
- <object class="GsCategoryPage" id="category_page">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="name">category</property>
- </packing>
- </child>
- <child>
- <object class="GsExtrasPage" id="extras_page">
+ <object class="GtkStack" id="stack_main">
<property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <child>
+ <object class="GsOverviewPage" id="overview_page">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="name">overview</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GsInstalledPage" id="installed_page">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="name">installed</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GsModeratePage" id="moderate_page">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="name">moderate</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GsLoadingPage" id="loading_page">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="name">loading</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GsSearchPage" id="search_page">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="name">search</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GsUpdatesPage" id="updates_page">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="name">updates</property>
+ </packing>
+ </child>
+
+ <child>
+ <object class="GsDetailsPage" id="details_page">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="name">details</property>
+ </packing>
+ </child>
+
+ <child>
+ <object class="GsCategoryPage" id="category_page">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="name">category</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GsExtrasPage" id="extras_page">
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="name">extras</property>
+ </packing>
+ </child>
</object>
- <packing>
- <property name="name">extras</property>
- </packing>
</child>
</object>
-
</child>
</object>
</child>
diff --git a/src/gs-metered-data-dialog.c b/src/gs-metered-data-dialog.c
new file mode 100644
index 00000000..d91c0c2e
--- /dev/null
+++ b/src/gs-metered-data-dialog.c
@@ -0,0 +1,68 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright © 2020 Endless Mobile, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "gs-metered-data-dialog.h"
+
+struct _GsMeteredDataDialog
+{
+ GtkDialog parent_instance;
+
+ GtkWidget *button_network_settings;
+};
+
+G_DEFINE_TYPE (GsMeteredDataDialog, gs_metered_data_dialog, GTK_TYPE_DIALOG)
+
+static void
+button_network_settings_clicked_cb (GtkButton *button,
+ gpointer user_data)
+{
+ g_autoptr(GError) error_local = NULL;
+
+ if (!g_spawn_command_line_async ("gnome-control-center wifi", &error_local)) {
+ g_warning ("Error opening GNOME Control Center: %s",
+ error_local->message);
+ return;
+ }
+}
+
+static void
+gs_metered_data_dialog_init (GsMeteredDataDialog *dialog)
+{
+ gtk_widget_init_template (GTK_WIDGET (dialog));
+}
+
+static void
+gs_metered_data_dialog_class_init (GsMeteredDataDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/Software/gs-metered-data-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, GsMeteredDataDialog, button_network_settings);
+
+ gtk_widget_class_bind_template_callback (widget_class, button_network_settings_clicked_cb);
+}
+
+GtkWidget *
+gs_metered_data_dialog_new (GtkWindow *parent)
+{
+ GsMeteredDataDialog *dialog;
+
+ dialog = g_object_new (GS_TYPE_METERED_DATA_DIALOG,
+ "use-header-bar", TRUE,
+ "transient-for", parent,
+ "modal", TRUE,
+ NULL);
+
+ return GTK_WIDGET (dialog);
+}
diff --git a/src/gs-metered-data-dialog.h b/src/gs-metered-data-dialog.h
new file mode 100644
index 00000000..62eecd47
--- /dev/null
+++ b/src/gs-metered-data-dialog.h
@@ -0,0 +1,22 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright © 2020 Endless Mobile, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#pragma once
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_METERED_DATA_DIALOG (gs_metered_data_dialog_get_type ())
+
+G_DECLARE_FINAL_TYPE (GsMeteredDataDialog, gs_metered_data_dialog, GS, METERED_DATA_DIALOG, GtkDialog)
+
+GtkWidget *gs_metered_data_dialog_new (GtkWindow *parent);
+
+G_END_DECLS
diff --git a/src/gs-metered-data-dialog.ui b/src/gs-metered-data-dialog.ui
new file mode 100644
index 00000000..def0243b
--- /dev/null
+++ b/src/gs-metered-data-dialog.ui
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.10"/>
+ <template class="GsMeteredDataDialog" parent="GtkDialog">
+ <property name="title" translatable="yes">Automatic Updates Paused</property>
+ <property name="modal">True</property>
+ <property name="destroy-with-parent">True</property>
+ <property name="resizable">False</property>
+ <property name="type-hint">dialog</property>
+ <property name="skip-taskbar-hint">True</property>
+ <property name="use-header-bar">1</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar">
+ <child type="title">
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Automatic Updates Paused</property>
+ <property name="selectable">False</property>
+ <style>
+ <class name="title"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <property name="margin">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="justify">fill</property>
+ <property name="wrap">True</property>
+ <property name="wrap-mode">word-char</property>
+ <property name="label" translatable="yes">The current network is metered. Metered
connections have data limits or charges associated with them. To save data, automatic updates have therefore
been paused.
+
+Automatic updates will be resumed when an unmetered network becomes available. Until then, it is still
possible to manually install updates.
+
+Alternatively, if the current network has been incorrectly identified as being metered, this setting can be
changed.</property>
+ <property name="max-width-chars">40</property>
+ <property name="halign">center</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <child type="center">
+ <object class="GtkButton" id="button_network_settings">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Open Network _Settings</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ <signal name="clicked" handler="button_network_settings_clicked_cb"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="fill">False</property>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/src/gs-shell.c b/src/gs-shell.c
index 173a8e48..009776ad 100644
--- a/src/gs-shell.c
+++ b/src/gs-shell.c
@@ -12,10 +12,15 @@
#include <string.h>
#include <glib/gi18n.h>
+#ifdef HAVE_MOGWAI
+#include <libmogwai-schedule-client/scheduler.h>
+#endif
+
#include "gs-common.h"
#include "gs-shell.h"
#include "gs-details-page.h"
#include "gs-installed-page.h"
+#include "gs-metered-data-dialog.h"
#include "gs-moderate-page.h"
#include "gs-loading-page.h"
#include "gs-search-page.h"
@@ -51,6 +56,7 @@ typedef struct {
typedef struct
{
+ GSettings *settings;
gboolean ignore_primary_buttons;
GCancellable *cancellable;
GsPluginLoader *plugin_loader;
@@ -66,6 +72,11 @@ typedef struct
gchar *events_info_uri;
gboolean in_mode_change;
GsPage *page;
+
+#ifdef HAVE_MOGWAI
+ MwscScheduler *scheduler;
+ gulong scheduler_invalidated_handler;
+#endif /* HAVE_MOGWAI */
} GsShellPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GsShell, gs_shell, G_TYPE_OBJECT)
@@ -186,6 +197,171 @@ gs_shell_set_header_end_widget (GsShell *shell, GtkWidget *widget)
}
}
+static void
+gs_shell_refresh_auto_updates_ui (GsShell *shell)
+{
+ GsShellPrivate *priv = gs_shell_get_instance_private (shell);
+ gboolean automatic_updates_paused;
+ gboolean automatic_updates_enabled;
+ GtkInfoBar *metered_updates_bar;
+
+ automatic_updates_enabled = g_settings_get_boolean (priv->settings, "download-updates");
+
+ metered_updates_bar = GTK_INFO_BAR (gtk_builder_get_object (priv->builder, "metered_updates_bar"));
+
+#ifdef HAVE_MOGWAI
+ automatic_updates_paused = (priv->scheduler == NULL || !mwsc_scheduler_get_allow_downloads
(priv->scheduler));
+#else
+ automatic_updates_paused = gs_plugin_loader_get_network_metered (priv->plugin_loader);
+#endif
+
+ gtk_info_bar_set_revealed (metered_updates_bar,
+ priv->mode != GS_SHELL_MODE_LOADING &&
+ automatic_updates_enabled &&
+ automatic_updates_paused);
+ gtk_info_bar_set_default_response (metered_updates_bar, GTK_RESPONSE_OK);
+}
+
+static void
+gs_shell_metered_updates_bar_response_cb (GtkInfoBar *info_bar,
+ gint response_id,
+ gpointer user_data)
+{
+ GsShell *shell = GS_SHELL (user_data);
+ GsShellPrivate *priv = gs_shell_get_instance_private (shell);
+ GtkDialog *dialog;
+
+ dialog = GTK_DIALOG (gs_metered_data_dialog_new (priv->main_window));
+ gs_shell_modal_dialog_present (shell, dialog);
+
+ /* just destroy */
+ g_signal_connect_swapped (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy), dialog);
+}
+
+static void
+gs_shell_download_updates_changed_cb (GSettings *settings,
+ const gchar *key,
+ gpointer user_data)
+{
+ GsShell *shell = user_data;
+
+ gs_shell_refresh_auto_updates_ui (shell);
+}
+
+static void
+gs_shell_network_metered_notify_cb (GsPluginLoader *plugin_loader,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+#ifndef HAVE_MOGWAI
+ GsShell *shell = user_data;
+
+ /* @automatic_updates_paused only depends on network-metered if we’re
+ * compiled without Mogwai. */
+ gs_shell_refresh_auto_updates_ui (shell);
+#endif
+}
+
+#ifdef HAVE_MOGWAI
+static void
+scheduler_invalidated_cb (GsShell *shell)
+{
+ GsShellPrivate *priv = gs_shell_get_instance_private (shell);
+
+ /* The scheduler shouldn’t normally be invalidated, since we Hold() it
+ * until we’re done with it. However, if the scheduler is stopped by
+ * systemd (`systemctl stop mogwai-scheduled`) this signal will be
+ * emitted. It may also be invalidated while our main window is hidden,
+ * as we release our Hold() then. */
+ g_signal_handler_disconnect (priv->scheduler,
+ priv->scheduler_invalidated_handler);
+ priv->scheduler_invalidated_handler = 0;
+
+ g_clear_object (&priv->scheduler);
+}
+
+static void
+scheduler_allow_downloads_changed_cb (GsShell *shell)
+{
+ gs_shell_refresh_auto_updates_ui (shell);
+}
+
+static void
+scheduler_hold_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer data)
+{
+ g_autoptr(GError) error_local = NULL;
+ MwscScheduler *scheduler = (MwscScheduler *) source_object;
+ g_autoptr(GsShell) shell = data; /* reference added when starting the async operation */
+ GsShellPrivate *priv = gs_shell_get_instance_private (shell);
+
+ if (!mwsc_scheduler_hold_finish (scheduler, result, &error_local)) {
+ g_warning ("Couldn't hold the Mogwai Scheduler daemon: %s",
+ error_local->message);
+ return;
+ }
+
+ priv->scheduler_invalidated_handler =
+ g_signal_connect_swapped (scheduler, "invalidated",
+ (GCallback) scheduler_invalidated_cb,
+ shell);
+
+ g_signal_connect_object (scheduler, "notify::allow-downloads",
+ (GCallback) scheduler_allow_downloads_changed_cb,
+ shell,
+ G_CONNECT_SWAPPED);
+
+ g_assert (priv->scheduler == NULL);
+ priv->scheduler = scheduler;
+
+ /* Update the UI accordingly. */
+ gs_shell_refresh_auto_updates_ui (shell);
+}
+
+static void
+scheduler_release_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer data)
+{
+ MwscScheduler *scheduler = (MwscScheduler *) source_object;
+ g_autoptr(GsShell) shell = data; /* reference added when starting the async operation */
+ GsShellPrivate *priv = gs_shell_get_instance_private (shell);
+ g_autoptr(GError) error_local = NULL;
+
+ if (!mwsc_scheduler_release_finish (scheduler, result, &error_local))
+ g_warning ("Couldn't release the Mogwai Scheduler daemon: %s",
+ error_local->message);
+
+ g_clear_object (&priv->scheduler);
+}
+
+static void
+scheduler_ready_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer data)
+{
+ MwscScheduler *scheduler;
+ g_autoptr(GError) error_local = NULL;
+ g_autoptr(GsShell) shell = data; /* reference added when starting the async operation */
+
+ scheduler = mwsc_scheduler_new_finish (result, &error_local);
+
+ if (scheduler == NULL) {
+ g_warning ("%s: Error getting Mogwai Scheduler: %s", G_STRFUNC,
+ error_local->message);
+ return;
+ }
+
+ mwsc_scheduler_hold_async (scheduler,
+ "monitoring allow-downloads property",
+ NULL,
+ scheduler_hold_cb,
+ g_object_ref (shell));
+}
+#endif /* HAVE_MOGWAI */
+
static void
free_back_entry (BackEntry *entry)
{
@@ -347,6 +523,16 @@ gs_shell_change_mode (GsShell *shell,
widget = gs_page_get_header_end_widget (page);
gs_shell_set_header_end_widget (shell, widget);
+ /* refresh the updates bar when moving out of the loading mode, but only
+ * if the Mogwai scheduler state is already known, to avoid spuriously
+ * showing the updates bar */
+#ifdef HAVE_MOGWAI
+ if (priv->scheduler != NULL)
+#else
+ if (TRUE)
+#endif
+ gs_shell_refresh_auto_updates_ui (shell);
+
/* destroy any existing modals */
if (priv->modal_dialogs != NULL) {
gsize i = 0;
@@ -740,6 +926,21 @@ main_window_closed_cb (GtkWidget *dialog, GdkEvent *event, gpointer user_data)
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "notification_event"));
gtk_revealer_set_reveal_child (GTK_REVEALER (widget), FALSE);
+ /* release our hold on the download scheduler */
+#ifdef HAVE_MOGWAI
+ if (priv->scheduler != NULL) {
+ if (priv->scheduler_invalidated_handler > 0)
+ g_signal_handler_disconnect (priv->scheduler,
+ priv->scheduler_invalidated_handler);
+ priv->scheduler_invalidated_handler = 0;
+
+ mwsc_scheduler_release_async (priv->scheduler,
+ NULL,
+ scheduler_release_cb,
+ g_object_ref (shell));
+ }
+#endif /* HAVE_MOGWAI */
+
gs_shell_clean_back_entry_stack (shell);
gtk_widget_hide (dialog);
return TRUE;
@@ -751,6 +952,18 @@ gs_shell_main_window_mapped_cb (GtkWidget *widget, GsShell *shell)
GsShellPrivate *priv = gs_shell_get_instance_private (shell);
gs_plugin_loader_set_scale (priv->plugin_loader,
(guint) gtk_widget_get_scale_factor (widget));
+
+ /* Set up the updates bar. Do this here rather than in gs_shell_setup()
+ * since we only want to hold the scheduler open while the gnome-software
+ * main window is visible, and not while we’re running in the background. */
+#ifdef HAVE_MOGWAI
+ if (priv->scheduler == NULL)
+ mwsc_scheduler_new_async (priv->cancellable,
+ (GAsyncReadyCallback) scheduler_ready_cb,
+ g_object_ref (shell));
+#else
+ gs_shell_refresh_auto_updates_ui (shell);
+#endif /* HAVE_MOGWAI */
}
static void
@@ -1910,8 +2123,13 @@ gs_shell_setup (GsShell *shell, GsPluginLoader *plugin_loader, GCancellable *can
g_signal_connect_object (priv->plugin_loader, "notify::allow-updates",
G_CALLBACK (gs_shell_allow_updates_notify_cb),
shell, 0);
+ g_signal_connect_object (priv->plugin_loader, "notify::network-metered",
+ G_CALLBACK (gs_shell_network_metered_notify_cb),
+ shell, 0);
priv->cancellable = g_object_ref (cancellable);
+ priv->settings = g_settings_new ("org.gnome.software");
+
/* get UI */
priv->builder = gtk_builder_new_from_resource ("/org/gnome/Software/gnome-software.ui");
priv->main_window = GTK_WINDOW (gtk_builder_get_object (priv->builder, "window_software"));
@@ -2025,6 +2243,14 @@ gs_shell_setup (GsShell *shell, GsPluginLoader *plugin_loader, GCancellable *can
g_hash_table_insert (priv->pages, g_strdup ("extras"), page);
gs_shell_setup_pages (shell);
+ /* set up the metered data info bar and mogwai */
+ widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "metered_updates_bar"));
+ g_signal_connect (widget, "response",
+ (GCallback) gs_shell_metered_updates_bar_response_cb, shell);
+
+ g_signal_connect (priv->settings, "changed::download-updates",
+ (GCallback) gs_shell_download_updates_changed_cb, shell);
+
/* set up search */
g_signal_connect (priv->main_window, "key-press-event",
G_CALLBACK (window_keypress_handler), shell);
@@ -2233,6 +2459,20 @@ gs_shell_dispose (GObject *object)
g_clear_pointer (&priv->pages, g_hash_table_unref);
g_clear_pointer (&priv->events_info_uri, g_free);
g_clear_pointer (&priv->modal_dialogs, g_ptr_array_unref);
+ g_clear_object (&priv->settings);
+
+#ifdef HAVE_MOGWAI
+ if (priv->scheduler != NULL) {
+ if (priv->scheduler_invalidated_handler > 0)
+ g_signal_handler_disconnect (priv->scheduler,
+ priv->scheduler_invalidated_handler);
+
+ mwsc_scheduler_release_async (priv->scheduler,
+ NULL,
+ scheduler_release_cb,
+ g_object_ref (shell));
+ }
+#endif /* HAVE_MOGWAI */
G_OBJECT_CLASS (gs_shell_parent_class)->dispose (object);
}
diff --git a/src/meson.build b/src/meson.build
index 300ae952..cbd0a511 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -38,6 +38,7 @@ gnome_software_sources = [
'gs-language.c',
'gs-loading-page.c',
'gs-main.c',
+ 'gs-metered-data-dialog.c',
'gs-moderate-page.c',
'gs-overview-page.c',
'gs-origin-popover-row.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]