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

tfry at users.sourceforge.net tfry at users.sourceforge.net
Tue Sep 29 12:53:13 UTC 2009


Revision: 2670
          http://rkward.svn.sourceforge.net/rkward/?rev=2670&view=rev
Author:   tfry
Date:     2009-09-29 12:53:03 +0000 (Tue, 29 Sep 2009)

Log Message:
-----------
Add beginnings of a qtscript-based code generation backend. Unfinished.

Modified Paths:
--------------
    trunk/rkward/rkward/plugin/rkstandardcomponent.cpp
    trunk/rkward/rkward/scriptbackends/CMakeLists.txt
    trunk/rkward/rkward/scriptbackends/phpbackend.cpp
    trunk/rkward/rkward/scriptbackends/scriptbackend.cpp

Added Paths:
-----------
    trunk/rkward/rkward/scriptbackends/qtscriptbackend.cpp
    trunk/rkward/rkward/scriptbackends/qtscriptbackend.h

Modified: trunk/rkward/rkward/plugin/rkstandardcomponent.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkstandardcomponent.cpp	2009-09-28 10:41:16 UTC (rev 2669)
+++ trunk/rkward/rkward/plugin/rkstandardcomponent.cpp	2009-09-29 12:53:03 UTC (rev 2670)
@@ -33,6 +33,7 @@
 
 #include "rkstandardcomponentgui.h"
 #include "../scriptbackends/phpbackend.h"
+#include "../scriptbackends/qtscriptbackend.h"
 #include "../scriptbackends/simplebackend.h"
 #include "../misc/xmlhelper.h"
 #include "../settings/rksettingsmoduleplugins.h"
@@ -84,7 +85,12 @@
 	QDomElement element = xml->getChildElement (doc_element, "code", DL_WARNING);
 	if (element.hasAttribute ("file")) {
 		QString dummy = QFileInfo (filename).path() + '/' + xml->getStringAttribute (element, "file", "code.php", DL_WARNING);
-		backend = new PHPBackend (dummy);
+
+		if (!dummy.endsWith (".php")) {
+			backend = new QtScriptBackend (dummy);
+		} else {
+			backend = new PHPBackend (dummy);
+		}
 	} else {
 		SimpleBackend *back = new SimpleBackend ();
 		back->setPreprocessTemplate (xml->getStringAttribute (element, "preprocess", QString::null, DL_INFO));

Modified: trunk/rkward/rkward/scriptbackends/CMakeLists.txt
===================================================================
--- trunk/rkward/rkward/scriptbackends/CMakeLists.txt	2009-09-28 10:41:16 UTC (rev 2669)
+++ trunk/rkward/rkward/scriptbackends/CMakeLists.txt	2009-09-29 12:53:03 UTC (rev 2670)
@@ -7,6 +7,7 @@
    phpbackend.cpp
    scriptbackend.cpp
    simplebackend.cpp
+   qtscriptbackend.cpp
    )
 
 QT4_AUTOMOC(${scriptbackends_STAT_SRCS})

Modified: trunk/rkward/rkward/scriptbackends/phpbackend.cpp
===================================================================
--- trunk/rkward/rkward/scriptbackends/phpbackend.cpp	2009-09-28 10:41:16 UTC (rev 2669)
+++ trunk/rkward/rkward/scriptbackends/phpbackend.cpp	2009-09-29 12:53:03 UTC (rev 2670)
@@ -2,7 +2,7 @@
                           phpbackend  -  description
                              -------------------
     begin                : Mon Jul 26 2004
-    copyright            : (C) 2004, 2007 by Thomas Friedrichsmeier
+    copyright            : (C) 2004, 2007, 2009 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -90,15 +90,11 @@
 	RK_TRACE (PHP);
 	if (!dead) {
 		dead = true;
-		php_process->kill ();
+		if (php_process) php_process->kill ();
 		QTimer::singleShot (10000, this, SLOT (deleteLater()));	// don't wait for ever for the process to die, even if it's somewhat dangerous
 	}
 
 	busy = false;
-	
-	while (command_stack.count ()) {
-		delete command_stack.takeFirst ();
-	}
 }
 
 void PHPBackend::tryNextFunction () {

Added: trunk/rkward/rkward/scriptbackends/qtscriptbackend.cpp
===================================================================
--- trunk/rkward/rkward/scriptbackends/qtscriptbackend.cpp	                        (rev 0)
+++ trunk/rkward/rkward/scriptbackends/qtscriptbackend.cpp	2009-09-29 12:53:03 UTC (rev 2670)
@@ -0,0 +1,252 @@
+/***************************************************************************
+                          krossbackend  -  description
+                             -------------------
+    begin                : Mon Sep 28 2009
+    copyright            : (C) 2009 by Thomas Friedrichsmeier
+    email                : tfry at users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+#include "qtscriptbackend.h"
+
+#include <QTimer>
+#include <QDir>
+
+#include "klocale.h"
+#include "kmessagebox.h"
+
+#include "../misc/rkcommonfunctions.h"
+
+#include "../debug.h"
+
+QtScriptBackend::QtScriptBackend (const QString &filename) : ScriptBackend () {
+	RK_TRACE (PHP);
+
+	script_thread = 0;
+	QtScriptBackend::filename = filename;
+	dead = false;
+	busy = true;
+}
+
+
+QtScriptBackend::~QtScriptBackend () {
+	RK_TRACE (PHP);
+
+	if (script_thread) script_thread->terminate ();
+}
+
+bool QtScriptBackend::initialize (RKComponentPropertyCode *code_property, bool add_headings) {
+	RK_TRACE (PHP);
+
+	if (script_thread) {
+		RK_DO (qDebug ("another template is already openend in this backend"), PHP, DL_ERROR);
+		return false;
+	}
+
+	QDir files_path (RKCommonFunctions::getRKWardDataDir () + "phpfiles/");
+	QString common_js (files_path.absoluteFilePath ("common.js"));
+
+	script_thread = new QtScriptBackendThread (common_js, filename, this);
+	connect (script_thread, SIGNAL (error(const QString&)), this, SLOT (threadError(const QString&)));
+	connect (script_thread, SIGNAL (commandDone(const QString&)), this, SLOT (commandDone(const QString&)));
+	connect (script_thread, SIGNAL (needData(const QString&)), this, SLOT (needData(const QString&)));
+	current_type = ScriptBackend::Ignore;
+
+	QtScriptBackend::code_property = code_property;
+	QtScriptBackend::add_headings = add_headings;
+
+	return true;
+}
+
+void QtScriptBackend::destroy () {
+	RK_TRACE (PHP);
+	if (!dead) {
+		dead = true;
+		if (script_thread) script_thread->terminate ();
+		QTimer::singleShot (10000, this, SLOT (deleteLater()));	// don't wait for ever for the process to die, even if it's somewhat dangerous
+	}
+
+	busy = false;
+}
+
+void QtScriptBackend::tryNextFunction () {
+	RK_TRACE (PHP);
+
+	if (script_thread && (!busy) && (!command_stack.isEmpty ())) {
+	/// clean up previous command if applicable
+		if (command_stack.first ()->complete) {
+			delete command_stack.takeFirst ();
+			
+			if (!command_stack.count ()) return;
+		}
+		
+		RK_DO (qDebug ("submitting QtScript code: %s", command_stack.first ()->command.toLatin1 ().data ()), PHP, DL_DEBUG);
+		script_thread->setCommand (command_stack.first ()->command);
+		busy = true;
+		command_stack.first ()->complete = true;
+		current_flags = command_stack.first ()->flags;
+		current_type = command_stack.first ()->type;
+	}
+}
+
+void QtScriptBackend::writeData (const QString &data) {
+	RK_TRACE (PHP);
+
+	RK_DO (qDebug ("submitting data: %s", data.toLatin1 ().data ()), PHP, DL_DEBUG);
+	script_thread->setData (data);
+	tryNextFunction ();
+}
+
+void QtScriptBackend::threadError (const QString &message) {
+	RK_TRACE (PHP);
+
+	if (dead) return;	// we are already dead, so we've shown an error before.
+
+	KMessageBox::error (0, i18n ("The QtScript-backend has reported an error:\n%1", message), i18n ("Scripting error"));
+
+	emit (haveError ());
+	destroy ();
+}
+
+void QtScriptBackend::commandDone (const QString &result) {
+	RK_TRACE (PHP);
+
+	commandFinished (result);
+}
+
+void QtScriptBackend::needData (const QString &identifier) {
+	RK_TRACE (PHP);
+
+	emit (requestValue (identifier));
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#include <kurl.h>
+
+QtScriptBackendThread::QtScriptBackendThread (const QString &commonfile, const QString &scriptfile, QtScriptBackend *parent) : QThread (parent) {
+	RK_TRACE (PHP);
+
+	_commonfile = commonfile;
+	_scriptfile = scriptfile;
+	start ();
+}
+
+QtScriptBackendThread::~QtScriptBackendThread () {
+	RK_TRACE (PHP);
+}
+
+void QtScriptBackendThread::setCommand (const QString &command) {
+	RK_TRACE (PHP);
+
+	mutex.lock ();
+	RK_ASSERT (_command.isEmpty ());
+	_command = command;
+	mutex.unlock ();
+}
+
+void QtScriptBackendThread::setData (const QString &data) {
+	RK_TRACE (PHP);
+
+	mutex.lock ();
+	RK_ASSERT (_data.isNull ());
+	if (data.isNull ()) _data = "";
+	else _data = data;
+	mutex.unlock ();
+}
+
+QString QtScriptBackendThread::getValue (const QString &identifier) {
+	RK_TRACE (PHP);
+
+	emit (needData (identifier));
+
+	QString ret;
+	while (1) {
+		mutex.lock ();
+		if (!_data.isNull ()) {
+			ret = _data;
+			_data.clear ();
+		}
+		mutex.unlock ();
+
+		if (!ret.isNull ()) return (ret);
+
+		msleep (5);
+	}
+}
+
+bool QtScriptBackendThread::includeFile (const QString &filename) {
+	RK_TRACE (PHP);
+
+	QString _filename = filename;
+	if (!filename.startsWith ("/")) {
+		KUrl script_path = KUrl (QUrl::fromLocalFile (_scriptfile)).upUrl ();
+		script_path.addPath (filename);
+		_filename = script_path.toLocalFile ();
+	}
+
+        QFile file (_filename);
+        if (!file.open (QIODevice::ReadOnly | QIODevice::Text)) {
+		emit (error (i18n ("The file \"%1\" (needed by \"%2\") could not be found. Please check your installation.", _filename, _scriptfile)));
+		return false;
+	}
+
+	// evaluate in global context
+	engine.currentContext ()->setActivationObject (engine.globalObject ());
+	QScriptValue result = engine.evaluate (file.readAll(), _filename);
+
+	if (result.isError ()) {
+		emit (error (result.toString ()));
+		return false;
+	}
+
+	return true;
+}
+
+void QtScriptBackendThread::run () {
+	RK_TRACE (PHP);
+
+	QScriptValue backend_object = engine.newQObject (this);
+	engine.globalObject ().setProperty ("thingy", backend_object);
+
+	if (!includeFile (_commonfile)) return;
+	if (!includeFile (_scriptfile)) return;
+
+	emit (commandDone ("startup complete"));
+
+	QString command;
+	while (1) {
+		mutex.lock ();
+		if (!_command.isEmpty ()) {
+			command = _command;
+			_command.clear ();
+		}
+		mutex.unlock ();
+
+		if (command.isEmpty ()) {
+			msleep (5);
+			continue;
+		}
+
+		// do it!
+		QScriptValue result = engine.evaluate (command);
+		if (result.isError ()) {
+			emit (error (result.toString ()));
+			return;
+		} else {
+			emit (commandDone (result.toString ()));
+		}
+
+		command.clear ();
+	}
+}
+
+#include "qtscriptbackend.moc"

Added: trunk/rkward/rkward/scriptbackends/qtscriptbackend.h
===================================================================
--- trunk/rkward/rkward/scriptbackends/qtscriptbackend.h	                        (rev 0)
+++ trunk/rkward/rkward/scriptbackends/qtscriptbackend.h	2009-09-29 12:53:03 UTC (rev 2670)
@@ -0,0 +1,90 @@
+/***************************************************************************
+                          krossbackend  -  description
+                             -------------------
+    begin                : Mon Sep 28 2009
+    copyright            : (C) 2009 by Thomas Friedrichsmeier
+    email                : tfry at users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef QTSCRIPTBACKEND_H
+#define QTSCRIPTBACKEND_H
+
+#include "scriptbackend.h"
+
+class QtScriptBackendThread;
+
+/** This class allows to use QtScript as a scripting backend in RKWard.
+
+The script itself is run in a separate thread to ensure good performance even for complex scripts. This is especially important for spinboxes, where the value is changes many times in quick succession. Note that this is also the reason not to use Kross, which appears to be not thread safe.
+
+TODO: The code is currently based on the old PHPBackend. Once that is truely obsolete, there should be room for redesigning several aspects. */
+class QtScriptBackend : public ScriptBackend {
+	Q_OBJECT
+public:
+	QtScriptBackend (const QString &filename);
+
+	~QtScriptBackend ();
+
+	bool initialize (RKComponentPropertyCode *code_property=0, bool add_headings=true);
+	void destroy ();
+	
+	void preprocess (int flags) { callFunction ("preprocess ();\n", flags, Preprocess); };
+	void calculate (int flags) { callFunction ("calculate ();\n", flags, Calculate); };
+	void printout (int flags) { callFunction ("printout ();\n", flags, Printout); };
+	void preview (int flags) { callFunction ("getPreview ();\n", flags, Preview); };
+	void writeData (const QString &data);
+public slots:
+	void threadError (const QString &message);
+	void commandDone (const QString &result);
+	void needData (const QString &identifier);
+private:
+	void tryNextFunction ();
+	QtScriptBackendThread *script_thread;
+
+	bool dead;
+
+	QString filename;
+};
+
+#include <QThread>
+#include <QMutex>
+#include <QScriptEngine>
+
+class QtScriptBackendThread : public QThread {
+	Q_OBJECT
+public:
+	QtScriptBackendThread (const QString &commonfile, const QString &scriptfile, QtScriptBackend *parent);
+	~QtScriptBackendThread ();
+
+	void setCommand (const QString &command);
+	void setData (const QString &data);
+signals:
+	void commandDone (const QString &result);
+	void needData (const QString &identifier);
+	void error (const QString &error);
+protected slots:
+	QString getValue (const QString &identifier);
+	bool includeFile (const QString &filename);
+protected:
+	void run ();
+private:
+	QString _command;
+	QString _data;
+	QString _commonfile;
+	QString _scriptfile;
+
+	QScriptEngine engine;
+
+	QMutex mutex;
+};
+
+#endif

Modified: trunk/rkward/rkward/scriptbackends/scriptbackend.cpp
===================================================================
--- trunk/rkward/rkward/scriptbackends/scriptbackend.cpp	2009-09-28 10:41:16 UTC (rev 2669)
+++ trunk/rkward/rkward/scriptbackends/scriptbackend.cpp	2009-09-29 12:53:03 UTC (rev 2670)
@@ -2,7 +2,7 @@
                           scriptbackend  -  description
                              -------------------
     begin                : Sun Aug 15 2004
-    copyright            : (C) 2004, 2006 by Thomas Friedrichsmeier
+    copyright            : (C) 2004, 2006, 2009 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -27,6 +27,9 @@
 }
 
 ScriptBackend::~ScriptBackend () {
+	while (command_stack.count ()) {
+		delete command_stack.takeFirst ();
+	}
 }
 
 void ScriptBackend::callFunction (const QString &function, int flags, int type) {


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