[rkward-cvs] [rkward] /: Start working on allowing to override some plugin aspects (visibility, for now) from R. Not functional, yet.

Thomas Friedrichsmeier thomas.friedrichsmeier at ruhr-uni-bochum.de
Sun Jan 4 21:14:13 UTC 2015


Git commit 1066746667bb0b46cbe06990d37ee1f4ed9c7e38 by Thomas Friedrichsmeier.
Committed on 04/01/2015 at 21:12.
Pushed by tfry into branch 'master'.

Start working on allowing to override some plugin aspects (visibility, for now) from R. Not functional, yet.
In the process, merge RKContextMap into RKComponentGUIXML, and rework rk.list.plugins(), somewhat.

M  +1    -0    ChangeLog
M  +2    -2    rkward/dialogs/rkimportdialog.h
M  +7    -25   rkward/plugin/rkcomponentcontext.cpp
M  +2    -27   rkward/plugin/rkcomponentcontext.h
M  +56   -26   rkward/plugin/rkcomponentmap.cpp
M  +26   -10   rkward/plugin/rkcomponentmap.h
M  +8    -0    rkward/rbackend/rinterface.cpp
M  +1    -0    rkward/rbackend/rpackages/rkward/NAMESPACE
M  +55   -19   rkward/rbackend/rpackages/rkward/R/rk.plugin-functions.R
M  +3    -16   rkward/rbackend/rpackages/rkward/man/rk.call.plugin.Rd
M  +1    -1    rkward/windows/rkwindowcatcher.cpp

http://commits.kde.org/rkward/1066746667bb0b46cbe06990d37ee1f4ed9c7e38

diff --git a/ChangeLog b/ChangeLog
index 39aa452..136df96 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,4 @@
+  - TODO: With the improved interface to plugins from R, make sure plugins can actually be modified at runtime without crashing (close and re-open them)
 - Pluginmap-management was reworked, partially, and moved to Settings->Manage R packages and plugins
 - Provide more detailed information on loaded plugins in rk.list.plugins()
 - Allow to override plugins from a different pluginmap (the plugin with the highest specified version is used)
diff --git a/rkward/dialogs/rkimportdialog.h b/rkward/dialogs/rkimportdialog.h
index ed5f007..71be040 100644
--- a/rkward/dialogs/rkimportdialog.h
+++ b/rkward/dialogs/rkimportdialog.h
@@ -25,7 +25,7 @@
 #include <khbox.h>
 
 class QComboBox;
-class RKContextMap;
+class RKComponentGUIXML;
 class RKImportDialogFormatSelector;
 
 /** This dialog is designed to allow the user to select a file, and file format. After that a suitable plugin
@@ -53,7 +53,7 @@ private:
 	QStringList format_labels;
 	QStringList filters;
 	QStringList component_ids;
-	RKContextMap *context;
+	RKComponentGUIXML *context;
 };
 
 /** Internal helper class to RKImportDialog. Needed solely to work around a design flaw in the KFileDialog API */
diff --git a/rkward/plugin/rkcomponentcontext.cpp b/rkward/plugin/rkcomponentcontext.cpp
index 254b179..d210759 100644
--- a/rkward/plugin/rkcomponentcontext.cpp
+++ b/rkward/plugin/rkcomponentcontext.cpp
@@ -2,7 +2,7 @@
                           rkcomponentcontext  -  description
                              -------------------
     begin                : Mon Jan 22 2007
-    copyright            : (C) 2007, 2014 by Thomas Friedrichsmeier
+    copyright            : (C) 2007, 2014, 2015 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -25,40 +25,22 @@
 
 #include "../debug.h"
 
-RKContextMap::RKContextMap (const QString &id) : RKComponentGUIXML () {
+RKContextHandler *RKComponentGUIXML::makeContextHandler (QObject *parent, bool create_actions) {
 	RK_TRACE (PLUGIN);
 
-	RKContextMap::id = id;
-}
-
-RKContextMap::~RKContextMap () {
-	RK_TRACE (PLUGIN);
-}
-
-RKContextHandler *RKContextMap::makeContextHandler (QObject *parent, bool create_actions) {
-	RK_TRACE (PLUGIN);
-
-	RKContextHandler *handler = new RKContextHandler (parent, gui_xml, id);
+	RKContextHandler *handler = new RKContextHandler (parent, gui_xml, context);
 	if (create_actions) {
-		for (QStringList::const_iterator it = component_ids.constBegin (); it != component_ids.constEnd (); ++it) {
-			RKComponentHandle *handle = RKComponentMap::getComponentHandle (*it);
+		const QStringList ids = components ();
+		for (int i = 0; i < ids.size (); ++i) {
+			RKComponentHandle *handle = RKComponentMap::getComponentHandle (ids[i]);
 			if (handle->isPlugin ()) {
-				handler->addAction (*it, handle);
+				handler->addAction (ids[i], handle);
 			}
 		}
 	}
 	return handler;
 }
 
-void RKContextMap::addedEntry (const QString &id, RKComponentHandle *) {
-	RK_TRACE (PLUGIN);
-
-	component_ids.append (id);
-}
-
-/////////////////// END RKContextMap /////////////////////
-//////////////// BEGIN RKContextHandler //////////////////
-
 RKContextHandler::RKContextHandler (QObject *parent, const QDomDocument &gui_xml, const QString &id) : QObject (parent), RKComponentBase (), KXMLGUIClient () {
 	RK_TRACE (PLUGIN);
 
diff --git a/rkward/plugin/rkcomponentcontext.h b/rkward/plugin/rkcomponentcontext.h
index fc841fd..184c192 100644
--- a/rkward/plugin/rkcomponentcontext.h
+++ b/rkward/plugin/rkcomponentcontext.h
@@ -2,7 +2,7 @@
                           rkcomponentcontext  -  description
                              -------------------
     begin                : Mon Jan 22 2007
-    copyright            : (C) 2007, 2014 by Thomas Friedrichsmeier
+    copyright            : (C) 2007, 2014, 2015 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -24,31 +24,6 @@
 #include "rkcomponent.h"
 
 class QDomElement;
-class RKContextHandler;
-class XMLHelper;
-
-/** This class keeps a list of components that are useable in a certain context (e.g. x11 device). It also keeps a description of the menu structure(s) that should be used for that context. Note that in order to use the XML-GUI, you should create an RKContextHandler using makeContextHandler().
-
- at author Thomas Friedrichsmeier
-*/
-class RKContextMap : public RKComponentGUIXML {
-public:
-/** constructor
- at param id The id of the context */
-	RKContextMap (const QString &id);
-/** destructor */
-	~RKContextMap ();
-/** Create a context handler for this context. */
-	RKContextHandler *makeContextHandler (QObject *parent, bool create_actions=true);
-	QStringList components () { return component_ids; };
-protected:
-	void addedEntry (const QString &id, RKComponentHandle * /* handle */);
-private:
-	QStringList component_ids;
-	QString id;
-};
-
-class KAction;
 
 /** An RKContextHandler can be thought of as an instance of a context. E.g. the x11 device context by itself is just an abstract description. To actually use the context for a given device, an RKContextHandler is used. The normal way to construct an instance of this class is using RKContextMap::makeContextHandler().
 
@@ -63,7 +38,7 @@ The last part (providing context information) is the most important one in this
 */
 class RKContextHandler : public QObject, public RKComponentBase, public KXMLGUIClient {
 	Q_OBJECT
-friend class RKContextMap;
+friend class RKComponentGUIXML;
 public:
 	void invokeComponent (RKComponentHandle *handle);
 	int type () { return ComponentContextHandler; };
diff --git a/rkward/plugin/rkcomponentmap.cpp b/rkward/plugin/rkcomponentmap.cpp
index e53e066..5594cd5 100644
--- a/rkward/plugin/rkcomponentmap.cpp
+++ b/rkward/plugin/rkcomponentmap.cpp
@@ -2,7 +2,7 @@
                           rkcomponentmap.cpp  -  description
                              -------------------
     begin                : Thu May 12 2005
-    copyright            : (C) 2005-2014 by Thomas Friedrichsmeier
+    copyright            : (C) 2005-2015 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -57,9 +57,10 @@ RKComponentAboutData RKPluginMapFile::getAboutData () {
 	return *about;
 }
 
-RKComponentGUIXML::RKComponentGUIXML () {
+RKComponentGUIXML::RKComponentGUIXML (const QString &context_id) {
 	RK_TRACE (PLUGIN);
 
+	context = context_id;
 	clearGUIDescription ();
 }
 
@@ -72,6 +73,7 @@ void RKComponentGUIXML::clearGUIDescription () {
 
 	gui_xml.setContent (QString ("<!DOCTYPE kpartgui>\n<kpartgui name=\"rkwardcomponents\" version=\"063\">\n<MenuBar>\n\n</MenuBar>\n</kpartgui>"));
 	toplevel_menu.clear ();
+	component_menus.clear ();
 }
 
 bool compareMenuEntries (const RKComponentGUIXML::Entry *a, const RKComponentGUIXML::Entry *b) {
@@ -96,7 +98,7 @@ void RKComponentGUIXML::resolveComponentLabelsAndSortMenu (Menu *menu, const QSt
 					// The reason that handling of label is delayed to this point is that if a plugin is overridden, we want to use the label specified for the effective plugin (which might have changed WRT the overridden plugin, too).
 					entry->label = handle->getLabel ();
 					addedEntry (entry->id, handle);
-					component_menus.insert (handle, menu_path);
+					component_menus.insert (entry->id, menu_path);
 				}
 			} else {
 				resolveComponentLabelsAndSortMenu (static_cast<Menu*> (entry), menu_path.isEmpty () ? entry->label : menu_path + "\t" + entry->label);
@@ -290,6 +292,19 @@ int RKComponentGUIXML::addEntries (RKComponentGUIXML::Menu *menu, XMLHelper &xml
 	return leaves;
 }
 
+// static
+QMultiMap<QString, RKComponentGUIXML::ComponentOverride> RKComponentGUIXML::overrides;
+void RKComponentGUIXML::addOverride (const QString& id, const QString& context, bool visible) {
+	ComponentOverride over;
+	over.context = context;
+	over.hidden = !visible;
+	overrides.insert (id, over);
+}
+
+void RKComponentGUIXML::clearOverrides () {
+	overrides.clear ();
+}
+
 /////////////////////////// END RKComponentXMLGUIClient /////////////////////////////////
 ////////////////////////////// Bhttp://apps.sourceforge.net/mediawiki/rkward/nfs/project/r/rk/rkward/6/6d/RKWardApplicationDetached.pngEGIN RKComponentMap /////////////////////////////////////
 
@@ -303,11 +318,12 @@ void RKComponentMap::initialize () {
 	component_map = new RKComponentMap ();
 }
 
-RKComponentMap::RKComponentMap () : QObject (), RKComponentGUIXML (), KXMLGUIClient () {
+RKComponentMap::RKComponentMap () : QObject (), RKComponentGUIXML ("global"), KXMLGUIClient () {
 	RK_TRACE (PLUGIN);
 
 	setComponentData (KGlobal::mainComponent ());
 	actionCollection ()->setConfigGroup ("Plugin Shortcuts");
+	contexts.insert ("global", this);
 }
 
 RKComponentMap::~RKComponentMap () {
@@ -334,32 +350,26 @@ void RKComponentMap::clearAll () {
 	component_attributes.clear ();
 	component_dependencies.clear ();
 	for (RKComponentContextMap::const_iterator it = contexts.constBegin (); it != contexts.constEnd (); ++it) {
-		delete (it.value ());
+		if (it.value () != this) delete (it.value ());
 	}
 	contexts.clear ();
+	contexts.insert ("global", this);
 
 	clearGUIDescription ();
 
 	setXMLGUIBuildDocument (gui_xml);
 }
 
-RKContextMap *RKComponentMap::getContext (const QString &id) {
+RKComponentGUIXML *RKComponentMap::getContext (const QString &id) {
 	RK_TRACE (PLUGIN);
 
-	RKContextMap *context = getMap ()->getContextLocal (id);
+	RKComponentGUIXML *context = getMap ()->contexts.value (id);
 	if (context) return context;
 
 	RK_DEBUG (PLUGIN, DL_WARNING, "no such context %s", id.toLatin1 ().data ());
 	return (0);
 }
 
-RKContextMap *RKComponentMap::getContextLocal (const QString &id) {
-	RK_TRACE (PLUGIN);
-
-	if (contexts.contains (id)) return (contexts[id]);
-	return 0;
-}
-
 RKComponentHandle* RKComponentMap::getComponentHandle (const QString &id) {
 	RK_TRACE (PLUGIN);
 
@@ -514,7 +524,7 @@ void RKComponentMap::finalizeAll () {
 	finalize ();
 	setXMLGUIBuildDocument (gui_xml);
 	actionCollection ()->readSettings ();
-	foreach (RKContextMap *ctx, getMap()->contexts) {
+	foreach (RKComponentGUIXML *ctx, getMap()->contexts) {
 		ctx->finalize ();
 	}
 }
@@ -651,9 +661,9 @@ RKPluginMapParseResult RKComponentMap::addPluginMap (const QString& plugin_map_f
 	for (XMLChildList::const_iterator it=list.constBegin (); it != list.constEnd (); ++it) {
 		QString id = xml.getStringAttribute (*it, "id", QString::null, DL_ERROR);
 
-		RKContextMap *context = getContextLocal (id);
+		RKComponentGUIXML *context = contexts.value (id);
 		if (!context) {
-			context = new RKContextMap (id);
+			context = new RKComponentGUIXML (id);
 			contexts.insert (id, context);
 		}
 		ret.valid_plugins += context->createMenus (xml, *it, cnamespace);
@@ -688,6 +698,18 @@ void RKComponentMap::addedEntry (const QString &id, RKComponentHandle *handle) {
 	}
 }
 
+void RKComponentGUIXML::appendPluginToList (const QString& id, QStringList* list) {
+	list->append (id);
+	list->append (context);
+	list->append (component_menus.value (id));
+	RKComponentHandle *handle = RKComponentMap::getComponentHandle (id);
+	if (handle) list->append (handle->getLabel ());
+	else {
+		RK_ASSERT (handle);
+		list->append (QString ());
+	}
+}
+
 QStringList RKComponentMap::listPlugins () {
 	RK_TRACE (PLUGIN);
 
@@ -696,24 +718,32 @@ QStringList RKComponentMap::listPlugins () {
 	ret.reserve (components.size () * 4);
 #endif
 	for (ComponentMap::const_iterator it = components.constBegin (); it != components.constEnd (); ++it) {
-		ret.append (it.key ());
-		ret.append ("global"); // context
-		ret.append (component_menus.value (it.value ()));
-		ret.append (it.value ()->getLabel ());
+		// RKComponentMap (in contrast to other contexts) will also contain plugins not added to the menu,
+		// and is listed separately, for this reason
+		getMap ()->appendPluginToList (it.key (), &ret);
 	}
 	for (RKComponentContextMap::const_iterator ctx = contexts.constBegin (); ctx != contexts.constEnd (); ++ctx) {
+		RKComponentGUIXML *context = ctx.value ();
+		if (context == getMap ()) continue;
+
 		QStringList ids = ctx.value ()->components ();
 		for (int i = 0; i < ids.size (); ++i) {
-			ret.append (ids[i]);
-			ret.append (ctx.key ());
-			RKComponentHandle *handle = getComponentHandle (ids[i]);
-			ret.append (ctx.value ()->component_menus.value (handle));
-			ret.append (handle->getLabel ());
+			context->appendPluginToList (ids[i], &ret);
 		}
 	}
 	return ret;
 }
 
+void RKComponentMap::setPluginStatus (const QStringList& ids, const QStringList& _contexts, const QStringList& _visible) {
+	RK_TRACE (PLUGIN);
+	RK_ASSERT (ids.size () == _contexts.size ());
+	RK_ASSERT (_contexts.size () == _visible.size ());
+
+	for (int i = 0; i < ids.size (); ++i) {
+		addOverride (ids[i], _contexts[i], (_visible[i] == "1"));
+	}
+}
+
 
 ///########################### END RKComponentMap ###############################
 ///########################### BEGIN RKComponentHandle ############################
diff --git a/rkward/plugin/rkcomponentmap.h b/rkward/plugin/rkcomponentmap.h
index df53ae6..6ade57b 100644
--- a/rkward/plugin/rkcomponentmap.h
+++ b/rkward/plugin/rkcomponentmap.h
@@ -2,7 +2,7 @@
                           rkcomponentmap.h  -  description
                              -------------------
     begin                : Thu May 12 2005
-    copyright            : (C) 2005-2014 by Thomas Friedrichsmeier
+    copyright            : (C) 2005-2015 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -115,10 +115,11 @@ private:
 
 class QDomElement;
 class XMLHelper;
+class RKContextHandler;
 
 /** This class keeps a QDomDocument that is a represenation of the GUI using KDEs XML-GUI format (a ui.rc). Use createMenus () to have it parse the menu descriptions from a .pluginmap file. It will adjust the XML description accordingly. When done, you can use to generated gui_xml to set it as the xmlGUIBuildDocument of a KXMLGUIClient. 
 
-This class represents the common functionality between RKComponentMap and RKContextMap.
+One instance of this class is generally around, persistently: The RKComonentMap (with context "global"). Further instances are around one for each context.
 
 @author Thomas Friedrichsmeier
 */
@@ -151,8 +152,12 @@ public:
 @returns number of plugins/menu-entries added successfully */
 	int createMenus (XMLHelper &xml, const QDomElement& hierarchy_description, const QString& cnamespace);
 	void finalize ();
+
+/** Create a context handler for this context. */
+	RKContextHandler *makeContextHandler (QObject *parent, bool create_actions=true);
+	QStringList components () { return component_menus.keys (); };
 protected:
-	RKComponentGUIXML ();
+	RKComponentGUIXML (const QString &context_id);
 	virtual ~RKComponentGUIXML ();
 
 /** reset the xml file */
@@ -164,15 +169,26 @@ protected:
 /** The generated XML GUI description in KDEs ui.rc format */
 	QDomDocument gui_xml;
 friend class RKComponentMap;
-	QMap<RKComponentHandle*, QString> component_menus;
+	QMap<QString, QString> component_menus;
+
+/** Add a component override, e.g. hiding component "t_test" in context "global". Overrides are persistent per session. */
+	static void addOverride (const QString &id, const QString &context, bool visible);
+/** Clear component overrides (see addOverride()). */
+	static void clearOverrides ();
 private:
 	int addEntries (RKComponentGUIXML::Menu *menu, XMLHelper &xml, const QDomElement description, const QString& cnamespace);
 	void menuItemsToXml (const RKComponentGUIXML::Menu *menu, QDomElement &xml);
 	void resolveComponentLabelsAndSortMenu (Menu *menu, const QString &menu_path=QString ());
-};
+	struct ComponentOverride {
+		QString context;
+		bool hidden;
+	};
+	static QMultiMap<QString, ComponentOverride> overrides;
+	QString context;
 
+	void appendPluginToList (const QString &id, QStringList *list);
+};
 
-class RKContextMap;
 
 class RKPluginMapParseResult {
 public:
@@ -218,7 +234,7 @@ public:
 	static RKComponentMap *getMap () { return component_map; };
 	static void initialize ();
 /** returns the context identified by id */
-	static RKContextMap *getContext (const QString &id);
+	static RKComponentGUIXML *getContext (const QString &id);
 
 	enum ComponentInvocationMode {
 		ManualSubmit,
@@ -230,6 +246,7 @@ public:
 	static bool invokeComponent (const QString &component_id, const QStringList &serialized_settings, ComponentInvocationMode submit_mode = ManualSubmit, QString *message=0, RCommandChain *in_chain = 0);
 /** @returns for rk.list.plugins(): Return a list of all currently registered component ids, their context, menu, and label (i.e. current four strings per component) */
 	QStringList listPlugins ();
+	void setPluginStatus (const QStringList &ids, const QStringList &contexts, const QStringList& visible);
 	bool isPluginMapLoaded (const QString& abs_filename) const;
 public slots:
 /** Slot called, when a menu-item for a component is selected. Responsible for creating the GUI. */
@@ -242,16 +259,15 @@ private:
 
 	RKComponentHandle* getComponentHandleLocal (const QString &id);
 	QString getComponentIdLocal (RKComponentHandle* component);
-	RKContextMap *getContextLocal (const QString &id);
 
-	typedef QMap<QString, RKContextMap*> RKComponentContextMap;
+	typedef QMap<QString, RKComponentGUIXML*> RKComponentContextMap;
 	RKComponentContextMap contexts;
 
 	QList<RKPluginMapFile*> pluginmapfiles;
 
 	static RKComponentMap *component_map;
 friend class RKComponentHandle;
-	// most components have neither attributes specific dependencies (other than dependencies shared by all plugins in a pluginmap).
+	// most components have neither attributes nor specific dependencies (other than dependencies shared by all plugins in a pluginmap).
 	// therefore, it saves a few bytes to store attributes and specific dependencies in a central map, rather than keeping structures
 	// per plugin
 	struct AttributeValueMap {
diff --git a/rkward/rbackend/rinterface.cpp b/rkward/rbackend/rinterface.cpp
index 3021e37..c181886 100644
--- a/rkward/rbackend/rinterface.cpp
+++ b/rkward/rbackend/rinterface.cpp
@@ -580,6 +580,14 @@ QStringList RInterface::processPlainGenericRequest (const QStringList &calllist)
 	} else if (call == "listPlugins") {
 		RK_ASSERT (calllist.count () == 1);
 		return RKComponentMap::getMap ()->listPlugins ();
+	} else if (call == "setPluginStatus") {
+		QStringList params = calllist.mid (1);
+		RK_ASSERT ((params.size () % 3) == 0);
+		const int rows = params.size () / 3;
+		QStringList ids = params.mid (0, rows);
+		QStringList contexts = params.mid (rows, rows);
+		QStringList visible = params.mid (rows*2, rows);
+		RKComponentMap::getMap ()->setPluginStatus (ids, contexts, visible);
 	} else if (call == "loadPluginMaps") {
 		bool force = (calllist.value (1) == "force");
 		bool reload = (calllist.value (2) == "reload");
diff --git a/rkward/rbackend/rpackages/rkward/NAMESPACE b/rkward/rbackend/rpackages/rkward/NAMESPACE
index 7ce14d3..5e5ca8d 100644
--- a/rkward/rbackend/rpackages/rkward/NAMESPACE
+++ b/rkward/rbackend/rpackages/rkward/NAMESPACE
@@ -103,6 +103,7 @@ export(rk.select.list)
 export(rk.sessionInfo)
 export(rk.set.label)
 export(rk.set.output.html.file)
+export(rk.set.plugin.status)
 export(rk.show.files)
 export(rk.show.html)
 export(rk.show.message)
diff --git a/rkward/rbackend/rpackages/rkward/R/rk.plugin-functions.R b/rkward/rbackend/rpackages/rkward/R/rk.plugin-functions.R
index 4fb9dc9..6a0387a 100644
--- a/rkward/rbackend/rpackages/rkward/R/rk.plugin-functions.R
+++ b/rkward/rbackend/rpackages/rkward/R/rk.plugin-functions.R
@@ -1,9 +1,9 @@
-#' Call or list built-in RKWard plugin(s)
+#' Call built-in RKWard plugin(s)
 #' 
 #' \code{rk.call.plugin} provides a high level wrapper to call any plugin
 #' available in RKWard. The exact string to be used as \code{plugin}, and the
 #' list of arguments available for a particular plugin, are generally not
-#' transparent to the user.\code{rk.list.plugins} can be used to obtain a list
+#' transparent to the user. \code{rk.list.plugins} can be used to obtain a list
 #' of current plugins. For plugin arguments, it is recommended to run the
 #' plugin, and inspect the "Run again" link that is generated on the output.
 #' 
@@ -20,10 +20,6 @@
 #' run in the global context. Any local variables of the calling context are
 #' not available to the plugin.
 #' 
-#' \code{rk.list.plugins} returns the a list of all currently
-#' registered plugins (in loaded pluginmaps).
-#' 
-#' @aliases rk.call.plugin rk.list.plugins
 #' @param plugin character string, giving the name of the plugin to call. See
 #'   Details.
 #' @param \dots arguments passed to the \code{plugin}
@@ -40,18 +36,11 @@
 #'   an error.
 #' @return \code{rk.call.plugin} returns \code{TRUE} invisibly.
 #' 
-#' \code{rk.list.plugins} returns a data.frame listing plugin ids, context, menu path
-#'   (tab-separated), and label of the plugin. If a plugin is available in more
-#'   than one context, it will be listed several times.
 #' @author Thomas Friedrichsmeier \email{rkward-devel@@lists.sourceforge.net}
 #' @seealso \code{\link{rk.results}}, \url{rkward://page/rkward_output}
 #' @keywords utilities
-#' @rdname rk.call.plugin
 #' @examples
 #' 
-#' ## list all current plugins
-#' rk.list.plugins ()
-#' 
 #' ## "t_test_two_vars" plugin:
 #' ## see the output: Windows->Show Output
 #' local({
@@ -65,12 +54,6 @@
 #' })
 #'
 #' @export
-rk.list.plugins <- function () {
-	plugs <- .rk.do.plain.call("listPlugins")
-	as.data.frame (matrix (plugs, ncol=4, byrow=TRUE, dimnames=list (1:(length (plugs) / 4), c ("ID", "Context", "Menupath", "Label"))), stringsAsFactors=FALSE)
-}
-
-#' @export
 #' @rdname rk.call.plugin
 "rk.call.plugin" <- function (plugin, ..., submit.mode = c ("manual", "auto", "submit")) {
 	# prepare arguments
@@ -137,3 +120,56 @@ rk.list.plugins <- function () {
 "rk.load.pluginmaps" <- function (pluginmap.files=NULL, force.add = TRUE, force.reload = TRUE) {
 	.rk.do.plain.call ("loadPluginMaps", c (ifelse (isTRUE (force.add), "force", "noforce"), ifelse (isTRUE (force.reload), "reload", "noreload"), as.character (pluginmap.files)), synchronous=FALSE)
 }
+
+#' List of modify loaded plugins
+#'
+#' \code{rk.list.plugins} returns the a list of all currently
+#' registered plugins (in loaded pluginmaps).
+#' \code{rk.set.plugin.status} allows to control the status of the given plugin(s). Currently,
+#'    only visibility can be controlled.
+#'
+#' @param id vector of ids (character) of the plugins to modify
+#' @param context in which the plugin should be shown / hidden. This can either be "",
+#'    meaning the plugin will be affected in all contexts it occurs in, or a character vector
+#'    of the same length as id.
+#' @param visible logical, controlling whether the plugin should be shown (\code{TRUE}) or
+#'    hidden (\code{FALSE}).
+#'
+#' @return \code{rk.list.plugins} returns a data.frame listing plugin ids, context, menu path
+#'   (tab-separated), and label of the plugin. If a plugin is available in more
+#'   than one context, it will be listed several times. The exact layout (number and order of columns)
+#'   of this data.frame might be subject to change. However, the \bold{names} of the columns in the
+#'   returned data.frame are expected to remain stable. \code {rk.set.plugin.status} returns \code{NULL}, invisibly
+#'
+#' @author Thomas Friedrichsmeier \email{rkward-devel@@lists.sourceforge.net}
+#' @keywords utilities
+#'
+#' @seealso \code{\link{rk.call.plugin}} for invoking a plugin, programatically
+#'
+#' @examples
+#' ## list all current plugins
+#' rk.list.plugins ()
+#'
+#' ## NOT RUN
+#' ## hide t.test plugin
+#' rk.set.plugin.status ("t_test", visible=FALSE)
+#' ## END NOT RUN
+#'
+#' @export
+#' @rdname rk.list.plugins
+#' @aliases rk.list.plugins rk.set.plugin.status
+"rk.list.plugins" <- function () {
+	plugs <- .rk.do.plain.call("listPlugins")
+	columns = c ("ID", "Context", "Menupath", "Label")
+	as.data.frame (matrix (plugs, ncol=length (columns), byrow=TRUE, dimnames=list (1:(length (plugs)/length (columns)), columns)), stringsAsFactors=FALSE)
+}
+
+#' @export
+#' @rdname rk.list.plugins
+"rk.set.plugin.status" <- function (id, context="", visible=TRUE) {
+	id <- as.character (id)
+	context <- rep (as.character (context), length.out=length (id))
+	visible <- rep (as.character (as.numeric (visible)), length.out=length (id))
+	.rk.do.plain.call ("setPluginStatus", c (id, context, visible))
+	invisible (NULL)
+}
diff --git a/rkward/rbackend/rpackages/rkward/man/rk.call.plugin.Rd b/rkward/rbackend/rpackages/rkward/man/rk.call.plugin.Rd
index 9e7225c..0cddcf2 100644
--- a/rkward/rbackend/rpackages/rkward/man/rk.call.plugin.Rd
+++ b/rkward/rbackend/rpackages/rkward/man/rk.call.plugin.Rd
@@ -1,11 +1,8 @@
 % Generated by roxygen2 (4.0.2): do not edit by hand
-\name{rk.list.plugins}
+\name{rk.call.plugin}
 \alias{rk.call.plugin}
-\alias{rk.list.plugins}
-\title{Call or list built-in RKWard plugin(s)}
+\title{Call built-in RKWard plugin(s)}
 \usage{
-rk.list.plugins()
-
 rk.call.plugin(plugin, ..., submit.mode = c("manual", "auto", "submit"))
 }
 \arguments{
@@ -28,16 +25,12 @@ an error.}
 }
 \value{
 \code{rk.call.plugin} returns \code{TRUE} invisibly.
-
-\code{rk.list.plugins} returns a data.frame listing plugin ids, context, menu path
-  (tab-separated), and label of the plugin. If a plugin is available in more
-  than one context, it will be listed several times.
 }
 \description{
 \code{rk.call.plugin} provides a high level wrapper to call any plugin
 available in RKWard. The exact string to be used as \code{plugin}, and the
 list of arguments available for a particular plugin, are generally not
-transparent to the user.\code{rk.list.plugins} can be used to obtain a list
+transparent to the user. \code{rk.list.plugins} can be used to obtain a list
 of current plugins. For plugin arguments, it is recommended to run the
 plugin, and inspect the "Run again" link that is generated on the output.
 }
@@ -54,14 +47,8 @@ tests, cross-references, and scripted tutorials.
 \bold{Note}: Even when using \code{"submit.mode=submit"}, the plugin code is
 run in the global context. Any local variables of the calling context are
 not available to the plugin.
-
-\code{rk.list.plugins} returns the a list of all currently
-registered plugins (in loaded pluginmaps).
 }
 \examples{
-## list all current plugins
-rk.list.plugins ()
-
 ## "t_test_two_vars" plugin:
 ## see the output: Windows->Show Output
 local({
diff --git a/rkward/windows/rkwindowcatcher.cpp b/rkward/windows/rkwindowcatcher.cpp
index aa9d341..c79a52c 100644
--- a/rkward/windows/rkwindowcatcher.cpp
+++ b/rkward/windows/rkwindowcatcher.cpp
@@ -708,7 +708,7 @@ RKCaughtX11WindowPart::RKCaughtX11WindowPart (RKCaughtX11Window *window) : KPart
 	action->setVisible (false);
 
 	// initialize context for plugins
-	RKContextMap *context = RKComponentMap::getContext ("x11");
+	RKComponentGUIXML *context = RKComponentMap::getContext ("x11");
 	if (!context) return;
 	RKContextHandler *context_handler = context->makeContextHandler (this);
 	insertChildClient (context_handler);





More information about the rkward-tracker mailing list