[gnome-software] Break out common code for a list of updates in a separate class
- From: Kalev Lember <klember src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] Break out common code for a list of updates in a separate class
- Date: Wed, 14 May 2014 13:57:19 +0000 (UTC)
commit 1c6b7d6c69d8086178ffdf37b84d51bd9e00dda0
Author: Kalev Lember <kalevlember gmail com>
Date: Sun May 11 14:54:23 2014 +0200
Break out common code for a list of updates in a separate class
To share code between GsShellUpdates and GsUpdateDialog, break out a new
GsUpdateList widget.
po/POTFILES.in | 1 +
src/Makefile.am | 2 +
src/gs-shell-updates.c | 136 +-------------------------------
src/gs-shell-updates.ui | 2 +-
src/gs-update-dialog.c | 28 +------
src/gs-update-dialog.ui | 2 +-
src/gs-update-list.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++
src/gs-update-list.h | 61 ++++++++++++++
8 files changed, 273 insertions(+), 160 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index caff6c6..34ebddc 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -33,6 +33,7 @@ src/gs-sources-dialog.c
[type: gettext/glade]src/gs-sources-dialog.ui
src/gs-update-dialog.c
[type: gettext/glade]src/gs-update-dialog.ui
+src/gs-update-list.c
src/gs-update-monitor.c
[type: gettext/glade]src/gs-star-widget.ui
src/gs-utils.c
diff --git a/src/Makefile.am b/src/Makefile.am
index f821dba..0f9526c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -141,6 +141,8 @@ gnome_software_SOURCES = \
gs-sources-dialog.h \
gs-update-dialog.c \
gs-update-dialog.h \
+ gs-update-list.c \
+ gs-update-list.h \
gs-update-monitor.c \
gs-update-monitor.h \
gs-proxy-settings.c \
diff --git a/src/gs-shell-updates.c b/src/gs-shell-updates.c
index 9c3837e..11da685 100644
--- a/src/gs-shell-updates.c
+++ b/src/gs-shell-updates.c
@@ -31,6 +31,7 @@
#include "gs-app-row.h"
#include "gs-markdown.h"
#include "gs-update-dialog.h"
+#include "gs-update-list.h"
#include <gdesktop-enums.h>
#include <langinfo.h>
@@ -65,8 +66,6 @@ struct GsShellUpdatesPrivate
GsShellUpdatesState state;
gboolean has_agreed_to_mobile_data;
gboolean ampm_available;
- GtkSizeGroup *sizegroup_image;
- GtkSizeGroup *sizegroup_name;
GtkWidget *button_updates_mobile;
GtkWidget *button_updates_offline;
@@ -406,7 +405,6 @@ gs_shell_updates_get_updates_cb (GsPluginLoader *plugin_loader,
GError *error = NULL;
GList *l;
GList *list;
- GsApp *app;
GsShellUpdatesPrivate *priv = shell_updates->priv;
GtkWidget *widget;
@@ -457,15 +455,8 @@ gs_shell_updates_get_updates_cb (GsPluginLoader *plugin_loader,
GS_SHELL_UPDATES_STATE_HAS_UPDATES);
}
for (l = list; l != NULL; l = l->next) {
- app = GS_APP (l->data);
- widget = gs_app_row_new ();
- gs_app_row_set_show_update (GS_APP_ROW (widget), TRUE);
- gs_app_row_set_app (GS_APP_ROW (widget), app);
- gtk_container_add (GTK_CONTAINER (priv->list_box_updates), widget);
- gs_app_row_set_size_groups (GS_APP_ROW (widget),
- priv->sizegroup_image,
- priv->sizegroup_name);
- gtk_widget_show (widget);
+ gs_update_list_add_app (GS_UPDATE_LIST (priv->list_box_updates),
+ GS_APP (l->data));
}
out:
@@ -560,54 +551,6 @@ gs_shell_updates_activated_cb (GtkListBox *list_box,
}
/**
- * gs_shell_updates_is_addon_id_kind
- **/
-static gboolean
-gs_shell_updates_is_addon_id_kind (GsApp *app)
-{
- GsAppIdKind id_kind;
- id_kind = gs_app_get_id_kind (app);
- if (id_kind == GS_APP_ID_KIND_DESKTOP)
- return FALSE;
- if (id_kind == GS_APP_ID_KIND_WEBAPP)
- return FALSE;
- return TRUE;
-}
-
-/**
- * gs_shell_updates_list_header_func
- **/
-static void
-gs_shell_updates_list_header_func (GtkListBoxRow *row,
- GtkListBoxRow *before,
- gpointer user_data)
-{
- GtkStyleContext *context;
- GtkWidget *header;
-
- /* first entry */
- gtk_list_box_row_set_header (row, NULL);
- if (before == NULL)
- return;
-
- /* desktop -> addons */
- if (!gs_shell_updates_is_addon_id_kind (gs_app_row_get_app (GS_APP_ROW (before))) &&
- gs_shell_updates_is_addon_id_kind (gs_app_row_get_app (GS_APP_ROW (row)))) {
- /* TRANSLATORS: This is the header dividing the normal
- * applications and the addons */
- header = gtk_label_new (_("Add-ons"));
- g_object_set (header,
- "xalign", 0.0,
- NULL);
- context = gtk_widget_get_style_context (header);
- gtk_style_context_add_class (context, "header-label");
- } else {
- header = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
- }
- gtk_list_box_row_set_header (row, header);
-}
-
-/**
* gs_shell_updates_refresh_cb:
**/
static void
@@ -863,68 +806,6 @@ gs_shell_updates_button_update_all_cb (GtkButton *button,
}
/**
- * gs_shell_installed_sort_func:
- **/
-static gchar *
-gs_shell_updates_get_app_sort_key (GsApp *app)
-{
- GString *key;
-
- key = g_string_sized_new (64);
-
- /* sort by kind */
- switch (gs_app_get_kind (app)) {
- case GS_APP_KIND_OS_UPDATE:
- g_string_append (key, "1:");
- break;
- default:
- g_string_append (key, "2:");
- break;
- }
-
- /* sort desktop files, then addons */
- switch (gs_app_get_id_kind (app)) {
- case GS_APP_ID_KIND_DESKTOP:
- g_string_append (key, "1:");
- break;
- default:
- g_string_append (key, "2:");
- break;
- }
-
- /* sort by install date */
- g_string_append_printf (key, "%09" G_GUINT64_FORMAT ":",
- G_MAXUINT64 - gs_app_get_install_date (app));
-
- /* finally, sort by short name */
- g_string_append (key, gs_app_get_name (app));
- return g_string_free (key, FALSE);
-}
-
-/**
- * gs_shell_updates_sort_func:
- **/
-static gint
-gs_shell_updates_sort_func (GtkListBoxRow *a,
- GtkListBoxRow *b,
- gpointer user_data)
-{
- GsApp *a1 = gs_app_row_get_app (GS_APP_ROW (a));
- GsApp *a2 = gs_app_row_get_app (GS_APP_ROW (b));
- gchar *key1 = gs_shell_updates_get_app_sort_key (a1);
- gchar *key2 = gs_shell_updates_get_app_sort_key (a2);
- gint retval;
-
- /* compare the keys according to the algorithm above */
- retval = g_strcmp0 (key1, key2);
-
- g_free (key1);
- g_free (key2);
-
- return retval;
-}
-
-/**
* gs_shell_updates_get_properties_cb:
**/
static void
@@ -973,13 +854,6 @@ gs_shell_updates_setup (GsShellUpdates *shell_updates,
/* setup updates */
g_signal_connect (priv->list_box_updates, "row-activated",
G_CALLBACK (gs_shell_updates_activated_cb), shell_updates);
- gtk_list_box_set_header_func (GTK_LIST_BOX (priv->list_box_updates),
- gs_shell_updates_list_header_func,
- shell_updates,
- NULL);
- gtk_list_box_set_sort_func (GTK_LIST_BOX (priv->list_box_updates),
- gs_shell_updates_sort_func,
- shell_updates, NULL);
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_update_all"));
g_signal_connect (widget, "clicked", G_CALLBACK (gs_shell_updates_button_update_all_cb),
shell_updates);
@@ -1046,8 +920,6 @@ gs_shell_updates_init (GsShellUpdates *shell_updates)
shell_updates->priv->state = GS_SHELL_UPDATES_STATE_STARTUP;
shell_updates->priv->settings = g_settings_new ("org.gnome.software");
shell_updates->priv->desktop_settings = g_settings_new ("org.gnome.desktop.interface");
- shell_updates->priv->sizegroup_image = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
- shell_updates->priv->sizegroup_name = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
ampm = nl_langinfo (AM_STR);
if (ampm != NULL && *ampm != '\0')
@@ -1072,8 +944,6 @@ gs_shell_updates_finalize (GObject *object)
g_object_unref (priv->control);
g_object_unref (priv->settings);
g_object_unref (priv->desktop_settings);
- g_object_unref (priv->sizegroup_image);
- g_object_unref (priv->sizegroup_name);
G_OBJECT_CLASS (gs_shell_updates_parent_class)->finalize (object);
}
diff --git a/src/gs-shell-updates.ui b/src/gs-shell-updates.ui
index 684b348..6364e28 100644
--- a/src/gs-shell-updates.ui
+++ b/src/gs-shell-updates.ui
@@ -64,7 +64,7 @@
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
- <object class="GtkListBox" id="list_box_updates">
+ <object class="GsUpdateList" id="list_box_updates">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="selection_mode">none</property>
diff --git a/src/gs-update-dialog.c b/src/gs-update-dialog.c
index 86c2717..660575a 100644
--- a/src/gs-update-dialog.c
+++ b/src/gs-update-dialog.c
@@ -28,6 +28,7 @@
#include "gs-app-row.h"
#include "gs-markdown.h"
#include "gs-offline-updates.h"
+#include "gs-update-list.h"
#include "gs-utils.h"
typedef struct {
@@ -39,8 +40,6 @@ typedef struct {
struct _GsUpdateDialogPrivate
{
GQueue *back_entry_stack;
- GtkSizeGroup *sizegroup_image;
- GtkSizeGroup *sizegroup_name;
GtkWidget *box_header;
GtkWidget *button_back;
GtkWidget *image_icon;
@@ -160,8 +159,6 @@ gs_update_dialog_show_installed_updates (GsUpdateDialog *dialog, GList *installe
{
GsUpdateDialogPrivate *priv = gs_update_dialog_get_instance_private (dialog);
GList *l;
- GsApp *app;
- GtkWidget *widget;
guint64 time_updates_installed;
/* TRANSLATORS: this is the title of the installed updates dialog window */
@@ -190,15 +187,8 @@ gs_update_dialog_show_installed_updates (GsUpdateDialog *dialog, GList *installe
gs_container_remove_all (GTK_CONTAINER (priv->list_box_installed_updates));
for (l = installed_updates; l != NULL; l = l->next) {
- app = GS_APP (l->data);
- widget = gs_app_row_new ();
- gs_app_row_set_show_update (GS_APP_ROW (widget), TRUE);
- gs_app_row_set_app (GS_APP_ROW (widget), app);
- gtk_container_add (GTK_CONTAINER (priv->list_box_installed_updates), widget);
- gs_app_row_set_size_groups (GS_APP_ROW (widget),
- priv->sizegroup_image,
- priv->sizegroup_name);
- gtk_widget_show (widget);
+ gs_update_list_add_app (GS_UPDATE_LIST (priv->list_box_installed_updates),
+ GS_APP (l->data));
}
}
@@ -334,8 +324,6 @@ gs_update_dialog_finalize (GObject *object)
g_queue_free_full (priv->back_entry_stack, (GDestroyNotify) back_entry_free);
priv->back_entry_stack = NULL;
}
- g_object_unref (priv->sizegroup_image);
- g_object_unref (priv->sizegroup_name);
G_OBJECT_CLASS (gs_update_dialog_parent_class)->finalize (object);
}
@@ -349,8 +337,6 @@ gs_update_dialog_init (GsUpdateDialog *dialog)
gtk_widget_init_template (GTK_WIDGET (dialog));
priv->back_entry_stack = g_queue_new ();
- priv->sizegroup_image = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
- priv->sizegroup_name = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
g_signal_connect (GTK_LIST_BOX (priv->list_box), "row-activated",
G_CALLBACK (row_activated_cb), dialog);
@@ -363,14 +349,6 @@ gs_update_dialog_init (GsUpdateDialog *dialog)
g_signal_connect (GTK_LIST_BOX (priv->list_box_installed_updates), "row-activated",
G_CALLBACK (installed_updates_row_activated_cb), dialog);
- gtk_list_box_set_header_func (GTK_LIST_BOX (priv->list_box_installed_updates),
- list_header_func,
- dialog, NULL);
-#if 0
- gtk_list_box_set_sort_func (GTK_LIST_BOX (priv->list_box_updates),
- installed_updates_sort_func,
- dialog, NULL);
-#endif
g_signal_connect (priv->button_back, "clicked",
G_CALLBACK (button_back_cb),
diff --git a/src/gs-update-dialog.ui b/src/gs-update-dialog.ui
index 4d781db..1ea2ed6 100644
--- a/src/gs-update-dialog.ui
+++ b/src/gs-update-dialog.ui
@@ -217,7 +217,7 @@
<class name="view"/>
</style>
<child>
- <object class="GtkListBox" id="list_box_installed_updates">
+ <object class="GsUpdateList" id="list_box_installed_updates">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="selection_mode">none</property>
diff --git a/src/gs-update-list.c b/src/gs-update-list.c
new file mode 100644
index 0000000..ab92eba
--- /dev/null
+++ b/src/gs-update-list.c
@@ -0,0 +1,201 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013-2014 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gs-update-list.h"
+
+#include "gs-app.h"
+#include "gs-app-row.h"
+
+struct _GsUpdateListPrivate
+{
+ GtkSizeGroup *sizegroup_image;
+ GtkSizeGroup *sizegroup_name;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GsUpdateList, gs_update_list, GTK_TYPE_LIST_BOX)
+
+void
+gs_update_list_add_app (GsUpdateList *update_list,
+ GsApp *app)
+{
+ GsUpdateListPrivate *priv = gs_update_list_get_instance_private (update_list);
+ GtkWidget *app_row;
+
+ app_row = gs_app_row_new ();
+ gs_app_row_set_show_update (GS_APP_ROW (app_row), TRUE);
+ gs_app_row_set_app (GS_APP_ROW (app_row), app);
+ gtk_container_add (GTK_CONTAINER (update_list), app_row);
+ gs_app_row_set_size_groups (GS_APP_ROW (app_row),
+ priv->sizegroup_image,
+ priv->sizegroup_name);
+ gtk_widget_show (app_row);
+}
+
+static gboolean
+is_addon_id_kind (GsApp *app)
+{
+ GsAppIdKind id_kind;
+ id_kind = gs_app_get_id_kind (app);
+ if (id_kind == GS_APP_ID_KIND_DESKTOP)
+ return FALSE;
+ if (id_kind == GS_APP_ID_KIND_WEBAPP)
+ return FALSE;
+ return TRUE;
+}
+
+static void
+list_header_func (GtkListBoxRow *row,
+ GtkListBoxRow *before,
+ gpointer user_data)
+{
+ GtkStyleContext *context;
+ GtkWidget *header;
+
+ /* first entry */
+ gtk_list_box_row_set_header (row, NULL);
+ if (before == NULL)
+ return;
+
+ /* desktop -> addons */
+ if (!is_addon_id_kind (gs_app_row_get_app (GS_APP_ROW (before))) &&
+ is_addon_id_kind (gs_app_row_get_app (GS_APP_ROW (row)))) {
+ /* TRANSLATORS: This is the header dividing the normal
+ * applications and the addons */
+ header = gtk_label_new (_("Add-ons"));
+ g_object_set (header,
+ "xalign", 0.0,
+ NULL);
+ context = gtk_widget_get_style_context (header);
+ gtk_style_context_add_class (context, "header-label");
+ } else {
+ header = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+ }
+ gtk_list_box_row_set_header (row, header);
+}
+
+static gchar *
+get_app_sort_key (GsApp *app)
+{
+ GString *key;
+
+ key = g_string_sized_new (64);
+
+ /* sort by kind */
+ switch (gs_app_get_kind (app)) {
+ case GS_APP_KIND_OS_UPDATE:
+ g_string_append (key, "1:");
+ break;
+ default:
+ g_string_append (key, "2:");
+ break;
+ }
+
+ /* sort desktop files, then addons */
+ switch (gs_app_get_id_kind (app)) {
+ case GS_APP_ID_KIND_DESKTOP:
+ g_string_append (key, "1:");
+ break;
+ default:
+ g_string_append (key, "2:");
+ break;
+ }
+
+ /* sort by install date */
+ g_string_append_printf (key, "%09" G_GUINT64_FORMAT ":",
+ G_MAXUINT64 - gs_app_get_install_date (app));
+
+ /* finally, sort by short name */
+ g_string_append (key, gs_app_get_name (app));
+ return g_string_free (key, FALSE);
+}
+
+static gint
+list_sort_func (GtkListBoxRow *a,
+ GtkListBoxRow *b,
+ gpointer user_data)
+{
+ GsApp *a1 = gs_app_row_get_app (GS_APP_ROW (a));
+ GsApp *a2 = gs_app_row_get_app (GS_APP_ROW (b));
+ gchar *key1 = get_app_sort_key (a1);
+ gchar *key2 = get_app_sort_key (a2);
+ gint retval;
+
+ /* compare the keys according to the algorithm above */
+ retval = g_strcmp0 (key1, key2);
+
+ g_free (key1);
+ g_free (key2);
+
+ return retval;
+}
+
+static void
+gs_update_list_finalize (GObject *object)
+{
+ GsUpdateList *update_list = GS_UPDATE_LIST (object);
+ GsUpdateListPrivate *priv = gs_update_list_get_instance_private (update_list);
+
+ g_clear_object (&priv->sizegroup_image);
+ g_clear_object (&priv->sizegroup_name);
+
+ G_OBJECT_CLASS (gs_update_list_parent_class)->finalize (object);
+}
+
+static void
+gs_update_list_init (GsUpdateList *update_list)
+{
+ GsUpdateListPrivate *priv = gs_update_list_get_instance_private (update_list);
+
+ priv->sizegroup_image = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+ priv->sizegroup_name = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+ gtk_list_box_set_header_func (GTK_LIST_BOX (update_list),
+ list_header_func,
+ update_list, NULL);
+ gtk_list_box_set_sort_func (GTK_LIST_BOX (update_list),
+ list_sort_func,
+ update_list, NULL);
+}
+
+static void
+gs_update_list_class_init (GsUpdateListClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gs_update_list_finalize;
+}
+
+GtkWidget *
+gs_update_list_new (void)
+{
+ GsUpdateList *update_list;
+
+ update_list = g_object_new (GS_TYPE_UPDATE_LIST, NULL);
+
+ return GTK_WIDGET (update_list);
+}
+
+/* vim: set noexpandtab: */
diff --git a/src/gs-update-list.h b/src/gs-update-list.h
new file mode 100644
index 0000000..ff2611b
--- /dev/null
+++ b/src/gs-update-list.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef GS_UPDATE_LIST_H
+#define GS_UPDATE_LIST_H
+
+#include <gtk/gtk.h>
+
+#include "gs-app.h"
+
+#define GS_TYPE_UPDATE_LIST (gs_update_list_get_type())
+#define GS_UPDATE_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GS_TYPE_UPDATE_LIST,
GsUpdateList))
+#define GS_UPDATE_LIST_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST((cls), GS_TYPE_UPDATE_LIST,
GsUpdateListClass))
+#define GS_IS_UPDATE_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GS_TYPE_UPDATE_LIST))
+#define GS_IS_UPDATE_LIST_CLASS(cls) (G_TYPE_CHECK_CLASS_TYPE((cls), GS_TYPE_UPDATE_LIST))
+#define GS_UPDATE_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GS_TYPE_UPDATE_LIST,
GsUpdateListClass))
+
+G_BEGIN_DECLS
+
+typedef struct _GsUpdateList GsUpdateList;
+typedef struct _GsUpdateListClass GsUpdateListClass;
+typedef struct _GsUpdateListPrivate GsUpdateListPrivate;
+
+struct _GsUpdateList
+{
+ GtkListBox parent;
+};
+
+struct _GsUpdateListClass
+{
+ GtkListBoxClass parent_class;
+};
+
+GType gs_update_list_get_type (void);
+GtkWidget *gs_update_list_new (void);
+void gs_update_list_add_app (GsUpdateList *update_list,
+ GsApp *app);
+
+G_END_DECLS
+
+#endif /* GS_UPDATE_LIST_H */
+
+/* vim: set noexpandtab: */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]