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

tfry at users.sf.net tfry at users.sf.net
Tue Oct 28 18:34:24 UTC 2014


Revision: 4973
          http://sourceforge.net/p/rkward/code/4973
Author:   tfry
Date:     2014-10-28 18:34:23 +0000 (Tue, 28 Oct 2014)
Log Message:
-----------
Use QtScript, instead of Kross for scripting UI logic.
QtScript is already used for evaluating plugin .js files, thus we are getting rid of one dependency, here (QtScript feels also slightly faster to initialize).
The reason for using Kross, back then was to allow fully custom widgets using Kross forms, experimentally. This never became a documented feature,
and if we are going to implement it in the future, it will most naturally be based on QML, then.

Modified Paths:
--------------
    trunk/rkward/rkward/CMakeLists.txt
    trunk/rkward/rkward/plugin/rkstandardcomponent.cpp
    trunk/rkward/rkward/plugins/testing/test1.xml
    trunk/rkward/rkward/scriptbackends/rkcomponentscripting.cpp
    trunk/rkward/rkward/scriptbackends/rkcomponentscripting.h

Modified: trunk/rkward/rkward/CMakeLists.txt
===================================================================
--- trunk/rkward/rkward/CMakeLists.txt	2014-10-28 12:09:30 UTC (rev 4972)
+++ trunk/rkward/rkward/CMakeLists.txt	2014-10-28 18:34:23 UTC (rev 4973)
@@ -63,7 +63,7 @@
 		@ONLY)
 ENDIF(Q_WS_MAC)
 
-TARGET_LINK_LIBRARIES(rkward.frontend ${KDE4_KDECORE_LIBS} windows ${RKWARD_ADDLIBS} agents dialogs plugin settings dataeditor core scriptbackends rbackend misc ${KDE4_KTEXTEDITOR_LIBS} ${KDE4_KHTML_LIBS} ${KDE4_KFILE_LIBS} ${KDE4_KDEUI_LIBS} ${KDE4_KROSSCORE_LIBS} ${QT_QTSCRIPT_LIBRARY} ${QT_QTNETWORK_LIBRARY})
+TARGET_LINK_LIBRARIES(rkward.frontend ${KDE4_KDECORE_LIBS} windows ${RKWARD_ADDLIBS} agents dialogs plugin settings dataeditor core scriptbackends rbackend misc ${KDE4_KTEXTEDITOR_LIBS} ${KDE4_KHTML_LIBS} ${KDE4_KFILE_LIBS} ${KDE4_KDEUI_LIBS} ${QT_QTSCRIPT_LIBRARY} ${QT_QTNETWORK_LIBRARY})
 
 # wrapper executable
 GET_DIRECTORY_PROPERTY(R_EXECUTABLE DIRECTORY rbackend DEFINITION R_EXECUTABLE)

Modified: trunk/rkward/rkward/plugin/rkstandardcomponent.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkstandardcomponent.cpp	2014-10-28 12:09:30 UTC (rev 4972)
+++ trunk/rkward/rkward/plugin/rkstandardcomponent.cpp	2014-10-28 18:34:23 UTC (rev 4973)
@@ -679,14 +679,11 @@
 			} else {
 				xml.displayError (&e, QString ("optiondisplay element is not allowed outside of an optionset"), DL_ERROR);
 			}
-		} else if (e.tagName () == QLatin1String ("scriptable")) {
-			widget = new RKComponent (component (), parent_widget);
-			QVBoxLayout *layout = new QVBoxLayout (widget);
-			layout->setContentsMargins (0, 0, 0, 0);
-			KVBox *box = new KVBox (widget);
-			layout->addWidget (box);
-			QString id_adjust;
-			parent->standardComponent (&id_adjust)->scriptingProxy ()->addScriptableWidget (id_adjust + id, widget);
+/*		} else if (e.tagName () == QLatin1String ("scriptable")) {
+ * TODO: We used to have some purely experimental code, here, to support fully custom elements (scripted via Kross->Forms). We will want 
+ * to have something like that, eventually. After porting to KF5, Qt5, and thus dropping legacy support, the natural way to add this will
+ * be QML.
+ */
 		} else {
 			xml.displayError (&e, QString ("Invalid tagname '%1'").arg (e.tagName ()), DL_ERROR);
 		}

Modified: trunk/rkward/rkward/plugins/testing/test1.xml
===================================================================
--- trunk/rkward/rkward/plugins/testing/test1.xml	2014-10-28 12:09:30 UTC (rev 4972)
+++ trunk/rkward/rkward/plugins/testing/test1.xml	2014-10-28 18:34:23 UTC (rev 4973)
@@ -9,9 +9,9 @@
  			last_command_id = -1;
 			gui.setValue ("text.text", "Select a dependent variable!");
 
-			f = Kross.module('forms');
+			/*f = Kross.module('forms');
 			label = f.createWidget(scripty, 'QLabel', 'Label', {});
-			label.setText ('<b>This label was created by the script. Be sure to read the label above, too.</b>');
+			label.setText ('<b>This label was created by the script. Be sure to read the label above, too.</b>');*/
 
 			gui.addChangeCommand ("x.available", "updateText ()");
 			updateText = function () {
@@ -46,7 +46,7 @@
 						<varslot type="numeric" id="y" source="vars" required="true" multi="true" label="fixed factors"/>
 					</column>
 				</row>
-				<scriptable id="scripty"/>
+				<!--<scriptable id="scripty"/>-->
 			</tab>
 			<tab label="Model">
 				<formula id="model" fixed_factors="y" dependent="x" label="Now choose the model"/>

Modified: trunk/rkward/rkward/scriptbackends/rkcomponentscripting.cpp
===================================================================
--- trunk/rkward/rkward/scriptbackends/rkcomponentscripting.cpp	2014-10-28 12:09:30 UTC (rev 4972)
+++ trunk/rkward/rkward/scriptbackends/rkcomponentscripting.cpp	2014-10-28 18:34:23 UTC (rev 4973)
@@ -20,6 +20,7 @@
 #include <klocale.h>
 #include <kdeversion.h>
 #include <kmessagebox.h>
+#include <QDir>
 
 #include "../plugin/rkcomponent.h"
 #include "../core/robjectlist.h"
@@ -35,9 +36,8 @@
 	RK_ASSERT (component);
 	RKComponentScriptingProxy::component = component;
 
-	script = new Kross::Action (this, QString ());
-	script->setInterpreter ("qtscript");
-	script->addObject (this, "_rkward");
+	QScriptValue backend_object = engine.newQObject (this);
+	engine.globalObject ().setProperty ("_rkward", backend_object);
 }
 
 RKComponentScriptingProxy::~RKComponentScriptingProxy () {
@@ -59,13 +59,7 @@
 	QDir files_path (RKCommonFunctions::getRKWardDataDir () + "phpfiles/");
 	_command.prepend ("_rkward.include('" + files_path.absoluteFilePath ("rkcomponentscripting.js") + "');\n");
 	_command.prepend ("_rkward.include('" + files_path.absoluteFilePath ("common.js") + "');\n");
-#if not KDE_IS_VERSION(4,3,0)
-	_command.prepend ("_rk_eval = function (x) { eval (x); }\n");
-#endif
-	script->setCode (_command.toUtf8 ());
-
-	script->trigger ();
-	handleScriptError ();
+	evaluate (_command);
 }
 
 void RKComponentScriptingProxy::handleScriptError (const QString& current_file) {
@@ -73,9 +67,10 @@
 
 	QString file = current_file;
 	if (file.isEmpty ()) file = _scriptfile;
-	if (script->hadError ()) {
-		QString message = i18n ("There was an error while evaluating script code.\nFile: %1\nLine: %2\nMessage: %3.", file, script->errorLineNo(), script->errorMessage());
-		KMessageBox::detailedError (0, message, script->errorTrace ());
+	if (engine.hasUncaughtException ()) {
+		QString message = i18n ("Script Error: %1\n", engine.uncaughtException ().toString ());
+		KMessageBox::detailedError (0, message, engine.uncaughtExceptionBacktrace ().join ("\n"));
+		engine.clearExceptions ();
 		emit (haveError());
 	}
 }
@@ -100,23 +95,16 @@
 	handleScriptError (_filename);
 }
 
-void RKComponentScriptingProxy::evaluate (const QByteArray &code) {
+void RKComponentScriptingProxy::evaluate (const QString &code) {
 	RK_TRACE (PHP);
 
-#if KDE_IS_VERSION(4,3,0)
-	script->evaluate (code);
-#else
-	script->callFunction ("_rk_eval", QVariantList() << QString (code));
-#endif
+	// evaluate in global context
+	engine.currentContext ()->setActivationObject (engine.globalObject ());
+	QScriptValue result = engine.evaluate (code, _scriptfile);
+
 	handleScriptError ();
 }
 
-void RKComponentScriptingProxy::addScriptableWidget (const QString& name, QWidget *widget) {
-	RK_TRACE (PHP);
-
-	script->addObject (widget, name);
-}
-
 void RKComponentScriptingProxy::addChangeCommand (const QString& changed_id, const QString& command) {
 	RK_TRACE (PHP);
 
@@ -131,7 +119,7 @@
 			connect (static_cast<RKComponentPropertyBase*> (base), SIGNAL (valueChanged(RKComponentPropertyBase*)), this, SLOT (propertyChanged(RKComponentPropertyBase*)));
 		}
 	} else {
-		script->setError (QString ("error ('No such property %1 (failed portion was %2)');\n").arg (changed_id, remainder));
+		evaluate (QString ("error ('No such property %1 (failed portion was %2)');\n").arg (changed_id, remainder));
 	}
 }
 
@@ -160,36 +148,26 @@
 	return (QVariant (com.command->id ()));
 }
 
-static QVariant marshall (RData *data) {
+static QScriptValue marshall (QScriptEngine *engine, RData *data) {
 	RK_TRACE (PHP);
 
 	if (data->getDataType () == RData::StringVector) {
-		return (QVariant (data->stringVector()));
+		return (qScriptValueFromSequence (engine, data->stringVector()));
 	} else if (data->getDataType () == RData::IntVector) {
-		const RData::IntStorage& is = data->intVector ();
-		QVariantList ret;
-		for (int i = 0; i < is.size (); ++i) {
-			ret.append (QVariant (is[i]));
-		}
-		return ret;
+		return (qScriptValueFromSequence (engine, data->intVector()));
 	} else if (data->getDataType () == RData::RealVector) {
-		const RData::RealStorage& rs = data->realVector ();
-		QVariantList ret;
-		for (int i = 0; i < rs.size (); ++i) {
-			ret.append (QVariant (rs[i]));
-		}
-		return ret;
+		return (qScriptValueFromSequence (engine, data->realVector()));
 	} else if (data->getDataType () == RData::StructureVector) {
 		const RData::RDataStorage& rs = data->structureVector ();
-		QVariantList ret;
+		QScriptValue ret = engine->newArray (rs.size ());
 		for (int i = 0; i < rs.size (); ++i) {
-			ret.append (marshall (rs[i]));
+			ret.setProperty (i, marshall (engine, rs[i]));
 		}
 		return ret;
 	} else {
 		RK_ASSERT (false);
 	}
-	return QVariant ();
+	return QScriptValue ();
 }
 
 void RKComponentScriptingProxy::scriptRCommandFinished (RCommand* command) {
@@ -209,10 +187,12 @@
 	if (command->wasCanceled ()) return;
 	if (command->failed ()) RK_DEBUG (PHP, DL_ERROR, "Plugin script R command %s failed. Full output wsa %s", qPrintable (command->command ()), qPrintable (command->fullOutput ()));
 
-	QVariantList args;
-	args.append (marshall (command));
-	args.append (QVariant (command->id ()));
-	script->callFunction (callback, args);
+	QScriptValueList args;
+	args.append (marshall (&engine, command));
+	args.append (QScriptValue (command->id ()));
+	QScriptValue callback_obj = engine.globalObject ().property (callback);
+	callback_obj.call (engine.globalObject (), args);
+	handleScriptError ();
 }
 
 void RKComponentScriptingProxy::componentChanged (RKComponent* changed) {
@@ -260,7 +240,7 @@
 	if (resolved && modifier.isEmpty () && resolved->isProperty ()) {
 		static_cast<RKComponentPropertyBase*> (resolved)->setValue (value);
 	} else {
-		script->setError (QString ("error ('No such property %1 (failed portion was %2)');\n").arg (id, modifier));
+		evaluate (QString ("error ('No such property %1 (failed portion was %2)');\n").arg (id, modifier));
 	}
 }
 
@@ -277,7 +257,7 @@
 		}
 		static_cast<RKComponentPropertyBase*> (resolved)->setValue (value.join ("\n"));
 	} else {
-		script->setError (QString ("error ('No such property %1 (failed portion was %2)');\n").arg (id, modifier));
+		evaluate (QString ("error ('No such property %1 (failed portion was %2)');\n").arg (id, modifier));
 	}
 }
 

Modified: trunk/rkward/rkward/scriptbackends/rkcomponentscripting.h
===================================================================
--- trunk/rkward/rkward/scriptbackends/rkcomponentscripting.h	2014-10-28 12:09:30 UTC (rev 4972)
+++ trunk/rkward/rkward/scriptbackends/rkcomponentscripting.h	2014-10-28 18:34:23 UTC (rev 4973)
@@ -20,8 +20,8 @@
 
 #include <QObject>
 #include <QHash>
+#include <QScriptEngine>
 
-#include <kross/core/action.h>
 #include "../rbackend/rcommand.h"
 
 class RKComponent;
@@ -41,7 +41,6 @@
 	~RKComponentScriptingProxy ();
 
 	void initialize (const QString& file, const QString& command);
-	void addScriptableWidget (const QString& name, QWidget *widget);
 public slots:
 	void componentChanged (RKComponent* changed);
 	void propertyChanged (RKComponentPropertyBase* changed);
@@ -68,15 +67,14 @@
 	void scriptRCommandFinished (RCommand* command);
 private:
 	RKComponent* component;
-	Kross::Action* script;
+	QScriptEngine engine;
 	struct OutstandingCommand {
 		RCommand *command;
 		QString callback;
 	};
 	QList<OutstandingCommand> outstanding_commands;
 	QString _scriptfile;
-/** helper function for compatibility with KDE < 4.3 */
-	void evaluate (const QByteArray &code);
+	void evaluate (const QString &code);
 
 	void handleChange (RKComponentBase* changed);
 	QHash<RKComponentBase*, QString> component_commands;





More information about the rkward-tracker mailing list