[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