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

tfry at users.sourceforge.net tfry at users.sourceforge.net
Mon Jan 8 00:52:30 UTC 2007


Revision: 1086
          http://svn.sourceforge.net/rkward/?rev=1086&view=rev
Author:   tfry
Date:     2007-01-07 16:52:29 -0800 (Sun, 07 Jan 2007)

Log Message:
-----------
First (incomplete) go at adding a help system

Modified Paths:
--------------
    trunk/rkward/rkward/plugin/rkcomponentmap.cpp
    trunk/rkward/rkward/plugin/rkcomponentmap.h
    trunk/rkward/rkward/plugin/rkstandardcomponent.cpp
    trunk/rkward/rkward/plugin/rkstandardcomponent.h
    trunk/rkward/rkward/plugin/rkstandardcomponentgui.cpp
    trunk/rkward/rkward/plugins/descriptive/descriptive_statistics.xml
    trunk/rkward/rkward/windows/rkhtmlwindow.cpp
    trunk/rkward/rkward/windows/rkhtmlwindow.h

Added Paths:
-----------
    trunk/rkward/rkward/plugins/descriptive/descriptive_statistics.rkh

Modified: trunk/rkward/rkward/plugin/rkcomponentmap.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponentmap.cpp	2007-01-07 20:41:34 UTC (rev 1085)
+++ trunk/rkward/rkward/plugin/rkcomponentmap.cpp	2007-01-08 00:52:29 UTC (rev 1086)
@@ -86,6 +86,26 @@
 }
 
 //static
+QString RKComponentMap::getComponentId (RKComponentHandle* by_component) {
+	RK_TRACE (PLUGIN);
+
+	return (getMap ()->getComponentIdLocal (by_component));
+}
+
+QString RKComponentMap::getComponentIdLocal (RKComponentHandle* component) {
+	RK_TRACE (PLUGIN);
+
+	for (ComponentMap::iterator it = components.begin (); it != components.end (); ++it) {
+		if (it.data () == component) {
+			return it.key ();
+		}
+	}
+
+	RK_ASSERT (false);
+	return (QString ());
+}
+
+//static
 QDomElement RKComponentMap::findOrCreateElement (QDomElement& parent, const QString& tagname, const QString& name, const QString& label, int index) {
 	RK_TRACE (PLUGIN);
 
@@ -219,11 +239,12 @@
 ///########################### END RKComponentMap ###############################
 ///########################### BEGIN RKComponentHandle ############################
 
-RKComponentHandle::RKComponentHandle (const QString &filename, RKComponentType type) {
+RKComponentHandle::RKComponentHandle (const QString &filename, const QString &label, RKComponentType type) {
 	RK_TRACE (PLUGIN);
 
 	RKComponentHandle::type = type;
 	RKComponentHandle::filename = filename;
+	RKComponentHandle::label = label;
 }
 
 RKComponentHandle::~RKComponentHandle () {
@@ -233,7 +254,7 @@
 //static 
 RKComponentHandle* RKComponentHandle::createComponentHandle (const QString &filename, RKComponentType type, const QString& id, const QString& label, RKComponentMap *map) {
 	if (type == (int) Standard) {
-		RKStandardComponentHandle *ret = new RKStandardComponentHandle (filename, type);
+		RKStandardComponentHandle *ret = new RKStandardComponentHandle (filename, label, type);
 		new KAction (label, 0, ret, SLOT (activated ()), map->actionCollection (), id.latin1 ());
 		return (ret);
 	}
@@ -258,7 +279,7 @@
 
 #include "rkstandardcomponent.h"
 
-RKStandardComponentHandle::RKStandardComponentHandle (const QString &filename, RKComponentType type) : QObject (RKWardMainWindow::getMain ()), RKComponentHandle (filename, type) {
+RKStandardComponentHandle::RKStandardComponentHandle (const QString &filename, const QString &label, RKComponentType type) : QObject (RKWardMainWindow::getMain ()), RKComponentHandle (filename, label, type) {
 	RK_TRACE (PLUGIN);
 }
 
@@ -269,7 +290,7 @@
 RKComponent *RKStandardComponentHandle::invoke (RKComponent *parent_component, QWidget *parent_widget) {
 	RK_TRACE (PLUGIN);
 
-	return (new RKStandardComponent (parent_component, parent_widget, getFilename ()));
+	return (new RKStandardComponent (parent_component, parent_widget, getFilename (), this));
 }
 
 void RKStandardComponentHandle::activated () {

Modified: trunk/rkward/rkward/plugin/rkcomponentmap.h
===================================================================
--- trunk/rkward/rkward/plugin/rkcomponentmap.h	2007-01-07 20:41:34 UTC (rev 1085)
+++ trunk/rkward/rkward/plugin/rkcomponentmap.h	2007-01-08 00:52:29 UTC (rev 1086)
@@ -34,11 +34,12 @@
 */
 class RKComponentHandle {
 public:
-	RKComponentHandle (const QString &filename, RKComponentType type);
+	RKComponentHandle (const QString &filename, const QString &label, RKComponentType type);
 
 	virtual ~RKComponentHandle ();
 
 	QString getFilename () { return filename; };
+	QString getLabel () { return label; };
 	RKComponentType getType () { return type; };
 	bool isPlugin ();
 
@@ -48,6 +49,7 @@
 private:
 /** The filename of the description file for this component */
 	QString filename;
+	QString label;
 	RKComponentType type;
 };
 
@@ -80,6 +82,7 @@
 
 /** returns the component identified by id */
 	static RKComponentHandle* getComponentHandle (const QString &id);
+	static QString getComponentId (RKComponentHandle* by_component);
 	static RKComponentMap *getMap () { return component_map; };
 	static void initialize ();
 private:
@@ -103,6 +106,7 @@
 	ComponentMap components;
 
 	RKComponentHandle* getComponentHandleLocal (const QString &id);
+	QString getComponentIdLocal (RKComponentHandle* component);
 	int addPluginMapLocal (const QString& plugin_map_file);
 
 	void clearLocal ();
@@ -118,7 +122,7 @@
 class RKStandardComponentHandle : public QObject, public RKComponentHandle {
 	Q_OBJECT
 public:
-	RKStandardComponentHandle (const QString &filename, RKComponentType type);
+	RKStandardComponentHandle (const QString &filename, const QString &label, RKComponentType type);
 
 	~RKStandardComponentHandle ();
 

Modified: trunk/rkward/rkward/plugin/rkstandardcomponent.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkstandardcomponent.cpp	2007-01-07 20:41:34 UTC (rev 1085)
+++ trunk/rkward/rkward/plugin/rkstandardcomponent.cpp	2007-01-08 00:52:29 UTC (rev 1086)
@@ -52,10 +52,11 @@
 #include "../debug.h"
 
 
-RKStandardComponent::RKStandardComponent (RKComponent *parent_component, QWidget *parent_widget, const QString &filename) : RKComponent (parent_component, parent_widget) {
+RKStandardComponent::RKStandardComponent (RKComponent *parent_component, QWidget *parent_widget, const QString &filename, RKComponentHandle *handle) : RKComponent (parent_component, parent_widget) {
 	RK_TRACE (PLUGIN);
 
 	RKStandardComponent::filename = filename;
+	RKStandardComponent::handle = handle;
 	backend = 0;
 	gui = 0;
 	wizard = 0;

Modified: trunk/rkward/rkward/plugin/rkstandardcomponent.h
===================================================================
--- trunk/rkward/rkward/plugin/rkstandardcomponent.h	2007-01-07 20:41:34 UTC (rev 1085)
+++ trunk/rkward/rkward/plugin/rkstandardcomponent.h	2007-01-08 00:52:29 UTC (rev 1086)
@@ -23,6 +23,7 @@
 #include <qdom.h>
 
 class RKStandardComponentGUI;
+class RKComponentHandle;
 class RKStandardComponentStack;
 class ScriptBackend;
 
@@ -36,7 +37,7 @@
 @param parent_component Parent component (or 0, if this is going to be a top-level component)
 @param parent_widget Parent widget (typically 0, if this is going to be a top-level component)
 @param filename Filename of the XML-file to construct this component from */
-	RKStandardComponent (RKComponent *parent_component, QWidget *parent_widget, const QString &filename);
+	RKStandardComponent (RKComponent *parent_component, QWidget *parent_widget, const QString &filename, RKComponentHandle *handle);
 /** destructor */
 	~RKStandardComponent ();
 /** reimplemented to update code on changes*/
@@ -63,6 +64,7 @@
 	void setCaption (const QString &caption);
 /** return the filename of the xml file */
 	QString getFilename () { return filename; };
+	RKComponentHandle *getHandle () { return handle; };
 public slots:
 /** this gets called by the script-backend, when it's done. Might enable the
 	submit button or destruct the plugin. */
@@ -83,6 +85,7 @@
 	QString filename;
 	ScriptBackend *backend;
 	RKStandardComponentGUI *gui;
+	RKComponentHandle *handle;
 	RKStandardComponentStack *wizard;
 /** Avoid updating code-display, etc. until the component is fully created */
 	bool created;

Modified: trunk/rkward/rkward/plugin/rkstandardcomponentgui.cpp
===================================================================
--- trunk/rkward/rkward/plugin/rkstandardcomponentgui.cpp	2007-01-07 20:41:34 UTC (rev 1085)
+++ trunk/rkward/rkward/plugin/rkstandardcomponentgui.cpp	2007-01-08 00:52:29 UTC (rev 1086)
@@ -19,6 +19,7 @@
 
 #include <klocale.h>
 #include <kaction.h>
+#include <kurl.h>
 
 #include <qtimer.h>
 #include <qsplitter.h>
@@ -28,6 +29,8 @@
 #include <qpushbutton.h>
 #include <qlabel.h>
 
+#include "rkcomponentmap.h"
+#include "../windows/rkworkplace.h"
 #include "../windows/rkcommandeditorwindow.h"
 #include "../rbackend/rinterface.h"
 #include "../misc/rkerrordialog.h"
@@ -159,6 +162,11 @@
 
 void RKStandardComponentGUI::help () {
 	RK_TRACE (PLUGIN);
+
+	QString id = RKComponentMap::getComponentId (component->getHandle ());
+
+	QString path = QStringList::split ("::", id).join ("/");
+	RKWorkplace::mainWorkplace ()->openHelpWindow (KURL ("rkcomponent:///" + path));
 }
 
 void RKStandardComponentGUI::closeEvent (QCloseEvent *e) {

Added: trunk/rkward/rkward/plugins/descriptive/descriptive_statistics.rkh
===================================================================
--- trunk/rkward/rkward/plugins/descriptive/descriptive_statistics.rkh	                        (rev 0)
+++ trunk/rkward/rkward/plugins/descriptive/descriptive_statistics.rkh	2007-01-08 00:52:29 UTC (rev 1086)
@@ -0,0 +1,25 @@
+<!DOCTYPE rkhelp>
+<document>
+	<!-- title can be ommitted, as this is the help page for a plugin
+	<title>alskfa</title>
+	-->
+	<summary>
+		Compute the most common descriptive statistics for one or more numeric vectors
+	</summary>
+	<usage>
+		If there are general usage instruction, not tied to an option, specify them here (see <link href="rkcomponent:///basic_statistics">testtitle</link>)
+
+		Next paragraph
+		Same paragraph
+	</usage>
+	<settings>
+		<setting id="x">Select one or more numeric vectors to analyse</setting>
+		<setting id="mean">Should the mean value be computed?</setting>
+		<setting id="trim">Trim of the mean. See <link href="rhelp:///mean"/></setting>
+	</settings>
+	<related>
+		<link href="rhelp:///mean"/>
+		<link href="rkcomponent:///basic_statistics"/>
+		<link href="rkhelp:///basic_functions"/>
+	</related>
+</document>

Modified: trunk/rkward/rkward/plugins/descriptive/descriptive_statistics.xml
===================================================================
--- trunk/rkward/rkward/plugins/descriptive/descriptive_statistics.xml	2007-01-07 20:41:34 UTC (rev 1085)
+++ trunk/rkward/rkward/plugins/descriptive/descriptive_statistics.xml	2007-01-08 00:52:29 UTC (rev 1086)
@@ -2,6 +2,8 @@
 <!-- This is a simple example, of how a "plugin" might be configured. -->
 <document>
 	<code file="descriptive_statistics.php" />
+	<help file="descriptive_statistics.rkh" />
+
 	<dialog label="Descriptive Statistics" >
 		<tabbook>
 			<tab label="Variables">

Modified: trunk/rkward/rkward/windows/rkhtmlwindow.cpp
===================================================================
--- trunk/rkward/rkward/windows/rkhtmlwindow.cpp	2007-01-07 20:41:34 UTC (rev 1085)
+++ trunk/rkward/rkward/windows/rkhtmlwindow.cpp	2007-01-08 00:52:29 UTC (rev 1086)
@@ -29,11 +29,15 @@
 #include <qwidget.h>
 #include <qlayout.h>
 #include <qtimer.h>
+#include <qdir.h>
 
 #include "../rkglobals.h"
+#include "../khelpdlg.h"
 #include "../rkward.h"
 #include "../settings/rksettingsmodulegeneral.h"
 #include "../misc/rkcommonfunctions.h"
+#include "../misc/xmlhelper.h"
+#include "../plugin/rkcomponentmap.h"
 #include "../windows/rkworkplace.h"
 #include "../windows/rkworkplaceview.h"
 #include "../debug.h"
@@ -99,6 +103,7 @@
 
 	url_history.next ();
 	RK_ASSERT (url_history.current ());
+qDebug ("Error is here");
 	khtmlpart->openURL (*(url_history.current ()));
 	updateCaption (*(url_history.current ()));
 
@@ -111,6 +116,7 @@
 
 	url_history.prev ();
 	RK_ASSERT (url_history.current ());
+qDebug ("Error is here");
 	khtmlpart->openURL (*(url_history.current ()));
 	updateCaption (*(url_history.current ()));
 
@@ -132,6 +138,12 @@
 	}
 
 	khtmlpart->openURL (url);
+	changeURL (url);
+
+	return true;
+}
+
+void RKHTMLWindow::changeURL (const KURL &url) {
 	updateCaption (url);
 
 	if (back && forward) {
@@ -144,8 +156,6 @@
 		back->setEnabled (url_history.count () > 1);
 		forward->setEnabled (false);
 	}
-
-	return true;
 }
 
 void RKHTMLWindow::updateCaption (const KURL &url) {
@@ -343,4 +353,130 @@
 	khtmlpart = 0;	// in case we try to redelete in a parent class
 }
 
+bool RKHelpWindow::openURL (const KURL &url) {
+	RK_TRACE (APP);
+
+	// TODO: real error handling
+	bool ok = true;
+	qDebug ("here1 %s", url.prettyURL ().latin1 ());
+	if (url.protocol () == "rkcomponent") {
+		ok = renderRKHelp (url);
+	} else if (url.protocol () == "rhelp") {
+		// TODO: find a nice solution to render this in the current window
+		RKGlobals::helpDialog ()->getFunctionHelp (url.path ());
+	} else if (url.protocol () == "rkhelp") {
+		ok = renderRKHelp (url);
+	} else {
+		ok = RKHTMLWindow::openURL (url);
+	}
+
+	if (!ok) {
+		khtmlpart->begin (url);
+		khtmlpart->write ("<html><body><h1>" + i18n ("Page does not exist or is broken") + "</h1></body></html>");
+		khtmlpart->end ();
+	}
+
+	changeURL (url);
+	return ok;
+}
+
+bool RKHelpWindow::renderRKHelp (const KURL &url) {
+	RK_TRACE (APP);
+
+	qDebug ("here2 %s", url.path ().latin1 ());
+	if (url.protocol () == "rkcomponent") {
+		bool success = false;
+		XMLHelper *component_xml = new XMLHelper ();
+		XMLHelper *help_xml = new XMLHelper ();
+
+		while (true) {		// dirty hack to streamline exit code: breaking from this while, before success is set to true will cause the XMLHelpers to be deleted, and false returned.
+			QStringList path_segments = QStringList::split ('/', url.path ());
+			if (path_segments.count () > 2) break;
+			if (path_segments.count () < 1) break;
+			if (path_segments.count () == 1) path_segments.push_front ("rkward");
+			RK_ASSERT (path_segments.count () == 2);
+			RKComponentHandle *chandle = RKComponentMap::getComponentHandle (path_segments.join ("::"));
+			if (!chandle) break;
+
+			qDebug ("here3");
+			QDomElement component_doc_element = component_xml->openXMLFile (chandle->getFilename (), DL_ERROR);
+			if (component_doc_element.isNull ()) break;
+			QDomElement element = component_xml->getChildElement (component_doc_element, "help", DL_ERROR);
+			if (element.isNull ()) break;
+			QString help_file_name = component_xml->getStringAttribute (element, "file", QString::null, DL_ERROR);
+			if (help_file_name.isNull ()) break;
+			help_file_name = QFileInfo (chandle->getFilename ()).dir (true).filePath (help_file_name);
+	
+			qDebug ("here4");
+			QDomElement help_doc_element = help_xml->openXMLFile (help_file_name, DL_ERROR);
+			if (help_doc_element.isNull ()) break;
+
+			khtmlpart->begin (url);
+			khtmlpart->write ("<html><head><title>" + chandle->getLabel () + "</title></head>\n<body>\n<h1>" + chandle->getLabel () + "</h1>\n");
+
+			qDebug ("here5");
+			element = help_xml->getChildElement (help_doc_element, "summary", DL_WARNING);
+			if (!element.isNull ()) {
+				khtmlpart->write ("<h2>" + i18n ("Summary") + "</h2>\n");
+				khtmlpart->write (renderHelpFragment (element));
+			}
+
+			element = help_xml->getChildElement (help_doc_element, "usage", DL_WARNING);
+			if (!element.isNull ()) {
+				khtmlpart->write ("<h2>" + i18n ("Usage") + "</h2>\n");
+				khtmlpart->write (renderHelpFragment (element));
+			}
+
+			// TODO: handle some generic sections
+
+			// TODO: handle settings section
+
+			// TODO: handle related section
+
+			khtmlpart->end ();
+			success = true;
+			break;
+		}
+
+		delete (component_xml);
+		delete (help_xml);
+		return (success);
+	}
+
+	return false;
+}
+
+QString RKHelpWindow::renderHelpFragment (QDomElement &fragment) {
+	RK_TRACE (APP);
+
+	QDomNodeList link_nodes = fragment.elementsByTagName ("link");
+	for (int i=link_nodes.count (); i >= 0; --i) {
+		QDomElement element = link_nodes.item (i).toElement ();
+		if (element.isNull ()) continue;
+
+		prepareHelpLink (&element);
+		qDebug ("fragment");
+	}
+
+	QString ret;
+	QTextOStream stream (&ret);
+	fragment.save (stream, 0);
+
+	ret.prepend ("<p>");
+	ret.append ("</p>");
+	ret.replace ("\n\n", "</p>\n<p>");
+
+	return ret;
+}
+
+void RKHelpWindow::prepareHelpLink (QDomElement *link_element) {
+	RK_TRACE (APP);
+	qDebug ("link");
+
+	link_element->setTagName ("a");
+	if (link_element->text ().isNull ()) {
+		link_element->appendChild (link_element->ownerDocument ().createTextNode ("TODO: determine link title"));
+	}
+}
+
 #include "rkhtmlwindow.moc"

Modified: trunk/rkward/rkward/windows/rkhtmlwindow.h
===================================================================
--- trunk/rkward/rkward/windows/rkhtmlwindow.h	2007-01-07 20:41:34 UTC (rev 1085)
+++ trunk/rkward/rkward/windows/rkhtmlwindow.h	2007-01-08 00:52:29 UTC (rev 1086)
@@ -75,6 +75,8 @@
 	KHTMLPart * khtmlpart;
 /** update caption according to given URL */
 	virtual void updateCaption (const KURL &url);
+/** called from openURL. Takes care of updating caption, and updating back/forward actions, if available */
+	void changeURL (const KURL &url);
 protected:
 	QPtrList<KURL> url_history;
 	KAction *back;
@@ -134,6 +136,8 @@
 	static QDateTime last_refresh_time;
 };
 
+class QDomElement;
+
 /**
 	\brief Show html help files.
 
@@ -150,6 +154,12 @@
 	RKHelpWindow (QWidget *parent = 0);
 /** destructor */
 	~RKHelpWindow ();
+/** reimplemented to handle our special protocols component://, rhelp://, and rkhelp:// in addition to the regular protocols */
+	bool openURL (const KURL &url);
+private:
+	bool renderRKHelp (const KURL &url);
+	QString renderHelpFragment (QDomElement &fragment);
+	void prepareHelpLink (QDomElement *link_element);
 };
 
 #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