[education/rkward/devel/workspace_output] rkward: Allow opening output files from file window.
Thomas Friedrichsmeier
null at kde.org
Wed Mar 2 16:55:52 GMT 2022
Git commit 4c0de2abf17a218e6cb84e2cdd69b2e6fd9ae87d by Thomas Friedrichsmeier.
Committed on 02/03/2022 at 16:55.
Pushed by tfry into branch 'devel/workspace_output'.
Allow opening output files from file window.
This needed some fixes around canonicalFilePath().
M +1 -1 rkward/dialogs/rksavemodifieddialog.cpp
M +27 -15 rkward/misc/rkoutputdirectory.cpp
M +5 -4 rkward/misc/rkoutputdirectory.h
M +1 -1 rkward/windows/rkhtmlwindow.cpp
M +14 -3 rkward/windows/rkworkplace.cpp
https://invent.kde.org/education/rkward/commit/4c0de2abf17a218e6cb84e2cdd69b2e6fd9ae87d
diff --git a/rkward/dialogs/rksavemodifieddialog.cpp b/rkward/dialogs/rksavemodifieddialog.cpp
index 5eefe7dd..03fc674b 100644
--- a/rkward/dialogs/rksavemodifieddialog.cpp
+++ b/rkward/dialogs/rksavemodifieddialog.cpp
@@ -155,7 +155,7 @@ void RKSaveModifiedDialog::saveSelected() {
for (auto it = outputdir_checklist.constBegin(); it != outputdir_checklist.constEnd(); ++it) {
if (it.key ()->checkState (0) != Qt::Checked) continue;
- RKOutputDirectory *dir = RKOutputDirectory::getOutputById(it.value());
+ RKOutputDirectory *dir = RKOutputDirectory::findOutputById(it.value());
if (dir) {
if (dir->save().failed()) all_ok = false;
}
diff --git a/rkward/misc/rkoutputdirectory.cpp b/rkward/misc/rkoutputdirectory.cpp
index cd122da5..c0b959e7 100644
--- a/rkward/misc/rkoutputdirectory.cpp
+++ b/rkward/misc/rkoutputdirectory.cpp
@@ -78,13 +78,13 @@ RKOutputDirectory::~RKOutputDirectory() {
RK_TRACE(APP);
}
-RKOutputDirectory* RKOutputDirectory::getOutputById(const QString& id) {
+RKOutputDirectory* RKOutputDirectory::findOutputById(const QString& id) {
RK_TRACE (APP);
return outputs.value(id);
}
-RKOutputDirectory* RKOutputDirectory::getOutputByWorkPath(const QString& workpath) {
+RKOutputDirectory* RKOutputDirectory::findOutputByWorkPath(const QString& workpath) {
RK_TRACE (APP);
if (workpath.endsWith("index.html")) {
@@ -94,10 +94,9 @@ RKOutputDirectory* RKOutputDirectory::getOutputByWorkPath(const QString& workpat
return nullptr;
}
-RKOutputDirectory* RKOutputDirectory::getOutputBySaveUrl(const QString& _dest) {
+RKOutputDirectory* RKOutputDirectory::findOutputBySaveUrl(const QString& dest) {
RK_TRACE (APP);
- QString dest = QFileInfo(_dest).canonicalFilePath();
for (auto it = outputs.constBegin(); it != outputs.constEnd(); ++it) {
if (it.value()->save_filename == dest) {
return(it.value());
@@ -106,7 +105,7 @@ RKOutputDirectory* RKOutputDirectory::getOutputBySaveUrl(const QString& _dest) {
return nullptr;
}
-RKOutputDirectory* RKOutputDirectory::getOutputByWindow(const RKMDIWindow *window) {
+RKOutputDirectory* RKOutputDirectory::findOutputByWindow(const RKMDIWindow *window) {
RK_TRACE (APP);
if (!window) return nullptr;
@@ -129,7 +128,7 @@ GenericRRequestResult RKOutputDirectory::save(const QString& _dest, RKOutputDire
}
GenericRRequestResult res = exportAs(dest, overwrite);
if (!res.failed()) {
- save_filename = res.ret.toString(); // might by different from dest, notably, if dest was empty
+ save_filename = res.ret.toString(); // might by different from dest, notably, if dest was empty or not yet normalized
known_modified = true; // dirty trick to ensure that updateSavedHash() will trigger a stateChange()->update caption in views, even if using SaveAs on an unmodified directory
updateSavedHash();
}
@@ -495,19 +494,32 @@ RKOutputDirectoryCallResult RKOutputDirectory::get(const QString &_filename, boo
} else {
return (getCurrentOutput(chain));
}
- } else {
- QString filename = QFileInfo(_filename).canonicalFilePath();
- ret.setDir(getOutputBySaveUrl(filename));
+ } else { // filename not empty
+ QFileInfo fi(_filename);
+ bool file_exists = fi.exists();
+ QString filename = file_exists ? fi.canonicalFilePath() : _filename;
+ RKOutputDirectory *dir = file_exists ? findOutputBySaveUrl(filename) : nullptr;
+ // NOTE: annoyingly QFileInfo::canonicalFilePath() returns an empty string, if the file does not exist
if (create) {
- if (ret.dir()) return GenericRRequestResult::makeError(i18n("Output '1%' is already loaded in this session. Cannot create it.", filename));
- if (QFileInfo(filename).exists()) return GenericRRequestResult::makeError(i18n("A file named '1%' already exists. Cannot create it.", filename));
+ if (dir) return GenericRRequestResult::makeError(i18n("Output '1%' is already loaded in this session. Cannot create it.", filename));
+ if (file_exists) return GenericRRequestResult::makeError(i18n("A file named '1%' already exists. Cannot create it.", filename));
+
ret.setDir(createOutputDirectoryInternal());
- ret.addMessages(ret.dir()->import(filename));
+ ret.addMessages(dir->save(filename)); // NOTE: save() takes care of normalizing
} else {
+ if (!file_exists) return GenericRRequestResult::makeError(i18n("File '%1' does not exist.", filename));
+
+ ret.setDir(findOutputBySaveUrl(filename));
if (!ret.dir()) {
- ret.setDir(createOutputDirectoryInternal());
- ret.addMessages(ret.dir()->import(filename));
+ auto dir = createOutputDirectoryInternal();
+ ret.addMessages(dir->import(filename));
+ if (ret.failed()) {
+ dir->purge(Force);
+ } else {
+ ret.setDir(dir);
+ }
}
+ // else we have already set the loaded dir as ret.dir()
}
}
return ret;
@@ -533,7 +545,7 @@ GenericRRequestResult RKOutputDirectory::handleRCall(const QStringList& params,
} else {
// all other commands pass the output id as second parameter. Look that up, first
QString id = params.value(1);
- auto out = getOutputById(id);
+ auto out = findOutputById(id);
if (!out) {
return GenericRRequestResult::makeError(i18n("The output identified by '%1' is not loaded in this session.", id));
}
diff --git a/rkward/misc/rkoutputdirectory.h b/rkward/misc/rkoutputdirectory.h
index 7015f62e..f4b6aea2 100644
--- a/rkward/misc/rkoutputdirectory.h
+++ b/rkward/misc/rkoutputdirectory.h
@@ -69,10 +69,9 @@ public:
QString workPath() const;
QString caption() const;
static GenericRRequestResult handleRCall(const QStringList& params, RCommandChain *chain);
- static RKOutputDirectory* getOutputById(const QString& id);
- static RKOutputDirectory* getOutputByWorkPath(const QString& workpath);
- static RKOutputDirectory* getOutputBySaveUrl(const QString& dest);
- static RKOutputDirectory* getOutputByWindow(const RKMDIWindow* window);
+ static RKOutputDirectory* findOutputById(const QString& id);
+ static RKOutputDirectory* findOutputByWorkPath(const QString& workpath);
+ static RKOutputDirectory* findOutputByWindow(const RKMDIWindow* window);
/** Return a list of all current output directories that have been modified. Used for asking for save during shutdown. */
static QList<RKOutputDirectory*> modifiedOutputDirectories();
@@ -94,6 +93,8 @@ private:
void updateSavedHash();
/** Currently active output. Could be nullptr in corner cases! */
RKOutputDirectory* activeOutput();
+ /** Note dest must be normalized. Hiding as private to avoid mis-use. */
+ static RKOutputDirectory* findOutputBySaveUrl(const QString& dest);
QString saved_hash;
QDateTime save_timestamp;
diff --git a/rkward/windows/rkhtmlwindow.cpp b/rkward/windows/rkhtmlwindow.cpp
index 0c9d4408..b9a53229 100644
--- a/rkward/windows/rkhtmlwindow.cpp
+++ b/rkward/windows/rkhtmlwindow.cpp
@@ -567,7 +567,7 @@ bool RKHTMLWindow::openURL (const QUrl &url) {
current_url = url; // needs to be set before registering
RKOutputWindowManager::self ()->registerWindow (this);
- dir = RKOutputDirectory::getOutputByWorkPath(url.toLocalFile());
+ dir = RKOutputDirectory::findOutputByWorkPath(url.toLocalFile());
part->setOutputDirectoryActionsEnabled(dir != nullptr);
if (dir) {
connect(dir, &RKOutputDirectory::stateChange, this, &RKHTMLWindow::updateState);
diff --git a/rkward/windows/rkworkplace.cpp b/rkward/windows/rkworkplace.cpp
index 886a512c..54ae864c 100644
--- a/rkward/windows/rkworkplace.cpp
+++ b/rkward/windows/rkworkplace.cpp
@@ -424,10 +424,21 @@ bool RKWorkplace::openAnyUrl (const QUrl &url, const QString &known_mimetype, bo
openHelpWindow (url, true);
return true; // TODO
}
- if (url.fileName ().toLower ().endsWith (QLatin1String (".rdata")) || url.fileName ().toLower ().endsWith (QLatin1String (".rda"))) {
- RKWardMainWindow::getMain ()->askOpenWorkspace (url);
+ QString lname = url.fileName().toLower();
+ if (lname.endsWith(QLatin1String(".rdata")) || lname.endsWith(QLatin1String(".rda"))) {
+ RKWardMainWindow::getMain()->askOpenWorkspace(url);
return true; // TODO
}
+ if (lname.endsWith(".rko")) {
+ auto ret = RKOutputDirectory::get(url.toLocalFile(), false);
+ if (!ret.failed()) {
+ ret.dir()->view(true);
+ return true;
+ } else {
+ KMessageBox::sorry(this, i18n("Failed to open output file. Error message was '%1'", ret.error));
+ return false;
+ }
+ }
if (mimetype.inherits ("text/plain")) {
return (openScriptEditor (url, QString ()));
}
@@ -805,7 +816,7 @@ QString RKWorkplace::makeItemDescription (RKMDIWindow *win) const {
specification = static_cast<RKCommandEditorWindow*> (win)->url ().url ();
if (specification.isEmpty ()) specification = static_cast<RKCommandEditorWindow*> (win)->id ();
} else if (win->isType (RKMDIWindow::OutputWindow)) {
- RKOutputDirectory *dir = RKOutputDirectory::getOutputByWindow(win);
+ RKOutputDirectory *dir = RKOutputDirectory::findOutputByWindow(win);
if (dir) {
type = "rkoutput";
specification = QUrl::fromLocalFile(dir->filename()).url();
More information about the rkward-tracker
mailing list