gnome-packagekit r481 - in trunk: . data src



Author: rhughes
Date: Wed Jan 28 10:28:07 2009
New Revision: 481
URL: http://svn.gnome.org/viewvc/gnome-packagekit?rev=481&view=rev

Log:
from git

Modified:
   trunk/NEWS
   trunk/configure.ac
   trunk/data/gnome-packagekit.schemas.in
   trunk/data/gpk-application.glade
   trunk/src/gpk-application.c
   trunk/src/gpk-check-update.c
   trunk/src/gpk-client-dialog.c
   trunk/src/gpk-client.c
   trunk/src/gpk-common.c
   trunk/src/gpk-common.h
   trunk/src/gpk-enum.c
   trunk/src/gpk-gnome.c
   trunk/src/gpk-repo.c
   trunk/src/gpk-smart-icon.h
   trunk/src/gpk-update-icon.c
   trunk/src/gpk-update-viewer.c
   trunk/src/gpk-watch.c

Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS	(original)
+++ trunk/NEWS	Wed Jan 28 10:28:07 2009
@@ -1,3 +1,41 @@
+Version 0.4.2
+~~~~~~~~~~~~~
+Released: 2000-01-19
+
+* Translations
+ - Updated Spanish translation (Daniel Mustieles)
+ - Updated Swedish translation (Daniel Nylander)
+ - Updated Brazilian Portuguese (Igor Pires Soares)
+ - Updated Spanish translation (Jorge Gonzalez)
+ - Updated Polish translation (Tomasz Dominikowski)
+ - Updated Norwegian bokmÃl translation (Kjartan Maraas)
+ - Updated Russian translation (Leonud Kanter)
+
+* New Features:
+ - Show the remaining time in the client UI if it's available (Richard Hughes)
+
+* Bugfix:
+ - Don't retry a policy action if the previous one failed (Richard Hughes)
+ - Drop obsolete InstallPackageNames definition (Richard Hughes)
+ - Use gtk_window_set_default_size() to set the window size so the user can
+   still resize it a little (Richard Hughes)
+ - Reduce the weight of autostart desktop files to avoid showing hidden entries
+   in the run dialog (Richard Hughes)
+ - Allow pattern matches in the banned firmware list (Richard Hughes)
+ - Add intel microcode to the banned firmware list (Richard Hughes)
+ - Lots of translation bugfixes found by Andre Klapper. Fixes gnome#19564 (Richard Hughes)
+ - Show the package that caused the restart required signal in the icon tooltip (Richard Hughes)
+ - Add a keyboard shortcut to the 'Continue Anyway' button when running an
+   application as root. Fixes fd#19595 (Richard Hughes)
+ - Clear the 'updates are being installed' notification if the update finishes
+   before the notification times out. Fixes novell#407347 (Richard Hughes)
+ - Use scrollbars in the description, and set the hbox to a fixed size to avoid
+   flicker. Fixes fd#19633 (Jens Knutson)
+ - Increase the anti-flicker timout when getting the package details to prevent
+   flicker when scrolling through packages
+ - Call gpk_check_privileged_user in the update viewer (Scott Reeves)
+ - Dont reference already freed pointer when help is not installed (Scott Reeves)
+
 Version 0.4.1
 ~~~~~~~~~~~~~
 Released: 2000-01-08

Modified: trunk/configure.ac
==============================================================================
--- trunk/configure.ac	(original)
+++ trunk/configure.ac	Wed Jan 28 10:28:07 2009
@@ -1,6 +1,6 @@
 AC_PREREQ(2.52)
 
-AC_INIT(gnome-packagekit, 0.4.2)
+AC_INIT(gnome-packagekit, 0.4.3)
 AC_CONFIG_SRCDIR(src)
 AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
 AM_CONFIG_HEADER(config.h)

Modified: trunk/data/gnome-packagekit.schemas.in
==============================================================================
--- trunk/data/gnome-packagekit.schemas.in	(original)
+++ trunk/data/gnome-packagekit.schemas.in	Wed Jan 28 10:28:07 2009
@@ -126,10 +126,10 @@
       <applyto>/apps/gnome-packagekit/notify_message</applyto>
       <owner>gnome-packagekit</owner>
       <type>bool</type>
-      <default>true</default>
+      <default>false</default>
       <locale name="C">
         <short>Notify the user when there are messages</short>
-        <long>Notify the user when there are messages</long>
+        <long>Notify the user when there are messages from the package manager</long>
       </locale>
     </schema>
 
@@ -443,7 +443,11 @@
       <type>string</type>
       <default>show-confirm-search,show-confirm-deps,show-confirm-install,show-progress,show-finished,show-warning</default>
       <locale name="C">
-        <short>Interaction modes to use by default</short>
+        <short>
+	  <!-- TRANSLATORS: An interaction mode is the level of user interaction
+	       that is allowed. See ./docs/DBusInterface.txt for more information -->
+          Interaction modes to use by default
+        </short>
         <long>When displaying UI from a session DBus request, automatically use these options by default</long>
       </locale>
     </schema>
@@ -455,7 +459,11 @@
       <type>string</type>
       <default>show-confirm-install</default>
       <locale name="C">
-        <short>Interaction modes that must be used, overriding requests from client</short>
+        <short>
+	  <!-- TRANSLATORS: An interaction mode is the level of user interaction
+	       that is allowed. See ./docs/DBusInterface.txt for more information -->
+	  Interaction modes that must be used, overriding requests from client
+	</short>
         <long>When displaying UI from a session DBus request, force these options to be turned on</long>
       </locale>
     </schema>

Modified: trunk/data/gpk-application.glade
==============================================================================
--- trunk/data/gpk-application.glade	(original)
+++ trunk/data/gpk-application.glade	Wed Jan 28 10:28:07 2009
@@ -687,7 +687,7 @@
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                                    <property name="vscrollbar_policy">GTK_POLICY_NEVER</property>
+                                    <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
                                     <property name="shadow_type">GTK_SHADOW_IN</property>
                                     <child>
                                       <widget class="GtkTextView" id="textview_description">
@@ -706,7 +706,7 @@
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                                    <property name="vscrollbar_policy">GTK_POLICY_NEVER</property>
+                                    <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
                                     <property name="shadow_type">GTK_SHADOW_IN</property>
                                     <child>
                                       <widget class="GtkTreeView" id="treeview_detail">

Modified: trunk/src/gpk-application.c
==============================================================================
--- trunk/src/gpk-application.c	(original)
+++ trunk/src/gpk-application.c	Wed Jan 28 10:28:07 2009
@@ -105,7 +105,7 @@
 	PkSearchType		 search_type;
 	PkSearchMode		 search_mode;
 	PkActionMode		 action;
-	PkPackageList		*package_list;
+	GPtrArray		*package_list;
 };
 
 enum {
@@ -375,13 +375,11 @@
 	GtkTreeModel *model;
 	PkBitfield state;
 	gboolean enabled;
-	guint length;
 
 	g_return_if_fail (PK_IS_APPLICATION (application));
 
 	/* okay to apply? */
-	length = pk_package_list_get_size (application->priv->package_list);
-	if (length == 0) {
+	if (application->priv->package_list->len == 0) {
 		widget = glade_xml_get_widget (application->priv->glade_xml, "button_apply");
 		gtk_widget_set_sensitive (widget, FALSE);
 		widget = glade_xml_get_widget (application->priv->glade_xml, "button_clear");
@@ -410,13 +408,29 @@
 }
 
 /**
+ * gpk_application_find_in_queue:
+ **/
+static gchar *
+gpk_application_find_in_queue (GpkApplication *application, const gchar *package_id)
+{
+	guint i;
+	gchar *value;
+
+	for (i=0; i<application->priv->package_list->len; i++) {
+		value = g_ptr_array_index (application->priv->package_list, i);
+		if (strcmp (value, package_id) == 0)
+			return value;
+	}
+	return NULL;
+}
+
+/**
  * gpk_application_install:
  **/
 static gboolean
 gpk_application_install (GpkApplication *application)
 {
-	gboolean ret;
-	PkPackageId *id;
+	gchar *value;
 
 	g_return_val_if_fail (PK_IS_APPLICATION (application), FALSE);
 
@@ -428,9 +442,11 @@
 
 	/* changed mind, or wrong mode */
 	if (application->priv->action == PK_ACTION_REMOVE) {
-		ret = pk_package_list_remove (application->priv->package_list, application->priv->package);
-		if (ret) {
-			egg_debug ("removed %s from package list", application->priv->package);
+		value = gpk_application_find_in_queue (application, application->priv->package);
+		if (value != NULL) {
+			egg_debug ("removed %s from package list", value);
+			g_ptr_array_remove (application->priv->package_list, value);
+			g_free (value);
 
 			/* correct buttons */
 			gpk_application_allow_install (application, FALSE);
@@ -444,16 +460,14 @@
 	}
 
 	/* already added */
-	ret = pk_package_list_contains (application->priv->package_list, application->priv->package);
-	if (ret) {
+	value = gpk_application_find_in_queue (application, application->priv->package);
+	if (value != NULL) {
 		egg_warning ("already added");
 		return FALSE;
 	}
 
 	application->priv->action = PK_ACTION_INSTALL;
-	id = pk_package_id_new_from_string (application->priv->package);
-	pk_package_list_add (application->priv->package_list, 0, id, NULL);
-	pk_package_id_free (id);
+	g_ptr_array_add (application->priv->package_list, g_strdup (application->priv->package));
 
 	/* correct buttons */
 	gpk_application_allow_install (application, FALSE);
@@ -538,8 +552,7 @@
 static gboolean
 gpk_application_remove (GpkApplication *application)
 {
-	gboolean ret;
-	PkPackageId *id;
+	gchar *value;
 
 	g_return_val_if_fail (PK_IS_APPLICATION (application), FALSE);
 
@@ -551,9 +564,11 @@
 
 	/* changed mind, or wrong mode */
 	if (application->priv->action == PK_ACTION_INSTALL) {
-		ret = pk_package_list_remove (application->priv->package_list, application->priv->package);
-		if (ret) {
-			egg_debug ("removed %s from package list", application->priv->package);
+		value = gpk_application_find_in_queue (application, application->priv->package);
+		if (value != NULL) {
+			egg_debug ("removed %s from package list", value);
+			g_ptr_array_remove (application->priv->package_list, value);
+			g_free (value);
 
 			/* correct buttons */
 			gpk_application_allow_install (application, TRUE);
@@ -567,16 +582,14 @@
 	}
 
 	/* already added */
-	ret = pk_package_list_contains (application->priv->package_list, application->priv->package);
-	if (ret) {
+	value = gpk_application_find_in_queue (application, application->priv->package);
+	if (value != NULL) {
 		egg_warning ("already added");
 		return FALSE;
 	}
 
 	application->priv->action = PK_ACTION_REMOVE;
-	id = pk_package_id_new_from_string (application->priv->package);
-	pk_package_list_add (application->priv->package_list, 0, id, NULL);
-	pk_package_id_free (id);
+	g_ptr_array_add (application->priv->package_list, g_strdup (application->priv->package));
 
 	/* correct buttons */
 	gpk_application_allow_install (application, TRUE);
@@ -902,7 +915,7 @@
 	/* only clear the last data if it takes a little while, else we flicker the display */
 	if (application->priv->details_event_id > 0)
 		g_source_remove (application->priv->details_event_id);
-	application->priv->details_event_id = g_timeout_add (100, (GSourceFunc) gpk_application_clear_details_really, application);
+	application->priv->details_event_id = g_timeout_add (200, (GSourceFunc) gpk_application_clear_details_really, application);
 }
 
 /**
@@ -925,12 +938,6 @@
 	gchar *text;
 	egg_markdown_set_output (application->priv->markdown, EGG_MARKDOWN_OUTPUT_TEXT);
 	text = egg_markdown_parse (application->priv->markdown, ascii);
-	if (egg_strlen (text, 1024) > 1023) {
-		text[1020] = '.';
-		text[1021] = '.';
-		text[1022] = '.';
-		text[1023] = '\0';
-	}
 	return text;
 }
 
@@ -1071,12 +1078,13 @@
 	/* format if required */
 	egg_markdown_set_output (application->priv->markdown, EGG_MARKDOWN_OUTPUT_PANGO);
 	summary = egg_markdown_parse (application->priv->markdown, obj->summary);
+	package_id = pk_package_id_to_string (obj->id);
 
 	/* mark as got so we don't warn */
 	application->priv->has_package = TRUE;
 
 	/* are we in the package list? */
-	in_queue = pk_obj_list_exists (PK_OBJ_LIST(application->priv->package_list), obj);
+	in_queue = (gpk_application_find_in_queue (application, package_id) != NULL);
 	installed = (obj->info == PK_INFO_ENUM_INSTALLED) || (obj->info == PK_INFO_ENUM_COLLECTION_INSTALLED);
 
 	if (installed)
@@ -1101,7 +1109,6 @@
 	/* can we modify this? */
 	enabled = gpk_application_get_checkbox_enable (application, state);
 
-	package_id = pk_package_id_to_string (obj->id);
 	gtk_list_store_append (application->priv->packages_store, &iter);
 	gtk_list_store_set (application->priv->packages_store, &iter,
 			    PACKAGES_COLUMN_STATE, state,
@@ -1119,15 +1126,15 @@
 		gtk_tree_selection_select_iter (selection, &iter);
 	}
 
-	g_free (package_id);
-	g_free (summary);
-	g_free (text);
-
 	/* only process every n events else we re-order too many times */
 	if (package_cnt++ % 200 == 0) {
 		while (gtk_events_pending ())
 			gtk_main_iteration ();
 	}
+
+	g_free (package_id);
+	g_free (summary);
+	g_free (text);
 }
 
 /**
@@ -1447,7 +1454,6 @@
 gpk_application_quit (GpkApplication *application)
 {
 	gboolean ret;
-	guint length;
 	GtkResponseType result;
 	GError *error = NULL;
 	GtkWidget *widget;
@@ -1456,8 +1462,7 @@
 	g_return_val_if_fail (PK_IS_APPLICATION (application), FALSE);
 
 	/* do we have any items queued for removal or installation? */
-	length = pk_package_list_get_size (application->priv->package_list);
-	if (length != 0) {
+	if (application->priv->package_list->len != 0) {
 		widget = glade_xml_get_widget (application->priv->glade_xml, "window_manager");
 		dialog = gtk_message_dialog_new (GTK_WINDOW (widget), GTK_DIALOG_MODAL,
 						 GTK_MESSAGE_WARNING, GTK_BUTTONS_CANCEL,
@@ -1657,7 +1662,9 @@
 		valid = gtk_tree_model_iter_next (model, &iter);
 	}
 
-	pk_obj_list_clear (PK_OBJ_LIST(application->priv->package_list));
+	/* clear queue */
+	g_ptr_array_foreach (application->priv->package_list, (GFunc) g_free, NULL);
+	g_ptr_array_set_size (application->priv->package_list, 0);
 
 	/* force a button refresh */
 	widget = glade_xml_get_widget (application->priv->glade_xml, "treeview_packages");
@@ -1680,7 +1687,7 @@
 
 	g_return_if_fail (PK_IS_APPLICATION (application));
 
-	package_ids = pk_package_list_to_strv (application->priv->package_list);
+	package_ids = pk_ptr_array_to_strv (application->priv->package_list);
 	if (application->priv->action == PK_ACTION_INSTALL) {
 		gpk_client_set_interaction (application->priv->gclient, GPK_CLIENT_INTERACT_WARNING_CONFIRM_PROGRESS);
 		ret = gpk_client_install_package_ids (application->priv->gclient, package_ids, NULL);
@@ -1707,7 +1714,8 @@
 	/* refresh the search as the items may have changed and the filter has not changed */
 	if (ret) {
 		/* clear if success */
-		pk_obj_list_clear (PK_OBJ_LIST(application->priv->package_list));
+		g_ptr_array_foreach (application->priv->package_list, (GFunc) g_free, NULL);
+		g_ptr_array_set_size (application->priv->package_list, 0);
 		application->priv->action = PK_ACTION_NONE;
 		gpk_application_set_buttons_apply_clear (application);
 		gpk_application_refresh_search_results (application);
@@ -2979,7 +2987,7 @@
 	application->priv->search_text = NULL;
 	application->priv->has_package = FALSE;
 	application->priv->details_event_id = 0;
-	application->priv->package_list = pk_package_list_new ();
+	application->priv->package_list = g_ptr_array_new ();
 
 	application->priv->gconf_client = gconf_client_get_default ();
 	application->priv->repos = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
@@ -3406,6 +3414,10 @@
 	}
 	gtk_widget_show (GTK_WIDGET(main_window));
 
+	/* set details box decent size */
+	widget = glade_xml_get_widget (application->priv->glade_xml, "hbox_packages");
+	gtk_widget_set_size_request (widget, -1, 120);
+
 	widget = glade_xml_get_widget (application->priv->glade_xml, "treeview_packages");
 	gtk_tree_view_columns_autosize (GTK_TREE_VIEW (widget));
 	g_signal_connect (GTK_TREE_VIEW (widget), "row-activated",
@@ -3542,9 +3554,11 @@
 	g_object_unref (application->priv->desktop);
 	g_object_unref (application->priv->gconf_client);
 	g_object_unref (application->priv->gclient);
-	g_object_unref (application->priv->package_list);
 	g_object_unref (application->priv->markdown);
 
+	g_ptr_array_foreach (application->priv->package_list, (GFunc) g_free, NULL);
+	g_ptr_array_set_size (application->priv->package_list, 0);
+
 	g_free (application->priv->url);
 	g_free (application->priv->group);
 	g_free (application->priv->package);

Modified: trunk/src/gpk-check-update.c
==============================================================================
--- trunk/src/gpk-check-update.c	(original)
+++ trunk/src/gpk-check-update.c	Wed Jan 28 10:28:07 2009
@@ -56,6 +56,8 @@
 
 /* the maximum number of lines of data on the libnotify widget */
 #define GPK_CHECK_UPDATE_MAX_NUMBER_SECURITY_ENTRIES	7
+#define ACTION_DISTRO_UPGRADE_INFO "distro-upgrade-info"
+#define ACTION_DISTRO_UPGRADE_DO_NOT_SHOW "distro-upgrade-do-not-show-available"
 
 struct GpkCheckUpdatePrivate
 {
@@ -420,6 +422,14 @@
 	} else if (egg_strequal (action, "do-not-show-update-not-battery")) {
 		egg_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 if (egg_strequal (action, ACTION_DISTRO_UPGRADE_INFO)) {
+		ret = g_spawn_command_line_async ("/usr/share/PackageKit/pk-upgrade-distro.sh", NULL);
+		if (!ret) {
+			egg_warning ("Failure launching pk-upgrade-distro.sh");
+		}
+	} else if (egg_strequal (action, ACTION_DISTRO_UPGRADE_DO_NOT_SHOW)) {
+		egg_debug ("set %s to FALSE", GPK_CONF_NOTIFY_DISTRO_UPGRADES);
+		gconf_client_set_bool (cupdate->priv->gconf_client, GPK_CONF_NOTIFY_DISTRO_UPGRADES, FALSE, NULL);
 	} else {
 		egg_warning ("unknown action id: %s", action);
 	}
@@ -765,8 +775,11 @@
 	/* TRANSLATORS: tooltip: how many updates are waiting to be applied */
 	g_string_append_printf (status_tooltip, ngettext ("There is %d update pending",
 							  "There are %d updates pending", length), length);
+#if GTK_CHECK_VERSION(2,15,0)
+	gtk_status_icon_set_tooltip_text (GTK_STATUS_ICON (cupdate->priv->sicon), status_tooltip->str);
+#else
 	gtk_status_icon_set_tooltip (GTK_STATUS_ICON (cupdate->priv->sicon), status_tooltip->str);
-
+#endif
 	/* if we are just refreshing after a failed update, don't try to do the actions */
 	if (!policy_action) {
 		egg_debug ("skipping actions");
@@ -1014,10 +1027,10 @@
 	}
 	notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER);
 	notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL);
-	notify_notification_add_action (notification, "upgrade-info",
+	notify_notification_add_action (notification, ACTION_DISTRO_UPGRADE_INFO,
 					/* TRANSLATORS: provides more information about the upgrade */
 					_("More information"), gpk_check_update_libnotify_cb, cupdate, NULL);
-	notify_notification_add_action (notification, "do-not-show-upgrade-available",
+	notify_notification_add_action (notification, ACTION_DISTRO_UPGRADE_DO_NOT_SHOW,
 					/* TRANSLATORS: hides forever */
 					_("Do not show this again"), gpk_check_update_libnotify_cb, cupdate, NULL);
 	ret = notify_notification_show (notification, &error);
@@ -1044,7 +1057,6 @@
 	cupdate->priv->important_updates_array = NULL;
 	cupdate->priv->number_updates_critical_last_shown = 0;
 	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 ();

Modified: trunk/src/gpk-client-dialog.c
==============================================================================
--- trunk/src/gpk-client-dialog.c	(original)
+++ trunk/src/gpk-client-dialog.c	Wed Jan 28 10:28:07 2009
@@ -437,7 +437,7 @@
 	}
 
 	/* get time text */
-	timestring = gpk_time_to_localised_string (remaining);
+	timestring = gpk_time_to_imprecise_string (remaining);
 	text = g_strdup_printf (_("Remaining time : %s"), timestring);
 	gtk_progress_bar_set_text (GTK_PROGRESS_BAR (widget), text);
 out:

Modified: trunk/src/gpk-client.c
==============================================================================
--- trunk/src/gpk-client.c	(original)
+++ trunk/src/gpk-client.c	Wed Jan 28 10:28:07 2009
@@ -2907,7 +2907,7 @@
 	GError *error_local = NULL;
 	gchar *text = NULL;
 	gchar *message = NULL;
-	NotifyNotification *notification;
+	NotifyNotification *notification = NULL;
 
 	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
 
@@ -2970,6 +2970,15 @@
 	/* wait for an answer */
 	g_main_loop_run (gclient->priv->loop);
 
+	/* close the notification */
+	if (notification != NULL) {
+		ret = notify_notification_close (notification, &error_local);
+		if (!ret) {
+			egg_debug ("failed to close notification: %s", error_local->message);
+			g_error_free (error_local);
+		}
+	}
+
 	/* fail the transaction and set the correct error */
 	ret = gpk_client_set_error_from_exit_enum (gclient->priv->exit, error);
 
@@ -3457,6 +3466,14 @@
 
 	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
 
+	/* reset client */
+	ret = pk_client_reset (gclient->priv->client_action, &error);
+	if (!ret) {
+		egg_warning ("failed to reset client: %s", error->message);
+		g_error_free (error);
+		return FALSE;
+	}
+
 	ret = pk_client_set_tid (gclient->priv->client_action, tid, &error);
 	if (!ret) {
 		egg_warning ("could not set tid: %s", error->message);
@@ -3476,7 +3493,6 @@
 		egg_warning ("could not get status");
 		return FALSE;
 	}
-	gpk_client_set_status (gclient, status);
 
 	/* are we cancellable? */
 	pk_client_get_allow_cancel (gclient->priv->client_action, &allow_cancel, NULL);
@@ -3495,21 +3511,6 @@
 						PK_CLIENT_PERCENTAGE_INVALID, 0, 0, gclient);
 	}
 
-	/* do the best we can */
-	ret = pk_client_get_package (gclient->priv->client_action, &package_id, NULL);
-	if (ret) {
-		PkPackageId *id;
-		PkPackageObj *obj;
-
-		id = pk_package_id_new_from_string (package_id);
-		if (id != NULL) {
-			obj = pk_package_obj_new (PK_INFO_ENUM_UNKNOWN, id, NULL);
-			gpk_client_package_cb (gclient->priv->client_action, obj, gclient);
-			pk_package_obj_free (obj);
-		}
-		pk_package_id_free (id);
-	}
-
 	/* get the role */
 	ret = pk_client_get_role (gclient->priv->client_action, &role, NULL, &error);
 	if (!ret) {
@@ -3527,6 +3528,26 @@
 		gpk_client_dialog_setup (gclient->priv->dialog, GPK_CLIENT_DIALOG_PAGE_PROGRESS, 0);
 	else
 		gpk_client_dialog_setup (gclient->priv->dialog, GPK_CLIENT_DIALOG_PAGE_PROGRESS, GPK_CLIENT_DIALOG_PACKAGE_PADDING);
+
+	/* set the status */
+	gpk_client_set_status (gclient, status);
+
+	/* do the best we can, and get the last package */
+	ret = pk_client_get_package (gclient->priv->client_action, &package_id, NULL);
+	if (ret) {
+		PkPackageId *id;
+		PkPackageObj *obj;
+
+		id = pk_package_id_new_from_string (package_id);
+		if (id != NULL) {
+			obj = pk_package_obj_new (PK_INFO_ENUM_UNKNOWN, id, NULL);
+			egg_warning ("package_id=%s", package_id);
+			gpk_client_package_cb (gclient->priv->client_action, obj, gclient);
+			pk_package_obj_free (obj);
+		}
+		pk_package_id_free (id);
+	}
+
 	gpk_client_dialog_present (gclient->priv->dialog);
 
 	/* wait for an answer */

Modified: trunk/src/gpk-common.c
==============================================================================
--- trunk/src/gpk-common.c	(original)
+++ trunk/src/gpk-common.c	Wed Jan 28 10:28:07 2009
@@ -245,7 +245,7 @@
 		dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL,
 						 GTK_MESSAGE_WARNING, GTK_BUTTONS_CANCEL, "%s", title);
 		/* TRANSLATORS: button: allow the user to run this, even when insecure */
-		gtk_dialog_add_button (GTK_DIALOG(dialog), _("Continue Anyway"), GTK_RESPONSE_OK);
+		gtk_dialog_add_button (GTK_DIALOG(dialog), _("Continue _Anyway"), GTK_RESPONSE_OK);
 		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG(dialog), "%s", message);
 		gtk_window_set_icon_name (GTK_WINDOW(dialog), GPK_ICON_SOFTWARE_INSTALLER);
 		result = gtk_dialog_run (GTK_DIALOG(dialog));
@@ -350,6 +350,56 @@
 }
 
 /**
+ * gpk_time_to_imprecise_string:
+ * @time_secs: The time value to convert in seconds
+ *
+ * Returns a localised timestring
+ *
+ * Return value: The time string, e.g. "2 hours"
+ **/
+gchar *
+gpk_time_to_imprecise_string (guint time_secs)
+{
+	gchar* timestring = NULL;
+	guint hours;
+	guint minutes;
+	guint seconds;
+
+	/* is valid? */
+	if (time_secs == 0) {
+		/* TRANSLATORS: The actions has just literally happened */
+		timestring = g_strdup_printf (_("Now"));
+		goto out;
+	}
+
+	/* make local copy */
+	seconds = time_secs;
+
+	/* less than a minute */
+	if (seconds < 60) {
+		/* TRANSLATORS: time */
+		timestring = g_strdup_printf (ngettext ("%i second", "%i seconds", seconds), seconds);
+		goto out;
+	}
+
+	/* Add 0.5 to do rounding */
+	minutes = (guint) ((time_secs / 60.0 ) + 0.5);
+
+	/* less than an hour */
+	if (minutes < 60) {
+		/* TRANSLATORS: time */
+		timestring = g_strdup_printf (ngettext ("%i minute", "%i minutes", minutes), minutes);
+		goto out;
+	}
+
+	hours = minutes / 60;
+	/* TRANSLATORS: time */
+	timestring = g_strdup_printf (ngettext ("%i hour", "%i hours", hours), hours);
+out:
+	return timestring;
+}
+
+/**
  * gpk_time_to_localised_string:
  * @time_secs: The time value to convert in seconds
  *
@@ -369,7 +419,7 @@
 	if (time_secs == 0) {
 		/* TRANSLATORS: The actions has just literally happened */
 		timestring = g_strdup_printf (_("Now"));
-		return timestring;
+		goto out;
 	}
 
 	/* make local copy */
@@ -381,7 +431,7 @@
 		timestring = g_strdup_printf (ngettext ("%i second",
 							"%i seconds",
 							seconds), seconds);
-		return timestring;
+		goto out;
 	}
 
 	/* Add 0.5 to do rounding */
@@ -401,7 +451,7 @@
 					minutes, ngettext ("minute", "minutes", minutes),
 					seconds, ngettext ("second", "seconds", seconds));
 		}
-		return timestring;
+		goto out;
 	}
 
 	/* more than an hour */
@@ -420,6 +470,7 @@
 				hours, ngettext ("hour", "hours", hours),
 				minutes, ngettext ("minute", "minutes", minutes));
 	}
+out:
 	return timestring;
 }
 
@@ -626,6 +677,33 @@
 		egg_test_failed (test, "failed, got %s", text);
 	g_free (text);
 
+	/************************************************************/
+	egg_test_title (test, "imprecise time 1s");
+	text = gpk_time_to_imprecise_string (1);
+	if (text != NULL && strcmp (text, "1 second") == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed, got %s", text);
+	g_free (text);
+
+	/************************************************************/
+	egg_test_title (test, "imprecise time 30m");
+	text = gpk_time_to_imprecise_string (30*60);
+	if (text != NULL && strcmp (text, "30 minutes") == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed, got %s", text);
+	g_free (text);
+
+	/************************************************************/
+	egg_test_title (test, "imprecise time 30m10s");
+	text = gpk_time_to_imprecise_string (30*60+10);
+	if (text != NULL && strcmp (text, "30 minutes") == 0)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "failed, got %s", text);
+	g_free (text);
+
 	/************************************************************
 	 ****************     package name text        **************
 	 ************************************************************/

Modified: trunk/src/gpk-common.h
==============================================================================
--- trunk/src/gpk-common.h	(original)
+++ trunk/src/gpk-common.h	Wed Jan 28 10:28:07 2009
@@ -89,6 +89,7 @@
 gchar		*gpk_package_id_name_version		(const PkPackageId *id);
 
 gchar		*gpk_time_to_localised_string		(guint		 time_secs);
+gchar		*gpk_time_to_imprecise_string		(guint		 time_secs);
 gboolean	 gpk_check_privileged_user		(const gchar	*application_name,
 							 gboolean	 show_ui);
 gboolean	 gpk_set_animated_icon_from_status	(GpkAnimatedIcon *icon,

Modified: trunk/src/gpk-enum.c
==============================================================================
--- trunk/src/gpk-enum.c	(original)
+++ trunk/src/gpk-enum.c	Wed Jan 28 10:28:07 2009
@@ -898,7 +898,7 @@
 		break;
 	case PK_STATUS_ENUM_WAITING_FOR_LOCK:
 		/* TRANSLATORS: The transaction state */
-		text = _("Waiting for legacy package manager lock");
+		text = _("Waiting for package manager lock");
 		break;
 	default:
 		egg_warning ("status unrecognised: %s", pk_status_enum_to_text (status));

Modified: trunk/src/gpk-gnome.c
==============================================================================
--- trunk/src/gpk-gnome.c	(original)
+++ trunk/src/gpk-gnome.c	Wed Jan 28 10:28:07 2009
@@ -62,6 +62,7 @@
 	GdkScreen *gscreen;
 	gint i;
 	gboolean ret = TRUE;
+	gboolean found_help_file = FALSE;
 	const gchar *const *langs = g_get_language_names ();
 
 	for (i = 0; langs[i]; i++) {
@@ -70,10 +71,17 @@
 			continue;
 		uri = g_build_filename (DATADIR, "/gnome/help/gnome-packagekit/",
 					lang, "/gnome-packagekit.xml", NULL);
-		if (g_file_test (uri, G_FILE_TEST_EXISTS))
+		if (g_file_test (uri, G_FILE_TEST_EXISTS)) {
+			found_help_file = TRUE;
 			break;
+		}
 		g_free (uri);
 	}
+	if (!found_help_file) {
+		egg_warning ("cant find help file");
+		return FALSE;
+	}
+
 	if (link_id)
 		command = g_strconcat ("gnome-open ghelp://", uri, "?", link_id, NULL);
 	else

Modified: trunk/src/gpk-repo.c
==============================================================================
--- trunk/src/gpk-repo.c	(original)
+++ trunk/src/gpk-repo.c	Wed Jan 28 10:28:07 2009
@@ -51,8 +51,7 @@
 static gboolean show_details;
 static GtkTreePath *path_global = NULL;
 
-enum
-{
+enum {
 	REPO_COLUMN_ENABLED,
 	REPO_COLUMN_TEXT,
 	REPO_COLUMN_ID,
@@ -143,16 +142,16 @@
 }
 
 /**
- * pk_button_help_cb:
+ * gpk_button_help_cb:
  **/
 static void
-pk_button_help_cb (GtkWidget *widget, gboolean  data)
+gpk_button_help_cb (GtkWidget *widget, gboolean  data)
 {
 	gpk_gnome_help ("software-sources");
 }
 
 static void
-pk_misc_installed_toggled (GtkCellRendererToggle *cell, gchar *path_str, gpointer data)
+gpk_misc_installed_toggled (GtkCellRendererToggle *cell, gchar *path_str, gpointer data)
 {
 	GtkWidget *widget;
 	GtkTreeModel *model = (GtkTreeModel *)data;
@@ -232,10 +231,10 @@
 }
 
 /**
- * pk_treeview_add_columns:
+ * gpk_treeview_add_columns:
  **/
 static void
-pk_treeview_add_columns (GtkTreeView *treeview)
+gpk_treeview_add_columns (GtkTreeView *treeview)
 {
 	GtkCellRenderer *renderer;
 	GtkTreeViewColumn *column;
@@ -243,7 +242,7 @@
 
 	/* column for installed toggles */
 	renderer = gtk_cell_renderer_toggle_new ();
-	g_signal_connect (renderer, "toggled", G_CALLBACK (pk_misc_installed_toggled), model);
+	g_signal_connect (renderer, "toggled", G_CALLBACK (gpk_misc_installed_toggled), model);
 
 	/* TRANSLATORS: column if the source is enabled */
 	column = gtk_tree_view_column_new_with_attributes (_("Enabled"), renderer,
@@ -260,10 +259,10 @@
 }
 
 /**
- * pk_repos_treeview_clicked_cb:
+ * gpk_repos_treeview_clicked_cb:
  **/
 static void
-pk_repos_treeview_clicked_cb (GtkTreeSelection *selection, gpointer data)
+gpk_repos_treeview_clicked_cb (GtkTreeSelection *selection, gpointer data)
 {
 	GtkTreeModel *model;
 	GtkTreeIter iter;
@@ -507,7 +506,7 @@
 	g_signal_connect_swapped (widget, "clicked", G_CALLBACK (gtk_main_quit), NULL);
 	widget = glade_xml_get_widget (glade_xml, "button_help");
 	g_signal_connect (widget, "clicked",
-			  G_CALLBACK (pk_button_help_cb), NULL);
+			  G_CALLBACK (gpk_button_help_cb), NULL);
 
 	widget = glade_xml_get_widget (glade_xml, "checkbutton_detail");
 	show_details = gconf_client_get_bool (gconf_client, GPK_CONF_REPO_SHOW_DETAILS, NULL);
@@ -529,10 +528,10 @@
 
 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
 	g_signal_connect (selection, "changed",
-			  G_CALLBACK (pk_repos_treeview_clicked_cb), NULL);
+			  G_CALLBACK (gpk_repos_treeview_clicked_cb), NULL);
 
 	/* add columns to the tree view */
-	pk_treeview_add_columns (GTK_TREE_VIEW (widget));
+	gpk_treeview_add_columns (GTK_TREE_VIEW (widget));
 	gtk_tree_view_columns_autosize (GTK_TREE_VIEW (widget));
 
 	/* show window */

Modified: trunk/src/gpk-smart-icon.h
==============================================================================
--- trunk/src/gpk-smart-icon.h	(original)
+++ trunk/src/gpk-smart-icon.h	Wed Jan 28 10:28:07 2009
@@ -52,8 +52,6 @@
 GType		 gpk_smart_icon_get_type		(void) G_GNUC_CONST;
 GpkSmartIcon	*gpk_smart_icon_new			(void);
 gboolean	 gpk_smart_icon_pulse			(GpkSmartIcon		*sicon);
-gboolean	 gpk_smart_icon_set_priority		(GpkSmartIcon		*sicon,
-							 guint			 number);
 gboolean	 gpk_smart_icon_set_icon_name		(GpkSmartIcon		*sicon,
 							 const gchar		*icon_name);
 

Modified: trunk/src/gpk-update-icon.c
==============================================================================
--- trunk/src/gpk-update-icon.c	(original)
+++ trunk/src/gpk-update-icon.c	Wed Jan 28 10:28:07 2009
@@ -163,8 +163,10 @@
 
 	/* TRANSLATORS: title to pass to to the user if there are not enough privs */
 	ret = gpk_check_privileged_user (_("Update applet"), FALSE);
-	if (!ret)
+	if (!ret) {
+		egg_warning ("Exit: gpk_check_privileged_user returned FALSE");
 		return 1;
+	}
 
 	/* add application specific icons to search path */
 	gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),

Modified: trunk/src/gpk-update-viewer.c
==============================================================================
--- trunk/src/gpk-update-viewer.c	(original)
+++ trunk/src/gpk-update-viewer.c	Wed Jan 28 10:28:07 2009
@@ -1840,6 +1840,11 @@
 	notify_init ("gpk-update-viewer");
 	gtk_init (&argc, &argv);
 
+	/* TRANSLATORS: title to pass to to the user if there are not enough privs */
+	ret = gpk_check_privileged_user (_("Software Update Viewer"), TRUE);
+	if (!ret)
+		return 1;
+
 	/* add application specific icons to search path */
 	gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
 					   GPK_DATA G_DIR_SEPARATOR_S "icons");

Modified: trunk/src/gpk-watch.c
==============================================================================
--- trunk/src/gpk-watch.c	(original)
+++ trunk/src/gpk-watch.c	Wed Jan 28 10:28:07 2009
@@ -35,6 +35,7 @@
 #include <glib/gi18n.h>
 
 #include <gtk/gtk.h>
+#include <glade/glade.h>
 #include <gconf/gconf-client.h>
 #include <libnotify/notify.h>
 #include <polkit-gnome/polkit-gnome.h>
@@ -64,9 +65,12 @@
 {
 	PkControl		*control;
 	GpkSmartIcon		*sicon;
-	GpkSmartIcon		*sicon_action;
+	GPtrArray		*cached_messages;
+	GPtrArray		*restart_package_names;
+	NotifyNotification	*notification_cached_messages;
 	GpkInhibit		*inhibit;
 	GpkClient		*gclient;
+	GpkClient		*monitor;
 	PkConnection		*pconnection;
 	PkTaskList		*tlist;
 	PkRestartEnum		 restart;
@@ -77,6 +81,19 @@
 	gchar			*error_details;
 };
 
+typedef struct {
+	PkMessageEnum	 type;
+	gchar		*tid;
+	gchar		*details;
+} GpkWatchCachedMessage;
+
+enum {
+	GPK_WATCH_COLUMN_TEXT,
+	GPK_WATCH_COLUMN_TID,
+	GPK_WATCH_COLUMN_DETAILS,
+	GPK_WATCH_COLUMN_LAST
+};
+
 G_DEFINE_TYPE (GpkWatch, gpk_watch, G_TYPE_OBJECT)
 
 /**
@@ -92,6 +109,19 @@
 }
 
 /**
+ * gpk_watch_cached_message_free:
+ **/
+static void
+gpk_watch_cached_message_free (GpkWatchCachedMessage *cached_message)
+{
+	if (cached_message == NULL)
+		return;
+	g_free (cached_message->tid);
+	g_free (cached_message->details);
+	g_free (cached_message);
+}
+
+/**
  * gpk_watch_refresh_tooltip:
  **/
 static gboolean
@@ -100,19 +130,59 @@
 	guint i;
 	PkTaskListItem *item;
 	guint length;
+	guint len;
 	GString *status;
 	const gchar *trailer;
 	const gchar *localised_status;
+	gchar *package_loc;
+	gchar **packages;
 
 	g_return_val_if_fail (GPK_IS_WATCH (watch), FALSE);
 
+	status = g_string_new ("");
 	length = pk_task_list_get_size (watch->priv->tlist);
 	egg_debug ("refresh tooltip %i", length);
 	if (length == 0) {
-		gtk_status_icon_set_tooltip (GTK_STATUS_ICON (watch->priv->sicon), "Doing nothing...");
-		return TRUE;
+
+		/* any restart required? */
+		if (watch->priv->restart != PK_RESTART_ENUM_NONE) {
+			g_string_append (status, gpk_restart_enum_to_localised_text (watch->priv->restart));
+			g_string_append_c (status, '\n');
+
+			len = watch->priv->restart_package_names->len;
+
+			if (len > 0) {
+				packages = pk_ptr_array_to_strv (watch->priv->restart_package_names);
+				package_loc = gpk_strv_join_locale (packages);
+				g_strfreev (packages);
+				if (package_loc != NULL) {
+					/* TRANSLATORS: a list of packages is shown that need to restarted */
+					g_string_append_printf (status, ngettext ("Package: %s", "Packages: %s", len), package_loc);
+				} else {
+					/* TRANSLATORS: over 5 packages require the system to be restarted, don't list them all here */
+					g_string_append_printf (status, ngettext ("%i package", "%i packages", len), len);
+				}
+				g_string_append_c (status, '\n');
+				g_free (package_loc);
+			}
+
+			/* remove final \n */
+			if (status->len > 0)
+				g_string_set_size (status, status->len - 1);
+
+			goto out;
+		}
+
+		/* do we have any cached messages to show? */
+		len = watch->priv->cached_messages->len;
+		if (len > 0) {
+			g_string_append_printf (status, ngettext ("%i message from the package manager", "%i messages from the package manager", len), len);
+			goto out;
+		}
+
+		egg_debug ("nothing to show");
+		goto out;
 	}
-	status = g_string_new ("");
 	for (i=0; i<length; i++) {
 		item = pk_task_list_get_item (watch->priv->tlist, i);
 		if (item == NULL) {
@@ -142,7 +212,12 @@
 	else
 		g_string_set_size (status, status->len-1);
 
+out:
+#if GTK_CHECK_VERSION(2,15,0)
+	gtk_status_icon_set_tooltip_text (GTK_STATUS_ICON (watch->priv->sicon), status->str);
+#else
 	gtk_status_icon_set_tooltip (GTK_STATUS_ICON (watch->priv->sicon), status->str);
+#endif
 	g_string_free (status, TRUE);
 	return TRUE;
 }
@@ -185,63 +260,75 @@
 static gboolean
 gpk_watch_refresh_icon (GpkWatch *watch)
 {
-	const gchar *icon;
+	const gchar *icon_name = NULL;
 	PkBitfield status;
-	gint value;
+	gint value = -1;
+	guint len;
 
 	g_return_val_if_fail (GPK_IS_WATCH (watch), FALSE);
 
 	egg_debug ("rescan");
 	status = gpk_watch_task_list_to_status_bitfield (watch);
 
-	/* nothing in the list */
-	if (status == 0) {
-		egg_debug ("no activity");
-		gpk_smart_icon_set_icon_name (watch->priv->sicon, NULL);
-		return TRUE;
+	/* something in list */
+	if (status != 0) {
+		/* get the most important icon */
+		value = pk_bitfield_contain_priority (status,
+						      PK_STATUS_ENUM_REFRESH_CACHE,
+						      PK_STATUS_ENUM_LOADING_CACHE,
+						      PK_STATUS_ENUM_CANCEL,
+						      PK_STATUS_ENUM_INSTALL,
+						      PK_STATUS_ENUM_REMOVE,
+						      PK_STATUS_ENUM_CLEANUP,
+						      PK_STATUS_ENUM_OBSOLETE,
+						      PK_STATUS_ENUM_SETUP,
+						      PK_STATUS_ENUM_RUNNING,
+						      PK_STATUS_ENUM_UPDATE,
+						      PK_STATUS_ENUM_DOWNLOAD,
+						      PK_STATUS_ENUM_DOWNLOAD_REPOSITORY,
+						      PK_STATUS_ENUM_DOWNLOAD_PACKAGELIST,
+						      PK_STATUS_ENUM_DOWNLOAD_FILELIST,
+						      PK_STATUS_ENUM_DOWNLOAD_CHANGELOG,
+						      PK_STATUS_ENUM_DOWNLOAD_GROUP,
+						      PK_STATUS_ENUM_DOWNLOAD_UPDATEINFO,
+						      PK_STATUS_ENUM_SCAN_APPLICATIONS,
+						      PK_STATUS_ENUM_GENERATE_PACKAGE_LIST,
+						      PK_STATUS_ENUM_QUERY,
+						      PK_STATUS_ENUM_INFO,
+						      PK_STATUS_ENUM_DEP_RESOLVE,
+						      PK_STATUS_ENUM_ROLLBACK,
+						      PK_STATUS_ENUM_TEST_COMMIT,
+						      PK_STATUS_ENUM_COMMIT,
+						      PK_STATUS_ENUM_REQUEST,
+						      PK_STATUS_ENUM_SIG_CHECK,
+						      PK_STATUS_ENUM_CLEANUP,
+						      PK_STATUS_ENUM_REPACKAGING,
+						      PK_STATUS_ENUM_WAIT,
+						      PK_STATUS_ENUM_WAITING_FOR_LOCK,
+						      PK_STATUS_ENUM_FINISHED, -1);
 	}
 
-	/* get the most important icon */
-	value = pk_bitfield_contain_priority (status,
-					      PK_STATUS_ENUM_REFRESH_CACHE,
-					      PK_STATUS_ENUM_LOADING_CACHE,
-					      PK_STATUS_ENUM_CANCEL,
-					      PK_STATUS_ENUM_INSTALL,
-					      PK_STATUS_ENUM_REMOVE,
-					      PK_STATUS_ENUM_CLEANUP,
-					      PK_STATUS_ENUM_OBSOLETE,
-					      PK_STATUS_ENUM_SETUP,
-					      PK_STATUS_ENUM_RUNNING,
-					      PK_STATUS_ENUM_UPDATE,
-					      PK_STATUS_ENUM_DOWNLOAD,
-					      PK_STATUS_ENUM_DOWNLOAD_REPOSITORY,
-					      PK_STATUS_ENUM_DOWNLOAD_PACKAGELIST,
-					      PK_STATUS_ENUM_DOWNLOAD_FILELIST,
-					      PK_STATUS_ENUM_DOWNLOAD_CHANGELOG,
-					      PK_STATUS_ENUM_DOWNLOAD_GROUP,
-					      PK_STATUS_ENUM_DOWNLOAD_UPDATEINFO,
-					      PK_STATUS_ENUM_SCAN_APPLICATIONS,
-					      PK_STATUS_ENUM_GENERATE_PACKAGE_LIST,
-					      PK_STATUS_ENUM_QUERY,
-					      PK_STATUS_ENUM_INFO,
-					      PK_STATUS_ENUM_DEP_RESOLVE,
-					      PK_STATUS_ENUM_ROLLBACK,
-					      PK_STATUS_ENUM_TEST_COMMIT,
-					      PK_STATUS_ENUM_COMMIT,
-					      PK_STATUS_ENUM_REQUEST,
-					      PK_STATUS_ENUM_SIG_CHECK,
-					      PK_STATUS_ENUM_CLEANUP,
-					      PK_STATUS_ENUM_REPACKAGING,
-					      PK_STATUS_ENUM_WAIT,
-					      PK_STATUS_ENUM_WAITING_FOR_LOCK,
-					      PK_STATUS_ENUM_FINISHED, -1);
-
 	/* only set if in the list and not unknown */
 	if (value != PK_STATUS_ENUM_UNKNOWN && value != -1) {
-		icon = gpk_status_enum_to_icon_name (value);
-		gpk_smart_icon_set_icon_name (watch->priv->sicon, icon);
+		icon_name = gpk_status_enum_to_icon_name (value);
+		goto out;
+	}
+
+	/* any restart required? */
+	if (watch->priv->restart != PK_RESTART_ENUM_NONE) {
+		icon_name = gpk_restart_enum_to_icon_name (watch->priv->restart);
+		goto out;
 	}
 
+	/* do we have any cached messages to show? */
+	len = watch->priv->cached_messages->len;
+	if (len > 0) {
+		icon_name = "emblem-important";
+		goto out;
+	}
+
+out:
+	gpk_smart_icon_set_icon_name (watch->priv->sicon, icon_name);
 	return TRUE;
 }
 
@@ -299,11 +386,9 @@
 	GError *error = NULL;
 	gchar *text = NULL;
 	gchar *message = NULL;
-	GString *string;
+	NotifyNotification *notification;
 	PkPackageId *id;
-	const gchar *icon_name;
 	const GPtrArray	*array;
-	NotifyNotification *notification;
 
 	g_return_if_fail (GPK_IS_WATCH (watch));
 
@@ -323,27 +408,13 @@
 		restart = pk_client_get_require_restart (client);
 		if (restart > watch->priv->restart) {
 
-			/* get title */
-			string = g_string_new (gpk_restart_enum_to_localised_text (restart));
-			g_string_append_c (string, '\n');
-
 			/* list packages requiring this */
 			array = pk_client_get_require_restart_list (client);
 			for (i=0; i<array->len; i++) {
 				id = g_ptr_array_index (array, i);
-				/* TRANSLATORS: this is a package that required an update */
-				g_string_append_printf (string, "%s %s\n", _("Package:"), id->name);
+				g_ptr_array_add (watch->priv->restart_package_names, g_strdup (id->name));
 			}
 
-			/* remove final \n */
-			if (string->len > 0)
-				g_string_set_size (string, string->len - 1);
-
-			icon_name = gpk_restart_enum_to_icon_name (restart);
-			gtk_status_icon_set_tooltip (GTK_STATUS_ICON (watch->priv->sicon_action), string->str);
-			gpk_smart_icon_set_icon_name (watch->priv->sicon_action, icon_name);
-			g_string_free (string, TRUE);
-
 			/* save new restart */
 			watch->priv->restart = restart;
 		}
@@ -448,12 +519,12 @@
 		return;
 	}
 
-        /* are we accepting notifications */
-        value = gconf_client_get_bool (watch->priv->gconf_client, GPK_CONF_NOTIFY_ERROR, NULL);
-        if (!value) {
-                egg_debug ("not showing notification as prevented in gconf");
-                return;
-        }
+	/* are we accepting notifications */
+	value = gconf_client_get_bool (watch->priv->gconf_client, GPK_CONF_NOTIFY_ERROR, NULL);
+	if (!value) {
+		egg_debug ("not showing notification as prevented in gconf");
+		return;
+	}
 
 	/* we need to format this */
 	message = gpk_error_enum_to_localised_message (error_code);
@@ -489,32 +560,38 @@
 {
 	gboolean ret;
 	GError *error = NULL;
-	const gchar *title;
-	gchar *title_prefix;
-	const gchar *filename;
-	gchar *escaped_details;
 	gboolean value;
 	NotifyNotification *notification;
+	GpkWatchCachedMessage *cached_message;
 
 	g_return_if_fail (GPK_IS_WATCH (watch));
 
-        /* are we accepting notifications */
-        value = gconf_client_get_bool (watch->priv->gconf_client, GPK_CONF_NOTIFY_MESSAGE, NULL);
-        if (!value) {
-                egg_debug ("not showing notification as prevented in gconf");
-                return;
-        }
-
-	title = gpk_message_enum_to_localised_text (message);
-	/* TRANSLATORS: Prefix to the title shown in the libnotify popup */
-	title_prefix = g_strdup_printf ("%s: %s", _("Package Manager"), title);
-	filename = gpk_message_enum_to_icon_name (message);
+	/* add to list */
+	cached_message = g_new0 (GpkWatchCachedMessage, 1);
+	cached_message->type = message;
+	cached_message->tid = pk_client_get_tid (client);
+	cached_message->details = g_strdup (details);
+	g_ptr_array_add (watch->priv->cached_messages, cached_message);
+
+	/* close existing */
+	if (watch->priv->notification_cached_messages != NULL) {
+		ret = notify_notification_close (watch->priv->notification_cached_messages, &error);
+		if (!ret) {
+			egg_warning ("error: %s", error->message);
+			g_error_free (error);
+			error = NULL;
+		}
+	}
 
-	/* we need to format this */
-	escaped_details = g_markup_escape_text (details, -1);
+	/* are we accepting notifications */
+	value = gconf_client_get_bool (watch->priv->gconf_client, GPK_CONF_NOTIFY_MESSAGE, NULL);
+	if (!value) {
+		egg_debug ("not showing notification as prevented in gconf");
+		return;
+	}
 
 	/* do the bubble */
-	notification = notify_notification_new (title_prefix, escaped_details, "help-browser", NULL);
+	notification = notify_notification_new_with_status_icon (_("New package manager message"), NULL, "emblem-important", GTK_STATUS_ICON(watch->priv->sicon));
 	notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER);
 	notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
 	ret = notify_notification_show (notification, &error);
@@ -522,9 +599,7 @@
 		egg_warning ("error: %s", error->message);
 		g_error_free (error);
 	}
-
-	g_free (escaped_details);
-	g_free (title_prefix);
+	watch->priv->notification_cached_messages = notification;
 }
 
 /**
@@ -633,10 +708,7 @@
  * Display the popup menu.
  **/
 static void
-gpk_watch_popup_menu_cb (GtkStatusIcon *status_icon,
-			guint          button,
-			guint32        timestamp,
-			GpkWatch       *watch)
+gpk_watch_popup_menu_cb (GtkStatusIcon *status_icon, guint button, guint32 timestamp, GpkWatch *watch)
 {
 	GtkMenu *menu = (GtkMenu*) gtk_menu_new ();
 	GtkWidget *item;
@@ -672,10 +744,10 @@
 }
 
 /**
- * gpk_watch_refresh_cache_cb:
+ * gpk_watch_menu_refresh_cache_cb:
  **/
 static void
-gpk_watch_refresh_cache_cb (GtkMenuItem *item, gpointer data)
+gpk_watch_menu_refresh_cache_cb (GtkMenuItem *item, gpointer data)
 {
 	gboolean ret;
 	GpkWatch *watch = GPK_WATCH (data);
@@ -693,13 +765,100 @@
 }
 
 /**
- * pk_monitor_action_unref_cb:
+ * gpk_watch_menu_show_messages_cb:
  **/
 static void
-pk_monitor_action_unref_cb (GpkClient *gclient, GpkWatch *watch)
+gpk_watch_menu_show_messages_cb (GtkMenuItem *item, gpointer data)
 {
-	g_return_if_fail (GPK_IS_WATCH (watch));
-	g_object_unref (gclient);
+	GpkWatch *watch = GPK_WATCH (data);
+	GladeXML *glade_xml;
+	GtkWidget *main_window;
+	GtkWidget *widget;
+	GtkListStore *list_store;
+	GtkCellRenderer *renderer;
+	GtkTreeViewColumn *column;
+	GtkTreeIter iter;
+	GtkTreeModel *model;
+	guint i;
+	GpkWatchCachedMessage *cached_message;
+
+	glade_xml = glade_xml_new (GPK_DATA "/gpk-repo.glade", NULL, NULL);
+	main_window = glade_xml_get_widget (glade_xml, "dialog_repo");
+	gtk_window_set_icon_name (GTK_WINDOW (main_window), GPK_ICON_SOFTWARE_LOG);
+	gtk_window_set_title (GTK_WINDOW (main_window), _("Package Manager Messages"));
+
+	/* set a size, if the screen allows */
+	gpk_window_set_size_request (GTK_WINDOW(main_window), 500, 200);
+
+	/* Get the main window quit */
+	g_signal_connect_swapped (main_window, "delete_event", G_CALLBACK (gtk_main_quit), NULL);
+
+	widget = glade_xml_get_widget (glade_xml, "button_close");
+	g_signal_connect_swapped (widget, "clicked", G_CALLBACK (gtk_main_quit), NULL);
+	widget = glade_xml_get_widget (glade_xml, "button_help");
+	gtk_widget_hide (widget);
+
+	widget = glade_xml_get_widget (glade_xml, "checkbutton_detail");
+	gtk_widget_hide (widget);
+
+	/* create list stores */
+	list_store = gtk_list_store_new (GPK_WATCH_COLUMN_LAST, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+	/* create repo tree view */
+	widget = glade_xml_get_widget (glade_xml, "treeview_repo");
+	gtk_tree_view_set_model (GTK_TREE_VIEW (widget), GTK_TREE_MODEL (list_store));
+
+	/* column for text */
+	renderer = gtk_cell_renderer_text_new ();
+	/* TRANSLATORS: column for the message type */
+	column = gtk_tree_view_column_new_with_attributes (_("Message"), renderer,
+							   "markup", GPK_WATCH_COLUMN_TEXT, NULL);
+	gtk_tree_view_column_set_sort_column_id (column, GPK_WATCH_COLUMN_TEXT);
+	gtk_tree_view_append_column (GTK_TREE_VIEW(widget), column);
+
+	/* column for details */
+	renderer = gtk_cell_renderer_text_new ();
+	/* TRANSLATORS: column for the message description */
+	column = gtk_tree_view_column_new_with_attributes (_("Details"), renderer,
+							   "markup", GPK_WATCH_COLUMN_DETAILS, NULL);
+	gtk_tree_view_column_set_sort_column_id (column, GPK_WATCH_COLUMN_TEXT);
+	gtk_tree_view_append_column (GTK_TREE_VIEW(widget), column);
+
+	gtk_tree_view_columns_autosize (GTK_TREE_VIEW(widget));
+
+	/* add items to treeview */
+	model = gtk_tree_view_get_model (GTK_TREE_VIEW(widget));
+	for (i=0; i<watch->priv->cached_messages->len; i++) {
+		cached_message = g_ptr_array_index (watch->priv->cached_messages, i);
+		gtk_list_store_append (GTK_LIST_STORE(model), &iter);
+		gtk_list_store_set (list_store, &iter,
+				    GPK_WATCH_COLUMN_TEXT, gpk_message_enum_to_localised_text (cached_message->type),
+				    GPK_WATCH_COLUMN_TID, cached_message->tid,
+				    GPK_WATCH_COLUMN_DETAILS, cached_message->details,
+				    -1);
+	}
+
+	/* show window */
+	gtk_widget_show (main_window);
+
+	/* focus back to the close button */
+	widget = glade_xml_get_widget (glade_xml, "button_close");
+	gtk_widget_grab_focus (widget);
+
+	/* wait */
+	gtk_main ();
+
+	gtk_widget_hide (main_window);
+
+	g_ptr_array_foreach (watch->priv->cached_messages, (GFunc) gpk_watch_cached_message_free, NULL);
+	g_ptr_array_set_size (watch->priv->cached_messages, 0);
+
+	g_object_unref (glade_xml);
+	g_object_unref (list_store);
+
+	/* refresh UI */
+	gpk_watch_refresh_icon (watch);
+	gpk_watch_refresh_tooltip (watch);
 }
 
 /**
@@ -709,7 +868,6 @@
 gpk_watch_menu_job_status_cb (GtkMenuItem *item, GpkWatch *watch)
 {
 	gchar *tid;
-	GpkClient *gclient = NULL;
 
 	g_return_if_fail (GPK_IS_WATCH (watch));
 
@@ -721,16 +879,13 @@
 	}
 
 	/* launch the UI */
-	gclient = gpk_client_new ();
-	gpk_client_set_interaction (gclient, GPK_CLIENT_INTERACT_WARNING_PROGRESS);
-	g_signal_connect (gclient, "quit", G_CALLBACK (pk_monitor_action_unref_cb), watch);
-	gpk_client_monitor_tid (gclient, tid);
+	gpk_client_monitor_tid (watch->priv->monitor, tid);
 }
 
 /**
  * gpk_watch_populate_menu_with_jobs:
  **/
-static void
+static guint
 gpk_watch_populate_menu_with_jobs (GpkWatch *watch, GtkMenu *menu)
 {
 	guint i;
@@ -743,11 +898,11 @@
 	gchar *text;
 	guint length;
 
-	g_return_if_fail (GPK_IS_WATCH (watch));
+	g_return_val_if_fail (GPK_IS_WATCH (watch), 0);
 
 	length = pk_task_list_get_size (watch->priv->tlist);
 	if (length == 0)
-		return;
+		goto out;
 
 	/* do a menu item for each job */
 	for (i=0; i<length; i++) {
@@ -779,71 +934,26 @@
 		gtk_menu_shell_append (GTK_MENU_SHELL (menu), widget);
 		g_free (text);
 	}
+out:
+	return length;
 }
 
 /**
- * gpk_watch_activate_status_cb:
- * @button: Which buttons are pressed
- *
- * Callback when the icon is clicked
- **/
-static void
-gpk_watch_activate_status_cb (GtkStatusIcon *status_icon,
-			     GpkWatch       *watch)
-{
-	GtkMenu *menu = (GtkMenu*) gtk_menu_new ();
-	GtkWidget *widget;
-	GtkWidget *image;
-
-	g_return_if_fail (GPK_IS_WATCH (watch));
-
-	egg_debug ("icon left clicked");
-
-	/* add jobs as drop down */
-	gpk_watch_populate_menu_with_jobs (watch, menu);
-
-	/* force a refresh if we are not updating or refreshing */
-	if (watch->priv->show_refresh_in_menu) {
-
-		/* Separator for HIG? */
-		widget = gtk_separator_menu_item_new ();
-		gtk_menu_shell_append (GTK_MENU_SHELL (menu), widget);
-
-		/* TRANSLATORS: This is a right click menu item, and will refresh all the package lists */
-		widget = gtk_image_menu_item_new_with_mnemonic (_("_Refresh Software List"));
-		image = gtk_image_new_from_icon_name ("view-refresh", GTK_ICON_SIZE_MENU);
-		gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
-		g_signal_connect (G_OBJECT (widget), "activate",
-				  G_CALLBACK (gpk_watch_refresh_cache_cb), watch);
-		gtk_menu_shell_append (GTK_MENU_SHELL (menu), widget);
-	}
-
-	/* 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());
-}
-
-/**
- * gpk_watch_hide_restart_cb:
+ * gpk_watch_menu_hide_restart_cb:
  **/
 static void
-gpk_watch_hide_restart_cb (GtkMenuItem *item, gpointer data)
+gpk_watch_menu_hide_restart_cb (GtkMenuItem *item, gpointer data)
 {
 	GpkWatch *watch = GPK_WATCH (data);
-
 	g_return_if_fail (GPK_IS_WATCH (watch));
-
-	/* just hide it */
-	gpk_smart_icon_set_icon_name (watch->priv->sicon_action, NULL);
+	gpk_smart_icon_set_icon_name (watch->priv->sicon, NULL);
 }
 
 /**
- * gpk_watch_log_out_cb:
+ * gpk_watch_menu_log_out_cb:
  **/
 static void
-gpk_watch_log_out_cb (GtkMenuItem *item, gpointer data)
+gpk_watch_menu_log_out_cb (GtkMenuItem *item, gpointer data)
 {
 	GpkWatch *watch = GPK_WATCH (data);
 	g_return_if_fail (GPK_IS_WATCH (watch));
@@ -851,45 +961,86 @@
 }
 
 /**
- * gpk_watch_activate_status_restart_cb:
+ * gpk_watch_activate_status_cb:
  * @button: Which buttons are pressed
  *
  * Callback when the icon is clicked
  **/
 static void
-gpk_watch_activate_status_restart_cb (GtkStatusIcon *status_icon, GpkWatch *watch)
+gpk_watch_activate_status_cb (GtkStatusIcon *status_icon, GpkWatch *watch)
 {
 	GtkMenu *menu = (GtkMenu*) gtk_menu_new ();
 	GtkWidget *widget;
 	GtkWidget *image;
+	guint len;
+	gboolean show_hide = FALSE;
 
 	g_return_if_fail (GPK_IS_WATCH (watch));
 
 	egg_debug ("icon left clicked");
 
+	/* add jobs as drop down */
+	len = gpk_watch_populate_menu_with_jobs (watch, menu);
+
+	/* force a refresh if we are not updating or refreshing */
+	if (watch->priv->show_refresh_in_menu) {
+
+		/* Separator for HIG? */
+		if (len > 0) {
+			widget = gtk_separator_menu_item_new ();
+			gtk_menu_shell_append (GTK_MENU_SHELL (menu), widget);
+		}
+
+		/* TRANSLATORS: This is a right click menu item, and will refresh all the package lists */
+		widget = gtk_image_menu_item_new_with_mnemonic (_("_Refresh Software List"));
+		image = gtk_image_new_from_icon_name ("view-refresh", GTK_ICON_SIZE_MENU);
+		gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
+		g_signal_connect (G_OBJECT (widget), "activate",
+				  G_CALLBACK (gpk_watch_menu_refresh_cache_cb), watch);
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), widget);
+	}
+
+	/* any messages to show? */
+	len = watch->priv->cached_messages->len;
+	if (len > 0) {
+		/* TRANSLATORS: messages from the transaction */
+		widget = gtk_image_menu_item_new_with_mnemonic (_("_Show messages"));
+		image = gtk_image_new_from_icon_name ("edit-paste", GTK_ICON_SIZE_MENU);
+		gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
+		g_signal_connect (G_OBJECT (widget), "activate",
+				  G_CALLBACK (gpk_watch_menu_show_messages_cb), watch);
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), widget);
+		show_hide = TRUE;
+	}
+
 	/* log off session */
 	if (watch->priv->restart == PK_RESTART_ENUM_SESSION) {
 		widget = gtk_image_menu_item_new_with_mnemonic (_("_Log out"));
 		image = gtk_image_new_from_icon_name ("system-log-out", GTK_ICON_SIZE_MENU);
 		gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
 		g_signal_connect (G_OBJECT (widget), "activate",
-				  G_CALLBACK (gpk_watch_log_out_cb), watch);
+				  G_CALLBACK (gpk_watch_menu_log_out_cb), watch);
 		gtk_menu_shell_append (GTK_MENU_SHELL (menu), widget);
+		show_hide = TRUE;
 	}
 
 	/* restart computer */
 	if (watch->priv->restart == PK_RESTART_ENUM_SYSTEM) {
 		widget = gtk_action_create_menu_item (GTK_ACTION (watch->priv->restart_action));
 		gtk_menu_shell_append (GTK_MENU_SHELL (menu), widget);
+		show_hide = TRUE;
 	}
 
-	/* TRANSLATORS: This hides the 'restart required' icon */
-	widget = gtk_image_menu_item_new_with_mnemonic (_("_Hide this icon"));
-	image = gtk_image_new_from_icon_name ("dialog-information", GTK_ICON_SIZE_MENU);
-	gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
-	g_signal_connect (G_OBJECT (widget), "activate",
-			  G_CALLBACK (gpk_watch_hide_restart_cb), watch);
-	gtk_menu_shell_append (GTK_MENU_SHELL (menu), widget);
+	/* anything we're allowed to hide? */
+	if (show_hide) {
+		/* TRANSLATORS: This hides the 'restart required' icon */
+		widget = gtk_image_menu_item_new_with_mnemonic (_("_Hide this icon"));
+		image = gtk_image_new_from_icon_name ("dialog-information", GTK_ICON_SIZE_MENU);
+		gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
+		g_signal_connect (G_OBJECT (widget), "activate",
+				  G_CALLBACK (gpk_watch_menu_hide_restart_cb), watch);
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), widget);
+	}
 
 	/* show the menu */
 	gtk_widget_show_all (GTK_WIDGET (menu));
@@ -1121,19 +1272,20 @@
 
 	watch->priv = GPK_WATCH_GET_PRIVATE (watch);
 	watch->priv->error_details = NULL;
+	watch->priv->notification_cached_messages = NULL;
 	watch->priv->restart = PK_RESTART_ENUM_NONE;
 
 	watch->priv->show_refresh_in_menu = TRUE;
 	watch->priv->gconf_client = gconf_client_get_default ();
 
 	watch->priv->sicon = gpk_smart_icon_new ();
-	gpk_smart_icon_set_priority (watch->priv->sicon, 1);
-
-	watch->priv->sicon_action = gpk_smart_icon_new ();
-	gpk_smart_icon_set_priority (watch->priv->sicon_action, 3);
-
 	watch->priv->set_proxy_timeout = 0;
 	watch->priv->gclient = gpk_client_new ();
+	watch->priv->cached_messages = g_ptr_array_new ();
+	watch->priv->restart_package_names = g_ptr_array_new ();
+
+	watch->priv->monitor = gpk_client_new ();
+	gpk_client_set_interaction (watch->priv->monitor, GPK_CLIENT_INTERACT_WARNING_PROGRESS);
 
 	/* we need to get ::locked */
 	watch->priv->control = pk_control_new ();
@@ -1150,11 +1302,6 @@
 	g_signal_connect_object (G_OBJECT (status_icon),
 				 "activate", G_CALLBACK (gpk_watch_activate_status_cb), watch, 0);
 
-	/* provide the user with a way to restart */
-	status_icon = GTK_STATUS_ICON (watch->priv->sicon_action);
-	g_signal_connect_object (G_OBJECT (status_icon),
-				 "activate", G_CALLBACK (gpk_watch_activate_status_restart_cb), watch, 0);
-
 	watch->priv->tlist = pk_task_list_new ();
 	g_signal_connect (watch->priv->tlist, "changed",
 			  G_CALLBACK (gpk_watch_task_list_changed_cb), watch);
@@ -1223,6 +1370,14 @@
 	if (watch->priv->set_proxy_timeout != 0)
 		g_source_remove (watch->priv->set_proxy_timeout);
 
+	/* free cached messages */
+	g_ptr_array_foreach (watch->priv->cached_messages, (GFunc) gpk_watch_cached_message_free, NULL);
+	g_ptr_array_free (watch->priv->cached_messages, TRUE);
+
+	/* free cached restart names */
+	g_ptr_array_foreach (watch->priv->restart_package_names, (GFunc) g_free, NULL);
+	g_ptr_array_free (watch->priv->restart_package_names, TRUE);
+
 	g_free (watch->priv->error_details);
 	g_object_unref (watch->priv->sicon);
 	g_object_unref (watch->priv->inhibit);
@@ -1232,6 +1387,7 @@
 	g_object_unref (watch->priv->pconnection);
 	g_object_unref (watch->priv->gconf_client);
 	g_object_unref (watch->priv->restart_action);
+	g_object_unref (watch->priv->monitor);
 
 	G_OBJECT_CLASS (gpk_watch_parent_class)->finalize (object);
 }



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