void gs_app_notify_installed (GsApp *app) { _cleanup_free_ gchar *summary = NULL; _cleanup_object_unref_ GNotification *n = NULL; /* TRANSLATORS: this is the summary of a notification that an application * has been successfully installed */ summary = g_strdup_printf (_("%s is now installed"), gs_app_get_name (app)); n = g_notification_new (summary); if (gs_app_get_id_kind (app) == AS_ID_KIND_DESKTOP) { /* TRANSLATORS: this is button that opens the newly installed application */ g_notification_add_button_with_target (n, _("Launch"), "app.launch", "s", gs_app_get_id (app)); } g_notification_set_default_action_and_target (n, "app.details", "(ss)", gs_app_get_id (app), ""); g_application_send_notification (g_application_get_default (), "installed", n); }
/** * gs_plugin_refine: */ gboolean gs_plugin_refine (GsPlugin *plugin, GList **list, GsPluginRefineFlags flags, GCancellable *cancellable, GError **error) { GsApp *app; GList *l; /* add reviews if possible */ if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEWS) { for (l = *list; l != NULL; l = l->next) { g_autoptr(GError) error_local = NULL; app = GS_APP (l->data); if (gs_app_get_reviews(app)->len > 0) continue; if (gs_app_get_id_no_prefix (app) == NULL) continue; if (gs_app_get_id_kind (app) == AS_ID_KIND_ADDON) continue; if (!gs_plugin_refine_reviews (plugin, app, cancellable, &error_local)) { g_warning ("Failed to get reviews: %s", error_local->message); } } } /* add ratings if possible */ if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEW_RATINGS) { for (l = *list; l != NULL; l = l->next) { g_autoptr(GError) error_local = NULL; app = GS_APP (l->data); if (gs_app_get_review_ratings(app) != NULL) continue; if (gs_app_get_id_no_prefix (app) == NULL) continue; if (gs_app_get_id_kind (app) == AS_ID_KIND_ADDON) continue; if (!gs_plugin_refine_ratings (plugin, app, cancellable, &error_local)) { g_warning ("Failed to get ratings: %s", error_local->message); } } } return TRUE; }
/** * gs_plugin_refine: */ gboolean gs_plugin_refine (GsPlugin *plugin, GList **list, GsPluginRefineFlags flags, GCancellable *cancellable, GError **error) { GList *l; GsApp *app; const gchar *tmp; for (l = *list; l != NULL; l = l->next) { app = GS_APP (l->data); if (gs_app_get_id_kind (app) != AS_ID_KIND_WEB_APP) continue; gs_app_set_size (app, 4096); tmp = gs_app_get_source_id_default (app); if (tmp != NULL) continue; if (!gs_plugin_refine_app (plugin, app, error)) return FALSE; } return TRUE; }
/** * gs_plugin_app_install: */ gboolean gs_plugin_app_install (GsPlugin *plugin, GsApp *app, GCancellable *cancellable, GError **error) { AsIcon *icon; gboolean ret = TRUE; gsize kf_length; g_autoptr(GError) error_local = NULL; g_autofree gchar *app_desktop = NULL; g_autofree gchar *epi_desktop = NULL; g_autofree gchar *epi_dir = NULL; g_autofree gchar *epi_icon = NULL; g_autofree gchar *exec = NULL; g_autofree gchar *hash = NULL; g_autofree gchar *id_nonfull = NULL; g_autofree gchar *kf_data = NULL; g_autofree gchar *wmclass = NULL; g_autoptr(GKeyFile) kf = NULL; g_autoptr(GFile) symlink_desktop = NULL; g_autoptr(GFile) symlink_icon = NULL; /* only process web apps */ if (gs_app_get_id_kind (app) != AS_ID_KIND_WEB_APP) return TRUE; /* create the correct directory */ id_nonfull = _gs_app_get_id_nonfull (app); hash = g_compute_checksum_for_string (G_CHECKSUM_SHA1, gs_app_get_name (app), -1); epi_dir = g_strdup_printf ("%s/epiphany/app-%s-%s", g_get_user_config_dir (), id_nonfull, hash); g_mkdir_with_parents (epi_dir, 0755); /* symlink icon */ epi_icon = g_build_filename (epi_dir, "app-icon.png", NULL); symlink_icon = g_file_new_for_path (epi_icon); icon = gs_app_get_icon (app); ret = g_file_make_symbolic_link (symlink_icon, as_icon_get_filename (icon), NULL, &error_local); if (!ret) { if (g_error_matches (error_local, G_IO_ERROR, G_IO_ERROR_EXISTS)) { g_debug ("ignoring icon symlink failure: %s", error_local->message); } else { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED, "Can't symlink icon: %s", error_local->message); return FALSE; } } /* add desktop file */ wmclass = g_strdup_printf ("%s-%s", id_nonfull, hash); kf = g_key_file_new (); g_key_file_set_string (kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, gs_app_get_name (app)); g_key_file_set_string (kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_COMMENT, gs_app_get_summary (app)); exec = g_strdup_printf ("epiphany --application-mode --profile=\"%s\" %s", epi_dir, gs_app_get_url (app, AS_URL_KIND_HOMEPAGE)); g_key_file_set_string (kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_EXEC, exec); g_key_file_set_boolean (kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_STARTUP_NOTIFY, TRUE); g_key_file_set_boolean (kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_TERMINAL, FALSE); g_key_file_set_boolean (kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY, FALSE); g_key_file_set_string (kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_TYPE, G_KEY_FILE_DESKTOP_TYPE_APPLICATION); g_key_file_set_string (kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_ICON, epi_icon); g_key_file_set_string (kf, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_STARTUP_WM_CLASS, wmclass); /* save keyfile */ kf_data = g_key_file_to_data (kf, &kf_length, error); if (kf_data == NULL) return FALSE; epi_desktop = g_strdup_printf ("%s/%s.desktop", epi_dir, wmclass); if (!g_file_set_contents (epi_desktop, kf_data, kf_length, error)) return FALSE; /* symlink it to somewhere the shell will notice */ app_desktop = g_build_filename (g_get_user_data_dir (), "applications", gs_app_get_id (app), NULL); symlink_desktop = g_file_new_for_path (app_desktop); ret = g_file_make_symbolic_link (symlink_desktop, epi_desktop, NULL, error); if (!ret) return FALSE; /* update state */ gs_app_set_state (app, AS_APP_STATE_INSTALLING); gs_app_set_state (app, AS_APP_STATE_INSTALLED); return TRUE; }
/** * gs_app_notify_unavailable: **/ GtkResponseType gs_app_notify_unavailable (GsApp *app, GtkWindow *parent) { GsAppLicenceHint hint = GS_APP_LICENCE_FREE; GtkResponseType response; GtkWidget *dialog; const gchar *licence; gboolean already_enabled = FALSE; /* FIXME */ guint i; struct { const gchar *str; GsAppLicenceHint hint; } keywords[] = { { "NonFree", GS_APP_LICENCE_NONFREE }, { "PatentConcern", GS_APP_LICENCE_PATENT_CONCERN }, { "Proprietary", GS_APP_LICENCE_NONFREE }, { NULL, 0 } }; _cleanup_free_ gchar *origin_url = NULL; _cleanup_object_unref_ GSettings *settings = NULL; _cleanup_string_free_ GString *body = NULL; _cleanup_string_free_ GString *title = NULL; /* this is very crude */ licence = gs_app_get_licence (app); if (licence != NULL) { for (i = 0; keywords[i].str != NULL; i++) { if (g_strstr_len (licence, -1, keywords[i].str) != NULL) hint |= keywords[i].hint; } } else { /* use the worst-case assumption */ hint = GS_APP_LICENCE_NONFREE | GS_APP_LICENCE_PATENT_CONCERN; } /* 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 (""); if (already_enabled) { g_string_append_printf (title, "<b>%s</b>", /* TRANSLATORS: window title */ _("Install Third-Party Software?")); } else { g_string_append_printf (title, "<b>%s</b>", /* TRANSLATORS: window title */ _("Enable Third-Party 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); /* FIXME: get the URL somehow... */ origin_url = g_strdup_printf ("<a href=\"\">%s>/a>", gs_app_get_origin (app)); body = g_string_new (""); if (hint & GS_APP_LICENCE_NONFREE) { 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 not <a href=\"https://en.wikipedia.org/wiki/Free_and_open-source_software\">" "free and open source software</a>, " "and is provided by “%s”."), gs_app_get_name (app), origin_url); } else { 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), origin_url); } /* tell the use what needs to be done */ if (!already_enabled) { g_string_append (body, " "); g_string_append (body, /* TRANSLATORS: a software source is a repo */ _("This software source must be " "enabled to continue installation.")); } /* be aware of patent clauses */ if (hint & GS_APP_LICENCE_PATENT_CONCERN) { g_string_append (body, "\n\n"); if (gs_app_get_id_kind (app) != AS_ID_KIND_CODEC) { g_string_append_printf (body, /* TRANSLATORS: Laws are geographical, urgh... */ _("It may be illegal to install " "or use %s in some countries."), gs_app_get_name (app)); } else { g_string_append (body, /* TRANSLATORS: Laws are geographical, urgh... */ _("It may be illegal to install or use " "this codec in some countries.")); } } 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 */ if (0) gtk_dialog_add_button (GTK_DIALOG (dialog), _("Don't Warn Again"), GTK_RESPONSE_YES); if (already_enabled) { gtk_dialog_add_button (GTK_DIALOG (dialog), /* TRANSLATORS: button text */ _("Install"), GTK_RESPONSE_OK); } else { gtk_dialog_add_button (GTK_DIALOG (dialog), /* TRANSLATORS: button text */ _("Enable and 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; }