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

tfry at users.sourceforge.net tfry at users.sourceforge.net
Fri Feb 19 18:27:38 UTC 2010


Revision: 2746
          http://rkward.svn.sourceforge.net/rkward/?rev=2746&view=rev
Author:   tfry
Date:     2010-02-19 18:27:37 +0000 (Fri, 19 Feb 2010)

Log Message:
-----------
Move auto-submission code outside of RKStandardComponent. This should put an end to the crashes during automated testing.

Modified Paths:
--------------
    trunk/rkward/rkward/plugin/rkcomponent.cpp
    trunk/rkward/rkward/plugin/rkcomponent.h
    trunk/rkward/rkward/plugin/rkcomponentmap.cpp
    trunk/rkward/rkward/plugin/rkstandardcomponent.cpp
    trunk/rkward/rkward/plugin/rkstandardcomponent.h

Modified: trunk/rkward/rkward/plugin/rkcomponent.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponent.cpp	2010-02-18 21:55:31 UTC (rev 2745)
+++ trunk/rkward/rkward/plugin/rkcomponent.cpp	2010-02-19 18:27:37 UTC (rev 2746)
@@ -2,7 +2,7 @@
                           rkcomponent  -  description
                              -------------------
     begin                : Tue Dec 13 2005
-    copyright            : (C) 2005, 2006, 2009 by Thomas Friedrichsmeier
+    copyright            : (C) 2005, 2006, 2009, 2010 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -152,6 +152,22 @@
 	return false;		// never happens in RKComponentBase, but might in subclasses
 }
 
+RKComponentBase::ComponentStatus RKComponentBase::recursiveStatus () {
+	RK_TRACE (PLUGIN);
+
+	bool processing = false;
+	bool children_satisfied = true;
+	for (QHash<QString, RKComponentBase*>::const_iterator it = child_map.constBegin (); it != child_map.constEnd (); ++it) {
+		ComponentStatus s = it.value ()->recursiveStatus ();
+		if (s == Dead) return Dead;
+		if (s == Processing) processing = true;
+		else if (s != Satisfied) children_satisfied = false;
+	}
+	if (processing) return Processing;
+	if (children_satisfied && isSatisfied ()) return Satisfied;
+	return Unsatisfied;
+}
+
 //############### RKComponent ########################
 
 RKComponent::RKComponent (RKComponent *parent_component, QWidget *parent_widget) : QWidget (parent_widget) {
@@ -227,6 +243,7 @@
 
 bool RKComponent::isValid () {
 	RK_TRACE (PLUGIN);
+#warning TODO: I do not think we need this. Use recursiveStatus, instead
 
 	for (QHash<QString, RKComponentBase*>::const_iterator it = child_map.constBegin (); it != child_map.constEnd (); ++it) {
 		if (!(it.value ()->isSatisfied ())) return false;

Modified: trunk/rkward/rkward/plugin/rkcomponent.h
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponent.h	2010-02-18 21:55:31 UTC (rev 2745)
+++ trunk/rkward/rkward/plugin/rkcomponent.h	2010-02-19 18:27:37 UTC (rev 2746)
@@ -2,7 +2,7 @@
                           rkcomponent  -  description
                              -------------------
     begin                : Tue Dec 13 2005
-    copyright            : (C) 2005, 2006, 2007, 2009 by Thomas Friedrichsmeier
+    copyright            : (C) 2005, 2006, 2007, 2009, 2010 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -67,6 +67,12 @@
 		NotAllSettingsApplied,
 		NoSuchComponent
 	};
+	enum ComponentStatus {
+		Dead,
+		Processing,
+		Unsatisfied,
+		Satisfied
+	};
 /** for RTTI. see RKComponentBase::RKComponentTypes */
 	virtual int type () = 0;
 /** tries to locate a component (or property) described by identifier as a child (of any generation) of this RKComponentBase. If found, a pointer to this is returned. Also, the modifier parameter is set to hold any remaining modifier contained in the identifier.
@@ -83,6 +89,8 @@
 	bool isComponent () { return (type () >= ComponentBase); };
 /** returns satisfaction state. see setRequired () */
 	virtual bool isSatisfied ();
+/** returns somewhat more elaborate state than isSatisfied(). (Effectively identical in the base class). */
+	virtual ComponentStatus recursiveStatus ();
 /** currently valid (i.e. satisfied, even if required)? default implementation always returns true */
 	virtual bool isValid () { return true; };
 /** set to required: will only be satisfied if it is valid. Else: always satisfied (but subclasses might override to always be dissatisfied on really bad values. By default RKComponentBase is required at construction */

Modified: trunk/rkward/rkward/plugin/rkcomponentmap.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponentmap.cpp	2010-02-18 21:55:31 UTC (rev 2745)
+++ trunk/rkward/rkward/plugin/rkcomponentmap.cpp	2010-02-19 18:27:37 UTC (rev 2746)
@@ -2,7 +2,7 @@
                           rkcomponentmap.cpp  -  description
                              -------------------
     begin                : Thu May 12 2005
-    copyright            : (C) 2005, 2006, 2007, 2009 by Thomas Friedrichsmeier
+    copyright            : (C) 2005, 2006, 2007, 2009, 2010 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -19,6 +19,8 @@
 
 #include <qfileinfo.h>
 #include <qdir.h>
+#include <QTime>
+#include <QObjectCleanupHandler>
 
 #include <klocale.h>
 #include <kactioncollection.h>
@@ -265,27 +267,45 @@
 		// not considered an error
 	}
 
+	if (submit_mode == ManualSubmit) return true;
+
+
 	// Auto-Submit
-	if (submit_mode != ManualSubmit) {
+	// the call to processEvents(), below, is quite dangerous, as the component self-destructs on errors. This helps us prevent crashes.
+	QObjectCleanupHandler chandler;
+	chandler.add (component);
+	
 #ifndef Q_OS_WIN
-		// if the plugin takes longer than 5 seconds to settle, than that really is sort of buggy...
-		bool submit_ok = component->submit (5000, in_chain);
+	// if the plugin takes longer than 5 seconds to settle, than that really is sort of buggy...
+	const int max_wait = 5000;
 #else
 #warning Temporary workaround. Remove this.
-		// (yet on windows, the PHP backend is *real* slow. We give it a bit longer as long as we still use it...
-		bool submit_ok = component->submit (50000, in_chain);
+	// (yet on windows, the PHP backend is *real* slow. We give it a bit longer as long as we still use it...
+	const int max_wait = 50000;
 #endif
-		if (!submit_ok) {
-			if (submit_mode == AutoSubmitOrFail) {
-				component->kill ();
-			}
 
-			_message.append (i18n ("\nThe plugin could not be auto-submitted with these settings."));
-			if (message) *message = _message;
-			else KMessageBox::sorry (RKWardMainWindow::getMain (), _message, i18n ("Could not submit"));
+	QTime t;
+	t.start ();
+	while ((!chandler.isEmpty ()) && (component->recursiveStatus () == RKComponentBase::Processing) && (t.elapsed () < max_wait)) {
+		QCoreApplication::processEvents (QEventLoop::ExcludeUserInputEvents, (max_wait / 2));
+	}
+	RKComponentBase::ComponentStatus status = RKComponentBase::Dead;
+	if (!chandler.isEmpty ()) status = component->recursiveStatus ();
+	chandler.remove (component);	// otherwise it would auto-delete the component, later!
 
-			return (submit_mode != AutoSubmitOrFail);
+	if (status == RKComponentBase::Satisfied) {
+		bool ok = component->submit (in_chain);
+		RK_ASSERT (ok);
+	} else {
+		if (submit_mode == AutoSubmitOrFail) {
+			if (status != RKComponentBase::Dead) component->kill ();
 		}
+
+		_message.append (i18n ("\nThe plugin could not be auto-submitted with these settings."));
+		if (message) *message = _message;
+		else KMessageBox::sorry (RKWardMainWindow::getMain (), _message, i18n ("Could not submit"));
+
+		return (submit_mode != AutoSubmitOrFail);
 	}
 
 	return true;

Modified: trunk/rkward/rkward/plugin/rkstandardcomponent.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkstandardcomponent.cpp	2010-02-18 21:55:31 UTC (rev 2745)
+++ trunk/rkward/rkward/plugin/rkstandardcomponent.cpp	2010-02-19 18:27:37 UTC (rev 2746)
@@ -2,7 +2,7 @@
                           rkstandardcomponent  -  description
                              -------------------
     begin                : Sun Feb 19 2006
-    copyright            : (C) 2006, 2007, 2009 by Thomas Friedrichsmeier
+    copyright            : (C) 2006, 2007, 2009, 2010 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -24,8 +24,6 @@
 #include <qtimer.h>
 #include <QVBoxLayout>
 #include <QGroupBox>
-#include <QTime>
-#include <QObjectCleanupHandler>
 
 #include <klocale.h>
 #include <kmessagebox.h>
@@ -110,9 +108,7 @@
 	QString dummy = QFileInfo (filename).path() + '/' + xml->getStringAttribute (element, "file", "::nosuchfile::", DL_INFO);
 	have_help = QFileInfo (dummy).exists ();
 
-	handle_change_timer = new QTimer (this);
-	handle_change_timer->setSingleShot (true);
-	connect (handle_change_timer, SIGNAL (timeout ()), this, SLOT (handleChange ()));
+	update_pending = false;
 
 // construct the GUI
 	if (!parent_component) {					// top-level
@@ -326,34 +322,24 @@
 	changed ();
 }
 
-bool RKStandardComponent::submit (int max_wait, RCommandChain *in_chain) {
+RKComponentBase::ComponentStatus RKStandardComponent::recursiveStatus () {
 	RK_TRACE (PLUGIN);
 
-	// the call to processEvents(), below, is quite dangerous, as the component self-destructs on errors. This helps us prevent crashes.
-	QObjectCleanupHandler chandler;
-	chandler.add (this);
+	if (killed) return Dead;
+	if (backend->isBusy () || update_pending) return Processing;
+	return (RKComponentBase::recursiveStatus ());
+}
 
-	RCommandChain *old_chain = command_chain; 	// should always be 0, but let's store it cleanly
-	command_chain = in_chain;
-	bool result = false;
+bool RKStandardComponent::submit (RCommandChain *in_chain) {
+	RK_TRACE (PLUGIN);
 
-	QTime t;
-	t.start ();
-	while ((handle_change_timer->isActive () || backend->isBusy ()) && (t.elapsed () < max_wait)) {
-		if (chandler.isEmpty () || killed) return (false);
-		QCoreApplication::processEvents (QEventLoop::ExcludeUserInputEvents, (max_wait / 2));
-		if (chandler.isEmpty () || killed) return (false);
-	}
-	if (!(handle_change_timer->isActive () || backend->isBusy ())) {
-		if (isSatisfied ()) {
-			gui->ok ();
-			result = true;
-		}
-	}
-	if (chandler.isEmpty () || killed) return (result);
-	command_chain = old_chain;
-	chandler.remove (this);
-	return result;
+	if (!isSatisfied ()) return false;
+
+        RCommandChain *prev_chain = command_chain;
+	command_chain = in_chain;
+	gui->ok ();
+	command_chain = prev_chain;
+	return true;
 }
 
 void RKStandardComponent::close () {
@@ -372,13 +358,18 @@
 	if (!created) return;
 	if (gui) gui->enableSubmit (false);
 
-	// delay actual handling, until all changes have run up
-	handle_change_timer->start (10);
+	// don't trigger update twice
+	if (!update_pending) {
+		update_pending = true;
+		QTimer::singleShot (0, this, SLOT (handleChange ()));
+	}
 }
 
 void RKStandardComponent::handleChange () {
 	RK_TRACE (PLUGIN);
 
+	if (killed) return;
+	update_pending = false;
 	backend->preprocess (0);
 	backend->calculate (0);
 	backend->printout (0);

Modified: trunk/rkward/rkward/plugin/rkstandardcomponent.h
===================================================================
--- trunk/rkward/rkward/plugin/rkstandardcomponent.h	2010-02-18 21:55:31 UTC (rev 2745)
+++ trunk/rkward/rkward/plugin/rkstandardcomponent.h	2010-02-19 18:27:37 UTC (rev 2746)
@@ -2,7 +2,7 @@
                           rkstandardcomponent  -  description
                              -------------------
     begin                : Sun Feb 19 2006
-    copyright            : (C) 2006, 2007, 2009 by Thomas Friedrichsmeier
+    copyright            : (C) 2006, 2007, 2009, 2010 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -69,13 +69,14 @@
 	QString getFilename () { return filename; };
 	RKComponentHandle *getHandle () { return handle; };
 	bool haveHelp () { return have_help; };
-/** tries to submit. Warning: This function waits for all changes to come in and may not return immediately!
- at param max_wait Maximum time to wait for changes to settle in msecs (approx.)
+/** Submits the current code (by simulating a click on the ok button).
 @param in_chain The command chain to insert the command in (0 for regular command stack).
- at return true, if the plugin-code could be submitted */
-	bool submit (int max_wait=1000, RCommandChain *in_chain = 0);
+ at return false, if the plugin-code could not be submitted (e.g. plugin was not satisfied) */
+	bool submit (RCommandChain *in_chain = 0);
 /** convenience access function: closes the corresponding GUI */
 	void close ();
+/** reimplemented to actually return Dead or Processing when appropriate */
+	ComponentStatus recursiveStatus ();
 
 	RCommandChain *commandChain () const { return command_chain; };
 public slots:
@@ -104,7 +105,7 @@
 	RKStandardComponentGUI *gui;
 	RKComponentHandle *handle;
 	RKStandardComponentStack *wizard;
-	QTimer *handle_change_timer;
+	bool update_pending;
 	RCommandChain *command_chain;
 /** Avoid updating code-display, etc. until the component is fully created */
 	bool created;


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