? INSTALL
? install-sh
? missing
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/totem/ChangeLog,v
retrieving revision 1.1156
diff -p -u -r1.1156 ChangeLog
--- ChangeLog	12 Feb 2005 04:09:15 -0000	1.1156
+++ ChangeLog	13 Feb 2005 03:22:48 -0000
@@ -1,3 +1,21 @@
+2005-02-12  William Jon McCann  <mccann@jhu.edu>
+
+	* src/totem.c (totem_action_error, totem_action_error_and_exit) 
+	(totem_action_subsystem_error, totem_action_play_error) 
+	(totem_action_play, totem_action_seek, totem_action_load_media) 
+	(totem_action_set_mrl_with_warning, totem_action_seek_relative) 
+	(on_error_event, on_play_disc1_activate, on_help_activate) 
+	(on_take_screenshot1_activate, on_properties1_activate) 
+	(commit_hide_skip_to, video_widget_create, main): 
+	* src/totem-preferences.c (on_button1_clicked): 
+	* src/totem-interface.c (totem_interface_error_dialog) 
+	(totem_interface_error, totem_interface_error_blocking) 
+	(eel_str_middle_truncate, totem_format_uri_for_display) 
+	(totem_interface_load):
+	Rework error messages.  Add details expander to error dialog.
+	Put technical details of error messages under expander.
+	Make sure that long URIs don't create an unusable dialog.
+
 2005-02-11  William Jon McCann  <mccann@jhu.edu>
 
 	* src/totem.c (popup_timeout_remove) 
Index: src/totem-interface.c
===================================================================
RCS file: /cvs/gnome/totem/src/totem-interface.c,v
retrieving revision 1.3
diff -p -u -r1.3 totem-interface.c
--- src/totem-interface.c	8 Feb 2005 18:04:14 -0000	1.3
+++ src/totem-interface.c	13 Feb 2005 03:22:49 -0000
@@ -1,3 +1,4 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /* totem-interface.c
  *
  *  Copyright (C) 2005 Bastien Nocera
@@ -30,16 +31,21 @@
  */
 
 #include "config.h"
-
+#include <string.h>
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
+#include <libgnomevfs/gnome-vfs.h>
 
 #include "totem-interface.h"
 
+#define MAXIMUM_DISPLAYED_FILE_NAME_LENGTH 50
+
 static GtkWidget *
-totem_interface_error_dialog (const char *title, const char *reason,
-		GtkWindow *parent)
+totem_interface_error_dialog (const char *title,
+			      const char *reason,
+			      const char *details,
+			      GtkWindow  *parent)
 {
 	GtkWidget *error_dialog;
 
@@ -48,28 +54,63 @@ totem_interface_error_dialog (const char
 
 	error_dialog =
 		gtk_message_dialog_new (GTK_WINDOW (parent),
-				GTK_DIALOG_MODAL,
-				GTK_MESSAGE_ERROR,
-				GTK_BUTTONS_OK,
-				"%s", title);
+					GTK_DIALOG_MODAL,
+					GTK_MESSAGE_ERROR,
+					GTK_BUTTONS_OK,
+					"%s", title);
 	gtk_message_dialog_format_secondary_text
 		(GTK_MESSAGE_DIALOG (error_dialog), "%s", reason);
 
 	gtk_container_set_border_width (GTK_CONTAINER (error_dialog), 5);
+
+
+	if (details) {
+		GtkWidget    *hbox;
+		GtkWidget    *expander;
+		GtkWidget    *label;
+		GtkSizeGroup *group;
+
+		group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+		hbox = gtk_hbox_new (FALSE, 6);
+		gtk_box_pack_start (GTK_BOX (GTK_DIALOG (error_dialog)->vbox), hbox, FALSE, FALSE, 12);
+
+		label = gtk_label_new ("");
+		gtk_size_group_add_widget (group, GTK_MESSAGE_DIALOG (error_dialog)->image);
+		gtk_size_group_add_widget (group, label);
+
+		gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 6);
+
+		label = gtk_label_new (details);
+		gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+		gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+		gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+		expander = gtk_expander_new_with_mnemonic (_("Show more _details"));
+		gtk_expander_set_spacing (GTK_EXPANDER (expander), 6);
+
+		gtk_container_add (GTK_CONTAINER (expander), label);
+		gtk_box_pack_start (GTK_BOX (hbox), expander, FALSE, FALSE, 6);
+
+		gtk_widget_show_all (hbox);
+	}
+
 	gtk_dialog_set_default_response (GTK_DIALOG (error_dialog),
-			GTK_RESPONSE_OK);
+					 GTK_RESPONSE_OK);
+	gtk_window_set_title (GTK_WINDOW (error_dialog), "");
 	gtk_window_set_modal (GTK_WINDOW (error_dialog), TRUE);
 
 	return error_dialog;
 }
 
 void
-totem_interface_error (const char *title, const char *reason,
-		GtkWindow *parent)
+totem_interface_error (const char *title,
+		       const char *reason,
+		       const char *details,
+		       GtkWindow  *parent)
 {
 	GtkWidget *error_dialog;
 
-	error_dialog = totem_interface_error_dialog (title, reason, parent);
+	error_dialog = totem_interface_error_dialog (title, reason, details, parent);
 
 	g_signal_connect (G_OBJECT (error_dialog), "destroy", G_CALLBACK
 			(gtk_widget_destroy), error_dialog);
@@ -77,20 +118,82 @@ totem_interface_error (const char *title
 			(gtk_widget_destroy), error_dialog);
 	gtk_window_set_modal (GTK_WINDOW (error_dialog), TRUE);
 
-	gtk_widget_show (error_dialog);
+	gtk_widget_show_all (error_dialog);
 }
 
 void
-totem_interface_error_blocking (const char *title, const char *reason,
-		GtkWindow *parent)
+totem_interface_error_blocking (const char *title,
+				const char *reason,
+				const char *details,
+				GtkWindow  *parent)
 {
 	GtkWidget *error_dialog;
 
-	error_dialog = totem_interface_error_dialog (title, reason, parent);
+	error_dialog = totem_interface_error_dialog (title, reason, details, parent);
 
 	gtk_dialog_run (GTK_DIALOG (error_dialog));
 }
 
+/* taken from eel eel-string.c */
+static char *
+eel_str_middle_truncate (const char *string,
+			 guint truncate_length)
+{
+	char *truncated;
+	guint length;
+	guint num_left_chars;
+	guint num_right_chars;
+
+	const char delimter[] = "...";
+	const guint delimter_length = strlen (delimter);
+	const guint min_truncate_length = delimter_length + 2;
+
+	if (string == NULL) {
+		return NULL;
+	}
+
+	/* It doesnt make sense to truncate strings to less than
+	 * the size of the delimiter plus 2 characters (one on each
+	 * side)
+	 */
+	if (truncate_length < min_truncate_length) {
+		return g_strdup (string);
+	}
+
+	length = strlen (string);
+
+	/* Make sure the string is not already small enough. */
+	if (length <= truncate_length) {
+		return g_strdup (string);
+	}
+
+	/* Find the 'middle' where the truncation will occur. */
+	num_left_chars = (truncate_length - delimter_length) / 2;
+	num_right_chars = truncate_length - num_left_chars - delimter_length + 1;
+
+	truncated = g_new (char, truncate_length + 1);
+
+	strncpy (truncated, string, num_left_chars);
+	strncpy (truncated + num_left_chars, delimter, delimter_length);
+	strncpy (truncated + num_left_chars + delimter_length, string + length - num_right_chars + 1, num_right_chars);
+	
+	return truncated;
+}
+
+char *
+totem_format_uri_for_display (const char *uri)
+{
+	char *disp, *disp_truncated;
+
+	disp = gnome_vfs_format_uri_for_display (uri);
+        /* Truncate names for display since very long file names with no spaces
+         * in them won't get wrapped, and can create insanely wide dialog boxes.
+         */
+	disp_truncated = eel_str_middle_truncate (disp, MAXIMUM_DISPLAYED_FILE_NAME_LENGTH);
+	g_free (disp);
+	return disp_truncated;
+}
+
 GladeXML *
 totem_interface_load (const char *name, const char *display_name,
 		gboolean fatal, GtkWindow *parent)
@@ -111,9 +214,9 @@ totem_interface_load (const char *name, 
 
 		msg = g_strdup_printf (_("Couldn't load the '%s' interface."), display_name);
 		if (fatal == FALSE)
-			totem_interface_error (msg, _("Make sure that Totem is properly installed."), parent);
+			totem_interface_error (msg, _("Make sure that Totem is properly installed."), NULL, parent);
 		else
-			totem_interface_error_blocking (msg, _("Make sure that Totem is properly installed."), parent);
+			totem_interface_error_blocking (msg, _("Make sure that Totem is properly installed."), NULL, parent);
 
 		g_free (msg);
 		return NULL;
Index: src/totem-interface.h
===================================================================
RCS file: /cvs/gnome/totem/src/totem-interface.h,v
retrieving revision 1.1
diff -p -u -r1.1 totem-interface.h
--- src/totem-interface.h	12 Jan 2005 17:56:46 -0000	1.1
+++ src/totem-interface.h	13 Feb 2005 03:22:49 -0000
@@ -35,11 +35,14 @@ GladeXML	*totem_interface_load		(const c
 						 gboolean fatal,
 						 GtkWindow *parent);
 void		 totem_interface_error		(const char *title,
-						 const char *reason,
-						 GtkWindow *parent);
+                                                 const char *reason,
+                                                 const char *details,
+                                                 GtkWindow  *parent);
 void		 totem_interface_error_blocking	(const char *title,
 						 const char *reason,
+						 const char *details,
 						 GtkWindow *parent);
+char *		 totem_format_uri_for_display	(const char *uri);
 
 G_END_DECLS
 
Index: src/totem-preferences.c
===================================================================
RCS file: /cvs/gnome/totem/src/totem-preferences.c,v
retrieving revision 1.52
diff -p -u -r1.52 totem-preferences.c
--- src/totem-preferences.c	8 Feb 2005 18:04:14 -0000	1.52
+++ src/totem-preferences.c	13 Feb 2005 03:22:49 -0000
@@ -309,17 +309,17 @@ on_button1_clicked (GtkButton *button, T
 	path = g_build_path (G_DIR_SEPARATOR_S,
 			g_get_home_dir (), PROPRIETARY_PLUGINS, NULL);
 
-	if ((g_getenv ("KDE_STARTUP_ENV") || g_getenv("KDE_FULL_SESSION")) && (filemanager = g_find_program_in_path("konqueror"))) {
+	if ((g_getenv ("KDE_STARTUP_ENV") || g_getenv ("KDE_FULL_SESSION")) && (filemanager = g_find_program_in_path ("konqueror"))) {
 		cmd = g_strconcat (filemanager, " ", path, NULL);
 		g_free (filemanager);
 	} else {
-		cmd = g_strdup_printf ("nautilus --no-default-window -no-desktop %s", path);
+		cmd = g_strdup_printf ("nautilusa --no-default-window -no-desktop %s", path);
 	}
 	g_free (path);
 
 	if (g_spawn_command_line_async (cmd, &err) == FALSE)
 	{
-		totem_action_error (_("Totem could not start the file manager."), err->message, totem);
+		totem_action_error (_("Could not open the plugins location"), _("The plugins location could not be opened because the file manager could not be started.  Please verify that the system is configured correctly."), err->message, totem);
 		g_error_free (err);
 	}
 
Index: src/totem.c
===================================================================
RCS file: /cvs/gnome/totem/src/totem.c,v
retrieving revision 1.406
diff -p -u -r1.406 totem.c
--- src/totem.c	12 Feb 2005 04:09:16 -0000	1.406
+++ src/totem.c	13 Feb 2005 03:22:51 -0000
@@ -119,18 +119,19 @@ long_action (void)
 }
 
 void
-totem_action_error (const char *title, const char *reason, Totem *totem)
+totem_action_error (const char *title, const char *reason, const char *details, Totem *totem)
 {
-	totem_interface_error (title, reason,
-			GTK_WINDOW (totem->win));
+	totem_interface_error (title, reason, details, GTK_WINDOW (totem->win));
 }
 
 static void
 totem_action_error_and_exit (const char *title,
-		const char *reason, Totem *totem)
+			     const char *reason,
+			     const char *details,
+			     Totem *totem)
 {
-	totem_interface_error_blocking (title, reason,
-			GTK_WINDOW (totem->win));
+	totem_interface_error_blocking (title, reason, details,
+					GTK_WINDOW (totem->win));
 	totem_action_exit (totem);
 }
 
@@ -267,6 +268,19 @@ play_pause_set_label (Totem *totem, Tote
 }
 
 static void
+totem_action_subsystem_error (Totem      *totem,
+			      const char *msg,
+			      const char *reason,
+			      GError     *err)
+{
+	char *detail;
+
+	detail = g_strdup_printf (_("The system has given the following reason for the error:\n%s"), err->message);
+	totem_action_error (msg, reason, detail, totem);
+	g_free (detail);
+}
+
+static void
 totem_action_eject (Totem *totem)
 {
 	GError *err = NULL;
@@ -284,12 +298,25 @@ totem_action_eject (Totem *totem)
 			(totem->gc, GCONF_PREFIX"/mediadev", NULL));
 	if (g_spawn_command_line_sync (cmd, NULL, NULL, NULL, &err) == FALSE)
 	{
-		totem_action_error (_("Totem could not eject the optical media."), err->message, totem);
+		totem_action_subsystem_error (totem, _("Could not eject the disc"), _("The system was unable to eject the audio/video disc."), err);
 		g_error_free (err);
 	}
 	g_free (cmd);
 }
 
+static void
+totem_action_play_error (Totem  *totem,
+			 GError *err)
+{
+	char *disp, *reason;
+
+	disp = totem_format_uri_for_display (totem->mrl);
+	reason = g_strdup_printf (_("An error occurred while attempting to play '%s'."), disp);
+	totem_action_subsystem_error (totem, _("Could not play media"), reason, err);
+	g_free (reason);
+	g_free (disp);
+}
+
 void
 totem_action_play (Totem *totem)
 {
@@ -303,16 +330,10 @@ totem_action_play (Totem *totem)
 	play_pause_set_label (totem, retval ? STATE_PLAYING : STATE_STOPPED);
 	if (retval == FALSE)
 	{
-		char *msg, *disp;
-
-		disp = gnome_vfs_unescape_string_for_display (totem->mrl);
-		msg = g_strdup_printf(_("Totem could not play '%s'."), disp);
-		g_free (disp);
-
 		totem_playlist_set_playing (totem->playlist, FALSE);
-		totem_action_error (msg, err->message, totem);
+		totem_action_play_error (totem, err);
 		totem_action_stop (totem);
-		g_free (msg);
+
 		g_error_free (err);
 	}
 }
@@ -330,16 +351,10 @@ totem_action_seek (Totem *totem, double 
 
 	if (retval == FALSE)
 	{
-		char *msg, *disp;
-
-		disp = gnome_vfs_unescape_string_for_display (totem->mrl);
-		msg = g_strdup_printf(_("Totem could not play '%s'."), disp);
-		g_free (disp);
-
 		totem_playlist_set_playing (totem->playlist, FALSE);
-		totem_action_error (msg, err->message, totem);
+		totem_action_play_error (totem, err);
 		totem_action_stop (totem);
-		g_free (msg);
+
 		g_error_free (err);
 	}
 }
@@ -359,8 +374,8 @@ totem_action_load_media (Totem *totem, M
 
 	if (bacon_video_widget_can_play (totem->bvw, type) == FALSE)
 	{
-		msg = g_strdup_printf (_("Totem cannot play this type of media (%s) because you do not have the appropriate plugins to handle it."), _(totem_cd_get_human_readable_name (type)));
-		totem_action_error (msg, _("Please install the necessary plugins and restart Totem to be able to play this media."), totem);
+		msg = g_strdup_printf (_("Unable to play this type of media (%s)"), _(totem_cd_get_human_readable_name (type)));
+		totem_action_error (msg, _("Additional plugins are required to play media of this type.  Please install the necessary plugins and restart the program to continue."), NULL, totem);
 		g_free (msg);
 		return FALSE;
 	}
@@ -368,8 +383,8 @@ totem_action_load_media (Totem *totem, M
 	mrls = bacon_video_widget_get_mrls (totem->bvw, type);
 	if (mrls == NULL)
 	{
-		msg = g_strdup_printf (_("Totem could not play this media (%s) although a plugin is present to handle it."), _(totem_cd_get_human_readable_name (type)));
-		totem_action_error (msg, _("You might want to check that a disc is present in the drive and that it is correctly configured."), totem);
+		msg = g_strdup_printf (_("Could not play this media (%s)"), _(totem_cd_get_human_readable_name (type)));
+		totem_action_error (msg, _("This media could not be played even though the appropriate plugins are installed.  Please check that a disc is present in the drive and that it is correctly configured."), NULL, totem);
 		g_free (msg);
 		return FALSE;
 	}
@@ -694,13 +709,7 @@ totem_action_set_mrl_with_warning (Totem
 
 		if (retval == FALSE && warn != FALSE)
 		{
-			char *msg, *disp;
-
-			disp = gnome_vfs_unescape_string_for_display (totem->mrl);
-			msg = g_strdup_printf(_("Totem could not play '%s'."), disp);
-			g_free (disp);
-			totem_action_error (msg, err->message, totem);
-			g_free (msg);
+			totem_action_play_error (totem, err);
 		}
 
 		if (retval == FALSE)
@@ -799,16 +808,10 @@ totem_action_seek_relative (Totem *totem
 
 	if (err != NULL)
 	{
-		char *msg, *disp;
-
-		disp = gnome_vfs_unescape_string_for_display (totem->mrl);
-		msg = g_strdup_printf(_("Totem could not play '%s'."), totem->mrl);
-		g_free (disp);
-
 		totem_playlist_set_playing (totem->playlist, FALSE);
 		totem_action_stop (totem);
-		totem_action_error (msg, err->message, totem);
-		g_free (msg);
+		totem_action_play_error (totem, err);
+
 		g_error_free (err);
 	}
 }
@@ -1142,10 +1145,9 @@ on_error_event (BaconVideoWidget *bvw, c
 		play_pause_set_label (totem, STATE_STOPPED);
 
 	if (fatal == FALSE) {
-		totem_action_error (_("An error occured"), message, totem);
+		totem_action_error (_("An error has occured"), message, NULL, totem);
 	} else {
-		totem_action_error_and_exit (_("An error occured"),
-				message, totem);
+		totem_action_error_and_exit (_("An error has occured"), message, NULL, totem);
 	}
 }
 
@@ -1593,8 +1595,9 @@ on_play_disc1_activate (GtkButton *butto
 	type = totem_cd_detect_type (device, &error);
 	switch (type) {
 		case MEDIA_TYPE_ERROR:
-			totem_action_error ("Failed to play Audio/Video Disc",
-					    error ? error->message : "Reason unknown",
+			totem_action_error (_("Could not play audio/video disc"),
+					    error ? error->message : _("Playing failed for an unknown reason."),
+					    NULL,
 					    totem);
 			return;
 		case MEDIA_TYPE_DATA:
@@ -1842,7 +1845,7 @@ on_help_activate (GtkButton *button, Tot
 
 	if (gnome_help_display ("totem.xml", NULL, &err) == FALSE)
 	{
-		totem_action_error (_("Totem could not display the help contents."), err->message, totem);
+		totem_action_error (_("Could not display the help contents"), err->message, NULL, totem);
 		g_error_free (err);
 	}
 }
@@ -1924,7 +1927,7 @@ on_take_screenshot1_activate (GtkButton 
 		if (err == NULL)
 			return;
 
-		totem_action_error (_("Totem could not get a screenshot of that film."), err->message, totem);
+		totem_action_error (_("Could not take a screenshot"), err->message, NULL, totem);
 		g_error_free (err);
 		return;
 	}
@@ -1932,7 +1935,7 @@ on_take_screenshot1_activate (GtkButton 
 	pixbuf = bacon_video_widget_get_current_frame (totem->bvw);
 	if (pixbuf == NULL)
 	{
-		totem_action_error (_("Totem could not get a screenshot of that film."), _("Please file a bug, this isn't supposed to happen."), totem);
+		totem_action_error (_("Could not take a screenshot"), _("Please file a bug, this isn't supposed to happen."), NULL, totem);
 		return;
 	}
 
@@ -1959,7 +1962,7 @@ on_properties1_activate (GtkButton *butt
 
 	if (totem->properties == NULL)
 	{
-		totem_action_error (_("Totem couldn't show the movie properties window."), _("Make sure that Totem is correctly installed."), totem);
+		totem_action_error (_("Couldn't display the media properties"), _("Make verify that the program is installed correctly."), NULL, totem);
 		return;
 	}
 
@@ -2042,15 +2045,10 @@ commit_hide_skip_to (GtkDialog *dialog, 
 
 	if (err != NULL)
 	{
-		char *msg, *disp;
-
-		disp = gnome_vfs_unescape_string_for_display (totem->mrl);
-		msg = g_strdup_printf(_("Totem could not seek in '%s'."), disp);
-		g_free (disp);
 		totem_action_stop (totem);
 		totem_playlist_set_playing (totem->playlist, FALSE);
-		totem_action_error (msg, err->message, totem);
-		g_free (msg);
+		totem_action_subsystem_error (totem, _("Could not go to position"), _("The program was unable to go to the requested position in the media stream."), err);
+
 		g_error_free (err);
 	}
 }
@@ -3205,7 +3203,7 @@ video_widget_create (Totem *totem) 
 
 		gtk_widget_hide (totem->win);
 
-		totem_action_error_and_exit (_("Totem could not startup."), err != NULL ? err->message : _("No reason."), totem);
+		totem_action_error_and_exit (_("Could not start the program"), _("The program has encountered a problem and is unable to start.  Please verify that another program is not exclusively using an audio or video device."), err != NULL ? err->message : NULL, totem);
 		if (err != NULL)
 			g_error_free (err);
 	}
@@ -3386,7 +3384,7 @@ main (int argc, char **argv)
 	if (XInitThreads () == 0)
 	{
 		gtk_init (&argc, &argv);
-		totem_action_error_and_exit (_("Could not initialise the thread-safe libraries."), _("Verify your system installation. Totem will now exit."), NULL);
+		totem_action_error_and_exit (_("Could not start the program"), _("The program was unable to initialize properly.  Please verify that the system is configured correctly."), _("Could not initialize the thread-safe libraries"), NULL);
 	}
 
 	g_thread_init (NULL);
@@ -3407,7 +3405,7 @@ main (int argc, char **argv)
 
 	if ((gc = gconf_client_get_default ()) == NULL)
 	{
-		totem_action_error_and_exit (_("Totem couln't initialise the configuration engine."), _("Make sure that GNOME is properly installed."), NULL);
+		totem_action_error_and_exit (_("Could not start the program"), _("The program was unable to initialize properly.  Please verify that the system is configured properly."), _("Could not initialize the configuration engine"), NULL);
 	}
 
 #ifndef HAVE_GTK_ONLY
Index: src/totem.h
===================================================================
RCS file: /cvs/gnome/totem/src/totem.h,v
retrieving revision 1.19
diff -p -u -r1.19 totem.h
--- src/totem.h	8 Feb 2005 18:04:14 -0000	1.19
+++ src/totem.h	13 Feb 2005 03:22:51 -0000
@@ -61,8 +61,9 @@ int	totem_action_get_aspect_ratio		(Tote
 void	totem_action_toggle_controls		(Totem *totem);
 
 void	totem_action_set_scale_ratio		(Totem *totem, gfloat ratio);
-void    totem_action_error                      (const char *title,
+void    totem_action_error			(const char *title,
 						 const char *reason,
+						 const char *details,
 						 Totem *totem);
 
 GtkWidget * totem_statusbar_create (void);
