[patch] provde better feedback to users during transforms

Douglas Burke <[email protected]>
Newsgroups gmane.editors.conglomerate.devel
Message-ID <Pine.GSO.4.58.0410141545060.12709@lagado>
The attached patch makes several changes to improve the user-experience
when calling the Export menu:

 - the cursor is set to "busy" during an actual transform; the dialog is
   now destroyed before the transform (partly due to issues in finding the
   windows to set the busy cursor in).
 - when docbook transforms are finished (at least for HTML and XSL:FO), an
   informational window is displayed letting the user know they succeeded
 - clean up to some error dialogs; added an error dialog for the case
   when the DocBook stylesheet can not be resolved (presumably due to a
   catalog error/inconsistency)

The changes hopefully make a docbook-exporters life a bit easier, since
there's more feedback on what is/isn't happening. However, I think we
really need a more visible means of tracking the progress of a transform
(and, in an ideal world, aborting a transform). The "export to PDF" option
kind of does this, so should we be using this technique for all
time-intensive processes?

The patch also includes a commented-out piece of code in which I was
going to list the attributes sent to a stylesheet when telling the user
there was a failure applying the stylesheet (look for the string
SILLY_IDEA). Although I think it may be useful information to include in
an error report, I came to the conclusion my approach wasn't the way to do
it.

Doug
cong.diff (text/plain, 24.2 KB)
Index: src/ChangeLog
===================================================================
RCS file: /cvs/gnome/conglomerate/src/ChangeLog,v
retrieving revision 1.732
diff -u -r1.732 ChangeLog
--- src/ChangeLog	14 Oct 2004 01:04:44 -0000	1.732
+++ src/ChangeLog	14 Oct 2004 19:42:52 -0000
@@ -1,3 +1,30 @@
+2004-10-14  Douglas Burke  <[email protected]>
+
+	* cong-plugin.c, cong-plugin.h:
+
+	During cong_ui_transform_doc() the cursor of all the primary windows
+	will be set to GDK_WATCH whilst the transform is taking place.
+
+	Minor clean up to error dialogs that appeared when stylesheets could
+	not be found or applied.
+	
+	cong_ui_transform_doc_to_uri() now returns a gboolean indicating
+	whether the transform was successfull.
+
+	* cong-file-export.c:
+
+	cong_ui_hook_file_export() now destroys the dialog before calling the
+	transform, to avoid a "hung" dialog window and because the cursor change
+	in cong_ui_transform_doc() (to a busy cursor) only happens for primary
+	windows and not dialogs. The case of a user selecting an exporter but
+	not a filename is now handled.
+	
+	* plugin-docbook.c:
+
+	Let the user know, via an informational window, that a transform
+	(i.e. exporter) has succeeded. Provide feedback - via dialogs - when
+	Conglomerate is unable to locate the DocBook stylesheets.
+
 2004-10-13  David Malcolm  <[email protected]>
 
 	* cong-dispspec-element.c, cong-dispspec-element.h, cong-dispspec-element-gxx.h: 
Index: src/cong-file-export.c
===================================================================
RCS file: /cvs/gnome/conglomerate/src/cong-file-export.c,v
retrieving revision 1.22
diff -u -r1.22 cong-file-export.c
--- src/cong-file-export.c	13 Oct 2004 19:57:33 -0000	1.22
+++ src/cong-file-export.c	14 Oct 2004 19:42:52 -0000
@@ -364,7 +364,7 @@
 					    "dialog_details");
 	g_assert (dialog_details);
 
-	if ( dialog_details->combo_array )
+	if (dialog_details->combo_array)
 		g_ptr_array_free (dialog_details->combo_array, FALSE);
 
 	gtk_widget_destroy (dialog);
@@ -376,15 +376,32 @@
  * @doc:
  * @toplevel_window:
  *
- * TODO: Write me
+ * Convert the document (@doc) to a different format. A dialog is
+ * displayed that lists all the registered exporters for this document
+ * type. If the user does not cancel then we check to see if a
+ * filename was given; if it was not the user is returned to the
+ * dialog, otherwise the chosen exporter is called.
+ *
+ * Open issues include:
+ * how to inform the user of what is going on, and
+ * whether we allow the user to stop an exporter whilst it is
+ * processing.
+ *
+ * At the moment the "Export" menu item can be called when there are
+ * no exporters registered for the document. We really should make the
+ * menu item insensitive in this situation to avoid this situation.
+ * (this is already pointed out in action_callback_file_export in
+ *  cong-menus.c)
  */
 void
 cong_ui_hook_file_export (CongDocument *doc,
 			  GtkWindow *toplevel_window)
 {
 	GtkWidget *dialog;
-	gint result;
 	CongExportDialogDetails *dialog_details;
+	CongServiceExporter* exporter = NULL;
+	gchar *export_uri = NULL;
+	gint flag = 1;
 
 	g_return_if_fail(doc);
 
@@ -395,55 +412,91 @@
 					    "dialog_details");
 	g_assert(dialog_details);
 
-	if (dialog_details->got_any_exporters) {
-		gtk_widget_show_all(dialog);
-
-		result = gtk_dialog_run(GTK_DIALOG(dialog));
+	/*
+	 * Temporary until we disable the Export menu item for
+	 * documents with no registered exporterd
+	 */
+	if (dialog_details->got_any_exporters==FALSE) {
+		GtkDialog* error_dialog;
+		gchar *what_failed;
+
+		cong_document_export_dialog_delete (dialog);
+
+		what_failed = g_strdup_printf (_("Conglomerate cannot export \"%s\""),
+					       cong_document_get_filename(doc));
+		error_dialog = cong_error_dialog_new (toplevel_window,
+						      what_failed, 
+						      _("None of Conglomerate's plugins know how to export files of this type."),
+						      "");
+
+		gtk_dialog_run (error_dialog);
+		gtk_widget_destroy (GTK_WIDGET(error_dialog));
+		g_free (what_failed);
+		return;
+	}
 
+	gtk_widget_show_all (dialog);
 
-		switch (result) {
-		default: /* Do nothing; dialog was cancelled */
-			break;
-			
-		case GTK_RESPONSE_OK:
-			{
-				CongServiceExporter* exporter;
-				
-				/* Which plugin has been selected? */
-				exporter = get_selected_exporter(dialog_details);
-				if (exporter) {
-					gchar *export_uri = cong_exporter_get_preferred_uri(exporter);
-					g_message("Exporter invoked: \"%s\" to \"%s\"", cong_service_get_name(CONG_SERVICE(exporter)), export_uri);
-					
-					cong_exporter_invoke(exporter, 
-							     doc, 
-							     export_uri,
-							     toplevel_window);
-					
-					g_free(export_uri);
-					
-				}
+	/*
+	 * Outcome of the dialog:
+	 *    - cancelled
+	 *    - user selected ok, filename selected
+	 *    - user selected ok, no filename selected
+	 *
+	 * For the last case we want to throw up a dialog saying a filename is
+	 * needed and re-display the dialog, otherwise we end the loop.
+	 */
+	while (flag==1)
+	{
+		gint result = gtk_dialog_run (GTK_DIALOG(dialog));
+		flag = 0;
+
+		if (result==GTK_RESPONSE_OK) {
+			exporter = get_selected_exporter (dialog_details);
+			g_assert (exporter);
+
+			export_uri = cong_exporter_get_preferred_uri (exporter);
+			if (export_uri==NULL) {
+				GtkDialog* error_dialog;
+				error_dialog = cong_error_dialog_new (toplevel_window,
+								      _("No output file specified"), 
+								      _("Please specify a file name."),
+								      "");
+				gtk_dialog_run (error_dialog);
+				gtk_widget_destroy (GTK_WIDGET(error_dialog));
+				flag = 1;
+				exporter = NULL; /* in case the user decides to cancel the dialog */
 			}
-			break;
 		}
-
-		/* FIXME: Somewhat hackish cleanup: */
-		gconf_client_notify_remove(cong_app_get_gconf_client(cong_app_singleton()),
-					   dialog_details->connection_id);
-	} else {
-		/* There are no plugins which can handle this document: */
-		gchar *filename = cong_document_get_filename(doc);
-		gchar *what_failed = g_strdup_printf(_("Conglomerate cannot export \"%s\""), filename);
-		GtkDialog* error_dialog = cong_error_dialog_new(toplevel_window,
-								what_failed, 
-								_("None of Conglomerate's plugins know how to export files of that type."),
-								"");
-
-		gtk_dialog_run(error_dialog);
-		gtk_widget_destroy(GTK_WIDGET(error_dialog));
 	}
 
 	/* FIXME: Somewhat hackish cleanup: */
+	gconf_client_notify_remove(cong_app_get_gconf_client(cong_app_singleton()),
+				   dialog_details->connection_id);
 	cong_document_export_dialog_delete (dialog);
 
+	/*
+	 * We use the exporter variable to determine whether we continue with the processing.
+	 * Note that we destroy the dialog BEFORE we do this check, so that we do not
+	 * get a "hung" dialog window. The exporter should make sure that the busy cursor
+	 * is set in the top-level Conglomerate windows to tell the user that something
+	 * is happening. This probably needs some "UI love" to ensure it is usable.
+	 *
+	 * (due to the current design of cong_ui_transform_doc() in cong-plugins.c we
+         *  would not get the "busy" cursor in the dialog window if it were open when
+         *  we call the exporter)
+	 */
+	if (exporter) {
+		g_assert (export_uri);
+		g_message("Exporter invoked: \"%s\" to \"%s\"",
+			  cong_service_get_name(CONG_SERVICE(exporter)),
+			  export_uri);
+
+		cong_exporter_invoke (exporter, 
+				      doc, 
+				      export_uri,
+				      toplevel_window);
+		g_free (export_uri);
+	}
+
 }
Index: src/cong-plugin.c
===================================================================
RCS file: /cvs/gnome/conglomerate/src/cong-plugin.c,v
retrieving revision 1.48
diff -u -r1.48 cong-plugin.c
--- src/cong-plugin.c	10 Oct 2004 19:36:50 -0000	1.48
+++ src/cong-plugin.c	14 Oct 2004 19:42:52 -0000
@@ -669,6 +669,26 @@
 	g_free (libxslt_params);
 }
 
+static void
+set_window_cursor_helper (gpointer primary_window, gpointer cursor)
+{
+	gdk_window_set_cursor (((CongPrimaryWindow *)primary_window)->window->window,
+			       (GdkCursor *)cursor );
+}
+
+static void
+set_window_cursor (GdkCursor *cursor)
+{
+	/*
+	 * It seems that we need the gdk_flush() to ensure the
+	 * change happens before calling something processor-intensive
+	 */
+	g_list_foreach ( cong_app_singleton()->primary_windows,
+			 set_window_cursor_helper,
+			 cursor );
+	gdk_flush();
+}
+
 /**
  * cong_ui_transform_doc:
  * @doc:
@@ -677,6 +697,14 @@
  * @toplevel_window:
  *
  * TODO: Write me
+ *
+ * The routine sets all primary windows of Conglomerate to have a busy cursor whilst
+ * the processing occurs. It will not pick up any dialog, or other, windows
+ * that may have been created by Conglomerate. At the moment this is not a problem,
+ * but it may be in the future. It may be possible to use GTK (or GDK) functions
+ * to fid all the windows that are currently controlled by Conglomerate, and
+ * so avoid this issue.
+ *
  * Returns:
  */
 xmlDocPtr 
@@ -689,6 +717,7 @@
 	xmlDocPtr input_clone;
 	xmlDocPtr result;
 	char **libxslt_params;
+	GdkCursor *busy_cursor;
 
 	g_return_val_if_fail (doc, NULL);
 	g_return_val_if_fail (stylesheet_filename, NULL);
@@ -696,15 +725,20 @@
 	xsl = xsltParseStylesheetFile(stylesheet_filename);
 
 	if (NULL==xsl) {
-		gchar *why_failed = g_strdup_printf(_("There was a problem reading the stylesheet file \"%s\""),stylesheet_filename);
+		/*
+		 * Since we can not assume that these are the DocBook stylesheets we can not
+		 * be too precise with the error message. The message below assumes that whatever stylesheet
+		 * was used was accessed via the XML catalog mechanism, hence the note about the catalog
+		 * file. It would be nice to make the URL an actual link but that is a lot more work.
+		 */
+		gchar *why_failed = g_strdup_printf (_("There was a problem reading the stylesheet file \"%s\""),stylesheet_filename);
+		GtkDialog* dialog = cong_error_dialog_new (toplevel_window,
+							   _("Conglomerate could not transform the document"),
+							   why_failed,
+							   _("Since Conglomerate could not read the stylesheet it is possible that your XML catalog file is set up incorrectly. See http://www.xmlsoft.org/catalog.html for more information on catalogs."));
 
-		GtkDialog* dialog = cong_error_dialog_new(toplevel_window,
-							  _("Conglomerate could not transform the document"),
-							  why_failed,
-							  "FIXME");
-	
-		cong_error_dialog_run(GTK_DIALOG(dialog));
-		gtk_widget_destroy(GTK_WIDGET(dialog));
+		cong_error_dialog_run (GTK_DIALOG(dialog));
+		gtk_widget_destroy (GTK_WIDGET(dialog));
 		return NULL;
 	}
 
@@ -715,29 +749,63 @@
 	g_assert(input_clone);
 
 	cong_stylesheet_parameter_list_debug (list_of_parameters);
-
 	libxslt_params = make_libxslt_params (list_of_parameters);
 
-	result = xsltApplyStylesheet(xsl, input_clone, (const char**)libxslt_params);
-	g_assert(result);
-
-	free_libxslt_params (libxslt_params);
+	busy_cursor = gdk_cursor_new(GDK_WATCH);
+	set_window_cursor (busy_cursor);
 
-	xmlFreeDoc(input_clone);
+	result = xsltApplyStylesheet(xsl, input_clone, (const char**)libxslt_params);
 
-	if (result->children==NULL) {
-		gchar *why_failed = g_strdup_printf(_("There was a problem applying the stylesheet file"));
+	set_window_cursor (NULL);
+	gdk_cursor_unref (busy_cursor);
 
-		GtkDialog* dialog = cong_error_dialog_new(toplevel_window,
-							  _("Conglomerate could not transform the document"),
-							  why_failed,
-							  "FIXME");
+	/* g_assert(result); */
+	if (result!=NULL && result->children==NULL) {
+		/* is this necessary? */
+		xmlFreeDoc(result);
+		result = NULL;
+	}
+	if (result==NULL) {
+		gchar *why_failed = g_strdup_printf (_("There was a problem applying the stylesheet file \"%s\" to \"%s\""),
+						     stylesheet_filename,
+						     cong_document_get_filename(doc));
+#ifdef SILLY_IDEA
+		if (list_of_parameters!=NULL) {
+			/*
+			 * add the stylesheet parameters to the dialog. This is probably a bad idea if the list 
+			 * contains more than a few items. Two problems when there are a large number of 
+			 * parameters are:
+			 *   1 - the loop below is inefficient in this situation
+			 *   2 - the dialog will be too large to read effectively
+			 *
+			 * could use the libxslt_params array rather than the list_of_parameters since this
+			 * can be used by g_strjoinv() and other related functions.
+			 */
+			GList *iter;
+			CongStylesheetParameter *param;
+			gchar *temp = g_strconcat (why_failed, _("\n\nThe following stylesheet parameters were used:\n"));
+			g_free (why_failed);
+			why_failed = temp;
+
+			for (iter=list_of_parameters; iter; iter=iter->next) {
+				param = (CongStylesheetParameter *)iter->data;
+				temp = g_strdup_printf ("%s  %s\t%s\n", why_failed, param->name, param->value);
+				g_free (why_failed);
+				why_failed = temp;
+			}
+		}
+#endif
+		GtkDialog* dialog = cong_error_dialog_new (toplevel_window,
+							   _("Conglomerate could not transform the document"),
+							   why_failed,
+							   "");
 	
-		cong_error_dialog_run(GTK_DIALOG(dialog));
-		gtk_widget_destroy(GTK_WIDGET(dialog));
-		return NULL;
+		cong_error_dialog_run (GTK_DIALOG(dialog));
+		gtk_widget_destroy (GTK_WIDGET(dialog));
 	}
 
+	xmlFreeDoc(input_clone);
+	free_libxslt_params (libxslt_params);
 	xsltFreeStylesheet(xsl);
 
 	return result;
@@ -751,9 +819,21 @@
  * @string_uri:
  * @toplevel_window:
  *
- * TODO: Write me
+ * Applies the stylesheet (@stylesheet_filename) to the
+ * document (@doc) and saves the output to @string_uri.
+ * 
+ * At present, it is assumed that a dialog window will be
+ * created if there is an error in the processing (e.g.
+ * unable to find the stylesheet or write to the given URI).
+ * No dialog is created on success (so that the calling routine
+ * can customise such a dialog, or not have one).
+ *
+ * It also relies on the #cong_ui_transform_doc() routines for
+ * providing feed-back to the user that something is happening.
+ *
+ * Returns: true on success, false on failure.
  */
-void 
+gboolean
 cong_ui_transform_doc_to_uri(CongDocument *doc,
 			     const gchar *stylesheet_filename,
 			     GList *list_of_parameters,
@@ -765,38 +845,37 @@
 	GnomeVFSResult vfs_result;
 	GnomeVFSFileSize file_size;
 
-	g_return_if_fail (doc);
-	g_return_if_fail (stylesheet_filename);
-	g_return_if_fail (string_uri);
-
-	/* FIXME:  need some kind of feedback e.g. a busy cursor */
+	g_return_val_if_fail (doc, 0);
+	g_return_val_if_fail (stylesheet_filename, 0);
+	g_return_val_if_fail (string_uri, 0);
 
 	doc_ptr = cong_ui_transform_doc(doc,
 					stylesheet_filename,
 					list_of_parameters,
 					toplevel_window);
+	if (doc_ptr == NULL) {
+		return 0;
+	}
 
-	if (doc_ptr) {
-		vfs_uri = gnome_vfs_uri_new(string_uri);
-	
-		vfs_result = cong_vfs_save_xml_to_uri (doc_ptr, 
-						       vfs_uri,	
-						       &file_size);
+	vfs_uri = gnome_vfs_uri_new(string_uri);
+	vfs_result = cong_vfs_save_xml_to_uri (doc_ptr, 
+					       vfs_uri,	
+					       &file_size);
 		
-		if (vfs_result != GNOME_VFS_OK) {
-			GtkDialog* dialog = cong_error_dialog_new_from_file_save_failure(toplevel_window,
-											 string_uri, 
-											 vfs_result, 
-											 &file_size);
+	if (vfs_result != GNOME_VFS_OK) {
+		GtkDialog* dialog = cong_error_dialog_new_from_file_save_failure(toplevel_window,
+										 string_uri, 
+										 vfs_result, 
+										 &file_size);
 			
-			cong_error_dialog_run(GTK_DIALOG(dialog));
-			gtk_widget_destroy(GTK_WIDGET(dialog));
-		}
-		
-		gnome_vfs_uri_unref(vfs_uri);
-
-		xmlFreeDoc(doc_ptr);
+		cong_error_dialog_run(GTK_DIALOG(dialog));
+		gtk_widget_destroy(GTK_WIDGET(dialog));
+		return 0;
 	}
+		
+	gnome_vfs_uri_unref(vfs_uri);
+	xmlFreeDoc(doc_ptr);
+	return 1;
 }
 
 /* Handy methods for "Import" methods; doing the necessary UI hooks: */
Index: src/cong-plugin.h
===================================================================
RCS file: /cvs/gnome/conglomerate/src/cong-plugin.h,v
retrieving revision 1.28
diff -u -r1.28 cong-plugin.h
--- src/cong-plugin.h	27 Jul 2004 17:17:44 -0000	1.28
+++ src/cong-plugin.h	14 Oct 2004 19:42:52 -0000
@@ -148,11 +148,11 @@
 				GList *list_of_parameters,
 				GtkWindow *toplevel_window);
 
-void cong_ui_transform_doc_to_uri(CongDocument *doc,
-				  const gchar *stylesheet_filename,
-				  GList *list_of_parameters,
-				  const gchar *uri,
-				  GtkWindow *toplevel_window);
+gboolean cong_ui_transform_doc_to_uri(CongDocument *doc,
+				      const gchar *stylesheet_filename,
+				      GList *list_of_parameters,
+				      const gchar *uri,
+				      GtkWindow *toplevel_window);
 
 gboolean cong_ui_load_imported_file_content(const gchar *uri,
 					    char** buffer,
Index: src/plugin-docbook.c
===================================================================
RCS file: /cvs/gnome/conglomerate/src/plugin-docbook.c,v
retrieving revision 1.50
diff -u -r1.50 plugin-docbook.c
--- src/plugin-docbook.c	19 Aug 2004 11:00:21 -0000	1.50
+++ src/plugin-docbook.c	14 Oct 2004 19:42:52 -0000
@@ -33,6 +33,8 @@
 #include "cong-util.h"
 #include "cong-fake-plugin-hooks.h"
 #include "cong-glade.h"
+#include "cong-dialog.h"
+#include "cong-vfs.h"
 
 #if ENABLE_PRINTING
 #include <libgnomeprint/gnome-print-config.h>
@@ -70,7 +72,9 @@
  * TODO: Write me
  */
 void 
-factory_page_creation_callback_unified(CongServiceDocumentFactory *factory, CongNewFileAssistant *assistant, gpointer user_data)
+factory_page_creation_callback_unified(CongServiceDocumentFactory *factory,
+				       CongNewFileAssistant *assistant,
+				       gpointer user_data)
 {
 #if 0
 	GnomeDruidPageStandard *which_settings_page;
@@ -1063,6 +1067,95 @@
 	return cong_util_is_docbook(doc);
 }
 
+/*
+ * Returns the location of the DocBook stylesheet used to convert
+ * a DocBook file to the type argument (e.g. "html" or "fo"). The
+ * return value must be free-ed by the user. The label argument is
+ * used in the error dialog to describe the format being converted
+ * to (e.g. "HTML" or "XSL:FO").
+ *
+ * If no stylesheet can be found then an error dialog is created
+ * and NULL is returned.
+ *
+ */
+static gchar *
+get_and_check_stylesheet_path(gchar *type,
+			      gchar *label,
+			      GtkWindow *toplevel_window)
+{
+	GtkDialog *error_dialog;
+	gchar *msg;
+	gchar *tail;
+	gchar *stylesheet_path;
+
+	tail = g_strdup_printf ("%s/docbook.xsl", type);
+	stylesheet_path = cong_utils_get_norman_walsh_stylesheet (tail);
+	g_free (tail);
+	if (stylesheet_path!=NULL) {
+		return stylesheet_path;
+	}
+
+	/*
+	 * The text may not be very helpful.
+	 * It would be nice to make the URLs be actual links.
+	 */
+	msg = g_strdup_printf( _("Conglomerate can not find the stylesheet used to convert DocBook to %s"),
+			       label );
+	error_dialog = cong_error_dialog_new (toplevel_window,
+					      _("Unable to locate the DocBook stylesheets"),
+					      msg,
+					      _("Ensure that Norman Walsh's DocBook XSL stylesheets, available at http://docbook.sourceforge.net/projects/xsl/, are installed and are added to your XML catalog file (see http://www.xmlsoft.org/catalog.html for more information on catalogs)."));
+	
+	gtk_dialog_run (error_dialog);
+	gtk_widget_destroy (GTK_WIDGET(error_dialog));
+	g_free (msg);
+	return NULL;
+}
+
+/*
+ * perhaps this should be part of cong_ui_transform_doc_to_uri() ?
+ */
+static void
+do_transform(gchar *type,
+	     CongDocument *doc,
+	     const gchar *stylesheet_path,
+	     GList *stylesheet_args,
+	     const gchar *string_uri,
+	     GtkWindow *toplevel_window)
+{
+	/*
+	 * If the call fails then we assume there will have been an
+	 * appropriate error dialog created, so we only need to create
+	 * a dialog on a successfull transform.
+	 */
+	if (cong_ui_transform_doc_to_uri(doc,
+					 stylesheet_path,
+					 stylesheet_args, 
+					 string_uri,
+					 toplevel_window)) {
+
+		GtkDialog *dialog;
+		gchar *filename_alone;
+		gchar *path;
+		gchar *message;
+		
+		cong_vfs_split_string_uri (string_uri, &filename_alone, &path);
+		message = g_strdup_printf (_("%s conversion complete.\n\nConverted %s to %s in %s"),
+					   type,
+					   cong_document_get_filename (doc),
+					   filename_alone,
+					   path);
+		dialog = cong_dialog_information_alert_new (toplevel_window,
+							    message);
+		
+		gtk_dialog_run (dialog);
+		gtk_widget_destroy (GTK_WIDGET(dialog));
+		g_free (message);
+		g_free (filename_alone);
+		g_free (path);
+	}
+}
+
 /**
  * html_exporter_action_callback:
  * @exporter:
@@ -1083,17 +1176,20 @@
 	g_return_if_fail(uri);
 
 	g_message("html_exporter_action_callback");
-	
-	stylesheet_path = cong_utils_get_norman_walsh_stylesheet("html/docbook.xsl");
-	g_assert(stylesheet_path);
 
-	cong_ui_transform_doc_to_uri(doc,
-				     stylesheet_path,
-				     NULL, 
-				     uri,
-				     toplevel_window);
+	stylesheet_path = get_and_check_stylesheet_path ("html","HTML",toplevel_window);
+	if (stylesheet_path==NULL) {
+		return;
+	}
 
-	g_free(stylesheet_path);
+	/* apply the transformation */
+	do_transform ("HTML",
+		      doc,
+		      stylesheet_path,
+		      NULL, 
+		      uri,
+		      toplevel_window);
+	g_free (stylesheet_path);
 }
 
 GList*
@@ -1161,8 +1257,10 @@
 	g_return_if_fail(doc);
 	g_return_if_fail(uri);
 
-	stylesheet_path = cong_utils_get_norman_walsh_stylesheet("fo/docbook.xsl");
-	g_assert(stylesheet_path);
+	stylesheet_path = get_and_check_stylesheet_path ("fo","XSL:FO",toplevel_window);
+	if (stylesheet_path==NULL) {
+		return;
+	}
 
 	list_of_parameters = make_fo_export_params ();
 
@@ -1233,17 +1331,19 @@
 
 	g_message("fo_exporter_action_callback");
 
-	stylesheet_path = cong_utils_get_norman_walsh_stylesheet("fo/docbook.xsl");
-	g_assert(stylesheet_path);
+	stylesheet_path = get_and_check_stylesheet_path ("fo","XSL:FO",toplevel_window);
+	if (stylesheet_path==NULL) {
+		return;
+	}
 
+	/* apply the transformation */
 	list_of_parameters = make_fo_export_params ();
-
-	cong_ui_transform_doc_to_uri(doc,
-				     stylesheet_path,
-				     list_of_parameters,
-				     uri,
-				     toplevel_window);
-
+	do_transform ("XSL:FO",
+		      doc,
+		      stylesheet_path,
+		      list_of_parameters, 
+		      uri,
+		      toplevel_window);
 	g_free(stylesheet_path);
 	cong_stylesheet_parameter_list_free (list_of_parameters);
 }
@@ -1304,34 +1404,31 @@
 
 	{
 		GList *list_of_parameters;	
-		gchar *stylesheet_path = cong_utils_get_norman_walsh_stylesheet("fo/docbook.xsl");
-		g_assert(stylesheet_path);
+		gchar *stylesheet_path = get_and_check_stylesheet_path ("fo","XSL:FO",toplevel_window);
+		if (stylesheet_path==NULL) {
+			/* what should we do on error here? */
+			return;
+		}
 
 		list_of_parameters = make_fo_export_params ();
-
 		fo_doc = cong_ui_transform_doc(doc,
 					       stylesheet_path,
 					       list_of_parameters,
 					       toplevel_window);
-
 		g_free(stylesheet_path);
 		cong_stylesheet_parameter_list_free (list_of_parameters);
 	}
 
 	if (fo_doc) {
 		cong_progress_checklist_complete_stage(progress_checklist);
-
 		cong_util_print_xslfo(toplevel_window, 
 				      gpc, 
 				      fo_doc);
-
 		xmlFreeDoc(fo_doc);
 	}
 
-
 	gtk_widget_destroy(progress_checklist_dialog);
 
-
 }
 #endif /* #if ENABLE_PRINTING */
 
@@ -1395,7 +1492,9 @@
  * Returns:
  */
 GtkWidget* 
-docbook_orderedlist_properties_factory_method(CongServiceNodePropertyDialog *custom_property_dialog, CongDocument *doc, CongNodePtr node)
+docbook_orderedlist_properties_factory_method(CongServiceNodePropertyDialog *custom_property_dialog,
+					      CongDocument *doc,
+					      CongNodePtr node)
 {
 	gchar* glade_filename;
 	GladeXML *xml;
@@ -1525,7 +1624,9 @@
  * Returns:
  */
 GtkWidget* 
-docbook_ulink_properties_factory_method(CongServiceNodePropertyDialog *custom_property_dialog, CongDocument *doc, CongNodePtr node)
+docbook_ulink_properties_factory_method(CongServiceNodePropertyDialog *custom_property_dialog,
+					CongDocument *doc,
+					CongNodePtr node)
 {
 	gchar* glade_filename;
 	GladeXML *xml;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.