[rkward-cvs] SF.net SVN: rkward: [1792] trunk/rkward

tfry at users.sourceforge.net tfry at users.sourceforge.net
Mon Apr 9 13:45:38 UTC 2007


Revision: 1792
          http://svn.sourceforge.net/rkward/?rev=1792&view=rev
Author:   tfry
Date:     2007-04-09 06:45:38 -0700 (Mon, 09 Apr 2007)

Log Message:
-----------
Make messages, warnings, and errors from plugin commands go to the output, instead of showing them in a dialog.
Make sure output from sub-commands is also added to the commands higher up in the chain

Modified Paths:
--------------
    trunk/rkward/ChangeLog
    trunk/rkward/TODO
    trunk/rkward/rkward/plugin/rkstandardcomponentgui.cpp
    trunk/rkward/rkward/plugin/rkstandardcomponentgui.h
    trunk/rkward/rkward/plugins/plots/pareto.php
    trunk/rkward/rkward/rbackend/rinterface.cpp
    trunk/rkward/rkward/rbackend/rpackages/rkward/DESCRIPTION
    trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal.R
    trunk/rkward/rkward/rbackend/rpackages/rkward/R/public.R
    trunk/rkward/rkward/rbackend/rthread.cpp
    trunk/rkward/rkward/rbackend/rthread.h

Modified: trunk/rkward/ChangeLog
===================================================================
--- trunk/rkward/ChangeLog	2007-04-05 16:28:37 UTC (rev 1791)
+++ trunk/rkward/ChangeLog	2007-04-09 13:45:38 UTC (rev 1792)
@@ -1,3 +1,5 @@
+- Messages, warnings, and errors for plugin commands are shown in the output, instead of in a dialog
+
 --- Version 0.4.7 - Apr-XX-2007
 - some fixes for GCC 4.3
 - fixed: the presence of user objects called "missing", "assign", or "get" would confuse some RKWard internals

Modified: trunk/rkward/TODO
===================================================================
--- trunk/rkward/TODO	2007-04-05 16:28:37 UTC (rev 1791)
+++ trunk/rkward/TODO	2007-04-09 13:45:38 UTC (rev 1792)
@@ -12,6 +12,8 @@
 	- Find a solution for error handling in plugins
 	- Do not use a sink in plugins. Rather, all printing code should print to the output file. Everything else will be added below the output.
 	- Separate plugin output by an <hr> or something (*after* a plugin has run, and *only if* it has produced some sort of output (or warnings/errors))
+	- if there is a substack command, warnings may get attached to the wrong command (as Rf_PrintWarnings() is called for the substack-command, before it is called for the main command)! What to do?! Something like current_toplevel_command? Will this always work, right? Probably not.
+		- Maybe keep a list of *all* still active commands, and append output to all of those
 
 Advertizing:
 	- start being a bit bolder about RKWard (descriptions, startup notification, etc.)

Modified: trunk/rkward/rkward/plugin/rkstandardcomponentgui.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkstandardcomponentgui.cpp	2007-04-05 16:28:37 UTC (rev 1791)
+++ trunk/rkward/rkward/plugin/rkstandardcomponentgui.cpp	2007-04-09 13:45:38 UTC (rev 1792)
@@ -32,7 +32,6 @@
 #include "../windows/rkworkplace.h"
 #include "../windows/rkcommandeditorwindow.h"
 #include "../rbackend/rinterface.h"
-#include "../misc/rkerrordialog.h"
 #include "../rkward.h"
 #include "../settings/rksettingsmoduleplugins.h"
 #include "../rkglobals.h"
@@ -45,9 +44,6 @@
 
 	toggle_code_button = 0;
 
-	// create an error-dialog
-	error_dialog = new RKRErrorDialog (i18n ("The R-backend has reported one or more error(s) while processing the plugin '%1'.\nThis may lead to an incorrect output and is likely due to a bug in the plugin.\nA transcript of the error message(s) is shown below.").arg (component->getFilename ()), i18n ("R-Error"), false);
-
 	RKStandardComponentGUI::component = component;
 	RKStandardComponentGUI::code_property = code_property;
 	connect (code_property, SIGNAL (valueChanged (RKComponentPropertyBase *)), this, SLOT (codeChanged (RKComponentPropertyBase *)));
@@ -67,8 +63,6 @@
 
 RKStandardComponentGUI::~RKStandardComponentGUI () {
 	RK_TRACE (PLUGIN);
-
-	delete error_dialog;
 }
 
 void RKStandardComponentGUI::createDialog (bool switchable) {
@@ -155,7 +149,7 @@
 	command.append (code_property->calculate ());
 	command.append (code_property->printout ());
 	command.append ("})\n");
-	RKGlobals::rInterface ()->issueCommand (new RCommand (command, RCommand::Plugin | RCommand::DirectToOutput | RCommand::ObjectListUpdate, QString::null, error_dialog));
+	RKGlobals::rInterface ()->issueCommand (new RCommand (command, RCommand::Plugin | RCommand::DirectToOutput | RCommand::ObjectListUpdate));
 }
 
 void RKStandardComponentGUI::cancel () {

Modified: trunk/rkward/rkward/plugin/rkstandardcomponentgui.h
===================================================================
--- trunk/rkward/rkward/plugin/rkstandardcomponentgui.h	2007-04-05 16:28:37 UTC (rev 1791)
+++ trunk/rkward/rkward/plugin/rkstandardcomponentgui.h	2007-04-09 13:45:38 UTC (rev 1792)
@@ -68,7 +68,6 @@
 class QPushButton;
 class QTimer;
 class QSplitter;
-class RKRErrorDialog;
 
 /** contains the standard GUI elements for a top-level RKStandardComponent. The base class creates a dialog interface. For a wizard interface use RKStandardComponentWizard. You *must* call createDialog () after construction, since I can't virualize this for reasons I don't understand!
 
@@ -105,7 +104,6 @@
 	void closeEvent (QCloseEvent *e);
 	RKStandardComponent *component;
 	QTimer *code_update_timer;
-	RKRErrorDialog *error_dialog;
 
 	// common widgets
 	QWidget *main_widget;

Modified: trunk/rkward/rkward/plugins/plots/pareto.php
===================================================================
--- trunk/rkward/rkward/plugins/plots/pareto.php	2007-04-05 16:28:37 UTC (rev 1791)
+++ trunk/rkward/rkward/plugins/plots/pareto.php	2007-04-09 13:45:38 UTC (rev 1792)
@@ -30,7 +30,7 @@
 x <- <? echo ($vars); ?>
 
 if (!is.numeric (x)) {
-       rk.print ("Data may not be numeric, but proceeding as requested.\nDid you forget to check the tabulate option?")
+	warning ("Data may not be numeric, but proceeding as requested.\nDid you forget to check the tabulate option?")
 }
 <?      } ?>
 

Modified: trunk/rkward/rkward/rbackend/rinterface.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rinterface.cpp	2007-04-05 16:28:37 UTC (rev 1791)
+++ trunk/rkward/rkward/rbackend/rinterface.cpp	2007-04-09 13:45:38 UTC (rev 1792)
@@ -294,10 +294,6 @@
 		} else {
 			issueCommand (".rk.set.reply (\"Too few arguments in call to get.tempfile.name.\")", RCommand::App | RCommand::Sync, QString::null, 0, 0, request->in_chain);
 		}
-	} else if (call == "get.output.html.file") {
-		QDir dir (RKSettingsModuleGeneral::filesPath ());
-		// TODO: make more generic, get filename sanely
-		issueCommand (".rk.set.reply (\"" + dir.filePath ("rk_out.html") + "\")", RCommand::App | RCommand::Sync, QString::null, 0, 0, request->in_chain);
 	} else if (call == "sync") {
 		RK_ASSERT (request->call_length >= 2);
 

Modified: trunk/rkward/rkward/rbackend/rpackages/rkward/DESCRIPTION
===================================================================
--- trunk/rkward/rkward/rbackend/rpackages/rkward/DESCRIPTION	2007-04-05 16:28:37 UTC (rev 1791)
+++ trunk/rkward/rkward/rbackend/rpackages/rkward/DESCRIPTION	2007-04-09 13:45:38 UTC (rev 1792)
@@ -1,6 +1,6 @@
 Package: rkward
 Title: Provides some helper functions for the RKWard frontend
-Version: 0.4.7
+Version: 0.4.8
 Author: Thomas Friedrichsmeier and the RKWard Team
 Description: Most of the functions in here are really only needed for the internal communication between RKWard and R. There are also a few functions, which allow access to RKWard or RKWard specifics. Most is not implemented, yet.
 Maintainer: RKWard-devel mailing list <rkward-devel at lists.sourceforge.net>

Modified: trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal.R
===================================================================
--- trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal.R	2007-04-05 16:28:37 UTC (rev 1791)
+++ trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal.R	2007-04-09 13:45:38 UTC (rev 1792)
@@ -372,6 +372,8 @@
 	ret
 }
 
+".rk.output.html.file" <- NULL
+
 ".rk.rkreply" <- NULL
 
 ".rk.set.reply" <- function (x) .rk.rkreply <<- x
@@ -422,3 +424,8 @@
 	.rk.do.call ("wdChange", NULL);
 }
 formals (setwd) <- formals (base::setwd)
+
+# hidden, as this is not portable to different output formats
+".rk.cat.output" <- function (x) {
+	cat (x, file = rk.get.output.html.file(), append = TRUE)
+}

Modified: trunk/rkward/rkward/rbackend/rpackages/rkward/R/public.R
===================================================================
--- trunk/rkward/rkward/rbackend/rpackages/rkward/R/public.R	2007-04-05 16:28:37 UTC (rev 1791)
+++ trunk/rkward/rkward/rbackend/rpackages/rkward/R/public.R	2007-04-09 13:45:38 UTC (rev 1792)
@@ -104,9 +104,14 @@
 }
 
 "rk.get.output.html.file" <- function () {
-	return (.rk.do.call ("get.output.html.file", ""))
+	return (.rk.output.html.file)
 }
 
+"rk.set.output.html.file" <- function (x) {
+	stopifnot (is.character (x))
+	assign (".rk.output.html.file", x, as.environment ("package:rkward"))
+}
+
 # renames a named object in a data.frame/list without changing it's position
 # TODO: create a generic function instead, that can handle all kinds of renames
 "rk.rename.in.container" <- function (x, old_name, new_name, envir=parent.frame()) {
@@ -144,6 +149,9 @@
 }
 
 "rk.header" <- function (title, parameters=list ()) {
+	sink (rk.get.output.html.file(), append=TRUE)
+	on.exit (sink ())
+
 	cat (paste ("<h1>", title, "</h1>\n", sep=""))
 	if (length (parameters)) {
 		cat ("<h2>Parameters</h2>\n<ul>")
@@ -160,6 +168,9 @@
 }
 
 "rk.results" <- function (x, titles=NULL) {
+	sink (rk.get.output.html.file(), append=TRUE)
+	on.exit (sink ())
+
 	if (is.list (x)) {	# or a data.frame
 		if (is.null (titles)) {
 			titles <- names (x)

Modified: trunk/rkward/rkward/rbackend/rthread.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rthread.cpp	2007-04-05 16:28:37 UTC (rev 1791)
+++ trunk/rkward/rkward/rbackend/rthread.cpp	2007-04-09 13:45:38 UTC (rev 1792)
@@ -149,6 +149,7 @@
 
 	// step 2: actual handling
 	if (!((command->type () & RCommand::EmptyCommand) || (command->status & RCommand::Canceled))) {
+		all_current_commands.append (command);
 		RKWardRError error;
 		
 		int ctype = command->type ();
@@ -157,7 +158,8 @@
 		RK_DO (qDebug ("running command: %s", ccommand.latin1()), RBACKEND, DL_DEBUG);
 	
 		if (command->type () & RCommand::DirectToOutput) {
-			runCommandInternal (QString ("sink (\"" + RKSettingsModuleGeneral::filesPath () + "/rk_out.html\", append=TRUE, split=TRUE)\n").local8Bit (), &error);
+			runCommandInternal (".rk.cat.output (\"<hr>\\n\")", &error, false);
+			RK_ASSERT (!error);
 		}
 
 		MUTEX_UNLOCK;
@@ -205,10 +207,19 @@
 		} else {
 			command->status |= RCommand::WasTried;
 		}
-	
-		RKWardRError dummy;
+
+		flushOutput ();
 		if (command->type () & RCommand::DirectToOutput) {
-			runCommandInternal ("sink ()\n", &dummy);
+			QString outp = command->fullOutput();
+
+			if (!outp.isEmpty ()) {
+				// all regular output was sink()ed, i.e. all remaining output is a message/warning/error
+				RKWardRError error;
+				runCommandInternal (".rk.cat.output (\"<h2>Messages, warnings, or errors:</h2>\\n\")", &error, false);
+				RK_ASSERT (!error);
+				runCommandInternal ("rk.print.literal (\"" + outp + "\")", &error, false);
+				RK_ASSERT (!error);
+			}
 		}
 	
 		if (error) {
@@ -216,8 +227,7 @@
 	//		runCommandInternal (".rk.init.handlers ()\n", &dummy);
 		}
 		RK_DO (qDebug ("done running command"), RBACKEND, DL_DEBUG);
-
-		flushOutput ();
+		all_current_commands.pop_back();
 	} else {
 		if (command->type () & RCommand::QuitCommand) {
 			killed = true;
@@ -279,23 +289,32 @@
 	RK_TRACE (RBACKEND);
 
 	if (current_command) {
-		current_command->output_list.append (current_output);
-		if (current_output->type == ROutput::Output) {
-			current_command->status |= RCommand::HasOutput;
-		} else if (current_output->type == ROutput::Warning) {
-			current_command->status |= RCommand::HasWarnings;
-		} else if (current_output->type == ROutput::Error) {
-			current_command->status |= RCommand::HasError;
+		for (QValueList<RCommand*>::const_iterator it = all_current_commands.constBegin (); it != all_current_commands.constEnd(); ++it) {
+			ROutput *output = current_output;
+			if ((*it) != current_command) {		// this output belongs to several commands at once. So we need to copy it.
+				output = new ROutput;
+				output->type = current_output->type;
+				output->output = current_output->output;
+			}
+
+			(*it)->output_list.append (output);
+			if (output->type == ROutput::Output) {
+				(*it)->status |= RCommand::HasOutput;
+			} else if (output->type == ROutput::Warning) {
+				(*it)->status |= RCommand::HasWarnings;
+			} else if (output->type == ROutput::Error) {
+				(*it)->status |= RCommand::HasError;
+			}
+
+			// pass a signal to the main thread for real-time update of output
+			QCustomEvent *event = new QCustomEvent (RCOMMAND_OUTPUT_EVENT);
+			ROutputContainer *outc = new ROutputContainer;
+			outc->output = output;
+			outc->command = *it;
+			event->setData (outc);
+			qApp->postEvent (RKGlobals::rInterface (), event);
 		}
 
-		// pass a signal to the main thread for real-time update of output
-		QCustomEvent *event = new QCustomEvent (RCOMMAND_OUTPUT_EVENT);
-		ROutputContainer *outc = new ROutputContainer;
-		outc->output = current_output;
-		outc->command = current_command;
-		event->setData (outc);
-		qApp->postEvent (RKGlobals::rInterface (), event);
-
 		RK_DO (qDebug ("output '%s'", current_output->output.latin1 ()), RBACKEND, DL_DEBUG);
 	} else {
 		// running Rcmdr, eh?
@@ -480,11 +499,11 @@
 		}
 	}
 
-// error sink and help browser
+// error/output sink and help browser
 	runCommandInternal ("options (error=quote (.rk.do.error ()))\n", &error);
 	if (error) status |= SinkFail;
-/*	runCommandInternal (".rk.init.handlers ()\n", &error);
-	if (error) status |= SinkFail; */
+	runCommandInternal ("rk.set.output.html.file (\"" + RKSettingsModuleGeneral::filesPath () + "/rk_out.html\")\n", &error);
+	if (error) status |= SinkFail;
 	runCommandInternal ("options (htmlhelp=TRUE); options (browser=\"dcop " + kapp->dcopClient ()->appId () + " rkwardapp openHTMLHelp \")", &error);
 	if (error) status |= OtherFail;
 	// TODO: error-handling?

Modified: trunk/rkward/rkward/rbackend/rthread.h
===================================================================
--- trunk/rkward/rkward/rbackend/rthread.h	2007-04-05 16:28:37 UTC (rev 1791)
+++ trunk/rkward/rkward/rbackend/rthread.h	2007-04-09 13:45:38 UTC (rev 1792)
@@ -19,6 +19,7 @@
 
 #include <qthread.h>
 #include <qstringlist.h>
+#include <qvaluelist.h>
 
 #include "rcommand.h"
 #include "rcommandstack.h"
@@ -187,6 +188,7 @@
 	QStringList changed_symbol_names;
 /** check wether the object list / global environment / individual symbols have changed, and updates them, if needed */
 	void checkObjectUpdatesNeeded (bool check_list);
+	QValueList<RCommand*> all_current_commands;
 };
 
 #endif


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the rkward-tracker mailing list