[gnome-software/wip/hughsie/non-free: 6/6] Add functionality to enable non-free sources
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software/wip/hughsie/non-free: 6/6] Add functionality to enable non-free sources
- Date: Mon, 29 Aug 2016 18:47:31 +0000 (UTC)
commit f135e7be891235e7d17c98f7b6af2f0103d77064
Author: Richard Hughes <richard hughsie com>
Date: Mon Aug 29 19:46:12 2016 +0100
Add functionality to enable non-free sources
data/org.gnome.software.gschema.xml | 12 +++
src/gs-shell-overview.c | 167 +++++++++++++++++++++++++++++++
src/gs-shell-overview.ui | 73 ++++++++++++++
src/gs-sources-dialog.c | 187 +++++++++++++++++++++++++++++++++++
src/gs-sources-dialog.ui | 27 ++++-
5 files changed, 461 insertions(+), 5 deletions(-)
---
diff --git a/data/org.gnome.software.gschema.xml b/data/org.gnome.software.gschema.xml
index 0677bc9..1d5ed1b 100644
--- a/data/org.gnome.software.gschema.xml
+++ b/data/org.gnome.software.gschema.xml
@@ -90,9 +90,21 @@
<default>true</default>
<summary>Show some UI elements informing the user that an app is non-free</summary>
</key>
+ <key name="show-nonfree-prompt" type="b">
+ <default>true</default>
+ <summary>Show the prompt to install nonfree software sources</summary>
+ </key>
+ <key name="show-nonfree-software" type="b">
+ <default>false</default>
+ <summary>Show non-free software in search results</summary>
+ </key>
<key name="nonfree-software-uri" type="s">
<default>'https://en.wikipedia.org/wiki/Proprietary_software'</default>
<summary>The URI that explains nonfree and proprietary software</summary>
</key>
+ <key name="nonfree-sources" type="as">
+ <default>['google-chrome']</default>
+ <summary>A list of non-free sources that can be optionally enabled</summary>
+ </key>
</schema>
</schemalist>
diff --git a/src/gs-shell-overview.c b/src/gs-shell-overview.c
index 57b4920..cf37f56 100644
--- a/src/gs-shell-overview.c
+++ b/src/gs-shell-overview.c
@@ -53,7 +53,10 @@ typedef struct
gchar *category_of_day;
GtkWidget *search_button;
GHashTable *category_hash; /* id : GsCategory */
+ GSettings *settings;
+ GtkWidget *infobar_proprietary;
+ GtkWidget *label_proprietary;
GtkWidget *bin_featured;
GtkWidget *box_overview;
GtkWidget *box_popular;
@@ -604,6 +607,141 @@ gs_shell_overview_categories_expander_cb (GtkButton *button, GsShellOverview *se
gtk_revealer_set_reveal_child (GTK_REVEALER (priv->categories_more), TRUE);
}
+static gchar *
+gs_utils_build_source_unique_id (const gchar *id)
+{
+ if (as_utils_unique_id_valid (id))
+ return g_strdup (id);
+ return as_utils_unique_id_build (AS_APP_SCOPE_UNKNOWN,
+ AS_BUNDLE_KIND_UNKNOWN,
+ NULL,
+ AS_APP_KIND_SOURCE,
+ id,
+ NULL);
+}
+
+static void
+g_shell_overview_get_sources_cb (GsPluginLoader *plugin_loader,
+ GAsyncResult *res,
+ GsShellOverview *self)
+{
+ guint i;
+ g_auto(GStrv) nonfree_ids = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GsAppList) list = NULL;
+ GsShellOverviewPrivate *priv = gs_shell_overview_get_instance_private (self);
+
+ /* get the results */
+ list = gs_plugin_loader_get_sources_finish (plugin_loader, res, &error);
+ if (list == NULL) {
+ if (g_error_matches (error,
+ G_IO_ERROR,
+ G_IO_ERROR_CANCELLED)) {
+ g_debug ("get sources cancelled");
+ } else {
+ g_warning ("failed to get sources: %s", error->message);
+ }
+ return;
+ }
+
+ /* enable each */
+ nonfree_ids = g_settings_get_strv (priv->settings, "nonfree-sources");
+ for (i = 0; nonfree_ids[i] != NULL; i++) {
+ GsApp *app;
+ g_autofree gchar *unique_id = NULL;
+
+ /* match the ID from GSettings to an actual GsApp */
+ unique_id = gs_utils_build_source_unique_id (nonfree_ids[i]);
+ app = gs_app_list_lookup (list, unique_id);
+ if (app == NULL) {
+ g_warning ("no source for %s", unique_id);
+ continue;
+ }
+
+ /* depending on the new policy, add or remove the source */
+ if (g_settings_get_boolean (priv->settings, "show-nonfree-software")) {
+ if (gs_app_get_state (app) == AS_APP_STATE_AVAILABLE) {
+ g_error ("not ready yet");
+ gs_page_install_app (GS_PAGE (self), app,
+ priv->cancellable);
+ }
+ } else {
+ if (gs_app_get_state (app) == AS_APP_STATE_INSTALLED) {
+ gs_page_remove_app (GS_PAGE (self), app,
+ priv->cancellable);
+ }
+ }
+ }
+}
+
+static void
+g_shell_overview_rescan_proprietary_sources (GsShellOverview *self)
+{
+ GsShellOverviewPrivate *priv = gs_shell_overview_get_instance_private (self);
+ gs_plugin_loader_get_sources_async (priv->plugin_loader,
+ GS_PLUGIN_REFINE_FLAGS_REQUIRE_SETUP_ACTION,
+ priv->cancellable,
+ (GAsyncReadyCallback) g_shell_overview_get_sources_cb,
+ self);
+}
+
+static void
+g_shell_overview_proprietary_response_cb (GtkInfoBar *info_bar,
+ gint response_id,
+ GsShellOverview *self)
+{
+ GsShellOverviewPrivate *priv = gs_shell_overview_get_instance_private (self);
+ g_settings_set_boolean (priv->settings, "show-nonfree-prompt", FALSE);
+ if (response_id == GTK_RESPONSE_CLOSE) {
+ gtk_widget_hide (priv->infobar_proprietary);
+ return;
+ }
+ if (response_id != GTK_RESPONSE_YES)
+ return;
+ g_settings_set_boolean (priv->settings, "show-nonfree-software", TRUE);
+
+ /* actually call into the plugin loader and do the action */
+ g_shell_overview_rescan_proprietary_sources (self);
+}
+
+static void
+gs_shell_overview_refresh_proprietary (GsShellOverview *self)
+{
+ GsShellOverviewPrivate *priv = gs_shell_overview_get_instance_private (self);
+ g_auto(GStrv) nonfree_ids = NULL;
+
+ /* only show if never prompted and have nonfree repos */
+ nonfree_ids = g_settings_get_strv (priv->settings, "nonfree-sources");
+ if (g_settings_get_boolean (priv->settings, "show-nonfree-prompt") &&
+ !g_settings_get_boolean (priv->settings, "show-nonfree-software") &&
+ g_strv_length (nonfree_ids) > 0) {
+ g_autoptr(GString) str = g_string_new (NULL);
+ g_autofree gchar *uri = NULL;
+
+ /* get from GSettings, as some distros want to override this */
+ uri = g_settings_get_string (priv->settings, "nonfree-software-uri");
+
+ /* TRANSLATORS: this is the proprietary info bar */
+ g_string_append (str, _("Provides access to additional software, "
+ "including web browsers and games."));
+ g_string_append (str, " ");
+ /* TRANSLATORS: this is the proprietary info bar */
+ g_string_append (str, _("Proprietary software has restrictions "
+ "on use and access to source code."));
+ if (uri != NULL && uri[0] != '\0') {
+ g_string_append (str, "\n");
+ g_string_append_printf (str, "<a href=\"%s\">%s</a>",
+ /* TRANSLATORS: this is the clickable
+ * link on the proprietary info bar */
+ uri, _("Find out more…"));
+ }
+ gtk_label_set_markup (GTK_LABEL (priv->label_proprietary), str->str);
+ gtk_widget_set_visible (priv->infobar_proprietary, TRUE);
+ } else {
+ gtk_widget_set_visible (priv->infobar_proprietary, FALSE);
+ }
+}
+
void
gs_shell_overview_setup (GsShellOverview *self,
GsShell *shell,
@@ -625,6 +763,14 @@ gs_shell_overview_setup (GsShellOverview *self,
priv->category_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify) g_object_unref);
+ /* create info bar if not already dismissed in initial-setup */
+ gs_shell_overview_refresh_proprietary (self);
+ gtk_info_bar_add_button (GTK_INFO_BAR (priv->infobar_proprietary),
+ /* TRANSLATORS: button to turn on proprietary software sources */
+ _("Enable"), GTK_RESPONSE_YES);
+ g_signal_connect (priv->infobar_proprietary, "response",
+ G_CALLBACK (g_shell_overview_proprietary_response_cb), self);
+
/* avoid a ref cycle */
priv->shell = shell;
@@ -657,9 +803,27 @@ gs_shell_overview_setup (GsShellOverview *self,
}
static void
+settings_changed_cb (GSettings *settings,
+ const gchar *key,
+ GsShellOverview *self)
+{
+ if (g_strcmp0 (key, "show-nonfree-software") == 0 ||
+ g_strcmp0 (key, "show-nonfree-prompt") == 0 ||
+ g_strcmp0 (key, "nonfree-software-uri") == 0 ||
+ g_strcmp0 (key, "nonfree-sources") == 0) {
+ gs_shell_overview_refresh_proprietary (self);
+ }
+}
+
+static void
gs_shell_overview_init (GsShellOverview *self)
{
+ GsShellOverviewPrivate *priv = gs_shell_overview_get_instance_private (self);
gtk_widget_init_template (GTK_WIDGET (self));
+ priv->settings = g_settings_new ("org.gnome.software");
+ g_signal_connect (priv->settings, "changed",
+ G_CALLBACK (settings_changed_cb),
+ self);
}
static void
@@ -671,6 +835,7 @@ gs_shell_overview_dispose (GObject *object)
g_clear_object (&priv->builder);
g_clear_object (&priv->plugin_loader);
g_clear_object (&priv->cancellable);
+ g_clear_object (&priv->settings);
g_clear_pointer (&priv->category_of_day, g_free);
g_clear_pointer (&priv->category_hash, g_hash_table_unref);
@@ -710,6 +875,8 @@ gs_shell_overview_class_init (GsShellOverviewClass *klass)
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/Software/gs-shell-overview.ui");
+ gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, infobar_proprietary);
+ gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, label_proprietary);
gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, bin_featured);
gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, box_overview);
gtk_widget_class_bind_template_child_private (widget_class, GsShellOverview, box_popular);
diff --git a/src/gs-shell-overview.ui b/src/gs-shell-overview.ui
index 18d2f1c..ab9e1ff 100644
--- a/src/gs-shell-overview.ui
+++ b/src/gs-shell-overview.ui
@@ -15,6 +15,79 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkInfoBar" id="infobar_proprietary">
+ <property name="visible">True</property>
+ <property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_close_button">True</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <property name="layout_style">end</property>
+ <child/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="content_area">
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <property name="border_width">12</property>
+ <child>
+ <object class="GtkLabel" id="label_proprietary_title">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Enable Proprietary Software
Sources?</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_proprietary">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label">Provides access to additional software.</property>
+ <property name="wrap">True</property>
+ <property name="wrap_mode">word-char</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+
<child>
<object class="GtkScrolledWindow" id="scrolledwindow_overview">
<property name="visible">True</property>
diff --git a/src/gs-sources-dialog.c b/src/gs-sources-dialog.c
index e9c2496..94d0cd1 100644
--- a/src/gs-sources-dialog.c
+++ b/src/gs-sources-dialog.c
@@ -25,6 +25,7 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
+#include "gs-app-list.h"
#include "gs-sources-dialog.h"
#include "gs-os-release.h"
#include "gs-sources-dialog-row.h"
@@ -33,17 +34,22 @@
struct _GsSourcesDialog
{
GtkDialog parent_instance;
+ GSettings *settings;
+ GsAppList *source_list;
GCancellable *cancellable;
GsPluginLoader *plugin_loader;
GtkWidget *button_back;
GtkWidget *button_remove;
+ GtkWidget *frame_proprietary;
GtkWidget *grid_noresults;
GtkWidget *label2;
GtkWidget *label_empty;
GtkWidget *label_header;
GtkWidget *listbox;
GtkWidget *listbox_apps;
+ GtkWidget *listbox_proprietary;
+ GtkWidget *row_proprietary;
GtkWidget *scrolledwindow_apps;
GtkWidget *spinner;
GtkWidget *stack;
@@ -51,6 +57,8 @@ struct _GsSourcesDialog
G_DEFINE_TYPE (GsSourcesDialog, gs_sources_dialog, GTK_TYPE_DIALOG)
+static void reload_sources (GsSourcesDialog *dialog);
+
static gchar *
get_source_installed_text (GPtrArray *sources)
{
@@ -155,6 +163,157 @@ add_source (GtkListBox *listbox, GsApp *app)
gtk_widget_show (row);
}
+static gchar *
+gs_utils_build_source_unique_id (const gchar *id)
+{
+ if (as_utils_unique_id_valid (id))
+ return g_strdup (id);
+ return as_utils_unique_id_build (AS_APP_SCOPE_UNKNOWN,
+ AS_BUNDLE_KIND_UNKNOWN,
+ NULL,
+ AS_APP_KIND_SOURCE,
+ id,
+ NULL);
+}
+
+static void
+source_modified_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source);
+ GsSourcesDialog *dialog = GS_SOURCES_DIALOG (user_data);
+ g_autoptr(GError) error = NULL;
+
+ if (!gs_plugin_loader_app_action_finish (plugin_loader, res, &error)) {
+ g_warning ("failed to remove: %s", error->message);
+ } else {
+ reload_sources (dialog);
+ }
+}
+
+static void
+gs_sources_dialog_rescan_proprietary_sources (GsSourcesDialog *dialog)
+{
+ guint i;
+ g_auto(GStrv) nonfree_ids = NULL;
+
+ nonfree_ids = g_settings_get_strv (dialog->settings, "nonfree-sources");
+ for (i = 0; nonfree_ids[i] != NULL; i++) {
+ GsApp *app;
+ g_autofree gchar *unique_id = NULL;
+ unique_id = gs_utils_build_source_unique_id (nonfree_ids[i]);
+ app = gs_app_list_lookup (dialog->source_list, unique_id);
+ if (app == NULL) {
+ g_warning ("no source for %s", unique_id);
+ continue;
+ }
+
+ /* depending on the new policy, add or remove the source */
+ if (g_settings_get_boolean (dialog->settings, "show-nonfree-software")) {
+ if (gs_app_get_state (app) == AS_APP_STATE_AVAILABLE) {
+ gs_plugin_loader_app_action_async (dialog->plugin_loader,
+ app,
+ GS_PLUGIN_LOADER_ACTION_INSTALL,
+ dialog->cancellable,
+ source_modified_cb,
+ dialog);
+ }
+ } else {
+ g_error ("Don't leave me this way!");
+ if (gs_app_get_state (app) == AS_APP_STATE_INSTALLED) {
+ gs_plugin_loader_app_action_async (dialog->plugin_loader,
+ app,
+ GS_PLUGIN_LOADER_ACTION_REMOVE,
+ dialog->cancellable,
+ source_modified_cb,
+ dialog);
+ }
+ }
+ }
+}
+
+static void
+gs_sources_dialog_switch_active_cb (GsSourcesDialogRow *row,
+ GParamSpec *pspec,
+ GsSourcesDialog *dialog)
+{
+ gboolean active = gs_sources_dialog_row_get_switch_active (row);
+ g_settings_set_boolean (dialog->settings, "show-nonfree-software", active);
+ g_settings_set_boolean (dialog->settings, "show-nonfree-prompt", FALSE);
+}
+
+static void
+gs_sources_dialog_refresh_proprietary_apps (GsSourcesDialog *dialog)
+{
+ GtkWidget *row;
+ gboolean switch_active;
+ guint i;
+ g_autofree gchar *text = NULL;
+ g_autofree gchar *uri = NULL;
+ g_auto(GStrv) nonfree_ids = NULL;
+ g_autoptr(GPtrArray) sources = g_ptr_array_new ();
+ g_autoptr(GString) str = g_string_new (NULL);
+
+ /* get from GSettings, as some distros want to override this */
+ nonfree_ids = g_settings_get_strv (dialog->settings, "nonfree-sources");
+ if (g_strv_length (nonfree_ids) == 0) {
+ gtk_widget_hide (dialog->frame_proprietary);
+ return;
+ }
+
+ /* TRANSLATORS: nonfree software */
+ g_string_append (str, _("Typically has restrictions on use and "
+ "access to source code."));
+ g_string_append (str, " ");
+
+ /* optional URL */
+ uri = g_settings_get_string (dialog->settings, "nonfree-software-uri");
+ if (uri != NULL) {
+ g_string_append_printf (str, "<a href=\"%s\">%s</a>", uri,
+ /* TRANSLATORS: this is the clickable
+ * link on the proprietary info bar */
+ _("Find out more…"));
+ }
+
+ /* add row */
+ if (dialog->row_proprietary == NULL) {
+ dialog->row_proprietary = gs_sources_dialog_row_new ();
+ g_signal_connect (dialog->row_proprietary, "notify::switch-active",
+ G_CALLBACK (gs_sources_dialog_switch_active_cb),
+ dialog);
+ gs_sources_dialog_row_set_name (GS_SOURCES_DIALOG_ROW (dialog->row_proprietary),
+ /* TRANSLATORS: list header */
+ _("Proprietary Software Sources"));
+ gs_sources_dialog_row_set_switch_enabled (GS_SOURCES_DIALOG_ROW (dialog->row_proprietary),
TRUE);
+ gtk_list_box_prepend (GTK_LIST_BOX (dialog->listbox_proprietary), dialog->row_proprietary);
+ gtk_widget_show (dialog->row_proprietary);
+ }
+ gs_sources_dialog_row_set_comment (GS_SOURCES_DIALOG_ROW (dialog->row_proprietary), str->str);
+
+ /* get all the proprietary sources */
+ for (i = 0; nonfree_ids[i] != NULL; i++) {
+ GsApp *app;
+ g_autofree gchar *unique_id = NULL;
+ unique_id = gs_utils_build_source_unique_id (nonfree_ids[i]);
+ app = gs_app_list_lookup (dialog->source_list, unique_id);
+ if (app == NULL) {
+ g_warning ("no source for %s", unique_id);
+ continue;
+ }
+ g_ptr_array_add (sources, app);
+ }
+ text = get_source_installed_text (sources);
+ gs_sources_dialog_row_set_description (GS_SOURCES_DIALOG_ROW (dialog->row_proprietary),
+ text);
+
+ /* if the user opted in then show the switch as active */
+ switch_active = g_settings_get_boolean (dialog->settings, "show-nonfree-software");
+ gs_sources_dialog_row_set_switch_active (GS_SOURCES_DIALOG_ROW (dialog->row_proprietary),
+ switch_active);
+ gtk_widget_show (dialog->frame_proprietary);
+}
+
static void
get_sources_cb (GsPluginLoader *plugin_loader,
GAsyncResult *res,
@@ -200,7 +359,11 @@ get_sources_cb (GsPluginLoader *plugin_loader,
if (gs_app_get_state (app) != AS_APP_STATE_INSTALLED)
continue;
add_source (GTK_LIST_BOX (dialog->listbox), app);
+ gs_app_list_add (dialog->source_list, app);
}
+
+ /* refresh widget */
+ gs_sources_dialog_refresh_proprietary_apps (dialog);
}
static void
@@ -441,6 +604,19 @@ set_plugin_loader (GsSourcesDialog *dialog, GsPluginLoader *plugin_loader)
}
static void
+settings_changed_cb (GSettings *settings,
+ const gchar *key,
+ GsSourcesDialog *dialog)
+{
+ if (g_strcmp0 (key, "show-nonfree-software") == 0 ||
+ g_strcmp0 (key, "nonfree-software-uri") == 0 ||
+ g_strcmp0 (key, "nonfree-sources") == 0) {
+ gs_sources_dialog_refresh_proprietary_apps (dialog);
+ gs_sources_dialog_rescan_proprietary_sources (dialog);
+ }
+}
+
+static void
gs_sources_dialog_dispose (GObject *object)
{
GsSourcesDialog *dialog = GS_SOURCES_DIALOG (object);
@@ -454,6 +630,8 @@ gs_sources_dialog_dispose (GObject *object)
g_cancellable_cancel (dialog->cancellable);
g_clear_object (&dialog->cancellable);
}
+ g_clear_object (&dialog->settings);
+ g_clear_object (&dialog->source_list);
G_OBJECT_CLASS (gs_sources_dialog_parent_class)->dispose (object);
}
@@ -466,7 +644,12 @@ gs_sources_dialog_init (GsSourcesDialog *dialog)
gtk_widget_init_template (GTK_WIDGET (dialog));
+ dialog->source_list = gs_app_list_new ();
dialog->cancellable = g_cancellable_new ();
+ dialog->settings = g_settings_new ("org.gnome.software");
+ g_signal_connect (dialog->settings, "changed",
+ G_CALLBACK (settings_changed_cb),
+ dialog);
gtk_list_box_set_header_func (GTK_LIST_BOX (dialog->listbox),
list_header_func,
@@ -486,6 +669,8 @@ gs_sources_dialog_init (GsSourcesDialog *dialog)
list_sort_func,
dialog, NULL);
+ gs_sources_dialog_refresh_proprietary_apps (dialog);
+
os_name = get_os_name ();
/* TRANSLATORS: This is the text displayed in the Software Sources
dialog when no OS-provided software sources are enabled. %s gets
@@ -518,12 +703,14 @@ gs_sources_dialog_class_init (GsSourcesDialogClass *klass)
gtk_widget_class_bind_template_child (widget_class, GsSourcesDialog, button_back);
gtk_widget_class_bind_template_child (widget_class, GsSourcesDialog, button_remove);
+ gtk_widget_class_bind_template_child (widget_class, GsSourcesDialog, frame_proprietary);
gtk_widget_class_bind_template_child (widget_class, GsSourcesDialog, grid_noresults);
gtk_widget_class_bind_template_child (widget_class, GsSourcesDialog, label2);
gtk_widget_class_bind_template_child (widget_class, GsSourcesDialog, label_empty);
gtk_widget_class_bind_template_child (widget_class, GsSourcesDialog, label_header);
gtk_widget_class_bind_template_child (widget_class, GsSourcesDialog, listbox);
gtk_widget_class_bind_template_child (widget_class, GsSourcesDialog, listbox_apps);
+ gtk_widget_class_bind_template_child (widget_class, GsSourcesDialog, listbox_proprietary);
gtk_widget_class_bind_template_child (widget_class, GsSourcesDialog, scrolledwindow_apps);
gtk_widget_class_bind_template_child (widget_class, GsSourcesDialog, spinner);
gtk_widget_class_bind_template_child (widget_class, GsSourcesDialog, stack);
diff --git a/src/gs-sources-dialog.ui b/src/gs-sources-dialog.ui
index e9a7977..92fc490 100644
--- a/src/gs-sources-dialog.ui
+++ b/src/gs-sources-dialog.ui
@@ -43,7 +43,7 @@
<object class="GtkLabel" id="label_header">
<property name="can_focus">False</property>
<property name="visible">True</property>
- <property name="label" translatable="yes">Software Sources</property>
+ <property name="label" translatable="yes">Additional Software Sources</property>
<property name="selectable">False</property>
<style>
<class name="title"/>
@@ -130,14 +130,34 @@
<property name="margin_bottom">32</property>
<property name="orientation">vertical</property>
<property name="spacing">4</property>
+
+ <child>
+ <object class="GtkFrame" id="frame_proprietary">
+ <property name="visible">True</property>
+ <property name="shadow_type">in</property>
+ <property name="halign">fill</property>
+ <property name="valign">start</property>
+ <property name="margin_bottom">16</property>
+ <child>
+ <object class="GtkListBox" id="listbox_proprietary">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="selection_mode">none</property>
+ </object>
+ </child>
+ </object>
+ </child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">Software sources give you access to additional
software.</property>
+ <property name="label" translatable="yes">Additional Sources</property>
<property name="wrap">True</property>
<property name="max_width_chars">30</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
<style>
<class name="dim-label"/>
</style>
@@ -145,7 +165,6 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="position">0</property>
</packing>
</child>
<child>
@@ -163,7 +182,6 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="position">1</property>
</packing>
</child>
<child>
@@ -193,7 +211,6 @@
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
- <property name="position">2</property>
</packing>
</child>
</object>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]