Commit 10667466 authored by Thomas Friedrichsmeier's avatar Thomas Friedrichsmeier
Browse files

Start working on allowing to override some plugin aspects (visibility, for...

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.
parent 4ad50389
- 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)
......
......@@ -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 */
......
......@@ -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@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);
......
......@@ -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@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().
@author Thomas Friedrichsmeier
*/
class RKContextMap : public RKComponentGUIXML {
public:
/** constructor
@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; };
......
......@@ -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@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 ############################
......
......@@ -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@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 {
......
......@@ -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");
......
......@@ -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)
......
#' 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({
......@@ -64,12 +53,6 @@
#' submit.mode="submit")
#' })
#'
#' @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")) {
......@@ -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)
}
% 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({
......
......@@ -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);
......