[rkward/work/generalized_preview] /: Start working on generalized preview:
Thomas Friedrichsmeier
thomas.friedrichsmeier at ruhr-uni-bochum.de
Thu Dec 10 11:04:11 UTC 2015
Git commit c84fd6728b8e5cbc8b71dfca672ca1561b64bc66 by Thomas Friedrichsmeier.
Committed on 10/12/2015 at 11:02.
Pushed by tfry into branch 'work/generalized_preview'.
Start working on generalized preview:
- Make an "id" property accessible, to allow the plugin to store data for the preview.
- Allow opening data.frames outside of globalenv() for read-only viewing in editor window(!).
- Create small helpers for creation and removal of preview data.
M +1 -0 ChangeLog
M +1 -1 rkward/core/rkmodificationtracker.cpp
M +1 -1 rkward/core/robject.cpp
M +1 -1 rkward/core/robject.h
M +4 -1 rkward/dataeditor/twintable.cpp
M +5 -4 rkward/plugin/rkpreviewbox.cpp
M +1 -0 rkward/plugin/rkpreviewbox.h
M +19 -0 rkward/rbackend/rpackages/rkward/R/internal.R
M +4 -0 rkward/rbackend/rpackages/rkward/R/internal_graphics.R
M +3 -2 rkward/windows/robjectbrowser.cpp
http://commits.kde.org/rkward/c84fd6728b8e5cbc8b71dfca672ca1561b64bc66
diff --git a/ChangeLog b/ChangeLog
index fdf07aa..9f12410 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,4 @@
+- data.frame objects outside of globalenv() can be opened read-only in an editor window
- Show a warning screen when invoking plugins from the command line (or from clicking an rkward://-link in an external application)
--- Version 0.6.4 - XXXXXXXXXXXXXXX
diff --git a/rkward/core/rkmodificationtracker.cpp b/rkward/core/rkmodificationtracker.cpp
index 940696a..6db6b58 100644
--- a/rkward/core/rkmodificationtracker.cpp
+++ b/rkward/core/rkmodificationtracker.cpp
@@ -64,7 +64,7 @@ bool RKModificationTracker::removeObject (RObject *object, RKEditor *editor, boo
if (!object->isPseudoObject ()) {
if (removed_in_workspace) {
- if (ed && (ed->getObject () == object)) { // NOTE: do not allow restoring of columns in a data.frame this way. See https://mail.kde.org/pipermail/rkward-devel/2012-March/003225.html and replies.
+ if (ed && (ed->getObject () == object) && object->canWrite ()) { // NOTE: do not allow restoring of columns in a data.frame this way. See https://mail.kde.org/pipermail/rkward-devel/2012-March/003225.html and replies.
if (KMessageBox::questionYesNo (0, i18n ("The object '%1' was removed from workspace or changed to a different type of object, but is currently opened for editing. Do you want to restore it?", object->getFullName ()), i18n ("Restore object?")) == KMessageBox::Yes) {
ed->restoreObject (object);
/* TODO: It would make a lot of sense to allow restoring to a different name, and possibly different location. This may need some thinking. Probably something like:
diff --git a/rkward/core/robject.cpp b/rkward/core/robject.cpp
index f0d531c..1c0ca12 100644
--- a/rkward/core/robject.cpp
+++ b/rkward/core/robject.cpp
@@ -749,7 +749,7 @@ void RObject::endEdit () {
RK_ASSERT (false);
}
-bool RObject::canEdit () const {
+bool RObject::canWrite () const {
RK_TRACE (OBJECTS);
// TODO: find out, if binding is locked:
diff --git a/rkward/core/robject.h b/rkward/core/robject.h
index 239bc10..92308c0 100644
--- a/rkward/core/robject.h
+++ b/rkward/core/robject.h
@@ -146,7 +146,7 @@ public:
/** Returns the editor of this object, if any, or 0 */
RKEditor* editor () const;
- bool canEdit () const;
+ bool canWrite () const;
bool canRead () const;
bool canRename () const;
bool canRemove () const;
diff --git a/rkward/dataeditor/twintable.cpp b/rkward/dataeditor/twintable.cpp
index fe83204..595e620 100644
--- a/rkward/dataeditor/twintable.cpp
+++ b/rkward/dataeditor/twintable.cpp
@@ -173,6 +173,8 @@ void TwinTable::initTable (RKVarEditModel* model, RObject* object) {
datamodel = model;
main_object = object;
+ action_enable_editing->setEnabled (object->canWrite ());
+ action_tb_unlock_editing->setEnabled (object->canWrite ());
dataview->setRKModel (model);
metaview->setRKModel (model->getMetaModel ());
model->setEditor (this);
@@ -468,7 +470,7 @@ void TwinTable::enableEditing (bool on) {
flushEdit ();
- rw = on;
+ rw = main_object ? on && main_object->canWrite () : on; // NOTE: File->New->Dataset creates an Editor window, first, then sets the object to edit afterwards (TODO which looks like silly design)
metaview->rw = rw;
dataview->rw = rw;
@@ -485,6 +487,7 @@ void TwinTable::enableEditing (bool on) {
edit_actions->setEnabled (rw);
action_enable_editing->setChecked (rw);
+ action_tb_lock_editing->setChecked (!rw);
action_tb_unlock_editing->setChecked (rw);
if (main_object) objectMetaChanged (main_object); // update_caption;
diff --git a/rkward/plugin/rkpreviewbox.cpp b/rkward/plugin/rkpreviewbox.cpp
index d2ccafc..db98265 100644
--- a/rkward/plugin/rkpreviewbox.cpp
+++ b/rkward/plugin/rkpreviewbox.cpp
@@ -48,6 +48,9 @@ RKPreviewBox::RKPreviewBox (const QDomElement &element, RKComponent *parent_comp
addChild ("state", state = new RKComponentPropertyBool (this, true, preview_active, "active", "inactive"));
state->setInternal (true); // restoring this does not make sense.
connect (state, SIGNAL (valueChanged(RKComponentPropertyBase*)), this, SLOT (changedState(RKComponentPropertyBase*)));
+ idprop = new RKComponentPropertyBase (this, false);
+ idprop->setValue (RObject::rQuote (QString ().sprintf ("%p", this)));
+ addChild ("id", idprop);
// create checkbox
QVBoxLayout *vbox = new QVBoxLayout (this);
@@ -145,8 +148,7 @@ void RKPreviewBox::tryPreviewNow () {
}
preview_active = true;
- QString dummy;
- RKGlobals::rInterface ()->issueCommand (dummy.sprintf (".rk.startPreviewDevice (\"%p\")", this), RCommand::Plugin | RCommand::Sync | RCommand::GetIntVector, QString (), this, START_DEVICE);
+ RKGlobals::rInterface ()->issueCommand (".rk.startPreviewDevice (" + idprop->value ().toString () + ')', RCommand::Plugin | RCommand::Sync | RCommand::GetIntVector, QString (), this, START_DEVICE);
RKCaughtX11Window::setStatusMessage (dev_num, i18n ("Preview updating"));
RKGlobals::rInterface ()->issueCommand ("local({\n" + code_property->preview () + "})\n", RCommand::Plugin | RCommand::Sync, QString (), this, DO_PLOT);
@@ -161,8 +163,7 @@ void RKPreviewBox::killPreview () {
if (!preview_active) return;
preview_active = false;
- QString command;
- RKGlobals::rInterface ()->issueCommand (command.sprintf (".rk.killPreviewDevice (\"%p\")", this), RCommand::Plugin | RCommand::Sync);
+ RKGlobals::rInterface ()->issueCommand (".rk.killPreviewDevice (" + idprop->value ().toString () + ')', RCommand::Plugin | RCommand::Sync);
last_plot_done = true;
new_plot_pending = false;
diff --git a/rkward/plugin/rkpreviewbox.h b/rkward/plugin/rkpreviewbox.h
index 9ab3d01..4803fbc 100644
--- a/rkward/plugin/rkpreviewbox.h
+++ b/rkward/plugin/rkpreviewbox.h
@@ -63,6 +63,7 @@ private:
QCheckBox *toggle_preview_box;
QLabel *status_label;
RKComponentPropertyCode *code_property;
+ RKComponentPropertyBase *idprop;
};
#endif
diff --git a/rkward/rbackend/rpackages/rkward/R/internal.R b/rkward/rbackend/rpackages/rkward/R/internal.R
index 82ce60a..0448ad5 100644
--- a/rkward/rbackend/rpackages/rkward/R/internal.R
+++ b/rkward/rbackend/rpackages/rkward/R/internal.R
@@ -447,3 +447,22 @@ assign("available.packages.cache", NULL, envir=.rk.variables)
# call separate assignments functions:
if (exists (".rk.fix.assignments.graphics")) eval (body (.rk.fix.assignments.graphics)) # internal_graphics.R
}
+
+assign(".rk.preview.data", list (), envir=.rk.variables)
+
+# TODO document, move somewhere appropriate
+".rk.create.preview.data" <- function (id) {
+ pdata <- .rk.variables$.rk.preview.data
+ if (is.null (pdata[[id]])) {
+ pdata[[id]] <- list ()
+ assign (".rk.preview.data", pdata, envir=.rk.variables)
+ }
+ invisible (pdata[[id]])
+}
+
+".rk.discard.preview.data" <- function (id) {
+ pdata <- .rk.variables$.rk.preview.data
+ pdata[[id]] <- NULL
+ assign (".rk.preview.data", pdata, envir=.rk.variables)
+ invisible (NULL)
+}
diff --git a/rkward/rbackend/rpackages/rkward/R/internal_graphics.R b/rkward/rbackend/rpackages/rkward/R/internal_graphics.R
index 52cde14..ec10fe4 100644
--- a/rkward/rbackend/rpackages/rkward/R/internal_graphics.R
+++ b/rkward/rbackend/rpackages/rkward/R/internal_graphics.R
@@ -23,6 +23,10 @@ assign(".rk.preview.devices", list (), envir=.rk.variables)
#' @export
".rk.startPreviewDevice" <- function (x) {
+ # NOTE: I considered rewriting this to use .rk.create.preview.data(), but it did not seem right
+ # 1. Creation and removal of storage is mostly trivial
+ # 2. Plot previews need some extra logic for handling deivce closes (see .rk.discard.preview.device.num()), and implementing
+ # this is easier, if plot preview data is kept in an entirely separate storage
a <- .rk.variables$.rk.preview.devices[[x]]
if (is.null (a)) {
devnum <- dev.cur ()
diff --git a/rkward/windows/robjectbrowser.cpp b/rkward/windows/robjectbrowser.cpp
index 5412162..1a6d6ee 100644
--- a/rkward/windows/robjectbrowser.cpp
+++ b/rkward/windows/robjectbrowser.cpp
@@ -250,7 +250,8 @@ void RObjectBrowserInternal::contextMenuCallback (RObject *, bool *) {
}
actions[Help]->setVisible (!(object->isType (RObject::ToplevelEnv) || object->isInGlobalEnv ()));
- actions[Edit]->setVisible (object->canEdit () && RKWorkplace::mainWorkplace ()->canEditObject (object));
+ actions[Edit]->setText (object->canWrite () ? i18n ("Edit") : i18n ("View in editor (read-only)"));
+ actions[Edit]->setVisible (RKWorkplace::mainWorkplace ()->canEditObject (object));
actions[View]->setVisible (object->canRead ());
actions[Rename]->setVisible (object->canRename ());
actions[Copy]->setVisible (object->canRead () && (!object->isType (RObject::ToplevelEnv)));
@@ -267,7 +268,7 @@ void RObjectBrowserInternal::doubleClicked (const QModelIndex& index) {
if (!object) return;
if (object == RObjectList::getObjectList ()) return;
- if (object->canEdit () && RKWorkplace::mainWorkplace ()->canEditObject (object)) {
+ if (RKWorkplace::mainWorkplace ()->canEditObject (object)) {
RKWorkplace::mainWorkplace ()->editObject (object);
} else {
RKWorkplace::mainWorkplace ()->flushAllData ();
More information about the rkward-tracker
mailing list