[gnome-software/wip/hughsie/editor: 16/16] Convert the editor to use xmlb rather than appstream-glib
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software/wip/hughsie/editor: 16/16] Convert the editor to use xmlb rather than appstream-glib
- Date: Tue, 30 Jul 2019 15:14:21 +0000 (UTC)
commit d02ef0398e8f9ed7d7ac220175f9c8a51011b154
Author: Richard Hughes <richard hughsie com>
Date: Wed Jul 17 17:02:42 2019 +0100
Convert the editor to use xmlb rather than appstream-glib
This also allows us to actually import and export the reference XML correctly.
src/gs-editor.c | 761 +++++++++++++++++++++++++++++++++++---------------------
src/meson.build | 3 +-
2 files changed, 478 insertions(+), 286 deletions(-)
---
diff --git a/src/gs-editor.c b/src/gs-editor.c
index 9bd06294..d5b3f236 100644
--- a/src/gs-editor.c
+++ b/src/gs-editor.c
@@ -10,6 +10,7 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <locale.h>
+#include <xmlb.h>
#include "gs-common.h"
#include "gs-css.h"
@@ -17,21 +18,150 @@
#include "gs-summary-tile.h"
#include "gs-upgrade-banner.h"
+#include "gnome-software-private.h"
+
typedef struct {
GCancellable *cancellable;
GtkApplication *application;
GtkBuilder *builder;
GtkWidget *featured_tile1;
GtkWidget *upgrade_banner;
- AsStore *store;
- AsStore *store_global;
- AsApp *selected_item;
- AsApp *deleted_item;
+ GsPluginLoader *plugin_loader;
+ GsAppList *store;
+ GsApp *selected_app;
+ GsApp *deleted_app;
gboolean is_in_refresh;
gboolean pending_changes;
guint refresh_details_delayed_id;
+ guint autosave_id;
+ GFile *autosave_file;
} GsEditor;
+static void
+gs_editor_error_message (GsEditor *self, const gchar *title, const gchar *message)
+{
+ GtkWidget *dialog;
+ GtkWindow *window;
+ window = GTK_WINDOW (gtk_builder_get_object (self->builder, "window_main"));
+ dialog = gtk_message_dialog_new (window,
+ GTK_DIALOG_MODAL |
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_OK,
+ "%s", title);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+static GsApp *
+gs_editor_node_to_app (XbNode *component)
+{
+ g_autoptr(GsApp) app = gs_app_new (NULL);
+ const gchar *tmp;
+ const gchar *keys[] = {
+ "GnomeSoftware::AppTile-css",
+ "GnomeSoftware::FeatureTile-css",
+ "GnomeSoftware::UpgradeBanner-css",
+ NULL };
+
+ /* <id> */
+ tmp = xb_node_query_text (component, "id", NULL);
+ if (tmp == NULL)
+ return NULL;
+ gs_app_set_id (app, tmp);
+
+ /* <kudos><kudo>foo</kudo></kudos> */
+ if (xb_node_query_text (component, "kudos/kudo[text()='GnomeSoftware::popular']", NULL) != NULL)
+ gs_app_add_kudo (app, GS_APP_KUDO_POPULAR);
+
+ /* <categories><category>Featured</category></categories> */
+ if (xb_node_query_text (component, "categories/category[text()='Featured']", NULL) != NULL)
+ gs_app_add_kudo (app, GS_APP_KUDO_FEATURED_RECOMMENDED);
+
+ /* <custom><value key="foo">bar</value></custom> */
+ for (guint j = 0; keys[j] != NULL; j++) {
+ g_autofree gchar *xpath = g_strdup_printf ("custom/value[@key='%s']", keys[j]);
+ tmp = xb_node_query_text (component, xpath, NULL);
+ if (tmp != NULL)
+ gs_app_set_metadata (app, keys[j], tmp);
+ }
+ return g_steal_pointer (&app);
+}
+
+static XbBuilderNode *
+gs_editor_app_to_node (GsApp *app)
+{
+ g_autoptr(XbBuilderNode) component = xb_builder_node_new ("component");
+ g_autoptr(XbBuilderNode) custom = NULL;
+ const gchar *keys[] = {
+ "GnomeSoftware::AppTile-css",
+ "GnomeSoftware::FeatureTile-css",
+ "GnomeSoftware::UpgradeBanner-css",
+ NULL };
+
+ /* <id> */
+ xb_builder_node_insert_text (component, "id", gs_app_get_id (app), NULL);
+
+ /* <categories><category>Featured</category></categories> */
+ if (gs_app_has_kudo (app, GS_APP_KUDO_FEATURED_RECOMMENDED)) {
+ g_autoptr(XbBuilderNode) cats = NULL;
+ cats = xb_builder_node_insert (component, "categories", NULL);
+ xb_builder_node_insert_text (cats, "category", "Featured", NULL);
+ }
+
+ /* <kudos><kudo>foo</kudo></kudos> */
+ if (gs_app_has_kudo (app, GS_APP_KUDO_POPULAR)) {
+ g_autoptr(XbBuilderNode) kudos = NULL;
+ kudos = xb_builder_node_insert (component, "kudos", NULL);
+ xb_builder_node_insert_text (kudos, "category", "GnomeSoftware::popular", NULL);
+ }
+
+ /* <custom><value key="foo">bar</value></custom> */
+ custom = xb_builder_node_insert (component, "custom", NULL);
+ for (guint j = 0; keys[j] != NULL; j++) {
+ g_autoptr(XbBuilderNode) value = xb_builder_node_new ("value");
+ const gchar *tmp = gs_app_get_metadata_item (app, keys[j]);
+ if (tmp == NULL)
+ continue;
+
+ /* add literal text */
+ xb_builder_node_add_flag (value, XB_BUILDER_NODE_FLAG_LITERAL_TEXT);
+ xb_builder_node_set_text (value, tmp, -1);
+ xb_builder_node_set_attr (value, "key", keys[j]);
+ xb_builder_node_add_child (custom, value);
+ }
+
+ return g_steal_pointer (&component);
+}
+
+static void
+gs_editor_add_nodes_from_silo (GsEditor *self, XbSilo *silo)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) components = NULL;
+
+ components = xb_silo_query (silo, "components/component", 0, &error);
+ if (components == NULL) {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ return;
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT))
+ return;
+ /* TRANSLATORS: error dialog title */
+ gs_editor_error_message (self, _("Failed to load components"), error->message);
+ return;
+ }
+ for (guint i = 0; i < components->len; i++) {
+ g_autoptr(GsApp) app = NULL;
+ XbNode *component = g_ptr_array_index (components, i);
+ app = gs_editor_node_to_app (component);
+ if (app == NULL)
+ continue;
+ gs_app_list_add (self->store, app);
+ }
+}
+
static gchar *
gs_editor_css_download_resources (GsEditor *self, const gchar *css, GError **error)
{
@@ -66,123 +196,31 @@ gs_design_validate_css (GsEditor *self, const gchar *markup, GError **error)
}
static void
-gs_editor_refine_app_pixbuf (GsApp *app)
+gs_editor_copy_from_global_app (GsApp *app, GsApp *global_app)
{
- GPtrArray *icons;
- if (gs_app_get_pixbuf (app) != NULL)
+ gs_app_set_state (app, AS_APP_STATE_UNKNOWN);
+
+ /* nothing found */
+ if (global_app == NULL) {
+ gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "Application");
+ gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "Description");
+ gs_app_set_description (app, GS_APP_QUALITY_NORMAL, "A multiline description");
+ gs_app_set_version (app, "3.28");
+ gs_app_set_pixbuf (app, NULL);
+ gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
return;
- icons = gs_app_get_icons (app);
- for (guint i = 0; i < icons->len; i++) {
- AsIcon *ic = g_ptr_array_index (icons, i);
- g_autoptr(GError) error = NULL;
- if (as_icon_get_kind (ic) == AS_ICON_KIND_STOCK) {
-
- g_autoptr(GdkPixbuf) pb = NULL;
- pb = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
- as_icon_get_name (ic),
- 64,
- GTK_ICON_LOOKUP_FORCE_SIZE,
- &error);
- if (pb == NULL) {
- g_warning ("failed to load icon: %s", error->message);
- continue;
- }
- gs_app_set_pixbuf (app, pb);
- } else {
- if (!as_icon_load (ic, AS_ICON_LOAD_FLAG_SEARCH_SIZE, &error)) {
- g_warning ("failed to load icon: %s", error->message);
- continue;
- }
- gs_app_set_pixbuf (app, as_icon_get_pixbuf (ic));
- }
- break;
- }
-}
-
-static GsApp *
-gs_editor_convert_app (GsEditor *self, AsApp *item)
-{
- AsApp *item_global;
- AsAppState item_state;
- GsApp *app;
- const gchar *keys[] = {
- "GnomeSoftware::AppTile-css",
- "GnomeSoftware::FeatureTile-css",
- "GnomeSoftware::UpgradeBanner-css",
- NULL };
-
- /* copy name, summary and description */
- app = gs_app_new (as_app_get_id (item));
- item_global = as_store_get_app_by_id (self->store_global, as_app_get_id (item));
- if (item_global == NULL) {
- const gchar *tmp;
- g_autoptr(AsIcon) ic = NULL;
- g_debug ("no app found for %s, using fallback", as_app_get_id (item));
-
- /* copy from AsApp, falling back to something sane */
- tmp = as_app_get_name (item, NULL);
- if (tmp == NULL)
- tmp = "Application";
- gs_app_set_name (app, GS_APP_QUALITY_NORMAL, tmp);
- tmp = as_app_get_comment (item, NULL);
- if (tmp == NULL)
- tmp = "Description";
- gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, tmp);
- tmp = as_app_get_description (item, NULL);
- if (tmp == NULL)
- tmp = "A multiline description";
- gs_app_set_description (app, GS_APP_QUALITY_NORMAL, tmp);
- ic = as_icon_new ();
- as_icon_set_kind (ic, AS_ICON_KIND_STOCK);
- as_icon_set_name (ic, "application-x-executable");
- gs_app_add_icon (app, ic);
- item_state = as_app_get_state (item);
- } else {
- GPtrArray *icons;
- g_debug ("found global app for %s", as_app_get_id (item));
- gs_app_set_name (app, GS_APP_QUALITY_NORMAL,
- as_app_get_name (item_global, NULL));
- gs_app_set_summary (app, GS_APP_QUALITY_NORMAL,
- as_app_get_comment (item_global, NULL));
- gs_app_set_description (app, GS_APP_QUALITY_NORMAL,
- as_app_get_description (item_global, NULL));
- icons = as_app_get_icons (item_global);
- for (guint i = 0; i < icons->len; i++) {
- AsIcon *icon = g_ptr_array_index (icons, i);
- gs_app_add_icon (app, icon);
- }
- item_state = as_app_get_state (item_global);
}
/* copy state */
- if (item_state == AS_APP_STATE_UNKNOWN)
- item_state = AS_APP_STATE_AVAILABLE;
- gs_app_set_state (app, item_state);
-
- /* copy version */
- gs_app_set_version (app, "3.28");
-
- /* load pixbuf */
- gs_editor_refine_app_pixbuf (app);
-
- /* copy metadata */
- for (guint i = 0; keys[i] != NULL; i++) {
- g_autoptr(GError) error = NULL;
- const gchar *markup = as_app_get_metadata_item (item, keys[i]);
- if (markup != NULL) {
- g_autofree gchar *css_new = NULL;
- css_new = gs_editor_css_download_resources (self, markup, &error);
- if (css_new == NULL) {
- g_warning ("%s", error->message);
- gs_app_set_metadata (app, keys[i], markup);
- } else {
- gs_app_set_metadata (app, keys[i], css_new);
- }
- } else {
- gs_app_set_metadata (app, keys[i], NULL);
- }
- }
- return app;
+ gs_app_set_name (app, GS_APP_QUALITY_NORMAL,
+ gs_app_get_name (global_app));
+ gs_app_set_summary (app, GS_APP_QUALITY_NORMAL,
+ gs_app_get_summary (global_app));
+ gs_app_set_description (app, GS_APP_QUALITY_NORMAL,
+ gs_app_get_description (global_app));
+ gs_app_set_version (app, gs_app_get_version (global_app));
+ gs_app_set_state (app, gs_app_get_state (global_app));
+ gs_app_set_pixbuf (app, gs_app_get_pixbuf (global_app));
}
static void
@@ -192,25 +230,18 @@ gs_editor_refresh_details (GsEditor *self)
GtkWidget *widget;
const gchar *css = NULL;
g_autoptr(GError) error = NULL;
- g_autoptr(GsApp) app = NULL;
/* ignore changed events */
self->is_in_refresh = TRUE;
- /* create a GsApp for the AsApp */
- if (self->selected_item != NULL) {
- app = gs_editor_convert_app (self, self->selected_item);
- g_debug ("refreshing details for %s", gs_app_get_id (app));
- }
-
/* get kind */
- if (self->selected_item != NULL)
- app_kind = as_app_get_kind (self->selected_item);
+ if (self->selected_app != NULL)
+ app_kind = gs_app_get_kind (self->selected_app);
/* feature tiles */
if (app_kind != AS_APP_KIND_OS_UPGRADE) {
- if (self->selected_item != NULL) {
- gs_app_tile_set_app (GS_APP_TILE (self->featured_tile1), app);
+ if (self->selected_app != NULL) {
+ gs_app_tile_set_app (GS_APP_TILE (self->featured_tile1), self->selected_app);
gtk_widget_set_sensitive (self->featured_tile1, TRUE);
} else {
gtk_widget_set_sensitive (self->featured_tile1, FALSE);
@@ -222,8 +253,8 @@ gs_editor_refresh_details (GsEditor *self)
/* upgrade banner */
if (app_kind == AS_APP_KIND_OS_UPGRADE) {
- if (self->selected_item != NULL) {
- gs_upgrade_banner_set_app (GS_UPGRADE_BANNER (self->upgrade_banner), app);
+ if (self->selected_app != NULL) {
+ gs_upgrade_banner_set_app (GS_UPGRADE_BANNER (self->upgrade_banner),
self->selected_app);
gtk_widget_set_sensitive (self->upgrade_banner, TRUE);
} else {
gtk_widget_set_sensitive (self->upgrade_banner, FALSE);
@@ -235,11 +266,11 @@ gs_editor_refresh_details (GsEditor *self)
/* name */
widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "box_name"));
- if (self->selected_item != NULL) {
+ if (self->selected_app != NULL) {
const gchar *tmp;
gtk_widget_set_visible (widget, app_kind == AS_APP_KIND_OS_UPGRADE);
widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "entry_name"));
- tmp = as_app_get_name (self->selected_item, NULL);
+ tmp = gs_app_get_name (self->selected_app);
if (tmp != NULL)
gtk_entry_set_text (GTK_ENTRY (widget), tmp);
} else {
@@ -248,11 +279,11 @@ gs_editor_refresh_details (GsEditor *self)
/* summary */
widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "box_summary"));
- if (self->selected_item != NULL) {
+ if (self->selected_app != NULL) {
const gchar *tmp;
gtk_widget_set_visible (widget, app_kind == AS_APP_KIND_OS_UPGRADE);
widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "entry_summary"));
- tmp = as_app_get_comment (self->selected_item, NULL);
+ tmp = gs_app_get_summary (self->selected_app);
if (tmp != NULL)
gtk_entry_set_text (GTK_ENTRY (widget), tmp);
} else {
@@ -261,7 +292,7 @@ gs_editor_refresh_details (GsEditor *self)
/* kudos */
widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "box_kudos"));
- if (self->selected_item != NULL) {
+ if (self->selected_app != NULL) {
gtk_widget_set_visible (widget, app_kind != AS_APP_KIND_OS_UPGRADE);
} else {
gtk_widget_set_visible (widget, TRUE);
@@ -269,10 +300,10 @@ gs_editor_refresh_details (GsEditor *self)
/* category featured */
widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "checkbutton_category_featured"));
- if (self->selected_item != NULL) {
+ if (self->selected_app != NULL) {
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget),
- as_app_has_category (self->selected_item,
- "Featured"));
+ gs_app_has_kudo (self->selected_app,
+ GS_APP_KUDO_FEATURED_RECOMMENDED));
gtk_widget_set_sensitive (widget, TRUE);
} else {
gtk_widget_set_sensitive (widget, FALSE);
@@ -280,10 +311,10 @@ gs_editor_refresh_details (GsEditor *self)
/* kudo popular */
widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "checkbutton_editors_pick"));
- if (self->selected_item != NULL) {
+ if (self->selected_app != NULL) {
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget),
- as_app_has_kudo (self->selected_item,
- "GnomeSoftware::popular"));
+ gs_app_has_kudo (self->selected_app,
+ GS_APP_KUDO_POPULAR));
gtk_widget_set_sensitive (widget, TRUE);
} else {
gtk_widget_set_sensitive (widget, FALSE);
@@ -291,17 +322,17 @@ gs_editor_refresh_details (GsEditor *self)
/* featured */
widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "textview_css"));
- if (self->selected_item != NULL) {
+ if (self->selected_app != NULL) {
GtkTextBuffer *buffer;
GtkTextIter iter_end;
GtkTextIter iter_start;
g_autofree gchar *css_existing = NULL;
if (app_kind == AS_APP_KIND_OS_UPGRADE) {
- css = as_app_get_metadata_item (self->selected_item,
+ css = gs_app_get_metadata_item (self->selected_app,
"GnomeSoftware::UpgradeBanner-css");
} else {
- css = as_app_get_metadata_item (self->selected_item,
+ css = gs_app_get_metadata_item (self->selected_app,
"GnomeSoftware::FeatureTile-css");
}
if (css == NULL)
@@ -318,8 +349,8 @@ gs_editor_refresh_details (GsEditor *self)
/* desktop ID */
widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "entry_desktop_id"));
- if (self->selected_item != NULL) {
- const gchar *id = as_app_get_id (self->selected_item);
+ if (self->selected_app != NULL) {
+ const gchar *id = gs_app_get_id (self->selected_app);
if (id == NULL)
id = "";
gtk_entry_set_text (GTK_ENTRY (widget), id);
@@ -362,6 +393,41 @@ gs_design_dialog_refresh_details_delayed_cb (gpointer user_data)
return FALSE;
}
+static XbSilo *
+gs_editor_build_silo_from_apps (GsEditor *self)
+{
+ g_autoptr(XbBuilder) builder = xb_builder_new ();
+ g_autoptr(XbBuilderNode) components = xb_builder_node_new ("components");
+
+ /* add all apps */
+ for (guint i = 0; i < gs_app_list_length (self->store); i++) {
+ GsApp *app = gs_app_list_index (self->store, i);
+ g_autoptr(XbBuilderNode) component = gs_editor_app_to_node (app);
+ xb_builder_node_add_child (components, component);
+ }
+ xb_builder_import_node (builder, components);
+
+ return xb_builder_compile (builder, XB_BUILDER_COMPILE_FLAG_NONE, NULL, NULL);
+}
+
+static void
+gs_editor_autosave (GsEditor *self)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(XbSilo) silo = gs_editor_build_silo_from_apps (self);
+ g_debug ("autosaving silo");
+ if (!xb_silo_save_to_file (silo, self->autosave_file, NULL, &error))
+ g_warning ("failed to autosave: %s", error->message);
+}
+
+static gboolean
+gs_editor_autosave_cb (gpointer user_data)
+{
+ GsEditor *self = (GsEditor *) user_data;
+ gs_editor_autosave (self);
+ return TRUE;
+}
+
static void
gs_design_dialog_refresh_details_delayed (GsEditor *self)
{
@@ -385,12 +451,12 @@ gs_design_dialog_buffer_changed_cb (GtkTextBuffer *buffer, GsEditor *self)
gtk_text_buffer_get_bounds (buffer, &iter_start, &iter_end);
css = gtk_text_buffer_get_text (buffer, &iter_start, &iter_end, FALSE);
g_debug ("CSS now '%s'", css);
- if (as_app_get_kind (self->selected_item) == AS_APP_KIND_OS_UPGRADE) {
- as_app_add_metadata (self->selected_item, "GnomeSoftware::UpgradeBanner-css", NULL);
- as_app_add_metadata (self->selected_item, "GnomeSoftware::UpgradeBanner-css", css);
+ if (gs_app_get_kind (self->selected_app) == AS_APP_KIND_OS_UPGRADE) {
+ gs_app_set_metadata (self->selected_app, "GnomeSoftware::UpgradeBanner-css", NULL);
+ gs_app_set_metadata (self->selected_app, "GnomeSoftware::UpgradeBanner-css", css);
} else {
- as_app_add_metadata (self->selected_item, "GnomeSoftware::FeatureTile-css", NULL);
- as_app_add_metadata (self->selected_item, "GnomeSoftware::FeatureTile-css", css);
+ gs_app_set_metadata (self->selected_app, "GnomeSoftware::FeatureTile-css", NULL);
+ gs_app_set_metadata (self->selected_app, "GnomeSoftware::FeatureTile-css", css);
}
self->pending_changes = TRUE;
gs_design_dialog_refresh_details_delayed (self);
@@ -452,13 +518,7 @@ static void
gs_editor_app_tile_clicked_cb (GsAppTile *tile, GsEditor *self)
{
GsApp *app = gs_app_tile_get_app (tile);
- AsApp *item = as_store_get_app_by_id (self->store, gs_app_get_id (app));
- if (item == NULL) {
- g_warning ("failed to find %s", gs_app_get_id (app));
- return;
- }
- g_set_object (&self->selected_item, item);
-
+ g_set_object (&self->selected_app, app);
gs_editor_refresh_details (self);
gs_editor_set_page (self, "details");
}
@@ -466,21 +526,15 @@ gs_editor_app_tile_clicked_cb (GsAppTile *tile, GsEditor *self)
static void
gs_editor_refresh_choice (GsEditor *self)
{
- GPtrArray *apps;
GtkContainer *container;
/* add all apps */
container = GTK_CONTAINER (gtk_builder_get_object (self->builder,
"flowbox_main"));
gs_container_remove_all (GTK_CONTAINER (container));
- apps = as_store_get_apps (self->store);
- for (guint i = 0; i < apps->len; i++) {
- AsApp *item = g_ptr_array_index (apps, i);
- GtkWidget *tile = NULL;
- g_autoptr(GsApp) app = NULL;
-
- app = gs_editor_convert_app (self, item);
- tile = gs_summary_tile_new (app);
+ for (guint i = 0; i < gs_app_list_length (self->store); i++) {
+ GsApp *app = gs_app_list_index (self->store, i);
+ GtkWidget *tile = gs_summary_tile_new (app);
g_signal_connect (tile, "clicked",
G_CALLBACK (gs_editor_app_tile_clicked_cb),
self);
@@ -493,28 +547,10 @@ gs_editor_refresh_choice (GsEditor *self)
}
}
-static void
-gs_editor_error_message (GsEditor *self, const gchar *title, const gchar *message)
-{
- GtkWidget *dialog;
- GtkWindow *window;
- window = GTK_WINDOW (gtk_builder_get_object (self->builder, "window_main"));
- dialog = gtk_message_dialog_new (window,
- GTK_DIALOG_MODAL |
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_WARNING,
- GTK_BUTTONS_OK,
- "%s", title);
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
- "%s", message);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
-}
-
static void
gs_editor_button_back_clicked_cb (GtkWidget *widget, GsEditor *self)
{
- gs_editor_set_page (self, as_store_get_size (self->store) == 0 ? "none" : "choice");
+ gs_editor_set_page (self, gs_app_list_length (self->store) == 0 ? "none" : "choice");
}
static void
@@ -539,26 +575,110 @@ gs_editor_refresh_file (GsEditor *self, GFile *file)
}
}
+static void
+gs_search_page_app_search_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GsApp) app = GS_APP (user_data);
+ g_autoptr(GsAppList) list = NULL;
+
+ list = gs_plugin_loader_job_process_finish (GS_PLUGIN_LOADER (source_object), res, &error);
+ if (list == NULL) {
+ if (g_error_matches (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_CANCELLED))
+ return;
+ g_warning ("failed to get search app: %s", error->message);
+ return;
+ }
+ for (guint i = 0; i < gs_app_list_length (list); i++) {
+ GsApp *app_tmp = gs_app_list_index (list, i);
+ if (g_strcmp0 (gs_app_get_id (app), gs_app_get_id (app_tmp)) == 0) {
+ gs_editor_copy_from_global_app (app, app_tmp);
+ return;
+ }
+ }
+ if (gs_app_list_length (list) > 0) {
+ GsApp *app_tmp = gs_app_list_index (list, 0);
+ gs_editor_copy_from_global_app (app, app_tmp);
+ }
+}
+
+static void
+gs_editor_plugin_app_search (GsEditor *self, GsApp *app)
+{
+ g_autoptr(GsPluginJob) plugin_job = NULL;
+ plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_SEARCH,
+ "search", gs_app_get_id (app),
+ "max-results", 20,
+ "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_SETUP_ACTION |
+ GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON,
+ NULL);
+ gs_plugin_loader_job_process_async (self->plugin_loader, plugin_job, NULL,
+ gs_search_page_app_search_cb,
+ g_object_ref (app));
+}
+
+static gboolean
+gs_editor_appstream_upgrade_cb (XbBuilderFixup *self,
+ XbBuilderNode *bn,
+ gpointer user_data,
+ GError **error)
+{
+ if (g_strcmp0 (xb_builder_node_get_element (bn), "metadata") == 0)
+ xb_builder_node_set_element (bn, "custom");
+ return TRUE;
+}
+
static void
gs_editor_button_import_file (GsEditor *self, GFile *file)
{
g_autoptr(GError) error = NULL;
+ g_autoptr(XbSilo) silo = NULL;
+ g_autoptr(XbBuilder) builder = xb_builder_new ();
+ g_autoptr(XbBuilderFixup) fixup = NULL;
+ g_autoptr(XbBuilderSource) source = xb_builder_source_new ();
/* load new file */
- if (!as_store_from_file (self->store, file, NULL, NULL, &error)) {
+ if (!xb_builder_source_load_file (source, file,
+ XB_BUILDER_SOURCE_FLAG_LITERAL_TEXT,
+ NULL, &error)) {
/* TRANSLATORS: error dialog title */
gs_editor_error_message (self, _("Failed to load file"), error->message);
return;
}
+ /* fix up any legacy installed files */
+ fixup = xb_builder_fixup_new ("AppStreamUpgrade",
+ gs_editor_appstream_upgrade_cb,
+ self, NULL);
+ xb_builder_fixup_set_max_depth (fixup, 3);
+ xb_builder_source_add_fixup (source, fixup);
+
+ xb_builder_import_source (builder, source);
+ silo = xb_builder_compile (builder, XB_BUILDER_COMPILE_FLAG_NONE, NULL, &error);
+ if (silo == NULL) {
+ /* TRANSLATORS: error dialog title */
+ gs_editor_error_message (self, _("Failed to load file"), error->message);
+ return;
+ }
+
+ /* add applications */
+ gs_editor_add_nodes_from_silo (self, silo);
+
/* update listview */
gs_editor_refresh_choice (self);
gs_editor_refresh_file (self, file);
+ /* set the global app state */
+ for (guint i = 0; i < gs_app_list_length (self->store); i++) {
+ GsApp *app = gs_app_list_index (self->store, i);
+ gs_editor_plugin_app_search (self, app);
+ }
+
/* set the appropriate page */
- gs_editor_set_page (self, as_store_get_size (self->store) == 0 ? "none" : "choice");
+ gs_editor_set_page (self, gs_app_list_length (self->store) == 0 ? "none" : "choice");
/* reset */
+ gs_editor_autosave (self);
self->pending_changes = FALSE;
}
@@ -574,7 +694,7 @@ gs_editor_button_import_clicked_cb (GtkApplication *application, GsEditor *self)
/* import warning */
window = GTK_WINDOW (gtk_builder_get_object (self->builder,
"window_main"));
- if (as_store_get_size (self->store) > 0) {
+ if (gs_app_list_length (self->store) > 0) {
dialog = gtk_message_dialog_new (window,
GTK_DIALOG_MODAL |
GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -599,7 +719,7 @@ gs_editor_button_import_clicked_cb (GtkApplication *application, GsEditor *self)
if (res == GTK_RESPONSE_CANCEL)
return;
if (res == GTK_RESPONSE_YES)
- as_store_remove_all (self->store);
+ gs_app_list_remove_all (self->store);
}
/* import the new file */
@@ -631,11 +751,12 @@ gs_editor_button_save_clicked_cb (GtkApplication *application, GsEditor *self)
gint res;
g_autoptr(GError) error = NULL;
g_autoptr(GFile) file = NULL;
+ g_autoptr(XbSilo) silo = NULL;
/* export a new file */
window = GTK_WINDOW (gtk_builder_get_object (self->builder,
"window_main"));
- dialog = gtk_file_chooser_dialog_new (_("Open AppStream File"),
+ dialog = gtk_file_chooser_dialog_new (_("Save AppStream File"),
window,
GTK_FILE_CHOOSER_ACTION_SAVE,
_("_Cancel"), GTK_RESPONSE_CANCEL,
@@ -651,17 +772,19 @@ gs_editor_button_save_clicked_cb (GtkApplication *application, GsEditor *self)
}
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
gtk_widget_destroy (dialog);
- if (!as_store_to_file (self->store,
- file,
- AS_NODE_TO_XML_FLAG_ADD_HEADER |
- AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE |
- AS_NODE_TO_XML_FLAG_FORMAT_INDENT,
- self->cancellable,
- &error)) {
+
+ /* export as XML */
+ silo = gs_editor_build_silo_from_apps (self);
+ if (!xb_silo_export_file (silo, file,
+ XB_NODE_EXPORT_FLAG_ADD_HEADER |
+ XB_NODE_EXPORT_FLAG_FORMAT_MULTILINE |
+ XB_NODE_EXPORT_FLAG_FORMAT_INDENT,
+ NULL, &error)) {
/* TRANSLATORS: error dialog title */
gs_editor_error_message (self, _("Failed to save file"), error->message);
return;
}
+
self->pending_changes = FALSE;
gs_editor_refresh_file (self, file);
gs_editor_refresh_details (self);
@@ -695,13 +818,13 @@ gs_editor_button_notification_dismiss_clicked_cb (GtkWidget *widget, GsEditor *s
static void
gs_editor_button_undo_remove_clicked_cb (GtkWidget *widget, GsEditor *self)
{
- if (self->deleted_item == NULL)
+ if (self->deleted_app == NULL)
return;
/* add this back to the store and set it as current */
- as_store_add_app (self->store, self->deleted_item);
- g_set_object (&self->selected_item, self->deleted_item);
- g_clear_object (&self->deleted_item);
+ gs_app_list_add (self->store, self->deleted_app);
+ g_set_object (&self->selected_app, self->deleted_app);
+ g_clear_object (&self->deleted_app);
/* hide notification */
widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "revealer_notification"));
@@ -719,17 +842,11 @@ gs_editor_button_remove_clicked_cb (GtkWidget *widget, GsEditor *self)
const gchar *name;
g_autofree gchar *msg = NULL;
- if (self->selected_item == NULL)
+ if (self->selected_app == NULL)
return;
/* send notification */
- name = as_app_get_name (self->selected_item, NULL);
- if (name == NULL) {
- AsApp *item_global = as_store_get_app_by_id (self->store_global,
- as_app_get_id (self->selected_item));
- if (item_global != NULL)
- name = as_app_get_name (item_global, NULL);
- }
+ name = gs_app_get_name (self->selected_app);
if (name != NULL) {
g_autofree gchar *name_markup = NULL;
name_markup = g_strdup_printf ("<b>%s</b>", name);
@@ -742,14 +859,14 @@ gs_editor_button_remove_clicked_cb (GtkWidget *widget, GsEditor *self)
gs_editor_show_notification (self, msg);
/* save this so we can undo */
- g_set_object (&self->deleted_item, self->selected_item);
+ g_set_object (&self->deleted_app, self->selected_app);
- as_store_remove_app_by_id (self->store, as_app_get_id (self->selected_item));
+ gs_app_list_remove (self->store, self->selected_app);
self->pending_changes = TRUE;
gs_editor_refresh_choice (self);
/* set the appropriate page */
- gs_editor_set_page (self, as_store_get_size (self->store) == 0 ? "none" : "choice");
+ gs_editor_set_page (self, gs_app_list_length (self->store) == 0 ? "none" : "choice");
}
static void
@@ -758,13 +875,13 @@ gs_editor_checkbutton_editors_pick_cb (GtkToggleButton *widget, GsEditor *self)
/* ignore, self change */
if (self->is_in_refresh)
return;
- if (self->selected_item == NULL)
+ if (self->selected_app == NULL)
return;
if (gtk_toggle_button_get_active (widget)) {
- as_app_add_kudo (self->selected_item, "GnomeSoftware::popular");
+ gs_app_add_kudo (self->selected_app, GS_APP_KUDO_POPULAR);
} else {
- as_app_remove_kudo (self->selected_item, "GnomeSoftware::popular");
+ gs_app_remove_kudo (self->selected_app, GS_APP_KUDO_POPULAR);
}
self->pending_changes = TRUE;
gs_editor_refresh_details (self);
@@ -776,33 +893,108 @@ gs_editor_checkbutton_category_featured_cb (GtkToggleButton *widget, GsEditor *s
/* ignore, self change */
if (self->is_in_refresh)
return;
- if (self->selected_item == NULL)
+ if (self->selected_app == NULL)
return;
if (gtk_toggle_button_get_active (widget)) {
- as_app_add_category (self->selected_item, "Featured");
+ gs_app_add_kudo (self->selected_app, GS_APP_KUDO_FEATURED_RECOMMENDED);
} else {
- as_app_remove_category (self->selected_item, "Featured");
+ gs_app_remove_kudo (self->selected_app, GS_APP_KUDO_FEATURED_RECOMMENDED);
}
self->pending_changes = TRUE;
gs_editor_refresh_details (self);
}
+static gboolean
+gs_editor_get_search_filter_id_prefix_cb (GsApp *app, gpointer user_data)
+{
+ const gchar *id = (const gchar *) user_data;
+ return g_str_has_prefix (gs_app_get_id (app), id);
+}
+
+static void
+gs_editor_get_search_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ GsEditor *self = (GsEditor *) user_data;
+ GtkListStore *store;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GsAppList) list = NULL;
+
+ /* get apps */
+ list = gs_plugin_loader_job_process_finish (self->plugin_loader, res, &error);
+ if (list == NULL) {
+ if (g_error_matches (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_CANCELLED))
+ return;
+ g_warning ("failed to get search apps: %s", error->message);
+ return;
+ }
+
+ /* only include the apps with the right ID prefix */
+ gs_app_list_filter (list,
+ gs_editor_get_search_filter_id_prefix_cb,
+ gs_app_get_id (self->selected_app));
+
+ /* load all the IDs into the completion model */
+ store = GTK_LIST_STORE (gtk_builder_get_object (self->builder, "liststore_ids"));
+ gtk_list_store_clear (store);
+ if (gs_app_list_length (list) == 1) {
+ GsApp *app = gs_app_list_index (list, 0);
+ GtkWidget *w = GTK_WIDGET (gtk_builder_get_object (self->builder, "entry_desktop_id"));
+ g_debug ("forcing completion: %s", gs_app_get_id (app));
+ gtk_entry_set_text (GTK_ENTRY (w), gs_app_get_id (app));
+ } else if (gs_app_list_length (list) > 0) {
+ for (guint i = 0; i < gs_app_list_length (list); i++) {
+ GsApp *app = gs_app_list_index (list, i);
+ GtkTreeIter iter;
+ gtk_list_store_append (store, &iter);
+ g_debug ("adding completion: %s", gs_app_get_id (app));
+ gtk_list_store_set (store, &iter, 0, gs_app_get_id (app), -1);
+ }
+ } else {
+ g_debug ("nothing found");
+ }
+
+ /* get the "best" application for the icon and description */
+ if (gs_app_list_length (list) > 0) {
+ GsApp *app = gs_app_list_index (list, 0);
+ g_debug ("setting global app %s", gs_app_get_unique_id (app));
+ gs_editor_copy_from_global_app (self->selected_app, app);
+ } else {
+ gs_editor_copy_from_global_app (self->selected_app, NULL);
+ }
+ gs_editor_refresh_details (self);
+}
+
static void
gs_editor_entry_desktop_id_notify_cb (GtkEntry *entry, GParamSpec *pspec, GsEditor *self)
{
+ const gchar *tmp;
+
/* ignore, self change */
if (self->is_in_refresh)
return;
- if (self->selected_item == NULL)
+ if (self->selected_app == NULL)
return;
- /* check the name does not already exist */
+ /* get the new list of possible apps */
+ tmp = gtk_entry_get_text (entry);
+ if (tmp != NULL && strlen (tmp) > 3) {
+ g_autoptr(GsPluginJob) plugin_job = NULL;
+ plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_SEARCH,
+ "search", tmp,
+ "max-results", 20,
+ "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_SETUP_ACTION |
+ GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON,
+ NULL);
+ gs_plugin_loader_job_process_async (self->plugin_loader, plugin_job, NULL,
+ gs_editor_get_search_cb,
+ self);
+ }
+
+ /* check the ID does not already exist */
//FIXME
- as_store_remove_app (self->store, self->selected_item);
- as_app_set_id (self->selected_item, gtk_entry_get_text (entry));
- as_store_add_app (self->store, self->selected_item);
+ gs_app_set_id (self->selected_app, tmp);
self->pending_changes = TRUE;
gs_editor_refresh_choice (self);
@@ -815,10 +1007,10 @@ gs_editor_entry_name_notify_cb (GtkEntry *entry, GParamSpec *pspec, GsEditor *se
/* ignore, self change */
if (self->is_in_refresh)
return;
- if (self->selected_item == NULL)
+ if (self->selected_app == NULL)
return;
- as_app_set_name (self->selected_item, NULL, gtk_entry_get_text (entry));
+ gs_app_set_name (self->selected_app, GS_APP_QUALITY_NORMAL, gtk_entry_get_text (entry));
self->pending_changes = TRUE;
gs_editor_refresh_choice (self);
@@ -831,10 +1023,10 @@ gs_editor_entry_summary_notify_cb (GtkEntry *entry, GParamSpec *pspec, GsEditor
/* ignore, self change */
if (self->is_in_refresh)
return;
- if (self->selected_item == NULL)
+ if (self->selected_app == NULL)
return;
- as_app_set_comment (self->selected_item, NULL, gtk_entry_get_text (entry));
+ gs_app_set_summary (self->selected_app, GS_APP_QUALITY_NORMAL, gtk_entry_get_text (entry));
self->pending_changes = TRUE;
gs_editor_refresh_choice (self);
@@ -880,39 +1072,23 @@ gs_editor_flow_box_sort_cb (GtkFlowBoxChild *row1, GtkFlowBoxChild *row2, gpoint
gs_app_get_name (gs_app_tile_get_app (tile2)));
}
-static void
-gs_editor_load_completion_model (GsEditor *self)
-{
- GPtrArray *apps;
- GtkListStore *store;
- GtkTreeIter iter;
-
- store = GTK_LIST_STORE (gtk_builder_get_object (self->builder, "liststore_ids"));
- apps = as_store_get_apps (self->store_global);
- for (guint i = 0; i < apps->len; i++) {
- AsApp *item = g_ptr_array_index (apps, i);
- gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter, 0, as_app_get_id (item), -1);
- }
-}
-
static void
gs_editor_button_new_feature_clicked_cb (GtkApplication *application, GsEditor *self)
{
g_autofree gchar *id = NULL;
- g_autoptr(AsApp) item = as_app_new ();
+ g_autoptr(GsApp) app = gs_app_new (NULL);
const gchar *css = "border: 1px solid #808080;\nbackground: #eee;\ncolor: #000;";
/* add new app */
- as_app_set_kind (item, AS_APP_KIND_DESKTOP);
+ gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
id = g_strdup_printf ("example-%04x.desktop",
(guint) g_random_int_range (0x0000, 0xffff));
- as_app_set_id (item, id);
- as_app_add_metadata (item, "GnomeSoftware::FeatureTile-css", css);
- as_app_add_kudo (item, "GnomeSoftware::popular");
- as_app_add_category (item, "Featured");
- as_store_add_app (self->store, item);
- g_set_object (&self->selected_item, item);
+ gs_app_set_id (app, id);
+ gs_app_set_metadata (app, "GnomeSoftware::FeatureTile-css", css);
+ gs_app_add_kudo (app, GS_APP_KUDO_POPULAR);
+ gs_app_add_kudo (app, GS_APP_KUDO_FEATURED_RECOMMENDED);
+ gs_app_list_add (self->store, app);
+ g_set_object (&self->selected_app, app);
self->pending_changes = TRUE;
gs_editor_refresh_choice (self);
@@ -923,18 +1099,19 @@ gs_editor_button_new_feature_clicked_cb (GtkApplication *application, GsEditor *
static void
gs_editor_button_new_os_upgrade_clicked_cb (GtkApplication *application, GsEditor *self)
{
- g_autoptr(AsApp) item = as_app_new ();
+ g_autoptr(GsApp) app = gs_app_new (NULL);
const gchar *css = "border: 1px solid #808080;\nbackground: #fffeee;\ncolor: #000;";
/* add new app */
- as_app_set_kind (item, AS_APP_KIND_OS_UPGRADE);
- as_app_set_state (item, AS_APP_STATE_AVAILABLE);
- as_app_set_id (item, "org.gnome.release");
- as_app_set_name (item, NULL, "GNOME");
- as_app_set_comment (item, NULL, "A major upgrade, with new features and added polish.");
- as_app_add_metadata (item, "GnomeSoftware::UpgradeBanner-css", css);
- as_store_add_app (self->store, item);
- g_set_object (&self->selected_item, item);
+ gs_app_set_kind (app, AS_APP_KIND_OS_UPGRADE);
+ gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
+ gs_app_set_id (app, "org.gnome.release");
+ gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "GNOME");
+ gs_app_set_version (app, "3.40");
+ gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "A major upgrade, with new features and added
polish.");
+ gs_app_set_metadata (app, "GnomeSoftware::UpgradeBanner-css", css);
+ gs_app_list_add (self->store, app);
+ g_set_object (&self->selected_app, app);
self->pending_changes = TRUE;
gs_editor_refresh_choice (self);
@@ -955,8 +1132,8 @@ gs_editor_startup_cb (GtkApplication *application, GsEditor *self)
GtkTextBuffer *buffer;
GtkWidget *main_window;
GtkWidget *widget;
- gboolean ret;
guint retval;
+ g_autofree gchar *fn = NULL;
g_autoptr(GError) error = NULL;
/* get UI */
@@ -968,23 +1145,14 @@ gs_editor_startup_cb (GtkApplication *application, GsEditor *self)
return;
}
- /* load all system appstream */
- as_store_set_add_flags (self->store_global, AS_STORE_ADD_FLAG_USE_MERGE_HEURISTIC);
- ret = as_store_load (self->store_global,
- AS_STORE_LOAD_FLAG_IGNORE_INVALID |
- AS_STORE_LOAD_FLAG_APP_INFO_SYSTEM |
- AS_STORE_LOAD_FLAG_APPDATA |
- AS_STORE_LOAD_FLAG_DESKTOP,
- self->cancellable,
- &error);
- if (!ret) {
- g_warning ("failed to load global store: %s", error->message);
+ self->plugin_loader = gs_plugin_loader_new ();
+ if (g_file_test (LOCALPLUGINDIR, G_FILE_TEST_EXISTS))
+ gs_plugin_loader_add_location (self->plugin_loader, LOCALPLUGINDIR);
+ if (!gs_plugin_loader_setup (self->plugin_loader, NULL, NULL, NULL, &error)) {
+ g_warning ("Failed to setup plugins: %s", error->message);
return;
}
- /* load all the IDs into the completion model */
- gs_editor_load_completion_model (self);
-
self->featured_tile1 = gs_feature_tile_new (NULL);
self->upgrade_banner = gs_upgrade_banner_new ();
widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "box_featured"));
@@ -1066,13 +1234,34 @@ gs_editor_startup_cb (GtkApplication *application, GsEditor *self)
g_signal_connect (widget, "delete_event",
G_CALLBACK (gs_editor_delete_event_cb), self);
+ /* load last saved state */
+ fn = gs_utils_get_cache_filename ("editor", "autosave.xmlb",
+ GS_UTILS_CACHE_FLAG_WRITEABLE, &error);
+ if (fn == NULL) {
+ g_warning ("Failed to get cache location: %s", error->message);
+ return;
+ }
+ self->autosave_file = g_file_new_for_path (fn);
+ if (g_file_query_exists (self->autosave_file, NULL)) {
+ g_autoptr(XbSilo) silo = xb_silo_new ();
+ g_debug ("loading apps from %s", fn);
+ if (!xb_silo_load_from_file (silo, self->autosave_file,
+ XB_SILO_LOAD_FLAG_NONE, NULL, &error))
+ g_warning ("Failed to load silo: %s", error->message);
+ gs_editor_add_nodes_from_silo (self, silo);
+ for (guint i = 0; i < gs_app_list_length (self->store); i++) {
+ GsApp *app = gs_app_list_index (self->store, i);
+ gs_editor_plugin_app_search (self, app);
+ }
+ }
+
/* clear entries */
gs_editor_refresh_choice (self);
gs_editor_refresh_details (self);
gs_editor_refresh_file (self, NULL);
/* set the appropriate page */
- gs_editor_set_page (self, "none");
+ gs_editor_set_page (self, gs_app_list_length (self->store) == 0 ? "none" : "choice");
main_window = GTK_WIDGET (gtk_builder_get_object (self->builder, "window_main"));
gtk_application_add_window (application, GTK_WINDOW (main_window));
@@ -1120,15 +1309,19 @@ gs_editor_commandline_cb (GApplication *application,
static void
gs_editor_self_free (GsEditor *self)
{
- if (self->selected_item != NULL)
- g_object_unref (self->selected_item);
- if (self->deleted_item != NULL)
- g_object_unref (self->deleted_item);
+ if (self->autosave_file != NULL)
+ g_object_unref (self->autosave_file);
+ if (self->selected_app != NULL)
+ g_object_unref (self->selected_app);
+ if (self->deleted_app != NULL)
+ g_object_unref (self->deleted_app);
if (self->refresh_details_delayed_id != 0)
g_source_remove (self->refresh_details_delayed_id);
+ if (self->autosave_id != 0)
+ g_source_remove (self->autosave_id);
+ g_object_unref (self->plugin_loader);
g_object_unref (self->cancellable);
g_object_unref (self->store);
- g_object_unref (self->store_global);
g_object_unref (self->builder);
g_free (self);
}
@@ -1151,10 +1344,8 @@ main (int argc, char *argv[])
self = g_new0 (GsEditor, 1);
self->cancellable = g_cancellable_new ();
self->builder = gtk_builder_new ();
- self->store = as_store_new ();
- as_store_set_add_flags (self->store, AS_STORE_ADD_FLAG_USE_UNIQUE_ID);
- self->store_global = as_store_new ();
- as_store_set_add_flags (self->store_global, AS_STORE_ADD_FLAG_USE_UNIQUE_ID);
+ self->store = gs_app_list_new ();
+ self->autosave_id = g_timeout_add_seconds (5, gs_editor_autosave_cb, self);
/* are we already activated? */
self->application = gtk_application_new ("org.gnome.Software.Editor",
diff --git a/src/meson.build b/src/meson.build
index e63fe104..ea8900ba 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -77,7 +77,8 @@ gnome_software_dependencies = [
gtk,
json_glib,
libm,
- libsoup
+ libsoup,
+ libxmlb,
]
if get_option('packagekit')
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]