gnome-packagekit r184 - in trunk: . libpackagekit-gnome po src



Author: rhughes
Date: Tue Apr 22 13:40:41 2008
New Revision: 184
URL: http://svn.gnome.org/viewvc/gnome-packagekit?rev=184&view=rev

Log:
from git

Added:
   trunk/src/gpk-client.c
   trunk/src/gpk-client.h
   trunk/src/gpk-common.c
   trunk/src/gpk-common.h
   trunk/src/gpk-error.c
   trunk/src/gpk-error.h
   trunk/src/gpk-gnome.c
   trunk/src/gpk-gnome.h
   trunk/src/gpk-self-test.c
Removed:
   trunk/libpackagekit-gnome/
Modified:
   trunk/Makefile.am
   trunk/configure.ac
   trunk/po/POTFILES.in
   trunk/src/.gitignore
   trunk/src/Makefile.am
   trunk/src/gpk-interface.xml
   trunk/src/gpk-log.c
   trunk/src/gpk-notify.c
   trunk/src/gpk-repo.c
   trunk/src/gpk-smart-icon.c
   trunk/src/gpk-smart-icon.h
   trunk/src/gpk-update-icon.c
   trunk/src/gpk-update-viewer.c

Modified: trunk/Makefile.am
==============================================================================
--- trunk/Makefile.am	(original)
+++ trunk/Makefile.am	Tue Apr 22 13:40:41 2008
@@ -1,7 +1,6 @@
 SUBDIRS =						\
 	libselftest					\
 	libgbus						\
-	libpackagekit-gnome				\
 	docs						\
 	man						\
 	src						\
@@ -9,15 +8,11 @@
 	data						\
 	help
 
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = packagekit-gnome.pc
-
 EXTRA_DIST =						\
 	MAINTAINERS					\
 	intltool-extract.in				\
 	intltool-merge.in				\
 	intltool-update.in				\
-	packagekit-gnome.pc.in				\
 	omf.make					\
 	xmldocs.make					\
 	gnome-doc-utils.make
@@ -25,11 +20,14 @@
 clean-local :
 	rm -f *~
 
+snapshot:
+	$(MAKE) dist distdir=$(PACKAGE)-$(VERSION)-`date +"%Y%m%d"`
+
 DISTCLEANFILES =					\
 	intltool-extract				\
 	intltool-merge					\
 	intltool-update					\
 	gnome-packagekit-*.tar.gz
 
-DISTCHECK_CONFIGURE_FLAGS = --disable-schemas-install --disable-scrollkeeper --enable-gtk-doc
+DISTCHECK_CONFIGURE_FLAGS = --disable-schemas-install --disable-scrollkeeper
 

Modified: trunk/configure.ac
==============================================================================
--- trunk/configure.ac	(original)
+++ trunk/configure.ac	Tue Apr 22 13:40:41 2008
@@ -5,30 +5,18 @@
 AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
 AM_CONFIG_HEADER(config.h)
 
-# libtool versioning - this applies to libpackagekit
-#
-# See http://sources.redhat.com/autobook/autobook/autobook_91.html#SEC91 for details
-#
-# increment;
-# CURRENT	If the API or ABI interface has changed (reset REVISION to 0)
-# REVISION	If the API and ABI remains the same, but bugs are fixed.
-# AGE		If libpackagekit can be linked into executables which can be
-# 		built with previous versions of this library. Don't use.
-LT_CURRENT=1
-LT_REVISION=0
-LT_AGE=0
-AC_SUBST(LT_CURRENT)
-AC_SUBST(LT_REVISION)
-AC_SUBST(LT_AGE)
-
 AC_PROG_CC
 AC_PROG_INSTALL
 AM_PROG_LIBTOOL
+AM_PROG_CC_C_O
 IT_PROG_INTLTOOL([0.35.0])
 
 GNOME_COMPILE_WARNINGS
 GNOME_DOC_INIT
 
+# set up gtk-doc
+GTK_DOC_CHECK(1.9)
+
 AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal)
 
 dnl ---------------------------------------------------------------------------
@@ -54,9 +42,6 @@
 
 AM_GLIB_GNU_GETTEXT
 
-# set up gtk-doc
-GTK_DOC_CHECK(1.9)
-
 dnl ---------------------------------------------------------------------------
 dnl - Library dependencies
 dnl ---------------------------------------------------------------------------
@@ -205,9 +190,7 @@
 dnl ---------------------------------------------------------------------------
 AC_OUTPUT([
 Makefile
-packagekit-gnome.pc
 libselftest/Makefile
-libpackagekit-gnome/Makefile
 libgbus/Makefile
 src/Makefile
 help/Makefile
@@ -215,8 +198,6 @@
 po/Makefile.in
 data/Makefile
 docs/Makefile
-docs/api/version.xml
-docs/api/Makefile
 data/icons/Makefile
 data/icons/16x16/Makefile
 data/icons/22x22/Makefile

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Tue Apr 22 13:40:41 2008
@@ -6,7 +6,7 @@
 data/gpk-application.glade
 data/gpk-backend-status.glade
 data/gpk-install-file.desktop.in
-data/gpk-install-file.glade
+data/gpk-client.glade
 data/gpk-log.desktop.in
 data/gpk-log.glade
 data/gpk-prefs.desktop.in
@@ -20,13 +20,14 @@
 data/gpk-update-viewer.glade
 data/gpk-error.glade
 data/gpk-eula.glade
-libpackagekit-gnome/gpk-error.c
-libpackagekit-gnome/gpk-common.c
-libpackagekit-gnome/gpk-client.c
+src/gpk-error.c
+src/gpk-common.c
+src/gpk-client.c
 src/gpk-application.c
 src/gpk-application-main.c
 src/gpk-backend-status.c
 src/gpk-inhibit.c
+src/gpk-firmware.c
 src/gpk-install-local-file.c
 src/gpk-install-package-name.c
 src/gpk-install-provide-file.c

Modified: trunk/src/.gitignore
==============================================================================
--- trunk/src/.gitignore	(original)
+++ trunk/src/.gitignore	Tue Apr 22 13:40:41 2008
@@ -1,6 +1,13 @@
 Makefile
 Makefile.in
 *.o
+*.la
+*.lo
+*.loT
+*.gcov
+*.gcda
+*.gcno
+*.out
 .deps
 .libs
 gpk-marshal.c
@@ -15,6 +22,7 @@
 gpk-prefs
 gpk-update-viewer
 gpk-backend-status
+gpk-self-test
 gpk-log
 .svn
 

Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am	(original)
+++ trunk/src/Makefile.am	Tue Apr 22 13:40:41 2008
@@ -21,16 +21,12 @@
 	-DLOCALEDIR=\""$(localedir)"\"			\
 	-DVERSION="\"$(VERSION)\"" 			\
 	-DPK_DATA=\"$(pkgdatadir)\"			\
-	-I$(top_srcdir)/libpackagekit-gnome		\
 	-I$(top_srcdir)/libgbus				\
+	-I$(top_srcdir)/libselftest			\
 	$(NULL)
 
-GPK_LIBS =						\
-	$(top_builddir)/libpackagekit-gnome/libpackagekit-gnome.la	\
-	$(NULL)
-
-GBUS_LIBS =						\
-	$(top_builddir)/libgbus/libgbus.la		\
+SELFTEST_LIBS =						\
+	$(top_builddir)/libselftest/libselftest.la	\
 	$(NULL)
 
 bin_PROGRAMS =						\
@@ -48,6 +44,14 @@
 
 gpk_install_provide_file_SOURCES =			\
 	gpk-install-provide-file.c			\
+	gpk-client.c					\
+	gpk-client.h					\
+	gpk-gnome.c					\
+	gpk-gnome.h					\
+	gpk-common.c					\
+	gpk-common.h					\
+	gpk-error.c					\
+	gpk-error.h					\
 	$(NULL)
 
 gpk_install_provide_file_LDADD =			\
@@ -58,11 +62,18 @@
 	$(GTK_LIBS)					\
 	$(PACKAGEKIT_LIBS)				\
 	$(POLKIT_GNOME_LIBS)				\
-	$(GPK_LIBS)					\
 	$(NULL)
 
 gpk_install_local_file_SOURCES =			\
 	gpk-install-local-file.c			\
+	gpk-client.c					\
+	gpk-client.h					\
+	gpk-gnome.c					\
+	gpk-gnome.h					\
+	gpk-common.c					\
+	gpk-common.h					\
+	gpk-error.c					\
+	gpk-error.h					\
 	$(NULL)
 
 gpk_install_local_file_LDADD =				\
@@ -73,11 +84,18 @@
 	$(GTK_LIBS)					\
 	$(PACKAGEKIT_LIBS)				\
 	$(POLKIT_GNOME_LIBS)				\
-	$(GPK_LIBS)					\
 	$(NULL)
 
 gpk_install_package_name_SOURCES =			\
 	gpk-install-package-name.c			\
+	gpk-client.c					\
+	gpk-client.h					\
+	gpk-gnome.c					\
+	gpk-gnome.h					\
+	gpk-common.c					\
+	gpk-common.h					\
+	gpk-error.c					\
+	gpk-error.h					\
 	$(NULL)
 
 gpk_install_package_name_LDADD =			\
@@ -88,7 +106,6 @@
 	$(GTK_LIBS)					\
 	$(PACKAGEKIT_LIBS)				\
 	$(POLKIT_GNOME_LIBS)				\
-	$(GPK_LIBS)					\
 	$(NULL)
 
 gpk_update_icon_SOURCES =				\
@@ -99,8 +116,12 @@
 	gpk-auto-refresh.h				\
 	gpk-watch.c					\
 	gpk-watch.h					\
+	gpk-firmware.c					\
+	gpk-firmware.h					\
 	gpk-inhibit.c					\
 	gpk-inhibit.h					\
+	gpk-dbus.c					\
+	gpk-dbus.h					\
 	gpk-smart-icon.c				\
 	gpk-smart-icon.h				\
 	gpk-marshal.c					\
@@ -109,6 +130,14 @@
 	gpk-consolekit.h				\
 	gpk-progress.c					\
 	gpk-progress.h					\
+	gpk-common.c					\
+	gpk-common.h					\
+	gpk-client.c					\
+	gpk-client.h					\
+	gpk-gnome.c					\
+	gpk-gnome.h					\
+	gpk-error.c					\
+	gpk-error.h					\
 	$(NULL)
 
 gpk_update_icon_LDADD =					\
@@ -120,13 +149,20 @@
 	$(LIBGLADE_LIBS)				\
 	$(PACKAGEKIT_LIBS)				\
 	$(POLKIT_GNOME_LIBS)				\
-	$(GPK_LIBS)					\
 	$(NULL)
 
 gpk_application_SOURCES =				\
 	gpk-application-main.c				\
 	gpk-application.c				\
 	gpk-application.h				\
+	gpk-common.c					\
+	gpk-common.h					\
+	gpk-gnome.c					\
+	gpk-gnome.h					\
+	gpk-error.c					\
+	gpk-error.h					\
+	gpk-client.c					\
+	gpk-client.h					\
 	gpk-statusbar.c					\
 	gpk-statusbar.h					\
 	$(NULL)
@@ -140,11 +176,12 @@
 	$(GTK_LIBS)					\
 	$(PACKAGEKIT_LIBS)				\
 	$(POLKIT_GNOME_LIBS)				\
-	$(GPK_LIBS)					\
 	$(NULL)
 
 gpk_prefs_SOURCES =					\
 	gpk-prefs.c					\
+	gpk-gnome.c					\
+	gpk-gnome.h					\
 	$(NULL)
 
 gpk_prefs_LDADD =					\
@@ -155,7 +192,6 @@
 	$(GTK_LIBS)					\
 	$(PACKAGEKIT_LIBS)				\
 	$(POLKIT_GNOME_LIBS)				\
-	$(GPK_LIBS)					\
 	$(NULL)
 
 gpk_update_viewer_SOURCES =				\
@@ -164,6 +200,14 @@
 	gpk-statusbar.h					\
 	gpk-consolekit.c				\
 	gpk-consolekit.h				\
+	gpk-client.c					\
+	gpk-client.h					\
+	gpk-gnome.c					\
+	gpk-gnome.h					\
+	gpk-common.c					\
+	gpk-common.h					\
+	gpk-error.c					\
+	gpk-error.h					\
 	gpk-cell-renderer-uri.c				\
 	gpk-cell-renderer-uri.h				\
 	$(NULL)
@@ -173,13 +217,19 @@
 	$(DBUS_LIBS)					\
 	$(LIBGLADE_LIBS)				\
 	$(GTK_LIBS)					\
+	$(GCONF_LIBS)					\
 	$(PACKAGEKIT_LIBS)				\
 	$(POLKIT_GNOME_LIBS)				\
-	$(GPK_LIBS)					\
 	$(NULL)
 
 gpk_repo_SOURCES =					\
 	gpk-repo.c					\
+	gpk-common.c					\
+	gpk-common.h					\
+	gpk-gnome.c					\
+	gpk-gnome.h					\
+	gpk-error.c					\
+	gpk-error.h					\
 	gpk-statusbar.c					\
 	gpk-statusbar.h					\
 	$(NULL)
@@ -192,11 +242,14 @@
 	$(GTK_LIBS)					\
 	$(PACKAGEKIT_LIBS)				\
 	$(POLKIT_GNOME_LIBS)				\
-	$(GPK_LIBS)					\
 	$(NULL)
 
 gpk_log_SOURCES =					\
 	gpk-log.c					\
+	gpk-gnome.c					\
+	gpk-gnome.h					\
+	gpk-common.c					\
+	gpk-common.h					\
 	$(NULL)
 
 gpk_log_LDADD =						\
@@ -206,7 +259,6 @@
 	$(GTK_LIBS)					\
 	$(PACKAGEKIT_LIBS)				\
 	$(POLKIT_GNOME_LIBS)				\
-	$(GPK_LIBS)					\
 	$(NULL)
 
 gpk_backend_status_SOURCES =				\
@@ -241,6 +293,39 @@
 		--output=gpk-interface.h		\
 		$(srcdir)/gpk-interface.xml
 
+check_PROGRAMS =						\
+	gpk-self-test
+
+noinst_PROGRAMS =						\
+	gpk-self-test
+
+gpk_self_test_SOURCES =						\
+	gpk-self-test.c						\
+	gpk-common.c						\
+	gpk-common.h						\
+	$(NULL)
+
+gpk_self_test_LDADD =						\
+	$(GLIB_LIBS)						\
+	$(GTK_LIBS)						\
+	$(DBUS_LIBS)						\
+	$(SELFTEST_LIBS)					\
+	$(PK_LIBS)						\
+	$(PACKAGEKIT_LIBS)					\
+	$(POLKIT_GNOME_LIBS)					\
+	$(NULL)
+
+gpk_self_test_CPPFLAGS = -DPK_BUILD_TESTS
+
+TESTS = gpk-self-test
+
+if PK_BUILD_GPROF
+clean-gprof:
+	rm -f *.out
+gprof: clean-gprof all check
+	gprof ./gpk-self-test > gprof.txt
+endif
+
 EXTRA_DIST =						\
 	gpk-marshal.list				\
 	gpk-interface.xml				\
@@ -249,6 +334,11 @@
 clean-local:
 	rm -f *~
 	rm -f gpk-marshal.c gpk-marshal.h
+	rm -f *.out
+	rm -f *.gcda
+	rm -f *.gcno
+	rm -f gcov.txt
+	rm -f gprof.txt
 
 CLEANFILES = *~ $(BUILT_SOURCES)
 

Added: trunk/src/gpk-client.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-client.c	Tue Apr 22 13:40:41 2008
@@ -0,0 +1,1116 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gpk-client
+ * @short_description: GObject class for libpackagekit-gnome client access
+ *
+ * A nice GObject to use for installing software in GNOME applications
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <glib/gprintf.h>
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <gconf/gconf-client.h>
+#include <pk-debug.h>
+#include <pk-client.h>
+#include <pk-package-id.h>
+#include <pk-control.h>
+
+#include <gpk-client.h>
+#include <gpk-common.h>
+#include <gpk-gnome.h>
+#include <gpk-error.h>
+
+static void     gpk_client_class_init	(GpkClientClass *klass);
+static void     gpk_client_init		(GpkClient      *gclient);
+static void     gpk_client_finalize	(GObject	*object);
+
+#define GPK_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPK_TYPE_CLIENT, GpkClientPrivate))
+#define PK_STOCK_WINDOW_ICON		"system-software-installer"
+
+/**
+ * GpkClientPrivate:
+ *
+ * Private #GpkClient data
+ **/
+struct _GpkClientPrivate
+{
+	PkClient		*client_action;
+	PkClient		*client_resolve;
+	PkClient		*client_signature;
+	GladeXML		*glade_xml;
+	GConfClient		*gconf_client;
+	gint			 pulse_timeout;
+	PkControl		*control;
+	PkRoleEnum		 roles;
+	gboolean		 do_key_auth;
+};
+
+typedef enum {
+	GPK_CLIENT_PAGE_PROGRESS,
+	GPK_CLIENT_PAGE_CONFIRM,
+	GPK_CLIENT_PAGE_ERROR,
+	GPK_CLIENT_PAGE_LAST
+} GpkClientPageEnum;
+
+G_DEFINE_TYPE (GpkClient, gpk_client, G_TYPE_OBJECT)
+
+/**
+ * gpk_client_error_quark:
+ *
+ * Return value: Our personal error quark.
+ **/
+GQuark
+gpk_client_error_quark (void)
+{
+	static GQuark quark = 0;
+	if (!quark) {
+		quark = g_quark_from_static_string ("gpk_client_error");
+	}
+	return quark;
+}
+
+/**
+ * gpk_client_error_get_type:
+ **/
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+GType
+gpk_client_error_get_type (void)
+{
+	static GType etype = 0;
+
+	if (etype == 0) {
+		static const GEnumValue values[] =
+		{
+			ENUM_ENTRY (GPK_CLIENT_ERROR_FAILED, "Failed"),
+			{ 0, NULL, NULL }
+		};
+		etype = g_enum_register_static ("PkClientError", values);
+	}
+	return etype;
+}
+
+/**
+ * gpk_client_set_page:
+ **/
+static void
+gpk_client_set_page (GpkClient *gclient, GpkClientPageEnum page)
+{
+	GList *list, *l;
+	GtkWidget *widget;
+	guint i;
+
+	g_return_if_fail (GPK_IS_CLIENT (gclient));
+
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "hbox_hidden");
+	list = gtk_container_get_children (GTK_CONTAINER (widget));
+	for (l=list, i=0; l; l=l->next, i++) {
+		if (i == page) {
+			gtk_widget_show (l->data);
+		} else {
+			gtk_widget_hide (l->data);
+		}
+	}
+}
+
+/**
+ * gpk_install_finished_timeout:
+ **/
+static gboolean
+gpk_install_finished_timeout (gpointer data)
+{
+	gtk_main_quit ();
+	return FALSE;
+}
+
+/**
+ * gpk_client_finished_cb:
+ **/
+static void
+gpk_client_finished_cb (PkClient *client, PkExitEnum exit, guint runtime, GpkClient *gclient)
+{
+	GtkWidget *widget;
+
+	g_return_if_fail (GPK_IS_CLIENT (gclient));
+
+	if (exit == PK_EXIT_ENUM_SUCCESS) {
+		gpk_client_set_page (gclient, GPK_CLIENT_PAGE_CONFIRM);
+
+		widget = glade_xml_get_widget (gclient->priv->glade_xml, "button_close2");
+		gtk_widget_grab_default (widget);
+
+		g_timeout_add_seconds (30, gpk_install_finished_timeout, gclient);
+	} else {
+		gtk_main_quit ();
+	}
+
+	/* make insensitive */
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "button_cancel");
+	gtk_widget_set_sensitive (widget, FALSE);
+
+	/* set to 100% */
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "progressbar_percent");
+	gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (widget), 1.0f);
+}
+
+/**
+ * gpk_client_progress_changed_cb:
+ **/
+static void
+gpk_client_progress_changed_cb (PkClient *client, guint percentage, guint subpercentage,
+				guint elapsed, guint remaining, GpkClient *gclient)
+{
+	GtkWidget *widget;
+
+	g_return_if_fail (GPK_IS_CLIENT (gclient));
+
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "progressbar_percent");
+	if (gclient->priv->pulse_timeout != 0) {
+		g_source_remove (gclient->priv->pulse_timeout);
+		gclient->priv->pulse_timeout = 0;
+	}
+
+	if (percentage != PK_CLIENT_PERCENTAGE_INVALID) {
+		gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (widget), (gfloat) percentage / 100.0);
+	}
+}
+
+/**
+ * gpk_client_pulse_progress:
+ **/
+static gboolean
+gpk_client_pulse_progress (GpkClient *gclient)
+{
+	GtkWidget *widget;
+
+	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
+
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "progressbar_percent");
+	gtk_progress_bar_pulse (GTK_PROGRESS_BAR (widget));
+	return TRUE;
+}
+
+/**
+ * gpk_client_status_changed_cb:
+ **/
+static void
+gpk_client_status_changed_cb (PkClient *client, PkStatusEnum status, GpkClient *gclient)
+{
+	GtkWidget *widget;
+	gchar *text;
+
+	g_return_if_fail (GPK_IS_CLIENT (gclient));
+
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "progress_part_label");
+	text = g_strdup_printf ("<b>%s</b>", gpk_status_enum_to_localised_text (status));
+	gtk_label_set_markup (GTK_LABEL (widget), text);
+	g_free (text);
+
+	if (status == PK_STATUS_ENUM_WAIT) {
+		if (gclient->priv->pulse_timeout == 0) {
+			widget = glade_xml_get_widget (gclient->priv->glade_xml, "progressbar_percent");
+
+			gtk_progress_bar_set_pulse_step (GTK_PROGRESS_BAR (widget ), 0.04);
+			gclient->priv->pulse_timeout = g_timeout_add (75, (GSourceFunc) gpk_client_pulse_progress, gclient);
+		}
+	}
+}
+
+/**
+ * gpk_client_error_code_cb:
+ **/
+static void
+gpk_client_error_code_cb (PkClient *client, PkErrorCodeEnum code, const gchar *details, GpkClient *gclient)
+{
+	g_return_if_fail (GPK_IS_CLIENT (gclient));
+
+	/* have we handled? */
+	if (code == PK_ERROR_ENUM_GPG_FAILURE) {
+		if (gclient->priv->do_key_auth) {
+			pk_debug ("ignoring GPG error as handled");
+			return;
+		}
+		pk_warning ("did not auth");
+	}
+
+	//remove GPK_CLIENT_PAGE_ERROR?
+	gpk_error_dialog (gpk_error_enum_to_localised_text (code),
+			  gpk_error_enum_to_localised_message (code), details);
+}
+
+/**
+ * gpk_client_package_cb:
+ **/
+static void
+gpk_client_package_cb (PkClient *client, PkInfoEnum info, const gchar *package_id,
+		      const gchar *summary, GpkClient *gclient)
+{
+	gchar *text;
+	GtkWidget *widget;
+
+	g_return_if_fail (GPK_IS_CLIENT (gclient));
+
+	text = gpk_package_id_format_twoline (package_id, summary);
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "label_package");
+	gtk_label_set_markup (GTK_LABEL (widget), text);
+	g_free (text);
+}
+
+/**
+ * gpk_client_allow_cancel_cb:
+ **/
+static void
+gpk_client_allow_cancel_cb (PkClient *client, gboolean allow_cancel, GpkClient *gclient)
+{
+	GtkWidget *widget;
+
+	g_return_if_fail (GPK_IS_CLIENT (gclient));
+
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "button_cancel");
+	gtk_widget_set_sensitive (widget, allow_cancel);
+}
+
+/**
+ * gpk_client_button_help_cb:
+ **/
+static void
+gpk_client_button_help_cb (GtkWidget *widget, GpkClient *gclient)
+{
+	g_return_if_fail (GPK_IS_CLIENT (gclient));
+	gpk_gnome_help (NULL);
+}
+
+/**
+ * pk_client_button_cancel_cb:
+ **/
+static void
+pk_client_button_cancel_cb (GtkWidget *widget, GpkClient *gclient)
+{
+	gboolean ret;
+	GError *error = NULL;
+
+	/* we might have a transaction running */
+	ret = pk_client_cancel (gclient->priv->client_action, &error);
+	if (!ret) {
+		pk_warning ("failed to cancel client: %s", error->message);
+		g_error_free (error);
+	}
+}
+
+/**
+ * gpk_client_error_message:
+ **/
+static void
+gpk_client_error_msg (GpkClient *gclient, const gchar *title, const gchar *message)
+{
+	GtkWidget *widget;
+	GtkWidget *dialog;
+
+	/* hide the main window */
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
+	gtk_widget_hide (widget);
+
+	dialog = gtk_message_dialog_new (GTK_WINDOW (widget), GTK_DIALOG_DESTROY_WITH_PARENT,
+					 GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, "%s", title);
+	gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", message);
+	gtk_dialog_run (GTK_DIALOG (dialog));
+	gtk_widget_destroy (dialog);
+}
+
+/**
+ * gpk_client_error_set:
+ *
+ * Sets the correct error code (if allowed) and print to the screen
+ * as a warning.
+ **/
+static gboolean
+gpk_client_error_set (GError **error, gint code, const gchar *format, ...)
+{
+	va_list args;
+	gchar *buffer = NULL;
+	gboolean ret = TRUE;
+
+	va_start (args, format);
+	g_vasprintf (&buffer, format, args);
+	va_end (args);
+
+	/* dumb */
+	if (error == NULL) {
+		pk_warning ("No error set, so can't set: %s", buffer);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* already set */
+	if (*error != NULL) {
+		pk_warning ("not NULL error!");
+		g_clear_error (error);
+	}
+
+	/* propogate */
+	g_set_error (error, GPK_CLIENT_ERROR, code, "%s", buffer);
+
+out:
+	g_free(buffer);
+	return ret;
+}
+
+/**
+ * gpk_client_install_local_file:
+ * @gclient: a valid #GpkClient instance
+ * @file_rel: a file such as <literal>./hal-devel-0.10.0.rpm</literal>
+ * @error: a %GError to put the error code and message in, or %NULL
+ *
+ * Install a file locally, and get the deps from the repositories.
+ * This is useful for double clicking on a .rpm or .deb file.
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+gboolean
+gpk_client_install_local_file (GpkClient *gclient, const gchar *file_rel, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+	gchar *text;
+	GtkWidget *widget;
+
+	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
+	g_return_val_if_fail (file_rel != NULL, FALSE);
+
+	/* show window */
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
+	gtk_widget_show (widget);
+
+	ret = pk_client_install_file (gclient->priv->client_action, file_rel, &error_local);
+	if (!ret) {
+		/* check if we got a permission denied */
+		if (g_str_has_prefix (error_local->message, "org.freedesktop.packagekit.")) {
+			gpk_client_error_msg (gclient, _("Failed to install file"),
+					      _("You don't have the necessary privileges to install local files"));
+			gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		} else {
+			text = g_markup_escape_text (error_local->message, -1);
+			gpk_client_error_msg (gclient, _("Failed to install file"), text);
+			g_free (text);
+			gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		}
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* wait for completion */
+	gtk_main ();
+
+	/* we're done */
+	if (gclient->priv->pulse_timeout != 0) {
+		g_source_remove (gclient->priv->pulse_timeout);
+		gclient->priv->pulse_timeout = 0;
+	}
+out:
+	return ret;
+}
+
+/**
+ * gpk_client_checkbutton_show_depends_cb:
+ **/
+static void
+gpk_client_checkbutton_show_depends_cb (GtkWidget *widget, GpkClient *gclient)
+{
+	gboolean checked;
+
+	g_return_if_fail (GPK_IS_CLIENT (gclient));
+
+	/* set the policy */
+	checked = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+	pk_debug ("Changing %s to %i", GPK_CONF_SHOW_DEPENDS, checked);
+	gconf_client_set_bool (gclient->priv->gconf_client, GPK_CONF_SHOW_DEPENDS, checked, NULL);
+}
+
+/**
+ * gpk_client_install_package_id:
+ * @gclient: a valid #GpkClient instance
+ * @package_id: a package_id such as <literal>hal-info;0.20;i386;fedora</literal>
+ * @error: a %GError to put the error code and message in, or %NULL
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+gboolean
+gpk_client_install_package_id (GpkClient *gclient, const gchar *package_id, GError **error)
+{
+	GtkWidget *widget;
+	GtkWidget *dialog;
+	GtkResponseType button;
+	gboolean ret;
+	GError *error_local = NULL;
+	gchar *text;
+	guint len;
+	guint i;
+	GString *string;
+	PkPackageItem *item;
+
+	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
+	g_return_val_if_fail (package_id != NULL, FALSE);
+
+	/* show window */
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
+	gtk_widget_show (widget);
+
+	/* are we dumb and can't check for depends? */
+	if (!pk_enums_contain (gclient->priv->roles, PK_ROLE_ENUM_GET_DEPENDS)) {
+		pk_warning ("skipping depends check");
+		goto skip_checks;
+	}
+
+	/* reset */
+	ret = pk_client_reset (gclient->priv->client_resolve, &error_local);
+	if (!ret) {
+		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"));
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* find out if this would drag in other packages */
+	ret = pk_client_get_depends (gclient->priv->client_resolve, PK_FILTER_ENUM_NOT_INSTALLED, package_id, TRUE, &error_local);
+	if (!ret) {
+		text = g_strdup_printf ("%s: %s", _("Could not work out what packages would be also installed"), error_local->message);
+		gpk_client_error_msg (gclient, _("Failed to get depends"), text);
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		g_free (text);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* any additional packages? */
+	len = pk_client_package_buffer_get_size	(gclient->priv->client_resolve);
+	if (len == 0) {
+		pk_debug ("no additional deps");
+		goto skip_checks;
+	}
+
+	/* have we previously said we don't want to be shown the confirmation */
+	ret = gconf_client_get_bool (gclient->priv->gconf_client, GPK_CONF_SHOW_DEPENDS, NULL);
+	if (!ret) {
+		pk_debug ("we've said we don't want deps anymore");
+		goto skip_checks;
+	}
+
+	/* process package list */
+	string = g_string_new (_("The following packages also have to be downloaded:"));
+	g_string_append (string, "\n\n");
+	for (i=0; i<len; i++) {
+		item = pk_client_package_buffer_get_item (gclient->priv->client_resolve, i);
+		text = gpk_package_id_format_oneline (item->package_id, item->summary);
+		g_string_append_printf (string, "%s\n", text);
+		g_free (text);
+	}
+	/* remove last \n */
+	g_string_set_size (string, string->len - 1);
+
+	/* display messagebox  */
+	text = g_string_free (string, FALSE);
+	pk_debug ("text=%s", text);
+
+	/* show UI */
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
+	dialog = gtk_message_dialog_new (GTK_WINDOW (widget), GTK_DIALOG_DESTROY_WITH_PARENT,
+					 GTK_MESSAGE_QUESTION, GTK_BUTTONS_CANCEL,
+					 "%s", _("Install additional packages?"));
+	/* add a specialist button */
+	gtk_dialog_add_button (GTK_DIALOG (dialog), _("Install"), GTK_RESPONSE_OK);
+
+	/* add a checkbutton for deps screen */
+	widget = gtk_check_button_new_with_label (_("Do not show me this again"));
+	g_signal_connect (widget, "clicked", G_CALLBACK (gpk_client_checkbutton_show_depends_cb), gclient);
+	gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), widget);
+	gtk_widget_show (widget);
+
+	gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", text);
+	button = gtk_dialog_run (GTK_DIALOG (dialog));
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+	g_free (text);
+
+	/* did we click no or exit the window? */
+	if (button != GTK_RESPONSE_OK) {
+		gpk_client_error_msg (gclient, _("Failed to install package"), _("Additional packages were not downloaded"));
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, "user did not agree to additional deps");
+		ret = FALSE;
+		goto out;
+	}
+
+skip_checks:
+	/* try to install the package_id */
+	ret = pk_client_install_package (gclient->priv->client_action, package_id, &error_local);
+	if (!ret) {
+		/* check if we got a permission denied */
+		if (g_str_has_prefix (error_local->message, "org.freedesktop.packagekit.")) {
+			gpk_client_error_msg (gclient, _("Failed to install package"),
+					        _("You don't have the necessary privileges to install packages"));
+			gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		} else {
+			text = g_markup_escape_text (error_local->message, -1);
+			gpk_client_error_msg (gclient, _("Failed to install package"), text);
+			gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+			g_free (text);
+		}
+		g_error_free (error_local);
+		goto out;
+	}
+
+	/* wait for completion */
+	gtk_main ();
+
+	/* we're done */
+	if (gclient->priv->pulse_timeout != 0) {
+		g_source_remove (gclient->priv->pulse_timeout);
+		gclient->priv->pulse_timeout = 0;
+	}
+out:
+	return ret;
+}
+
+/**
+ * gpk_client_install_package_name:
+ * @gclient: a valid #GpkClient instance
+ * @package: a pakage name such as <literal>hal-info</literal>
+ * @error: a %GError to put the error code and message in, or %NULL
+ *
+ * Install a package of the newest and most correct version.
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+gboolean
+gpk_client_install_package_name (GpkClient *gclient, const gchar *package, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+	guint len;
+	guint i;
+	gboolean already_installed = FALSE;
+	gchar *package_id = NULL;
+	PkPackageItem *item;
+	GtkWidget *widget;
+
+	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
+	g_return_val_if_fail (package != NULL, FALSE);
+
+	/* show window */
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
+	gtk_widget_show (widget);
+
+	ret = pk_client_resolve (gclient->priv->client_resolve, PK_FILTER_ENUM_NONE, package, &error_local);
+	if (!ret) {
+		gpk_client_error_msg (gclient, _("Failed to resolve package"), _("Incorrect response from search"));
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* found nothing? */
+	len = pk_client_package_buffer_get_size	(gclient->priv->client_resolve);
+	if (len == 0) {
+		gpk_client_error_msg (gclient, _("Failed to find package"), _("The package could not be found online"));
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, NULL);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* see what we've got already */
+	for (i=0; i<len; i++) {
+		item = pk_client_package_buffer_get_item (gclient->priv->client_resolve, i);
+		if (item->info == PK_INFO_ENUM_INSTALLED) {
+			already_installed = TRUE;
+			break;
+		} else if (item->info == PK_INFO_ENUM_AVAILABLE) {
+			pk_debug ("package '%s' resolved", item->package_id);
+			package_id = g_strdup (item->package_id);
+			break;
+		}
+	}
+
+	/* already installed? */
+	if (already_installed) {
+		gpk_client_error_msg (gclient, _("Failed to install package"), _("The package is already installed"));
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* got junk? */
+	if (package_id == NULL) {
+		gpk_client_error_msg (gclient, _("Failed to find package"), _("Incorrect response from search"));
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* install this specific package */
+	ret = gpk_client_install_package_id (gclient, package_id, error);
+out:
+	g_free (package_id);
+	return ret;
+}
+
+/**
+ * gpk_client_install_provide_file:
+ * @gclient: a valid #GpkClient instance
+ * @full_path: a file path name such as <literal>/usr/sbin/packagekitd</literal>
+ * @error: a %GError to put the error code and message in, or %NULL
+ *
+ * Install a package which provides a file on the system.
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+gboolean
+gpk_client_install_provide_file (GpkClient *gclient, const gchar *full_path, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+	guint len;
+	guint i;
+	gboolean already_installed = FALSE;
+	gchar *package_id = NULL;
+	PkPackageItem *item;
+	PkPackageId *ident;
+	gchar *text;
+	GtkWidget *widget;
+
+	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
+	g_return_val_if_fail (full_path != NULL, FALSE);
+
+	/* show window */
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
+	gtk_widget_show (widget);
+
+	ret = pk_client_search_file (gclient->priv->client_resolve, PK_FILTER_ENUM_NONE, full_path, &error_local);
+	if (!ret) {
+		text = g_strdup_printf ("%s: %s", _("Incorrect response from search"), error_local->message);
+		gpk_client_error_msg (gclient, _("Failed to search for file"), text);
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		g_free (text);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* found nothing? */
+	len = pk_client_package_buffer_get_size	(gclient->priv->client_resolve);
+	if (len == 0) {
+		gpk_client_error_msg (gclient, _("Failed to find package"), _("The file could not be found in any packages"));
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, NULL);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* see what we've got already */
+	for (i=0; i<len; i++) {
+		item = pk_client_package_buffer_get_item (gclient->priv->client_resolve, i);
+		if (item->info == PK_INFO_ENUM_INSTALLED) {
+			already_installed = TRUE;
+			g_free (package_id);
+			package_id = g_strdup (item->package_id);
+			break;
+		} else if (item->info == PK_INFO_ENUM_AVAILABLE) {
+			pk_debug ("package '%s' resolved to:", item->package_id);
+			package_id = g_strdup (item->package_id);
+		}
+	}
+
+	/* already installed? */
+	if (already_installed) {
+		ident = pk_package_id_new_from_string (package_id);
+		text = g_strdup_printf (_("The %s package already provides the file %s"), ident->name, full_path);
+		gpk_client_error_msg (gclient, _("Failed to install file"), text);
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		g_free (text);
+		pk_package_id_free (ident);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* got junk? */
+	if (package_id == NULL) {
+		gpk_client_error_msg (gclient, _("Failed to install file"), _("Incorrect response from file search"));
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* install this specific package */
+	ret = gpk_client_install_package_id (gclient, package_id, error);
+out:
+	g_free (package_id);
+	return ret;
+}
+
+/**
+ * gpk_client_sig_button_yes:
+ **/
+static void
+gpk_client_sig_button_yes (GtkWidget *widget, GpkClient *gclient)
+{
+	g_return_if_fail (GPK_IS_CLIENT (gclient));
+	gclient->priv->do_key_auth = TRUE;
+	gtk_main_quit ();
+}
+
+/**
+ * gpk_client_button_help:
+ **/
+static void
+gpk_client_button_help (GtkWidget *widget, GpkClient *gclient)
+{
+	g_return_if_fail (GPK_IS_CLIENT (gclient));
+	/* TODO: need a whole section on this! */
+	gpk_gnome_help (NULL);
+}
+
+/**
+ * gpk_client_repo_signature_required_cb:
+ **/
+static void
+gpk_client_repo_signature_required_cb (PkClient *client, const gchar *package_id, const gchar *repository_name,
+				       const gchar *key_url, const gchar *key_userid, const gchar *key_id,
+				       const gchar *key_fingerprint, const gchar *key_timestamp,
+				       PkSigTypeEnum type, GpkClient *gclient)
+{
+	gboolean ret;
+	GError *error = NULL;
+	GtkWidget *widget;
+	GladeXML *glade_xml;
+
+	g_return_if_fail (GPK_IS_CLIENT (gclient));
+
+	glade_xml = glade_xml_new (PK_DATA "/gpk-signature.glade", NULL, NULL);
+
+	/* connect up default actions */
+	widget = glade_xml_get_widget (glade_xml, "window_gpg");
+	g_signal_connect_swapped (widget, "delete_event", G_CALLBACK (gtk_main_quit), NULL);
+	widget = glade_xml_get_widget (glade_xml, "button_no");
+	g_signal_connect_swapped (widget, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+
+	/* set icon name */
+	gtk_window_set_icon_name (GTK_WINDOW (widget), PK_STOCK_WINDOW_ICON);
+
+	/* connect up buttons */
+	widget = glade_xml_get_widget (glade_xml, "button_yes");
+	g_signal_connect (widget, "clicked", G_CALLBACK (gpk_client_sig_button_yes), gclient);
+	widget = glade_xml_get_widget (glade_xml, "button_help");
+	g_signal_connect (widget, "clicked", G_CALLBACK (gpk_client_button_help), gclient);
+
+	/* show correct text */
+	widget = glade_xml_get_widget (glade_xml, "label_name");
+	gtk_label_set_label (GTK_LABEL (widget), repository_name);
+	widget = glade_xml_get_widget (glade_xml, "label_url");
+	gtk_label_set_label (GTK_LABEL (widget), key_url);
+	widget = glade_xml_get_widget (glade_xml, "label_user");
+	gtk_label_set_label (GTK_LABEL (widget), key_userid);
+	widget = glade_xml_get_widget (glade_xml, "label_id");
+	gtk_label_set_label (GTK_LABEL (widget), key_id);
+
+	/* show window */
+	widget = glade_xml_get_widget (glade_xml, "window_gpg");
+	gtk_widget_show (widget);
+
+	/* wait for button press */
+	gclient->priv->do_key_auth = FALSE;
+	gtk_main ();
+
+	/* hide window */
+	if (GTK_IS_WIDGET (widget)) {
+		gtk_widget_hide (widget);
+	}
+	g_object_unref (glade_xml);
+
+	/* disagreed with auth */
+	if (!gclient->priv->do_key_auth) {
+		return;
+	}
+
+	/* install signature */
+	pk_debug ("install signature %s", key_id);
+	ret = pk_client_reset (gclient->priv->client_signature, &error);
+	if (!ret) {
+		gpk_error_dialog (_("Failed to install signature"), _("The client could not be reset"), error->message);
+		g_error_free (error);
+		return;
+	}
+	/* this is asynchronous, else we get into livelock */
+	ret = pk_client_install_signature (gclient->priv->client_signature, PK_SIGTYPE_ENUM_GPG,
+					   key_id, package_id, &error);
+	if (!ret) {
+		gpk_error_dialog (_("Failed to install signature"), _("The method failed"), error->message);
+		g_error_free (error);
+		gclient->priv->do_key_auth = FALSE;
+	}
+}
+
+/**
+ * gpk_client_eula_required_cb:
+ **/
+static void
+gpk_client_eula_required_cb (PkClient *client, const gchar *eula_id, const gchar *package_id,
+			     const gchar *vendor_name, const gchar *license_agreement, GpkClient *gclient)
+{
+	gboolean ret;
+	GError *error = NULL;
+	GtkWidget *widget;
+	GladeXML *glade_xml;
+	GtkTextBuffer *buffer;
+	gchar *text;
+	PkPackageId *ident;
+
+	g_return_if_fail (GPK_IS_CLIENT (gclient));
+
+	glade_xml = glade_xml_new (PK_DATA "/gpk-eula.glade", NULL, NULL);
+
+	/* connect up default actions */
+	widget = glade_xml_get_widget (glade_xml, "window_eula");
+	g_signal_connect_swapped (widget, "delete_event", G_CALLBACK (gtk_main_quit), NULL);
+	widget = glade_xml_get_widget (glade_xml, "button_cancel");
+	g_signal_connect_swapped (widget, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+
+	/* set icon name */
+	gtk_window_set_icon_name (GTK_WINDOW (widget), PK_STOCK_WINDOW_ICON);
+
+	/* connect up buttons */
+	widget = glade_xml_get_widget (glade_xml, "button_agree");
+	g_signal_connect (widget, "clicked", G_CALLBACK (gpk_client_sig_button_yes), gclient);
+	widget = glade_xml_get_widget (glade_xml, "button_help");
+	g_signal_connect (widget, "clicked", G_CALLBACK (gpk_client_button_help), gclient);
+
+	/* title */
+	widget = glade_xml_get_widget (glade_xml, "label_title");
+	ident = pk_package_id_new_from_string (package_id);
+	text = g_strdup_printf ("<b><big>License required for %s by %s</big></b>", ident->name, vendor_name);
+	gtk_label_set_label (GTK_LABEL (widget), text);
+	pk_package_id_free (ident);
+	g_free (text);
+
+	buffer = gtk_text_buffer_new (NULL);
+	gtk_text_buffer_insert_at_cursor (buffer, license_agreement, strlen (license_agreement));
+	widget = glade_xml_get_widget (glade_xml, "textview_details");
+	gtk_text_view_set_buffer (GTK_TEXT_VIEW (widget), buffer);
+
+	/* set minimum size a bit bigger */
+	gtk_widget_set_size_request (widget, 100, 200);
+
+	/* show window */
+	widget = glade_xml_get_widget (glade_xml, "window_eula");
+	gtk_widget_show (widget);
+
+	/* wait for button press */
+	gclient->priv->do_key_auth = FALSE;
+	gtk_main ();
+
+	/* hide window */
+	if (GTK_IS_WIDGET (widget)) {
+		gtk_widget_hide (widget);
+	}
+	g_object_unref (glade_xml);
+	g_object_unref (buffer);
+
+	/* disagreed with auth */
+	if (!gclient->priv->do_key_auth) {
+		return;
+	}
+
+	/* install signature */
+	pk_debug ("accept EULA %s", eula_id);
+	ret = pk_client_reset (gclient->priv->client_signature, &error);
+	if (!ret) {
+		gpk_error_dialog (_("Failed to accept EULA"), _("The client could not be reset"), error->message);
+		g_error_free (error);
+		return;
+	}
+
+	/* this is asynchronous, else we get into livelock */
+	ret = pk_client_accept_eula (gclient->priv->client_signature, eula_id, &error);
+	if (!ret) {
+		gpk_error_dialog (_("Failed to accept EULA"), _("The method failed"), error->message);
+		g_error_free (error);
+		gclient->priv->do_key_auth = FALSE;
+	}
+}
+
+/**
+ * gpk_client_signature_finished_cb:
+ **/
+static void
+gpk_client_signature_finished_cb (PkClient *client, PkExitEnum exit, guint runtime, GpkClient *gclient)
+{
+	gboolean ret;
+	GError *error = NULL;
+
+	g_return_if_fail (GPK_IS_CLIENT (gclient));
+
+	pk_debug ("trying to requeue install");
+	ret = pk_client_requeue (gclient->priv->client_action, &error);
+	if (!ret) {
+		gpk_error_dialog (_("Failed to install"), _("The install task could not be requeued"), error->message);
+		g_error_free (error);
+	}
+}
+
+/**
+ * gpk_client_class_init:
+ * @klass: The #GpkClientClass
+ **/
+static void
+gpk_client_class_init (GpkClientClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = gpk_client_finalize;
+	g_type_class_add_private (klass, sizeof (GpkClientPrivate));
+}
+
+/**
+ * gpk_client_init:
+ * @gclient: a valid #GpkClient instance
+ **/
+static void
+gpk_client_init (GpkClient *gclient)
+{
+	GtkWidget *widget;
+
+	gclient->priv = GPK_CLIENT_GET_PRIVATE (gclient);
+
+	gclient->priv->glade_xml = NULL;
+	gclient->priv->pulse_timeout = 0;
+	gclient->priv->do_key_auth = FALSE;
+
+	/* add application specific icons to search path */
+	gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
+					   PK_DATA G_DIR_SEPARATOR_S "icons");
+
+	/* use gconf for session settings */
+	gclient->priv->gconf_client = gconf_client_get_default ();
+
+	/* get actions */
+	gclient->priv->control = pk_control_new ();
+	gclient->priv->roles = pk_control_get_actions (gclient->priv->control);
+
+	gclient->priv->client_action = pk_client_new ();
+	g_signal_connect (gclient->priv->client_action, "finished",
+			  G_CALLBACK (gpk_client_finished_cb), gclient);
+	g_signal_connect (gclient->priv->client_action, "progress-changed",
+			  G_CALLBACK (gpk_client_progress_changed_cb), gclient);
+	g_signal_connect (gclient->priv->client_action, "status-changed",
+			  G_CALLBACK (gpk_client_status_changed_cb), gclient);
+	g_signal_connect (gclient->priv->client_action, "error-code",
+			  G_CALLBACK (gpk_client_error_code_cb), gclient);
+	g_signal_connect (gclient->priv->client_action, "package",
+			  G_CALLBACK (gpk_client_package_cb), gclient);
+	g_signal_connect (gclient->priv->client_action, "allow-cancel",
+			  G_CALLBACK (gpk_client_allow_cancel_cb), gclient);
+	g_signal_connect (gclient->priv->client_action, "repo-signature-required",
+			  G_CALLBACK (gpk_client_repo_signature_required_cb), gclient);
+	g_signal_connect (gclient->priv->client_action, "eula-required",
+			  G_CALLBACK (gpk_client_eula_required_cb), gclient);
+
+	gclient->priv->client_resolve = pk_client_new ();
+	g_signal_connect (gclient->priv->client_resolve, "status-changed",
+			  G_CALLBACK (gpk_client_status_changed_cb), gclient);
+	pk_client_set_use_buffer (gclient->priv->client_resolve, TRUE, NULL);
+	pk_client_set_synchronous (gclient->priv->client_resolve, TRUE, NULL);
+
+	/* this is asynchronous, else we get into livelock */
+	gclient->priv->client_signature = pk_client_new ();
+	g_signal_connect (gclient->priv->client_signature, "finished",
+			  G_CALLBACK (gpk_client_signature_finished_cb), gclient);
+
+	gclient->priv->glade_xml = glade_xml_new (PK_DATA "/gpk-client.glade", NULL, NULL);
+
+	/* Get the main window quit */
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
+	g_signal_connect_swapped (widget, "delete_event", G_CALLBACK (gtk_main_quit), NULL);
+
+	/* just close */
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "button_close");
+	g_signal_connect_swapped (widget, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "button_close2");
+	g_signal_connect_swapped (widget, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "button_close3");
+	g_signal_connect_swapped (widget, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "button_cancel");
+	g_signal_connect (widget, "clicked",
+			  G_CALLBACK (pk_client_button_cancel_cb), gclient);
+	gtk_widget_set_sensitive (widget, FALSE);
+
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "button_help3");
+	g_signal_connect (widget, "clicked",
+			  G_CALLBACK (gpk_client_button_help_cb), gclient);
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "button_help4");
+	g_signal_connect (widget, "clicked",
+			  G_CALLBACK (gpk_client_button_help_cb), gclient);
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "button_help5");
+	g_signal_connect (widget, "clicked",
+			  G_CALLBACK (gpk_client_button_help_cb), gclient);
+
+	/* set the label blank initially */
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "progress_part_label");
+	gtk_label_set_label (GTK_LABEL (widget), "");
+
+	gpk_client_set_page (gclient, GPK_CLIENT_PAGE_PROGRESS);
+}
+
+/**
+ * gpk_client_finalize:
+ * @object: The object to finalize
+ **/
+static void
+gpk_client_finalize (GObject *object)
+{
+	GpkClient *gclient;
+
+	g_return_if_fail (GPK_IS_CLIENT (object));
+
+	gclient = GPK_CLIENT (object);
+	g_return_if_fail (gclient->priv != NULL);
+	g_object_unref (gclient->priv->client_action);
+	g_object_unref (gclient->priv->client_resolve);
+	g_object_unref (gclient->priv->client_signature);
+	g_object_unref (gclient->priv->control);
+	g_object_unref (gclient->priv->gconf_client);
+
+	G_OBJECT_CLASS (gpk_client_parent_class)->finalize (object);
+}
+
+/**
+ * gpk_client_new:
+ *
+ * PkClient is a nice GObject wrapper for gnome-packagekit and makes installing software easy
+ *
+ * Return value: A new %GpkClient instance
+ **/
+GpkClient *
+gpk_client_new (void)
+{
+	GpkClient *gclient;
+	gclient = g_object_new (GPK_TYPE_CLIENT, NULL);
+	return GPK_CLIENT (gclient);
+}
+

Added: trunk/src/gpk-client.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-client.h	Tue Apr 22 13:40:41 2008
@@ -0,0 +1,88 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_CLIENT_H
+#define __GPK_CLIENT_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GPK_TYPE_CLIENT		(gpk_client_get_type ())
+#define GPK_CLIENT(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), GPK_TYPE_CLIENT, GpkClient))
+#define GPK_CLIENT_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), GPK_TYPE_CLIENT, GpkClientClass))
+#define GPK_IS_CLIENT(o)	(G_TYPE_CHECK_INSTANCE_TYPE ((o), GPK_TYPE_CLIENT))
+#define GPK_IS_CLIENT_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), GPK_TYPE_CLIENT))
+#define GPK_CLIENT_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GPK_TYPE_CLIENT, GpkClientClass))
+#define GPK_CLIENT_ERROR	(gpk_client_error_quark ())
+#define GPK_CLIENT_TYPE_ERROR	(gpk_client_error_get_type ())
+
+/**
+ * GpkClientError:
+ * @GPK_CLIENT_ERROR_FAILED: the transaction failed for an unknown reason
+ *
+ * Errors that can be thrown
+ */
+typedef enum
+{
+	GPK_CLIENT_ERROR_FAILED
+} GpkClientError;
+
+typedef struct _GpkClientPrivate	 GpkClientPrivate;
+typedef struct _GpkClient		 GpkClient;
+typedef struct _GpkClientClass		 GpkClientClass;
+
+struct _GpkClient
+{
+	GObject				 parent;
+	GpkClientPrivate		*priv;
+};
+
+struct _GpkClientClass
+{
+	GObjectClass	parent_class;
+};
+
+GQuark		 gpk_client_error_quark			(void);
+GType		 gpk_client_get_type			(void) G_GNUC_CONST;
+GpkClient	*gpk_client_new				(void);
+
+gboolean	 gpk_client_install_local_file		(GpkClient	*gclient,
+							 const gchar	*file_rel,
+							 GError		**error)
+							 G_GNUC_WARN_UNUSED_RESULT;
+gboolean	 gpk_client_install_provide_file	(GpkClient	*gclient,
+							 const gchar	*full_path,
+							 GError		**error)
+							 G_GNUC_WARN_UNUSED_RESULT;
+gboolean	 gpk_client_install_package_name	(GpkClient	*gclient,
+							 const gchar	*package,
+							 GError		**error)
+							 G_GNUC_WARN_UNUSED_RESULT;
+gboolean	 gpk_client_install_package_id		(GpkClient	*gclient,
+							 const gchar	*package_id,
+							 GError		**error)
+							 G_GNUC_WARN_UNUSED_RESULT;
+
+G_END_DECLS
+
+#endif /* __GPK_CLIENT_H */

Added: trunk/src/gpk-common.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-common.c	Tue Apr 22 13:40:41 2008
@@ -0,0 +1,1699 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <math.h>
+#include <string.h>
+#include <unistd.h>
+#include <gtk/gtk.h>
+#include <dbus/dbus-glib.h>
+
+#include <polkit-gnome/polkit-gnome.h>
+
+#include <pk-debug.h>
+#include <pk-package-id.h>
+#include <pk-enum.h>
+#include <pk-common.h>
+#include "gpk-common.h"
+
+/* icon names */
+static PkEnumMatch enum_info_icon_name[] = {
+	{PK_INFO_ENUM_UNKNOWN,			"help-browser"},	/* fall though value */
+	{PK_INFO_ENUM_INSTALLED,		"pk-package-installed"},
+	{PK_INFO_ENUM_AVAILABLE,		"pk-package-available"},
+	{PK_INFO_ENUM_LOW,			"pk-update-low"},
+	{PK_INFO_ENUM_NORMAL,			"pk-update-normal"},
+	{PK_INFO_ENUM_IMPORTANT,		"pk-update-high"},
+	{PK_INFO_ENUM_SECURITY,			"pk-update-security"},
+	{PK_INFO_ENUM_BUGFIX,			"pk-update-bugfix"},
+	{PK_INFO_ENUM_ENHANCEMENT,		"pk-update-enhancement"},
+	{PK_INFO_ENUM_BLOCKED,			"pk-setup"},
+	{PK_INFO_ENUM_DOWNLOADING,		"pk-package-download"},
+	{PK_INFO_ENUM_UPDATING,			"pk-package-update"},
+	{PK_INFO_ENUM_INSTALLING,		"pk-package-add"},
+	{PK_INFO_ENUM_REMOVING,			"pk-package-delete"},
+	{PK_INFO_ENUM_OBSOLETING,		"pk-package-cleanup"},
+	{PK_INFO_ENUM_CLEANUP,			"pk-package-cleanup"},
+	{0, NULL}
+};
+
+static PkEnumMatch enum_status_icon_name[] = {
+	{PK_STATUS_ENUM_UNKNOWN,		"help-browser"},	/* fall though value */
+	{PK_STATUS_ENUM_WAIT,			"pk-wait"},
+	{PK_STATUS_ENUM_SETUP,			"pk-setup"},
+	{PK_STATUS_ENUM_RUNNING,		"pk-setup"},
+	{PK_STATUS_ENUM_QUERY,			"pk-package-search"},
+	{PK_STATUS_ENUM_INFO,			"pk-package-info"},
+	{PK_STATUS_ENUM_REFRESH_CACHE,		"pk-refresh-cache"},
+	{PK_STATUS_ENUM_REMOVE,			"pk-package-delete"},
+	{PK_STATUS_ENUM_DOWNLOAD,		"pk-package-download"},
+	{PK_STATUS_ENUM_INSTALL,		"pk-package-add"},
+	{PK_STATUS_ENUM_UPDATE,			"pk-package-update"},
+	{PK_STATUS_ENUM_CLEANUP,		"pk-package-cleanup"},
+	{PK_STATUS_ENUM_OBSOLETE,		"pk-package-cleanup"},
+	{PK_STATUS_ENUM_DEP_RESOLVE,		"pk-package-info"}, /* TODO: need better icon */
+	{PK_STATUS_ENUM_ROLLBACK,		"pk-package-info"}, /* TODO: need better icon */
+	{PK_STATUS_ENUM_COMMIT,			"pk-setup"}, /* TODO: need better icon */
+	{PK_STATUS_ENUM_REQUEST,		"pk-package-search"},
+	{PK_STATUS_ENUM_FINISHED,		"pk-package-cleanup"}, /* TODO: need better icon */
+	{PK_STATUS_ENUM_CANCEL,			"pk-package-cleanup"}, /* TODO: need better icon */
+	{PK_STATUS_ENUM_DOWNLOAD_REPOSITORY,	"pk-refresh-cache"},
+	{PK_STATUS_ENUM_DOWNLOAD_PACKAGELIST,	"pk-refresh-cache"},
+	{PK_STATUS_ENUM_DOWNLOAD_FILELIST,	"pk-refresh-cache"},
+	{PK_STATUS_ENUM_DOWNLOAD_CHANGELOG,	"pk-refresh-cache"},
+	{PK_STATUS_ENUM_DOWNLOAD_GROUP,		"pk-refresh-cache"},
+	{PK_STATUS_ENUM_DOWNLOAD_UPDATEINFO,	"pk-refresh-cache"},
+	{0, NULL}
+};
+
+static PkEnumMatch enum_role_icon_name[] = {
+	{PK_ROLE_ENUM_UNKNOWN,			"help-browser"},	/* fall though value */
+	{PK_ROLE_ENUM_CANCEL,			"process-stop.svg"},
+	{PK_ROLE_ENUM_RESOLVE,			"pk-package-search"},
+	{PK_ROLE_ENUM_ROLLBACK,			"pk-rollback"},
+	{PK_ROLE_ENUM_GET_DEPENDS,		"pk-package-info"},
+	{PK_ROLE_ENUM_GET_UPDATE_DETAIL,	"pk-package-info"},
+	{PK_ROLE_ENUM_GET_DESCRIPTION,		"pk-package-info"},
+	{PK_ROLE_ENUM_GET_REQUIRES,		"pk-package-info"},
+	{PK_ROLE_ENUM_GET_UPDATES,		"pk-package-info"},
+	{PK_ROLE_ENUM_SEARCH_DETAILS,		"pk-package-search"},
+	{PK_ROLE_ENUM_SEARCH_FILE,		"pk-package-search"},
+	{PK_ROLE_ENUM_SEARCH_GROUP,		"pk-package-search"},
+	{PK_ROLE_ENUM_SEARCH_NAME,		"pk-package-search"},
+	{PK_ROLE_ENUM_REFRESH_CACHE,		"pk-refresh-cache"},
+	{PK_ROLE_ENUM_REMOVE_PACKAGE,		"pk-package-delete"},
+	{PK_ROLE_ENUM_INSTALL_PACKAGE,		"pk-package-add"},
+	{PK_ROLE_ENUM_INSTALL_FILE,		"pk-package-add"},
+	{PK_ROLE_ENUM_UPDATE_PACKAGES,		"pk-package-update"},
+	{PK_ROLE_ENUM_SERVICE_PACK,		"pk-package-update"},
+	{PK_ROLE_ENUM_UPDATE_SYSTEM,		"system-software-update"},
+	{PK_ROLE_ENUM_GET_REPO_LIST,		"pk-package-sources"},
+	{PK_ROLE_ENUM_REPO_ENABLE,		"pk-package-sources"},
+	{PK_ROLE_ENUM_REPO_SET_DATA,		"pk-package-sources"},
+	{PK_ROLE_ENUM_INSTALL_SIGNATURE,	"emblem-system"},
+	{PK_ROLE_ENUM_GET_PACKAGES,		"pk-package-search"},
+	{0, NULL}
+};
+
+static PkEnumMatch enum_group_icon_name[] = {
+	{PK_GROUP_ENUM_UNKNOWN,			"help-browser"},	/* fall though value */
+	{PK_GROUP_ENUM_ACCESSIBILITY,		"preferences-desktop-accessibility"},
+	{PK_GROUP_ENUM_ACCESSORIES,		"applications-accessories"},
+	{PK_GROUP_ENUM_EDUCATION,		"utilities-system-monitor"},
+	{PK_GROUP_ENUM_GAMES,			"applications-games"},
+	{PK_GROUP_ENUM_GRAPHICS,		"applications-graphics"},
+	{PK_GROUP_ENUM_INTERNET,		"applications-internet"},
+	{PK_GROUP_ENUM_OFFICE,			"applications-office"},
+	{PK_GROUP_ENUM_OTHER,			"applications-other"},
+	{PK_GROUP_ENUM_PROGRAMMING,		"applications-development"},
+	{PK_GROUP_ENUM_MULTIMEDIA,		"applications-multimedia"},
+	{PK_GROUP_ENUM_SYSTEM,			"applications-system"},
+	{PK_GROUP_ENUM_DESKTOP_GNOME,		"pk-desktop-gnome"},
+	{PK_GROUP_ENUM_DESKTOP_KDE,		"pk-desktop-kde"},
+	{PK_GROUP_ENUM_DESKTOP_XFCE,		"pk-desktop-xfce"},
+	{PK_GROUP_ENUM_DESKTOP_OTHER,		"user-desktop"},
+	{PK_GROUP_ENUM_PUBLISHING,		"accessories-dictionary"},
+	{PK_GROUP_ENUM_SERVERS,			"network-server"},
+	{PK_GROUP_ENUM_FONTS,			"preferences-desktop-font"},
+	{PK_GROUP_ENUM_ADMIN_TOOLS,		"system-lock-screen"},
+	{PK_GROUP_ENUM_LEGACY,			"media-floppy"},
+	{PK_GROUP_ENUM_LOCALIZATION,		"preferences-desktop-locale"},
+	{PK_GROUP_ENUM_VIRTUALIZATION,		"computer"},
+	{PK_GROUP_ENUM_SECURITY,		"network-wireless-encrypted"},
+	{PK_GROUP_ENUM_POWER_MANAGEMENT,	"battery"},
+	{PK_GROUP_ENUM_COMMUNICATION,		"folder-remote"},
+	{PK_GROUP_ENUM_NETWORK,			"network-wired"},
+	{PK_GROUP_ENUM_MAPS,			"applications-multimedia"},
+	{PK_GROUP_ENUM_REPOS,			"system-file-manager"},
+	{0, NULL}
+};
+
+static PkEnumMatch enum_restart_icon_name[] = {
+	{PK_RESTART_ENUM_UNKNOWN,		"help-browser"},	/* fall though value */
+	{PK_RESTART_ENUM_NONE,			"dialog-information"},
+	{PK_RESTART_ENUM_SYSTEM,		"dialog-error"},
+	{PK_RESTART_ENUM_SESSION,		"dialog-warning"},
+	{PK_RESTART_ENUM_APPLICATION,		"dialog-warning"},
+	{0, NULL}
+};
+
+static PkEnumMatch enum_message_icon_name[] = {
+	{PK_MESSAGE_ENUM_UNKNOWN,		"help-browser"},	/* fall though value */
+	{PK_MESSAGE_ENUM_NOTICE,		"dialog-information"},
+	{PK_MESSAGE_ENUM_WARNING,		"dialog-warning"},
+	{PK_MESSAGE_ENUM_DAEMON,		"dialog-error"},
+	{0, NULL}
+};
+
+/**
+ * gpk_size_to_si_size_text:
+ **/
+gchar *
+gpk_size_to_si_size_text (guint64 size)
+{
+	gdouble frac;
+
+	/* double cast, not sure why, but it works */
+	frac = (gdouble) (long int) size;
+
+	/* first chunk */
+	if (frac < 1024) {
+		return g_strdup_printf ("%li bytes", (long int) size);
+	}
+	/* next chunk */
+	frac /= 1024.0;
+	if (frac < 1024) {
+		return g_strdup_printf ("%.1lf kB", frac);
+	}
+	/* next chunk */
+	frac /= 1024.0;
+	if (frac < 1024) {
+		return g_strdup_printf ("%.1lf MB", frac);
+	}
+	/* next chunk */
+	frac /= 1024.0;
+	if (frac < 1024) {
+		return g_strdup_printf ("%.1lf GB", frac);
+	}
+	/* no way.... */
+	pk_warning ("cannot have a file this large!");
+	return NULL;
+}
+
+/**
+ * gpk_package_id_format_twoline:
+ *
+ * Return value: "<b>GTK Toolkit</b>\ngtk2-2.12.2 (i386)"
+ **/
+gchar *
+gpk_package_id_format_twoline (const gchar *package_id, const gchar *summary)
+{
+	PkPackageId *ident;
+	gchar *summary_safe;
+	gchar *text;
+	GString *string;
+
+	/* split by delimeter */
+	ident = pk_package_id_new_from_string (package_id);
+	if (ident == NULL) {
+		pk_warning ("invalid package_id %s", package_id);
+		return NULL;
+	}
+
+	/* optional */
+	if (pk_strzero (summary)) {
+		string = g_string_new (ident->name);
+	} else {
+		string = g_string_new ("");
+		summary_safe = g_markup_escape_text (summary, -1);
+		g_string_append_printf (string, "<b>%s</b>\n%s", summary_safe, ident->name);
+		g_free (summary_safe);
+	}
+
+	/* some backends don't provide this */
+	if (ident->version != NULL) {
+		g_string_append_printf (string, "-%s", ident->version);
+	}
+	if (ident->arch != NULL) {
+		g_string_append_printf (string, " (%s)", ident->arch);
+	}
+
+	text = g_string_free (string, FALSE);
+	pk_package_id_free (ident);
+	return text;
+}
+
+/**
+ * gpk_package_id_format_oneline:
+ *
+ * Return value: "<b>GTK Toolkit</b> (gtk2)"
+ **/
+gchar *
+gpk_package_id_format_oneline (const gchar *package_id, const gchar *summary)
+{
+	PkPackageId *ident;
+	gchar *summary_safe;
+	gchar *text;
+
+	/* split by delimeter */
+	ident = pk_package_id_new_from_string (package_id);
+	if (ident == NULL) {
+		pk_warning ("invalid package_id %s", package_id);
+		return NULL;
+	}
+
+	if (pk_strzero (summary)) {
+		/* just have name */
+		text = g_strdup (ident->name);
+	} else {
+		summary_safe = g_markup_escape_text (summary, -1);
+		text = g_strdup_printf ("<b>%s</b> (%s)", summary_safe, ident->name);
+		g_free (summary_safe);
+	}
+
+	pk_package_id_free (ident);
+	return text;
+}
+
+/**
+ * gpk_package_id_name_version:
+ **/
+gchar *
+gpk_package_id_name_version (const gchar *package_id)
+{
+	PkPackageId *ident;
+	gchar *text;
+	GString *string;
+
+	if (pk_strzero (package_id)) {
+		return g_strdup (_("Package identifier not valid"));
+	}
+
+	/* split by delimeter */
+	ident = pk_package_id_new_from_string (package_id);
+	if (ident == NULL) {
+		pk_warning ("invalid package_id %s", package_id);
+		return NULL;
+	}
+
+	string = g_string_new (ident->name);
+	if (ident->version != NULL) {
+		g_string_append_printf (string, "-%s", ident->version);
+	}
+	text = g_string_free (string, FALSE);
+
+	pk_package_id_free (ident);
+	return text;
+}
+
+/**
+ * pk_package_id_get_name:
+ **/
+gchar *
+gpk_package_get_name (const gchar *package_id)
+{
+	gchar *package = NULL;
+	PkPackageId *ident;
+
+	ident = pk_package_id_new_from_string (package_id);
+	if (ident == NULL) {
+		package = g_strdup (package_id);
+	} else {
+		package = g_strdup (ident->name);
+	}
+	pk_package_id_free (ident);
+	return package;
+}
+
+/**
+ * gpk_error_enum_to_localised_text:
+ **/
+const gchar *
+gpk_error_enum_to_localised_text (PkErrorCodeEnum code)
+{
+	const gchar *text = NULL;
+	switch (code) {
+	case PK_ERROR_ENUM_NO_NETWORK:
+		text = _("No network connection available");
+		break;
+	case PK_ERROR_ENUM_NO_CACHE:
+		text = _("No package cache is available.");
+		break;
+	case PK_ERROR_ENUM_OOM:
+		text = _("Out of memory");
+		break;
+	case PK_ERROR_ENUM_CREATE_THREAD_FAILED:
+		text = _("Failed to create a thread");
+		break;
+	case PK_ERROR_ENUM_NOT_SUPPORTED:
+		text = _("Not supported by this backend");
+		break;
+	case PK_ERROR_ENUM_INTERNAL_ERROR:
+		text = _("An internal system error has occurred");
+		break;
+	case PK_ERROR_ENUM_GPG_FAILURE:
+		text = _("A security trust relationship is not present");
+		break;
+	case PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED:
+		text = _("The package is not installed");
+		break;
+	case PK_ERROR_ENUM_PACKAGE_NOT_FOUND:
+		text = _("The package was not found");
+		break;
+	case PK_ERROR_ENUM_PACKAGE_ALREADY_INSTALLED:
+		text = _("The package is already installed");
+		break;
+	case PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED:
+		text = _("The package download failed");
+		break;
+	case PK_ERROR_ENUM_GROUP_NOT_FOUND:
+		text = _("The group was not found");
+		break;
+	case PK_ERROR_ENUM_DEP_RESOLUTION_FAILED:
+		text = _("Dependency resolution failed");
+		break;
+	case PK_ERROR_ENUM_FILTER_INVALID:
+		text = _("Search filter was invalid");
+		break;
+	case PK_ERROR_ENUM_PACKAGE_ID_INVALID:
+		text = _("The package identifier was not well formed");
+		break;
+	case PK_ERROR_ENUM_TRANSACTION_ERROR:
+		text = _("Transaction error");
+		break;
+	case PK_ERROR_ENUM_REPO_NOT_FOUND:
+		text = _("Repository name was not found");
+		break;
+	case PK_ERROR_ENUM_CANNOT_REMOVE_SYSTEM_PACKAGE:
+		text = _("Could not remove a protected system package");
+		break;
+	case PK_ERROR_ENUM_TRANSACTION_CANCELLED:
+		text = _("The task was canceled");
+		break;
+	case PK_ERROR_ENUM_PROCESS_KILL:
+		text = _("The task was forcibly canceled");
+		break;
+	case PK_ERROR_ENUM_FAILED_CONFIG_PARSING:
+		text = _("Reading the config file failed");
+		break;
+	case PK_ERROR_ENUM_CANNOT_CANCEL:
+		text = _("The task cannot be cancelled");
+		break;
+	case PK_ERROR_ENUM_CANNOT_INSTALL_SOURCE_PACKAGE:
+		text = _("Source packages cannot be installed");
+		break;
+	case PK_ERROR_ENUM_NO_LICENSE_AGREEMENT:
+		text = _("The license agreement failed");
+		break;
+	case PK_ERROR_ENUM_FILE_CONFLICTS:
+		text = _("Local file conflict between packages");
+		break;
+	case PK_ERROR_ENUM_REPO_NOT_AVAILABLE:
+		text = _("Problem connecting to a software source");
+		break;
+	case PK_ERROR_ENUM_FAILED_INITIALIZATION:
+		text = _("Failed to initialize");
+		break;
+	case PK_ERROR_ENUM_FAILED_FINALISE:
+		text = _("Failed to finalise");
+		break;
+	case PK_ERROR_ENUM_CANNOT_GET_LOCK:
+		text = _("Cannot get lock");
+		break;
+	case PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE:
+		text = _("No packages to update");
+		break;
+	case PK_ERROR_ENUM_CANNOT_WRITE_REPO_CONFIG:
+		text = _("Cannot write repository configuration");
+		break;
+	case PK_ERROR_ENUM_LOCAL_INSTALL_FAILED:
+		text = _("Local install failed");
+		break;
+	case PK_ERROR_ENUM_BAD_GPG_SIGNATURE:
+		text = _("Bad GPG signature");
+		break;
+	case PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR:
+		text = _("Repository configuration invalid");
+		break;
+	default:
+		g_warning ("Unknown error");
+	}
+	return text;
+}
+
+/**
+ * gpk_error_enum_to_localised_message:
+ **/
+const gchar *
+gpk_error_enum_to_localised_message (PkErrorCodeEnum code)
+{
+	const gchar *text = NULL;
+	switch (code) {
+	case PK_ERROR_ENUM_NO_NETWORK:
+		text = _("There is no network connection available.\n"
+			 "Please check your connection settings and try again");
+		break;
+	case PK_ERROR_ENUM_NO_CACHE:
+		text = _("The package list needs to be rebuilt.\n"
+			 "This should have been done by the backend automatically.");
+		break;
+	case PK_ERROR_ENUM_OOM:
+		text = _("The service that is responsible for handling user requests is out of memory.\n"
+			 "Please restart your computer.");
+		break;
+	case PK_ERROR_ENUM_CREATE_THREAD_FAILED:
+		text = _("A thread could not be created to service the user request.");
+		break;
+	case PK_ERROR_ENUM_NOT_SUPPORTED:
+		text = _("The action is not supported by this backend.\n"
+			 "Please report a bug as this shouldn't have happened.");
+		break;
+	case PK_ERROR_ENUM_INTERNAL_ERROR:
+		text = _("A problem that we were not expecting has occurred.\n"
+			 "Please report this bug with the error description.");
+		break;
+	case PK_ERROR_ENUM_GPG_FAILURE:
+		text = _("A security trust relationship could not be made with software source.\n"
+			 "Please check your security settings.");
+		break;
+	case PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED:
+		text = _("The package that is trying to be removed or updated is not already installed.");
+		break;
+	case PK_ERROR_ENUM_PACKAGE_NOT_FOUND:
+		text = _("The package that is being modified was not found on your system or in any software source.");
+		break;
+	case PK_ERROR_ENUM_PACKAGE_ALREADY_INSTALLED:
+		text = _("The package that is trying to be installed is already installed.");
+		break;
+	case PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED:
+		text = _("The package download failed.\n"
+			 "Please check your network connectivity.");
+		break;
+	case PK_ERROR_ENUM_GROUP_NOT_FOUND:
+		text = _("The group type was not found.\n"
+			 "Please check your group list and try again.");
+		break;
+	case PK_ERROR_ENUM_DEP_RESOLUTION_FAILED:
+		text = _("A package could not be found that allows the task to complete.\n"
+			 "More information is available in the detailed report.");
+		break;
+	case PK_ERROR_ENUM_FILTER_INVALID:
+		text = _("The search filter was not correctly formed.");
+		break;
+	case PK_ERROR_ENUM_PACKAGE_ID_INVALID:
+		text = _("The package identifier was not well formed when sent to the server.\n"
+			 "This normally indicates an internal error and should be reported.");
+		break;
+	case PK_ERROR_ENUM_TRANSACTION_ERROR:
+		text = _("An unspecified task error has occurred.\n"
+			 "More information is available in the detailed report.");
+		break;
+	case PK_ERROR_ENUM_REPO_NOT_FOUND:
+		text = _("The remote software source name was not found.\n"
+			 "You may need to enable an item in Software Sources");
+		break;
+	case PK_ERROR_ENUM_CANNOT_REMOVE_SYSTEM_PACKAGE:
+		text = _("Removing a protected system package is not alloed.");
+		break;
+	case PK_ERROR_ENUM_TRANSACTION_CANCELLED:
+		text = _("The task was canceled successfully and no packages were changed.");
+		break;
+	case PK_ERROR_ENUM_PROCESS_KILL:
+		text = _("The task was canceled successfully and no packages were changed.\n"
+			 "The backend did not exit cleanly.");
+		break;
+	case PK_ERROR_ENUM_FAILED_CONFIG_PARSING:
+		text = _("The native package configuration file could not be opened.\n"
+			 "Please make sure configuration is valid.");
+		break;
+	case PK_ERROR_ENUM_CANNOT_CANCEL:
+		text = _("The task is not safe to be cancelled at this time.");
+		break;
+	case PK_ERROR_ENUM_CANNOT_INSTALL_SOURCE_PACKAGE:
+		text = _("Source packages are not normally installed this way.\n"
+			 "Check the extension of the file you are trying to install.");
+		break;
+	case PK_ERROR_ENUM_NO_LICENSE_AGREEMENT:
+		text = _("The license agreement was not agreed to.\n"
+			 "To use this software you have to accept the license.");
+		break;
+	case PK_ERROR_ENUM_FILE_CONFLICTS:
+		text = _("Two packages provide the same file.\n"
+			 "This is usually due to mixing packages for different software sources.");
+		break;
+	case PK_ERROR_ENUM_REPO_NOT_AVAILABLE:
+		text = _("There was a (possibly temporary) problem connecting to a software source\n"
+			 "Please check the detailed error for further details.");
+		break;
+	case PK_ERROR_ENUM_FAILED_INITIALIZATION:
+		text = _("Failed to initialize packaging backend.\n"
+			 "This may occur if other packaging tools are being used simultaneously.");
+		break;
+	case PK_ERROR_ENUM_FAILED_FINALISE:
+		text = _("Failed to close down the backend instance.\n"
+			 "This error can normally be ignored.");
+		break;
+	case PK_ERROR_ENUM_CANNOT_GET_LOCK:
+		text = _("Cannot get the exclusive lock on the packaging backend.\n"
+			 "Please close any other legacy packaging tools that may be open.");
+		break;
+	case PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE:
+		text = _("No packages that were selected we able to be updated.");
+		break;
+	case PK_ERROR_ENUM_CANNOT_WRITE_REPO_CONFIG:
+		text = _("The repository configuration could not be modified.");
+		break;
+	case PK_ERROR_ENUM_LOCAL_INSTALL_FAILED:
+		text = _("Installing the local file failed.\n"
+			 "More information is available in the detailed report.");
+		break;
+	case PK_ERROR_ENUM_BAD_GPG_SIGNATURE:
+		text = _("The software source signature could not be verified.");
+		break;
+	case PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR:
+		text = _("Repository configuration was invalid and could not be read.");
+		break;
+	default:
+		g_warning ("Unknown error, please report a bug.\n"
+			   "More information is available in the detailed report.");
+	}
+	return text;
+}
+
+/**
+ * gpk_restart_enum_to_localised_text_future:
+ **/
+const gchar *
+gpk_restart_enum_to_localised_text_future (PkRestartEnum restart)
+{
+	const gchar *text = NULL;
+	switch (restart) {
+	case PK_RESTART_ENUM_NONE:
+		text = _("No restart is necessary for this update");
+		break;
+	case PK_RESTART_ENUM_APPLICATION:
+		text = _("An application restart is required after this update");
+		break;
+	case PK_RESTART_ENUM_SESSION:
+		text = _("You will be required to log off and back on after this update");
+		break;
+	case PK_RESTART_ENUM_SYSTEM:
+		text = _("A system restart is required after this update");
+		break;
+	default:
+		pk_warning ("restart unrecognised: %i", restart);
+	}
+	return text;
+}
+
+/**
+ * gpk_restart_enum_to_localised_text:
+ **/
+const gchar *
+gpk_restart_enum_to_localised_text (PkRestartEnum restart)
+{
+	const gchar *text = NULL;
+	switch (restart) {
+	case PK_RESTART_ENUM_NONE:
+		text = _("No restart is required");
+		break;
+	case PK_RESTART_ENUM_SYSTEM:
+		text = _("A system restart is required");
+		break;
+	case PK_RESTART_ENUM_SESSION:
+		text = _("You will need to log off and log back on");
+		break;
+	case PK_RESTART_ENUM_APPLICATION:
+		text = _("You need to restart the application");
+		break;
+	default:
+		pk_warning ("restart unrecognised: %i", restart);
+	}
+	return text;
+}
+
+/**
+ * gpk_message_enum_to_localised_text:
+ **/
+const gchar *
+gpk_message_enum_to_localised_text (PkMessageEnum message)
+{
+	const gchar *text = NULL;
+	switch (message) {
+	case PK_MESSAGE_ENUM_NOTICE:
+		text = _("PackageKit notice");
+		break;
+	case PK_MESSAGE_ENUM_WARNING:
+		text = _("PackageKit warning");
+		break;
+	case PK_MESSAGE_ENUM_DAEMON:
+		text = _("PackageKit daemon");
+		break;
+	default:
+		pk_warning ("message unrecognised: %i", message);
+	}
+	return text;
+}
+
+/**
+ * gpk_status_enum_to_localised_text:
+ **/
+const gchar *
+gpk_status_enum_to_localised_text (PkStatusEnum status)
+{
+	const gchar *text = NULL;
+	switch (status) {
+	case PK_STATUS_ENUM_UNKNOWN:
+		text = _("Unknown state");
+		break;
+	case PK_STATUS_ENUM_SETUP:
+		text = _("Waiting for PackageKit service");
+		break;
+	case PK_STATUS_ENUM_WAIT:
+		text = _("Waiting for other tasks to complete");
+		break;
+	case PK_STATUS_ENUM_RUNNING:
+		text = _("Running task");
+		break;
+	case PK_STATUS_ENUM_QUERY:
+		text = _("Querying");
+		break;
+	case PK_STATUS_ENUM_INFO:
+		text = _("Getting information");
+		break;
+	case PK_STATUS_ENUM_REMOVE:
+		text = _("Removing");
+		break;
+	case PK_STATUS_ENUM_DOWNLOAD:
+		text = _("Downloading");
+		break;
+	case PK_STATUS_ENUM_INSTALL:
+		text = _("Installing");
+		break;
+	case PK_STATUS_ENUM_REFRESH_CACHE:
+		text = _("Refreshing software list");
+		break;
+	case PK_STATUS_ENUM_UPDATE:
+		text = _("Updating");
+		break;
+	case PK_STATUS_ENUM_CLEANUP:
+		text = _("Cleaning up");
+		break;
+	case PK_STATUS_ENUM_OBSOLETE:
+		text = _("Obsoleting");
+		break;
+	case PK_STATUS_ENUM_DEP_RESOLVE:
+		text = _("Resolving dependencies");
+		break;
+	case PK_STATUS_ENUM_SIG_CHECK:
+		text = _("Checking signatures");
+		break;
+	case PK_STATUS_ENUM_ROLLBACK:
+		text = _("Rolling back");
+		break;
+	case PK_STATUS_ENUM_TEST_COMMIT:
+		text = _("Testing changes");
+		break;
+	case PK_STATUS_ENUM_COMMIT:
+		text = _("Committing changes");
+		break;
+	case PK_STATUS_ENUM_REQUEST:
+		text = _("Requesting data");
+		break;
+	case PK_STATUS_ENUM_FINISHED:
+		text = _("Finished");
+		break;
+	case PK_STATUS_ENUM_CANCEL:
+		text = _("Cancelling");
+		break;
+	case PK_STATUS_ENUM_DOWNLOAD_REPOSITORY:
+		text = _("Downloading repository information");
+		break;
+	case PK_STATUS_ENUM_DOWNLOAD_PACKAGELIST:
+		text = _("Downloading list of packages");
+		break;
+	case PK_STATUS_ENUM_DOWNLOAD_FILELIST:
+		text = _("Downloading file lists");
+		break;
+	case PK_STATUS_ENUM_DOWNLOAD_CHANGELOG:
+		text = _("Downloading lists of changes");
+		break;
+	case PK_STATUS_ENUM_DOWNLOAD_GROUP:
+		text = _("Downloading groups");
+		break;
+	case PK_STATUS_ENUM_DOWNLOAD_UPDATEINFO:
+		text = _("Downloading update information");
+		break;
+	default:
+		pk_warning ("status unrecognised: %s", pk_status_enum_to_text (status));
+	}
+	return text;
+}
+
+/**
+ * gpk_update_enum_to_localised_text:
+ **/
+gchar *
+gpk_update_enum_to_localised_text (PkInfoEnum info, guint number)
+{
+	gchar *text = NULL;
+	switch (info) {
+	case PK_INFO_ENUM_LOW:
+		text = g_strdup_printf (ngettext ("%i trivial update", "%i trivial updates", number), number);
+		break;
+	case PK_INFO_ENUM_NORMAL:
+		text = g_strdup_printf (ngettext ("%i update", "%i updates", number), number);
+		break;
+	case PK_INFO_ENUM_IMPORTANT:
+		text = g_strdup_printf (ngettext ("%i important update", "%i important updates", number), number);
+		break;
+	case PK_INFO_ENUM_SECURITY:
+		text = g_strdup_printf (ngettext ("%i security update", "%i security updates", number), number);
+		break;
+	case PK_INFO_ENUM_BUGFIX:
+		text = g_strdup_printf (ngettext ("%i bug fix update", "%i bug fix updates", number), number);
+		break;
+	case PK_INFO_ENUM_ENHANCEMENT:
+		text = g_strdup_printf (ngettext ("%i enhancement update", "%i enhancement updates", number), number);
+		break;
+	default:
+		pk_warning ("update info unrecognised: %s", pk_info_enum_to_text (info));
+	}
+	return text;
+}
+
+/**
+ * gpk_info_enum_to_localised_text:
+ **/
+const gchar *
+gpk_info_enum_to_localised_text (PkInfoEnum info)
+{
+	const gchar *text = NULL;
+	switch (info) {
+	case PK_INFO_ENUM_LOW:
+		text = _("Trivial update");
+		break;
+	case PK_INFO_ENUM_NORMAL:
+		text = _("Update");
+		break;
+	case PK_INFO_ENUM_IMPORTANT:
+		text = _("Important update");
+		break;
+	case PK_INFO_ENUM_SECURITY:
+		text = _("Security update");
+		break;
+	case PK_INFO_ENUM_BUGFIX:
+		text = _("Bug fix update");
+		break;
+	case PK_INFO_ENUM_ENHANCEMENT:
+		text = _("Enhancement update");
+		break;
+	case PK_INFO_ENUM_BLOCKED:
+		text = _("Blocked update");
+		break;
+	case PK_INFO_ENUM_INSTALLED:
+		text = _("Installed");
+		break;
+	case PK_INFO_ENUM_AVAILABLE:
+		text = _("Available");
+		break;
+	default:
+		pk_warning ("info unrecognised: %s", pk_info_enum_to_text (info));
+	}
+	return text;
+}
+
+/**
+ * gpk_info_enum_to_localised_present:
+ **/
+const gchar *
+gpk_info_enum_to_localised_present (PkInfoEnum info)
+{
+	const gchar *text = NULL;
+	switch (info) {
+	case PK_INFO_ENUM_DOWNLOADING:
+		text = _("Downloading");
+		break;
+	case PK_INFO_ENUM_UPDATING:
+		text = _("Updating");
+		break;
+	case PK_INFO_ENUM_INSTALLING:
+		text = _("Installing");
+		break;
+	case PK_INFO_ENUM_REMOVING:
+		text = _("Removing");
+		break;
+	case PK_INFO_ENUM_CLEANUP:
+		text = _("Cleaning up");
+		break;
+	case PK_INFO_ENUM_OBSOLETING:
+		text = _("Obsoleting");
+		break;
+	default:
+		pk_warning ("info unrecognised: %s", pk_info_enum_to_text (info));
+	}
+	return text;
+}
+
+/**
+ * gpk_info_enum_to_localised_past:
+ **/
+const gchar *
+gpk_info_enum_to_localised_past (PkInfoEnum info)
+{
+	const gchar *text = NULL;
+	switch (info) {
+	case PK_INFO_ENUM_DOWNLOADING:
+		text = _("Downloaded");
+		break;
+	case PK_INFO_ENUM_UPDATING:
+		text = _("Updated");
+		break;
+	case PK_INFO_ENUM_INSTALLING:
+		text = _("Installed");
+		break;
+	case PK_INFO_ENUM_REMOVING:
+		text = _("Removed");
+		break;
+	case PK_INFO_ENUM_CLEANUP:
+		text = _("Cleaned up");
+		break;
+	case PK_INFO_ENUM_OBSOLETING:
+		text = _("Obsoleted");
+		break;
+	default:
+		pk_warning ("info unrecognised: %s", pk_info_enum_to_text (info));
+	}
+	return text;
+}
+
+/**
+ * gpk_role_enum_to_localised_present:
+ **/
+const gchar *
+gpk_role_enum_to_localised_present (PkRoleEnum role)
+{
+	const gchar *text = NULL;
+	switch (role) {
+	case PK_ROLE_ENUM_UNKNOWN:
+		text = _("Unknown role type");
+		break;
+	case PK_ROLE_ENUM_GET_DEPENDS:
+		text = _("Getting dependencies");
+		break;
+	case PK_ROLE_ENUM_GET_UPDATE_DETAIL:
+		text = _("Getting update detail");
+		break;
+	case PK_ROLE_ENUM_GET_DESCRIPTION:
+		text = _("Getting description");
+		break;
+	case PK_ROLE_ENUM_GET_REQUIRES:
+		text = _("Getting requires");
+		break;
+	case PK_ROLE_ENUM_GET_UPDATES:
+		text = _("Getting updates");
+		break;
+	case PK_ROLE_ENUM_SEARCH_DETAILS:
+		text = _("Searching details");
+		break;
+	case PK_ROLE_ENUM_SEARCH_FILE:
+		text = _("Searching for file");
+		break;
+	case PK_ROLE_ENUM_SEARCH_GROUP:
+		text = _("Searching groups");
+		break;
+	case PK_ROLE_ENUM_SEARCH_NAME:
+		text = _("Searching for package name");
+		break;
+	case PK_ROLE_ENUM_REMOVE_PACKAGE:
+		text = _("Removing");
+		break;
+	case PK_ROLE_ENUM_INSTALL_PACKAGE:
+		text = _("Installing");
+		break;
+	case PK_ROLE_ENUM_INSTALL_FILE:
+		text = _("Installing file");
+		break;
+	case PK_ROLE_ENUM_REFRESH_CACHE:
+		text = _("Refreshing package cache");
+		break;
+	case PK_ROLE_ENUM_UPDATE_PACKAGES:
+		text = _("Updating packages");
+		break;
+	case PK_ROLE_ENUM_UPDATE_SYSTEM:
+		text = _("Updating system");
+		break;
+	case PK_ROLE_ENUM_CANCEL:
+		text = _("Canceling");
+		break;
+	case PK_ROLE_ENUM_ROLLBACK:
+		text = _("Rolling back");
+		break;
+	case PK_ROLE_ENUM_GET_REPO_LIST:
+		text = _("Getting list of repositories");
+		break;
+	case PK_ROLE_ENUM_REPO_ENABLE:
+		text = _("Enabling repository");
+		break;
+	case PK_ROLE_ENUM_REPO_SET_DATA:
+		text = _("Setting repository data");
+		break;
+	case PK_ROLE_ENUM_RESOLVE:
+		text = _("Resolved");
+		break;
+	case PK_ROLE_ENUM_GET_FILES:
+		text = _("Getting file list");
+		break;
+	case PK_ROLE_ENUM_WHAT_PROVIDES:
+		text = _("Getting what provides");
+		break;
+	case PK_ROLE_ENUM_SERVICE_PACK:
+		text = _("Service pack");
+		break;
+	case PK_ROLE_ENUM_INSTALL_SIGNATURE:
+		text = _("Installing signature");
+		break;
+	case PK_ROLE_ENUM_GET_PACKAGES:
+		text = _("Getting package lists");
+		break;
+	case PK_ROLE_ENUM_ACCEPT_EULA:
+		text = _("Accepting EULA");
+		break;
+	default:
+		pk_warning ("role unrecognised: %s", pk_role_enum_to_text (role));
+	}
+	return text;
+}
+
+/**
+ * gpk_role_enum_to_localised_past:
+ *
+ * These are past tense versions of the action
+ **/
+const gchar *
+gpk_role_enum_to_localised_past (PkRoleEnum role)
+{
+	const gchar *text = NULL;
+	switch (role) {
+	case PK_ROLE_ENUM_UNKNOWN:
+		text = _("Unknown role type");
+		break;
+	case PK_ROLE_ENUM_GET_DEPENDS:
+		text = _("Got dependencies");
+		break;
+	case PK_ROLE_ENUM_GET_UPDATE_DETAIL:
+		text = _("Got update detail");
+		break;
+	case PK_ROLE_ENUM_GET_DESCRIPTION:
+		text = _("Got description");
+		break;
+	case PK_ROLE_ENUM_GET_REQUIRES:
+		text = _("Got requires");
+		break;
+	case PK_ROLE_ENUM_GET_UPDATES:
+		text = _("Got updates");
+		break;
+	case PK_ROLE_ENUM_SEARCH_DETAILS:
+		text = _("Got details");
+		break;
+	case PK_ROLE_ENUM_SEARCH_FILE:
+		text = _("Searched for file");
+		break;
+	case PK_ROLE_ENUM_SEARCH_GROUP:
+		text = _("Searched groups");
+		break;
+	case PK_ROLE_ENUM_SEARCH_NAME:
+		text = _("Searched for package name");
+		break;
+	case PK_ROLE_ENUM_REMOVE_PACKAGE:
+		text = _("Removed package");
+		break;
+	case PK_ROLE_ENUM_INSTALL_PACKAGE:
+		text = _("Installed package");
+		break;
+	case PK_ROLE_ENUM_INSTALL_FILE:
+		text = _("Installed local file");
+		break;
+	case PK_ROLE_ENUM_SERVICE_PACK:
+		text = _("Updating from service pack");
+		break;
+	case PK_ROLE_ENUM_REFRESH_CACHE:
+		text = _("Refreshed package cache");
+		break;
+	case PK_ROLE_ENUM_UPDATE_PACKAGES:
+		text = _("Updated package");
+		break;
+	case PK_ROLE_ENUM_UPDATE_SYSTEM:
+		text = _("Updated system");
+		break;
+	case PK_ROLE_ENUM_CANCEL:
+		text = _("Canceled");
+		break;
+	case PK_ROLE_ENUM_ROLLBACK:
+		text = _("Rolled back");
+		break;
+	case PK_ROLE_ENUM_GET_REPO_LIST:
+		text = _("Got list of repositories");
+		break;
+	case PK_ROLE_ENUM_REPO_ENABLE:
+		text = _("Enabled repository");
+		break;
+	case PK_ROLE_ENUM_REPO_SET_DATA:
+		text = _("Set repository data");
+		break;
+	case PK_ROLE_ENUM_RESOLVE:
+		text = _("Resolved");
+		break;
+	case PK_ROLE_ENUM_GET_FILES:
+		text = _("Got file list");
+		break;
+	case PK_ROLE_ENUM_WHAT_PROVIDES:
+		text = _("Got what provides");
+		break;
+	case PK_ROLE_ENUM_INSTALL_SIGNATURE:
+		text = _("Installed signature");
+		break;
+	case PK_ROLE_ENUM_GET_PACKAGES:
+		text = _("Got package lists");
+		break;
+	case PK_ROLE_ENUM_ACCEPT_EULA:
+		text = _("Accepted EULA");
+		break;
+	default:
+		pk_warning ("role unrecognised: %s", pk_role_enum_to_text (role));
+	}
+	return text;
+}
+
+/**
+ * gpk_group_enum_to_localised_text:
+ **/
+const gchar *
+gpk_group_enum_to_localised_text (PkGroupEnum group)
+{
+	const gchar *text = NULL;
+	switch (group) {
+	case PK_GROUP_ENUM_ACCESSIBILITY:
+		text = _("Accessibility");
+		break;
+	case PK_GROUP_ENUM_ACCESSORIES:
+		text = _("Accessories");
+		break;
+	case PK_GROUP_ENUM_EDUCATION:
+		text = _("Education");
+		break;
+	case PK_GROUP_ENUM_GAMES:
+		text = _("Games");
+		break;
+	case PK_GROUP_ENUM_GRAPHICS:
+		text = _("Graphics");
+		break;
+	case PK_GROUP_ENUM_INTERNET:
+		text = _("Internet");
+		break;
+	case PK_GROUP_ENUM_OFFICE:
+		text = _("Office");
+		break;
+	case PK_GROUP_ENUM_OTHER:
+		text = _("Other");
+		break;
+	case PK_GROUP_ENUM_PROGRAMMING:
+		text = _("Programming");
+		break;
+	case PK_GROUP_ENUM_MULTIMEDIA:
+		text = _("Multimedia");
+		break;
+	case PK_GROUP_ENUM_SYSTEM:
+		text = _("System");
+		break;
+	case PK_GROUP_ENUM_DESKTOP_GNOME:
+		text = _("GNOME desktop");
+		break;
+	case PK_GROUP_ENUM_DESKTOP_KDE:
+		text = _("KDE desktop");
+		break;
+	case PK_GROUP_ENUM_DESKTOP_XFCE:
+		text = _("XFCE desktop");
+		break;
+	case PK_GROUP_ENUM_DESKTOP_OTHER:
+		text = _("Other desktops");
+		break;
+	case PK_GROUP_ENUM_PUBLISHING:
+		text = _("Publishing");
+		break;
+	case PK_GROUP_ENUM_SERVERS:
+		text = _("Servers");
+		break;
+	case PK_GROUP_ENUM_FONTS:
+		text = _("Fonts");
+		break;
+	case PK_GROUP_ENUM_ADMIN_TOOLS:
+		text = _("Admin tools");
+		break;
+	case PK_GROUP_ENUM_LEGACY:
+		text = _("Legacy");
+		break;
+	case PK_GROUP_ENUM_LOCALIZATION:
+		text = _("Localization");
+		break;
+	case PK_GROUP_ENUM_VIRTUALIZATION:
+		text = _("Virtualization");
+		break;
+	case PK_GROUP_ENUM_SECURITY:
+		text = _("Security");
+		break;
+	case PK_GROUP_ENUM_POWER_MANAGEMENT:
+		text = _("Power management");
+		break;
+	case PK_GROUP_ENUM_COMMUNICATION:
+		text = _("Communication");
+		break;
+	case PK_GROUP_ENUM_NETWORK:
+		text = _("Network");
+		break;
+	case PK_GROUP_ENUM_MAPS:
+		text = _("Maps");
+		break;
+	case PK_GROUP_ENUM_REPOS:
+		text = _("Software sources");
+		break;
+	case PK_GROUP_ENUM_UNKNOWN:
+		text = _("Unknown group");
+		break;
+	default:
+		pk_warning ("group unrecognised: %i", group);
+	}
+	return text;
+}
+
+/**
+ * gpk_info_enum_to_icon_name:
+ **/
+const gchar *
+gpk_info_enum_to_icon_name (PkInfoEnum info)
+{
+	return pk_enum_find_string (enum_info_icon_name, info);
+}
+
+/**
+ * gpk_status_enum_to_icon_name:
+ **/
+const gchar *
+gpk_status_enum_to_icon_name (PkStatusEnum status)
+{
+	return pk_enum_find_string (enum_status_icon_name, status);
+}
+
+/**
+ * gpk_role_enum_to_icon_name:
+ **/
+const gchar *
+gpk_role_enum_to_icon_name (PkRoleEnum role)
+{
+	return pk_enum_find_string (enum_role_icon_name, role);
+}
+
+/**
+ * gpk_group_enum_to_icon_name:
+ **/
+const gchar *
+gpk_group_enum_to_icon_name (PkGroupEnum group)
+{
+	return pk_enum_find_string (enum_group_icon_name, group);
+}
+
+/**
+ * gpk_restart_enum_to_icon_name:
+ **/
+const gchar *
+gpk_restart_enum_to_icon_name (PkRestartEnum restart)
+{
+	return pk_enum_find_string (enum_restart_icon_name, restart);
+}
+
+/**
+ * gpk_message_enum_to_icon_name:
+ **/
+const gchar *
+gpk_message_enum_to_icon_name (PkMessageEnum message)
+{
+	return pk_enum_find_string (enum_message_icon_name, message);
+}
+
+/**
+ * gpk_time_to_localised_string:
+ * @time_secs: The time value to convert in seconds
+ *
+ * Returns a localised timestring
+ *
+ * Return value: The time string, e.g. "2 hours 3 minutes"
+ **/
+gchar *
+gpk_time_to_localised_string (guint time_secs)
+{
+	gchar* timestring = NULL;
+	guint hours;
+	guint minutes;
+	guint seconds;
+
+	/* is valid? */
+	if (time_secs == 0) {
+		timestring = g_strdup_printf (_("Now"));
+		return timestring;
+	}
+
+	/* make local copy */
+	seconds = time_secs;
+
+	/* less than a minute */
+	if (seconds < 60) {
+		timestring = g_strdup_printf (ngettext ("%i second",
+							"%i seconds",
+							seconds), seconds);
+		return timestring;
+	}
+
+	/* Add 0.5 to do rounding */
+	minutes = (guint) ((time_secs / 60.0 ) + 0.5);
+	seconds = seconds % 60;
+
+	/* less than an hour */
+	if (minutes < 60) {
+		if (seconds == 0) {
+			timestring = g_strdup_printf (ngettext ("%i minute",
+								"%i minutes",
+								minutes), minutes);
+		} else {
+			/* TRANSLATOR: "%i %s %i %s" are "%i minutes %i seconds"
+			 * Swap order with "%2$s %2$i %1$s %1$i if needed */
+			timestring = g_strdup_printf (_("%i %s %i %s"),
+					minutes, ngettext ("minute", "minutes", minutes),
+					seconds, ngettext ("second", "seconds", seconds));
+		}
+		return timestring;
+	}
+
+	/* more than an hour */
+	hours = minutes / 60;
+	minutes = minutes % 60;
+	if (minutes == 0) {
+		timestring = g_strdup_printf (ngettext (
+				"%i hour",
+				"%i hours",
+				hours), hours);
+	} else {
+		/* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes"
+		 * Swap order with "%2$s %2$i %1$s %1$i if needed */
+		timestring = g_strdup_printf (_("%i %s %i %s"),
+				hours, ngettext ("hour", "hours", hours),
+				minutes, ngettext ("minute", "minutes", minutes));
+	}
+	return timestring;
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef PK_BUILD_TESTS
+#include <libselftest.h>
+
+void
+gpk_common_self_test (gpointer data)
+{
+	gchar *text;
+	guint i;
+	const gchar *string;
+	LibSelfTest *test = (LibSelfTest *) data;
+
+	if (libst_start (test, "GpkCommon", CLASS_AUTO) == FALSE) {
+		return;
+	}
+
+	/************************************************************
+	 ****************        time text             **************
+	 ************************************************************/
+	libst_title (test, "time zero");
+	text = gpk_time_to_localised_string (0);
+	if (text != NULL && strcmp (text, _("Now")) == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************/
+	libst_title (test, "time 1s");
+	text = gpk_time_to_localised_string (1);
+	if (text != NULL && strcmp (text, _("1 second")) == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************/
+	libst_title (test, "time 1m");
+	text = gpk_time_to_localised_string (1*60);
+	if (text != NULL && strcmp (text, _("1 minute")) == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************/
+	libst_title (test, "time 1h");
+	text = gpk_time_to_localised_string (1*60*60);
+	if (text != NULL && strcmp (text, _("1 hour")) == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************/
+	libst_title (test, "time 30s");
+	text = gpk_time_to_localised_string (30);
+	if (text != NULL && strcmp (text, _("30 seconds")) == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************/
+	libst_title (test, "time 30m");
+	text = gpk_time_to_localised_string (30*60);
+	if (text != NULL && strcmp (text, _("30 minutes")) == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************/
+	libst_title (test, "time 30m1s");
+	text = gpk_time_to_localised_string (30*60+1);
+	if (text != NULL && strcmp (text, _("30 minutes 1 second")) == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************/
+	libst_title (test, "time 30m10s");
+	text = gpk_time_to_localised_string (30*60+10);
+	if (text != NULL && strcmp (text, _("30 minutes 10 seconds")) == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************
+	 ****************        size text             **************
+	 ************************************************************/
+	libst_title (test, "size zero");
+	text = gpk_size_to_si_size_text (0);
+	if (text != NULL && strcmp (text, _("0 bytes")) == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************/
+	libst_title (test, "size 512 bytes");
+	text = gpk_size_to_si_size_text (512);
+	if (text != NULL && strcmp (text, _("512 bytes")) == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************/
+	libst_title (test, "size 256.2 MB");
+	text = gpk_size_to_si_size_text (256*1025*1024);
+	if (text != NULL && strcmp (text, _("256.2 MB")) == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************
+	 ****************     package name text        **************
+	 ************************************************************/
+	libst_title (test, "get name null");
+	text = gpk_package_get_name (NULL);
+	if (text == NULL) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+
+	/************************************************************/
+	libst_title (test, "get name not id");
+	text = gpk_package_get_name ("ania");
+	if (text != NULL && strcmp (text, "ania") == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************/
+	libst_title (test, "get name just id");
+	text = gpk_package_get_name ("simon;1.0.0;i386;moo");
+	if (text != NULL && strcmp (text, "simon") == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************
+	 ****************     package name text        **************
+	 ************************************************************/
+	libst_title (test, "package id pretty null");
+	text = gpk_package_id_format_twoline (NULL, NULL);
+	if (text == NULL) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+
+	/************************************************************/
+	libst_title (test, "package id pretty valid package id, no summary");
+	text = gpk_package_id_format_twoline ("simon;0.0.1;i386;data", NULL);
+	if (text != NULL && strcmp (text, "simon-0.0.1 (i386)") == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************/
+	libst_title (test, "package id pretty valid package id, no summary 2");
+	text = gpk_package_id_format_twoline ("simon;0.0.1;;data", NULL);
+	if (text != NULL && strcmp (text, "simon-0.0.1") == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************/
+	libst_title (test, "package id pretty valid package id, no summary 3");
+	text = gpk_package_id_format_twoline ("simon;;;data", NULL);
+	if (text != NULL && strcmp (text, "simon") == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************/
+	libst_title (test, "package id pretty valid package id, no summary 4");
+	text = gpk_package_id_format_twoline ("simon;0.0.1;;data", "dude");
+	if (text != NULL && strcmp (text, "<b>dude</b>\nsimon-0.0.1") == 0) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, "failed, got %s", text);
+	}
+	g_free (text);
+
+	/************************************************************
+	 ****************     localised enums          **************
+	 ************************************************************/
+	libst_title (test, "check we convert all the localised past role enums");
+	for (i=1; i<PK_ROLE_ENUM_UNKNOWN; i*=2) {
+		string = gpk_role_enum_to_localised_past (i);
+		if (string == NULL) {
+			libst_failed (test, "failed to get %i", i);
+			break;
+		}
+	}
+	libst_success (test, NULL);
+
+	/************************************************************/
+	libst_title (test, "check we convert all the localised present role enums");
+	for (i=1; i<PK_ROLE_ENUM_UNKNOWN; i*=2) {
+		string = gpk_role_enum_to_localised_present (i);
+		if (string == NULL) {
+			libst_failed (test, "failed to get %i", i);
+			break;
+		}
+	}
+	libst_success (test, NULL);
+
+	/************************************************************/
+	libst_title (test, "check we convert all the role icon name enums");
+	for (i=1; i<PK_ROLE_ENUM_UNKNOWN; i*=2) {
+		string = gpk_role_enum_to_icon_name (i);
+		if (string == NULL) {
+			libst_failed (test, "failed to get %i", i);
+			break;
+		}
+	}
+	libst_success (test, NULL);
+
+	/************************************************************/
+	libst_title (test, "check we convert all the info icon names enums");
+	for (i=1; i<PK_INFO_ENUM_UNKNOWN; i*=2) {
+		string = gpk_info_enum_to_icon_name (i);
+		if (string == NULL) {
+			libst_failed (test, "failed to get %i", i);
+			break;
+		}
+	}
+	libst_success (test, NULL);
+
+	/************************************************************/
+	libst_title (test, "check we convert all the localised status enums");
+	for (i=1; i<PK_STATUS_ENUM_UNKNOWN; i*=2) {
+		string = gpk_status_enum_to_localised_text (i);
+		if (string == NULL) {
+			libst_failed (test, "failed to get %i", i);
+			break;
+		}
+	}
+	libst_success (test, NULL);
+
+	/************************************************************/
+	libst_title (test, "check we convert all the status icon names enums");
+	for (i=1; i<PK_STATUS_ENUM_UNKNOWN; i*=2) {
+		string = gpk_status_enum_to_icon_name (i);
+		if (string == NULL) {
+			libst_failed (test, "failed to get %i", i);
+			break;
+		}
+	}
+	libst_success (test, NULL);
+
+	/************************************************************/
+	libst_title (test, "check we convert all the restart icon names enums");
+	for (i=0; i<PK_RESTART_ENUM_UNKNOWN; i++) {
+		string = gpk_restart_enum_to_icon_name (i);
+		if (string == NULL) {
+			libst_failed (test, "failed to get %i", i);
+			break;
+		}
+	}
+	libst_success (test, NULL);
+
+	/************************************************************/
+	libst_title (test, "check we convert all the localised error enums");
+	for (i=0; i<PK_ERROR_ENUM_UNKNOWN; i++) {
+		string = gpk_error_enum_to_localised_text (i);
+		if (string == NULL) {
+			libst_failed (test, "failed to get %s", pk_error_enum_to_text(i));
+			break;
+		}
+	}
+	libst_success (test, NULL);
+
+	/************************************************************/
+	libst_title (test, "check we convert all the localised error messages");
+	for (i=0; i<PK_ERROR_ENUM_UNKNOWN; i++) {
+		string = gpk_error_enum_to_localised_message (i);
+		if (string == NULL) {
+			libst_failed (test, "failed to get %s", pk_error_enum_to_text(i));
+			break;
+		}
+	}
+	libst_success (test, NULL);
+
+	/************************************************************/
+	libst_title (test, "check we convert all the localised restart enums");
+	for (i=0; i<PK_RESTART_ENUM_UNKNOWN; i++) {
+		string = gpk_restart_enum_to_localised_text (i);
+		if (string == NULL) {
+			libst_failed (test, "failed to get %i", i);
+			break;
+		}
+	}
+	libst_success (test, NULL);
+
+	/************************************************************/
+	libst_title (test, "check we convert all the message icon name enums");
+	for (i=0; i<PK_MESSAGE_ENUM_UNKNOWN; i++) {
+		string = gpk_message_enum_to_icon_name (i);
+		if (string == NULL) {
+			libst_failed (test, "failed to get %i", i);
+			break;
+		}
+	}
+	libst_success (test, NULL);
+
+	/************************************************************/
+	libst_title (test, "check we convert all the localised message enums");
+	for (i=0; i<PK_MESSAGE_ENUM_UNKNOWN; i++) {
+		string = gpk_message_enum_to_localised_text (i);
+		if (string == NULL) {
+			libst_failed (test, "failed to get %i", i);
+			break;
+		}
+	}
+	libst_success (test, NULL);
+
+	/************************************************************/
+	libst_title (test, "check we convert all the localised restart future enums");
+	for (i=0; i<PK_RESTART_ENUM_UNKNOWN; i++) {
+		string = gpk_restart_enum_to_localised_text_future (i);
+		if (string == NULL) {
+			libst_failed (test, "failed to get %i", i);
+			break;
+		}
+	}
+	libst_success (test, NULL);
+
+	/************************************************************/
+	libst_title (test, "check we convert all the localised group enums");
+	for (i=1; i<PK_GROUP_ENUM_UNKNOWN; i*=2) {
+		string = gpk_group_enum_to_localised_text (i);
+		if (string == NULL) {
+			libst_failed (test, "failed to get %i", i);
+			break;
+		}
+	}
+	libst_success (test, NULL);
+
+	/************************************************************/
+	libst_title (test, "check we convert all the group icon name enums");
+	for (i=1; i<PK_GROUP_ENUM_UNKNOWN; i*=2) {
+		string = gpk_group_enum_to_icon_name (i);
+		if (string == NULL) {
+			libst_failed (test, "failed to get %i", i);
+			break;
+		}
+	}
+	libst_success (test, NULL);
+
+	libst_end (test);
+}
+#endif
+

Added: trunk/src/gpk-common.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-common.h	Tue Apr 22 13:40:41 2008
@@ -0,0 +1,98 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_COMMON_H
+#define __GPK_COMMON_H
+
+#include <glib-object.h>
+#include <pk-enum.h>
+
+G_BEGIN_DECLS
+
+#define GPK_CONF_NOTIFY_COMPLETED		"/apps/gnome-packagekit/notify_complete"
+#define GPK_CONF_NOTIFY_AVAILABLE		"/apps/gnome-packagekit/notify_available"
+#define GPK_CONF_NOTIFY_CRITICAL		"/apps/gnome-packagekit/notify_critical"
+#define GPK_CONF_NOTIFY_ERROR			"/apps/gnome-packagekit/notify_errors"
+#define GPK_CONF_NOTIFY_MESSAGE			"/apps/gnome-packagekit/notify_message"
+#define GPK_CONF_NOTIFY_UPDATE_STARTED		"/apps/gnome-packagekit/notify_update_started"
+#define GPK_CONF_NOTIFY_UPDATE_NOT_BATTERY	"/apps/gnome-packagekit/notify_update_not_battery"
+#define GPK_CONF_NOTIFY_UPDATE_FAILED		"/apps/gnome-packagekit/notify_update_failed"
+#define GPK_CONF_NOTIFY_UPDATE_COMPLETE		"/apps/gnome-packagekit/notify_update_complete"
+#define GPK_CONF_NOTIFY_UPDATE_COMPLETE_RESTART	"/apps/gnome-packagekit/notify_update_complete_restart"
+#define GPK_CONF_AUTOCOMPLETE			"/apps/gnome-packagekit/autocomplete"
+#define GPK_CONF_SESSION_STARTUP_TIMEOUT	"/apps/gnome-packagekit/session_startup_timeout"
+#define GPK_CONF_FREQUENCY_GET_UPDATES		"/apps/gnome-packagekit/frequency_get_updates"
+#define GPK_CONF_FREQUENCY_REFRESH_CACHE	"/apps/gnome-packagekit/frequency_refresh_cache"
+#define GPK_CONF_AUTO_UPDATE			"/apps/gnome-packagekit/auto_update"
+#define GPK_CONF_UPDATE_BATTERY			"/apps/gnome-packagekit/update_battery"
+#define GPK_CONF_REPO_SHOW_DETAILS		"/apps/gnome-packagekit/repo/show_details"
+#define GPK_CONF_SHOW_DEPENDS			"/apps/gnome-packagekit/show_depends"
+#define GPK_CONF_PROMPT_FIRMWARE		"/apps/gnome-packagekit/prompt_firmware"
+
+#define GPK_CONF_APPLICATION_FILTER_BASENAME	"/apps/gnome-packagekit/application/filter_basename"
+#define GPK_CONF_APPLICATION_FILTER_NEWEST	"/apps/gnome-packagekit/application/filter_newest"
+
+void		 gpk_common_self_test			(gpointer	 data);
+gchar		*gpk_package_get_name			(const gchar	*package_id);
+gchar		*gpk_package_id_format_twoline		(const gchar	*package_id,
+							 const gchar	*summary);
+gchar		*gpk_package_id_format_oneline		(const gchar	*package_id,
+							 const gchar	*summary);
+gchar		*gpk_package_id_name_version		(const gchar	*package_id);
+
+const gchar	*gpk_role_enum_to_localised_past	(PkRoleEnum	 role)
+							 G_GNUC_CONST;
+const gchar	*gpk_role_enum_to_localised_present	(PkRoleEnum	 role)
+							 G_GNUC_CONST;
+const gchar	*gpk_role_enum_to_icon_name		(PkRoleEnum	 role);
+const gchar	*gpk_info_enum_to_localised_text	(PkInfoEnum	 info)
+							 G_GNUC_CONST;
+const gchar	*gpk_info_enum_to_localised_past	(PkInfoEnum	 info)
+							 G_GNUC_CONST;
+const gchar	*gpk_info_enum_to_localised_present	(PkInfoEnum	 info)
+							 G_GNUC_CONST;
+const gchar	*gpk_info_enum_to_icon_name		(PkInfoEnum	 info);
+const gchar	*gpk_status_enum_to_localised_text	(PkStatusEnum	 status)
+							 G_GNUC_CONST;
+const gchar	*gpk_status_enum_to_icon_name		(PkStatusEnum	 status);
+const gchar	*gpk_restart_enum_to_icon_name		(PkRestartEnum	 restart);
+const gchar	*gpk_error_enum_to_localised_text	(PkErrorCodeEnum code)
+							 G_GNUC_CONST;
+const gchar	*gpk_error_enum_to_localised_message	(PkErrorCodeEnum code);
+const gchar	*gpk_restart_enum_to_localised_text	(PkRestartEnum	 restart)
+							 G_GNUC_CONST;
+const gchar	*gpk_message_enum_to_icon_name		(PkMessageEnum	 message);
+const gchar	*gpk_message_enum_to_localised_text	(PkMessageEnum	 message)
+							 G_GNUC_CONST;
+const gchar	*gpk_restart_enum_to_localised_text_future(PkRestartEnum	 restart)
+							 G_GNUC_CONST;
+const gchar	*gpk_group_enum_to_localised_text	(PkGroupEnum	 group)
+							 G_GNUC_CONST;
+const gchar	*gpk_group_enum_to_icon_name		(PkGroupEnum	 group);
+gchar		*gpk_size_to_si_size_text		(guint64	 size);
+gchar		*gpk_update_enum_to_localised_text	(PkInfoEnum	 info,
+							 guint		 number)
+							 G_GNUC_CONST;
+gchar		*gpk_time_to_localised_string		(guint		 time_secs);
+
+G_END_DECLS
+
+#endif	/* __GPK_COMMON_H */

Added: trunk/src/gpk-error.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-error.c	Tue Apr 22 13:40:41 2008
@@ -0,0 +1,103 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <string.h>
+#include <unistd.h>
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <pk-debug.h>
+#include <pk-common.h>
+
+#define PK_STOCK_WINDOW_ICON		"system-software-installer"
+
+/**
+ * gpk_error_dialog:
+ * @title: the localised text to put in bold as a title
+ * @message: the localised text to put as a message
+ * @details: the geeky text to in the expander, or %NULL if nothing
+ *
+ * Shows a modal error, and blocks until the user clicks close
+ **/
+gboolean
+gpk_error_dialog (const gchar *title, const gchar *message, const gchar *details)
+{
+	GtkWidget *widget;
+	GladeXML *glade_xml;
+	GtkTextBuffer *buffer = NULL;
+	gchar *text;
+
+	glade_xml = glade_xml_new (PK_DATA "/gpk-error.glade", NULL, NULL);
+
+	/* connect up actions */
+	widget = glade_xml_get_widget (glade_xml, "window_error");
+	g_signal_connect_swapped (widget, "delete_event", G_CALLBACK (gtk_main_quit), NULL);
+
+	/* set icon name */
+	gtk_window_set_icon_name (GTK_WINDOW (widget), PK_STOCK_WINDOW_ICON);
+
+	/* close button */
+	widget = glade_xml_get_widget (glade_xml, "button_close");
+	g_signal_connect_swapped (widget, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+
+	/* title */
+	widget = glade_xml_get_widget (glade_xml, "label_title");
+	text = g_strdup_printf ("<b><big>%s</big></b>", title);
+	gtk_label_set_label (GTK_LABEL (widget), text);
+	g_free (text);
+
+	/* message */
+	widget = glade_xml_get_widget (glade_xml, "label_message");
+	gtk_label_set_label (GTK_LABEL (widget), message);
+
+	/* show text in the expander */
+	if (pk_strzero (details)) {
+		widget = glade_xml_get_widget (glade_xml, "expander_details");
+		gtk_widget_hide (widget);
+	} else {
+		buffer = gtk_text_buffer_new (NULL);
+//		text = g_markup_escape_text (details, -1);
+		gtk_text_buffer_insert_at_cursor (buffer, details, strlen (details));
+		widget = glade_xml_get_widget (glade_xml, "textview_details");
+		gtk_text_view_set_buffer (GTK_TEXT_VIEW (widget), buffer);
+	}
+
+	/* show window */
+	widget = glade_xml_get_widget (glade_xml, "window_error");
+	gtk_widget_show (widget);
+
+	/* wait for button press */
+	gtk_main ();
+
+	/* hide window */
+	if (GTK_IS_WIDGET (widget)) {
+		gtk_widget_hide (widget);
+	}
+	g_object_unref (glade_xml);
+	if (buffer != NULL) {
+		g_object_unref (buffer);
+	}
+	return TRUE;
+}
+

Added: trunk/src/gpk-error.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-error.h	Tue Apr 22 13:40:41 2008
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_ERROR_H
+#define __GPK_ERROR_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+gboolean	 gpk_error_dialog			(const gchar	*title,
+							 const gchar	*message,
+							 const gchar	*details);
+
+G_END_DECLS
+
+#endif	/* __GPK_ERROR_H */

Added: trunk/src/gpk-gnome.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-gnome.c	Tue Apr 22 13:40:41 2008
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <string.h>
+
+#include <pk-debug.h>
+
+/**
+ * gpk_gnome_open:
+ * @url: a url such as <literal>http://www.hughsie.com</literal>
+ **/
+gboolean
+gpk_gnome_open (const gchar *url)
+{
+	gchar *data;
+	gboolean ret;
+
+	g_return_val_if_fail (url != NULL, FALSE);
+
+	data = g_strconcat ("gnome-open ", url, NULL);
+	ret = g_spawn_command_line_async (data, NULL);
+	if (ret == FALSE) {
+		pk_warning ("spawn of '%s' failed", data);
+	}
+	g_free (data);
+	return ret;
+}
+
+/**
+ * gpk_gnome_help:
+ * @link_id: Subsection of gnome-packagekit help file, or %NULL.
+ **/
+gboolean
+gpk_gnome_help (const gchar *link_id)
+{
+	GError *error = NULL;
+	gchar *command;
+	const gchar *lang;
+	gchar *uri = NULL;
+	GdkScreen *gscreen;
+	gint i;
+	gboolean ret = TRUE;
+	const gchar *const *langs = g_get_language_names ();
+
+	for (i = 0; langs[i]; i++) {
+		lang = langs[i];
+		if (strchr (lang, '.')) {
+			continue;
+		}
+		uri = g_build_filename(DATADIR,
+				       "/gnome/help/gnome-packagekit/",
+					lang,
+				       "/gnome-packagekit.xml",
+					NULL);
+		if (g_file_test (uri, G_FILE_TEST_EXISTS)) {
+                    break;
+		}
+	}
+	if (link_id) {
+		command = g_strconcat ("gnome-open ghelp://", uri, "?", link_id, NULL);
+	} else {
+		command = g_strconcat ("gnome-open ghelp://", uri,  NULL);
+	}
+	pk_debug ("using command %s", command);
+
+	gscreen = gdk_screen_get_default();
+	gdk_spawn_command_line_on_screen (gscreen, command, &error);
+	if (error != NULL) {
+		GtkWidget *d;
+		d = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+					    GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", error->message);
+		gtk_dialog_run (GTK_DIALOG(d));
+		gtk_widget_destroy (d);
+		g_error_free (error);
+		ret = FALSE;
+	}
+
+	g_free (command);
+	g_free (uri);
+	return ret;
+}
+

Added: trunk/src/gpk-gnome.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-gnome.h	Tue Apr 22 13:40:41 2008
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_GNOME_H
+#define __GPK_GNOME_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+gboolean	 gpk_gnome_open				(const gchar	*url);
+gboolean	 gpk_gnome_help				(const gchar	*link_id);
+
+G_END_DECLS
+
+#endif	/* __GPK_GNOME_H */

Modified: trunk/src/gpk-interface.xml
==============================================================================
--- trunk/src/gpk-interface.xml	(original)
+++ trunk/src/gpk-interface.xml	Tue Apr 22 13:40:41 2008
@@ -1,6 +1,18 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <node name="/">
   <interface name="org.freedesktop.PackageKit">
+    <method name="InstallLocalFile">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="s" name="full_path" direction="in"/>
+    </method>
+    <method name="InstallProvideFile">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="s" name="full_path" direction="in"/>
+    </method>
+    <method name="InstallPackageName">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="s" name="package_name" direction="in"/>
+    </method>
   </interface>
 </node>
 

Modified: trunk/src/gpk-log.c
==============================================================================
--- trunk/src/gpk-log.c	(original)
+++ trunk/src/gpk-log.c	Tue Apr 22 13:40:41 2008
@@ -36,7 +36,6 @@
 #include <pk-debug.h>
 #include <pk-client.h>
 #include <pk-control.h>
-#include <pk-connection.h>
 #include <pk-package-id.h>
 #include <pk-common.h>
 
@@ -44,47 +43,36 @@
 #include <gpk-gnome.h>
 
 static GladeXML *glade_xml = NULL;
-static GtkListStore *list_store_general = NULL;
-static GtkListStore *list_store_details = NULL;
+static GtkListStore *list_store = NULL;
 static PkClient *client = NULL;
 static gchar *transaction_id = NULL;
-static GHashTable *hash = NULL;
 static PolKitGnomeAction *rollback_action = NULL;
 
 enum
 {
-	PACKAGES_COLUMN_GENERAL_ICON,
-	PACKAGES_COLUMN_GENERAL_TEXT,
-	PACKAGES_COLUMN_GENERAL_ID,
-	PACKAGES_COLUMN_GENERAL_LAST
-};
-
-enum
-{
-	PACKAGES_COLUMN_DETAILS_ICON,
-	PACKAGES_COLUMN_DETAILS_TEXT,
-	PACKAGES_COLUMN_DETAILS_LAST
+	GPK_LOG_COLUMN_ICON,
+	GPK_LOG_COLUMN_TEXT,
+	GPK_LOG_COLUMN_ID,
+	GPK_LOG_COLUMN_LAST
 };
 
 /**
- * pk_button_help_cb:
+ * gpk_log_button_help_cb:
  **/
 static void
-pk_button_help_cb (GtkWidget *widget,
-		   gboolean  data)
+gpk_log_button_help_cb (GtkWidget *widget, gboolean data)
 {
-	gpk_gnome_help ("software-sources");
+	gpk_gnome_help ("update-log");
 }
 
 /**
- * pk_button_rollback_cb:
+ * gpk_log_button_rollback_cb:
  **/
 static void
-pk_button_rollback_cb (PolKitGnomeAction *action, gpointer data)
+gpk_log_button_rollback_cb (PolKitGnomeAction *action, gpointer data)
 {
 	gboolean ret;
 	GError *error = NULL;
-	GMainLoop *loop = (GMainLoop *) data;
 
 	/* rollback */
 	ret = pk_client_rollback (client, transaction_id, &error);
@@ -92,43 +80,22 @@
 		pk_warning ("failed to reset client: %s", error->message);
 		g_error_free (error);
 	}
-
-	g_main_loop_quit (loop);
-}
-
-/**
- * pk_button_close_cb:
- **/
-static void
-pk_button_close_cb (GtkWidget *widget, gpointer data)
-{
-	GMainLoop *loop = (GMainLoop *) data;
-	g_main_loop_quit (loop);
-	pk_debug ("emitting action-close");
+	gtk_main_quit ();
 }
 
 /**
- * pk_transaction_db_get_pretty_date:
+ * gpk_log_get_localised_date:
  **/
 static gchar *
-pk_transaction_db_get_pretty_date (const gchar *timespec)
+gpk_log_get_localised_date (const gchar *timespec)
 {
 	GDate *date;
 	GTimeVal timeval;
-	GTimeVal timeval_now;
 	gchar buffer[100];
-	guint hours;
 
 	/* the old date */
 	g_time_val_from_iso8601 (timespec, &timeval);
 
-	/* the new date */
-	g_get_current_time (&timeval_now);
-
-	/* the difference in hours */
-	hours = (timeval_now.tv_sec - timeval.tv_sec) / (60 * 60);
-	pk_debug ("hours is %i", hours);
-
 	/* get printed string */
 	date = g_date_new ();
 	g_date_set_time_val (date, &timeval);
@@ -139,180 +106,151 @@
 }
 
 /**
- * pk_transaction_cb:
+ * gpk_log_get_type_line:
  **/
-static void
-pk_transaction_cb (PkClient *client, const gchar *tid, const gchar *timespec,
-		   gboolean succeeded, PkRoleEnum role, guint duration, const gchar *data, gpointer user_data)
+static gchar *
+gpk_log_get_type_line (gchar **array, PkInfoEnum info)
 {
-	GtkTreeIter iter;
+	guint i;
+	guint size;
+	PkInfoEnum info_local;
+	GString *string;
 	gchar *text;
-	gchar *pretty;
-	const gchar *icon_name;
-	const gchar *role_text;
+	gchar *whole;
+	gchar **sections;
 
-	/* only show transactions that succeeded */
-	if (!succeeded) {
-		pk_debug ("tid %s did not succeed, so not adding", tid);
-		return;
+	string = g_string_new ("");
+	size = g_strv_length (array);
+	for (i=0; i<size; i++) {
+		sections = g_strsplit (array[i], "\t", 0);
+		info_local = pk_info_enum_from_text (sections[0]);
+		if (info_local == info) {
+			text = gpk_package_id_format_oneline (sections[1], NULL);
+			g_string_append_printf (string, "%s, ", text);
+			g_free (text);
+		}
+		g_strfreev (sections);
 	}
 
-	/* we save this */
-	g_hash_table_insert (hash, g_strdup (tid), g_strdup (data));
-
-	pretty = pk_transaction_db_get_pretty_date (timespec);
-	pk_debug ("pretty=%s", pretty);
-	role_text = gpk_role_enum_to_localised_past (role);
-	text = g_markup_printf_escaped ("<b>%s</b>\n%s", role_text, pretty);
-	g_free (pretty);
+	/* nothing, so return NULL */
+	if (string->len == 0) {
+		g_string_free (string, TRUE);
+		return NULL;
+	}
 
-	gtk_list_store_append (list_store_general, &iter);
-	gtk_list_store_set (list_store_general, &iter,
-			    PACKAGES_COLUMN_GENERAL_TEXT, text,
-			    PACKAGES_COLUMN_GENERAL_ID, tid,
-			    -1);
+	/* remove last comma space */
+	g_string_set_size (string, string->len - 2);
 
-	icon_name = gpk_role_enum_to_icon_name (role);
-	gtk_list_store_set (list_store_general, &iter, PACKAGES_COLUMN_GENERAL_ICON, icon_name, -1);
+	/* add a nice header, and make text italic */
+	text = g_string_free (string, FALSE);
+	whole = g_strdup_printf ("<b>%s</b>: %s\n", gpk_info_enum_to_localised_past (info), text);
+	g_free (text);
+	return whole;
 }
 
 /**
- * pk_window_delete_event_cb:
- * @event: The event type, unused.
+ * gpk_log_get_transaction_item:
  **/
-static gboolean
-pk_window_delete_event_cb (GtkWidget	*widget,
-			    GdkEvent	*event,
-			    gpointer data)
+static gchar *
+gpk_log_get_transaction_item (const gchar *timespec, const gchar *data)
 {
-	GMainLoop *loop = (GMainLoop *) data;
-	g_main_loop_quit (loop);
-	return FALSE;
+	gchar *pretty;
+	GString *string;
+	gchar *text;
+	gchar **array;
+
+	pretty = gpk_log_get_localised_date (timespec);
+	string = g_string_new ("");
+	g_string_append_printf (string, "<big><b>%s</b></big>\n", pretty);
+	g_free (pretty);
+
+	array = g_strsplit (data, "\n", 0);
+
+	/* get each type */
+	text = gpk_log_get_type_line (array, PK_INFO_ENUM_INSTALLING);
+	if (text != NULL) {
+		g_string_append (string, text);
+	}
+	g_free (text);
+	text = gpk_log_get_type_line (array, PK_INFO_ENUM_REMOVING);
+	if (text != NULL) {
+		g_string_append (string, text);
+	}
+	g_free (text);
+	text = gpk_log_get_type_line (array, PK_INFO_ENUM_UPDATING);
+	if (text != NULL) {
+		g_string_append (string, text);
+	}
+	g_free (text);
+	g_strfreev (array);
+
+	/* remove last \n */
+	if (string->len > 0) {
+		g_string_set_size (string, string->len - 1);
+	}
+
+	return g_string_free (string, FALSE);
 }
 
 /**
- * pk_treeview_add_general_columns:
+ * gpk_log_transaction_cb:
  **/
 static void
-pk_treeview_add_general_columns (GtkTreeView *treeview)
+gpk_log_transaction_cb (PkClient *client, const gchar *tid, const gchar *timespec,
+			gboolean succeeded, PkRoleEnum role, guint duration, const gchar *data, gpointer user_data)
 {
-	GtkCellRenderer *renderer;
-	GtkTreeViewColumn *column;
+	GtkTreeIter iter;
+	gchar *text;
+	const gchar *icon_name;
 
-	/* image */
-	renderer = gtk_cell_renderer_pixbuf_new ();
-        g_object_set (renderer, "stock-size", GTK_ICON_SIZE_DIALOG, NULL);
-	column = gtk_tree_view_column_new_with_attributes (_("Role"), renderer,
-							   "icon-name", PACKAGES_COLUMN_GENERAL_ICON, NULL);
-	gtk_tree_view_append_column (treeview, column);
+	/* only show transactions that succeeded */
+	if (!succeeded) {
+		pk_debug ("tid %s did not succeed, so not adding", tid);
+		return;
+	}
 
-	/* column for text */
-	renderer = gtk_cell_renderer_text_new ();
-	column = gtk_tree_view_column_new_with_attributes (_("Transaction"), renderer,
-							   "markup", PACKAGES_COLUMN_GENERAL_TEXT, NULL);
-	gtk_tree_view_column_set_sort_column_id (column, PACKAGES_COLUMN_GENERAL_TEXT);
-	gtk_tree_view_append_column (treeview, column);
-	gtk_tree_view_column_set_expand (column, TRUE);
+	/* put formatted text into treeview */
+	text = gpk_log_get_transaction_item (timespec, data);
+	gtk_list_store_append (list_store, &iter);
+	gtk_list_store_set (list_store, &iter,
+			    GPK_LOG_COLUMN_TEXT, text,
+			    GPK_LOG_COLUMN_ID, tid, -1);
+	g_free (text);
+
+	icon_name = gpk_role_enum_to_icon_name (role);
+	gtk_list_store_set (list_store, &iter, GPK_LOG_COLUMN_ICON, icon_name, -1);
 }
 
 /**
- * pk_treeview_add_details_columns:
+ * pk_treeview_add_general_columns:
  **/
 static void
-pk_treeview_add_details_columns (GtkTreeView *treeview)
+pk_treeview_add_general_columns (GtkTreeView *treeview)
 {
 	GtkCellRenderer *renderer;
 	GtkTreeViewColumn *column;
 
 	/* image */
 	renderer = gtk_cell_renderer_pixbuf_new ();
-        g_object_set (renderer, "stock-size", GTK_ICON_SIZE_LARGE_TOOLBAR, NULL);
-	column = gtk_tree_view_column_new_with_attributes (_("Type"), renderer,
-							   "icon-name", PACKAGES_COLUMN_DETAILS_ICON, NULL);
+        g_object_set (renderer, "stock-size", GTK_ICON_SIZE_DIALOG, NULL);
+	column = gtk_tree_view_column_new_with_attributes (_("Role"), renderer,
+							   "icon-name", GPK_LOG_COLUMN_ICON, NULL);
 	gtk_tree_view_append_column (treeview, column);
 
 	/* column for text */
 	renderer = gtk_cell_renderer_text_new ();
-	column = gtk_tree_view_column_new_with_attributes (_("Details"), renderer,
-							   "markup", PACKAGES_COLUMN_DETAILS_TEXT, NULL);
-	gtk_tree_view_column_set_sort_column_id (column, PACKAGES_COLUMN_DETAILS_TEXT);
+	column = gtk_tree_view_column_new_with_attributes (_("Transaction"), renderer,
+							   "markup", GPK_LOG_COLUMN_TEXT, NULL);
+	gtk_tree_view_column_set_sort_column_id (column, GPK_LOG_COLUMN_TEXT);
 	gtk_tree_view_append_column (treeview, column);
 	gtk_tree_view_column_set_expand (column, TRUE);
 }
 
-
-/**
- * pk_details_item_add:
- **/
-static void
-pk_details_item_add (GtkListStore *list_store, PkInfoEnum info, const gchar *package_id, const gchar *summary)
-{
-	GtkTreeIter iter;
-	gchar *text;
-	const gchar *icon_name;
-	const gchar *info_text;
-
-	info_text = gpk_info_enum_to_localised_text (info);
-	text = gpk_package_id_format_twoline (package_id, summary);
-	icon_name = gpk_info_enum_to_icon_name (info);
-
-	gtk_list_store_append (list_store_details, &iter);
-	gtk_list_store_set (list_store_details, &iter,
-			    PACKAGES_COLUMN_DETAILS_TEXT, text, 
-			    PACKAGES_COLUMN_DETAILS_ICON, icon_name, -1);
-	g_free (text);
-}
-
-/**
- * pk_treeview_details_populate:
- **/
-static void
-pk_treeview_details_populate (const gchar *tid)
-{
-	GtkWidget *widget;
-	gchar **array;
-	gchar **sections;
-	guint i;
-	guint size;
-	PkInfoEnum info;
-	gchar *transaction_data;
-
-	/* get from hash */
-	transaction_data = (gchar *) g_hash_table_lookup (hash, tid);
-
-	/* no details? */
-	if (pk_strzero (transaction_data)) {
-		widget = glade_xml_get_widget (glade_xml, "frame_details");
-		gtk_widget_hide (widget);
-		return;
-	}
-
-	widget = glade_xml_get_widget (glade_xml, "treeview_details");
-	gtk_list_store_clear (list_store_details);
-
-	array = g_strsplit (transaction_data, "\n", 0);
-	size = g_strv_length (array);
-	for (i=0; i<size; i++) {
-		sections = g_strsplit (array[i], "\t", 0);
-		info = pk_info_enum_from_text (sections[0]);
-		if (info == PK_INFO_ENUM_UPDATING ||
-		    info == PK_INFO_ENUM_INSTALLING ||
-		    info == PK_INFO_ENUM_REMOVING) {
-			pk_details_item_add (list_store_details, info, sections[1], sections[2]);
-		}
-		g_strfreev (sections);
-	}
-	g_strfreev (array);
-
-	widget = glade_xml_get_widget (glade_xml, "frame_details");
-	gtk_widget_show (widget);
-}
-
 /**
- * pk_treeview_clicked_cb:
+ * gpk_log_treeview_clicked_cb:
  **/
 static void
-pk_treeview_clicked_cb (GtkTreeSelection *selection, gboolean data)
+gpk_log_treeview_clicked_cb (GtkTreeSelection *selection, gboolean data)
 {
 	GtkTreeModel *model;
 	GtkTreeIter iter;
@@ -321,44 +259,27 @@
 	/* This will only work in single or browse selection mode! */
 	if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
 		g_free (transaction_id);
-		gtk_tree_model_get (model, &iter,
-				    PACKAGES_COLUMN_GENERAL_ID, &id, -1);
+		gtk_tree_model_get (model, &iter, GPK_LOG_COLUMN_ID, &id, -1);
 
-		/* make back into transaction_id */
-		transaction_id = g_strdup (id);
+		/* show transaction_id */
+		pk_debug ("selected row is: %s", id);
 		g_free (id);
-		pk_debug ("selected row is: %s", transaction_id);
-
-		/* get the decription */
-		pk_treeview_details_populate (transaction_id);
 	} else {
 		pk_debug ("no row selected");
 	}
 }
 
 /**
- * pk_connection_changed_cb:
- **/
-static void
-pk_connection_changed_cb (PkConnection *pconnection, gboolean connected, gboolean data)
-{
-	pk_debug ("connected=%i", connected);
-}
-
-/**
  * main:
  **/
 int
 main (int argc, char *argv[])
 {
-	GMainLoop *loop;
 	gboolean verbose = FALSE;
 	gboolean program_version = FALSE;
 	GOptionContext *context;
-	GtkWidget *main_window;
 	GtkWidget *widget;
 	GtkTreeSelection *selection;
-	PkConnection *pconnection;
 	PkRoleEnum roles;
 	PolKitAction *pk_action;
 	GtkWidget *button;
@@ -402,52 +323,34 @@
 	gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
                                            PK_DATA G_DIR_SEPARATOR_S "icons");
 
-	loop = g_main_loop_new (NULL, FALSE);
-
 	client = pk_client_new ();
 	g_signal_connect (client, "transaction",
-			  G_CALLBACK (pk_transaction_cb), NULL);
+			  G_CALLBACK (gpk_log_transaction_cb), NULL);
 
 	/* get actions */
 	control = pk_control_new ();
 	roles = pk_control_get_actions (control);
 	g_object_unref (control);
 
-	/* save the description in a hash */
-	hash = g_hash_table_new (g_str_hash, g_str_equal);
-
-	pconnection = pk_connection_new ();
-	g_signal_connect (pconnection, "connection-changed",
-			  G_CALLBACK (pk_connection_changed_cb), NULL);
-
 	glade_xml = glade_xml_new (PK_DATA "/gpk-log.glade", NULL, NULL);
-	main_window = glade_xml_get_widget (glade_xml, "window_transactions");
-
-	/* Hide window first so that the dialogue resizes itself without redrawing */
-	gtk_widget_hide (main_window);
-	gtk_window_set_icon_name (GTK_WINDOW (main_window), "system-software-update");
-
-	/* hide the details for now */
-	widget = glade_xml_get_widget (glade_xml, "frame_details");
-	gtk_widget_hide (widget);
+	widget = glade_xml_get_widget (glade_xml, "window_transactions");
+	gtk_window_set_icon_name (GTK_WINDOW (widget), "system-software-update");
+	gtk_widget_set_size_request (widget, 500, 400);
 
 	/* Get the main window quit */
-	g_signal_connect (main_window, "delete_event",
-			  G_CALLBACK (pk_window_delete_event_cb), loop);
+	g_signal_connect_swapped (widget, "delete_event", G_CALLBACK (gtk_main_quit), NULL);
 
 	widget = glade_xml_get_widget (glade_xml, "button_close");
-	g_signal_connect (widget, "clicked",
-			  G_CALLBACK (pk_button_close_cb), loop);
+	g_signal_connect_swapped (widget, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+	gtk_widget_grab_default (widget);
+
 	widget = glade_xml_get_widget (glade_xml, "button_help");
 	g_signal_connect (widget, "clicked",
-			  G_CALLBACK (pk_button_help_cb), NULL);
+			  G_CALLBACK (gpk_log_button_help_cb), NULL);
 
 	pk_action = polkit_action_new ();
 	polkit_action_set_action_id (pk_action, "org.freedesktop.packagekit.rollback");
-	rollback_action = polkit_gnome_action_new_default ("rollback",
-							   pk_action,
-							   _("_Rollback"),
-							   NULL);
+	rollback_action = polkit_gnome_action_new_default ("rollback", pk_action, _("_Rollback"), NULL);
 	g_object_set (rollback_action,
 		      "no-icon-name", "gtk-go-back-ltr",
 		      "auth-icon-name", "gtk-go-back-ltr",
@@ -455,12 +358,12 @@
 		      "self-blocked-icon-name", "gtk-go-back-ltr",
 		      NULL);
 	polkit_action_unref (pk_action);
-	g_signal_connect (rollback_action, "activate",
-			  G_CALLBACK (pk_button_rollback_cb), loop);
+	g_signal_connect (rollback_action, "activate", G_CALLBACK (gpk_log_button_rollback_cb), NULL);
 	button = polkit_gnome_action_create_button (rollback_action);
 	widget = glade_xml_get_widget (glade_xml, "buttonbox");
         gtk_box_pack_start (GTK_BOX (widget), button, FALSE, FALSE, 0);
         gtk_box_reorder_child (GTK_BOX (widget), button, 1);
+
 	/* hide the rollback button if we can't do the action */
 	if (pk_enums_contain (roles, PK_ROLE_ENUM_ROLLBACK)) {
 		polkit_gnome_action_set_visible (rollback_action, TRUE);
@@ -468,47 +371,35 @@
 		polkit_gnome_action_set_visible (rollback_action, FALSE);
 	}
 
-	gtk_widget_set_size_request (main_window, 500, 300);
-
 	/* create list stores */
-	list_store_general = gtk_list_store_new (PACKAGES_COLUMN_GENERAL_LAST, G_TYPE_STRING,
+	list_store = gtk_list_store_new (GPK_LOG_COLUMN_LAST, G_TYPE_STRING,
 						 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
-	list_store_details = gtk_list_store_new (PACKAGES_COLUMN_DETAILS_LAST, G_TYPE_STRING, G_TYPE_STRING);
 
 	/* create transaction_id tree view */
 	widget = glade_xml_get_widget (glade_xml, "treeview_transactions");
 	gtk_tree_view_set_model (GTK_TREE_VIEW (widget),
-				 GTK_TREE_MODEL (list_store_general));
+				 GTK_TREE_MODEL (list_store));
 
 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
 	g_signal_connect (selection, "changed",
-			  G_CALLBACK (pk_treeview_clicked_cb), NULL);
+			  G_CALLBACK (gpk_log_treeview_clicked_cb), NULL);
 
 	/* add columns to the tree view */
 	pk_treeview_add_general_columns (GTK_TREE_VIEW (widget));
 	gtk_tree_view_columns_autosize (GTK_TREE_VIEW (widget));
 
-	/* create transaction_id tree view */
-	widget = glade_xml_get_widget (glade_xml, "treeview_details");
-	gtk_tree_view_set_model (GTK_TREE_VIEW (widget),
-				 GTK_TREE_MODEL (list_store_details));
-	pk_treeview_add_details_columns (GTK_TREE_VIEW (widget));
-	gtk_tree_view_columns_autosize (GTK_TREE_VIEW (widget));
-
 	/* get the update list */
 	pk_client_get_old_transactions (client, 0, NULL);
-	gtk_widget_show (main_window);
 
-	g_main_loop_run (loop);
-	g_main_loop_unref (loop);
+	/* show */
+	widget = glade_xml_get_widget (glade_xml, "window_transactions");
+	gtk_widget_show (widget);
+	gtk_main ();
 
 	g_object_unref (glade_xml);
-	g_object_unref (list_store_general);
-	g_object_unref (list_store_details);
+	g_object_unref (list_store);
 	g_object_unref (client);
-	g_object_unref (pconnection);
 	g_free (transaction_id);
-	g_hash_table_unref (hash);
 
 	return 0;
 }

Modified: trunk/src/gpk-notify.c
==============================================================================
--- trunk/src/gpk-notify.c	(original)
+++ trunk/src/gpk-notify.c	Tue Apr 22 13:40:41 2008
@@ -713,6 +713,7 @@
 	/* work out icon */
 	icon = gpk_notify_get_best_update_icon (notify, client);
 	gpk_smart_icon_set_icon_name (notify->priv->sicon, icon);
+	gpk_smart_icon_pulse (notify->priv->sicon);
 
 	/* make tooltip */
 	if (status_security->len != 0) {
@@ -848,7 +849,7 @@
 	pk_client_set_use_buffer (client, TRUE, NULL);
 
 	/* get updates */
-	ret = pk_client_get_updates (client, PK_FILTER_ENUM_BASENAME, &error);
+	ret = pk_client_get_updates (client, PK_FILTER_ENUM_NONE, &error);
 	if (!ret) {
 		pk_warning ("failed to get updates: %s", error->message);
 		g_error_free (error);

Modified: trunk/src/gpk-repo.c
==============================================================================
--- trunk/src/gpk-repo.c	(original)
+++ trunk/src/gpk-repo.c	Tue Apr 22 13:40:41 2008
@@ -356,7 +356,7 @@
 
 	glade_xml = glade_xml_new (PK_DATA "/gpk-repo.glade", NULL, NULL);
 	main_window = glade_xml_get_widget (glade_xml, "window_repo");
-	gtk_window_set_icon_name (GTK_WINDOW (main_window), "system-installer");
+	gtk_window_set_icon_name (GTK_WINDOW (main_window), "pk-package-sources");
 
 	/* Get the main window quit */
 	g_signal_connect (main_window, "delete_event",

Added: trunk/src/gpk-self-test.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-self-test.c	Tue Apr 22 13:40:41 2008
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+#include <libselftest.h>
+#include <pk-debug.h>
+#include "gpk-common.h"
+
+int
+main (int argc, char **argv)
+{
+	LibSelfTest test;
+
+	if (! g_thread_supported ()) {
+		g_thread_init (NULL);
+	}
+	g_type_init ();
+	libst_init (&test);
+	pk_debug_init (TRUE);
+
+	/* tests go here */
+	gpk_common_self_test (&test);
+
+	return (libst_finish (&test));
+}
+

Modified: trunk/src/gpk-smart-icon.c
==============================================================================
--- trunk/src/gpk-smart-icon.c	(original)
+++ trunk/src/gpk-smart-icon.c	Tue Apr 22 13:40:41 2008
@@ -62,7 +62,10 @@
 	gchar			*new;
 	gchar			*notify_data;
 	guint			 event_source;
+	guint			 pulse_source;
 	gboolean		 has_gconf_check;
+	gfloat			 icon_opacity;
+	gboolean		 going_down;
 };
 
 enum {
@@ -81,6 +84,7 @@
 	{GPK_NOTIFY_BUTTON_CANCEL_UPDATE,	"cancel-update"},
 	{GPK_NOTIFY_BUTTON_UPDATE_COMPUTER,	"update-computer"},
 	{GPK_NOTIFY_BUTTON_RESTART_COMPUTER,	"restart-computer"},
+	{GPK_NOTIFY_BUTTON_INSTALL_FIRMWARE,	"install-firmware"},
 	{0, NULL}
 };
 
@@ -101,6 +105,101 @@
 			      G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING);
 }
 
+/**
+ * gpk_smart_icon_set_pixmap_opacity:
+ **/
+static gboolean
+gpk_smart_icon_set_pixmap_opacity (GdkPixbuf *pixbuf, gfloat adjust)
+{
+	gint width, height, rowstride, n_channels;
+	guchar *pixels, *p;
+	gint x, y;
+
+	width = gdk_pixbuf_get_width (pixbuf);
+	height = gdk_pixbuf_get_height (pixbuf);
+	rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+	n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+	pixels = gdk_pixbuf_get_pixels (pixbuf);
+
+	/* scale the opacity of each pixel */
+	for (y=0; y<height-1;y++) {
+		for (x=0; x<height-1;x++) {
+			p = pixels + y * rowstride + x * n_channels;
+			p[3] = (gfloat) p[3] * adjust;
+		}
+	}
+	return TRUE;
+}
+
+/**
+ * gpk_smart_icon_pulse_timeout_cb:
+ **/
+static gboolean
+gpk_smart_icon_pulse_timeout_cb (gpointer data)
+{
+	GpkSmartIcon *sicon = (GpkSmartIcon *) data;
+	GdkPixbuf *pixbuf;
+	GdkRectangle area;
+
+	g_return_val_if_fail (PK_IS_SMART_ICON (sicon), FALSE);
+
+	/* have we hidden the icon already? */
+	if (sicon->priv->current == NULL || sicon->priv->new == NULL) {
+		pk_debug ("not pulsing as icon cleared");
+		return FALSE;
+	}
+
+	/* get pixmap the same size as the original icon */
+	gtk_status_icon_get_geometry (GTK_STATUS_ICON (sicon->priv->status_icon), NULL, &area, NULL);
+	pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), sicon->priv->current, area.width, 0, NULL);
+
+	/* set the new pixmap with the correct opacity */
+	gpk_smart_icon_set_pixmap_opacity (pixbuf, sicon->priv->icon_opacity);
+	gtk_status_icon_set_from_pixbuf (GTK_STATUS_ICON (sicon->priv->status_icon), pixbuf);
+	g_object_unref (pixbuf);
+
+	/* dimming down */
+	if (sicon->priv->going_down) {
+		sicon->priv->icon_opacity -= 0.1;
+		if (sicon->priv->icon_opacity<0) {
+			sicon->priv->icon_opacity = 0;
+			sicon->priv->going_down = FALSE;
+		}
+		return TRUE;
+	}
+
+	/* dimming up */
+	sicon->priv->icon_opacity += 0.1;
+	if (sicon->priv->icon_opacity>1) {
+		/* restore */
+		gtk_status_icon_set_from_icon_name (GTK_STATUS_ICON (sicon->priv->status_icon), sicon->priv->current);
+		sicon->priv->pulse_source = 0;
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/**
+ * gpk_smart_icon_pulse:
+ **/
+gboolean
+gpk_smart_icon_pulse (GpkSmartIcon *sicon)
+{
+	g_return_val_if_fail (PK_IS_SMART_ICON (sicon), FALSE);
+
+	sicon->priv->icon_opacity = 0.9;
+	sicon->priv->going_down = TRUE;
+	if (sicon->priv->pulse_source != 0) {
+		pk_warning ("already pulsing");
+		return FALSE;
+	}
+	sicon->priv->pulse_source = g_timeout_add (20, gpk_smart_icon_pulse_timeout_cb, sicon);
+	return TRUE;
+}
+
+/**
+ * gpk_smart_icon_set_icon_name_cb:
+ **/
 static gboolean
 gpk_smart_icon_set_icon_name_cb (gpointer data)
 {
@@ -277,6 +376,8 @@
 		text = _("Update computer now");
 	} else if (button == GPK_NOTIFY_BUTTON_RESTART_COMPUTER) {
 		text = _("Restart computer now");
+	} else if (button == GPK_NOTIFY_BUTTON_INSTALL_FIRMWARE) {
+		text = _("Install firmware");
 	}
 
 	/* save data privately, TODO: this really needs to be in a hashtable */
@@ -353,6 +454,7 @@
 	sicon->priv->dialog = NULL;
 	sicon->priv->notify_data = NULL;
 	sicon->priv->event_source = 0;
+	sicon->priv->pulse_source = 0;
 	sicon->priv->has_gconf_check = FALSE;
 	sicon->priv->gconf_client = gconf_client_get_default ();
 
@@ -376,6 +478,14 @@
 	sicon = PK_SMART_ICON (object);
 	g_return_if_fail (sicon->priv != NULL);
 
+	/* remove any timers that may be firing */
+	if (sicon->priv->event_source != 0) {
+		g_source_remove (sicon->priv->event_source);
+	}
+	if (sicon->priv->pulse_source != 0) {
+		g_source_remove (sicon->priv->pulse_source);
+	}
+
 	g_free (sicon->priv->new);
 	g_free (sicon->priv->current);
 	g_object_unref (sicon->priv->gconf_client);

Modified: trunk/src/gpk-smart-icon.h
==============================================================================
--- trunk/src/gpk-smart-icon.h	(original)
+++ trunk/src/gpk-smart-icon.h	Tue Apr 22 13:40:41 2008
@@ -69,6 +69,7 @@
 	GPK_NOTIFY_BUTTON_CANCEL_UPDATE,
 	GPK_NOTIFY_BUTTON_UPDATE_COMPUTER,
 	GPK_NOTIFY_BUTTON_RESTART_COMPUTER,
+	GPK_NOTIFY_BUTTON_INSTALL_FIRMWARE,
 	GPK_NOTIFY_BUTTON_UNKNOWN
 } GpkNotifyButton;
 
@@ -76,6 +77,7 @@
 GpkSmartIcon	*gpk_smart_icon_new			(void);
 GtkStatusIcon	*gpk_smart_icon_get_status_icon		(GpkSmartIcon	*sicon);
 gboolean	 gpk_smart_icon_sync			(GpkSmartIcon	*sicon);
+gboolean	 gpk_smart_icon_pulse			(GpkSmartIcon	*sicon);
 gboolean	 gpk_smart_icon_set_icon_name		(GpkSmartIcon	*sicon,
 							 const gchar	*icon_name);
 gboolean	 gpk_smart_icon_set_tooltip		(GpkSmartIcon	*sicon,

Modified: trunk/src/gpk-update-icon.c
==============================================================================
--- trunk/src/gpk-update-icon.c	(original)
+++ trunk/src/gpk-update-icon.c	Tue Apr 22 13:40:41 2008
@@ -38,6 +38,8 @@
 
 #include "gpk-notify.h"
 #include "gpk-watch.h"
+#include "gpk-firmware.h"
+#include "gpk-dbus.h"
 #include "gpk-interface.h"
 
 /**
@@ -83,7 +85,7 @@
 		return FALSE;
 	}
 
-	dbus_g_object_type_install_info (GPK_TYPE_NOTIFY, &dbus_glib_gpk_dbus_object_info);
+	dbus_g_object_type_install_info (GPK_TYPE_DBUS, &dbus_glib_gpk_dbus_object_info);
 	dbus_g_connection_register_g_object (connection, PK_DBUS_PATH, object);
 
 	return TRUE;
@@ -111,6 +113,7 @@
 	gboolean program_version = FALSE;
 	GpkNotify *notify = NULL;
 	GpkWatch *watch = NULL;
+	GpkFirmware *firmware = NULL;
 	GOptionContext *context;
 	GError *error = NULL;
 	gboolean ret;
@@ -159,6 +162,7 @@
 	/* create new objects */
 	notify = gpk_notify_new ();
 	watch = gpk_watch_new ();
+	firmware = gpk_firmware_new ();
 	loop = g_main_loop_new (NULL, FALSE);
 
 	/* find out when we are replaced */
@@ -189,6 +193,7 @@
 	g_main_loop_unref (loop);
 	g_object_unref (notify);
 	g_object_unref (watch);
+	g_object_unref (firmware);
 	g_object_unref (libgbus);
 
 	return 0;

Modified: trunk/src/gpk-update-viewer.c
==============================================================================
--- trunk/src/gpk-update-viewer.c	(original)
+++ trunk/src/gpk-update-viewer.c	Tue Apr 22 13:40:41 2008
@@ -636,6 +636,9 @@
 		gtk_widget_set_sensitive (widget, FALSE);
 		polkit_gnome_action_set_sensitive (update_system_action, FALSE);
 		polkit_gnome_action_set_sensitive (update_packages_action, FALSE);
+
+		widget = glade_xml_get_widget (glade_xml, "button_close3");
+		gtk_widget_grab_default (widget);
 	} else {
 
 		PkPackageItem *item;
@@ -734,7 +737,7 @@
 		g_error_free (error);
 		return;
 	}
-	ret = pk_client_get_updates (client_query, PK_FILTER_ENUM_BASENAME, &error);
+	ret = pk_client_get_updates (client_query, PK_FILTER_ENUM_NONE, &error);
 	if (!ret) {
 		pk_warning ("failed to get updates: %s", error->message);
 		g_error_free (error);
@@ -1374,6 +1377,9 @@
 				polkit_gnome_action_set_visible (restart_action, TRUE);
 			}
 
+			widget = glade_xml_get_widget (glade_xml, "button_close4");
+			gtk_widget_grab_default (widget);
+
 			/* set correct view */
 			pk_update_viewer_set_page (PAGE_CONFIRM);
 		}
@@ -1481,9 +1487,6 @@
 	gchar *title_bold;
 	gchar *details_safe;
 
-	/* set correct view */
-	pk_update_viewer_set_page (PAGE_ERROR);
-
 	/* set bold title */
 	widget = glade_xml_get_widget (glade_xml, "label_error_title");
 	title = gpk_error_enum_to_localised_text (code);
@@ -1498,6 +1501,12 @@
 	details_safe = g_markup_escape_text (details, -1);
 	gtk_label_set_label (GTK_LABEL (widget), details_safe);
 	g_free (details_safe);
+
+	widget = glade_xml_get_widget (glade_xml, "button_close5");
+	gtk_widget_grab_default (widget);
+
+	/* set correct view */
+	pk_update_viewer_set_page (PAGE_ERROR);
 }
 
 /**



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