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

tfry at users.sourceforge.net tfry at users.sourceforge.net
Sat May 7 10:35:43 UTC 2011


Revision: 3536
          http://rkward.svn.sourceforge.net/rkward/?rev=3536&view=rev
Author:   tfry
Date:     2011-05-07 10:35:43 +0000 (Sat, 07 May 2011)

Log Message:
-----------
Add a new 'PlainGenericRequest' for requests that do not need to call sub-commands.
This makes code a bit easier in some places, and is a bit faster (esp. for those calls which can be made asynchronous).
Converted a first bunch of the old substack requests, many more left to go.

Modified Paths:
--------------
    trunk/rkward/rkward/rbackend/rinterface.cpp
    trunk/rkward/rkward/rbackend/rinterface.h
    trunk/rkward/rkward/rbackend/rkrbackend.cpp
    trunk/rkward/rkward/rbackend/rkrbackend.h
    trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.h
    trunk/rkward/rkward/rbackend/rkrsupport.cpp
    trunk/rkward/rkward/rbackend/rkrsupport.h
    trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal.R
    trunk/rkward/rkward/rbackend/rpackages/rkward/R/public.R
    trunk/rkward/rkward/windows/rkcommandeditorwindow.cpp

Modified: trunk/rkward/rkward/rbackend/rinterface.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rinterface.cpp	2011-05-05 16:04:37 UTC (rev 3535)
+++ trunk/rkward/rkward/rbackend/rinterface.cpp	2011-05-07 10:35:43 UTC (rev 3536)
@@ -317,6 +317,9 @@
 		tryNextCommand ();
 	} else if (request->type == RBackendRequest::HistoricalSubstackRequest) {
 		processHistoricalSubstackRequest (request);
+	} else if (request->type == RBackendRequest::PlainGenericRequest) {
+		request->params["return"] = QVariant (processPlainGenericRequest (request->params["call"].toStringList ()));
+		RKRBackendProtocolFrontend::setRequestCompleted (request);
 	} else if ((request->type == RBackendRequest::Started)) {
 		// The backend thread has finished basic initialization, but we still have more to do...
 		startup_errors = request->params["message"].toString ();
@@ -441,6 +444,30 @@
 	else locked -= locked & User;
 }
 
+QStringList RInterface::processPlainGenericRequest (const QStringList &calllist) {
+	RK_TRACE (RBACKEND);
+
+	QString call = calllist.value (0);
+	if (call == "get.tempfile.name") {
+		RK_ASSERT (calllist.count () == 3);
+		return (QStringList (RKCommonFunctions::getUseableRKWardSavefileName (calllist.value (1), calllist.value (2))));
+	} else if (call == "set.output.file") {
+		RK_ASSERT (calllist.count () == 2);
+		RKOutputWindowManager::self ()->setCurrentOutputPath (calllist.value (1));
+	} else if (call == "wdChange") {
+		// in case of separate processes, apply new working directory in frontend, too.
+		QDir::setCurrent (calllist.value (1));
+		RKWardMainWindow::getMain ()->updateCWD ();
+	} else if (call == "highlightRCode") {
+		return (QStringList (RKCommandHighlighter::commandToHTML (calllist.value (1))));
+	} else {
+		return (QStringList ("Error: unrecognized request '" + call + "'."));
+	}
+
+	// for those calls which were recognized, but do not return anything
+	return QStringList ();
+}
+
 void RInterface::processHistoricalSubstackRequest (RBackendRequest* request) {
 	RK_TRACE (RBACKEND);
 
@@ -451,27 +478,8 @@
 
 	QStringList calllist = request->params["call"].toStringList ();
 
-	if (calllist.isEmpty ()) {
-		RK_ASSERT (false);
-		closeChain (in_chain);
-		return;
-	}
-
-	QString call = calllist[0];
-	if (call == "get.tempfile.name") {
-		if (calllist.count () >= 3) {
-			QString file_prefix = calllist[1];
-			QString file_extension = calllist[2];
-
-			issueCommand (".rk.set.reply (\"" + RKCommonFunctions::getUseableRKWardSavefileName (file_prefix, file_extension) + "\")", RCommand::App | RCommand::Sync, QString::null, 0, 0, in_chain);
-		} else {
-			issueCommand ("stop (\"Too few arguments in call to get.tempfile.name.\")", RCommand::App | RCommand::Sync, QString::null, 0, 0, in_chain);
-		}
-	} else if (call == "set.output.file") {
-		RK_ASSERT (calllist.count () == 2);
-
-		RKOutputWindowManager::self ()->setCurrentOutputPath (calllist[1]);
-	} else if (call == "sync") {
+	QString call = calllist.value (0);
+	if (call == "sync") {
 		RK_ASSERT (calllist.count () >= 2);
 
 		for (int i = 1; i < calllist.count (); ++i) {
@@ -491,6 +499,22 @@
 	} else if (call == "syncglobal") {
 		RK_DO (qDebug ("triggering update of globalenv"), RBACKEND, DL_DEBUG);
 		RObjectList::getGlobalEnv ()->updateFromR (in_chain, calllist.mid (1));
+#ifndef DISABLE_RKWINDOWCATCHER
+	// NOTE: WARNING: When converting these to PlainGenericRequests, the occasional "error, figure margins too large" starts coming up, again. Not sure, why.
+ 	} else if (call == "startOpenX11") {
+		RK_ASSERT (calllist.count () == 2);
+		window_catcher->start (calllist.value (1).toInt ());
+ 	} else if (call == "endOpenX11") {
+		RK_ASSERT (calllist.count () == 2);
+		window_catcher->stop (calllist.value (1).toInt ());
+	} else if (call == "updateDeviceHistory") {
+		if (calllist.count () >= 2) {
+			window_catcher->updateHistory (calllist.mid (1));
+		}
+	} else if (call == "killDevice") {
+		RK_ASSERT (calllist.count () == 2);
+		window_catcher->killDevice (calllist.value (1).toInt ());
+#endif // DISABLE_RKWINDOWCATCHER
 	} else if (call == "edit") {
 		RK_ASSERT (calllist.count () >= 2);
 
@@ -509,30 +533,6 @@
 		RKWardMainWindow::getMain ()->close ();
 		// if we're still alive, quitting was cancelled
 		issueCommand (".rk.set.reply (\"Quitting was cancelled\")", RCommand::App | RCommand::Sync, QString::null, 0, 0, in_chain);
-#ifndef DISABLE_RKWINDOWCATCHER
- 	} else if (call == "startOpenX11") {
-		// TODO: error checking/handling (wrong parameter count/type)
-		if (calllist.count () >= 2) {
-			window_catcher->start (QString (calllist[1]).toInt ());
-		}
- 	} else if (call == "endOpenX11") {
-		// TODO: error checking/handling (wrong parameter count/type)
-		if (calllist.count () >= 2) {
-			window_catcher->stop (QString (calllist[1]).toInt ());
-		}
-	} else if (call == "updateDeviceHistory") {
-		if (calllist.count () >= 2) {
-			window_catcher->updateHistory (calllist.mid (1));
-		}
-	} else if (call == "killDevice") {
-		if (calllist.count () >= 2) {
-			window_catcher->killDevice (calllist[1].toInt ());
-		}
-#endif // DISABLE_RKWINDOWCATCHER
-	} else if (call == "wdChange") {
-		// in case of separate processes, apply new working directory in frontend, too.
-		QDir::setCurrent (calllist.value(1, QString ()));
-		RKWardMainWindow::getMain ()->updateCWD ();
 	} else if (call == "preLocaleChange") {
 		int res = KMessageBox::warningContinueCancel (0, i18n ("A command in the R backend is trying to change the character encoding. While RKWard offers support for this, and will try to adjust to the new locale, this operation may cause subtle bugs, if data windows are currently open. Also the feature is not well tested, yet, and it may be advisable to save your workspace before proceeding.\nIf you have any data editor opened, or in any doubt, it is recommended to close those first (this will probably be auto-detected in later versions of RKWard). In this case, please chose 'Cancel' now, then close the data windows, save, and retry."), i18n ("Locale change"));
 		if (res != KMessageBox::Continue) {
@@ -624,8 +624,6 @@
 		} else {
 			RK_ASSERT (false);
 		}
-	} else if (call == "highlightRCode") {
-		issueCommand (".rk.set.reply (" + RObject::rQuote (RKCommandHighlighter::commandToHTML (calllist.value (1))) + ")", RCommand::App | RCommand::Sync, QString::null, 0, 0, in_chain);
 	} else if (call == "getWorkspaceUrl") {
 		KUrl url = RObjectList::getObjectList ()->getWorkspaceURL ();
 		if (!url.isEmpty ()) issueCommand (".rk.set.reply (" + RObject::rQuote (url.url ()) + ")", RCommand::App | RCommand::Sync, QString::null, 0, 0, in_chain);

Modified: trunk/rkward/rkward/rbackend/rinterface.h
===================================================================
--- trunk/rkward/rkward/rbackend/rinterface.h	2011-05-05 16:04:37 UTC (rev 3535)
+++ trunk/rkward/rkward/rbackend/rinterface.h	2011-05-07 10:35:43 UTC (rev 3536)
@@ -95,6 +95,7 @@
 	} command_logfile_mode;
 
 	void processHistoricalSubstackRequest (RBackendRequest *request);
+	QStringList processPlainGenericRequest (const QStringList &calllist);
 	void processRBackendRequest (RBackendRequest *request);
 
 /** A list of all commands that have entered, and not yet left, the backend thread */

Modified: trunk/rkward/rkward/rbackend/rkrbackend.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackend.cpp	2011-05-05 16:04:37 UTC (rev 3535)
+++ trunk/rkward/rkward/rbackend/rkrbackend.cpp	2011-05-07 10:35:43 UTC (rev 3536)
@@ -827,12 +827,20 @@
 		}
 	}
 
-#warning TODO: extend this by sychronity parameter
 	RKRBackend::this_pointer->handleHistoricalSubstackRequest (list);
 
 	return R_NilValue;
 }
 
+SEXP doPlainGenericRequest (SEXP call, SEXP synchronous) {
+	RK_TRACE (RBACKEND);
+
+	R_CheckUserInterrupt ();
+
+	QStringList ret = RKRBackend::this_pointer->handlePlainGenericRequest (RKRSupport::SEXPToStringList (call), RKRSupport::SEXPToInt (synchronous));
+	return RKRSupport::StringListToSEXP (ret);
+}
+
 void R_CheckStackWrapper (void *) {
 	R_CheckStack ();
 }
@@ -969,6 +977,7 @@
 	R_CallMethodDef callMethods [] = {
 		{ "rk.do.error", (DL_FUNC) &doError, 1 },
 		{ "rk.do.command", (DL_FUNC) &doSubstackCall, 1 },
+		{ "rk.do.generic.request", (DL_FUNC) &doPlainGenericRequest, 2 },
 		{ "rk.get.structure", (DL_FUNC) &doGetStructure, 4 },
 		{ "rk.get.structure.global", (DL_FUNC) &doGetGlobalEnvStructure, 3 },
 		{ "rk.copy.no.eval", (DL_FUNC) &doCopyNoEval, 3 },
@@ -1300,6 +1309,15 @@
 	handleRequest (&request);
 }
 
+QStringList RKRBackend::handlePlainGenericRequest (const QStringList &parameters, bool synchronous) {
+	RK_TRACE (RBACKEND);
+
+	RBackendRequest request (synchronous, RBackendRequest::PlainGenericRequest);
+	request.params["call"] = parameters;
+	handleRequest (&request);
+	return request.params.value ("return").toStringList ();
+}
+
 void RKRBackend::initialize () {
 	RK_TRACE (RBACKEND);
 

Modified: trunk/rkward/rkward/rbackend/rkrbackend.h
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackend.h	2011-05-05 16:04:37 UTC (rev 3535)
+++ trunk/rkward/rkward/rbackend/rkrbackend.h	2011-05-07 10:35:43 UTC (rev 3536)
@@ -109,8 +109,11 @@
 	static void processX11Events ();
 
 	void handleRequest (RBackendRequest *request) { handleRequest (request, true); };
-/** A relic of history. Eventually most of these will be replaced by dedicated RBackendRequests. */
+/** A relic of history. See also handleGenericRequest */
 	void handleHistoricalSubstackRequest (const QStringList &list);
+/** Sends a request to the frontend and returns the result (an empty QStringList in case of asynchronous requests). Note that this function has considerable overlap with
+handleHistoricalSubstackRequest(). Exactly which requests get handled by which function is somewhat arbitrary, ATM. However, request that do not need sub-commands to be run, should generally be converted to use handlePlainGenericRequest(). (And probably all historicalSubstackRequests should be replaced!) */
+	QStringList handlePlainGenericRequest (const QStringList &parameters, bool synchronous);
 	RCommandProxy* fetchNextCommand ();
 
 /** The command currently being executed. */

Modified: trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.h
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.h	2011-05-05 16:04:37 UTC (rev 3535)
+++ trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.h	2011-05-07 10:35:43 UTC (rev 3536)
@@ -42,6 +42,7 @@
 		EvalRequest,
 		CallbackRequest,
 		HistoricalSubstackRequest,
+		PlainGenericRequest,
 		SetParamsFromBackend,
 		CommandLineIn,	/**< The next line of the current user command has been submitted in the backend. */
 #ifndef RKWARD_THREADED

Modified: trunk/rkward/rkward/rbackend/rkrsupport.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkrsupport.cpp	2011-05-05 16:04:37 UTC (rev 3535)
+++ trunk/rkward/rkward/rbackend/rkrsupport.cpp	2011-05-07 10:35:43 UTC (rev 3536)
@@ -124,6 +124,17 @@
 	return list;
 }
 
+SEXP RKRSupport::StringListToSEXP (const QStringList& list) {
+	RK_TRACE (RBACKEND);
+
+	SEXP ret = Rf_allocVector (STRSXP, list.size ());
+	for (int i = 0; i < list.size (); ++i) {
+		// TODO: in R 2.13.0 there is Rf_mkCharCE(). This could be used to set unicode strings, directly. But of course, we'd have to check, when exactly this was introduced.
+		SET_STRING_ELT (ret, i, Rf_mkChar (RKRBackend::this_pointer->current_locale_codec->fromUnicode (list[i]).data ()));
+	}
+	return ret;
+}
+
 RData::IntStorage RKRSupport::SEXPToIntArray (SEXP from_exp) {
 	RK_TRACE (RBACKEND);
 

Modified: trunk/rkward/rkward/rbackend/rkrsupport.h
===================================================================
--- trunk/rkward/rkward/rbackend/rkrsupport.h	2011-05-05 16:04:37 UTC (rev 3535)
+++ trunk/rkward/rkward/rbackend/rkrsupport.h	2011-05-07 10:35:43 UTC (rev 3536)
@@ -35,6 +35,7 @@
 	bool callSimpleBool (SEXP fun, SEXP arg, SEXP env);
 
 	QStringList SEXPToStringList (SEXP from_exp);
+	SEXP StringListToSEXP (const QStringList &list);
 	QString SEXPToString (SEXP from_exp);
 	RData::IntStorage SEXPToIntArray (SEXP from_exp);
 	int SEXPToInt (SEXP from_exp, int def_value = INT_MIN);

Modified: trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal.R
===================================================================
--- trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal.R	2011-05-05 16:04:37 UTC (rev 3535)
+++ trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal.R	2011-05-07 10:35:43 UTC (rev 3536)
@@ -72,6 +72,10 @@
 	return (.rk.rkreply)
 }
 
+".rk.do.plain.call" <- function (x, args=NULL, synchronous=TRUE) {
+	.Call ("rk.do.generic.request", c (x, args), isTRUE (synchronous))
+}
+
 # package information formats may - according to the help - be subject to change. Hence this function to cope with "missing" values
 # also it concatenates everything to a single vector, so we can easily get the whole structure with a single call
 ".rk.get.installed.packages" <- function () {
@@ -311,7 +315,7 @@
 
 "setwd" <- function () {
 	ret <- eval (body (base::setwd))
-	.rk.do.call ("wdChange", base::getwd ())
+	.rk.do.plain.call ("wdChange", base::getwd (), synchronous=FALSE)
 	invisible (ret)
 }
 formals (setwd) <- formals (base::setwd)

Modified: trunk/rkward/rkward/rbackend/rpackages/rkward/R/public.R
===================================================================
--- trunk/rkward/rkward/rbackend/rpackages/rkward/R/public.R	2011-05-05 16:04:37 UTC (rev 3535)
+++ trunk/rkward/rkward/rbackend/rpackages/rkward/R/public.R	2011-05-07 10:35:43 UTC (rev 3536)
@@ -114,7 +114,7 @@
 }
 
 "rk.get.tempfile.name" <- function (prefix="image", extension=".jpg") {
-	return (.rk.do.call ("get.tempfile.name", c (prefix, extension)))
+	return (.rk.do.plain.call ("get.tempfile.name", c (prefix, extension)))
 }
 
 "rk.get.workspace.url" <- function () {
@@ -137,7 +137,7 @@
 	}
 
 	# needs to come after initialization, so initialization alone does not trigger an update during startup
-	.rk.do.call ("set.output.file", x);
+	.rk.do.plain.call ("set.output.file", x, synchronous=FALSE);
 }
 
 "rk.save.workplace" <- function (file=NULL, description=NULL) {
@@ -194,7 +194,7 @@
 }
 
 "rk.print.code" <- function(code) {
-	.rk.cat.output (.rk.do.call ("highlightRCode", as.character (code)))
+	.rk.cat.output (.rk.do.plain.call ("highlightRCode", as.character (code)))
 }
 
 "rk.header" <- function (title, parameters=list (), level=1) {

Modified: trunk/rkward/rkward/windows/rkcommandeditorwindow.cpp
===================================================================
--- trunk/rkward/rkward/windows/rkcommandeditorwindow.cpp	2011-05-05 16:04:37 UTC (rev 3535)
+++ trunk/rkward/rkward/windows/rkcommandeditorwindow.cpp	2011-05-07 10:35:43 UTC (rev 3536)
@@ -1111,9 +1111,9 @@
 	QString ret;
 	KTextEditor::Attribute::Ptr m_defaultAttribute = iface->defaultStyle(KTextEditor::HighlightInterface::dsNormal);
 	if ( !m_defaultAttribute ) {
-		ret = "<pre>";
+		ret = "<pre class=\"code\">";
 	} else {
-		ret = QString("<pre style='%1%2%3%4'>")
+		ret = QString("<pre style='%1%2%3%4' class=\"code\">")
 				.arg(m_defaultAttribute->fontBold() ? "font-weight:bold;" : "")
 				.arg(m_defaultAttribute->fontItalic() ? "text-style:italic;" : "")
 				.arg("color:" + m_defaultAttribute->foreground().color().name() + ';');
@@ -1155,7 +1155,7 @@
 
 #else	// KDE < 4.4: No Highlighting Interface
 QString RKCommandHighlighter::commandToHTML (const QString r_command) {
-	return (QString ("<pre>") + r_command + "</pre>");
+	return (QString ("<pre class=\"code\">") + r_command + "</pre>");
 }
 #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