Re: [rfc][patch] Add optional PackageKit hook to install new applications



For the record, we have a patch that does it in another way, maybe less
intrusive, by adding another tab to the “open with application…” dialog.

Of course, for now it uses gnome-app-install and synaptic, so the logic
would need to be rewritten for PackageKit.

Here it is if it interests anyone.

Cheers,
-- 
 .''`.
: :' :      We are debian.org. Lower your prices, surrender your code.
`. `'       We will add your hardware and software distinctiveness to
  `-        our own. Resistance is futile.
--- nautilus.old/libnautilus-private/nautilus-open-with-dialog.c.orig	2008-07-07 14:31:14.000000000 -0300
+++ nautilus/libnautilus-private/nautilus-open-with-dialog.c	2008-09-23 09:01:53.000000000 -0300
@@ -32,6 +32,7 @@
 #include <eel/eel-stock-dialogs.h>
 
 #include <string.h>
+#include <unistd.h>
 #include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
 #include <gio/gio.h>
@@ -39,18 +40,30 @@
 #define sure_string(s)                    ((const char *)((s)!=NULL?(s):""))
 #define DESKTOP_ENTRY_GROUP		  "Desktop Entry"
 
+#define APP_DESKTOP_DIR   "/usr/share/app-install/desktop"
+#define APP_INSTALLED_DIR "/usr/share/applications"
+#define APP_ICON_DIR      "/usr/share/app-install/icons"
+#define PACKAGE_FIELD     "X-AppInstall-Package"
+#define GKSU_PATH         "/usr/bin/gksu"
+#define SYNAPTIC_PATH     "/usr/sbin/synaptic"
+#define SYNAPTIC_DESKTOP  APP_INSTALLED_DIR "/synaptic.desktop"
+
 struct _NautilusOpenWithDialogDetails {
 	GAppInfo *selected_app_info;
+	char *selected_package;
 	
 	char *content_type;
 	char *extension;
 	char *type_description;
 
+	GtkWidget *notebook;
+
 	GtkWidget *label;
 	GtkWidget *entry;
 	GtkWidget *button;
 
 	GtkWidget *desc_label;
+	GtkWidget *desc_label2;
 
 	GtkWidget *open_label;
 
@@ -59,6 +72,11 @@
 	GSList	      *add_icon_paths;
 	gint	       add_items_idle_id;
 	gint	       add_icons_idle_id;
+
+	GtkWidget     *avail_program_list;
+	GtkListStore  *avail_program_list_store;
+	GSList        *add_icon_avail_paths;
+	gint           add_avail_items_idle_id;
 };
 
 enum {
@@ -71,6 +89,9 @@
         NUM_COLUMNS
 };
 
+#define COLUMN_PACKAGE COLUMN_EXEC
+#define COLUMN_PATH COLUMN_APP_INFO
+
 enum {
 	RESPONSE_OPEN
 };
@@ -98,6 +119,10 @@
 		g_source_remove (dialog->details->add_items_idle_id);
 	}
 
+	if (dialog->details->add_avail_items_idle_id) {
+		g_source_remove (dialog->details->add_avail_items_idle_id);
+	}
+
 	if (dialog->details->selected_app_info) {
 		g_object_unref (dialog->details->selected_app_info);
 	}
@@ -110,6 +135,15 @@
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static gint
+get_current_page (NautilusOpenWithDialog *dialog)
+{
+	if (dialog->details->notebook == NULL)
+		return 0;
+	else
+		return gtk_notebook_get_current_page (GTK_NOTEBOOK (dialog->details->notebook));
+}
+
 static void
 nautilus_open_with_dialog_destroy (GtkObject *object)
 {
@@ -267,6 +301,56 @@
 }
 
 static void
+synaptic_died_cb (GPid pid, gint status, gchar *filename)
+{
+	unlink (filename);
+	g_free (filename);
+}
+
+static void
+install_application (NautilusOpenWithDialog *dialog)
+{
+	GtkTreeSelection *selection;
+	GtkTreeModel     *model;
+	GtkTreeIter       iter;
+	gchar            *package;
+	gchar            *temp;
+	gchar            *filename;
+	GPid              pid;
+	gint              fd;
+	gchar            *args [] = { GKSU_PATH, "--desktop", SYNAPTIC_DESKTOP,
+	                              "--", SYNAPTIC_PATH, "--hide-main-window",
+	                              "--non-interactive", "-o", "Synaptic::closeZvt=true",
+	                              "--set-selections-file", NULL, NULL };
+
+	g_return_if_fail (dialog->details->avail_program_list != NULL);
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->details->avail_program_list));
+	if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+		return;
+	gtk_tree_model_get (model, &iter, COLUMN_PACKAGE, &package, -1);
+	if (!package)
+		return;
+
+	fd = g_file_open_tmp ("nautilus_synaptic_XXXXXX", &filename, NULL);
+	if (!fd) {
+		g_free (package);
+		return;
+	}
+	temp = g_strconcat (package, "\tinstall\n", NULL);
+	g_free (package);
+	write (fd, temp, strlen(temp));
+	close (fd);
+	g_free (temp);
+	args[10] = filename;
+	if (g_spawn_async (NULL, args, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
+	                   NULL, NULL, &pid, NULL)) {
+		g_child_watch_add (pid, (GChildWatchFunc) synaptic_died_cb, filename);
+	} else {
+		synaptic_died_cb (0, 0, filename);
+	}
+}
+
+static void
 emit_application_selected (NautilusOpenWithDialog *dialog,
 			   GAppInfo *application)
 {
@@ -283,7 +367,10 @@
 
 	switch (response_id) {
 	case RESPONSE_OPEN:
-		if (check_application (dialog)) {
+		if (get_current_page (dialog)) {
+			install_application (dialog);
+			gtk_widget_destroy (GTK_WIDGET (dialog));
+		} else if (check_application (dialog)) {
 			application = add_or_find_application (dialog);
 
 			if (application) {
@@ -412,9 +499,9 @@
 }
 
 static GdkPixbuf *
-get_pixbuf_for_icon (GIcon *icon)
+get_pixbuf_for_icon (GIcon *icon, gboolean use_app_icons)
 {
-	GdkPixbuf  *pixbuf;
+	GdkPixbuf  *pixbuf = NULL;
 	char *filename;
 
 	pixbuf = NULL;
@@ -425,24 +512,43 @@
 		}
 		g_free (filename);
 	} else if (G_IS_THEMED_ICON (icon)) {
-		const char * const *names;
-		char *icon_no_extension;
-		char *p;
-		
+		const char * const *names;		
 		names = g_themed_icon_get_names (G_THEMED_ICON (icon));
 		
 		if (names != NULL && names[0] != NULL) {
-			icon_no_extension = g_strdup (names[0]);
-			p = strrchr (icon_no_extension, '.');
-			if (p &&
-			    (strcmp (p, ".png") == 0 ||
-			     strcmp (p, ".xpm") == 0 ||
-			     strcmp (p, ".svg") == 0)) {
-				*p = 0;
+			if (use_app_icons) {
+				char *fullpath = g_build_filename (APP_ICON_DIR, names[0], NULL);
+				if (!strrchr (names[0], '.')) {
+					char *exts[] = { ".svg", ".png", ".xpm", NULL };
+					int i;
+					for (i=0; exts[i]; i++) {
+						char *fullpath2 = g_strconcat (fullpath, exts[i], NULL);
+						if (g_file_test (fullpath2, G_FILE_TEST_EXISTS)) {
+							g_free (fullpath);
+							fullpath = fullpath2;
+							break;
+						}
+						g_free (fullpath2);
+					}
+				}
+				pixbuf = gdk_pixbuf_new_from_file_at_size (fullpath, 24, 24, NULL);
+				g_free (fullpath);
+			}
+			if (pixbuf == NULL) {
+				char *icon_no_extension;
+				char *p;
+				icon_no_extension = g_strdup (names[0]);
+				p = strrchr (icon_no_extension, '.');
+				if (p &&
+				    (strcmp (p, ".png") == 0 ||
+				     strcmp (p, ".xpm") == 0 ||
+				     strcmp (p, ".svg") == 0)) {
+					*p = 0;
+				}
+				pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+								   icon_no_extension, 24, 0, NULL);
+				g_free (icon_no_extension);
 			}
-			pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
-							   icon_no_extension, 24, 0, NULL);
-			g_free (icon_no_extension);
 		}
 	}
 	return pixbuf;
@@ -456,20 +562,32 @@
 	GdkPixbuf    *pixbuf;
 	GIcon *icon;
 	gboolean      long_operation;
+	GtkListStore *store;
+	GSList      **paths;
+	gboolean      use_app_icons;
 
 	long_operation = FALSE;
 	do {
-		if (!dialog->details->add_icon_paths) {
+		if (!dialog->details->add_icon_paths && !dialog->details->add_icon_avail_paths) {
 			dialog->details->add_icons_idle_id = 0;
 			return FALSE;
 		}
 
-		path = dialog->details->add_icon_paths->data;
-		dialog->details->add_icon_paths->data = NULL;
-		dialog->details->add_icon_paths = g_slist_delete_link (dialog->details->add_icon_paths,
-								       dialog->details->add_icon_paths);
+		if (dialog->details->add_icon_paths) {
+			paths = &(dialog->details->add_icon_paths);
+			store = dialog->details->program_list_store;
+			use_app_icons = FALSE;
+		} else {
+			paths = &(dialog->details->add_icon_avail_paths);
+			store = dialog->details->avail_program_list_store;
+			use_app_icons = TRUE;
+		}
+
+		path = (*paths)->data;
+		(*paths)->data = NULL;
+		*paths = g_slist_delete_link (*paths, *paths);
 
-		if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (dialog->details->program_list_store),
+		if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (store),
 					      &iter, path)) {
 			gtk_tree_path_free (path);
 			continue;
@@ -477,17 +595,17 @@
 		
 		gtk_tree_path_free (path);
 
-		gtk_tree_model_get (GTK_TREE_MODEL (dialog->details->program_list_store), &iter,
+		gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
 				    COLUMN_GICON, &icon, -1);
 
 		if (icon == NULL) {
 			continue;
 		}
 
-		pixbuf = get_pixbuf_for_icon (icon);
+		pixbuf = get_pixbuf_for_icon (icon, use_app_icons);
 		if (pixbuf) {
 			long_operation = TRUE;
-			gtk_list_store_set (dialog->details->program_list_store, &iter, COLUMN_ICON, pixbuf, -1);
+			gtk_list_store_set (store, &iter, COLUMN_ICON, pixbuf, -1);
 			g_object_unref (pixbuf);
 		}
 		
@@ -563,6 +681,23 @@
 	}
 }
 
+static gint
+nautilus_open_with_sort_func (GtkTreeModel *model,
+                              GtkTreeIter *a,
+                              GtkTreeIter *b,
+                              gpointer data)
+{
+	gchar *name_a, *name_b;
+	gint retval;
+
+	gtk_tree_model_get (model, a, COLUMN_NAME, &name_a, -1);
+	gtk_tree_model_get (model, b, COLUMN_NAME, &name_b, -1);
+	retval = g_utf8_collate (name_a, name_b);
+
+	g_free (name_a);
+	g_free (name_b);
+	return retval;
+}
 
 
 static gboolean
@@ -645,39 +780,170 @@
 	return FALSE;
 }
 
+static gboolean
+nautilus_open_with_dialog_add_avail_items_idle (NautilusOpenWithDialog *dialog)
+{
+	GtkCellRenderer   *renderer;
+	GtkTreeViewColumn *column;
+	GDir              *dir;
+	const gchar       *filename;
+
+	if (dialog->details->content_type == NULL) {
+		/* Nothing to show anyway */
+		return FALSE;
+	}
+
+	/* create list store */
+	dialog->details->avail_program_list_store = gtk_list_store_new (NUM_COLUMNS,
+									G_TYPE_STRING,
+									GDK_TYPE_PIXBUF,
+									G_TYPE_ICON,
+									G_TYPE_STRING,
+									G_TYPE_STRING,
+									G_TYPE_STRING);
+
+	dir = g_dir_open (APP_DESKTOP_DIR, 0, NULL);
+	g_assert (dir != NULL);
+
+	while ((filename = g_dir_read_name (dir)) != NULL) {
+		gchar *absolute_name = g_build_filename (APP_DESKTOP_DIR, filename, NULL);
+		gchar *installed_name = g_build_filename (APP_INSTALLED_DIR, filename, NULL);
+		GKeyFile *key_file = g_key_file_new ();
+		gchar **mime_types;
+		/* FIXME : it would be MUCH better if g_desktop_app_info_new_from_keyfile existed */
+
+		if (!g_file_test (installed_name, G_FILE_TEST_EXISTS) &&
+		    g_key_file_load_from_file (key_file, absolute_name, G_KEY_FILE_NONE, NULL) &&
+		    (mime_types = g_key_file_get_string_list (key_file, G_KEY_FILE_DESKTOP_GROUP,
+		                                              G_KEY_FILE_DESKTOP_KEY_MIME_TYPE, NULL, NULL))) {
+			int i;
+			for (i = 0; mime_types[i]; i++) {
+				if (g_str_equal (mime_types[i], dialog->details->content_type)) {
+					GtkTreeIter iter;
+					GtkTreePath *path;
+					gchar *icon_file = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP,
+					                                          G_KEY_FILE_DESKTOP_KEY_ICON, NULL);
+					gchar *name = g_key_file_get_locale_string (key_file,
+					                                            G_KEY_FILE_DESKTOP_GROUP,
+					                                            G_KEY_FILE_DESKTOP_KEY_NAME,
+					                                            NULL, NULL);
+					gchar *comment = g_key_file_get_locale_string (key_file,
+					                                               G_KEY_FILE_DESKTOP_GROUP,
+					                                               G_KEY_FILE_DESKTOP_KEY_COMMENT,
+					                                               NULL, NULL);
+					gchar *package = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP,
+					                                        PACKAGE_FIELD, NULL);
+
+					gtk_list_store_append (dialog->details->avail_program_list_store, &iter);
+					gtk_list_store_set (dialog->details->avail_program_list_store, &iter,
+							    COLUMN_PATH,      absolute_name,
+							    COLUMN_ICON,      NULL,
+							    COLUMN_GICON,     g_themed_icon_new (icon_file),
+							    COLUMN_NAME,      name,
+							    COLUMN_COMMENT,   comment,
+							    COLUMN_PACKAGE,   package,
+							    -1);
+
+					g_free (icon_file);
+					g_free (name);
+					g_free (comment);
+					g_free (package);
+
+					path = gtk_tree_model_get_path (GTK_TREE_MODEL (dialog->details->avail_program_list_store), &iter);
+					if (path != NULL) {
+						dialog->details->add_icon_avail_paths = g_slist_prepend (dialog->details->add_icon_avail_paths, path);
+					}
+
+					break;
+				}
+			}
+			g_strfreev (mime_types);
+		}
+		g_key_file_free (key_file);
+		g_free (absolute_name);
+		g_free (installed_name);
+	}
+	g_dir_close (dir);
+
+	gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->details->avail_program_list), 
+	                         GTK_TREE_MODEL (dialog->details->avail_program_list_store));
+	gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (dialog->details->avail_program_list),
+	                                     nautilus_open_with_search_equal_func,
+	                                     NULL, NULL);
+	gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (dialog->details->avail_program_list_store), 0,
+	                                 nautilus_open_with_sort_func, NULL, NULL);
+	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (dialog->details->avail_program_list_store), 0,
+	                                      GTK_SORT_ASCENDING);
+
+	renderer = gtk_cell_renderer_pixbuf_new ();
+	column = gtk_tree_view_column_new ();
+	gtk_tree_view_column_pack_start (column, renderer, FALSE);
+	gtk_tree_view_column_set_attributes (column, renderer,
+	                                     "pixbuf", COLUMN_ICON,
+	                                     NULL);
+
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_pack_start (column, renderer, TRUE);
+	gtk_tree_view_column_set_attributes (column, renderer,
+	                                     "text", COLUMN_NAME,
+	                                     NULL);
+
+	gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->details->avail_program_list), column);
+
+	dialog->details->add_icon_avail_paths = g_slist_reverse (dialog->details->add_icon_avail_paths);
+
+	if (!dialog->details->add_icons_idle_id) {
+		dialog->details->add_icons_idle_id =
+			g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, (GSourceFunc) nautilus_open_with_dialog_add_icon_idle,
+			                 dialog, NULL);
+	}
+
+	dialog->details->add_avail_items_idle_id = 0;                   
+                 
+	return FALSE;
+}
+
 static void
 program_list_selection_changed (GtkTreeSelection  *selection,
 				NautilusOpenWithDialog *dialog)
 {
 	GtkTreeModel     *model;
 	GtkTreeIter       iter;
-	GAppInfo *info;
 		
 	if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
 		gtk_widget_set_sensitive (dialog->details->button, FALSE);
 		return;
 	}
 
-	info = NULL;
-	gtk_tree_model_get (model, &iter,
-			    COLUMN_APP_INFO, &info,
-			    -1);
-				  
-	if (info == NULL) {
-		return;
-	}
-
-	gtk_entry_set_text (GTK_ENTRY (dialog->details->entry),
-			    sure_string (g_app_info_get_executable (info)));
-	gtk_label_set_text (GTK_LABEL (dialog->details->desc_label),
-			    sure_string (g_app_info_get_description (info)));
 	gtk_widget_set_sensitive (dialog->details->button, TRUE);
 
-	if (dialog->details->selected_app_info) {
-		g_object_unref (dialog->details->selected_app_info);
+	if (get_current_page (dialog)) {
+		char *temp;
+		gtk_tree_model_get (model, &iter, COLUMN_COMMENT, &temp, -1);
+		gtk_label_set_text (GTK_LABEL (dialog->details->desc_label2), sure_string (temp));
+		g_free (temp);
+
+		gtk_tree_model_get (model, &iter, COLUMN_PACKAGE, &temp, -1);
+		g_free (dialog->details->selected_package);
+		dialog->details->selected_package = temp;
+	} else {
+		GAppInfo *info = NULL;
+		const char *exec = NULL;
+		const char *desc = NULL;
+		gtk_tree_model_get (model, COLUMN_APP_INFO, &info, -1);
+		if (info) {
+			exec = g_app_info_get_executable (info);
+			desc = g_app_info_get_description (info);
+		}
+
+		gtk_entry_set_text (GTK_ENTRY (dialog->details->entry), sure_string (exec));
+		gtk_label_set_text (GTK_LABEL (dialog->details->desc_label), sure_string (desc));
+
+		if (dialog->details->selected_app_info) {
+			g_object_unref (dialog->details->selected_app_info);
+		}
+		dialog->details->selected_app_info = info;
 	}
-	
-	dialog->details->selected_app_info = info;
 }
 
 static void
@@ -687,9 +953,15 @@
 				  NautilusOpenWithDialog *dialog)
 {
 	GtkTreeSelection *selection;
+	GtkTreeView *treeview;
+
+	if (get_current_page (dialog))
+		treeview = GTK_TREE_VIEW (dialog->details->avail_program_list);
+	else
+		treeview = GTK_TREE_VIEW (dialog->details->program_list);
 
 	/* update the entry with the info from the selection */
-	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->details->program_list));	
+	selection = gtk_tree_view_get_selection (treeview);	
 	program_list_selection_changed (selection, dialog);
 	
 	gtk_dialog_response (GTK_DIALOG (&dialog->parent), RESPONSE_OPEN);
@@ -711,16 +983,48 @@
 }
 
 static void
+tab_changed (GtkNotebook *notebook, GtkNotebookPage *page, gint index, NautilusOpenWithDialog *dialog)
+{
+	char *text;
+	GtkTreeView *treeview;
+
+	if (index) {
+		text = _("_Install");
+		treeview = GTK_TREE_VIEW (dialog->details->avail_program_list);
+	} else {
+		text = _("_Open");
+		treeview = GTK_TREE_VIEW (dialog->details->program_list);
+	}
+	gtk_label_set_text_with_mnemonic (GTK_LABEL(dialog->details->open_label), text);
+
+	gtk_widget_set_sensitive (dialog->details->button,
+	                          gtk_tree_selection_get_selected (gtk_tree_view_get_selection (treeview),
+	                                                           NULL, NULL));
+}
+
+static gboolean
+can_install_apps ()
+{
+	return g_file_test (APP_DESKTOP_DIR, G_FILE_TEST_IS_DIR) &&
+	       g_file_test (GKSU_PATH, G_FILE_TEST_IS_EXECUTABLE) &&
+	       g_file_test (SYNAPTIC_PATH, G_FILE_TEST_IS_EXECUTABLE);
+}
+
+
+static void
 nautilus_open_with_dialog_instance_init (NautilusOpenWithDialog *dialog)
 {
 	GtkWidget *hbox;
+	GtkWidget *vbox_out;
 	GtkWidget *vbox;
 	GtkWidget *vbox2;
-	GtkWidget *label;
+	GtkWidget *vbox3;
 	GtkWidget *align;
 	GtkWidget *scrolled_window;
+	GtkWidget *scrolled_window2;
 	GtkWidget *expander;
 	GtkTreeSelection *selection;
+	GtkTreeSelection *selection2;
 
 	dialog->details = g_new0 (NautilusOpenWithDialogDetails, 1);
 
@@ -732,6 +1036,8 @@
 
 	gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2);
 
+	vbox_out = gtk_vbox_new (FALSE, 6);
+
 	vbox = gtk_vbox_new (FALSE, 12);
 	gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
 
@@ -741,10 +1047,12 @@
 	dialog->details->label = gtk_label_new ("");
 	gtk_misc_set_alignment (GTK_MISC (dialog->details->label), 0.0, 0.5);
 	gtk_label_set_line_wrap (GTK_LABEL (dialog->details->label), TRUE);
-	gtk_box_pack_start (GTK_BOX (vbox2), dialog->details->label,
+	gtk_box_pack_start (GTK_BOX (vbox_out), dialog->details->label,
 			    FALSE, FALSE, 0);
 	gtk_widget_show (dialog->details->label);
 
+	if (can_install_apps ())
+		dialog->details->notebook = gtk_notebook_new ();
 
 	scrolled_window = gtk_scrolled_window_new (NULL, NULL);
 	gtk_widget_set_size_request (scrolled_window, 400, 300);
@@ -781,8 +1089,6 @@
 						     (GSourceFunc) nautilus_open_with_dialog_add_items_idle,
 						      dialog, NULL);
 
-	
-	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), vbox, TRUE, TRUE, 0);
 	gtk_widget_show_all (vbox);
 
 
@@ -809,6 +1115,60 @@
 	gtk_box_pack_start (GTK_BOX (hbox), dialog->details->button, FALSE, FALSE, 0);
 	gtk_widget_show (dialog->details->button);
 
+	if (dialog->details->notebook) {
+		gtk_box_pack_start (GTK_BOX (vbox_out), dialog->details->notebook, FALSE, FALSE, 0);
+		gtk_notebook_append_page (GTK_NOTEBOOK (dialog->details->notebook), vbox,
+		                          gtk_label_new_with_mnemonic (_("_Installed applications")));
+
+		vbox3 = gtk_vbox_new (FALSE, 6);
+
+		scrolled_window2 = gtk_scrolled_window_new (NULL, NULL);
+		gtk_widget_set_size_request (scrolled_window2, 400, 300);
+
+		gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window2),
+		                                     GTK_SHADOW_IN);
+		gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window2),
+		                                GTK_POLICY_AUTOMATIC,
+		                                GTK_POLICY_AUTOMATIC);
+		dialog->details->avail_program_list = gtk_tree_view_new ();
+		gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (dialog->details->avail_program_list),
+		                                   FALSE);
+		gtk_container_add (GTK_CONTAINER (scrolled_window2), dialog->details->avail_program_list);
+
+		gtk_box_pack_start (GTK_BOX (vbox3), scrolled_window2, TRUE, TRUE, 0);
+
+		dialog->details->desc_label2 = gtk_label_new (_("Select an application to view its description."));
+		gtk_misc_set_alignment (GTK_MISC (dialog->details->desc_label2), 0.0, 0.5);
+		gtk_label_set_justify (GTK_LABEL (dialog->details->desc_label2), GTK_JUSTIFY_LEFT);
+		gtk_label_set_line_wrap (GTK_LABEL (dialog->details->desc_label2), TRUE);
+		gtk_label_set_single_line_mode (GTK_LABEL (dialog->details->desc_label2), FALSE);
+		gtk_box_pack_start (GTK_BOX (vbox3), dialog->details->desc_label2, FALSE, FALSE, 0);
+
+		selection2 = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->details->avail_program_list));
+		gtk_tree_selection_set_mode (selection2, GTK_SELECTION_SINGLE);
+		g_signal_connect (selection2, "changed",
+		                  G_CALLBACK (program_list_selection_changed),
+		                  dialog);
+		g_signal_connect (dialog->details->avail_program_list, "row-activated",
+		                  G_CALLBACK (program_list_selection_activated),
+		                  dialog);
+
+		dialog->details->add_avail_items_idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+		                                                            (GSourceFunc) nautilus_open_with_dialog_add_avail_items_idle,
+		                                                            dialog, NULL);
+
+		gtk_widget_show (vbox3);
+		gtk_notebook_append_page (GTK_NOTEBOOK (dialog->details->notebook), vbox3,
+		                          gtk_label_new_with_mnemonic (_("_Available applications")));
+		gtk_widget_show (dialog->details->notebook);
+		g_signal_connect (dialog->details->notebook, "switch-page",
+		                  G_CALLBACK (tab_changed), dialog);
+	} else {
+		gtk_box_pack_start (GTK_BOX (vbox_out), vbox, FALSE, FALSE, 0);
+	}
+	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), vbox_out, TRUE, TRUE, 0);
+	gtk_widget_show_all (vbox_out);
+
 	gtk_dialog_add_button (GTK_DIALOG (dialog),
 			       GTK_STOCK_CANCEL,
 			       GTK_RESPONSE_CANCEL);
@@ -825,12 +1185,12 @@
 	hbox = gtk_hbox_new (FALSE, 2);
 	gtk_widget_show (hbox);
 
-	label = gtk_label_new_with_mnemonic (_("_Open"));
-	gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (dialog->details->button));
-	gtk_widget_show (label);
-	dialog->details->open_label = label;
+	dialog->details->open_label = gtk_label_new (NULL);
+	tab_changed (NULL, NULL, 0, dialog);
+	gtk_label_set_mnemonic_widget (GTK_LABEL (dialog->details->open_label), GTK_WIDGET (dialog->details->button));
+	gtk_widget_show (dialog->details->open_label);
 
-	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+	gtk_box_pack_start (GTK_BOX (hbox), dialog->details->open_label, FALSE, FALSE, 0);
 
 	align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
 	gtk_widget_show (align);
@@ -838,7 +1198,6 @@
 	gtk_widget_show (dialog->details->button);
 	GTK_WIDGET_SET_FLAGS (dialog->details->button, GTK_CAN_DEFAULT);
 
-
 	gtk_container_add (GTK_CONTAINER (align), hbox);
 	gtk_container_add (GTK_CONTAINER (dialog->details->button), align);
 

Attachment: signature.asc
Description: Ceci est une partie de message =?ISO-8859-1?Q?num=E9riquement?= =?ISO-8859-1?Q?_sign=E9e?=



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