gnome-packagekit r198 - trunk/src



Author: rhughes
Date: Wed May  7 23:16:04 2008
New Revision: 198
URL: http://svn.gnome.org/viewvc/gnome-packagekit?rev=198&view=rev

Log:
from git

Added:
   trunk/src/gpk-client-chooser.c
   trunk/src/gpk-client-chooser.h
   trunk/src/gpk-client-depends.c
   trunk/src/gpk-client-depends.h
   trunk/src/gpk-client-requires.c
   trunk/src/gpk-client-requires.h
   trunk/src/gpk-client-resolve.c
   trunk/src/gpk-client-resolve.h
   trunk/src/gpk-dbus.c
   trunk/src/gpk-dbus.h
   trunk/src/gpk-install-mime-type.c
   trunk/src/gpk-interface.h
Removed:
   trunk/src/gpk-progress.c
   trunk/src/gpk-progress.h
Modified:
   trunk/src/.gitignore
   trunk/src/Makefile.am
   trunk/src/gpk-application.c
   trunk/src/gpk-backend-status.c
   trunk/src/gpk-client-untrusted.c
   trunk/src/gpk-client.c
   trunk/src/gpk-client.h
   trunk/src/gpk-common.c
   trunk/src/gpk-common.h
   trunk/src/gpk-install-local-file.c
   trunk/src/gpk-install-package-name.c
   trunk/src/gpk-interface.xml
   trunk/src/gpk-log.c
   trunk/src/gpk-prefs.c
   trunk/src/gpk-update-viewer.c
   trunk/src/gpk-watch.c

Modified: trunk/src/.gitignore
==============================================================================
--- trunk/src/.gitignore	(original)
+++ trunk/src/.gitignore	Wed May  7 23:16:04 2008
@@ -18,6 +18,7 @@
 gpk-update-icon
 gpk-install-local-file
 gpk-install-package-name
+gpk-install-mime-type
 gpk-install-provide-file
 gpk-prefs
 gpk-update-viewer

Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am	(original)
+++ trunk/src/Makefile.am	Wed May  7 23:16:04 2008
@@ -34,6 +34,7 @@
 	gpk-repo					\
 	gpk-prefs					\
 	gpk-install-local-file				\
+	gpk-install-mime-type				\
 	gpk-install-provide-file			\
 	gpk-install-package-name			\
 	gpk-update-icon					\
@@ -51,10 +52,18 @@
 	gpk-client.h					\
 	gpk-client-eula.c				\
 	gpk-client-eula.h				\
+	gpk-client-resolve.c				\
+	gpk-client-resolve.h				\
+	gpk-client-depends.c				\
+	gpk-client-depends.h				\
+	gpk-client-requires.c				\
+	gpk-client-requires.h				\
 	gpk-client-signature.c				\
 	gpk-client-signature.h				\
 	gpk-client-untrusted.c				\
 	gpk-client-untrusted.h				\
+	gpk-client-chooser.c				\
+	gpk-client-chooser.h				\
 	gpk-smart-icon.c				\
 	gpk-smart-icon.h				\
 	gpk-gnome.c					\
@@ -94,6 +103,15 @@
 	$(shared_LIBS)					\
 	$(NULL)
 
+gpk_install_mime_type_SOURCES =				\
+	gpk-install-mime-type.c				\
+	$(shared_SOURCES)				\
+	$(NULL)
+
+gpk_install_mime_type_LDADD =				\
+	$(shared_LIBS)					\
+	$(NULL)
+
 gpk_install_package_name_SOURCES =			\
 	gpk-install-package-name.c			\
 	$(shared_SOURCES)				\
@@ -117,8 +135,6 @@
 	gpk-inhibit.h					\
 	gpk-dbus.c					\
 	gpk-dbus.h					\
-	gpk-progress.c					\
-	gpk-progress.h					\
 	$(shared_SOURCES)				\
 	$(NULL)
 
@@ -233,6 +249,7 @@
 
 gpk_self_test_LDADD =						\
 	$(shared_LIBS)						\
+	$(SELFTEST_LIBS)					\
 	$(NULL)
 
 gpk_self_test_CPPFLAGS = -DPK_BUILD_TESTS

Modified: trunk/src/gpk-application.c
==============================================================================
--- trunk/src/gpk-application.c	(original)
+++ trunk/src/gpk-application.c	Wed May  7 23:16:04 2008
@@ -229,11 +229,14 @@
 gpk_application_install (GpkApplication *application, const gchar *package_id)
 {
 	gboolean ret;
+	gchar **package_ids = NULL;
 	g_return_val_if_fail (PK_IS_APPLICATION (application), FALSE);
 	g_return_val_if_fail (package_id != NULL, FALSE);
 
 	pk_debug ("install %s", application->priv->package);
-	ret = gpk_client_install_package_id (application->priv->gclient, package_id, NULL);
+	package_ids = g_strsplit (package_id, "|", 1);
+	ret = gpk_client_install_package_ids (application->priv->gclient, package_ids, NULL);
+	g_strfreev (package_ids);
 
 	/* refresh the search as the items may have changed and the filter has not changed */
 	if (ret) {
@@ -277,9 +280,12 @@
 gpk_application_remove_cb (PolKitGnomeAction *action, GpkApplication *application)
 {
 	gboolean ret;
+	gchar **package_ids = NULL;
 	g_return_if_fail (PK_IS_APPLICATION (application));
 
-	ret = gpk_client_remove_package_id (application->priv->gclient, application->priv->package, NULL);
+	package_ids = g_strsplit (application->priv->package, "|", 1);
+	ret = gpk_client_remove_package_ids (application->priv->gclient, package_ids, NULL);
+	g_strfreev (package_ids);
 
 	/* refresh the search as the items may have changed and the filter has not changed */
 	if (ret) {
@@ -651,8 +657,8 @@
 	gpk_statusbar_hide (application->priv->statusbar);
 
 	/* do we need to update the search? */
-	if (role == PK_ROLE_ENUM_INSTALL_PACKAGE ||
-	    role == PK_ROLE_ENUM_REMOVE_PACKAGE) {
+	if (role == PK_ROLE_ENUM_INSTALL_PACKAGES ||
+	    role == PK_ROLE_ENUM_REMOVE_PACKAGES) {
 		widget = glade_xml_get_widget (application->priv->glade_xml, "button_cancel2");
 		gtk_widget_hide (widget);
 		/* refresh the search as the items may have changed and the filter has not changed */
@@ -1195,13 +1201,13 @@
 		pk_debug ("selected row is: %i %s", installed, application->priv->package);
 
 		if (installed == FALSE &&
-		    pk_enums_contain (application->priv->roles, PK_ROLE_ENUM_INSTALL_PACKAGE)) {
+		    pk_enums_contain (application->priv->roles, PK_ROLE_ENUM_INSTALL_PACKAGES)) {
 			polkit_gnome_action_set_visible (application->priv->install_action, TRUE);
 		} else {
 			polkit_gnome_action_set_visible (application->priv->install_action, FALSE);
 		}
 		if (installed &&
-		    pk_enums_contain (application->priv->roles, PK_ROLE_ENUM_REMOVE_PACKAGE)) {
+		    pk_enums_contain (application->priv->roles, PK_ROLE_ENUM_REMOVE_PACKAGES)) {
 			polkit_gnome_action_set_visible (application->priv->remove_action, TRUE);
 		} else {
 			polkit_gnome_action_set_visible (application->priv->remove_action, FALSE);

Modified: trunk/src/gpk-backend-status.c
==============================================================================
--- trunk/src/gpk-backend-status.c	(original)
+++ trunk/src/gpk-backend-status.c	Wed May  7 23:16:04 2008
@@ -190,15 +190,15 @@
 		widget = glade_xml_get_widget (glade_xml, "image_refresh_cache");
 		gtk_image_set_from_icon_name (GTK_IMAGE (widget), "gtk-apply", GTK_ICON_SIZE_MENU);
 	}
-	if (pk_enums_contain (roles, PK_ROLE_ENUM_REMOVE_PACKAGE)) {
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_REMOVE_PACKAGES)) {
 		widget = glade_xml_get_widget (glade_xml, "image_package_remove");
 		gtk_image_set_from_icon_name (GTK_IMAGE (widget), "gtk-apply", GTK_ICON_SIZE_MENU);
 	}
-	if (pk_enums_contain (roles, PK_ROLE_ENUM_INSTALL_PACKAGE)) {
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_INSTALL_PACKAGES)) {
 		widget = glade_xml_get_widget (glade_xml, "image_package_install");
 		gtk_image_set_from_icon_name (GTK_IMAGE (widget), "gtk-apply", GTK_ICON_SIZE_MENU);
 	}
-	if (pk_enums_contain (roles, PK_ROLE_ENUM_INSTALL_FILE)) {
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_INSTALL_FILES)) {
 		widget = glade_xml_get_widget (glade_xml, "image_file_install");
 		gtk_image_set_from_icon_name (GTK_IMAGE (widget), "gtk-apply", GTK_ICON_SIZE_MENU);
 	}

Added: trunk/src/gpk-client-chooser.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-client-chooser.c	Wed May  7 23:16:04 2008
@@ -0,0 +1,278 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <polkit-gnome/polkit-gnome.h>
+
+#include <pk-debug.h>
+#include <pk-common.h>
+#include <pk-client.h>
+#include <pk-enum.h>
+#include <pk-package-id.h>
+#include "gpk-gnome.h"
+#include "gpk-common.h"
+
+static GtkListStore *list_store = NULL;
+static gchar *package_id = NULL;
+static PolKitGnomeAction *button_action = NULL;
+
+enum
+{
+	GPK_CHOOSER_COLUMN_ICON,
+	GPK_CHOOSER_COLUMN_TEXT,
+	GPK_CHOOSER_COLUMN_ID,
+	GPK_CHOOSER_COLUMN_LAST
+};
+
+/**
+ * gpk_client_chooser_button_help_cb:
+ **/
+static void
+gpk_client_chooser_button_help_cb (GtkWidget *widget, gpointer data)
+{
+	gpk_gnome_help ("mime-types");
+}
+
+/**
+ * gpk_client_chooser_button_close_cb:
+ **/
+static void
+gpk_client_chooser_button_close_cb (GtkWidget *widget, gpointer data)
+{
+	/* clear package_id */
+	g_free (package_id);
+	package_id = NULL;
+	gtk_main_quit ();
+}
+
+/**
+ * gpk_client_chooser_button_action_cb:
+ **/
+static void
+gpk_client_chooser_button_action_cb (PolKitGnomeAction *action, gpointer data)
+{
+	gtk_main_quit ();
+}
+
+/**
+ * gpk_client_chooser_treeview_clicked_cb:
+ **/
+static void
+gpk_client_chooser_treeview_clicked_cb (GtkTreeSelection *selection, gboolean data)
+{
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+
+	/* This will only work in single or browse selection mode! */
+	if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+		g_free (package_id);
+		gtk_tree_model_get (model, &iter, GPK_CHOOSER_COLUMN_ID, &package_id, -1);
+
+		/* show package_id */
+		pk_debug ("selected row is: %s", package_id);
+	} else {
+		pk_debug ("no row selected");
+	}
+}
+
+/**
+ * gpk_update_viewer_create_custom_widget:
+ **/
+static GtkWidget *
+gpk_update_viewer_create_custom_widget (GladeXML *xml, gchar *func_name, gchar *name,
+				        gchar *string1, gchar *string2,
+				        gint int1, gint int2, gpointer user_data)
+{
+	if (pk_strequal (name, "button_action")) {
+		return polkit_gnome_action_create_button (button_action);
+	}
+	pk_warning ("name unknown=%s", name);
+	return NULL;
+}
+
+/**
+ * pk_treeview_add_general_columns:
+ **/
+static void
+pk_treeview_add_general_columns (GtkTreeView *treeview)
+{
+	GtkCellRenderer *renderer;
+	GtkTreeViewColumn *column;
+
+	/* image */
+	renderer = gtk_cell_renderer_pixbuf_new ();
+        g_object_set (renderer, "stock-size", GTK_ICON_SIZE_DIALOG, NULL);
+	column = gtk_tree_view_column_new_with_attributes (_("Icon"), renderer,
+							   "icon-name", GPK_CHOOSER_COLUMN_ICON, NULL);
+	gtk_tree_view_append_column (treeview, column);
+
+	/* column for text */
+	renderer = gtk_cell_renderer_text_new ();
+	column = gtk_tree_view_column_new_with_attributes (_("Package"), renderer,
+							   "markup", GPK_CHOOSER_COLUMN_TEXT, NULL);
+	gtk_tree_view_column_set_sort_column_id (column, GPK_CHOOSER_COLUMN_TEXT);
+	gtk_tree_view_append_column (treeview, column);
+	gtk_tree_view_column_set_expand (column, TRUE);
+}
+
+/**
+ * gpk_update_viewer_setup_policykit:
+ *
+ * We have to do this before the glade stuff if done as the custom handler needs the actions setup
+ **/
+static void
+gpk_update_viewer_setup_policykit (void)
+{
+	PolKitAction *pk_action;
+	pk_action = polkit_action_new ();
+	polkit_action_set_action_id (pk_action, "org.freedesktop.packagekit.install");
+	button_action = polkit_gnome_action_new_default ("install", pk_action, _("_Install"), NULL);
+	g_object_set (button_action,
+		      "no-icon-name", GTK_STOCK_FLOPPY,
+		      "auth-icon-name", GTK_STOCK_FLOPPY,
+		      "yes-icon-name", GTK_STOCK_FLOPPY,
+		      "self-blocked-icon-name", GTK_STOCK_FLOPPY,
+		      NULL);
+	polkit_action_unref (pk_action);
+}
+
+/**
+ * gpk_client_chooser_show:
+ *
+ * Return value: the package_id of the selected package, or NULL
+ **/
+gchar *
+gpk_client_chooser_show (PkClient *results, PkRoleEnum role, const gchar *title)
+{
+	GladeXML *glade_xml;
+	GtkWidget *widget;
+	GtkTreeSelection *selection;
+	PkPackageItem *item;
+	GtkTreeIter iter;
+	const gchar *icon_name;
+	gchar *text;
+	guint len;
+	guint i;
+
+	g_return_val_if_fail (results != NULL, FALSE);
+	g_return_val_if_fail (title != NULL, FALSE);
+
+	/* we have to do this before we connect up the glade file */
+	gpk_update_viewer_setup_policykit ();
+
+	/* use custom widgets */
+	glade_set_custom_handler (gpk_update_viewer_create_custom_widget, NULL);
+
+	glade_xml = glade_xml_new (PK_DATA "/gpk-log.glade", NULL, NULL);
+
+	/* connect up default actions */
+	widget = glade_xml_get_widget (glade_xml, "window_simple");
+	g_signal_connect_swapped (widget, "delete_event", G_CALLBACK (gtk_main_quit), NULL);
+	gtk_widget_set_size_request (widget, 600, 300);
+
+	/* connect up buttons */
+	widget = glade_xml_get_widget (glade_xml, "button_help");
+	g_signal_connect (widget, "clicked", G_CALLBACK (gpk_client_chooser_button_help_cb), NULL);
+	widget = glade_xml_get_widget (glade_xml, "button_close");
+	g_signal_connect (widget, "clicked", G_CALLBACK (gpk_client_chooser_button_close_cb), NULL);
+
+	/* set icon name */
+	widget = glade_xml_get_widget (glade_xml, "window_simple");
+	gtk_window_set_icon_name (GTK_WINDOW (widget), "system-software-installer");
+	gtk_window_set_title (GTK_WINDOW (widget), title);
+
+	/* connect up PolicyKit actions */
+	g_signal_connect (button_action, "activate", G_CALLBACK (gpk_client_chooser_button_action_cb), NULL);
+
+	/* create list stores */
+	list_store = gtk_list_store_new (GPK_CHOOSER_COLUMN_LAST, G_TYPE_STRING,
+						 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+	/* create package_id tree view */
+	widget = glade_xml_get_widget (glade_xml, "treeview_simple");
+	gtk_tree_view_set_model (GTK_TREE_VIEW (widget),
+				 GTK_TREE_MODEL (list_store));
+
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+	g_signal_connect (selection, "changed",
+			  G_CALLBACK (gpk_client_chooser_treeview_clicked_cb), NULL);
+
+	/* add columns to the tree view */
+	pk_treeview_add_general_columns (GTK_TREE_VIEW (widget));
+	gtk_tree_view_columns_autosize (GTK_TREE_VIEW (widget));
+
+	/* see what we've got already */
+	len = pk_client_package_buffer_get_size	(results);
+	for (i=0; i<len; i++) {
+		item = pk_client_package_buffer_get_item (results, i);
+		pk_debug ("package '%s' got:", item->package_id);
+
+		/* put formatted text into treeview */
+		gtk_list_store_append (list_store, &iter);
+		text = gpk_package_id_format_twoline (item->package_id, item->summary);
+		icon_name = gpk_info_enum_to_icon_name (PK_INFO_ENUM_AVAILABLE);
+		gtk_list_store_set (list_store, &iter,
+				    GPK_CHOOSER_COLUMN_TEXT, text,
+				    GPK_CHOOSER_COLUMN_ID, item->package_id, -1);
+		gtk_list_store_set (list_store, &iter, GPK_CHOOSER_COLUMN_ICON, icon_name, -1);
+		g_free (text);
+	}
+
+	/* show window */
+	widget = glade_xml_get_widget (glade_xml, "window_simple");
+	gtk_widget_show (widget);
+
+	/* wait for button press */
+	gtk_main ();
+
+	/* hide window */
+	if (GTK_IS_WIDGET (widget)) {
+		gtk_widget_hide (widget);
+	}
+	g_object_unref (glade_xml);
+
+	return package_id;
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef PK_BUILD_TESTS
+#include <libselftest.h>
+
+void
+gpk_client_chooser_self_test (gpointer data)
+{
+	LibSelfTest *test = (LibSelfTest *) data;
+
+	if (libst_start (test, "GpkClientEula", CLASS_AUTO) == FALSE) {
+		return;
+	}
+	libst_end (test);
+}
+#endif
+

Added: trunk/src/gpk-client-chooser.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-client-chooser.h	Wed May  7 23:16:04 2008
@@ -0,0 +1,37 @@
+/* -*- 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_CLIENT_CHOOSER_H
+#define __GPK_CLIENT_CHOOSER_H
+
+#include <glib-object.h>
+#include <pk-enum.h>
+
+G_BEGIN_DECLS
+
+void		 gpk_client_chooser_self_test		(gpointer	 data);
+gchar		*gpk_client_chooser_show		(PkClient	*results,
+							 PkRoleEnum	 role,
+							 const gchar	*title);
+
+G_END_DECLS
+
+#endif	/* __GPK_CLIENT_CHOOSER_H */

Added: trunk/src/gpk-client-depends.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-client-depends.c	Wed May  7 23:16:04 2008
@@ -0,0 +1,207 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <gconf/gconf-client.h>
+
+#include <pk-debug.h>
+#include <pk-client.h>
+#include <pk-package-id.h>
+#include <pk-package-list.h>
+#include "gpk-gnome.h"
+#include "gpk-error.h"
+#include "gpk-common.h"
+
+static PkClient *client = NULL;
+static GConfClient *gconf_client = NULL;
+
+/**
+ * gpk_client_checkbutton_show_depends_cb:
+ **/
+static void
+gpk_client_checkbutton_show_depends_cb (GtkWidget *widget, gpointer data)
+{
+	gboolean checked;
+	/* set the policy */
+	checked = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+	pk_debug ("Changing %s to %i", GPK_CONF_SHOW_DEPENDS, checked);
+	gconf_client_set_bool (gconf_client, GPK_CONF_SHOW_DEPENDS, checked, NULL);
+}
+
+static gboolean
+gpk_client_depends_indervidual (PkPackageList *list, const gchar *package_id)
+{
+	GError *error = NULL;
+	PkPackageItem *item;
+	gboolean ret;
+	guint len;
+	guint i;
+
+	/* reset */
+	ret = pk_client_reset (client, &error);
+	if (!ret) {
+		gpk_error_dialog (_("Failed to reset client"), NULL, error->message);
+		g_error_free (error);
+		return FALSE;
+	}
+
+	/* find out if this would drag in other packages */
+	ret = pk_client_get_depends (client, PK_FILTER_ENUM_NOT_INSTALLED, package_id, TRUE, &error);
+	if (!ret) {
+		gpk_error_dialog (_("Failed to get depends"),
+				  _("Could not work out what packages would be also installed"),
+				  error->message);
+		g_error_free (error);
+		return FALSE;
+	}
+
+	/* no additional packages? */
+	len = pk_client_package_buffer_get_size	(client);
+	if (len == 0) {
+		pk_debug ("no additional deps");
+		return TRUE;
+	}
+
+	/* process package list */
+	for (i=0; i<len; i++) {
+		item = pk_client_package_buffer_get_item (client, i);
+		pk_package_list_add (list, item->info, item->package_id, item->summary);
+	}
+	return TRUE;
+}
+
+/**
+ * gpk_client_depends_show:
+ *
+ * Return value: if we agreed to remove the deps
+ **/
+gboolean
+gpk_client_depends_show (gchar **package_ids)
+{
+	GtkWidget *widget;
+	GtkWidget *dialog;
+	GtkResponseType button;
+	PkPackageList *list;
+	gboolean ret;
+	guint length;
+	guint i;
+	GString *string;
+	PkPackageItem *item;
+	gchar *text;
+
+	list = pk_package_list_new ();
+	gconf_client = gconf_client_get_default ();
+
+	client = pk_client_new ();
+	pk_client_set_use_buffer (client, TRUE, NULL);
+	pk_client_set_synchronous (client, TRUE, NULL);
+
+	/* have we previously said we don't want to be shown the confirmation */
+	ret = gconf_client_get_bool (gconf_client, GPK_CONF_SHOW_DEPENDS, NULL);
+	if (!ret) {
+		pk_debug ("we've said we don't want the dep dialog");
+		ret = TRUE;
+		goto out;
+	}
+
+	length = g_strv_length (package_ids);
+	for (i=0; i<length; i++) {
+		ret = gpk_client_depends_indervidual (list, package_ids[i]);
+		if (!ret) {
+			ret = FALSE;
+			goto out;
+		}
+	}
+
+	/* process package list */
+	string = g_string_new (_("The following packages also have to be downloaded:"));
+	g_string_append (string, "\n\n");
+	length = pk_package_list_get_size (list);
+	/* shortcut */
+	if (length == 0) {
+		goto out;
+	}
+	for (i=0; i<length; i++) {
+		item = pk_package_list_get_item (list, i);
+		text = gpk_package_id_format_oneline (item->package_id, item->summary);
+		g_string_append_printf (string, "%s\n", text);
+		g_free (text);
+	}
+	/* remove last \n */
+	g_string_set_size (string, string->len - 1);
+
+	/* display messagebox  */
+	text = g_string_free (string, FALSE);
+
+	/* show UI */
+	dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
+					 GTK_MESSAGE_QUESTION, GTK_BUTTONS_CANCEL,
+					 "%s", _("Install additional packages?"));
+	/* add a specialist button */
+	gtk_dialog_add_button (GTK_DIALOG (dialog), _("Install"), GTK_RESPONSE_OK);
+
+	/* add a checkbutton for deps screen */
+	widget = gtk_check_button_new_with_label (_("Do not show me this again"));
+	g_signal_connect (widget, "clicked", G_CALLBACK (gpk_client_checkbutton_show_depends_cb), NULL);
+	gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), widget);
+	gtk_widget_show (widget);
+
+	gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", text);
+	button = gtk_dialog_run (GTK_DIALOG (dialog));
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+	g_free (text);
+
+	/* did we click no or exit the window? */
+	if (button != GTK_RESPONSE_OK) {
+		ret = FALSE;
+	}
+
+out:
+	g_object_unref (list);
+	g_object_unref (client);
+	g_object_unref (gconf_client);
+	return ret;
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef PK_BUILD_TESTS
+#include <libselftest.h>
+
+void
+gpk_client_depends_self_test (gpointer data)
+{
+	LibSelfTest *test = (LibSelfTest *) data;
+
+	if (libst_start (test, "GpkClientDepends", CLASS_AUTO) == FALSE) {
+		return;
+	}
+	libst_end (test);
+}
+#endif
+

Added: trunk/src/gpk-client-depends.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-client-depends.h	Wed May  7 23:16:04 2008
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_CLIENT_DEPENDS_H
+#define __GPK_CLIENT_DEPENDS_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+void		 gpk_client_depends_self_test		(gpointer	 data);
+gboolean	 gpk_client_depends_show		(gchar		**package_ids);
+
+G_END_DECLS
+
+#endif	/* __GPK_CLIENT_DEPENDS_H */

Added: trunk/src/gpk-client-requires.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-client-requires.c	Wed May  7 23:16:04 2008
@@ -0,0 +1,180 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+
+#include <pk-debug.h>
+#include <pk-client.h>
+#include <pk-package-id.h>
+#include <pk-package-list.h>
+#include "gpk-gnome.h"
+#include "gpk-error.h"
+#include "gpk-common.h"
+
+static PkClient *client = NULL;
+
+static gboolean
+gpk_client_requires_indervidual (PkPackageList *list, const gchar *package_id)
+{
+	GError *error = NULL;
+	PkPackageItem *item;
+	gboolean ret;
+	guint len;
+	guint i;
+
+	/* reset */
+	ret = pk_client_reset (client, &error);
+	if (!ret) {
+		gpk_error_dialog (_("Failed to reset client"), NULL, error->message);
+		g_error_free (error);
+		return FALSE;
+	}
+
+	/* find out if this would force removal of other packages */
+	ret = pk_client_get_requires (client, PK_FILTER_ENUM_INSTALLED, package_id, TRUE, &error);
+	if (!ret) {
+		gpk_error_dialog (_("Failed to get requires"),
+				  _("Could not work out what packages would also be removed"),
+				  error->message);
+		g_error_free (error);
+		return FALSE;
+	}
+
+	/* no additional packages? */
+	len = pk_client_package_buffer_get_size	(client);
+	if (len == 0) {
+		pk_debug ("no requires");
+		return TRUE;
+	}
+
+	/* process package list */
+	for (i=0; i<len; i++) {
+		item = pk_client_package_buffer_get_item (client, i);
+		pk_package_list_add (list, item->info, item->package_id, item->summary);
+	}
+	return TRUE;
+}
+
+/**
+ * gpk_client_requires_show:
+ *
+ * Return value: if we agreed to remove the deps
+ **/
+gboolean
+gpk_client_requires_show (gchar **package_ids)
+{
+	GtkWidget *dialog;
+	GtkResponseType button;
+	PkPackageList *list;
+	gboolean ret;
+	guint length;
+	guint i;
+	GString *string;
+	PkPackageItem *item;
+	gchar *text;
+
+	list = pk_package_list_new ();
+
+	client = pk_client_new ();
+	pk_client_set_use_buffer (client, TRUE, NULL);
+	pk_client_set_synchronous (client, TRUE, NULL);
+
+	length = g_strv_length (package_ids);
+	for (i=0; i<length; i++) {
+		ret = gpk_client_requires_indervidual (list, package_ids[i]);
+		if (!ret) {
+			ret = FALSE;
+			goto out;
+		}
+	}
+
+	/* process package list */
+	string = g_string_new (_("The following packages have to be removed:"));
+	g_string_append (string, "\n\n");
+	length = pk_package_list_get_size (list);
+	/* shortcut */
+	if (length == 0) {
+		goto out;
+	}
+	for (i=0; i<length; i++) {
+		item = pk_package_list_get_item (list, i);
+		text = gpk_package_id_format_oneline (item->package_id, item->summary);
+		g_string_append_printf (string, "%s\n", text);
+		g_free (text);
+	}
+	/* remove last \n */
+	g_string_set_size (string, string->len - 1);
+
+	/* display messagebox  */
+	text = g_string_free (string, FALSE);
+
+	/* show UI */
+	if (g_strv_length (package_ids) == 1) {
+		text = g_strdup_printf (_("%i other packages depends on %s"), length, package_ids[0]);
+	} else {
+		text = g_strdup_printf (_("%i other packages depends on these packages"), length);
+	}
+	dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
+					 GTK_MESSAGE_QUESTION, GTK_BUTTONS_CANCEL, "%s", text);
+	g_free (text);
+	/* add a specialist button */
+	gtk_dialog_add_button (GTK_DIALOG (dialog), _("Remove all packages"), GTK_RESPONSE_OK);
+
+	gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", text);
+	button = gtk_dialog_run (GTK_DIALOG (dialog));
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+	g_free (text);
+
+	/* did we click no or exit the window? */
+	if (button != GTK_RESPONSE_OK) {
+		ret = FALSE;
+	}
+
+out:
+	g_object_unref (list);
+	g_object_unref (client);
+	return ret;
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef PK_BUILD_TESTS
+#include <libselftest.h>
+
+void
+gpk_client_requires_self_test (gpointer data)
+{
+	LibSelfTest *test = (LibSelfTest *) data;
+
+	if (libst_start (test, "GpkClientDepends", CLASS_AUTO) == FALSE) {
+		return;
+	}
+	libst_end (test);
+}
+#endif
+

Added: trunk/src/gpk-client-requires.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-client-requires.h	Wed May  7 23:16:04 2008
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_CLIENT_REQUIRES_H
+#define __GPK_CLIENT_REQUIRES_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+void		 gpk_client_requires_self_test		(gpointer	 data);
+gboolean	 gpk_client_requires_show		(gchar		**package_ids);
+
+G_END_DECLS
+
+#endif	/* __GPK_CLIENT_REQUIRES_H */

Added: trunk/src/gpk-client-resolve.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-client-resolve.c	Wed May  7 23:16:04 2008
@@ -0,0 +1,164 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+
+#include <pk-debug.h>
+#include <pk-client.h>
+#include <pk-common.h>
+#include <pk-package-id.h>
+#include "gpk-gnome.h"
+#include "gpk-error.h"
+#include "gpk-common.h"
+
+static PkClient *client = NULL;
+
+static gchar *
+gpk_client_resolve_indervidual (const gchar *package)
+{
+	GError *error = NULL;
+	PkPackageItem *item;
+	gchar *package_id = NULL;
+	gboolean already_installed = FALSE;
+	gboolean ret;
+	gchar *title;
+	guint len;
+	guint i;
+
+	/* reset */
+	ret = pk_client_reset (client, &error);
+	if (!ret) {
+		gpk_error_dialog (_("Failed to reset client"), NULL, error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* find out if we can find a package */
+	ret = pk_client_resolve (client, PK_FILTER_ENUM_NONE, package, &error);
+	if (!ret) {
+		gpk_error_dialog (_("Failed to resolve package"),
+				  _("Incorrect response from search"),
+				  error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* found nothing? */
+	len = pk_client_package_buffer_get_size	(client);
+	if (len == 0) {
+		title = g_strdup_printf (_("Could not find %s"), package);
+		gpk_error_dialog (title, _("The package could not be found in any software sources"), NULL);
+		g_free (title);
+		goto out;
+	}
+
+	/* see what we've got already */
+	for (i=0; i<len; i++) {
+		item = pk_client_package_buffer_get_item (client, i);
+		if (item->info == PK_INFO_ENUM_INSTALLED) {
+			already_installed = TRUE;
+		} else if (item->info == PK_INFO_ENUM_AVAILABLE) {
+			pk_debug ("package '%s' resolved", item->package_id);
+			//TODO: we need to list these in a gpk-client-chooser
+			if (package_id != NULL) {
+				pk_warning ("throwing away %s", package_id);
+				g_free (package_id);
+			}
+			package_id = g_strdup (item->package_id);
+		}
+	}
+
+	/* already installed? */
+	if (already_installed) {
+		title = g_strdup_printf (_("Failed to install %s"), package);
+		gpk_error_dialog (title, _("The package is already installed"), NULL);
+		g_free (title);
+		goto out;
+	}
+
+	/* got junk? */
+	if (package_id == NULL) {
+		gpk_error_dialog (_("Failed to find package"), _("Incorrect response from search"), NULL);
+		goto out;
+	}
+out:
+	return package_id;
+}
+
+/**
+ * gpk_client_resolve_show:
+ *
+ * Return value: if we agreed to remove the deps
+ **/
+gchar **
+gpk_client_resolve_show (gchar **packages)
+{
+	guint i;
+	guint length;
+	gchar *package_id;
+	gchar **package_ids = NULL;
+	GPtrArray *array;
+
+	array = g_ptr_array_new ();
+	client = pk_client_new ();
+	pk_client_set_use_buffer (client, TRUE, NULL);
+	pk_client_set_synchronous (client, TRUE, NULL);
+
+	length = g_strv_length (packages);
+	for (i=0; i<length; i++) {
+		package_id = gpk_client_resolve_indervidual (packages[i]);
+		if (package_id == NULL) {
+			goto out;
+		}
+		g_ptr_array_add (array, package_id);
+	}
+	package_ids = pk_ptr_array_to_argv (array);
+
+out:
+	g_ptr_array_free (array, TRUE);
+	g_object_unref (client);
+	return package_ids;
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef PK_BUILD_TESTS
+#include <libselftest.h>
+
+void
+gpk_client_resolve_self_test (gpointer data)
+{
+	LibSelfTest *test = (LibSelfTest *) data;
+
+	if (libst_start (test, "GpkClientResolve", CLASS_AUTO) == FALSE) {
+		return;
+	}
+	libst_end (test);
+}
+#endif
+

Added: trunk/src/gpk-client-resolve.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-client-resolve.h	Wed May  7 23:16:04 2008
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GPK_CLIENT_RESOLVE_H
+#define __GPK_CLIENT_RESOLVE_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+void		 gpk_client_resolve_self_test		(gpointer	 data);
+gchar		**gpk_client_resolve_show		(gchar		**packages);
+
+G_END_DECLS
+
+#endif	/* __GPK_CLIENT_RESOLVE_H */

Modified: trunk/src/gpk-client-untrusted.c
==============================================================================
--- trunk/src/gpk-client-untrusted.c	(original)
+++ trunk/src/gpk-client-untrusted.c	Wed May  7 23:16:04 2008
@@ -62,13 +62,9 @@
 	GladeXML *glade_xml;
 	gchar *text;
 	const gchar *title;
-	const gchar *message;
+	gchar *message;
 	PolKitGnomeAction *update_system_action;
 
-	title = gpk_error_enum_to_localised_text (code);
-	message = _("Malicious software can damage your computer or cause other harm. "
-		    "Are you <b>sure</b> you want to install this package?");
-
 	glade_xml = glade_xml_new (PK_DATA "/gpk-error.glade", NULL, NULL);
 
 	/* connect up actions */
@@ -84,14 +80,19 @@
 	g_signal_connect_swapped (widget, "clicked", G_CALLBACK (gtk_main_quit), NULL);
 
 	/* title */
+	title = gpk_error_enum_to_localised_text (code);
 	widget = glade_xml_get_widget (glade_xml, "label_title");
 	text = g_strdup_printf ("<b><big>%s</big></b>", title);
 	gtk_label_set_label (GTK_LABEL (widget), text);
 	g_free (text);
 
 	/* message */
+	message = g_strdup_printf ("%s\n%s",
+				   _("Malicious software can damage your computer or cause other harm."),
+				   _("Are you <b>sure</b> you want to install this package?"));
 	widget = glade_xml_get_widget (glade_xml, "label_message");
 	gtk_label_set_markup (GTK_LABEL (widget), message);
+	g_free (message);
 
 	/* don't show text in the expander */
 	widget = glade_xml_get_widget (glade_xml, "expander_details");

Modified: trunk/src/gpk-client.c
==============================================================================
--- trunk/src/gpk-client.c	(original)
+++ trunk/src/gpk-client.c	Wed May  7 23:16:04 2008
@@ -45,6 +45,10 @@
 #include <gpk-client-eula.h>
 #include <gpk-client-signature.h>
 #include <gpk-client-untrusted.h>
+#include <gpk-client-chooser.h>
+#include <gpk-client-resolve.h>
+#include <gpk-client-depends.h>
+#include <gpk-client-requires.h>
 #include <gpk-common.h>
 #include <gpk-gnome.h>
 #include <gpk-error.h>
@@ -67,7 +71,7 @@
 {
 	PkClient		*client_action;
 	PkClient		*client_resolve;
-	PkClient		*client_signature;
+	PkClient		*client_secondary;
 	GpkSmartIcon		*sicon;
 	GladeXML		*glade_xml;
 	GConfClient		*gconf_client;
@@ -87,6 +91,12 @@
 	GPK_CLIENT_PAGE_LAST
 } GpkClientPageEnum;
 
+enum {
+	GPK_CLIENT_QUIT,
+	LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
 G_DEFINE_TYPE (GpkClient, gpk_client, G_TYPE_OBJECT)
 
 /**
@@ -174,6 +184,7 @@
 	/* go! */
 	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
 	gtk_widget_hide (widget);
+	g_signal_emit (gclient, signals [GPK_CLIENT_QUIT], 0);
 }
 
 /**
@@ -193,6 +204,7 @@
 	/* go! */
 	gtk_widget_hide (widget);
 	gtk_main_quit ();
+	g_signal_emit (gclient, signals [GPK_CLIENT_QUIT], 0);
 	return FALSE;
 }
 
@@ -202,7 +214,9 @@
 static gboolean
 gpk_install_finished_timeout (gpointer data)
 {
+	GpkClient *gclient = (GpkClient *) data;
 	gtk_main_quit ();
+	g_signal_emit (gclient, signals [GPK_CLIENT_QUIT], 0);
 	return FALSE;
 }
 
@@ -318,9 +332,18 @@
 gpk_client_finished_cb (PkClient *client, PkExitEnum exit, guint runtime, GpkClient *gclient)
 {
 	GtkWidget *widget;
+	PkRoleEnum role;
 
 	g_return_if_fail (GPK_IS_CLIENT (gclient));
 
+	pk_client_get_role (client, &role, NULL, NULL);
+
+	/* do nothing */
+	if (role == PK_ROLE_ENUM_GET_UPDATES) {
+		gtk_main_quit ();
+		return;
+	}
+
 	/* do we show a libnotify window instead? */
 	if (!gclient->priv->show_progress) {
 		gpk_client_finished_no_progress (client, exit, runtime, gclient);
@@ -439,6 +462,13 @@
 		return;
 	}
 
+	/* ignore some errors */
+	if (code == PK_ERROR_ENUM_PROCESS_KILL ||
+	    code == PK_ERROR_ENUM_TRANSACTION_CANCELLED) {
+		pk_debug ("error ignored %s\n%s", pk_error_enum_to_text (code), details);
+		return;
+	}
+
 	pk_debug ("code was %s", pk_error_enum_to_text (code));
 	gpk_error_dialog (gpk_error_enum_to_localised_text (code),
 			  gpk_error_enum_to_localised_message (code), details);
@@ -563,15 +593,17 @@
 }
 
 /**
- * gpk_client_install_local_file_internal:
+ * gpk_client_install_local_files_internal:
  **/
 static gboolean
-gpk_client_install_local_file_internal (GpkClient *gclient, gboolean trusted,
-					const gchar *file_rel, GError **error)
+gpk_client_install_local_files_internal (GpkClient *gclient, gboolean trusted,
+					 gchar **files_rel, GError **error)
 {
 	gboolean ret;
 	GError *error_local = NULL;
 	gchar *text;
+	guint length;
+	const gchar *title;
 
 	/* reset */
 	ret = pk_client_reset (gclient->priv->client_action, &error_local);
@@ -583,19 +615,21 @@
 	}
 
 	/* install local file */
-	ret = pk_client_install_file (gclient->priv->client_action, trusted, file_rel, &error_local);
+	ret = pk_client_install_files (gclient->priv->client_action, trusted, files_rel, &error_local);
 	if (ret) {
 		return TRUE;
 	}
 
 	/* check if we got a permission denied */
 	if (g_str_has_prefix (error_local->message, "org.freedesktop.packagekit.")) {
-		gpk_client_error_msg (gclient, _("Failed to install file"),
+		gpk_client_error_msg (gclient, _("Failed to install files"),
 				      _("You don't have the necessary privileges to install local files"));
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 	} else {
 		text = g_markup_escape_text (error_local->message, -1);
-		gpk_client_error_msg (gclient, _("Failed to install file"), text);
+		length = g_strv_length (files_rel);
+		title = ngettext ("Failed to install file", "Failed to install files", length);
+		gpk_client_error_msg (gclient, title, text);
 		g_free (text);
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 	}
@@ -617,6 +651,29 @@
 }
 
 /**
+ * gpk_client_setup_window:
+ **/
+static gboolean
+gpk_client_setup_window (GpkClient *gclient, const gchar *title)
+{
+	GtkWidget *widget;
+
+	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
+
+	/* set title */
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
+	gtk_window_set_title (GTK_WINDOW (widget), title);
+
+	/* clear status and progress text */
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "progress_part_label");
+	gtk_label_set_label (GTK_LABEL (widget), "");
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "label_package");
+	gtk_label_set_label (GTK_LABEL (widget), "");
+
+	return TRUE;
+}
+
+/**
  * gpk_client_install_local_file:
  * @gclient: a valid #GpkClient instance
  * @file_rel: a file such as <literal>./hal-devel-0.10.0.rpm</literal>
@@ -628,23 +685,21 @@
  * Return value: %TRUE if the method succeeded
  **/
 gboolean
-gpk_client_install_local_file (GpkClient *gclient, const gchar *file_rel, GError **error)
+gpk_client_install_local_files (GpkClient *gclient, gchar **files_rel, GError **error)
 {
 	gboolean ret;
-	GtkWidget *widget;
 
 	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
-	g_return_val_if_fail (file_rel != NULL, FALSE);
+	g_return_val_if_fail (files_rel != NULL, FALSE);
 
 	gclient->priv->retry_untrusted_value = FALSE;
-	ret = gpk_client_install_local_file_internal (gclient, TRUE, file_rel, error);
+	ret = gpk_client_install_local_files_internal (gclient, TRUE, files_rel, error);
 	if (!ret) {
 		goto out;
 	}
 
 	/* set title */
-	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
-	gtk_window_set_title (GTK_WINDOW (widget), _("Install local file"));
+	gpk_client_setup_window (gclient, _("Install local file"));
 
 	/* setup the UI */
 	gpk_client_set_page (gclient, GPK_CLIENT_PAGE_PROGRESS);
@@ -654,7 +709,7 @@
 
 	/* do we need to try again with better auth? */
 	if (gclient->priv->retry_untrusted_value) {
-		ret = gpk_client_install_local_file_internal (gclient, FALSE, file_rel, error);
+		ret = gpk_client_install_local_files_internal (gclient, FALSE, files_rel, error);
 		if (!ret) {
 			goto out;
 		}
@@ -669,23 +724,7 @@
 }
 
 /**
- * gpk_client_checkbutton_show_depends_cb:
- **/
-static void
-gpk_client_checkbutton_show_depends_cb (GtkWidget *widget, GpkClient *gclient)
-{
-	gboolean checked;
-
-	g_return_if_fail (GPK_IS_CLIENT (gclient));
-
-	/* set the policy */
-	checked = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
-	pk_debug ("Changing %s to %i", GPK_CONF_SHOW_DEPENDS, checked);
-	gconf_client_set_bool (gclient->priv->gconf_client, GPK_CONF_SHOW_DEPENDS, checked, NULL);
-}
-
-/**
- * gpk_client_remove_package_id:
+ * gpk_client_remove_package_ids:
  * @gclient: a valid #GpkClient instance
  * @package_id: a package_id such as <literal>hal-info;0.20;i386;fedora</literal>
  * @error: a %GError to put the error code and message in, or %NULL
@@ -693,110 +732,50 @@
  * Return value: %TRUE if the method succeeded
  **/
 gboolean
-gpk_client_remove_package_id (GpkClient *gclient, const gchar *package_id, GError **error)
+gpk_client_remove_package_ids (GpkClient *gclient, gchar **package_ids, GError **error)
 {
-	GtkWidget *widget;
-	GtkWidget *dialog;
-	GtkResponseType button;
 	gboolean ret;
 	GError *error_local = NULL;
 	gchar *text = NULL;
-	gchar *title = NULL;
-	gchar *package_name = NULL;
-	guint len;
-	guint i;
-	GString *string;
-	PkPackageItem *item;
 
 	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
-	g_return_val_if_fail (package_id != NULL, FALSE);
+	g_return_val_if_fail (package_ids != NULL, FALSE);
 
 	/* set title */
-	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
-	gtk_window_set_title (GTK_WINDOW (widget), _("Remove packages"));
+	gpk_client_setup_window (gclient, _("Remove packages"));
 
 	/* are we dumb and can't check for depends? */
-	if (!pk_enums_contain (gclient->priv->roles, PK_ROLE_ENUM_GET_DEPENDS)) {
+	if (!pk_enums_contain (gclient->priv->roles, PK_ROLE_ENUM_GET_REQUIRES)) {
 		pk_warning ("skipping depends check");
 		goto skip_checks;
 	}
 
-	/* reset */
-	ret = pk_client_reset (gclient->priv->client_resolve, &error_local);
+	ret = gpk_client_depends_show (package_ids);
+	/* did we click no or exit the window? */
 	if (!ret) {
-		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"));
-		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		gpk_client_error_msg (gclient, _("Failed to remove package"), _("Additional packages were also not removed"));
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, "user did not agree to additional requires");
 		ret = FALSE;
 		goto out;
 	}
 
-	/* find out if this would drag in other packages */
-	ret = pk_client_get_requires (gclient->priv->client_resolve, PK_FILTER_ENUM_NOT_INSTALLED, package_id, TRUE, &error_local);
+skip_checks:
+	/* reset */
+	ret = pk_client_reset (gclient->priv->client_action, &error_local);
 	if (!ret) {
-		text = g_strdup_printf ("%s: %s", _("Could not work out what packages would be also removeed"), error_local->message);
-		gpk_client_error_msg (gclient, _("Failed to get depends"), text);
+		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"));
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 		ret = FALSE;
 		goto out;
 	}
 
-	/* any additional packages? */
-	len = pk_client_package_buffer_get_size	(gclient->priv->client_resolve);
-	if (len == 0) {
-		pk_debug ("no additional requires");
-		goto skip_checks;
-	}
-
-	/* process package list */
-	string = g_string_new (_("The following packages have to be removed:"));
-	g_string_append (string, "\n\n");
-	for (i=0; i<len; i++) {
-		item = pk_client_package_buffer_get_item (gclient->priv->client_resolve, i);
-		text = gpk_package_id_format_oneline (item->package_id, item->summary);
-		g_string_append_printf (string, "%s\n", text);
-		g_free (text);
-	}
-	/* remove last \n */
-	g_string_set_size (string, string->len - 1);
-
-	/* display messagebox  */
-	text = g_string_free (string, FALSE);
-	pk_debug ("text=%s", text);
-
-	/* show UI */
-	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
-	package_name = gpk_package_get_name (package_id);
-	title = g_strdup_printf (_("Other software depends on %s"), package_name);
-	g_free (package_name);
-
-	dialog = gtk_message_dialog_new (GTK_WINDOW (widget), GTK_DIALOG_DESTROY_WITH_PARENT,
-					 GTK_MESSAGE_QUESTION, GTK_BUTTONS_CANCEL, "%s", title);
-	g_free (title);
-
-	/* add a specialist button */
-	gtk_dialog_add_button (GTK_DIALOG (dialog), _("Remove all packages"), GTK_RESPONSE_OK);
-
-	gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", text);
-	button = gtk_dialog_run (GTK_DIALOG (dialog));
-	gtk_widget_destroy (GTK_WIDGET (dialog));
-	g_free (text);
-
-	/* did we click no or exit the window? */
-	if (button != GTK_RESPONSE_OK) {
-		gpk_client_error_msg (gclient, _("Failed to remove package"), _("Additional packages were also not removed"));
-		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, "user did not agree to additional requires");
-		ret = FALSE;
-		goto out;
-	}
-
-skip_checks:
-	/* try to remove the package_id */
-	ret = pk_client_remove_package (gclient->priv->client_action, package_id, TRUE, FALSE, &error_local);
+	/* try to remove the package_ids */
+	ret = pk_client_remove_packages (gclient->priv->client_action, package_ids, TRUE, FALSE, &error_local);
 	if (!ret) {
 		/* check if we got a permission denied */
 		if (g_str_has_prefix (error_local->message, "org.freedesktop.packagekit.")) {
 			gpk_client_error_msg (gclient, _("Failed to remove package"),
-					        _("You don't have the necessary privileges to remove packages"));
+						_("You don't have the necessary privileges to remove packages"));
 			gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 		} else {
 			text = g_markup_escape_text (error_local->message, -1);
@@ -821,7 +800,7 @@
 }
 
 /**
- * gpk_client_install_package_id:
+ * gpk_client_install_package_ids:
  * @gclient: a valid #GpkClient instance
  * @package_id: a package_id such as <literal>hal-info;0.20;i386;fedora</literal>
  * @error: a %GError to put the error code and message in, or %NULL
@@ -829,25 +808,17 @@
  * Return value: %TRUE if the method succeeded
  **/
 gboolean
-gpk_client_install_package_id (GpkClient *gclient, const gchar *package_id, GError **error)
+gpk_client_install_package_ids (GpkClient *gclient, gchar **package_ids, GError **error)
 {
-	GtkWidget *widget;
-	GtkWidget *dialog;
-	GtkResponseType button;
 	gboolean ret;
 	GError *error_local = NULL;
 	gchar *text;
-	guint len;
-	guint i;
-	GString *string;
-	PkPackageItem *item;
 
 	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
-	g_return_val_if_fail (package_id != NULL, FALSE);
+	g_return_val_if_fail (package_ids != NULL, FALSE);
 
 	/* set title */
-	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
-	gtk_window_set_title (GTK_WINDOW (widget), _("Install packages"));
+	gpk_client_setup_window (gclient, _("Install packages"));
 
 	/* are we dumb and can't check for depends? */
 	if (!pk_enums_contain (gclient->priv->roles, PK_ROLE_ENUM_GET_DEPENDS)) {
@@ -855,77 +826,9 @@
 		goto skip_checks;
 	}
 
-	/* reset */
-	ret = pk_client_reset (gclient->priv->client_resolve, &error_local);
-	if (!ret) {
-		gpk_client_error_msg (gclient, _("Failed to reset client"), _("Failed to reset resolve"));
-		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
-		ret = FALSE;
-		goto out;
-	}
-
-	/* find out if this would drag in other packages */
-	ret = pk_client_get_depends (gclient->priv->client_resolve, PK_FILTER_ENUM_NOT_INSTALLED, package_id, TRUE, &error_local);
-	if (!ret) {
-		text = g_strdup_printf ("%s: %s", _("Could not work out what packages would be also installed"), error_local->message);
-		gpk_client_error_msg (gclient, _("Failed to get depends"), text);
-		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
-		g_free (text);
-		ret = FALSE;
-		goto out;
-	}
-
-	/* any additional packages? */
-	len = pk_client_package_buffer_get_size	(gclient->priv->client_resolve);
-	if (len == 0) {
-		pk_debug ("no additional deps");
-		goto skip_checks;
-	}
-
-	/* have we previously said we don't want to be shown the confirmation */
-	ret = gconf_client_get_bool (gclient->priv->gconf_client, GPK_CONF_SHOW_DEPENDS, NULL);
-	if (!ret) {
-		pk_debug ("we've said we don't want deps anymore");
-		goto skip_checks;
-	}
-
-	/* process package list */
-	string = g_string_new (_("The following packages also have to be downloaded:"));
-	g_string_append (string, "\n\n");
-	for (i=0; i<len; i++) {
-		item = pk_client_package_buffer_get_item (gclient->priv->client_resolve, i);
-		text = gpk_package_id_format_oneline (item->package_id, item->summary);
-		g_string_append_printf (string, "%s\n", text);
-		g_free (text);
-	}
-	/* remove last \n */
-	g_string_set_size (string, string->len - 1);
-
-	/* display messagebox  */
-	text = g_string_free (string, FALSE);
-	pk_debug ("text=%s", text);
-
-	/* show UI */
-	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
-	dialog = gtk_message_dialog_new (GTK_WINDOW (widget), GTK_DIALOG_DESTROY_WITH_PARENT,
-					 GTK_MESSAGE_QUESTION, GTK_BUTTONS_CANCEL,
-					 "%s", _("Install additional packages?"));
-	/* add a specialist button */
-	gtk_dialog_add_button (GTK_DIALOG (dialog), _("Install"), GTK_RESPONSE_OK);
-
-	/* add a checkbutton for deps screen */
-	widget = gtk_check_button_new_with_label (_("Do not show me this again"));
-	g_signal_connect (widget, "clicked", G_CALLBACK (gpk_client_checkbutton_show_depends_cb), gclient);
-	gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), widget);
-	gtk_widget_show (widget);
-
-	gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", text);
-	button = gtk_dialog_run (GTK_DIALOG (dialog));
-	gtk_widget_destroy (GTK_WIDGET (dialog));
-	g_free (text);
-
+	ret = gpk_client_depends_show (package_ids);
 	/* did we click no or exit the window? */
-	if (button != GTK_RESPONSE_OK) {
+	if (!ret) {
 		gpk_client_error_msg (gclient, _("Failed to install package"), _("Additional packages were not downloaded"));
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, "user did not agree to additional deps");
 		ret = FALSE;
@@ -943,12 +846,12 @@
 	}
 
 	/* try to install the package_id */
-	ret = pk_client_install_package (gclient->priv->client_action, package_id, &error_local);
+	ret = pk_client_install_packages (gclient->priv->client_action, package_ids, &error_local);
 	if (!ret) {
 		/* check if we got a permission denied */
 		if (g_str_has_prefix (error_local->message, "org.freedesktop.packagekit.")) {
 			gpk_client_error_msg (gclient, _("Failed to install package"),
-					        _("You don't have the necessary privileges to install packages"));
+						_("You don't have the necessary privileges to install packages"));
 			gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
 		} else {
 			text = g_markup_escape_text (error_local->message, -1);
@@ -980,69 +883,34 @@
  * Return value: %TRUE if the method succeeded
  **/
 gboolean
-gpk_client_install_package_name (GpkClient *gclient, const gchar *package, GError **error)
+gpk_client_install_package_names (GpkClient *gclient, gchar **packages, GError **error)
 {
 	gboolean ret;
 	GError *error_local = NULL;
-	guint len;
-	guint i;
-	gboolean already_installed = FALSE;
-	gchar *package_id = NULL;
-	PkPackageItem *item;
+	gchar **package_ids = NULL;
 
 	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
-	g_return_val_if_fail (package != NULL, FALSE);
-
-	ret = pk_client_resolve (gclient->priv->client_resolve, PK_FILTER_ENUM_NONE, package, &error_local);
-	if (!ret) {
-		gpk_client_error_msg (gclient, _("Failed to resolve package"), _("Incorrect response from search"));
-		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
-		ret = FALSE;
-		goto out;
-	}
-
-	/* found nothing? */
-	len = pk_client_package_buffer_get_size	(gclient->priv->client_resolve);
-	if (len == 0) {
-		gpk_client_error_msg (gclient, _("Failed to find package"), _("The package could not be found online"));
-		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, NULL);
-		ret = FALSE;
-		goto out;
-	}
-
-	/* see what we've got already */
-	for (i=0; i<len; i++) {
-		item = pk_client_package_buffer_get_item (gclient->priv->client_resolve, i);
-		if (item->info == PK_INFO_ENUM_INSTALLED) {
-			already_installed = TRUE;
-			break;
-		} else if (item->info == PK_INFO_ENUM_AVAILABLE) {
-			pk_debug ("package '%s' resolved", item->package_id);
-			package_id = g_strdup (item->package_id);
-			break;
-		}
-	}
+	g_return_val_if_fail (packages != NULL, FALSE);
 
-	/* already installed? */
-	if (already_installed) {
-		gpk_client_error_msg (gclient, _("Failed to install package"), _("The package is already installed"));
-		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+	/* resolve a 2D array to package_id's */
+	package_ids = gpk_client_resolve_show (packages);
+	if (package_ids == NULL) {
 		ret = FALSE;
 		goto out;
 	}
 
-	/* got junk? */
-	if (package_id == NULL) {
-		gpk_client_error_msg (gclient, _("Failed to find package"), _("Incorrect response from search"));
+	/* install these packages */
+	ret = gpk_client_install_package_ids (gclient, package_ids, &error_local);
+	if (!ret) {
+		/* copy error message */
 		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
-		ret = FALSE;
 		goto out;
 	}
-
-	/* install this specific package */
-	ret = gpk_client_install_package_id (gclient, package_id, error);
 out:
-	g_free (package_id);
+	if (error_local != NULL) {
+		g_error_free (error_local);
+	}
+	g_strfreev (package_ids);
 	return ret;
 }
 
@@ -1067,6 +935,7 @@
 	gchar *package_id = NULL;
 	PkPackageItem *item;
 	PkPackageId *ident;
+	gchar **package_ids = NULL;
 	gchar *text;
 
 	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
@@ -1126,8 +995,74 @@
 	}
 
 	/* install this specific package */
-	ret = gpk_client_install_package_id (gclient, package_id, error);
+	package_ids = g_strsplit (package_id, "|", 1);
+	ret = gpk_client_install_package_ids (gclient, package_ids, error);
 out:
+	g_strfreev (package_ids);
+	g_free (package_id);
+	return ret;
+}
+
+/**
+ * gpk_client_install_mime_type:
+ * @gclient: a valid #GpkClient instance
+ * @mime_type: a mime_type such as <literal>application/text</literal>
+ * @error: a %GError to put the error code and message in, or %NULL
+ *
+ * Install a application to handle a mime type
+ *
+ * Return value: %TRUE if the method succeeded
+ **/
+gboolean
+gpk_client_install_mime_type (GpkClient *gclient, const gchar *mime_type, GError **error)
+{
+	gboolean ret;
+	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);
+	g_return_val_if_fail (mime_type != NULL, FALSE);
+
+	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_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		g_free (text);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* found nothing? */
+	len = pk_client_package_buffer_get_size	(gclient->priv->client_resolve);
+	if (len == 0) {
+		gpk_client_error_msg (gclient, _("Failed to find software"),
+				      _("No new applications can be found to handle this type of file"));
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, NULL);
+		ret = FALSE;
+		goto out;
+	}
+
+	/* populate a chooser */
+	package_id = gpk_client_chooser_show (gclient->priv->client_resolve, 0, _("Applications that can open this type of file"));
+
+	/* 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_set (error, GPK_CLIENT_ERROR_FAILED, "user chose nothing");
+		ret = FALSE;
+		goto out;
+	}
+
+	/* install this specific package */
+	package_ids = g_strsplit (package_id, "|", 1);
+	ret = gpk_client_install_package_ids (gclient, package_ids, error);
+out:
+	g_strfreev (package_ids);
 	g_free (package_id);
 	return ret;
 }
@@ -1139,7 +1074,6 @@
 gpk_client_update_system (GpkClient *gclient, GError **error)
 {
 	gboolean ret;
-	GtkWidget *widget;
 	GError *error_local = NULL;
 	gchar *text = NULL;
 	gchar *message = NULL;
@@ -1156,8 +1090,7 @@
 	}
 
 	/* set title */
-	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
-	gtk_window_set_title (GTK_WINDOW (widget), _("System update"));
+	gpk_client_setup_window (gclient, _("System update"));
 
 	/* wrap update, but handle all the GPG and EULA stuff */
 	ret = pk_client_update_system (gclient->priv->client_action, &error_local);
@@ -1203,13 +1136,118 @@
 }
 
 /**
+ * gpk_client_refresh_cache:
+ **/
+gboolean
+gpk_client_refresh_cache (GpkClient *gclient, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+	gchar *text = NULL;
+	gchar *message = NULL;
+
+	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_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		g_error_free (error_local);
+		return FALSE;
+	}
+
+	/* set title */
+	gpk_client_setup_window (gclient, _("Refresh package lists"));
+
+	/* wrap update, but handle all the GPG and EULA stuff */
+	ret = pk_client_refresh_cache (gclient->priv->client_action, TRUE, &error_local);
+	if (!ret) {
+		/* print a proper error if we have it */
+		if (error_local->code == PK_CLIENT_ERROR_FAILED_AUTH) {
+			message = g_strdup (_("Authorisation could not be obtained"));
+		} else {
+			message = g_strdup_printf (_("The error was: %s"), error_local->message);
+		}
+
+		/* 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_set (error, GPK_CLIENT_ERROR_FAILED, message);
+		goto out;
+	}
+
+	/* setup the UI */
+	gpk_client_set_page (gclient, GPK_CLIENT_PAGE_PROGRESS);
+
+	/* wait for completion */
+	gtk_main ();
+
+out:
+	g_free (message);
+	g_free (text);
+	return ret;
+}
+
+/**
+ * gpk_client_get_updates:
+ **/
+PkPackageList *
+gpk_client_get_updates (GpkClient *gclient, GError **error)
+{
+	gboolean ret;
+	GError *error_local = NULL;
+	PkPackageList *list = NULL;
+	PkPackageItem *item;
+	guint length;
+	guint i;
+
+	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 get-updates"));
+		gpk_client_error_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		g_error_free (error_local);
+		return FALSE;
+	}
+
+	/* set title */
+	gpk_client_setup_window (gclient, _("Getting update lists"));
+
+	/* 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_set (error, GPK_CLIENT_ERROR_FAILED, error_local->message);
+		goto out;
+	}
+
+	/* setup the UI */
+	gpk_client_set_page (gclient, GPK_CLIENT_PAGE_PROGRESS);
+
+	/* wait for completion */
+	gtk_main ();
+
+	/* copy from client to local */
+	list = pk_package_list_new ();
+	length = pk_client_package_buffer_get_size (gclient->priv->client_action);
+	for (i=0;i<length;i++) {
+		item = pk_client_package_buffer_get_item (gclient->priv->client_action, i);
+		pk_package_list_add (list, item->info, item->package_id, item->summary);
+	}
+out:
+	return list;
+}
+
+/**
  * gpk_client_update_packages:
  **/
 gboolean
 gpk_client_update_packages (GpkClient *gclient, gchar **package_ids, GError **error)
 {
 	gboolean ret;
-	GtkWidget *widget;
 	GError *error_local = NULL;
 	gchar *text = NULL;
 	gchar *message = NULL;
@@ -1226,11 +1264,10 @@
 	}
 
 	/* set title */
-	widget = glade_xml_get_widget (gclient->priv->glade_xml, "window_updates");
-	gtk_window_set_title (GTK_WINDOW (widget), _("Update packages"));
+	gpk_client_setup_window (gclient, _("Update packages"));
 
 	/* wrap update, but handle all the GPG and EULA stuff */
-	ret = pk_client_update_packages_strv (gclient->priv->client_action, package_ids, &error_local);
+	ret = pk_client_update_packages (gclient->priv->client_action, package_ids, &error_local);
 	if (!ret) {
 		/* print a proper error if we have it */
 		if (error_local->code == PK_CLIENT_ERROR_FAILED_AUTH) {
@@ -1281,14 +1318,14 @@
 
 	/* install signature */
 	pk_debug ("install signature %s", key_id);
-	ret = pk_client_reset (gclient->priv->client_signature, &error);
+	ret = pk_client_reset (gclient->priv->client_secondary, &error);
 	if (!ret) {
 		gpk_error_dialog (_("Failed to install signature"), _("The client could not be reset"), error->message);
 		g_error_free (error);
 		return;
 	}
 	/* this is asynchronous, else we get into livelock */
-	ret = pk_client_install_signature (gclient->priv->client_signature, PK_SIGTYPE_ENUM_GPG,
+	ret = pk_client_install_signature (gclient->priv->client_secondary, PK_SIGTYPE_ENUM_GPG,
 					   key_id, package_id, &error);
 	gclient->priv->do_key_auth = ret;
 	if (!ret) {
@@ -1317,7 +1354,7 @@
 
 	/* install signature */
 	pk_debug ("accept EULA %s", eula_id);
-	ret = pk_client_reset (gclient->priv->client_signature, &error);
+	ret = pk_client_reset (gclient->priv->client_secondary, &error);
 	if (!ret) {
 		gpk_error_dialog (_("Failed to accept EULA"), _("The client could not be reset"), error->message);
 		g_error_free (error);
@@ -1325,7 +1362,7 @@
 	}
 
 	/* this is asynchronous, else we get into livelock */
-	ret = pk_client_accept_eula (gclient->priv->client_signature, eula_id, &error);
+	ret = pk_client_accept_eula (gclient->priv->client_secondary, eula_id, &error);
 	if (!ret) {
 		gpk_error_dialog (_("Failed to accept EULA"), _("The method failed"), error->message);
 		g_error_free (error);
@@ -1334,22 +1371,35 @@
 }
 
 /**
- * gpk_client_signature_finished_cb:
+ * gpk_client_secondary_now_requeue:
  **/
-static void
-gpk_client_signature_finished_cb (PkClient *client, PkExitEnum exit, guint runtime, GpkClient *gclient)
+static gboolean
+gpk_client_secondary_now_requeue (GpkClient *gclient)
 {
 	gboolean ret;
 	GError *error = NULL;
 
-	g_return_if_fail (GPK_IS_CLIENT (gclient));
+	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
 
 	pk_debug ("trying to requeue install");
 	ret = pk_client_requeue (gclient->priv->client_action, &error);
 	if (!ret) {
-		gpk_error_dialog (_("Failed to install"), _("The install task could not be requeued"), error ? error->message : _("Error details not available"));
+		gpk_error_dialog (_("Failed to install"), _("The install task could not be requeued"), error->message);
 		g_error_free (error);
 	}
+	gtk_main ();
+	return FALSE;
+}
+
+/**
+ * gpk_client_secondary_finished_cb:
+ **/
+static void
+gpk_client_secondary_finished_cb (PkClient *client, PkExitEnum exit, guint runtime, GpkClient *gclient)
+{
+	g_return_if_fail (GPK_IS_CLIENT (gclient));
+	/* we have to do this idle add, else we get into deadlock */
+	g_idle_add ((GSourceFunc) gpk_client_secondary_now_requeue, gclient);
 }
 
 /**
@@ -1385,6 +1435,116 @@
 }
 
 /**
+ * pk_common_get_role_text:
+ **/
+static gchar *
+pk_common_get_role_text (PkClient *client)
+{
+	const gchar *role_text;
+	gchar *package_id;
+	gchar *text;
+	gchar *package;
+	PkRoleEnum role;
+	GError *error = NULL;
+	gboolean ret;
+
+	/* get role and text */
+	ret = pk_client_get_role (client, &role, &package_id, &error);
+	if (!ret) {
+		pk_warning ("failed to get role: %s", error->message);
+		g_error_free (error);
+		return NULL;
+	}
+
+	/* backup */
+	role_text = gpk_role_enum_to_localised_present (role);
+
+	if (!pk_strzero (package_id) && role != PK_ROLE_ENUM_UPDATE_PACKAGES) {
+		package = gpk_package_get_name (package_id);
+		text = g_strdup_printf ("%s: %s", role_text, package);
+		g_free (package);
+	} else {
+		text = g_strdup_printf ("%s", role_text);
+	}
+	g_free (package_id);
+
+	return text;
+}
+
+/**
+ * gpk_client_monitor_tid:
+ **/
+gboolean
+gpk_client_monitor_tid (GpkClient *gclient, const gchar *tid)
+{
+	GtkWidget *widget;
+	PkStatusEnum status;
+	gboolean ret;
+	gboolean allow_cancel;
+	gchar *text;
+	guint percentage;
+	guint subpercentage;
+	guint elapsed;
+	guint remaining;
+	GError *error = NULL;
+
+	g_return_val_if_fail (GPK_IS_CLIENT (gclient), FALSE);
+
+	ret = pk_client_set_tid (gclient->priv->client_action, tid, &error);
+	if (!ret) {
+		pk_warning ("could not set tid: %s", error->message);
+		g_error_free (error);
+		return FALSE;
+	}
+
+	/* fill in role */
+	text = pk_common_get_role_text (gclient->priv->client_action);
+	gpk_client_setup_window (gclient, text);
+	g_free (text);
+
+	/* coldplug */
+	ret = pk_client_get_status (gclient->priv->client_action, &status, NULL);
+	/* no such transaction? */
+	if (!ret) {
+		pk_warning ("could not get status");
+		return FALSE;
+	}
+
+	/* are we cancellable? */
+	pk_client_get_allow_cancel (gclient->priv->client_action, &allow_cancel, NULL);
+	widget = glade_xml_get_widget (gclient->priv->glade_xml, "button_cancel");
+	gtk_widget_set_sensitive (widget, allow_cancel);
+
+	gpk_client_status_changed_cb (gclient->priv->client_action, status, gclient);
+
+	/* coldplug */
+	ret = pk_client_get_progress (gclient->priv->client_action,
+				      &percentage, &subpercentage, &elapsed, &remaining, NULL);
+	if (ret) {
+		gpk_client_progress_changed_cb (gclient->priv->client_action, percentage,
+						subpercentage, elapsed, remaining, gclient);
+	} else {
+		pk_warning ("GetProgress failed");
+		gpk_client_progress_changed_cb (gclient->priv->client_action,
+						PK_CLIENT_PERCENTAGE_INVALID,
+						PK_CLIENT_PERCENTAGE_INVALID, 0, 0, gclient);
+	}
+
+	/* do the best we can */
+	ret = pk_client_get_package (gclient->priv->client_action, &text, NULL);
+	if (ret) {
+		gpk_client_package_cb (gclient->priv->client_action, 0, text, NULL, gclient);
+	}
+
+	gpk_client_set_page (gclient, GPK_CLIENT_PAGE_PROGRESS);
+
+	/* wait for completion */
+	gtk_main ();
+
+	return TRUE;
+}
+
+/**
  * gpk_client_class_init:
  * @klass: The #GpkClientClass
  **/
@@ -1394,6 +1554,13 @@
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	object_class->finalize = gpk_client_finalize;
 	g_type_class_add_private (klass, sizeof (GpkClientPrivate));
+	signals [GPK_CLIENT_QUIT] =
+		g_signal_new ("quit",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      0, NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
 }
 
 /**
@@ -1426,6 +1593,7 @@
 	gclient->priv->roles = pk_control_get_actions (gclient->priv->control);
 
 	gclient->priv->client_action = pk_client_new ();
+	pk_client_set_use_buffer (gclient->priv->client_action, TRUE, NULL);
 	g_signal_connect (gclient->priv->client_action, "finished",
 			  G_CALLBACK (gpk_client_finished_cb), gclient);
 	g_signal_connect (gclient->priv->client_action, "progress-changed",
@@ -1454,9 +1622,9 @@
 	pk_client_set_synchronous (gclient->priv->client_resolve, TRUE, NULL);
 
 	/* this is asynchronous, else we get into livelock */
-	gclient->priv->client_signature = pk_client_new ();
-	g_signal_connect (gclient->priv->client_signature, "finished",
-			  G_CALLBACK (gpk_client_signature_finished_cb), gclient);
+	gclient->priv->client_secondary = pk_client_new ();
+	g_signal_connect (gclient->priv->client_secondary, "finished",
+			  G_CALLBACK (gpk_client_secondary_finished_cb), gclient);
 
 	gclient->priv->glade_xml = glade_xml_new (PK_DATA "/gpk-client.glade", NULL, NULL);
 
@@ -1511,7 +1679,7 @@
 
 	g_object_unref (gclient->priv->client_action);
 	g_object_unref (gclient->priv->client_resolve);
-	g_object_unref (gclient->priv->client_signature);
+	g_object_unref (gclient->priv->client_secondary);
 	g_object_unref (gclient->priv->control);
 	g_object_unref (gclient->priv->gconf_client);
 	g_object_unref (gclient->priv->sicon);

Modified: trunk/src/gpk-client.h
==============================================================================
--- trunk/src/gpk-client.h	(original)
+++ trunk/src/gpk-client.h	Wed May  7 23:16:04 2008
@@ -24,6 +24,7 @@
 
 #include <glib-object.h>
 #include <gtk/gtk.h>
+#include <pk-package-list.h>
 
 G_BEGIN_DECLS
 
@@ -66,23 +67,28 @@
 GType		 gpk_client_get_type			(void) G_GNUC_CONST;
 GpkClient	*gpk_client_new				(void);
 
-gboolean	 gpk_client_install_local_file		(GpkClient	*gclient,
-							 const gchar	*file_rel,
+gboolean	 gpk_client_install_local_files		(GpkClient	*gclient,
+							 gchar		**files_rel,
 							 GError		**error);
 gboolean	 gpk_client_install_provide_file	(GpkClient	*gclient,
 							 const gchar	*full_path,
 							 GError		**error);
-gboolean	 gpk_client_install_package_name	(GpkClient	*gclient,
-							 const gchar	*package,
+gboolean	 gpk_client_install_mime_type		(GpkClient	*gclient,
+							 const gchar	*mime_type,
 							 GError		**error);
-gboolean	 gpk_client_install_package_id		(GpkClient	*gclient,
-							 const gchar	*package_id,
+gboolean	 gpk_client_install_package_names	(GpkClient	*gclient,
+							 gchar		**packages,
 							 GError		**error);
-gboolean	 gpk_client_remove_package_id		(GpkClient	*gclient,
-							 const gchar	*package_id,
+gboolean	 gpk_client_install_package_ids		(GpkClient	*gclient,
+							 gchar		**package_ids,
+							 GError		**error);
+gboolean	 gpk_client_remove_package_ids		(GpkClient	*gclient,
+							 gchar		**package_ids,
 							 GError		**error);
 gboolean	 gpk_client_update_system		(GpkClient	*gclient,
 							 GError		**error);
+gboolean	 gpk_client_refresh_cache		(GpkClient	*gclient,
+							 GError		**error);
 gboolean	 gpk_client_update_packages		(GpkClient	*gclient,
 							 gchar		**package_ids,
 							 GError		**error);
@@ -90,6 +96,10 @@
 							 gboolean	 enabled);
 void		 gpk_client_show_progress		(GpkClient	*gclient,
 							 gboolean	 enabled);
+PkPackageList	*gpk_client_get_updates			(GpkClient	*gclient,
+							 GError		**error);
+gboolean	 gpk_client_monitor_tid			(GpkClient	*gclient,
+							 const gchar	*tid);
 
 G_END_DECLS
 

Modified: trunk/src/gpk-common.c
==============================================================================
--- trunk/src/gpk-common.c	(original)
+++ trunk/src/gpk-common.c	Wed May  7 23:16:04 2008
@@ -102,9 +102,9 @@
 	{PK_ROLE_ENUM_SEARCH_GROUP,		"pk-package-search"},
 	{PK_ROLE_ENUM_SEARCH_NAME,		"pk-package-search"},
 	{PK_ROLE_ENUM_REFRESH_CACHE,		"pk-refresh-cache"},
-	{PK_ROLE_ENUM_REMOVE_PACKAGE,		"pk-package-delete"},
-	{PK_ROLE_ENUM_INSTALL_PACKAGE,		"pk-package-add"},
-	{PK_ROLE_ENUM_INSTALL_FILE,		"pk-package-add"},
+	{PK_ROLE_ENUM_REMOVE_PACKAGES,		"pk-package-delete"},
+	{PK_ROLE_ENUM_INSTALL_PACKAGES,		"pk-package-add"},
+	{PK_ROLE_ENUM_INSTALL_FILES,		"pk-package-add"},
 	{PK_ROLE_ENUM_UPDATE_PACKAGES,		"pk-package-update"},
 	{PK_ROLE_ENUM_SERVICE_PACK,		"pk-package-update"},
 	{PK_ROLE_ENUM_UPDATE_SYSTEM,		"system-software-update"},
@@ -954,13 +954,13 @@
 	case PK_ROLE_ENUM_SEARCH_NAME:
 		text = _("Searching for package name");
 		break;
-	case PK_ROLE_ENUM_REMOVE_PACKAGE:
+	case PK_ROLE_ENUM_REMOVE_PACKAGES:
 		text = _("Removing");
 		break;
-	case PK_ROLE_ENUM_INSTALL_PACKAGE:
+	case PK_ROLE_ENUM_INSTALL_PACKAGES:
 		text = _("Installing");
 		break;
-	case PK_ROLE_ENUM_INSTALL_FILE:
+	case PK_ROLE_ENUM_INSTALL_FILES:
 		text = _("Installing file");
 		break;
 	case PK_ROLE_ENUM_REFRESH_CACHE:
@@ -1054,13 +1054,13 @@
 	case PK_ROLE_ENUM_SEARCH_NAME:
 		text = _("Searched for package name");
 		break;
-	case PK_ROLE_ENUM_REMOVE_PACKAGE:
+	case PK_ROLE_ENUM_REMOVE_PACKAGES:
 		text = _("Removed package");
 		break;
-	case PK_ROLE_ENUM_INSTALL_PACKAGE:
+	case PK_ROLE_ENUM_INSTALL_PACKAGES:
 		text = _("Installed package");
 		break;
-	case PK_ROLE_ENUM_INSTALL_FILE:
+	case PK_ROLE_ENUM_INSTALL_FILES:
 		text = _("Installed local file");
 		break;
 	case PK_ROLE_ENUM_SERVICE_PACK:
@@ -1340,6 +1340,27 @@
 	return timestring;
 }
 
+/**
+ * gpk_convert_argv_to_strv:
+ **/
+gchar **
+gpk_convert_argv_to_strv (gchar *argv[])
+{
+	gchar **array;
+	guint length;
+	guint i;
+
+	length = g_strv_length (argv) - 1;
+	array = g_new0 (gchar *, length+1);
+	for (i=0; i<length; i++) {
+		/* we miss out argv[0] as it's the program name */
+		array[i] = g_strdup (argv[i+1]);
+		pk_debug ("array[%i]=%s", i, array[i]);
+	}
+	array[i] = NULL;
+	return array;
+}
+
 /***************************************************************************
  ***                          MAKE CHECK TESTS                           ***
  ***************************************************************************/

Modified: trunk/src/gpk-common.h
==============================================================================
--- trunk/src/gpk-common.h	(original)
+++ trunk/src/gpk-common.h	Wed May  7 23:16:04 2008
@@ -92,6 +92,7 @@
 							 guint		 number)
 							 G_GNUC_CONST;
 gchar		*gpk_time_to_localised_string		(guint		 time_secs);
+gchar		**gpk_convert_argv_to_strv		(gchar		*argv[]);
 
 G_END_DECLS
 

Added: trunk/src/gpk-dbus.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-dbus.c	Wed May  7 23:16:04 2008
@@ -0,0 +1,318 @@
+/* -*- 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 <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <string.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include <sys/wait.h>
+#include <fcntl.h>
+
+#include <glib/gi18n.h>
+#include <libgbus.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <pk-common.h>
+#include <pk-package-id.h>
+#include <pk-package-ids.h>
+#include <pk-enum.h>
+#include <pk-debug.h>
+#include <pk-package-list.h>
+
+#include "gpk-dbus.h"
+#include "gpk-client.h"
+
+static void     gpk_dbus_class_init	(GpkDbusClass *klass);
+static void     gpk_dbus_init		(GpkDbus      *dbus);
+static void     gpk_dbus_finalize		(GObject	   *object);
+
+#define GPK_DBUS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPK_TYPE_DBUS, GpkDbusPrivate))
+
+struct GpkDbusPrivate
+{
+	GpkClient		*gclient;
+};
+
+G_DEFINE_TYPE (GpkDbus, gpk_dbus, G_TYPE_OBJECT)
+
+/**
+ * gpk_dbus_error_quark:
+ * Return value: Our personal error quark.
+ **/
+GQuark
+gpk_dbus_error_quark (void)
+{
+	static GQuark quark = 0;
+	if (!quark) {
+		quark = g_quark_from_static_string ("gpk_dbus_error");
+	}
+	return quark;
+}
+
+/**
+ * gpk_dbus_error_get_type:
+ **/
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+GType
+gpk_dbus_error_get_type (void)
+{
+	static GType etype = 0;
+
+	if (etype == 0) {
+		static const GEnumValue values[] =
+		{
+			ENUM_ENTRY (GPK_DBUS_ERROR_DENIED, "PermissionDenied"),
+			{ 0, NULL, NULL }
+		};
+		etype = g_enum_register_static ("GpkDbusError", values);
+	}
+	return etype;
+}
+
+/**
+ * gpk_dbus_install_local_file:
+ **/
+void
+gpk_dbus_install_local_file (GpkDbus *dbus, const gchar *full_path, DBusGMethodInvocation *context)
+{
+	gboolean ret;
+	GError *error;
+	GError *error_local;
+	gchar *sender;
+	gchar **full_paths;
+
+	g_return_if_fail (PK_IS_DBUS (dbus));
+
+	pk_debug ("InstallLocalFile method called: %s", full_path);
+
+	/* check sender */
+	sender = dbus_g_method_get_sender (context);
+	pk_warning ("sender=%s", sender);
+
+	/* just convert from char* to char** */
+	full_paths = g_strsplit (full_path, "|", 1);
+	ret = gpk_client_install_local_files (dbus->priv->gclient, full_paths, &error_local);
+	g_strfreev (full_paths);
+	if (!ret) {
+		error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_DENIED,
+				     "Method failed: %s", error_local->message);
+		g_error_free (error_local);
+		dbus_g_method_return_error (context, error);
+		return;
+	}
+
+	dbus_g_method_return (context);
+}
+
+/**
+ * gpk_dbus_install_provide_file:
+ **/
+void
+gpk_dbus_install_provide_file (GpkDbus *dbus, const gchar *full_path, DBusGMethodInvocation *context)
+{
+	gboolean ret;
+	GError *error;
+	GError *error_local;
+	gchar *sender;
+
+	g_return_if_fail (PK_IS_DBUS (dbus));
+
+	pk_debug ("InstallProvideFile method called: %s", full_path);
+
+	/* check sender */
+	sender = dbus_g_method_get_sender (context);
+	pk_warning ("sender=%s", sender);
+
+	ret = gpk_client_install_provide_file (dbus->priv->gclient, full_path, &error_local);
+	if (!ret) {
+		error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_DENIED,
+				     "Method failed: %s", error_local->message);
+		g_error_free (error_local);
+		dbus_g_method_return_error (context, error);
+		return;
+	}
+
+	dbus_g_method_return (context);
+}
+
+/**
+ * gpk_dbus_install_package_name:
+ **/
+void
+gpk_dbus_install_package_name (GpkDbus *dbus, const gchar *package_name, DBusGMethodInvocation *context)
+{
+	gboolean ret;
+	GError *error;
+	GError *error_local;
+	gchar *sender;
+	gchar **package_names;
+
+	g_return_if_fail (PK_IS_DBUS (dbus));
+
+	pk_debug ("InstallPackageName method called: %s", package_name);
+
+	/* check sender */
+	sender = dbus_g_method_get_sender (context);
+	pk_warning ("sender=%s", sender);
+
+	/* just convert from char* to char** */
+	package_names = g_strsplit (package_name, "|", 1);
+	ret = gpk_client_install_package_names (dbus->priv->gclient, package_names, &error_local);
+	g_strfreev (package_names);
+
+	if (!ret) {
+		error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_DENIED,
+				     "Method failed: %s", error_local->message);
+		g_error_free (error_local);
+		dbus_g_method_return_error (context, error);
+		return;
+	}
+
+	dbus_g_method_return (context);
+}
+
+/**
+ * gpk_dbus_install_mime_type:
+ **/
+void
+gpk_dbus_install_mime_type (GpkDbus *dbus, const gchar *mime_type, DBusGMethodInvocation *context)
+{
+	gboolean ret;
+	GError *error;
+	GError *error_local;
+	gchar *sender;
+
+	g_return_if_fail (PK_IS_DBUS (dbus));
+
+	pk_debug ("InstallmimeType method called: %s", mime_type);
+
+	/* check sender */
+	sender = dbus_g_method_get_sender (context);
+	pk_warning ("sender=%s", sender);
+
+	ret = gpk_client_install_mime_type (dbus->priv->gclient, mime_type, &error_local);
+	if (!ret) {
+		error = g_error_new (GPK_DBUS_ERROR, GPK_DBUS_ERROR_DENIED,
+				     "Method failed: %s", error_local->message);
+		g_error_free (error_local);
+		dbus_g_method_return_error (context, error);
+		return;
+	}
+
+	dbus_g_method_return (context);
+}
+
+/**
+ * gpk_dbus_class_init:
+ * @klass: The GpkDbusClass
+ **/
+static void
+gpk_dbus_class_init (GpkDbusClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = gpk_dbus_finalize;
+	g_type_class_add_private (klass, sizeof (GpkDbusPrivate));
+}
+
+/**
+ * gpk_dbus_init:
+ * @dbus: This class instance
+ **/
+static void
+gpk_dbus_init (GpkDbus *dbus)
+{
+	dbus->priv = GPK_DBUS_GET_PRIVATE (dbus);
+	dbus->priv->gclient = gpk_client_new ();
+}
+
+/**
+ * gpk_dbus_finalize:
+ * @object: The object to finalize
+ **/
+static void
+gpk_dbus_finalize (GObject *object)
+{
+	GpkDbus *dbus;
+	g_return_if_fail (PK_IS_DBUS (object));
+
+	dbus = GPK_DBUS (object);
+	g_return_if_fail (dbus->priv != NULL);
+	g_object_unref (dbus->priv->gclient);
+
+	G_OBJECT_CLASS (gpk_dbus_parent_class)->finalize (object);
+}
+
+/**
+ * gpk_dbus_new:
+ *
+ * Return value: a new GpkDbus object.
+ **/
+GpkDbus *
+gpk_dbus_new (void)
+{
+	GpkDbus *dbus;
+	dbus = g_object_new (GPK_TYPE_DBUS, NULL);
+	return GPK_DBUS (dbus);
+}
+
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef PK_BUILD_TESTS
+#include <libselftest.h>
+
+void
+libst_dbus (LibSelfTest *test)
+{
+	GpkDbus *dbus = NULL;
+	gboolean ret;
+	const gchar *temp;
+	GError *error = NULL;
+
+	if (libst_start (test, "GpkDbus", CLASS_AUTO) == FALSE) {
+		return;
+	}
+
+	/************************************************************/
+	libst_title (test, "get GpkDbus object");
+	dbus = gpk_dbus_new ();
+	if (dbus != NULL) {
+		libst_success (test, NULL);
+	} else {
+		libst_failed (test, NULL);
+	}
+
+	g_object_unref (dbus);
+
+	libst_end (test);
+}
+#endif
+

Added: trunk/src/gpk-dbus.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-dbus.h	Wed May  7 23:16:04 2008
@@ -0,0 +1,78 @@
+/* -*- 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_DBUS_H
+#define __GPK_DBUS_H
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+#define GPK_TYPE_DBUS		(gpk_dbus_get_type ())
+#define GPK_DBUS(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), GPK_TYPE_DBUS, GpkDbus))
+#define GPK_DBUS_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), GPK_TYPE_DBUS, GpkDbusClass))
+#define PK_IS_DBUS(o)	 	(G_TYPE_CHECK_INSTANCE_TYPE ((o), GPK_TYPE_DBUS))
+#define PK_IS_DBUS_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), GPK_TYPE_DBUS))
+#define GPK_DBUS_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GPK_TYPE_DBUS, GpkDbusClass))
+#define GPK_DBUS_ERROR		(gpk_dbus_error_quark ())
+#define GPK_DBUS_TYPE_ERROR	(gpk_dbus_error_get_type ())
+
+typedef struct GpkDbusPrivate GpkDbusPrivate;
+
+typedef struct
+{
+	 GObject		 parent;
+	 GpkDbusPrivate	*priv;
+} GpkDbus;
+
+typedef struct
+{
+	GObjectClass	parent_class;
+} GpkDbusClass;
+
+typedef enum
+{
+	GPK_DBUS_ERROR_DENIED,
+	GPK_DBUS_ERROR_LAST
+} GpkDbusError;
+
+GQuark		 gpk_dbus_error_quark			(void);
+GType		 gpk_dbus_error_get_type		(void) G_GNUC_CONST;
+GType		 gpk_dbus_get_type			(void) G_GNUC_CONST;
+GpkDbus		*gpk_dbus_new				(void);
+
+void		 gpk_dbus_install_local_file		(GpkDbus	*dbus,
+							 const gchar	*full_path,
+							 DBusGMethodInvocation *context);
+void		 gpk_dbus_install_provide_file		(GpkDbus	*dbus,
+							 const gchar	*full_path,
+							 DBusGMethodInvocation *context);
+void		 gpk_dbus_install_package_name		(GpkDbus	*dbus,
+							 const gchar	*package_name,
+							 DBusGMethodInvocation *context);
+void		 gpk_dbus_install_mime_type		(GpkDbus	*dbus,
+							 const gchar	*mime_type,
+							 DBusGMethodInvocation *context);
+
+G_END_DECLS
+
+#endif /* __GPK_DBUS_H */

Modified: trunk/src/gpk-install-local-file.c
==============================================================================
--- trunk/src/gpk-install-local-file.c	(original)
+++ trunk/src/gpk-install-local-file.c	Wed May  7 23:16:04 2008
@@ -42,6 +42,7 @@
 	gboolean verbose = FALSE;
 	GError *error;
 	GpkClient *gclient;
+	gchar **files;
 
 	const GOptionEntry options[] = {
 		{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
@@ -75,15 +76,12 @@
 				  _("You need to specify a file to install"), NULL);
 		return 1;
 	}
-	if (argc > 2) {
-		gpk_error_dialog (_("Failed to install local files"),
-				  _("You can only specify one file to install"), NULL);
-		return 1;
-	}
 
 	error = NULL;
 	gclient = gpk_client_new ();
-	ret = gpk_client_install_local_file (gclient, argv[1], NULL);
+	files = gpk_convert_argv_to_strv (argv);
+	ret = gpk_client_install_local_files (gclient, files, NULL);
+	g_strfreev (files);
 	g_object_unref (gclient);
 
 	return !ret;

Added: trunk/src/gpk-install-mime-type.c
==============================================================================
--- (empty file)
+++ trunk/src/gpk-install-mime-type.c	Wed May  7 23:16:04 2008
@@ -0,0 +1,90 @@
+/* -*- 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 <locale.h>
+
+#include <pk-debug.h>
+#include <gpk-common.h>
+#include <gpk-client.h>
+#include <gpk-error.h>
+
+/**
+ * main:
+ **/
+int
+main (int argc, char *argv[])
+{
+	GOptionContext *context;
+	gboolean ret;
+	gboolean verbose = FALSE;
+	GError *error;
+	GpkClient *gclient;
+
+	const GOptionEntry options[] = {
+		{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
+		  N_("Show extra debugging information"), NULL },
+		{ NULL}
+	};
+
+	setlocale (LC_ALL, "");
+
+	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	textdomain (GETTEXT_PACKAGE);
+
+	if (! g_thread_supported ()) {
+		g_thread_init (NULL);
+	}
+	g_type_init ();
+
+	g_set_application_name (_("PackageKit MimeType Installer"));
+	context = g_option_context_new ("gpk-install-mime-type");
+	g_option_context_set_summary (context, _("PackageKit MimeType Installer"));
+	g_option_context_add_main_entries (context, options, NULL);
+	g_option_context_parse (context, &argc, &argv, NULL);
+	g_option_context_free (context);
+
+	pk_debug_init (verbose);
+	gtk_init (&argc, &argv);
+
+	if (argc < 2) {
+		gpk_error_dialog (_("Failed to install file handler"),
+				  _("You need to specify a mime-type to install"), NULL);
+		return 1;
+	}
+	if (argc > 2) {
+		gpk_error_dialog (_("Failed to install file handler"),
+				  _("You can only specify one mime-type to install"), NULL);
+		return 1;
+	}
+
+	error = NULL;
+	gclient = gpk_client_new ();
+	ret = gpk_client_install_mime_type (gclient, argv[1], NULL);
+	g_object_unref (gclient);
+
+	return !ret;
+}

Modified: trunk/src/gpk-install-package-name.c
==============================================================================
--- trunk/src/gpk-install-package-name.c	(original)
+++ trunk/src/gpk-install-package-name.c	Wed May  7 23:16:04 2008
@@ -42,6 +42,7 @@
 	gboolean verbose = FALSE;
 	GError *error;
 	GpkClient *gclient;
+	gchar **packages;
 
 	const GOptionEntry options[] = {
 		{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
@@ -75,15 +76,12 @@
 				  _("You need to specify a package to install"), NULL);
 		return 1;
 	}
-	if (argc > 2) {
-		gpk_error_dialog (_("Failed to install packages from name"),
-				  _("You can only specify one package name to install"), NULL);
-		return 1;
-	}
 
 	error = NULL;
 	gclient = gpk_client_new ();
-	ret = gpk_client_install_package_name (gclient, argv[1], NULL);
+	packages = gpk_convert_argv_to_strv (argv);
+	ret = gpk_client_install_package_names (gclient, packages, NULL);
+	g_strfreev (packages);
 	g_object_unref (gclient);
 
 	return !ret;

Added: trunk/src/gpk-interface.h
==============================================================================
--- (empty file)
+++ trunk/src/gpk-interface.h	Wed May  7 23:16:04 2008
@@ -0,0 +1,120 @@
+/* Generated by dbus-binding-tool; do not edit! */
+
+
+#ifndef __dbus_glib_marshal_gpk_dbus_MARSHAL_H__
+#define __dbus_glib_marshal_gpk_dbus_MARSHAL_H__
+
+#include	<glib-object.h>
+
+G_BEGIN_DECLS
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v)     g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v)      g_value_get_int (v)
+#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
+#define g_marshal_value_peek_long(v)     g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
+#define g_marshal_value_peek_float(v)    g_value_get_float (v)
+#define g_marshal_value_peek_double(v)   g_value_get_double (v)
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v)    g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ *          Do not access GValues directly in your code. Instead, use the
+ *          g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
+#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
+#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* NONE:STRING,POINTER (/tmp/dbus-binding-tool-c-marshallers.UXU2AU:1) */
+extern void dbus_glib_marshal_gpk_dbus_VOID__STRING_POINTER (GClosure     *closure,
+                                                             GValue       *return_value,
+                                                             guint         n_param_values,
+                                                             const GValue *param_values,
+                                                             gpointer      invocation_hint,
+                                                             gpointer      marshal_data);
+void
+dbus_glib_marshal_gpk_dbus_VOID__STRING_POINTER (GClosure     *closure,
+                                                 GValue       *return_value G_GNUC_UNUSED,
+                                                 guint         n_param_values,
+                                                 const GValue *param_values,
+                                                 gpointer      invocation_hint G_GNUC_UNUSED,
+                                                 gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__STRING_POINTER) (gpointer     data1,
+                                                     gpointer     arg_1,
+                                                     gpointer     arg_2,
+                                                     gpointer     data2);
+  register GMarshalFunc_VOID__STRING_POINTER callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__STRING_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_string (param_values + 1),
+            g_marshal_value_peek_pointer (param_values + 2),
+            data2);
+}
+#define dbus_glib_marshal_gpk_dbus_NONE__STRING_POINTER	dbus_glib_marshal_gpk_dbus_VOID__STRING_POINTER
+
+G_END_DECLS
+
+#endif /* __dbus_glib_marshal_gpk_dbus_MARSHAL_H__ */
+
+#include <dbus/dbus-glib.h>
+static const DBusGMethodInfo dbus_glib_gpk_dbus_methods[] = {
+  { (GCallback) gpk_dbus_install_local_file, dbus_glib_marshal_gpk_dbus_NONE__STRING_POINTER, 0 },
+  { (GCallback) gpk_dbus_install_provide_file, dbus_glib_marshal_gpk_dbus_NONE__STRING_POINTER, 61 },
+  { (GCallback) gpk_dbus_install_package_name, dbus_glib_marshal_gpk_dbus_NONE__STRING_POINTER, 124 },
+  { (GCallback) gpk_dbus_install_mime_type, dbus_glib_marshal_gpk_dbus_NONE__STRING_POINTER, 190 },
+};
+
+const DBusGObjectInfo dbus_glib_gpk_dbus_object_info = {
+  0,
+  dbus_glib_gpk_dbus_methods,
+  4,
+"org.freedesktop.PackageKit\0InstallLocalFile\0A\0full_path\0I\0s\0\0org.freedesktop.PackageKit\0InstallProvideFile\0A\0full_path\0I\0s\0\0org.freedesktop.PackageKit\0InstallPackageName\0A\0package_name\0I\0s\0\0org.freedesktop.PackageKit\0InstallMimeType\0A\0mime_type\0I\0s\0\0\0",
+"\0",
+"\0"
+};
+

Modified: trunk/src/gpk-interface.xml
==============================================================================
--- trunk/src/gpk-interface.xml	(original)
+++ trunk/src/gpk-interface.xml	Wed May  7 23:16:04 2008
@@ -13,6 +13,10 @@
       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
       <arg type="s" name="package_name" direction="in"/>
     </method>
+    <method name="InstallMimeType">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg type="s" name="mime_type" direction="in"/>
+    </method>
   </interface>
 </node>
 

Modified: trunk/src/gpk-log.c
==============================================================================
--- trunk/src/gpk-log.c	(original)
+++ trunk/src/gpk-log.c	Wed May  7 23:16:04 2008
@@ -46,7 +46,7 @@
 static GtkListStore *list_store = NULL;
 static PkClient *client = NULL;
 static gchar *transaction_id = NULL;
-static PolKitGnomeAction *rollback_action = NULL;
+static PolKitGnomeAction *button_action = NULL;
 
 enum
 {
@@ -270,6 +270,42 @@
 }
 
 /**
+ * gpk_update_viewer_create_custom_widget:
+ **/
+static GtkWidget *
+gpk_update_viewer_create_custom_widget (GladeXML *xml, gchar *func_name, gchar *name,
+				        gchar *string1, gchar *string2,
+				        gint int1, gint int2, gpointer user_data)
+{
+	if (pk_strequal (name, "button_action")) {
+		return polkit_gnome_action_create_button (button_action);
+	}
+	pk_warning ("name unknown=%s", name);
+	return NULL;
+}
+
+/**
+ * gpk_update_viewer_setup_policykit:
+ *
+ * We have to do this before the glade stuff if done as the custom handler needs the actions setup
+ **/
+static void
+gpk_update_viewer_setup_policykit (void)
+{
+	PolKitAction *pk_action;
+	pk_action = polkit_action_new ();
+	polkit_action_set_action_id (pk_action, "org.freedesktop.packagekit.rollback");
+	button_action = polkit_gnome_action_new_default ("rollback", pk_action, _("_Rollback"), NULL);
+	g_object_set (button_action,
+		      "no-icon-name", "gtk-go-back-ltr",
+		      "auth-icon-name", "gtk-go-back-ltr",
+		      "yes-icon-name", "gtk-go-back-ltr",
+		      "self-blocked-icon-name", "gtk-go-back-ltr",
+		      NULL);
+	polkit_action_unref (pk_action);
+}
+
+/**
  * main:
  **/
 int
@@ -281,8 +317,6 @@
 	GtkWidget *widget;
 	GtkTreeSelection *selection;
 	PkRoleEnum roles;
-	PolKitAction *pk_action;
-	GtkWidget *button;
 	PkControl *control;
 
 	const GOptionEntry options[] = {
@@ -323,6 +357,12 @@
 	gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
                                            PK_DATA G_DIR_SEPARATOR_S "icons");
 
+	/* we have to do this before we connect up the glade file */
+	gpk_update_viewer_setup_policykit ();
+
+	/* use custom widgets */
+	glade_set_custom_handler (gpk_update_viewer_create_custom_widget, NULL);
+
 	client = pk_client_new ();
 	g_signal_connect (client, "transaction",
 			  G_CALLBACK (gpk_log_transaction_cb), NULL);
@@ -333,7 +373,7 @@
 	g_object_unref (control);
 
 	glade_xml = glade_xml_new (PK_DATA "/gpk-log.glade", NULL, NULL);
-	widget = glade_xml_get_widget (glade_xml, "window_transactions");
+	widget = glade_xml_get_widget (glade_xml, "window_simple");
 	gtk_window_set_icon_name (GTK_WINDOW (widget), "system-software-update");
 	gtk_widget_set_size_request (widget, 500, 400);
 
@@ -348,27 +388,14 @@
 	g_signal_connect (widget, "clicked",
 			  G_CALLBACK (gpk_log_button_help_cb), NULL);
 
-	pk_action = polkit_action_new ();
-	polkit_action_set_action_id (pk_action, "org.freedesktop.packagekit.rollback");
-	rollback_action = polkit_gnome_action_new_default ("rollback", pk_action, _("_Rollback"), NULL);
-	g_object_set (rollback_action,
-		      "no-icon-name", "gtk-go-back-ltr",
-		      "auth-icon-name", "gtk-go-back-ltr",
-		      "yes-icon-name", "gtk-go-back-ltr",
-		      "self-blocked-icon-name", "gtk-go-back-ltr",
-		      NULL);
-	polkit_action_unref (pk_action);
-	g_signal_connect (rollback_action, "activate", G_CALLBACK (gpk_log_button_rollback_cb), NULL);
-	button = polkit_gnome_action_create_button (rollback_action);
-	widget = glade_xml_get_widget (glade_xml, "buttonbox");
-        gtk_box_pack_start (GTK_BOX (widget), button, FALSE, FALSE, 0);
-        gtk_box_reorder_child (GTK_BOX (widget), button, 1);
+	/* connect up PolicyKit actions */
+	g_signal_connect (button_action, "activate", G_CALLBACK (gpk_log_button_rollback_cb), NULL);
 
 	/* hide the rollback button if we can't do the action */
 	if (pk_enums_contain (roles, PK_ROLE_ENUM_ROLLBACK)) {
-		polkit_gnome_action_set_visible (rollback_action, TRUE);
+		polkit_gnome_action_set_visible (button_action, TRUE);
 	} else {
-		polkit_gnome_action_set_visible (rollback_action, FALSE);
+		polkit_gnome_action_set_visible (button_action, FALSE);
 	}
 
 	/* create list stores */
@@ -376,7 +403,7 @@
 						 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
 
 	/* create transaction_id tree view */
-	widget = glade_xml_get_widget (glade_xml, "treeview_transactions");
+	widget = glade_xml_get_widget (glade_xml, "treeview_simple");
 	gtk_tree_view_set_model (GTK_TREE_VIEW (widget),
 				 GTK_TREE_MODEL (list_store));
 
@@ -392,7 +419,7 @@
 	pk_client_get_old_transactions (client, 0, NULL);
 
 	/* show */
-	widget = glade_xml_get_widget (glade_xml, "window_transactions");
+	widget = glade_xml_get_widget (glade_xml, "window_simple");
 	gtk_widget_show (widget);
 	gtk_main ();
 

Modified: trunk/src/gpk-prefs.c
==============================================================================
--- trunk/src/gpk-prefs.c	(original)
+++ trunk/src/gpk-prefs.c	Wed May  7 23:16:04 2008
@@ -121,7 +121,6 @@
 	const gchar *action;
 	PkUpdateEnum update = PK_UPDATE_ENUM_UNKNOWN;
 	GConfClient *client;
-	GtkWidget *check_widget;
 	GtkWidget *notify_widget;
 
 	client = gconf_client_get_default ();
@@ -130,19 +129,15 @@
 		pk_warning ("value NULL");
 		return;
 	}
-	check_widget = glade_xml_get_widget (glade_xml, "checkbutton_update_battery");
 	notify_widget = glade_xml_get_widget (glade_xml, "checkbutton_notify_updates");
 	if (strcmp (value, PK_UPDATE_ALL_TEXT) == 0) {
 		update = PK_UPDATE_ENUM_ALL;
-		gtk_widget_set_sensitive (check_widget, TRUE);
 		gtk_widget_set_sensitive (notify_widget, FALSE);
 	} else if (strcmp (value, PK_UPDATE_SECURITY_TEXT) == 0) {
 		update = PK_UPDATE_ENUM_SECURITY;
-		gtk_widget_set_sensitive (check_widget, TRUE);
 		gtk_widget_set_sensitive (notify_widget, TRUE);
 	} else if (strcmp (value, PK_UPDATE_NONE_TEXT) == 0) {
 		update = PK_UPDATE_ENUM_NONE;
-		gtk_widget_set_sensitive (check_widget, FALSE);
 		gtk_widget_set_sensitive (notify_widget, TRUE);
 	} else {
 		g_assert (FALSE);
@@ -325,9 +320,6 @@
 	widget = glade_xml_get_widget (glade_xml, "checkbutton_notify_completed");
 	pk_prefs_notify_checkbutton_setup (widget, GPK_CONF_NOTIFY_COMPLETED);
 
-	widget = glade_xml_get_widget (glade_xml, "checkbutton_update_battery");
-	pk_prefs_notify_checkbutton_setup (widget, GPK_CONF_UPDATE_BATTERY);
-
 	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");

Modified: trunk/src/gpk-update-viewer.c
==============================================================================
--- trunk/src/gpk-update-viewer.c	(original)
+++ trunk/src/gpk-update-viewer.c	Wed May  7 23:16:04 2008
@@ -109,7 +109,6 @@
 typedef enum {
 	PAGE_PREVIEW,
 	PAGE_DETAILS,
-	PAGE_PROGRESS,
 	PAGE_CONFIRM,
 	PAGE_LAST
 } PkPageEnum;
@@ -130,11 +129,24 @@
 static void
 pk_update_viewer_set_page (PkPageEnum page)
 {
-	GList *list, *l;
 	GtkWidget *widget;
-	GtkRequisition req;
+	GList *list, *l;
 	guint i;
 
+	widget = glade_xml_get_widget (glade_xml, "window_updates");
+	if (page == PAGE_LAST) {
+		gtk_widget_hide (widget);
+		return;
+	}
+
+	/* some pages are resizeable */
+	if (page == PAGE_DETAILS) {
+		gtk_window_set_resizable (GTK_WINDOW (widget), TRUE);
+	} else {
+		gtk_window_set_resizable (GTK_WINDOW (widget), FALSE);
+	}
+	gtk_widget_show (widget);
+
 	widget = glade_xml_get_widget (glade_xml, "hbox_hidden");
 	list = gtk_container_get_children (GTK_CONTAINER (widget));
 	for (l=list, i=0; l; l=l->next, i++) {
@@ -144,21 +156,6 @@
 			gtk_widget_hide (l->data);
 		}
 	}
-
-	/* some pages are resizeable */
-	widget = glade_xml_get_widget (glade_xml, "window_updates");
-	if (page == PAGE_DETAILS || page == PAGE_PROGRESS) {
-		gtk_window_set_resizable (GTK_WINDOW (widget), TRUE);
-		if (page == PAGE_PROGRESS) {
-			/* use the natural size unless it's really big */
-			gtk_widget_size_request (widget, &req);
-			gtk_window_resize (GTK_WINDOW (widget),
-				(req.width < 500) ? req.width : 500,
-				(req.height < 400) ? req.height : 400);
-		}
-	} else {
-		gtk_window_set_resizable (GTK_WINDOW (widget), FALSE);
-	}
 }
 
 /**
@@ -174,10 +171,9 @@
 	widget = glade_xml_get_widget (glade_xml, "button_overview2");
 	gtk_widget_hide (widget);
 
-	/* set correct view */
-//	pk_update_viewer_set_page (PAGE_PROGRESS);
-
+	pk_update_viewer_set_page (PAGE_LAST);
 	gpk_client_update_system (gclient, NULL);
+	pk_update_viewer_set_page (PAGE_CONFIRM);
 }
 
 /**
@@ -241,14 +237,12 @@
 		gtk_widget_show (widget);
 	}
 
-	pk_update_viewer_set_page (PAGE_LAST);
-
 	/* set correct view */
+	pk_update_viewer_set_page (PAGE_LAST);
 	package_ids = pk_package_ids_from_array (array);
 	gpk_client_update_packages (gclient, package_ids, NULL);
 	g_strfreev (package_ids);
-
-	pk_update_viewer_set_page (PAGE_PROGRESS);
+	pk_update_viewer_set_page (PAGE_CONFIRM);
 
 	/* get rid of the array, and free the contents */
 	g_ptr_array_free (array, TRUE);
@@ -508,29 +502,6 @@
 }
 
 /**
- * pk_update_viewer_button_cancel_cb:
- **/
-static void
-pk_update_viewer_button_cancel_cb (GtkWidget *widget, gpointer data)
-{
-	gboolean ret;
-	GError *error = NULL;
-
-	/* we might have a transaction running */
-	ret = pk_client_cancel (client_query, &error);
-	if (!ret) {
-		pk_warning ("failed to cancel client: %s", error->message);
-		g_error_free (error);
-		error = NULL;
-	}
-	ret = pk_client_cancel (client_action, &error);
-	if (!ret) {
-		pk_warning ("failed to cancel client: %s", error->message);
-		g_error_free (error);
-	}
-}
-
-/**
  * pk_update_viewer_button_close_and_cancel_cb:
  **/
 static void
@@ -724,7 +695,6 @@
 	gchar *text;
 	PkRoleEnum role;
 	const gchar *icon_name;
-	GtkWidget *widget;
 
 	pk_client_get_role (client, &role, NULL, NULL);
 	pk_debug ("role = %s, package = %s:%s:%s", pk_role_enum_to_text (role),
@@ -744,17 +714,6 @@
 		g_free (text);
 		return;
 	}
-
-	if (role == PK_ROLE_ENUM_UPDATE_SYSTEM ||
-	    role == PK_ROLE_ENUM_UPDATE_PACKAGES) {
-		text = gpk_package_id_format_twoline (package_id, summary);
-		widget = glade_xml_get_widget (glade_xml, "progress_package_label");
-		gtk_label_set_markup (GTK_LABEL (widget), text);
-
-		g_free (text);
-
-		return;
-	}
 }
 
 /**
@@ -924,12 +883,6 @@
 pk_update_viewer_status_changed_cb (PkClient *client, PkStatusEnum status, gpointer data)
 {
 	GtkWidget *widget;
-	gchar *text;
-
-	widget = glade_xml_get_widget (glade_xml, "progress_part_label");
-	text = g_strdup_printf ("<b>%s</b>", gpk_status_enum_to_localised_text (status));
-	gtk_label_set_markup (GTK_LABEL (widget), text);
-	g_free (text);
 
 	/* when we are testing the transaction, no package should be displayed */
 	if (status == PK_STATUS_ENUM_TEST_COMMIT) {
@@ -1374,17 +1327,6 @@
 }
 
 /**
- * pk_update_viewer_allow_cancel_cb:
- **/
-static void
-pk_update_viewer_allow_cancel_cb (PkClient *client, gboolean allow_cancel, gpointer data)
-{
-	GtkWidget *widget;
-	widget = glade_xml_get_widget (glade_xml, "button_cancel");
-	gtk_widget_set_sensitive (widget, allow_cancel);
-}
-
-/**
  * pk_update_viewer_preview_set_animation:
  **/
 static void
@@ -1818,8 +1760,6 @@
 			  G_CALLBACK (pk_update_viewer_status_changed_cb), NULL);
 	g_signal_connect (client_query, "error-code",
 			  G_CALLBACK (pk_update_viewer_error_code_cb), NULL);
-	g_signal_connect (client_query, "allow-cancel",
-			  G_CALLBACK (pk_update_viewer_allow_cancel_cb), NULL);
 
 	client_action = pk_client_new ();
 	pk_client_set_use_buffer (client_action, TRUE, NULL);
@@ -1833,8 +1773,6 @@
 			  G_CALLBACK (pk_update_viewer_status_changed_cb), NULL);
 	g_signal_connect (client_action, "error-code",
 			  G_CALLBACK (pk_update_viewer_error_code_cb), NULL);
-	g_signal_connect (client_action, "allow-cancel",
-			  G_CALLBACK (pk_update_viewer_allow_cancel_cb), NULL);
 
 	/* get actions */
 	roles = pk_control_get_actions (control);
@@ -1871,22 +1809,9 @@
 			  G_CALLBACK (pk_update_viewer_button_close_and_cancel_cb), NULL);
 
 	/* normal close buttons */
-	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_close4");
 	g_signal_connect_swapped (widget, "clicked", G_CALLBACK (gtk_main_quit), NULL);
 
-	/* cancel button */
-	widget = glade_xml_get_widget (glade_xml, "button_cancel");
-	g_signal_connect (widget, "clicked",
-			  G_CALLBACK (pk_update_viewer_button_cancel_cb), NULL);
-	gtk_widget_set_sensitive (widget, FALSE);
-
-	/* can we ever do the action? */
-	if (pk_enums_contain (roles, PK_ROLE_ENUM_CANCEL) == FALSE) {
-		gtk_widget_hide (widget);
-	}
-
 	/* connect up PolicyKit actions */
 	g_signal_connect (refresh_action, "activate",
 			  G_CALLBACK (pk_update_viewer_refresh_cb), NULL);
@@ -1988,12 +1913,6 @@
 	pk_update_update_last_refreshed_time ();
 	pk_update_update_last_updated_time ();
 
-	/* set the labels blank until we get a package */
-	widget = glade_xml_get_widget (glade_xml, "progress_part_label");
-	gtk_label_set_label (GTK_LABEL (widget), "");
-	widget = glade_xml_get_widget (glade_xml, "progress_package_label");
-	gtk_label_set_label (GTK_LABEL (widget), "");
-
 	/* we need to grey out all the buttons if we are in progress */
 	g_signal_connect (tlist, "changed",
 			  G_CALLBACK (pk_update_viewer_task_list_changed_cb), NULL);

Modified: trunk/src/gpk-watch.c
==============================================================================
--- trunk/src/gpk-watch.c	(original)
+++ trunk/src/gpk-watch.c	Wed May  7 23:16:04 2008
@@ -50,7 +50,7 @@
 
 #include "gpk-common.h"
 #include "gpk-watch.h"
-#include "gpk-progress.h"
+#include "gpk-client.h"
 #include "gpk-inhibit.h"
 #include "gpk-smart-icon.h"
 #include "gpk-consolekit.h"
@@ -280,7 +280,7 @@
 
 	/* show an icon if the user needs to reboot */
 	if (role == PK_ROLE_ENUM_UPDATE_PACKAGES ||
-	    role == PK_ROLE_ENUM_INSTALL_PACKAGE ||
+	    role == PK_ROLE_ENUM_INSTALL_PACKAGES ||
 	    role == PK_ROLE_ENUM_UPDATE_SYSTEM) {
 		restart = pk_client_get_require_restart (client);
 		if (restart == PK_RESTART_ENUM_SYSTEM ||
@@ -323,11 +323,11 @@
 		return;
 	}
 
-	if (role == PK_ROLE_ENUM_REMOVE_PACKAGE) {
+	if (role == PK_ROLE_ENUM_REMOVE_PACKAGES) {
 		package = gpk_package_get_name (package_id);
 		message = g_strdup_printf (_("Package '%s' has been removed"), package);
 		g_free (package);
-	} else if (role == PK_ROLE_ENUM_INSTALL_PACKAGE) {
+	} else if (role == PK_ROLE_ENUM_INSTALL_PACKAGES) {
 		package = gpk_package_get_name (package_id);
 		message = g_strdup_printf (_("Package '%s' has been installed"), package);
 		g_free (package);
@@ -632,11 +632,10 @@
  * pk_monitor_action_unref_cb:
  **/
 static void
-pk_monitor_action_unref_cb (GpkProgress *progress, GpkWatch *watch)
+pk_monitor_action_unref_cb (GpkClient *gclient, GpkWatch *watch)
 {
 	g_return_if_fail (GPK_IS_WATCH (watch));
-
-	g_object_unref (progress);
+	g_object_unref (gclient);
 }
 
 /**
@@ -646,18 +645,22 @@
 gpk_watch_menu_job_status_cb (GtkMenuItem *item, GpkWatch *watch)
 {
 	gchar *tid;
-	GpkProgress *progress = NULL;
+	GpkClient *gclient = NULL;
 
 	g_return_if_fail (GPK_IS_WATCH (watch));
 
 	/* find the job we should bind to */
 	tid = (gchar *) g_object_get_data (G_OBJECT (item), "tid");
+	if (pk_strzero(tid) || tid[0] != '/') {
+		pk_warning ("invalid job, maybe transaction already removed");
+		return;
+	}
 
 	/* launch the UI */
-	progress = gpk_progress_new ();
-	g_signal_connect (progress, "action-unref",
-			  G_CALLBACK (pk_monitor_action_unref_cb), watch);
-	gpk_progress_monitor_tid (progress, tid);
+	gclient = gpk_client_new ();
+	gpk_client_show_finished (gclient, FALSE);
+	g_signal_connect (gclient, "quit", G_CALLBACK (pk_monitor_action_unref_cb), watch);
+	gpk_client_monitor_tid (gclient, tid);
 }
 
 /**
@@ -707,7 +710,7 @@
 		/* add a job */
 		widget = gtk_image_menu_item_new_with_mnemonic (text);
 
-		/* we need the job ID so we know what GpkProgress to show */
+		/* we need the job ID so we know what transaction to show */
 		g_object_set_data (G_OBJECT (widget), "tid", (gpointer) item->tid);
 
 		image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);



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