[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