[gnome-software] Add UI to support unavailable packages



commit 2a6d6ac3f8c020f3add926c04b73e9f843a9ab63
Author: Richard Hughes <richard hughsie com>
Date:   Thu Dec 11 16:49:53 2014 +0000

    Add UI to support unavailable packages

 data/org.gnome.software.gschema.xml |    5 ++
 src/gs-app-row.c                    |   13 +++-
 src/gs-shell-details.c              |   21 ++++++-
 src/gs-shell-search.c               |   33 +++++++++-
 src/gs-utils.c                      |  120 +++++++++++++++++++++++++++++++++++
 src/gs-utils.h                      |    3 +
 6 files changed, 190 insertions(+), 5 deletions(-)
---
diff --git a/data/org.gnome.software.gschema.xml b/data/org.gnome.software.gschema.xml
index bfd9fb4..559ab8e 100644
--- a/data/org.gnome.software.gschema.xml
+++ b/data/org.gnome.software.gschema.xml
@@ -19,6 +19,11 @@
       <summary>Applications require AppData to be shown in the search results</summary>
       <description>If enabled applications require a long description before they are shown to the user in 
the search results.</description>
     </key>
+    <key name="prompt-for-nonfree" type="b">
+      <default>true</default>
+      <summary>Non-free applications show a warning dialog before install</summary>
+      <description>When non-free applications are installed a warning dialog can be shown. This controls if 
that dialog is supressed.</description>
+    </key>
     <key name="check-timestamp" type="x">
       <default>0</default>
       <summary>The last update check timestamp</summary>
diff --git a/src/gs-app-row.c b/src/gs-app-row.c
index e306731..4d607a4 100644
--- a/src/gs-app-row.c
+++ b/src/gs-app-row.c
@@ -186,9 +186,16 @@ gs_app_row_refresh (GsAppRow *app_row)
        switch (gs_app_get_state (app_row->priv->app)) {
        case AS_APP_STATE_UNAVAILABLE:
                gtk_widget_set_visible (priv->button, TRUE);
-               /* TRANSLATORS: this is a button next to the search results that
-                * allows the application to be easily installed */
-               gtk_button_set_label (GTK_BUTTON (priv->button), _("Visit website"));
+               if (gs_app_get_url (app_row->priv->app, AS_URL_KIND_MISSING) != NULL) {
+                       /* TRANSLATORS: this is a button next to the search results that
+                        * allows the application to be easily installed */
+                       gtk_button_set_label (GTK_BUTTON (priv->button), _("Visit website"));
+               } else {
+                       /* TRANSLATORS: this is a button next to the search results that
+                        * allows the application to be easily installed.
+                        * The ellipsis indicates that further steps are required */
+                       gtk_button_set_label (GTK_BUTTON (priv->button), _("Install…"));
+               }
                break;
        case AS_APP_STATE_QUEUED_FOR_INSTALL:
                gtk_widget_set_visible (priv->label, TRUE);
diff --git a/src/gs-shell-details.c b/src/gs-shell-details.c
index d95dd35..9657e11 100644
--- a/src/gs-shell-details.c
+++ b/src/gs-shell-details.c
@@ -189,9 +189,20 @@ gs_shell_details_switch_to (GsShellDetails *shell_details)
        case AS_APP_STATE_INSTALLED:
        case AS_APP_STATE_REMOVING:
        case AS_APP_STATE_UPDATABLE:
-       case AS_APP_STATE_UNAVAILABLE:
                gtk_widget_set_visible (priv->button_install, FALSE);
                break;
+       case AS_APP_STATE_UNAVAILABLE:
+               if (gs_app_get_url (priv->app, AS_URL_KIND_MISSING) != NULL) {
+                       gtk_widget_set_visible (priv->button_install, FALSE);
+               } else {
+                       gtk_widget_set_visible (priv->button_install, TRUE);
+                       /* TRANSLATORS: this is a button that allows the apps to
+                        * be installed.
+                        * The ellipsis indicates that further steps are required,
+                        * e.g. enabling software sources or the like */
+                       gtk_button_set_label (GTK_BUTTON (priv->button_install), _("_Install…"));
+               }
+               break;
        default:
                g_warning ("App unexpectedly in state %s",
                           as_app_state_to_string (state));
@@ -1182,6 +1193,14 @@ gs_shell_details_app_install (GsShellDetails *shell_details, GsApp *app)
 {
        GsShellDetailsPrivate *priv = shell_details->priv;
        GsShellDetailsHelper *helper;
+       GtkResponseType response;
+
+       /* probably non-free */
+       if (gs_app_get_state (app) == AS_APP_STATE_UNAVAILABLE) {
+               response = gs_app_notify_unavailable (app, gs_shell_get_window (priv->shell));
+               if (response != GTK_RESPONSE_OK)
+                       return;
+       }
 
        helper = g_new0 (GsShellDetailsHelper, 1);
        helper->shell_details = g_object_ref (shell_details);
diff --git a/src/gs-shell-search.c b/src/gs-shell-search.c
index 81a2f42..f9ffb41 100644
--- a/src/gs-shell-search.c
+++ b/src/gs-shell-search.c
@@ -219,6 +219,32 @@ gs_shell_search_show_missing_url (GsApp *app)
 }
 
 /**
+ * gs_shell_search_install_unavailable_app:
+ **/
+static void
+gs_shell_search_install_unavailable_app (GsShellSearch *shell_search, GsApp *app)
+{
+       GsShellSearchPrivate *priv = shell_search->priv;
+       GtkResponseType response;
+       GsShellSearchHelper *helper;
+
+       /* get confirmation */
+       response = gs_app_notify_unavailable (app, gs_shell_get_window (priv->shell));
+       if (response == GTK_RESPONSE_OK) {
+               g_debug ("installing %s", gs_app_get_id (app));
+               helper = g_new0 (GsShellSearchHelper, 1);
+               helper->shell_search = g_object_ref (shell_search);
+               helper->app = g_object_ref (app);
+               gs_plugin_loader_app_action_async (priv->plugin_loader,
+                                                  app,
+                                                  GS_PLUGIN_LOADER_ACTION_INSTALL,
+                                                  priv->cancellable,
+                                                  gs_shell_search_app_installed_cb,
+                                                  helper);
+       }
+}
+
+/**
  * gs_shell_search_app_row_clicked_cb:
  **/
 static void
@@ -231,8 +257,13 @@ gs_shell_search_app_row_clicked_cb (GsAppRow *app_row,
                gs_shell_search_app_install (shell_search, app);
        else if (gs_app_get_state (app) == AS_APP_STATE_INSTALLED)
                gs_shell_search_app_remove (shell_search, app);
-       else if (gs_app_get_state (app) == AS_APP_STATE_UNAVAILABLE)
+       else if (gs_app_get_state (app) == AS_APP_STATE_UNAVAILABLE) {
+               if (gs_app_get_url (app, AS_URL_KIND_MISSING) == NULL) {
+                       gs_shell_search_install_unavailable_app (shell_search, app);
+                       return;
+               }
                gs_shell_search_show_missing_url (app);
+       }
 }
 
 /**
diff --git a/src/gs-utils.c b/src/gs-utils.c
index 01fa2d7..f12bb3f 100644
--- a/src/gs-utils.c
+++ b/src/gs-utils.c
@@ -189,6 +189,126 @@ gs_app_notify_failed_modal (GsApp *app,
        gtk_window_present (GTK_WINDOW (dialog));
 }
 
+/**
+ * gs_app_notify_unavailable_nonfree:
+ **/
+static GtkResponseType
+gs_app_notify_unavailable_nonfree (GsApp *app, GtkWindow *parent)
+{
+       GtkResponseType response;
+       GtkWidget *dialog;
+       _cleanup_object_unref_ GSettings *settings = NULL;
+       _cleanup_string_free_ GString *body = NULL;
+       _cleanup_string_free_ GString *title = NULL;
+
+       /* check if the user has already dismissed */
+       settings = g_settings_new ("org.gnome.software");
+       if (!g_settings_get_boolean (settings, "prompt-for-nonfree"))
+               return GTK_RESPONSE_OK;
+
+       title = g_string_new ("");
+       g_string_append_printf (title, "<b>%s</b>",
+                               /* TRANSLATORS: window title, nonfree in this
+                                * case refers to Free and Open Source */
+                               _("You're About to Install Non-Free Software"));
+       dialog = gtk_message_dialog_new (parent,
+                                        GTK_DIALOG_MODAL,
+                                        GTK_MESSAGE_QUESTION,
+                                        GTK_BUTTONS_CANCEL,
+                                        NULL);
+       gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), title->str);
+
+       body = g_string_new ("");
+       g_string_append_printf (body,
+                               /* TRANSLATORS: the replacements are as follows:
+                                * 1. Application name, e.g. "Firefox"
+                                * 2. Start of hypertext e.g. <a>
+                                * 3. End of hypertext e.g. </a> */
+                               _("%s is not %sfree and open source software%s."),
+                               gs_app_get_name (app),
+                               "<a href=\"http://en.wikipedia.org/wiki/Free_and_open-source_software\";>",
+                               "</a>");
+       g_string_append (body, " ");
+       g_string_append (body,
+                       /* TRANSLATORS: Laws are geographical, urgh... */
+                       _("Depending on your country of residence, "
+                         "installing it could make you liable to prosecution."));
+       g_string_append (body, "\n");
+       g_string_append (body,
+                       /* TRANSLATORS: ...and you need to ask for advice */
+                       _("If you are uncertain about this, "
+                         "you should obtain legal advice."));
+
+       gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", body->str);
+       /* TRANSLATORS: this is button text to not ask about non-free content again */
+       gtk_dialog_add_button (GTK_DIALOG (dialog), _("Don't Warn Again"), GTK_RESPONSE_YES);
+       /* TRANSLATORS: this is button text to enable the repo and install the app */
+       gtk_dialog_add_button (GTK_DIALOG (dialog), _("Install"), GTK_RESPONSE_OK);
+       response = gtk_dialog_run (GTK_DIALOG (dialog));
+       if (response == GTK_RESPONSE_YES) {
+               response = GTK_RESPONSE_OK;
+               g_settings_set_boolean (settings, "prompt-for-nonfree", FALSE);
+       }
+       gtk_widget_destroy (dialog);
+       return response;
+}
+
+/**
+ * gs_app_notify_unavailable_other:
+ **/
+static GtkResponseType
+gs_app_notify_unavailable_other (GsApp *app, GtkWindow *parent)
+{
+       GtkResponseType response;
+       GtkWidget *dialog;
+       _cleanup_string_free_ GString *body = NULL;
+       _cleanup_string_free_ GString *title = NULL;
+
+       title = g_string_new ("");
+       g_string_append_printf (title, "<b>%s</b>",
+                               /* TRANSLATORS: window title, additional in this
+                                * case means not-currently-enabled */
+                               _("Enable Additional Software Source?"));
+       dialog = gtk_message_dialog_new (parent,
+                                        GTK_DIALOG_MODAL,
+                                        GTK_MESSAGE_QUESTION,
+                                        GTK_BUTTONS_CANCEL,
+                                        NULL);
+       gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), title->str);
+
+       body = g_string_new ("");
+       g_string_append_printf (body,
+                               /* TRANSLATORS: the replacements are as follows:
+                                * 1. Application name, e.g. "Firefox"
+                                * 2. Software source name, e.g. fedora-optional */
+                               _("%s is provided by %s."),
+                               gs_app_get_name (app),
+                               gs_app_get_origin (app));
+       g_string_append (body, "\n");
+       g_string_append (body,
+                       /* TRANSLATORS: once the source is enabled it stays enabled */
+                       _("Do you want to enable it?"));
+
+       gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", body->str);
+       /* TRANSLATORS: this is button text to enable the repo and install the app */
+       gtk_dialog_add_button (GTK_DIALOG (dialog), _("Enable"), GTK_RESPONSE_OK);
+       response = gtk_dialog_run (GTK_DIALOG (dialog));
+       gtk_widget_destroy (dialog);
+       return response;
+}
+
+/**
+ * gs_app_notify_unavailable:
+ **/
+GtkResponseType
+gs_app_notify_unavailable (GsApp *app, GtkWindow *parent)
+{
+       /* this is very crude */
+       if (g_strstr_len (gs_app_get_licence (app), -1, "Proprietary") != NULL)
+               return gs_app_notify_unavailable_nonfree (app, parent);
+       return gs_app_notify_unavailable_other (app, parent);
+}
+
 guint
 gs_string_replace (GString *string, const gchar *search, const gchar *replace)
 {
diff --git a/src/gs-utils.h b/src/gs-utils.h
index aeac877..a92f670 100644
--- a/src/gs-utils.h
+++ b/src/gs-utils.h
@@ -39,6 +39,9 @@ void   gs_app_notify_failed_modal     (GsApp          *app,
                                         GtkWindow      *parent_window,
                                         GsPluginLoaderAction action,
                                         const GError   *error);
+GtkResponseType
+       gs_app_notify_unavailable       (GsApp          *app,
+                                        GtkWindow      *parent);
 
 guint   gs_string_replace              (GString        *string,
                                         const gchar    *search,


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