[education/rkward/devel/workspace_output] rkward: WIP. Don't push.

Thomas Friedrichsmeier null at kde.org
Sat Oct 10 09:18:45 BST 2020


Git commit 1233b4113cd9f12d0f9876ab32e9be234140b23f by Thomas Friedrichsmeier.
Committed on 25/03/2018 at 08:02.
Pushed by tfry into branch 'devel/workspace_output'.

WIP. Don't push.

M  +53   -8    rkward/dialogs/rksavemodifieddialog.cpp
M  +2    -0    rkward/dialogs/rksavemodifieddialog.h
M  +4    -1    rkward/rbackend/rkrinterface.cpp
M  +6    -4    rkward/rbackend/rpackages/rkward/R/rk.filename-functions.R
M  +13   -6    rkward/windows/rkhtmlwindow.cpp
M  +18   -6    rkward/windows/rkhtmlwindow.h
M  +1    -1    rkward/windows/rkworkplace.h

https://invent.kde.org/education/rkward/commit/1233b4113cd9f12d0f9876ab32e9be234140b23f

diff --git a/rkward/dialogs/rksavemodifieddialog.cpp b/rkward/dialogs/rksavemodifieddialog.cpp
index d5e12df2..10b1111d 100644
--- a/rkward/dialogs/rksavemodifieddialog.cpp
+++ b/rkward/dialogs/rksavemodifieddialog.cpp
@@ -27,11 +27,16 @@
 
 #include <klocale.h>
 
+#include "../windows/rkworkplace.h"
+#include "../windows/rkhtmlwindow.h"
+
 #include "../debug.h"
 
 bool RKSaveModifiedDialog::askSaveModified (QWidget* parent, QList <RKMDIWindow*> windows, bool project) {
 	RK_TRACE (APP);
 
+	save_project_check = 0;
+
 	QList<RKMDIWindow*> modified_wins;
 	for (int i = 0; i < windows.size (); ++i) {
 		if (windows[i]->isModified ()) {
@@ -48,6 +53,21 @@ bool RKSaveModifiedDialog::askSaveModified (QWidget* parent, QList <RKMDIWindow*
 	return true;
 }
 
+QTreeWidgetItem* makeHeaderItem (const QString &label, QTreeWidget* tree) {
+	RK_TRACE (APP);
+
+	QTreeWidgetItem* header = new QTreeWidgetItem (QStringList (label));
+	header->setFirstColumnSpanned (true);
+	header->setFlags (Qt::ItemIsEnabled);
+	QFont f = tree->font ();
+	f.setBold (true);
+	header->setFont (0, f);
+	tree->addTopLevelItem (header);
+	header->setExpanded (true);
+
+	return header;
+}
+
 RKSaveModifiedDialog::RKSaveModifiedDialog (QWidget* parent, QList<RKMDIWindow*> modified_wins, bool project) : QDialog (parent) {
 	RK_TRACE (APP);
 
@@ -61,17 +81,32 @@ RKSaveModifiedDialog::RKSaveModifiedDialog (QWidget* parent, QList<RKMDIWindow*>
 	v_layout->addWidget (tree);
 
 	tree->header ()->hide ();
+#warning TODO: remove me
+project = true;
 	if (project) {
+		QTreeWidgetItem *header = makeHeaderItem (i18n ("R Workspace (Data and Functions)"), tree);
+		QString url = RKWorkplace::mainWorkplace ()->workspaceURL ().toDisplayString ();
+		if (url.isEmpty ()) {
+			url = i18n ("Not previously saved");
+		}
+		QTreeWidgetItem *save_project_check = new QTreeWidgetItem (QStringList (url));
+		header->addChild (save_project_check);
+		save_project_check->setCheckState (0, Qt::Checked);
+
+		QStringList modified_outputs = RKOutputWindowManager::modifiedOutputDirectories ();
+		if (!modified_outputs.isEmpty ()) {
+			QTreeWidgetItem *header = makeHeaderItem (i18n ("Output files"), tree);
+			for (int i = 0; i < modified_outputs.size (); ++i) {
+				QTreeWidgetItem *item = new QTreeWidgetItem (RKOutputWindowManager::outputCaption (modified_outputs[i]));
+				item->setFirstColumnSpanned (true);
+				header->addChild (item);
+				item->setCheckState (0, Qt::Checked);
+				outputdir_checklist.insert (item, modified_outputs[i]);
+			}
+		}
 	}
 	if (!modified_wins.isEmpty ()) {
-		QTreeWidgetItem* header = new QTreeWidgetItem (QStringList (i18n ("Scripts")));
-		header->setFirstColumnSpanned (true);
-		header->setFlags (Qt::ItemIsEnabled);
-		QFont f = tree->font ();
-		f.setBold (true);
-		header->setFont (0, f);
-		tree->addTopLevelItem (header);
-		header->setExpanded (true);
+		QTreeWidgetItem* header = makeHeaderItem (i18n ("Scripts"), tree);
 		for (int i = 0; i < modified_wins.size (); ++i) {
 			QTreeWidgetItem *item = new QTreeWidgetItem (QStringList (modified_wins[i]->fullCaption ()));
 			item->setFirstColumnSpanned (true);
@@ -115,6 +150,16 @@ void RKSaveModifiedDialog::saveSelected () {
 		if (!it.value ()) continue;
 		if (!it.value ()->save ()) all_ok = false; // but we proceed with the others
 	}
+
+	if (save_project_check && save_project_check->checkState (0) == Qt::Checked) {
+#warning TODO
+	}
+
+	for (QMap<QTreeWidgetItem *, QString>::const_iterator it = outputdir_checklist.constBegin (); it != outputdir_checklist.constEnd (); ++it) {
+		if (it.key ()->checkState (0) != Qt::Checked) continue;
+		RKOutputWindowManager::saveOutputDirectory (it.value ());
+	}
+
 	if (all_ok) accept ();
 	else reject ();
 }
diff --git a/rkward/dialogs/rksavemodifieddialog.h b/rkward/dialogs/rksavemodifieddialog.h
index 88cbfa8e..37ee2463 100644
--- a/rkward/dialogs/rksavemodifieddialog.h
+++ b/rkward/dialogs/rksavemodifieddialog.h
@@ -39,6 +39,8 @@ private:
 	RKSaveModifiedDialog (QWidget* parent, QList<RKMDIWindow*> modified_windows, bool project);
 	virtual ~RKSaveModifiedDialog ();
 	QMap<QTreeWidgetItem *, QPointer<RKMDIWindow>> window_checklist;
+	QTreeWidgetItem *save_project_check;
+	QMap<QTreeWidgetItem *, QString> outputdir_checklist;
 private slots:
 	void saveWorkplaceChanged ();
 	void saveSelected ();
diff --git a/rkward/rbackend/rkrinterface.cpp b/rkward/rbackend/rkrinterface.cpp
index 2e3a53d7..032ae1e4 100644
--- a/rkward/rbackend/rkrinterface.cpp
+++ b/rkward/rbackend/rkrinterface.cpp
@@ -764,7 +764,10 @@ void RInterface::processHistoricalSubstackRequest (const QStringList &calllist,
 		if (subcall == QStringLiteral ("export")) {
 			error = RKOutputWindowManager::self ()->saveOutputDirectoryAs (calllist.value (2), calllist.value (3), calllist.value (4) == QStringLiteral ("TRUE"), in_chain);
 		} else if (subcall == QStringLiteral ("import")) {
-			error = RKOutputWindowManager::self ()->importOutputDirectory (calllist.value (2), calllist.value (3), calllist.value (4) == QStringLiteral ("TRUE"), in_chain);
+			RKOutputWindowManager::ImportMode mode = RKOutputWindowManager::Ask;
+			if (calllist.value (4) == "integrate") mode = RKOutputWindowManager::Integrate;
+			else if (calllist.value (4) == "keep.separate") mode = RKOutputWindowManager::KeepSeparate;
+			error = RKOutputWindowManager::self ()->importOutputDirectory (calllist.value (2), calllist.value (3), mode, calllist.value (5) == QStringLiteral ("TRUE"), in_chain);
 		} else if (subcall == QStringLiteral ("create")) {
 			RKOutputWindowManager::self ()->createOutputDirectory (in_chain);
 		} else {
diff --git a/rkward/rbackend/rpackages/rkward/R/rk.filename-functions.R b/rkward/rbackend/rpackages/rkward/R/rk.filename-functions.R
index b1c06bd5..0da7a9c8 100644
--- a/rkward/rbackend/rpackages/rkward/R/rk.filename-functions.R
+++ b/rkward/rbackend/rpackages/rkward/R/rk.filename-functions.R
@@ -274,19 +274,21 @@
 #' @rdname rk.get.tempfile.name
 rk.export.output.dir <- function (source.dir=basename (rk.get.output.html.file ()), target.dir, ask=TRUE) {
 # This is not terribly complex, but we need an implementation in the frontend, anyway, so we use that.
-	x <- .rk.do.call ("output", c ("export", source.dir, target.dir, as.character (isTRUE (ask))))
+	.rk.do.call ("output", c ("export", source.dir, target.dir, as.character (isTRUE (ask))))
 }
 
 #' @export
 #' @rdname rk.get.tempfile.name
-rk.import.output.dir <- function (source.dir, activate="index.html", ask=TRUE) {
+rk.import.output.dir <- function (source.dir, activate="index.html", mode=c("ask", "integrate", "keep.separate"), ask=TRUE) {
 # This is not terribly complex, but we need an implementation in the frontend, anyway, so we use that.
-	x <- .rk.do.call ("output", c ("import", source.dir, activate, as.character (isTRUE (ask))))
+	.rk.do.call ("output", c ("import", source.dir, activate, as.character (isTRUE (ask))))
+	rk.get.output.html.file ()
 }
 
 #' @export
 #' @rdname rk.get.tempfile.name
 rk.create.output.dir <- function () {
 # This is not terribly complex, but we need an implementation in the frontend, anyway, so we use that.
-	x <- .rk.do.call ("output", c ("create"))
+	.rk.do.call ("output", c ("create"))
+	rk.get.output.html.file ()
 }
diff --git a/rkward/windows/rkhtmlwindow.cpp b/rkward/windows/rkhtmlwindow.cpp
index 71d79516..d5039c16 100644
--- a/rkward/windows/rkhtmlwindow.cpp
+++ b/rkward/windows/rkhtmlwindow.cpp
@@ -1203,14 +1203,14 @@ bool copyDirRecursively (const QString& _source_dir, const QString& _dest_dir) {
 	return ok;
 }
 
-QString RKOutputWindowManager::saveOutputDirectory (const QString& _dir, RCommandChain* chain) {
+QString RKOutputWindowManager::exportOutputDirectory (const QString& _dir, RCommandChain* chain) {
 	RK_TRACE (APP);
 
 	const QString dir = QFileInfo (_dir).canonicalFilePath ();
-	return saveOutputDirectoryAs (_dir, outputs.value (dir).save_dir, true, chain);  // pass raw "dir" parameter b/c of error handling.
+	return exportOutputDirectoryAs (_dir, outputs.value (dir).export_dir, true, chain);  // pass raw "dir" parameter b/c of error handling.
 }
 
-QString RKOutputWindowManager::saveOutputDirectoryAs (const QString& dir, const QString& _dest, bool ask_overwrite, RCommandChain* chain) {
+QString RKOutputWindowManager::exportOutputDirectoryAs (const QString& dir, const QString& _dest, bool ask_overwrite, RCommandChain* chain) {
 	RK_TRACE (APP);
 
 	const QString work_dir = QFileInfo (dir).canonicalFilePath ();
@@ -1220,7 +1220,7 @@ QString RKOutputWindowManager::saveOutputDirectoryAs (const QString& dir, const
 
 	QString dest = _dest;
 	if (dest.isEmpty ()) {
-		QFileDialog dialog (RKWardMainWindow::getMain (), i18n ("Specify directory where to save output"), outputs.value (work_dir).save_dir);
+		QFileDialog dialog (RKWardMainWindow::getMain (), i18n ("Specify directory where to export output"), outputs.value (work_dir).export_dir);
 		dialog.setFileMode (QFileDialog::Directory);
 		dialog.setOption (QFileDialog::ShowDirsOnly, true);
 		dialog.setAcceptMode (QFileDialog::AcceptSave);
@@ -1236,7 +1236,7 @@ QString RKOutputWindowManager::saveOutputDirectoryAs (const QString& dir, const
 				return i18n ("The directory %1 exists, but does not appear to be an RKWard output directory. Refusing to overwrite it.", dest);
 			}
 
-			const QString warning = i18n ("Are you sure you want to overwrite the existing directory '%1'? All current contents, including subdirectories will be lost.", dest);
+			const QString warning = i18n ("Are you sure you want to overwrite the existing directory '%1'? All current contents, <b>including subdirectories</b> will be lost.", dest);
 			KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel (RKWardMainWindow::getMain (), warning, i18n ("Overwrite Directory?"), KStandardGuiItem::overwrite (),
 			                                                                 KStandardGuiItem::cancel (), QString (), KMessageBox::Options (KMessageBox::Notify | KMessageBox::Dangerous));
 			if (KMessageBox::Continue != res) {
@@ -1274,7 +1274,7 @@ QString RKOutputWindowManager::saveOutputDirectoryAs (const QString& dir, const
 
 	OutputDirectory& od = outputs[work_dir];
 	od.save_timestamp = QDateTime::currentDateTime ();
-	od.save_dir = dest;
+	od.export_dir = dest;
 	od.saved_hash = hashDirectoryState (work_dir);
 
 	return QString ();
@@ -1455,6 +1455,13 @@ QStringList RKOutputWindowManager::modifiedOutputDirectories() const {
 	return ret;
 }
 
+QString RKOutputWindowManager::outputCaption (const QString& dir) const {
+	RK_TRACE (APP);
+
+	// TODO: real implementation!
+	return (dir);
+}
+
 bool RKOutputWindowManager::isRKWwardOutputDirectory (const QString& dir) {
 	RK_TRACE (APP);
 
diff --git a/rkward/windows/rkhtmlwindow.h b/rkward/windows/rkhtmlwindow.h
index d7d0812a..72e3f970 100644
--- a/rkward/windows/rkhtmlwindow.h
+++ b/rkward/windows/rkhtmlwindow.h
@@ -226,17 +226,26 @@ public:
 	QList<RKHTMLWindow*> existingOutputWindows (const QString &path = QString ()) const;
 /** Create (and show) a new output window (for the current output path, unless path is specified), and @return the pointer */
 	RKHTMLWindow* newOutputWindow (const QString& path = QString ());
+	enum ImportMode {
+		Ask,           /// Ask whether to integrate imported output into workplace
+		Integrate,     /// Integrate imported output (forget original source, save with workplace)
+		KeepSeparate   /// Keep output separate (save back to original source)
+	};
 /** Import an existing output directory. @Returns error message, if any, and empty string in case of success */
 	QString importOutputDirectory (const QString& dir, const QString& index_file=QString (), bool ask_revert = true, RCommandChain* chain = 0);
-/** Save the given output directory to the locaiton it was last saved to / imported from. If the output directory has not been saved / imported, yet, prompt the user for a destination.
-    @param index_path output directory to save
+/** Export the given output directory to the location it was last exported to / imported from. If the output directory has not been exported / imported, yet, prompt the user for a destination.
+    @param dir output directory to export
     @returns error message, if any, an empty string in case of success */
-	QString saveOutputDirectory (const QString& dir, RCommandChain* chain = 0);
-/** Save the given output directory. @see saveOutputDirectory ().
-    @param index_path the output directory to save
+	QString exportOutputDirectory (const QString& dir, RCommandChain* chain = 0);
+/** Export the given output directory. @see exportOutputDirectory ().
+    @param dir the output directory to export
     @param dest destination directory. May be left empty, in which case the user will be prompted for a destination.
     @returns error message, if any, an empty string in case of success */
-	QString saveOutputDirectoryAs (const QString& dir, const QString& dest = QString (), bool ask_overwrite = true, RCommandChain* chain = 0);
+	QString exportOutputDirectoryAs (const QString& dir, const QString& dest = QString (), bool ask_overwrite = true, RCommandChain* chain = 0);
+/** Save the given output directory to the given location. Does not ask for overwrite confirmation.
+    @param dir output directory to save
+    @returns error message, if any, an empty string in case of success */
+	QString saveOutputDirectory (const QString& dir, const QString& dest, RCommandChain* chain = 0);
 /** Create a new empty output directory.
     @returns path of the new directory */
 	QString createOutputDirectory (RCommandChain* chain = 0);
@@ -245,6 +254,8 @@ public:
 
 /** Return a list of all current output directories that have been modified. Used for asking for save during shutdown. */
 	QStringList modifiedOutputDirectories () const;
+/** Return the name / caption of the given output directory */
+	QString outputCaption (const QString &dir) const;
 /** Use with case! Purges all current output directories, saved or not. You should query modifiedOutputDirectories (), and make sure to prompt for saving, before calling this. For use during shutdown. */
 	void purgeAllOututputDirectories ();
 private:
@@ -260,6 +271,7 @@ private:
 		QString index_file;
 		QString saved_hash;
 		QDateTime save_timestamp;
+		QString export_dir;
 		QString save_dir;
 	};
 	/** map of outputs. Key is the working directory of the output */
diff --git a/rkward/windows/rkworkplace.h b/rkward/windows/rkworkplace.h
index c0527791..4dafae1c 100644
--- a/rkward/windows/rkworkplace.h
+++ b/rkward/windows/rkworkplace.h
@@ -138,7 +138,7 @@ public:
 /** Close the given window, whether it is attached or detached.
 @param window window to close */
 	void closeWindow (RKMDIWindow *window, RKMDIWindow::CloseWindowMode ask_save = RKMDIWindow::AutoAskSaveModified);
-/** Close the given windows, whether they are attached or detached. TODO: Be smart about asking what to save.
+/** Close the given windows, whether they are attached or detached.
 @param windows list windows to close
 @returns false if cancelled by user (user was prompted for saving, and chose cancel) */
 	bool closeWindows (QList<RKMDIWindow*> windows);




More information about the rkward-tracker mailing list