gnome-packagekit r211 - in trunk: data po src



Author: rhughes
Date: Wed May 28 11:46:01 2008
New Revision: 211
URL: http://svn.gnome.org/viewvc/gnome-packagekit?rev=211&view=rev

Log:
from git

Added:
   trunk/src/gpk-animated-icon.c
   trunk/src/gpk-animated-icon.h
   trunk/src/gpk-check-update.c
   trunk/src/gpk-check-update.h
Removed:
   trunk/src/gpk-notify.c
   trunk/src/gpk-notify.h
Modified:
   trunk/data/gpk-application.glade
   trunk/data/gpk-update-viewer.glade
   trunk/po/POTFILES.in
   trunk/src/Makefile.am
   trunk/src/gpk-application.c
   trunk/src/gpk-client.c
   trunk/src/gpk-client.h
   trunk/src/gpk-common.c
   trunk/src/gpk-error.c
   trunk/src/gpk-error.h
   trunk/src/gpk-firmware.c
   trunk/src/gpk-interface.h
   trunk/src/gpk-update-viewer.c
   trunk/src/gpk-watch.c

Modified: trunk/data/gpk-application.glade
==============================================================================
--- trunk/data/gpk-application.glade	(original)
+++ trunk/data/gpk-application.glade	Wed May 28 11:46:01 2008
@@ -502,7 +502,7 @@
                                             <child>
                                               <widget class="GtkLabel" id="label_button_find">
                                                 <property name="visible">True</property>
-                                                <property name="label">_Find</property>
+                                                <property name="label">Fi_nd</property>
                                                 <property name="use_underline">True</property>
                                               </widget>
                                               <packing>

Modified: trunk/data/gpk-update-viewer.glade
==============================================================================
--- trunk/data/gpk-update-viewer.glade	(original)
+++ trunk/data/gpk-update-viewer.glade	Wed May 28 11:46:01 2008
@@ -4,11 +4,8 @@
 <glade-interface>
   <widget class="GtkWindow" id="window_updates">
     <property name="title" translatable="yes">Update System</property>
-    <property name="resizable">False</property>
-    <property name="modal">True</property>
     <property name="window_position">GTK_WIN_POS_CENTER</property>
     <property name="icon_name">system-software-update</property>
-    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
     <child>
       <widget class="GtkVBox" id="vbox4">
         <property name="visible">True</property>

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Wed May 28 11:46:01 2008
@@ -33,7 +33,6 @@
 src/gpk-install-mime-type.c
 src/gpk-log.c
 src/gpk-check-update.c
-src/gpk-notify.c
 src/gpk-prefs.c
 src/gpk-repo.c
 src/gpk-smart-icon.c

Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am	(original)
+++ trunk/src/Makefile.am	Wed May 28 11:46:01 2008
@@ -73,8 +73,6 @@
 	gpk-client-chooser.h				\
 	gpk-smart-icon.c				\
 	gpk-smart-icon.h				\
-	gpk-notify.c					\
-	gpk-notify.h					\
 	gpk-gnome.c					\
 	gpk-gnome.h					\
 	gpk-common.c					\

Added: trunk/src/gpk-animated-icon.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-animated-icon.c	Wed May 28 11:46:01 2008
@@ -0,0 +1,247 @@
+/* -*- 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 <gtk/gtk.h>
+#include <pk-debug.h>
+#include <pk-common.h>
+
+#include "gpk-animated-icon.h"
+
+G_DEFINE_TYPE (GpkAnimatedIcon, gpk_animated_icon, GTK_TYPE_IMAGE)
+
+static gpointer parent_class = NULL;
+
+/**
+ * gpk_animated_icon_free_pixbufs:
+ **/
+static gboolean
+gpk_animated_icon_free_pixbufs (GpkAnimatedIcon *icon)
+{
+	guint i;
+
+	g_return_val_if_fail (GPK_IS_ANIMATED_ICON (icon), FALSE);
+
+	/* none loaded */
+	if (icon->frames == NULL) {
+		pk_debug ("nothing to free");
+		return FALSE;
+	}
+
+	/* free each frame */
+	for (i=0; i<icon->number_frames; i++) {
+		g_object_unref (icon->frames[i]);
+	}
+	g_free (icon->frames);
+	icon->frames = NULL;
+	return TRUE;
+}
+
+/**
+ * gpk_animated_icon_set_filename_tile:
+ **/
+gboolean
+gpk_animated_icon_set_filename_tile (GpkAnimatedIcon *icon, GtkIconSize size, const gchar *name)
+{
+	gint w, h;
+	gint rows, cols;
+	gint r, c, i;
+	GdkPixbuf *pixbuf;
+
+	g_return_val_if_fail (GPK_IS_ANIMATED_ICON (icon), FALSE);
+	g_return_val_if_fail (name != NULL, FALSE);
+
+	/* have we already set the same icon */
+	if (pk_strequal (icon->filename, name)) {
+		pk_debug ("already set the same icon name %s, ignoring", name);
+		return FALSE;
+	}
+
+	/* stop existing animation */
+	gpk_animated_icon_enable_animation (icon, FALSE);
+
+	/* save new value */
+	g_free (icon->filename);
+	icon->filename = g_strdup (name);
+
+	/* do we need to unload */
+	if (icon->frames != NULL) {
+		gpk_animated_icon_free_pixbufs (icon);
+	}
+
+	pk_debug ("loading from %s", name);
+	gtk_icon_size_lookup (size, &w, &h);
+
+	pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), name, w, 0, NULL);
+	/* can't load from gnome-icon-theme */
+	if (pixbuf == NULL) {
+		pk_warning ("can't load %s", name);
+		return FALSE;
+	}
+
+	cols = gdk_pixbuf_get_width (pixbuf) / w;
+	rows = gdk_pixbuf_get_height (pixbuf) / h;
+
+	icon->frame_counter = 0;
+	icon->number_frames = rows * cols;
+	icon->frames = g_new (GdkPixbuf*, icon->number_frames);
+
+	for (i = 0, r = 0; r < rows; r++)
+		for (c = 0; c < cols; c++, i++) {
+		icon->frames[i] = gdk_pixbuf_new_subpixbuf (pixbuf, c * w, r * h, w, h);
+	}
+
+	g_object_unref (pixbuf);
+
+	return TRUE;
+}
+
+/**
+ * gpk_animated_icon_update:
+ **/
+static gboolean
+gpk_animated_icon_update (GpkAnimatedIcon *icon)
+{
+	/* have we loaded a file */
+	if (icon->frames == NULL) {
+		pk_warning ("no frames to process");
+		return FALSE;
+	}
+
+	/* set new */
+	gtk_image_set_from_pixbuf (GTK_IMAGE (icon), icon->frames[icon->frame_counter]);
+
+	/* advance counter, wrapping around */
+	icon->frame_counter = (icon->frame_counter + 1) % icon->number_frames;
+
+	return TRUE;
+}
+
+/**
+ * gpk_animated_icon_set_frame_delay:
+ **/
+gboolean
+gpk_animated_icon_set_frame_delay (GpkAnimatedIcon *icon, guint delay_ms)
+{
+	g_return_val_if_fail (GPK_IS_ANIMATED_ICON (icon), FALSE);
+
+	pk_debug ("frame delay set to %ims", delay_ms);
+	icon->frame_delay = delay_ms;
+
+	/* do we have to change a running icon? */
+	if (icon->animation_id != 0) {
+		g_source_remove (icon->animation_id);
+		icon->animation_id = g_timeout_add (icon->frame_delay, (GSourceFunc) gpk_animated_icon_update, icon);
+	}
+
+	return TRUE;
+}
+
+/**
+ * gpk_animated_icon_enable_animation:
+ **/
+gboolean
+gpk_animated_icon_enable_animation (GpkAnimatedIcon *icon, gboolean enabled)
+{
+	g_return_val_if_fail (GPK_IS_ANIMATED_ICON (icon), FALSE);
+
+	if (!enabled) {
+		if (icon->animation_id == 0) {
+			pk_debug ("ignoring stop on stopped icon");
+			return FALSE;
+		}
+
+		g_source_remove (icon->animation_id);
+		icon->animation_id = 0;
+		return TRUE;
+	}
+
+	/* don't double queue */
+	if (icon->animation_id != 0) {
+		pk_debug ("ignoring start on started icon");
+		return FALSE;
+	}
+
+	/* start */
+	icon->frame_counter = 0;
+	icon->animation_id = g_timeout_add (icon->frame_delay, (GSourceFunc) gpk_animated_icon_update, icon);
+	gpk_animated_icon_update (icon);
+	return TRUE;
+}
+
+/**
+ * gpk_image_finalize:
+ * @object: The object to finalize
+ **/
+static void
+gpk_image_finalize (GObject *object)
+{
+	GpkAnimatedIcon *icon;
+	icon = GPK_ANIMATED_ICON (object);
+
+	/* avoid going pop after unref when spinning */
+	if (icon->animation_id != 0) {
+		g_source_remove (icon->animation_id);
+	}
+	g_free (icon->filename);
+	gpk_animated_icon_free_pixbufs (icon);
+
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gpk_animated_icon_class_init (GpkAnimatedIconClass *class)
+{
+	GtkImageClass *image_class;
+	GObjectClass *object_class = G_OBJECT_CLASS (class);
+	object_class->finalize = gpk_image_finalize;
+
+	parent_class = g_type_class_peek_parent (class);
+	image_class = GTK_IMAGE_CLASS (class);
+}
+
+/**
+ * gpk_animated_icon_init:
+ **/
+static void
+gpk_animated_icon_init (GpkAnimatedIcon *icon)
+{
+	g_return_if_fail (GPK_IS_ANIMATED_ICON (icon));
+	icon->frames = NULL;
+	icon->filename = NULL;
+	icon->animation_id = 0;
+	icon->frame_counter = 0;
+	icon->number_frames = 0;
+	icon->frame_delay = 200;
+}
+
+/**
+ * gpk_animated_icon_new:
+ **/
+GtkWidget *
+gpk_animated_icon_new (void)
+{
+	return g_object_new (GPK_TYPE_ANIMATED_ICON, NULL);
+}
+

Added: trunk/src/gpk-animated-icon.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-animated-icon.h	Wed May 28 11:46:01 2008
@@ -0,0 +1,69 @@
+/* -*- 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_ANIMATED_ICON_H
+#define GPK_ANIMATED_ICON_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#define GPK_TYPE_ANIMATED_ICON			(gpk_animated_icon_get_type())
+#define GPK_ANIMATED_ICON(obj)			(G_TYPE_CHECK_INSTANCE_CAST((obj), GPK_TYPE_ANIMATED_ICON, GpkAnimatedIcon))
+#define GPK_ANIMATED_ICON_CLASS(cls)		(G_TYPE_CHECK_CLASS_CAST((cls), GPK_TYPE_ANIMATED_ICON, GpkAnimatedIconClass))
+#define GPK_IS_ANIMATED_ICON(obj)		(G_TYPE_CHECK_INSTANCE_TYPE((obj), GPK_TYPE_ANIMATED_ICON))
+#define GPK_IS_ANIMATED_ICON_CLASS(cls)		(G_TYPE_CHECK_CLASS_TYPE((cls), GPK_TYPE_ANIMATED_ICON))
+#define GPK_ANIMATED_ICON_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GPK_TYPE_ANIMATED_ICON, GpkAnimatedIconClass))
+
+G_BEGIN_DECLS
+
+typedef struct _GpkAnimatedIcon			GpkAnimatedIcon;
+typedef struct _GpkAnimatedIconClass		GpkAnimatedIconClass;
+
+struct _GpkAnimatedIcon
+{
+	GtkImage		 parent;
+	gchar			*filename;
+	guint			 animation_id;
+	guint			 frame_counter;
+	guint			 number_frames;
+	guint			 frame_delay;
+	GdkPixbuf		**frames;
+};
+
+struct _GpkAnimatedIconClass
+{
+	GtkImageClass		 parent_class;
+};
+
+GType		 gpk_animated_icon_get_type		(void) G_GNUC_CONST;
+GtkWidget	*gpk_animated_icon_new			(void);
+gboolean	 gpk_animated_icon_set_filename_tile	(GpkAnimatedIcon	*icon,
+							 GtkIconSize		 size,
+							 const gchar		*name);
+gboolean	 gpk_animated_icon_set_frame_delay	(GpkAnimatedIcon	*icon,
+							 guint			 delay_ms);
+gboolean	 gpk_animated_icon_enable_animation	(GpkAnimatedIcon	*icon,
+							 gboolean		 enabled);
+
+G_END_DECLS
+
+#endif /* GPK_ANIMATED_ICON_H */
+

Modified: trunk/src/gpk-application.c
==============================================================================
--- trunk/src/gpk-application.c	(original)
+++ trunk/src/gpk-application.c	Wed May 28 11:46:01 2008
@@ -177,7 +177,6 @@
 gpk_application_set_find_cancel_buttons (GpkApplication *application, gboolean find)
 {
 	GtkWidget *widget;
-	widget = glade_xml_get_widget (application->priv->glade_xml, "notebook_search_cancel");
 
 	/* if we can't do it, then just make the button insensitive */
 	if (!pk_enums_contain (application->priv->roles, PK_ROLE_ENUM_CANCEL)) {
@@ -186,6 +185,7 @@
 	}
 
 	/* which tab to enable? */
+	widget = glade_xml_get_widget (application->priv->glade_xml, "notebook_search_cancel");
 	if (find) {
 		gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), 0);
 	} else {
@@ -549,6 +549,7 @@
 static void
 gpk_application_error_code_cb (PkClient *client, PkErrorCodeEnum code, const gchar *details, GpkApplication *application)
 {
+	GtkWidget *widget;
 	g_return_if_fail (PK_IS_APPLICATION (application));
 
 	/* obvious message, don't tell the user */
@@ -556,8 +557,9 @@
 		return;
 	}
 
-	gpk_error_dialog (gpk_error_enum_to_localised_text (code),
-			  gpk_error_enum_to_localised_message (code), details);
+	widget = glade_xml_get_widget (application->priv->glade_xml, "window_manager");
+	gpk_error_dialog_modal (GTK_WINDOW (widget), gpk_error_enum_to_localised_text (code),
+				gpk_error_enum_to_localised_message (code), details);
 }
 
 /**
@@ -728,8 +730,9 @@
 	if (!ret) {
 		pk_debug ("invalid input text, will fail");
 		/* TODO - make the dialog turn red... */
-		gpk_error_dialog (_("Invalid search text"),
-				  _("The search text contains invalid characters"), NULL);
+		widget = glade_xml_get_widget (application->priv->glade_xml, "window_manager");
+		gpk_error_dialog_modal (GTK_WINDOW (widget), _("Invalid search text"),
+					_("The search text contains invalid characters"), NULL);
 		return FALSE;
 	}
 	pk_debug ("find %s", package);
@@ -755,8 +758,9 @@
 	}
 
 	if (!ret) {
-		gpk_error_dialog (_("The search could not be completed"),
-				  _("Running the transaction failed"), error->message);
+		widget = glade_xml_get_widget (application->priv->glade_xml, "window_manager");
+		gpk_error_dialog_modal (GTK_WINDOW (widget), _("The search could not be completed"),
+					_("Running the transaction failed"), error->message);
 		g_error_free (error);
 		return FALSE;
 	}
@@ -778,7 +782,6 @@
 	widget = glade_xml_get_widget (application->priv->glade_xml, "notebook_search_cancel");
 	gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), 1);
 
-
 	return TRUE;
 }
 
@@ -789,6 +792,7 @@
 gpk_application_perform_search_others (GpkApplication *application)
 {
 	gboolean ret;
+	GtkWidget *widget;
 	GError *error = NULL;
 
 	g_return_val_if_fail (PK_IS_APPLICATION (application), FALSE);
@@ -821,8 +825,9 @@
 		/* switch around buttons */
 		gpk_application_set_find_cancel_buttons (application, FALSE);
 	} else {
-		gpk_error_dialog (_("The group could not be queried"),
-				  _("Running the transaction failed"), error->message);
+		widget = glade_xml_get_widget (application->priv->glade_xml, "window_manager");
+		gpk_error_dialog_modal (GTK_WINDOW (widget), _("The group could not be queried"),
+					_("Running the transaction failed"), error->message);
 		g_error_free (error);
 	}
 	return ret;
@@ -1001,6 +1006,7 @@
 	gchar *package_id = NULL;
 	gchar *message;
 	const gchar *icon;
+	GtkWidget *widget;
 
 	gtk_tree_model_get (model, &iter,
 			    PACKAGES_COLUMN_INSTALLED, &installed,
@@ -1021,7 +1027,8 @@
 					   _("Click 'Clear list' to remove the previous selection or "
 					     "'Remove packages' to complete the previous action."),
 					   _("After completing the action new packages can be selected to be installed."));
-		gpk_error_dialog (_("Already selected packages to be removed"), message, NULL);
+		widget = glade_xml_get_widget (application->priv->glade_xml, "window_manager");
+		gpk_error_dialog_modal (GTK_WINDOW (widget), _("Already selected packages to be removed"), message, NULL);
 		g_free (message);
 		pk_warning ("ignoring action as ACTION=REMOVE and not in list");
 		goto out;
@@ -1040,7 +1047,8 @@
 					   _("Click 'Clear list' to remove the previous selection or "
 					     "'Install packages' to complete the previous action."),
 					   _("After completing the action new packages can be selected to be removed."));
-		gpk_error_dialog (_("Already selected packages to be installed"), message, NULL);
+		widget = glade_xml_get_widget (application->priv->glade_xml, "window_manager");
+		gpk_error_dialog_modal (GTK_WINDOW (widget), _("Already selected packages to be installed"), message, NULL);
 		g_free (message);
 		pk_warning ("ignoring action as ACTION=INSTALL");
 		goto out;
@@ -1130,7 +1138,8 @@
 	g_return_if_fail (PK_IS_APPLICATION (application));
 
 	if (application->priv->package == NULL) {
-		gpk_error_dialog (_("Cannot add package"), _("There is no package selected"), NULL);
+		widget = glade_xml_get_widget (application->priv->glade_xml, "window_manager");
+		gpk_error_dialog_modal (GTK_WINDOW (widget), _("Cannot add package"), _("There is no package selected"), NULL);
 		return;
 	}
 
@@ -2408,6 +2417,9 @@
 	application->priv->glade_xml = glade_xml_new (PK_DATA "/gpk-application.glade", NULL, NULL);
 	main_window = glade_xml_get_widget (application->priv->glade_xml, "window_manager");
 
+	/* make GpkClient windows modal */
+	gpk_client_set_parent (application->priv->gclient, GTK_WINDOW (main_window));
+
 	/* 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), PK_STOCK_APP_ICON);
@@ -2586,13 +2598,13 @@
 
 	/* hide the refresh cache button if we can't do it */
 	if (pk_enums_contain (application->priv->roles, PK_ROLE_ENUM_REFRESH_CACHE) == FALSE) {
-		widget = glade_xml_get_widget (application->priv->glade_xml, "imagemenuitem_refresh");
+		widget = glade_xml_get_widget (application->priv->glade_xml, "toolbutton_refresh");
 		gtk_widget_hide (widget);
 	}
 
 	/* hide the software-sources button if we can't do it */
 	if (pk_enums_contain (application->priv->roles, PK_ROLE_ENUM_GET_REPO_LIST) == FALSE) {
-		widget = glade_xml_get_widget (application->priv->glade_xml, "imagemenuitem_sources");
+		widget = glade_xml_get_widget (application->priv->glade_xml, "toolbutton_sources");
 		gtk_widget_hide (widget);
 	}
 

Added: trunk/src/gpk-check-update.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-check-update.c	Wed May 28 11:46:01 2008
@@ -0,0 +1,1001 @@
+/* -*- 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 <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <errno.h>
+
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <glib/gi18n.h>
+
+#include <gtk/gtk.h>
+#include <gconf/gconf-client.h>
+#include <libnotify/notify.h>
+
+#include <pk-debug.h>
+#include <pk-client.h>
+#include <pk-control.h>
+#include <pk-common.h>
+#include <pk-task-list.h>
+#include <pk-connection.h>
+#include <pk-package-id.h>
+#include <pk-package-ids.h>
+#include <pk-package-list.h>
+
+#include <gpk-common.h>
+#include <gpk-gnome.h>
+
+#include "gpk-smart-icon.h"
+#include "gpk-auto-refresh.h"
+#include "gpk-client.h"
+#include "gpk-check-update.h"
+
+static void     gpk_check_update_class_init	(GpkCheckUpdateClass *klass);
+static void     gpk_check_update_init		(GpkCheckUpdate      *cupdate);
+static void     gpk_check_update_finalize	(GObject	     *object);
+
+#define GPK_CHECK_UPDATE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPK_TYPE_CHECK_UPDATE, GpkCheckUpdatePrivate))
+
+struct GpkCheckUpdatePrivate
+{
+	GpkSmartIcon		*sicon;
+	PkConnection		*pconnection;
+	PkTaskList		*tlist;
+	PkControl		*control;
+	GpkAutoRefresh		*arefresh;
+	GpkClient		*gclient;
+	GConfClient		*gconf_client;
+	gboolean		 cache_okay;
+	gboolean		 cache_update_in_progress;
+	NotifyNotification	*notification_updates_available;
+	GPtrArray		*important_updates_array;
+};
+
+G_DEFINE_TYPE (GpkCheckUpdate, gpk_check_update, G_TYPE_OBJECT)
+
+/**
+ * gpk_check_update_class_init:
+ * @klass: The GpkCheckUpdateClass
+ **/
+static void
+gpk_check_update_class_init (GpkCheckUpdateClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = gpk_check_update_finalize;
+
+	g_type_class_add_private (klass, sizeof (GpkCheckUpdatePrivate));
+}
+
+/**
+ * gpk_check_update_show_help_cb:
+ **/
+static void
+gpk_check_update_show_help_cb (GtkMenuItem *item, GpkCheckUpdate *cupdate)
+{
+	g_return_if_fail (GPK_IS_CHECK_UPDATE (cupdate));
+	gpk_gnome_help ("update-icon");
+}
+
+/**
+ * gpk_check_update_show_preferences_cb:
+ **/
+static void
+gpk_check_update_show_preferences_cb (GtkMenuItem *item, GpkCheckUpdate *cupdate)
+{
+	const gchar *command = "gpk-prefs";
+	if (g_spawn_command_line_async (command, NULL) == FALSE) {
+		pk_warning ("Couldn't execute command: %s", command);
+	}
+}
+
+/**
+ * gpk_check_update_about_dialog_url_cb:
+ **/
+static void 
+gpk_check_update_about_dialog_url_cb (GtkAboutDialog *about, const char *address, gpointer data)
+{
+	GError *error = NULL;
+	gboolean ret;
+	char *cmdline;
+	GdkScreen *gscreen;
+	GtkWidget *error_dialog;
+	gchar *url;
+	gchar *protocol = (gchar*) data;
+
+	if (protocol != NULL)
+		url = g_strconcat (protocol, address, NULL);
+	else
+		url = g_strdup (address);
+
+	gscreen = gtk_window_get_screen (GTK_WINDOW (about));
+
+	cmdline = g_strconcat ("xdg-open ", url, NULL);
+	ret = gdk_spawn_command_line_on_screen (gscreen, cmdline, &error);
+	g_free (cmdline);
+
+	if (ret)
+		goto out;
+
+	g_error_free (error);
+	error = NULL;
+
+	cmdline = g_strconcat ("gnome-open ", url, NULL);
+	ret = gdk_spawn_command_line_on_screen (gscreen, cmdline, &error);
+	g_free (cmdline);
+
+	if (!ret) {
+		error_dialog = gtk_message_dialog_new (GTK_WINDOW (about),
+						       GTK_DIALOG_MODAL,
+						       GTK_MESSAGE_INFO,
+						       GTK_BUTTONS_OK,
+						       _("Failed to show url"));
+		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (error_dialog),
+							  "%s", error->message);
+		gtk_dialog_run (GTK_DIALOG (error_dialog));
+		gtk_widget_destroy (error_dialog);
+		g_error_free (error);
+	}
+
+out:
+	g_free (url);
+}
+
+/**
+ * gpk_check_update_show_about_cb:
+ **/
+static void
+gpk_check_update_show_about_cb (GtkMenuItem *item, gpointer data)
+{
+	static gboolean been_here = FALSE;
+	const char *authors[] = {
+		"Richard Hughes <richard hughsie com>",
+		NULL};
+	const char *documenters[] = {
+		"Richard Hughes <richard hughsie com>",
+		NULL};
+	const char *license[] = {
+		N_("Licensed under the GNU General Public License Version 2"),
+		N_("PackageKit is free software; you can redistribute it and/or\n"
+		   "modify it under the terms of the GNU General Public License\n"
+		   "as published by the Free Software Foundation; either version 2\n"
+		   "of the License, or (at your option) any later version."),
+		N_("PackageKit is distributed in the hope that it will be useful,\n"
+		   "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+		   "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+		   "GNU General Public License for more details."),
+		N_("You should have received a copy of the GNU General Public License\n"
+		   "along with this program; if not, write to the Free Software\n"
+		   "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n"
+		   "02110-1301, USA.")
+	};
+  	const char  *translators = _("translator-credits");
+	char	    *license_trans;
+
+	/* Translators comment: put your own name here to appear in the about dialog. */
+  	if (!strcmp (translators, "translator-credits")) {
+		translators = NULL;
+	}
+
+	license_trans = g_strconcat (_(license[0]), "\n\n", _(license[1]), "\n\n",
+				     _(license[2]), "\n\n", _(license[3]), "\n",  NULL);
+
+	/* FIXME: unnecessary with libgnomeui >= 2.16.0 */
+	if (!been_here) {
+		been_here = TRUE;
+		gtk_about_dialog_set_url_hook (gpk_check_update_about_dialog_url_cb, NULL, NULL);
+		gtk_about_dialog_set_email_hook (gpk_check_update_about_dialog_url_cb, "mailto:";, NULL);
+	}
+
+	gtk_window_set_default_icon_name ("system-software-installer");
+	gtk_show_about_dialog (NULL,
+			       "version", VERSION,
+			       "copyright", "Copyright \xc2\xa9 2007 Richard Hughes",
+			       "license", license_trans,
+			       "website-label", _("PackageKit Website"),
+			       "website", "www.packagekit.org",
+			       "comments", "PackageKit",
+			       "authors", authors,
+			       "documenters", documenters,
+			       "translator-credits", translators,
+			       "logo-icon-name", "system-software-installer",
+			       NULL);
+	g_free (license_trans);
+}
+
+/**
+ * gpk_check_update_popup_menu_cb:
+ *
+ * Display the popup menu.
+ **/
+static void
+gpk_check_update_popup_menu_cb (GtkStatusIcon *status_icon, guint button, guint32 timestamp, GpkCheckUpdate *icon)
+{
+	GtkMenu *menu = (GtkMenu*) gtk_menu_new ();
+	GtkWidget *item;
+	GtkWidget *image;
+
+	pk_debug ("icon right clicked");
+
+	/* Preferences */
+	item = gtk_image_menu_item_new_with_mnemonic (_("_Preferences"));
+	image = gtk_image_new_from_icon_name (GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU);
+	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+	g_signal_connect (G_OBJECT (item), "activate",
+			  G_CALLBACK (gpk_check_update_show_preferences_cb), icon);
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+	/* Separator for HIG? */
+	item = gtk_separator_menu_item_new ();
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+	/* No help yet */
+	item = gtk_image_menu_item_new_with_mnemonic (_("_Help"));
+	image = gtk_image_new_from_icon_name (GTK_STOCK_HELP, GTK_ICON_SIZE_MENU);
+	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+	g_signal_connect (G_OBJECT (item), "activate",
+			  G_CALLBACK (gpk_check_update_show_help_cb), icon);
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+	/* About */
+	item = gtk_image_menu_item_new_with_mnemonic (_("_About"));
+	image = gtk_image_new_from_icon_name (GTK_STOCK_ABOUT, GTK_ICON_SIZE_MENU);
+	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+	g_signal_connect (G_OBJECT (item), "activate",
+			  G_CALLBACK (gpk_check_update_show_about_cb), icon);
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+	/* show the menu */
+	gtk_widget_show_all (GTK_WIDGET (menu));
+	gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
+			gtk_status_icon_position_menu, status_icon,
+			button, timestamp);
+	if (button == 0) {
+		gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
+	}
+}
+
+static gboolean gpk_check_update_query_updates (GpkCheckUpdate *cupdate);
+
+/**
+ * gpk_check_update_get_updates_post_update_cb:
+ **/
+static gboolean
+gpk_check_update_get_updates_post_update_cb (GpkCheckUpdate *cupdate)
+{
+	g_return_val_if_fail (GPK_IS_CHECK_UPDATE (cupdate), FALSE);
+	gpk_check_update_query_updates (cupdate);
+	return FALSE;
+}
+
+/**
+ * gpk_check_update_update_system:
+ **/
+static gboolean
+gpk_check_update_update_system (GpkCheckUpdate *cupdate)
+{
+	gboolean ret;
+	ret = gpk_client_update_system (cupdate->priv->gclient, NULL);
+
+	/* we failed, show the icon */
+	if (!ret) {
+		gpk_smart_icon_set_icon_name (cupdate->priv->sicon, NULL);
+		/* we failed, so re-get the update list */
+		g_timeout_add_seconds (2, (GSourceFunc) gpk_check_update_get_updates_post_update_cb, cupdate);
+	}
+	return ret;
+}
+
+/**
+ * gpk_check_update_menuitem_update_system_cb:
+ **/
+static void
+gpk_check_update_menuitem_update_system_cb (GtkMenuItem *item, gpointer data)
+{
+	GpkCheckUpdate *cupdate = GPK_CHECK_UPDATE (data);
+	g_return_if_fail (GPK_IS_CHECK_UPDATE (cupdate));
+	gpk_client_show_finished (cupdate->priv->gclient, TRUE);
+	gpk_client_show_progress (cupdate->priv->gclient, TRUE);
+	gpk_check_update_update_system (cupdate);
+}
+
+/**
+ * gpk_check_update_menuitem_show_updates_cb:
+ **/
+static void
+gpk_check_update_menuitem_show_updates_cb (GtkMenuItem *item, gpointer data)
+{
+	const gchar *command = "gpk-update-viewer";
+	if (g_spawn_command_line_async (command, NULL) == FALSE) {
+		pk_warning ("Couldn't execute command: %s", command);
+	}
+}
+
+/**
+ * gpk_check_update_activate_update_cb:
+ * @button: Which buttons are pressed
+ *
+ * Callback when the icon is clicked
+ **/
+static void
+gpk_check_update_activate_update_cb (GtkStatusIcon *status_icon, GpkCheckUpdate *icon)
+{
+	GtkMenu *menu = (GtkMenu*) gtk_menu_new ();
+	GtkWidget *item;
+	GtkWidget *image;
+
+	pk_debug ("icon left clicked");
+
+	/* show updates */
+	item = gtk_image_menu_item_new_with_mnemonic (_("_Show Updates"));
+	image = gtk_image_new_from_icon_name ("system-software-update", GTK_ICON_SIZE_MENU);
+	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+	g_signal_connect (G_OBJECT (item), "activate",
+			  G_CALLBACK (gpk_check_update_menuitem_show_updates_cb), icon);
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+	/* update system */
+	item = gtk_image_menu_item_new_with_mnemonic (_("_Update System Now"));
+	image = gtk_image_new_from_icon_name ("software-update-available", GTK_ICON_SIZE_MENU);
+	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+	g_signal_connect (G_OBJECT (item), "activate",
+			  G_CALLBACK (gpk_check_update_menuitem_update_system_cb), icon);
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+	/* show the menu */
+	gtk_widget_show_all (GTK_WIDGET (menu));
+	gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
+			gtk_status_icon_position_menu, status_icon,
+			1, gtk_get_current_event_time());
+}
+
+/**
+ * pk_connection_changed_cb:
+ **/
+static void
+pk_connection_changed_cb (PkConnection *pconnection, gboolean connected, GpkCheckUpdate *cupdate)
+{
+	g_return_if_fail (GPK_IS_CHECK_UPDATE (cupdate));
+	pk_debug ("connected=%i", connected);
+}
+
+/**
+ * gpk_check_update_libnotify_cb:
+ **/
+static void
+gpk_check_update_libnotify_cb (NotifyNotification *notification, gchar *action, gpointer data)
+{
+	gboolean ret;
+	GError *error = NULL;
+	gchar **package_ids;
+	GpkCheckUpdate *cupdate = GPK_CHECK_UPDATE (data);
+
+	if (pk_strequal (action, "update-all-packages")) {
+		gpk_check_update_update_system (cupdate);
+	} else if (pk_strequal (action, "update-just-security")) {
+
+		/* just update the important updates */
+		package_ids = pk_package_ids_from_array (cupdate->priv->important_updates_array);
+		gpk_client_show_finished (cupdate->priv->gclient, FALSE);
+		gpk_client_show_progress (cupdate->priv->gclient, FALSE);
+		ret = gpk_client_update_packages (cupdate->priv->gclient, package_ids, &error);
+		if (!ret) {
+			pk_warning ("Individual updates failed: %s", error->message);
+			g_error_free (error);
+		}
+		g_strfreev (package_ids);
+
+	} else if (pk_strequal (action, "do-not-show-notify-critical")) {
+		pk_debug ("set %s to FALSE", GPK_CONF_NOTIFY_CRITICAL);
+		gconf_client_set_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_CRITICAL, FALSE, NULL);
+	} else if (pk_strequal (action, "do-not-show-update-not-battery")) {
+		pk_debug ("set %s to FALSE", GPK_CONF_NOTIFY_UPDATE_NOT_BATTERY);
+		gconf_client_set_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_UPDATE_NOT_BATTERY, FALSE, NULL);
+	} else {
+		pk_warning ("unknown action id: %s", action);
+	}
+}
+
+/**
+ * gpk_check_update_critical_updates_warning:
+ **/
+static void
+gpk_check_update_critical_updates_warning (GpkCheckUpdate *cupdate, const gchar *details, GPtrArray *array)
+{
+	guint i;
+	const gchar *package_id;
+	const gchar *title;
+	gchar *message;
+	GString *string;
+	gboolean ret;
+	GError *error = NULL;
+	NotifyNotification *notification;
+
+	g_return_if_fail (GPK_IS_CHECK_UPDATE (cupdate));
+
+	/* do we do the notification? */
+	ret = gconf_client_get_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_CRITICAL, NULL);
+	if (!ret) {
+		pk_debug ("ignoring due to GConf");
+		return;
+	}
+
+	/* save for later */
+	if (cupdate->priv->important_updates_array != NULL) {
+		g_ptr_array_free (cupdate->priv->important_updates_array, TRUE);
+	}
+	cupdate->priv->important_updates_array = g_ptr_array_new ();
+	for (i=0; i<array->len; i++) {
+		package_id = g_ptr_array_index (array, i);
+		g_ptr_array_add (cupdate->priv->important_updates_array, g_strdup (package_id));
+	}
+
+	/* format title */
+	title = ngettext ("Security update available", "Security updates available", array->len);
+
+	/* format message text */
+	string = g_string_new ("");
+	g_string_append (string, ngettext ("The following important update is available for your computer:",
+					   "The following important updates are available for your computer:", array->len));
+	g_string_append (string, "\n\n");
+	g_string_append (string, details);
+	message = g_string_free (string, FALSE);
+
+	/* close any existing notification */
+	if (cupdate->priv->notification_updates_available != NULL) {
+		notify_notification_close (cupdate->priv->notification_updates_available, NULL);
+		cupdate->priv->notification_updates_available = NULL;
+	}
+
+	/* do the bubble */
+	notification = notify_notification_new (title, message, "help-browser", NULL);
+	if (notification == NULL) {
+		pk_error ("moo");
+	}
+	notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER);
+	notify_notification_set_urgency (notification, NOTIFY_URGENCY_CRITICAL);
+	notify_notification_add_action (notification, "update-just-security",
+					_("Install important updates"), gpk_check_update_libnotify_cb, cupdate, NULL);
+	notify_notification_add_action (notification, "update-all-packages",
+					_("Install all updates"), gpk_check_update_libnotify_cb, cupdate, NULL);
+	notify_notification_add_action (notification, "do-not-show-notify-critical",
+					_("Do not show this again"), gpk_check_update_libnotify_cb, cupdate, NULL);
+	ret = notify_notification_show (notification, &error);
+	if (!ret) {
+		pk_warning ("error: %s", error->message);
+		g_error_free (error);
+	}
+	/* track so we can prevent doubled notifications */
+	cupdate->priv->notification_updates_available = notification;
+
+	g_free (message);
+}
+
+/**
+ * gpk_check_update_client_info_to_enums:
+ **/
+static PkInfoEnum
+gpk_check_update_client_info_to_enums (GpkCheckUpdate *cupdate, PkPackageList *list)
+{
+	guint i;
+	guint length;
+	PkInfoEnum infos = 0;
+	PkPackageItem *item;
+
+	g_return_val_if_fail (GPK_IS_CHECK_UPDATE (cupdate), PK_INFO_ENUM_UNKNOWN);
+
+	/* shortcut */
+	length = pk_package_list_get_size (list);
+	if (length == 0) {
+		return PK_INFO_ENUM_UNKNOWN;
+	}
+
+	/* add each status to a list */
+	for (i=0; i<length; i++) {
+		item = pk_package_list_get_item (list, i);
+		if (item == NULL) {
+			pk_warning ("not found item %i", i);
+			break;
+		}
+		pk_debug ("%s %s", item->package_id, pk_info_enum_to_text (item->info));
+		pk_enums_add (infos, item->info);
+	}
+	return infos;
+}
+
+/**
+ * gpk_check_update_get_best_update_icon:
+ **/
+static const gchar *
+gpk_check_update_get_best_update_icon (GpkCheckUpdate *cupdate, PkPackageList *list)
+{
+	gint value;
+	PkInfoEnum infos;
+	const gchar *icon;
+
+	g_return_val_if_fail (GPK_IS_CHECK_UPDATE (cupdate), NULL);
+
+	/* get an enumerated list with all the update types */
+	infos = gpk_check_update_client_info_to_enums (cupdate, list);
+
+	/* get the most important icon */
+	value = pk_enums_contain_priority (infos,
+					   PK_INFO_ENUM_SECURITY,
+					   PK_INFO_ENUM_IMPORTANT,
+					   PK_INFO_ENUM_BUGFIX,
+					   PK_INFO_ENUM_NORMAL,
+					   PK_INFO_ENUM_ENHANCEMENT,
+					   PK_INFO_ENUM_LOW, -1);
+	if (value == -1) {
+		pk_warning ("should not be possible!");
+		value = PK_INFO_ENUM_LOW;
+	}
+
+	/* get the icon */
+	icon = gpk_info_enum_to_icon_name (value);
+	return icon;
+}
+
+/**
+ * gpk_check_update_check_on_battery:
+ **/
+static gboolean
+gpk_check_update_check_on_battery (GpkCheckUpdate *cupdate)
+{
+	gboolean ret;
+	GError *error = NULL;
+	const gchar *message;
+	NotifyNotification *notification;
+
+	g_return_val_if_fail (GPK_IS_CHECK_UPDATE (cupdate), FALSE);
+
+	ret = gconf_client_get_bool (cupdate->priv->gconf_client, GPK_CONF_UPDATE_BATTERY, NULL);
+	if (ret) {
+		pk_debug ("okay to update due to policy");
+		return TRUE;
+	}
+
+	ret = gpk_auto_refresh_get_on_battery (cupdate->priv->arefresh);
+	if (!ret) {
+		pk_debug ("okay to update as on AC");
+		return TRUE;
+	}
+
+	/* do we do the notification? */
+	ret = gconf_client_get_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_UPDATE_NOT_BATTERY, NULL);
+	if (!ret) {
+		pk_debug ("ignoring due to GConf");
+		return FALSE;
+	}
+
+	/* do the bubble */
+	message = _("Automatic updates are not being installed as the computer is on battery power");
+	notification = notify_notification_new (_("Will not install updates"), message, "help-browser", NULL);
+	notify_notification_set_timeout (notification, 15000);
+	notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+	notify_notification_add_action (notification, "do-not-show-update-not-battery",
+					_("Do not show this warning again"), gpk_check_update_libnotify_cb, cupdate, NULL);
+	notify_notification_add_action (notification, "update-all-packages",
+					_("Do the updates anyway"), gpk_check_update_libnotify_cb, cupdate, NULL);
+	ret = notify_notification_show (notification, &error);
+	if (!ret) {
+		pk_warning ("error: %s", error->message);
+		g_error_free (error);
+	}
+
+	return FALSE;
+}
+
+/**
+ * gpk_check_update_get_update_policy:
+ **/
+static PkUpdateEnum
+gpk_check_update_get_update_policy (GpkCheckUpdate *cupdate)
+{
+	PkUpdateEnum update;
+	gchar *updates;
+
+	g_return_val_if_fail (GPK_IS_CHECK_UPDATE (cupdate), FALSE);
+
+	updates = gconf_client_get_string (cupdate->priv->gconf_client, GPK_CONF_AUTO_UPDATE, NULL);
+	if (updates == NULL) {
+		pk_warning ("'%s' gconf key is null!", GPK_CONF_AUTO_UPDATE);
+		return PK_UPDATE_ENUM_UNKNOWN;
+	}
+	update = pk_update_enum_from_text (updates);
+	g_free (updates);
+	return update;
+}
+
+/**
+ * gpk_check_update_query_updates:
+ **/
+static gboolean
+gpk_check_update_query_updates (GpkCheckUpdate *cupdate)
+{
+	PkPackageItem *item;
+	guint length;
+	guint i;
+	gboolean ret = FALSE;
+	GString *status_security;
+	GString *status_tooltip;
+	PkUpdateEnum update;
+	PkPackageId *ident;
+	GPtrArray *security_array;
+	const gchar *icon;
+	gchar **package_ids;
+	PkPackageList *list;
+	GError *error = NULL;
+
+	g_return_val_if_fail (GPK_IS_CHECK_UPDATE (cupdate), FALSE);
+
+	if (pk_task_list_contains_role (cupdate->priv->tlist, PK_ROLE_ENUM_UPDATE_SYSTEM)) {
+		pk_debug ("Not checking for updates as already in progress");
+		return FALSE;
+	}
+
+	/* get updates */
+	gpk_client_show_finished (cupdate->priv->gclient, FALSE);
+	gpk_client_show_progress (cupdate->priv->gclient, FALSE);
+	list = gpk_client_get_updates (cupdate->priv->gclient, &error);
+	if (list == NULL) {
+		pk_warning ("failed to get updates: %s", error->message);
+		g_error_free (error);
+		return FALSE;
+	}
+
+	/* we have updates to process */
+	status_security = g_string_new ("");
+	status_tooltip = g_string_new ("");
+	security_array = g_ptr_array_new ();
+
+	/* find packages */
+	length = pk_package_list_get_size (list);
+	pk_debug ("length=%i", length);
+
+	/* we have no updates */
+	if (length == 0) {
+		pk_debug ("no updates");
+		gpk_smart_icon_set_icon_name (cupdate->priv->sicon, NULL);
+		goto out;
+	}
+
+	/* find the security updates */
+	for (i=0; i<length; i++) {
+		item = pk_package_list_get_item (list, i);
+		pk_debug ("%s, %s, %s", pk_info_enum_to_text (item->info),
+			  item->package_id, item->summary);
+		ident = pk_package_id_new_from_string (item->package_id);
+		if (item->info == PK_INFO_ENUM_SECURITY) {
+			/* add to array */
+			g_ptr_array_add (security_array, g_strdup (item->package_id));
+			g_string_append_printf (status_security, "<b>%s</b> - %s\n",
+						ident->name, item->summary);
+		}
+		pk_package_id_free (ident);
+	}
+
+	/* do we do the automatic updates? */
+	update = gpk_check_update_get_update_policy (cupdate);
+	if (update == PK_UPDATE_ENUM_UNKNOWN) {
+		pk_warning ("policy unknown");
+		goto out;
+	}
+
+	/* work out icon */
+	icon = gpk_check_update_get_best_update_icon (cupdate, list);
+	gpk_smart_icon_set_icon_name (cupdate->priv->sicon, icon);
+	gpk_smart_icon_pulse (cupdate->priv->sicon);
+
+	/* make tooltip */
+	if (status_security->len != 0) {
+		g_string_set_size (status_security, status_security->len-1);
+	}
+	g_string_append_printf (status_tooltip, ngettext ("There is %d update pending",
+							  "There are %d updates pending", length), length);
+	gtk_status_icon_set_tooltip (GTK_STATUS_ICON (cupdate->priv->sicon), status_tooltip->str);
+
+	/* is policy none? */
+	if (update == PK_UPDATE_ENUM_NONE) {
+		pk_debug ("not updating as policy NONE");
+
+		/* do we warn the user? */
+		if (security_array->len > 0) {
+			gpk_check_update_critical_updates_warning (cupdate, status_security->str, security_array);
+		}
+		goto out;
+	}
+
+	/* are we on battery and configured to skip the action */
+	ret = gpk_check_update_check_on_battery (cupdate);
+	if (!ret) {
+		pk_debug ("on battery so not doing update");
+		/* do we warn the user? */
+		if (security_array->len > 0) {
+			gpk_check_update_critical_updates_warning (cupdate, status_security->str, security_array);
+		}
+		goto out;
+	}
+
+	/* just do security updates */
+	if (update == PK_UPDATE_ENUM_SECURITY) {
+		if (security_array->len == 0) {
+			pk_debug ("policy security, but none available");
+			goto out;
+		}
+
+		/* convert */
+		package_ids = pk_package_ids_from_array (security_array);
+		gpk_client_show_finished (cupdate->priv->gclient, FALSE);
+		gpk_client_show_progress (cupdate->priv->gclient, FALSE);
+		ret = gpk_client_update_packages (cupdate->priv->gclient, package_ids, &error);
+		if (!ret) {
+			pk_warning ("Individual updates failed: %s", error->message);
+			g_error_free (error);
+
+			/* we failed, so re-get the update list */
+			gpk_check_update_query_updates (cupdate);
+		}
+		g_strfreev (package_ids);
+		goto out;
+	}
+
+	/* just do everything */
+	if (update == PK_UPDATE_ENUM_ALL) {
+		pk_debug ("we should do the update automatically!");
+		gpk_client_show_finished (cupdate->priv->gclient, FALSE);
+		gpk_client_show_progress (cupdate->priv->gclient, FALSE);
+		g_idle_add ((GSourceFunc) gpk_check_update_update_system, cupdate);
+		goto out;
+	}
+
+	/* shouldn't happen */
+	pk_warning ("unknown update mode");
+out:
+	g_object_unref (list);
+	g_string_free (status_security, TRUE);
+	g_string_free (status_tooltip, TRUE);
+	g_ptr_array_free (security_array, TRUE);
+
+	return ret;
+}
+
+/**
+ * gpk_check_update_updates_changed_cb:
+ **/
+static void
+gpk_check_update_updates_changed_cb (PkClient *client, GpkCheckUpdate *cupdate)
+{
+	g_return_if_fail (GPK_IS_CHECK_UPDATE (cupdate));
+
+	/* now try to get newest update list */
+	pk_debug ("updates changed");
+	g_idle_add ((GSourceFunc) gpk_check_update_query_updates, cupdate);
+}
+
+/**
+ * gpk_check_update_restart_schedule_cb:
+ **/
+static void
+gpk_check_update_restart_schedule_cb (PkClient *client, GpkCheckUpdate *cupdate)
+{
+	gboolean ret;
+	GError *error = NULL;
+	const gchar *file;
+
+	g_return_if_fail (GPK_IS_CHECK_UPDATE (cupdate));
+
+	/* wait for the daemon to quit */
+	g_usleep (2*G_USEC_PER_SEC);
+
+	file = BINDIR "/gpk-update-icon";
+	pk_debug ("trying to spawn: %s", file);
+	ret = g_spawn_command_line_async (file, &error);
+	if (!ret) {
+		pk_warning ("failed to spawn new instance: %s", error->message);
+		g_error_free (error);
+	}
+}
+
+/**
+ * gpk_check_update_task_list_changed_cb:
+ **/
+static void
+gpk_check_update_task_list_changed_cb (PkTaskList *tlist, GpkCheckUpdate *cupdate)
+{
+	g_return_if_fail (GPK_IS_CHECK_UPDATE (cupdate));
+	/* hide icon if we are updating */
+	if (pk_task_list_contains_role (tlist, PK_ROLE_ENUM_UPDATE_SYSTEM) ||
+	    pk_task_list_contains_role (tlist, PK_ROLE_ENUM_UPDATE_PACKAGES)) {
+		gpk_smart_icon_set_icon_name (cupdate->priv->sicon, NULL);
+	}
+}
+
+/**
+ * gpk_check_update_auto_refresh_cache_cb:
+ **/
+static void
+gpk_check_update_auto_refresh_cache_cb (GpkAutoRefresh *arefresh, GpkCheckUpdate *cupdate)
+{
+	gboolean ret;
+	g_return_if_fail (GPK_IS_CHECK_UPDATE (cupdate));
+
+	pk_debug ("refresh cache");
+
+	/* got a cache, no need to poll */
+	if (cupdate->priv->cache_okay) {
+		return;
+	}
+
+	/* already in progress, but not yet certified okay */
+	if (cupdate->priv->cache_update_in_progress) {
+		return;
+	}
+
+	cupdate->priv->cache_update_in_progress = TRUE;
+	cupdate->priv->cache_okay = TRUE;
+
+	/* use the gnome helper to refresh the cache */
+	gpk_client_show_finished (cupdate->priv->gclient, FALSE);
+	gpk_client_show_progress (cupdate->priv->gclient, FALSE);
+	ret = gpk_client_refresh_cache (cupdate->priv->gclient, NULL);
+	if (!ret) {
+		/* we failed to get the cache */
+		pk_warning ("failed to refresh cache");
+
+		/* try again in a few minutes */
+		cupdate->priv->cache_okay = FALSE;
+	} else {
+		/* stop the polling */
+		cupdate->priv->cache_okay = TRUE;
+
+		/* now try to get updates */
+		pk_debug ("get updates");
+		gpk_check_update_query_updates (cupdate);
+	}
+	cupdate->priv->cache_update_in_progress = FALSE;
+}
+
+/**
+ * gpk_check_update_auto_get_updates_cb:
+ **/
+static void
+gpk_check_update_auto_get_updates_cb (GpkAutoRefresh *arefresh, GpkCheckUpdate *cupdate)
+{
+	g_return_if_fail (GPK_IS_CHECK_UPDATE (cupdate));
+
+	/* show the icon at login time
+	 * hopefully it just needs a quick network access, else we may have to
+	 * make it a gconf variable */
+	gpk_check_update_query_updates (cupdate);
+}
+
+/**
+ * gpk_check_update_init:
+ * @cupdate: This class instance
+ **/
+static void
+gpk_check_update_init (GpkCheckUpdate *cupdate)
+{
+	GtkStatusIcon *status_icon;
+	cupdate->priv = GPK_CHECK_UPDATE_GET_PRIVATE (cupdate);
+
+	cupdate->priv->notification_updates_available = NULL;
+	cupdate->priv->important_updates_array = NULL;
+	cupdate->priv->sicon = gpk_smart_icon_new ();
+	gpk_smart_icon_set_priority (cupdate->priv->sicon, 2);
+
+	cupdate->priv->gconf_client = gconf_client_get_default ();
+	cupdate->priv->arefresh = gpk_auto_refresh_new ();
+	g_signal_connect (cupdate->priv->arefresh, "refresh-cache",
+			  G_CALLBACK (gpk_check_update_auto_refresh_cache_cb), cupdate);
+	g_signal_connect (cupdate->priv->arefresh, "get-updates",
+			  G_CALLBACK (gpk_check_update_auto_get_updates_cb), cupdate);
+
+	/* right click actions are common */
+	status_icon = GTK_STATUS_ICON (cupdate->priv->sicon);
+	g_signal_connect_object (G_OBJECT (status_icon),
+				 "popup_menu",
+				 G_CALLBACK (gpk_check_update_popup_menu_cb),
+				 cupdate, 0);
+	g_signal_connect_object (G_OBJECT (status_icon),
+				 "activate",
+				 G_CALLBACK (gpk_check_update_activate_update_cb),
+				 cupdate, 0);
+
+	/* install stuff using the gnome helpers */
+	cupdate->priv->gclient = gpk_client_new ();
+	gpk_client_show_finished (cupdate->priv->gclient, TRUE);
+	gpk_client_show_progress (cupdate->priv->gclient, TRUE);
+
+	cupdate->priv->pconnection = pk_connection_new ();
+	g_signal_connect (cupdate->priv->pconnection, "connection-changed",
+			  G_CALLBACK (pk_connection_changed_cb), cupdate);
+	if (pk_connection_valid (cupdate->priv->pconnection)) {
+		pk_connection_changed_cb (cupdate->priv->pconnection, TRUE, cupdate);
+	}
+
+	cupdate->priv->control = pk_control_new ();
+	g_signal_connect (cupdate->priv->control, "updates-changed",
+			  G_CALLBACK (gpk_check_update_updates_changed_cb), cupdate);
+	g_signal_connect (cupdate->priv->control, "restart-schedule",
+			  G_CALLBACK (gpk_check_update_restart_schedule_cb), cupdate);
+
+	/* we need the task list so we can hide the update icon when we are doing the update */
+	cupdate->priv->tlist = pk_task_list_new ();
+	g_signal_connect (cupdate->priv->tlist, "changed",
+			  G_CALLBACK (gpk_check_update_task_list_changed_cb), cupdate);
+
+	/* refresh the cache, and poll until we get a good refresh */
+	cupdate->priv->cache_okay = FALSE;
+	cupdate->priv->cache_update_in_progress = FALSE;
+}
+
+/**
+ * gpk_check_update_finalize:
+ * @object: The object to finalize
+ **/
+static void
+gpk_check_update_finalize (GObject *object)
+{
+	GpkCheckUpdate *cupdate;
+
+	g_return_if_fail (GPK_IS_CHECK_UPDATE (object));
+
+	cupdate = GPK_CHECK_UPDATE (object);
+
+	g_return_if_fail (cupdate->priv != NULL);
+
+	g_object_unref (cupdate->priv->sicon);
+	g_object_unref (cupdate->priv->pconnection);
+	g_object_unref (cupdate->priv->tlist);
+	g_object_unref (cupdate->priv->arefresh);
+	g_object_unref (cupdate->priv->gconf_client);
+	g_object_unref (cupdate->priv->control);
+	g_object_unref (cupdate->priv->gclient);
+	if (cupdate->priv->important_updates_array != NULL) {
+		g_ptr_array_free (cupdate->priv->important_updates_array, TRUE);
+	}
+
+	G_OBJECT_CLASS (gpk_check_update_parent_class)->finalize (object);
+}
+
+/**
+ * gpk_check_update_new:
+ *
+ * Return value: a new GpkCheckUpdate object.
+ **/
+GpkCheckUpdate *
+gpk_check_update_new (void)
+{
+	GpkCheckUpdate *cupdate;
+	cupdate = g_object_new (GPK_TYPE_CHECK_UPDATE, NULL);
+	return GPK_CHECK_UPDATE (cupdate);
+}
+

Added: trunk/src/gpk-check-update.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-check-update.h	Wed May 28 11:46:01 2008
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007-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_CHECK_UPDATE_H
+#define __GPK_CHECK_UPDATE_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GPK_TYPE_CHECK_UPDATE		(gpk_check_update_get_type ())
+#define GPK_CHECK_UPDATE(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), GPK_TYPE_CHECK_UPDATE, GpkCheckUpdate))
+#define GPK_CHECK_UPDATE_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), GPK_TYPE_CHECK_UPDATE, GpkCheckUpdateClass))
+#define GPK_IS_CHECK_UPDATE(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GPK_TYPE_CHECK_UPDATE))
+#define GPK_IS_CHECK_UPDATE_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), GPK_TYPE_CHECK_UPDATE))
+#define GPK_CHECK_UPDATE_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GPK_TYPE_CHECK_UPDATE, GpkCheckUpdateClass))
+#define GPK_CHECK_UPDATE_ERROR		(gpk_check_update_error_quark ())
+#define GPK_CHECK_UPDATE_TYPE_ERROR	(gpk_check_update_error_get_type ())
+
+typedef struct GpkCheckUpdatePrivate GpkCheckUpdatePrivate;
+
+typedef struct
+{
+	 GObject		 parent;
+	 GpkCheckUpdatePrivate	*priv;
+} GpkCheckUpdate;
+
+typedef struct
+{
+	GObjectClass	parent_class;
+} GpkCheckUpdateClass;
+
+GType		 gpk_check_update_get_type		  	(void) G_GNUC_CONST;
+GpkCheckUpdate	*gpk_check_update_new				(void);
+
+G_END_DECLS
+
+#endif /* __GPK_CHECK_UPDATE_H */

Modified: trunk/src/gpk-client.c
==============================================================================
--- trunk/src/gpk-client.c	(original)
+++ trunk/src/gpk-client.c	Wed May 28 11:46:01 2008
@@ -35,6 +35,8 @@
 #include <glade/glade.h>
 #include <gconf/gconf-client.h>
 #include <polkit-gnome/polkit-gnome.h>
+#include <libnotify/notify.h>
+
 #include <pk-debug.h>
 #include <pk-client.h>
 #include <pk-package-id.h>
@@ -52,7 +54,6 @@
 #include <gpk-common.h>
 #include <gpk-gnome.h>
 #include <gpk-error.h>
-#include "gpk-notify.h"
 #include "gpk-consolekit.h"
 #include "gpk-animated-icon.h"
 
@@ -73,7 +74,6 @@
 	PkClient		*client_action;
 	PkClient		*client_resolve;
 	PkClient		*client_secondary;
-	GpkNotify		*notify;
 	GladeXML		*glade_xml;
 	GConfClient		*gconf_client;
 	guint			 pulse_timer_id;
@@ -84,7 +84,8 @@
 	gboolean		 retry_untrusted_value;
 	gboolean		 show_finished;
 	gboolean		 show_progress;
-	gboolean 		 finished_okay;
+	gboolean		 show_progress_files;
+	PkExitEnum		 exit;
 };
 
 typedef enum {
@@ -252,11 +253,51 @@
 }
 
 /**
+ * gpk_client_libnotify_cb:
+ **/
+static void
+gpk_client_libnotify_cb (NotifyNotification *notification, gchar *action, gpointer data)
+{
+	gboolean ret;
+	GError *error = NULL;
+	GpkClient *gclient = GPK_CLIENT (data);
+
+	if (pk_strequal (action, "do-not-show-complete-restart")) {
+		pk_debug ("set %s to FALSE", GPK_CONF_NOTIFY_UPDATE_COMPLETE_RESTART);
+		gconf_client_set_bool (gclient->priv->gconf_client, GPK_CONF_NOTIFY_UPDATE_COMPLETE_RESTART, FALSE, NULL);
+	} else if (pk_strequal (action, "do-not-show-complete")) {
+		pk_debug ("set %s to FALSE", GPK_CONF_NOTIFY_UPDATE_COMPLETE);
+		gconf_client_set_bool (gclient->priv->gconf_client, GPK_CONF_NOTIFY_UPDATE_COMPLETE, FALSE, NULL);
+	} else if (pk_strequal (action, "do-not-show-update-started")) {
+		pk_debug ("set %s to FALSE", GPK_CONF_NOTIFY_UPDATE_STARTED);
+		gconf_client_set_bool (gclient->priv->gconf_client, GPK_CONF_NOTIFY_UPDATE_STARTED, FALSE, NULL);
+	} else if (pk_strequal (action, "cancel")) {
+		/* try to cancel */
+		ret = pk_client_cancel (gclient->priv->client_action, &error);
+		if (!ret) {
+			pk_warning ("failed to cancel client: %s", error->message);
+			g_error_free (error);
+		}
+	} else if (pk_strequal (action, "restart-computer")) {
+		/* restart using gnome-power-manager */
+		ret = gpk_restart_system ();
+		if (!ret) {
+			pk_warning ("failed to reboot");
+		}
+	} else {
+		pk_warning ("unknown action id: %s", action);
+	}
+}
+
+/**
  * gpk_client_finished_no_progress:
  **/
 static void
 gpk_client_finished_no_progress (PkClient *client, PkExitEnum exit_code, guint runtime, GpkClient *gclient)
 {
+	gboolean ret;
+	GError *error = NULL;
+	NotifyNotification *notification;
 	PkRestartEnum restart;
 	guint i;
 	guint length;
@@ -319,20 +360,31 @@
 		g_string_set_size (message_text, message_text->len-1);
 	}
 
-	/* this will not show if specified in gconf */
-	gpk_notify_create (gclient->priv->notify,
-			   _("The system update has completed"), message_text->str,
-			   "software-update-available",
-			   GPK_NOTIFY_URGENCY_LOW, GPK_NOTIFY_TIMEOUT_LONG);
+	/* do we do the notification? */
+	ret = gconf_client_get_bool (gclient->priv->gconf_client, GPK_CONF_NOTIFY_UPDATE_COMPLETE, NULL);
+	if (!ret) {
+		pk_debug ("ignoring due to GConf");
+		return;
+	}
+
+	/* do the bubble */
+	notification = notify_notification_new (_("The system update has completed"), message_text->str, "help-browser", NULL);
+	notify_notification_set_timeout (notification, 15000);
+	notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
 	if (restart == PK_RESTART_ENUM_SYSTEM) {
-		gpk_notify_button (gclient->priv->notify, GPK_NOTIFY_BUTTON_RESTART_COMPUTER, NULL);
-		gpk_notify_button (gclient->priv->notify, GPK_NOTIFY_BUTTON_DO_NOT_SHOW_AGAIN,
-					      GPK_CONF_NOTIFY_UPDATE_COMPLETE_RESTART);
+		notify_notification_add_action (notification, "restart",
+						_("Restart computer now"), gpk_client_libnotify_cb, gclient, NULL);
+		notify_notification_add_action (notification, "do-not-show-complete-restart",
+						_("Do not show this again"), gpk_client_libnotify_cb, gclient, NULL);
 	} else {
-		gpk_notify_button (gclient->priv->notify, GPK_NOTIFY_BUTTON_DO_NOT_SHOW_AGAIN,
-					      GPK_CONF_NOTIFY_UPDATE_COMPLETE);
+		notify_notification_add_action (notification, "do-not-show-complete",
+						_("Do not show this again"), gpk_client_libnotify_cb, gclient, NULL);
+	}
+	ret = notify_notification_show (notification, &error);
+	if (!ret) {
+		pk_warning ("error: %s", error->message);
+		g_error_free (error);
 	}
-	gpk_notify_show (gclient->priv->notify);
 	g_string_free (message_text, TRUE);
 }
 
@@ -347,8 +399,8 @@
 
 	g_return_if_fail (GPK_IS_CLIENT (gclient));
 
-	/* save this */
-	gclient->priv->finished_okay = (exit == PK_EXIT_ENUM_SUCCESS);
+	/* save this so we can return a proper error value */
+	gclient->priv->exit = exit;
 
 	pk_client_get_role (client, &role, NULL, NULL);
 	/* do nothing */
@@ -465,8 +517,11 @@
 static void
 gpk_client_error_code_cb (PkClient *client, PkErrorCodeEnum code, const gchar *details, GpkClient *gclient)
 {
+	gboolean ret;
+	GError *error = NULL;
 	const gchar *title;
 	const gchar *message;
+	NotifyNotification *notification;
 
 	g_return_if_fail (GPK_IS_CLIENT (gclient));
 
@@ -502,15 +557,18 @@
 	message = gpk_error_enum_to_localised_message (code);
 	if (gclient->priv->show_progress) {
 		gpk_error_dialog (title, message, details);
-	} else {
-		/* this will not show if specified in gconf */
-		gpk_notify_create (gclient->priv->notify, title, message, "help-browser",
-				   GPK_NOTIFY_URGENCY_LOW, GPK_NOTIFY_TIMEOUT_LONG);
-		gpk_notify_button (gclient->priv->notify,
-					      GPK_NOTIFY_BUTTON_DO_NOT_SHOW_AGAIN, GPK_CONF_NOTIFY_ERROR);
-		gpk_notify_show (gclient->priv->notify);
+		return;
 	}
 
+	/* do the bubble */
+	notification = notify_notification_new (title, message, "help-browser", NULL);
+	notify_notification_set_timeout (notification, 15000);
+	notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+	ret = notify_notification_show (notification, &error);
+	if (!ret) {
+		pk_warning ("error: %s", error->message);
+		g_error_free (error);
+	}
 }
 
 /**
@@ -525,6 +583,11 @@
 
 	g_return_if_fail (GPK_IS_CLIENT (gclient));
 
+	/* ignore this if it's uninteresting */
+	if (!gclient->priv->show_progress_files) {
+		return;
+	}
+
 	text = gpk_package_id_format_twoline (package_id, summary);
 	widget = glade_xml_get_widget (gclient->priv->glade_xml, "label_package");
 	gtk_widget_show (widget);
@@ -577,20 +640,14 @@
  * gpk_client_error_msg:
  **/
 static void
-gpk_client_error_msg (GpkClient *gclient, const gchar *title, const gchar *message)
+gpk_client_error_msg (GpkClient *gclient, const gchar *title, const gchar *message, const gchar *details)
 {
 	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_error_dialog_modal (GTK_WINDOW (widget), title, message, details);
 }
 
 /**
@@ -647,7 +704,7 @@
 	/* reset */
 	ret = pk_client_reset (gclient->priv->client_action, &error_local);
 	if (!ret) {
-		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"));
+		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"), error_local->message);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 		g_error_free (error_local);
 		return FALSE;
@@ -662,13 +719,13 @@
 	/* 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 files"),
-				      _("You don't have the necessary privileges to install local files"));
+				      _("You don't have the necessary privileges to install local files"), NULL);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 	} else {
 		text = g_markup_escape_text (error_local->message, -1);
 		length = g_strv_length (files_rel);
 		title = ngettext ("Failed to install file", "Failed to install files", length);
-		gpk_client_error_msg (gclient, title, text);
+		gpk_client_error_msg (gclient, title, text, error_local->message);
 		g_free (text);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 	}
@@ -720,6 +777,34 @@
 }
 
 /**
+ * gpk_client_set_error_from_exit_enum:
+ **/
+static gboolean
+gpk_client_set_error_from_exit_enum (PkExitEnum exit, GError **error)
+{
+	/* trivial case */
+	if (exit == PK_EXIT_ENUM_SUCCESS) {
+		return TRUE;
+	}
+
+	/* set the correct error type */
+	if (exit == PK_EXIT_ENUM_FAILED) {
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, "Unspecified failure");
+	} else if (exit == PK_EXIT_ENUM_CANCELLED) {
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, "Transaction was cancelled");
+	} else if (exit == PK_EXIT_ENUM_KEY_REQUIRED) {
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, "A key was required but not provided");
+	} else if (exit == PK_EXIT_ENUM_EULA_REQUIRED) {
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, "A EULA was not agreed to");
+	} else if (exit == PK_EXIT_ENUM_KILLED) {
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, "The transaction was killed");
+	} else {
+		pk_error ("unknown exit code");
+	}
+	return FALSE;
+}
+
+/**
  * gpk_client_install_local_file:
  * @gclient: a valid #GpkClient instance
  * @file_rel: a file such as <literal>./hal-devel-0.10.0.rpm</literal>
@@ -781,6 +866,7 @@
 	gpk_client_setup_window (gclient, _("Install local file"));
 
 	/* setup the UI */
+	gclient->priv->show_progress_files = TRUE;
 	gpk_client_set_page (gclient, GPK_CLIENT_PAGE_PROGRESS);
 
 	/* wait for completion */
@@ -796,8 +882,8 @@
 		gtk_main ();
 	}
 
-	/* retval depends on SUCCESS */
-	ret = gclient->priv->finished_okay;
+	/* fail the transaction and set the correct error */
+	ret = gpk_client_set_error_from_exit_enum (gclient->priv->exit, error);
 
 	/* we're done */
 	gpk_client_done (gclient);
@@ -835,7 +921,7 @@
 	ret = gpk_client_depends_show (package_ids);
 	/* did we click no or exit the window? */
 	if (!ret) {
-		gpk_client_error_msg (gclient, _("Failed to remove package"), _("Additional packages were also not removed"));
+		gpk_client_error_msg (gclient, _("Failed to remove package"), _("Additional packages were also not removed"), NULL);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, "user did not agree to additional requires");
 		ret = FALSE;
 		goto out;
@@ -845,7 +931,7 @@
 	/* reset */
 	ret = pk_client_reset (gclient->priv->client_action, &error_local);
 	if (!ret) {
-		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"));
+		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"), error_local->message);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 		ret = FALSE;
 		goto out;
@@ -857,11 +943,11 @@
 		/* 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 remove package"),
-						_("You don't have the necessary privileges to remove packages"));
+						_("You don't have the necessary privileges to remove packages"), NULL);
 			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 remove package"), text);
+			gpk_client_error_msg (gclient, _("Failed to remove package"), text, error_local->message);
 			gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 			g_free (text);
 		}
@@ -870,13 +956,14 @@
 	}
 
 	/* setup the UI */
+	gclient->priv->show_progress_files = TRUE;
 	gpk_client_set_page (gclient, GPK_CLIENT_PAGE_PROGRESS);
 
 	/* wait for completion */
 	gtk_main ();
 
-	/* retval depends on SUCCESS */
-	ret = gclient->priv->finished_okay;
+	/* fail the transaction and set the correct error */
+	ret = gpk_client_set_error_from_exit_enum (gclient->priv->exit, error);
 
 	/* we're done */
 	gpk_client_done (gclient);
@@ -906,6 +993,7 @@
 	gpk_client_setup_window (gclient, _("Install packages"));
 
 	/* setup the UI */
+	gclient->priv->show_progress_files = TRUE;
 	gpk_client_set_page (gclient, GPK_CLIENT_PAGE_PROGRESS);
 
 	/* are we dumb and can't check for depends? */
@@ -917,7 +1005,7 @@
 	ret = gpk_client_depends_show (package_ids);
 	/* did we click no or exit the window? */
 	if (!ret) {
-		gpk_client_error_msg (gclient, _("Failed to install package"), _("Additional packages were not downloaded"));
+		gpk_client_error_msg (gclient, _("Failed to install package"), _("Additional packages were not downloaded"), NULL);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, "user did not agree to additional deps");
 		ret = FALSE;
 		goto out;
@@ -927,7 +1015,7 @@
 	/* reset */
 	ret = pk_client_reset (gclient->priv->client_action, &error_local);
 	if (!ret) {
-		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"));
+		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"), error_local->message);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 		g_error_free (error_local);
 		return FALSE;
@@ -939,11 +1027,11 @@
 		/* 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"));
+					      _("You don't have the necessary privileges to install packages"), NULL);
 			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_msg (gclient, _("Failed to install package"), text, error_local->message);
 			gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 			g_free (text);
 		}
@@ -954,8 +1042,8 @@
 	/* wait for completion */
 	gtk_main ();
 
-	/* retval depends on SUCCESS */
-	ret = gclient->priv->finished_okay;
+	/* fail the transaction and set the correct error */
+	ret = gpk_client_set_error_from_exit_enum (gclient->priv->exit, error);
 
 	/* we're done */
 	gpk_client_done (gclient);
@@ -1036,7 +1124,7 @@
 	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_msg (gclient, _("Failed to search for file"), text, NULL);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 		g_free (text);
 		ret = FALSE;
@@ -1046,7 +1134,7 @@
 	/* 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_msg (gclient, _("Failed to find package"), _("The file could not be found in any packages"), NULL);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, NULL);
 		ret = FALSE;
 		goto out;
@@ -1070,7 +1158,7 @@
 	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_msg (gclient, _("Failed to install file"), text, NULL);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 		g_free (text);
 		pk_package_id_free (ident);
@@ -1080,7 +1168,7 @@
 
 	/* got junk? */
 	if (package_id == NULL) {
-		gpk_client_error_msg (gclient, _("Failed to install file"), _("Incorrect response from file search"));
+		gpk_client_error_msg (gclient, _("Failed to install file"), _("Incorrect response from file search"), NULL);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 		ret = FALSE;
 		goto out;
@@ -1112,7 +1200,6 @@
 	GError *error_local = NULL;
 	gchar *package_id = NULL;
 	gchar **package_ids = NULL;
-	gchar *text;
 	guint len;
 
 	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
@@ -1121,10 +1208,8 @@
 	ret = pk_client_what_provides (gclient->priv->client_resolve, PK_FILTER_ENUM_NOT_INSTALLED,
 				       PK_PROVIDES_ENUM_MIMETYPE, mime_type, &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 provides"), text);
+		gpk_client_error_msg (gclient, _("Failed to search for provides"), _("Incorrect response from search"), error_local->message);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
-		g_free (text);
 		ret = FALSE;
 		goto out;
 	}
@@ -1133,7 +1218,7 @@
 	len = pk_client_package_buffer_get_size	(gclient->priv->client_resolve);
 	if (len == 0) {
 		gpk_client_error_msg (gclient, _("Failed to find software"),
-				      _("No new applications can be found to handle this type of file"));
+				      _("No new applications can be found to handle this type of file"), NULL);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, NULL);
 		ret = FALSE;
 		goto out;
@@ -1144,7 +1229,7 @@
 
 	/* selected nothing */
 	if (package_id == NULL) {
-		gpk_client_error_msg (gclient, _("Failed to install software"), _("No spplications were chosen to be installed"));
+		gpk_client_error_msg (gclient, _("Failed to install software"), _("No spplications were chosen to be installed"), NULL);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, "user chose nothing");
 		ret = FALSE;
 		goto out;
@@ -1169,13 +1254,14 @@
 	GError *error_local = NULL;
 	gchar *text = NULL;
 	gchar *message = NULL;
+	NotifyNotification *notification;
 
 	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
 
 	/* reset */
 	ret = pk_client_reset (gclient->priv->client_action, &error_local);
 	if (!ret) {
-		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"));
+		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"), error_local->message);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 		goto out;
 	}
@@ -1195,33 +1281,40 @@
 
 		/* display and set */
 		text = g_strdup_printf ("%s: %s", _("Failed to update system"), message);
-		gpk_client_error_msg (gclient, _("Failed to update system"), text);
+		gpk_client_error_msg (gclient, _("Failed to update system"), text, error_local->message);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, message);
 		goto out;
 	}
 
 	/* setup the UI */
+	gclient->priv->show_progress_files = TRUE;
 	gpk_client_set_page (gclient, GPK_CLIENT_PAGE_PROGRESS);
 
 	/* if we are not showing UI, then notify the user what we are doing (just on the active terminal) */
-	if (!gclient->priv->show_progress) {
-		/* this will not show if specified in gconf */
-		gpk_notify_create (gclient->priv->notify,
-				   _("Updates are being installed"),
-				   _("Updates are being automatically installed on your computer"),
-				   "software-update-urgent",
-				   GPK_NOTIFY_URGENCY_LOW, GPK_NOTIFY_TIMEOUT_LONG);
-		gpk_notify_button (gclient->priv->notify, GPK_NOTIFY_BUTTON_CANCEL_UPDATE, NULL);
-		gpk_notify_button (gclient->priv->notify, GPK_NOTIFY_BUTTON_DO_NOT_SHOW_AGAIN,
-					      GPK_CONF_NOTIFY_UPDATE_STARTED);
-		gpk_notify_show (gclient->priv->notify);
+	ret = gconf_client_get_bool (gclient->priv->gconf_client, GPK_CONF_NOTIFY_CRITICAL, NULL);
+	if (!gclient->priv->show_progress && ret) {
+		/* do the bubble */
+		notification = notify_notification_new (_("Updates are being installed"),
+							_("Updates are being automatically installed on your computer"),
+							"software-update-urgent", NULL);
+		notify_notification_set_timeout (notification, 15000);
+		notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+		notify_notification_add_action (notification, "cancel",
+						_("Cancel update"), gpk_client_libnotify_cb, gclient, NULL);
+		notify_notification_add_action (notification, "do-not-show-update-started",
+						_("Do not show this again"), gpk_client_libnotify_cb, gclient, NULL);
+		ret = notify_notification_show (notification, &error_local);
+		if (!ret) {
+			pk_warning ("error: %s", error_local->message);
+			g_error_free (error_local);
+		}
 	}
 
 	/* wait for completion */
 	gtk_main ();
 
-	/* retval depends on SUCCESS */
-	ret = gclient->priv->finished_okay;
+	/* fail the transaction and set the correct error */
+	ret = gpk_client_set_error_from_exit_enum (gclient->priv->exit, error);
 
 out:
 	if (error_local != NULL) {
@@ -1248,7 +1341,7 @@
 	/* reset */
 	ret = pk_client_reset (gclient->priv->client_action, &error_local);
 	if (!ret) {
-		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"));
+		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"), error_local->message);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 		goto out;
 	}
@@ -1268,19 +1361,20 @@
 
 		/* display and set */
 		text = g_strdup_printf ("%s: %s", _("Failed to update package lists"), message);
-		gpk_client_error_msg (gclient, _("Failed to update package lists"), text);
+		gpk_client_error_msg (gclient, _("Failed to update package lists"), text, NULL);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, message);
 		goto out;
 	}
 
 	/* setup the UI */
+	gclient->priv->show_progress_files = FALSE;
 	gpk_client_set_page (gclient, GPK_CLIENT_PAGE_PROGRESS);
 
 	/* wait for completion */
 	gtk_main ();
 
-	/* retval depends on SUCCESS */
-	ret = gclient->priv->finished_okay;
+	/* fail the transaction and set the correct error */
+	ret = gpk_client_set_error_from_exit_enum (gclient->priv->exit, error);
 
 out:
 	if (error_local != NULL) {
@@ -1309,7 +1403,7 @@
 	/* reset */
 	ret = pk_client_reset (gclient->priv->client_action, &error_local);
 	if (!ret) {
-		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset get-updates"));
+		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset get-updates"), error_local->message);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 		g_error_free (error_local);
 		return FALSE;
@@ -1321,12 +1415,13 @@
 	/* wrap update, but handle all the GPG and EULA stuff */
 	ret = pk_client_get_updates (gclient->priv->client_action, PK_FILTER_ENUM_NONE, &error_local);
 	if (!ret) {
-		gpk_client_error_msg (gclient, _("Getting update lists failed"), _("Failed to get updates"));
+		gpk_client_error_msg (gclient, _("Getting update lists failed"), _("Failed to get updates"), error_local->message);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 		goto out;
 	}
 
 	/* setup the UI */
+	gclient->priv->show_progress_files = FALSE;
 	gpk_client_set_page (gclient, GPK_CLIENT_PAGE_PROGRESS);
 
 	/* wait for completion */
@@ -1359,7 +1454,7 @@
 	/* reset */
 	ret = pk_client_reset (gclient->priv->client_action, &error_local);
 	if (!ret) {
-		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"));
+		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"), error_local->message);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 		goto out;
 	}
@@ -1379,19 +1474,20 @@
 
 		/* display and set */
 		text = g_strdup_printf ("%s: %s", _("Failed to update packages"), message);
-		gpk_client_error_msg (gclient, _("Failed to update packages"), text);
+		gpk_client_error_msg (gclient, _("Failed to update packages"), text, NULL);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, message);
 		goto out;
 	}
 
 	/* setup the UI */
+	gclient->priv->show_progress_files = TRUE;
 	gpk_client_set_page (gclient, GPK_CLIENT_PAGE_PROGRESS);
 
 	/* wait for completion */
 	gtk_main ();
 
-	/* retval depends on SUCCESS */
-	ret = gclient->priv->finished_okay;
+	/* fail the transaction and set the correct error */
+	ret = gpk_client_set_error_from_exit_enum (gclient->priv->exit, error);
 
 out:
 	if (error_local != NULL) {
@@ -1514,38 +1610,6 @@
 }
 
 /**
- * gpk_client_notify_button_cb:
- **/
-static void
-gpk_client_notify_button_cb (GpkNotify *notify, GpkNotifyButton button,
-			     const gchar *data, GpkClient *gclient)
-{
-	gboolean ret;
-
-	g_return_if_fail (GPK_IS_CLIENT (gclient));
-
-	pk_debug ("got: %i with data %s", button, data);
-	/* find the localised text */
-	if (button == GPK_NOTIFY_BUTTON_DO_NOT_SHOW_AGAIN ||
-	    button == GPK_NOTIFY_BUTTON_DO_NOT_WARN_AGAIN) {
-		if (data == NULL) {
-			pk_warning ("data NULL");
-		} else {
-			pk_debug ("setting %s to FALSE", data);
-			gconf_client_set_bool (gclient->priv->gconf_client, data, FALSE, NULL);
-		}
-	} else if (button == GPK_NOTIFY_BUTTON_CANCEL_UPDATE) {
-		pk_client_button_cancel_cb (NULL, gclient);
-	} else if (button == GPK_NOTIFY_BUTTON_RESTART_COMPUTER) {
-		/* restart using gnome-power-manager */
-		ret = gpk_restart_system ();
-		if (!ret) {
-			pk_warning ("failed to reboot");
-		}
-	}
-}
-
-/**
  * pk_common_get_role_text:
  **/
 static gchar *
@@ -1598,6 +1662,7 @@
 	guint elapsed;
 	guint remaining;
 	GError *error = NULL;
+	PkRoleEnum role;
 
 	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
 
@@ -1647,6 +1712,19 @@
 		gpk_client_package_cb (gclient->priv->client_action, 0, text, NULL, gclient);
 	}
 
+	/* get the role */
+	ret = pk_client_get_role (gclient->priv->client_action, &role, NULL, &error);
+	if (!ret) {
+		pk_warning ("failed to get role: %s", error->message);
+		g_error_free (error);
+	}
+
+	/* setup the UI */
+	if (role == PK_ROLE_ENUM_GET_UPDATES) {
+		gclient->priv->show_progress_files = FALSE;
+	} else {
+		gclient->priv->show_progress_files = TRUE;
+	}
 	gpk_client_set_page (gclient, GPK_CLIENT_PAGE_PROGRESS);
 
 	/* wait for completion */
@@ -1656,6 +1734,19 @@
 }
 
 /**
+ * gpk_client_set_parent:
+ **/
+gboolean
+gpk_client_set_parent (GpkClient *gclient, GtkWindow *window)
+{
+	GtkWidget *widget;
+	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
+	gtk_window_set_transient_for (GTK_WINDOW (widget), window);
+	return TRUE;
+}
+
+/**
  * gpk_client_create_custom_widget:
  **/
 static GtkWidget *
@@ -1703,9 +1794,10 @@
 	gclient->priv->glade_xml = NULL;
 	gclient->priv->pulse_timer_id = 0;
 	gclient->priv->using_secondary_client = FALSE;
-	gclient->priv->finished_okay = TRUE;
+	gclient->priv->exit = PK_EXIT_ENUM_FAILED;
 	gclient->priv->show_finished = TRUE;
 	gclient->priv->show_progress = TRUE;
+	gclient->priv->show_progress_files = TRUE;
 	gclient->priv->finished_timer_id = 0;
 
 	/* add application specific icons to search path */
@@ -1741,10 +1833,6 @@
 	g_signal_connect (gclient->priv->client_action, "eula-required",
 			  G_CALLBACK (gpk_client_eula_required_cb), gclient);
 
-	gclient->priv->notify = gpk_notify_new ();
-	g_signal_connect (gclient->priv->notify, "notification-button",
-			  G_CALLBACK (gpk_client_notify_button_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);
@@ -1812,7 +1900,6 @@
 	g_object_unref (gclient->priv->client_secondary);
 	g_object_unref (gclient->priv->control);
 	g_object_unref (gclient->priv->gconf_client);
-	g_object_unref (gclient->priv->notify);
 
 	G_OBJECT_CLASS (gpk_client_parent_class)->finalize (object);
 }

Modified: trunk/src/gpk-client.h
==============================================================================
--- trunk/src/gpk-client.h	(original)
+++ trunk/src/gpk-client.h	Wed May 28 11:46:01 2008
@@ -100,6 +100,8 @@
 							 GError		**error);
 gboolean	 gpk_client_monitor_tid			(GpkClient	*gclient,
 							 const gchar	*tid);
+gboolean	 gpk_client_set_parent			(GpkClient	*gclient,
+							 GtkWindow	*window);
 
 G_END_DECLS
 

Modified: trunk/src/gpk-common.c
==============================================================================
--- trunk/src/gpk-common.c	(original)
+++ trunk/src/gpk-common.c	Wed May 28 11:46:01 2008
@@ -1341,7 +1341,8 @@
 gboolean
 gpk_set_animated_icon_from_status (GpkAnimatedIcon *icon, PkStatusEnum status, GtkIconSize size)
 {
-	const gchar *name;
+	const gchar *name = NULL;
+	guint delay = 0;
 
 	/* choose icon */
 	if (status == PK_STATUS_ENUM_REFRESH_CACHE ||
@@ -1352,17 +1353,30 @@
 	    status == PK_STATUS_ENUM_DOWNLOAD_GROUP ||
 	    status == PK_STATUS_ENUM_DOWNLOAD_UPDATEINFO) {
 		name = "pk-action-refresh-cache";
-		gpk_animated_icon_set_frame_delay (icon, 150);
-		gpk_animated_icon_set_filename_tile (icon, size, name);
-		gpk_animated_icon_enable_animation (icon, TRUE);
-	} else if (status == PK_STATUS_ENUM_QUERY ||
-		   status == PK_STATUS_ENUM_INFO) {
+		delay = 150;
+	} else if (status == PK_STATUS_ENUM_DOWNLOAD) {
+		name = "pk-action-download";
+		delay = 150;
+	} else if (status == PK_STATUS_ENUM_QUERY) {
+		name = "pk-action-searching";
+		delay = 150;
+	} else if (status == PK_STATUS_ENUM_WAIT) {
+		name = "pk-action-waiting";
+		delay = 150;
+	} else if (status == PK_STATUS_ENUM_INFO) {
 		name = "process-working";
-		gpk_animated_icon_set_frame_delay (icon, 50);
+		delay = 50;
+	} else {
+		name = gpk_status_enum_to_icon_name (status);
+	}
+
+	/* animate or set static */
+	if (delay != 0) {
+		gpk_animated_icon_set_frame_delay (icon, delay);
 		gpk_animated_icon_set_filename_tile (icon, size, name);
 		gpk_animated_icon_enable_animation (icon, TRUE);
 	} else {
-		name = gpk_status_enum_to_icon_name (status);
+		gpk_animated_icon_enable_animation (icon, FALSE);
 		gtk_image_set_from_icon_name (GTK_IMAGE (icon), name, size);
 	}
 

Modified: trunk/src/gpk-error.c
==============================================================================
--- trunk/src/gpk-error.c	(original)
+++ trunk/src/gpk-error.c	Wed May 28 11:46:01 2008
@@ -33,7 +33,8 @@
 #define PK_STOCK_WINDOW_ICON		"system-software-installer"
 
 /**
- * gpk_error_dialog:
+ * gpk_error_dialog_modal:
+ * @window: the parent 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
@@ -41,7 +42,7 @@
  * Shows a modal error, and blocks until the user clicks close
  **/
 gboolean
-gpk_error_dialog (const gchar *title, const gchar *message, const gchar *details)
+gpk_error_dialog_modal (GtkWindow *window, const gchar *title, const gchar *message, const gchar *details)
 {
 	GtkWidget *widget;
 	GladeXML *glade_xml;
@@ -54,6 +55,11 @@
 	widget = glade_xml_get_widget (glade_xml, "window_error");
 	g_signal_connect_swapped (widget, "delete_event", G_CALLBACK (gtk_main_quit), NULL);
 
+	/* make modal if window set */
+	if (window != NULL) {
+		gtk_window_set_transient_for (GTK_WINDOW (widget), window);
+	}
+
 	/* set icon name */
 	gtk_window_set_icon_name (GTK_WINDOW (widget), PK_STOCK_WINDOW_ICON);
 
@@ -101,3 +107,17 @@
 	return TRUE;
 }
 
+/**
+ * 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)
+{
+	return gpk_error_dialog_modal (NULL, title, message, details);
+}
+

Modified: trunk/src/gpk-error.h
==============================================================================
--- trunk/src/gpk-error.h	(original)
+++ trunk/src/gpk-error.h	Wed May 28 11:46:01 2008
@@ -29,6 +29,10 @@
 gboolean	 gpk_error_dialog			(const gchar	*title,
 							 const gchar	*message,
 							 const gchar	*details);
+gboolean	 gpk_error_dialog_modal			(GtkWindow	*window,
+							 const gchar	*title,
+							 const gchar	*message,
+							 const gchar	*details);
 
 G_END_DECLS
 

Modified: trunk/src/gpk-firmware.c
==============================================================================
--- trunk/src/gpk-firmware.c	(original)
+++ trunk/src/gpk-firmware.c	Wed May 28 11:46:01 2008
@@ -35,6 +35,7 @@
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 #include <gconf/gconf-client.h>
+#include <libnotify/notify.h>
 
 #include <pk-debug.h>
 #include <pk-client.h>
@@ -44,7 +45,6 @@
 #include <gpk-client.h>
 #include <gpk-common.h>
 
-#include "gpk-notify.h"
 #include "gpk-firmware.h"
 
 static void     gpk_firmware_class_init	(GpkFirmwareClass *klass);
@@ -57,28 +57,12 @@
 
 struct GpkFirmwarePrivate
 {
-	GpkNotify		*notify;
 	gchar			**files;
+	GConfClient		*gconf_client;
 };
 
 G_DEFINE_TYPE (GpkFirmware, gpk_firmware, G_TYPE_OBJECT)
 
-static gboolean
-gpk_firmware_timeout_cb (gpointer data)
-{
-	const gchar *message;
-	GpkFirmware *firmware = (GpkFirmware *) data;
-
-	message = _("Additional firmware is required to make hardware in this computer function correctly.");
-	gpk_notify_create (firmware->priv->notify, _("Additional firmware required"), message,
-			   "help-browser", GPK_NOTIFY_URGENCY_LOW, GPK_NOTIFY_TIMEOUT_NEVER);
-	gpk_notify_button (firmware->priv->notify, GPK_NOTIFY_BUTTON_INSTALL_FIRMWARE, NULL);
-	gpk_notify_button (firmware->priv->notify, GPK_NOTIFY_BUTTON_DO_NOT_SHOW_AGAIN, GPK_CONF_PROMPT_FIRMWARE);
-	gpk_notify_show (firmware->priv->notify);
-
-	return FALSE;
-}
-
 /**
  * gpk_firmware_install_file:
  **/
@@ -95,19 +79,50 @@
 }
 
 /**
- * gpk_firmware_notify_button_cb:
+ * gpk_firmware_libnotify_cb:
  **/
 static void
-gpk_firmware_notify_button_cb (GpkNotify *notify, GpkNotifyButton button,
-			       const gchar *data, GpkFirmware *firmware)
+gpk_firmware_libnotify_cb (NotifyNotification *notification, gchar *action, gpointer data)
 {
-	pk_debug ("got: %i with data %s", button, data);
-	/* find the localised text */
-	if (button == GPK_NOTIFY_BUTTON_INSTALL_FIRMWARE) {
+	GpkFirmware *firmware = GPK_FIRMWARE (data);
+
+	if (pk_strequal (action, "install-firmware")) {
 		gpk_firmware_install_file (firmware);
+	} else if (pk_strequal (action, "do-not-show-prompt-firmware")) {
+		pk_debug ("set %s to FALSE", GPK_CONF_PROMPT_FIRMWARE);
+		gconf_client_set_bool (firmware->priv->gconf_client, GPK_CONF_PROMPT_FIRMWARE, FALSE, NULL);
+	} else {
+		pk_warning ("unknown action id: %s", action);
 	}
 }
 
+static gboolean
+gpk_firmware_timeout_cb (gpointer data)
+{
+	gboolean ret;
+	GError *error = NULL;
+	const gchar *message;
+	GpkFirmware *firmware = GPK_FIRMWARE (data);
+	NotifyNotification *notification;
+
+	message = _("Additional firmware is required to make hardware in this computer function correctly.");
+	notification = notify_notification_new (_("Additional firmware required"), message, "help-browser", NULL);
+	notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER);
+	notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+	notify_notification_add_action (notification, "install-firmware",
+					_("Install firmware"), gpk_firmware_libnotify_cb, firmware, NULL);
+	notify_notification_add_action (notification, "do-not-show-prompt-firmware",
+					_("Do not show this again"), gpk_firmware_libnotify_cb, firmware, NULL);
+	ret = notify_notification_show (notification, &error);
+	if (!ret) {
+		pk_warning ("error: %s", error->message);
+		g_error_free (error);
+	}
+
+	/* never repeat */
+	return FALSE;
+}
+
 /**
  * gpk_firmware_class_init:
  * @klass: The GpkFirmwareClass
@@ -133,10 +148,14 @@
 
 	firmware->priv = GPK_FIRMWARE_GET_PRIVATE (firmware);
 	firmware->priv->files = NULL;
+	firmware->priv->gconf_client = gconf_client_get_default ();
 
-	firmware->priv->notify = gpk_notify_new ();
-	g_signal_connect (firmware->priv->notify, "notification-button",
-			  G_CALLBACK (gpk_firmware_notify_button_cb), firmware);
+	/* should we check and show the user */
+	ret = gconf_client_get_bool (firmware->priv->gconf_client, GPK_CONF_PROMPT_FIRMWARE, NULL);
+	if (!ret) {
+		pk_debug ("not showing thanks to GConf");
+		return;
+	}
 
 	/* file exists? */
 	ret = g_file_test (GPK_FIRMWARE_STATE_FILE, G_FILE_TEST_EXISTS);
@@ -181,7 +200,7 @@
 
 	g_return_if_fail (firmware->priv != NULL);
 	g_strfreev (firmware->priv->files);
-	g_object_unref (firmware->priv->notify);
+	g_object_unref (firmware->priv->gconf_client);
 
 	G_OBJECT_CLASS (gpk_firmware_parent_class)->finalize (object);
 }

Modified: trunk/src/gpk-interface.h
==============================================================================
--- trunk/src/gpk-interface.h	(original)
+++ trunk/src/gpk-interface.h	Wed May 28 11:46:01 2008
@@ -53,7 +53,7 @@
 #endif /* !G_ENABLE_DEBUG */
 
 
-/* NONE:STRING,POINTER (/tmp/dbus-binding-tool-c-marshallers.UXU2AU:1) */
+/* NONE:STRING,POINTER (/tmp/dbus-binding-tool-c-marshallers.1G9VBU:1) */
 extern void dbus_glib_marshal_gpk_dbus_VOID__STRING_POINTER (GClosure     *closure,
                                                              GValue       *return_value,
                                                              guint         n_param_values,

Modified: trunk/src/gpk-update-viewer.c
==============================================================================
--- trunk/src/gpk-update-viewer.c	(original)
+++ trunk/src/gpk-update-viewer.c	Wed May 28 11:46:01 2008
@@ -146,6 +146,9 @@
 	} else {
 		gtk_window_set_resizable (GTK_WINDOW (widget), FALSE);
 	}
+	if (page == PAGE_CONFIRM) {
+		gtk_window_unmaximize (GTK_WINDOW (widget));
+	}
 	gtk_widget_show (widget);
 
 	widget = glade_xml_get_widget (glade_xml, "hbox_hidden");
@@ -195,6 +198,7 @@
 	GtkWidget *widget;
 	GtkTreeModel *model;
 	GtkTreeIter iter;
+	gboolean ret;
 	gboolean valid;
 	gboolean update;
 	gboolean selected_all = TRUE;
@@ -251,9 +255,16 @@
 	pk_update_viewer_set_page (PAGE_LAST);
 	package_ids = pk_package_ids_from_array (array);
 	gpk_client_show_progress (gclient, TRUE);
-	gpk_client_update_packages (gclient, package_ids, NULL);
+	ret = gpk_client_update_packages (gclient, package_ids, NULL);
 	g_strfreev (package_ids);
-	pk_update_viewer_set_page (PAGE_CONFIRM);
+
+	/* did we succeed updating the system */
+	if (!ret) {
+		/* show the preview page */
+		pk_update_viewer_set_page (PAGE_PREVIEW);
+	} else {
+		pk_update_viewer_set_page (PAGE_CONFIRM);
+	}
 
 	/* get rid of the array, and free the contents */
 	g_ptr_array_free (array, TRUE);
@@ -1710,6 +1721,9 @@
 	glade_xml = glade_xml_new (PK_DATA "/gpk-update-viewer.glade", NULL, NULL);
 	main_window = glade_xml_get_widget (glade_xml, "window_updates");
 
+	/* make GpkClient windows modal */
+	gpk_client_set_parent (gclient, GTK_WINDOW (main_window));
+
 	/* hide until we have updates */
 	widget = glade_xml_get_widget (glade_xml, "hbox_reboot");
 	gtk_widget_hide (widget);

Modified: trunk/src/gpk-watch.c
==============================================================================
--- trunk/src/gpk-watch.c	(original)
+++ trunk/src/gpk-watch.c	Wed May 28 11:46:01 2008
@@ -36,6 +36,7 @@
 
 #include <gtk/gtk.h>
 #include <gconf/gconf-client.h>
+#include <libnotify/notify.h>
 
 #include <polkit-gnome/polkit-gnome.h>
 
@@ -49,7 +50,6 @@
 #include <pk-package-id.h>
 
 #include "gpk-common.h"
-#include "gpk-notify.h"
 #include "gpk-watch.h"
 #include "gpk-client.h"
 #include "gpk-inhibit.h"
@@ -71,7 +71,6 @@
 	PkControl		*control;
 	GpkSmartIcon		*sicon;
 	GpkSmartIcon		*sicon_restart;
-	GpkNotify		*notify;
 	GpkInhibit		*inhibit;
 	GpkClient		*gclient;
 	PkConnection		*pconnection;
@@ -259,6 +258,22 @@
 }
 
 /**
+ * gpk_watch_libnotify_cb:
+ **/
+static void
+gpk_watch_libnotify_cb (NotifyNotification *notification, gchar *action, gpointer data)
+{
+	GpkWatch *watch = GPK_WATCH (data);
+
+	if (pk_strequal (action, "do-not-show-notify-complete")) {
+		pk_debug ("set %s to FALSE", GPK_CONF_PROMPT_FIRMWARE);
+		gconf_client_set_bool (watch->priv->gconf_client, GPK_CONF_NOTIFY_COMPLETED, FALSE, NULL);
+	} else {
+		pk_warning ("unknown action id: %s", action);
+	}
+}
+
+/**
  * gpk_watch_finished_cb:
  **/
 static void
@@ -274,6 +289,7 @@
 	gchar *package;
 	const gchar *restart_message;
 	const gchar *icon_name;
+	NotifyNotification *notification;
 
 	g_return_if_fail (GPK_IS_WATCH (watch));
 
@@ -347,11 +363,18 @@
 		return;
 	}
 
-	/* libnotify dialog */
-	gpk_notify_create (watch->priv->notify, _("Task completed"), message,
-			   "help-browser", GPK_NOTIFY_URGENCY_LOW, GPK_NOTIFY_TIMEOUT_SHORT);
-	gpk_notify_button (watch->priv->notify, GPK_NOTIFY_BUTTON_DO_NOT_SHOW_AGAIN, GPK_CONF_NOTIFY_COMPLETED);
-	gpk_notify_show (watch->priv->notify);
+	/* do the bubble */
+	notification = notify_notification_new (_("Task completed"), message, "help-browser", NULL);
+	notify_notification_set_timeout (notification, 5000);
+	notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+	notify_notification_add_action (notification, "do-not-show-notify-complete",
+					_("Do not show this again"), gpk_watch_libnotify_cb, watch, NULL);
+	ret = notify_notification_show (notification, &error);
+	if (!ret) {
+		pk_warning ("error: %s", error->message);
+		g_error_free (error);
+	}
+
 	g_free (message);
 	g_free (package_id);
 }
@@ -362,10 +385,13 @@
 static void
 gpk_watch_error_code_cb (PkTaskList *tlist, PkClient *client, PkErrorCodeEnum error_code, const gchar *details, GpkWatch *watch)
 {
+	gboolean ret;
+	GError *error = NULL;
 	gchar *escaped_details;
 	const gchar *title;
 	gboolean is_active;
 	gboolean value;
+	NotifyNotification *notification;
 
 	g_return_if_fail (GPK_IS_WATCH (watch));
 
@@ -399,10 +425,16 @@
 	/* we need to format this */
 	escaped_details = g_markup_escape_text (details, -1);
 
-	gpk_notify_create (watch->priv->notify, title, escaped_details, "help-browser",
-			   GPK_NOTIFY_URGENCY_LOW, GPK_NOTIFY_TIMEOUT_LONG);
-	gpk_notify_button (watch->priv->notify, GPK_NOTIFY_BUTTON_DO_NOT_SHOW_AGAIN, GPK_CONF_NOTIFY_ERROR);
-	gpk_notify_show (watch->priv->notify);
+	/* do the bubble */
+	notification = notify_notification_new (title, escaped_details, "help-browser", NULL);
+	notify_notification_set_timeout (notification, 15000);
+	notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+	ret = notify_notification_show (notification, &error);
+	if (!ret) {
+		pk_warning ("error: %s", error->message);
+		g_error_free (error);
+	}
+
 	g_free (escaped_details);
 }
 
@@ -412,10 +444,13 @@
 static void
 gpk_watch_message_cb (PkTaskList *tlist, PkClient *client, PkMessageEnum message, const gchar *details, GpkWatch *watch)
 {
+	gboolean ret;
+	GError *error = NULL;
 	const gchar *title;
 	const gchar *filename;
 	gchar *escaped_details;
 	gboolean value;
+	NotifyNotification *notification;
 
 	g_return_if_fail (GPK_IS_WATCH (watch));
 
@@ -432,10 +467,16 @@
 	/* we need to format this */
 	escaped_details = g_markup_escape_text (details, -1);
 
-	gpk_notify_create (watch->priv->notify, title, escaped_details, filename,
-			   GPK_NOTIFY_URGENCY_LOW, GPK_NOTIFY_TIMEOUT_NEVER);
-	gpk_notify_button (watch->priv->notify, GPK_NOTIFY_BUTTON_DO_NOT_SHOW_AGAIN, GPK_CONF_NOTIFY_MESSAGE);
-	gpk_notify_show (watch->priv->notify);
+	/* do the bubble */
+	notification = notify_notification_new (title, escaped_details, "help-browser", NULL);
+	notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER);
+	notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+	ret = notify_notification_show (notification, &error);
+	if (!ret) {
+		pk_warning ("error: %s", error->message);
+		g_error_free (error);
+	}
+
 	g_free (escaped_details);
 }
 
@@ -601,7 +642,6 @@
 	gboolean ret;
 	GpkWatch *watch = GPK_WATCH (data);
 	GError *error = NULL;
-	gchar *message;
 
 	g_return_if_fail (GPK_IS_WATCH (watch));
 
@@ -610,13 +650,8 @@
 	gpk_client_show_progress (watch->priv->gclient, FALSE);
 	ret = gpk_client_refresh_cache (watch->priv->gclient, &error);
 	if (!ret) {
-		message = g_strdup_printf (_("The error was: %s"), error->message);
-		pk_warning ("%s", message);
+		pk_warning ("%s", error->message);
 		g_error_free (error);
-		gpk_notify_create (watch->priv->notify, _("Failed to refresh cache"), message,
-				   "process-stop", GPK_NOTIFY_URGENCY_LOW, GPK_NOTIFY_TIMEOUT_SHORT);
-		g_free (message);
-		gpk_notify_show (watch->priv->notify);
 	}
 }
 
@@ -1041,8 +1076,6 @@
 	gpk_smart_icon_set_priority (watch->priv->sicon_restart, 3);
 
 	watch->priv->set_proxy_timeout = 0;
-
-	watch->priv->notify = gpk_notify_new ();
 	watch->priv->gclient = gpk_client_new ();
 
 	/* we need to get ::locked */
@@ -1134,7 +1167,6 @@
 		g_source_remove (watch->priv->set_proxy_timeout);
 	}
 
-	g_object_unref (watch->priv->notify);
 	g_object_unref (watch->priv->sicon);
 	g_object_unref (watch->priv->inhibit);
 	g_object_unref (watch->priv->tlist);



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