[rkward/frameworks] /: Also remember last used location in plugin filebrowsers. While at it, implement basic validity checking.
Thomas Friedrichsmeier
thomas.friedrichsmeier at ruhr-uni-bochum.de
Sat Nov 28 14:53:19 UTC 2015
Git commit 94aa5b017ab5280c759ee2e9874a1a9878c61fe8 by Thomas Friedrichsmeier.
Committed on 28/11/2015 at 14:53.
Pushed by tfry into branch 'frameworks'.
Also remember last used location in plugin filebrowsers. While at it, implement basic validity checking.
M +1 -0 ChangeLog
M +31 -3 rkward/misc/getfilenamewidget.cpp
M +4 -0 rkward/misc/getfilenamewidget.h
M +79 -8 rkward/plugin/rkpluginbrowser.cpp
M +9 -3 rkward/plugin/rkpluginbrowser.h
http://commits.kde.org/rkward/94aa5b017ab5280c759ee2e9874a1a9878c61fe8
diff --git a/ChangeLog b/ChangeLog
index 270b5ec..90bc0f5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,4 @@
+- File selection fields in plugin dialogs remember the last used directory (per session), and check for a valid selection
- Better handling of text drag-and-drop inside the R console window
--- Version 0.6.4 - XXXXXXXXXXXXXXX
diff --git a/rkward/misc/getfilenamewidget.cpp b/rkward/misc/getfilenamewidget.cpp
index f0b9e71..d23c056 100644
--- a/rkward/misc/getfilenamewidget.cpp
+++ b/rkward/misc/getfilenamewidget.cpp
@@ -24,6 +24,8 @@
#include <KLineEdit>
#include <kurlrequester.h>
+#include "../settings/rksettingsmodulegeneral.h"
+
#include "../debug.h"
GetFileNameWidget::GetFileNameWidget (QWidget *parent, FileType mode, bool only_local, const QString &label, const QString &caption, const QString &initial) : QWidget (parent) {
@@ -35,11 +37,9 @@ GetFileNameWidget::GetFileNameWidget (QWidget *parent, FileType mode, bool only_
if (!label.isEmpty ()) vbox->addWidget (new QLabel (label, this));
edit = new KUrlRequester (this);
- connect (edit, &KUrlRequester::textChanged, this, &GetFileNameWidget::locationEditChanged);
vbox->addWidget (edit);
- edit->setUrl (QUrl::fromUserInput (initial, QString (), QUrl::AssumeLocalFile));
-
+ _mode = mode;
KFile::Modes mode_flags;
if (mode == ExistingDirectory) {
mode_flags = KFile::Directory | KFile::ExistingOnly;
@@ -60,6 +60,26 @@ GetFileNameWidget::GetFileNameWidget (QWidget *parent, FileType mode, bool only_
if (only_local) mode_flags |= KFile::LocalOnly;
edit->setMode (mode_flags);
+ QString append = initial;
+ if (initial.startsWith ('<')) {
+ storage_key = initial.section ('>', 0, 0).mid (1);
+ append = initial.section ('>', 1);
+ }
+ QUrl initial_url = RKSettingsModuleGeneral::lastUsedUrlFor (storage_key); // storage_key == QString () in the default case is intended
+ if (!append.isEmpty ()) {
+ if (initial_url.isLocalFile ()) {
+ initial_url = QUrl::fromUserInput (append, initial_url.toLocalFile (), QUrl::AssumeLocalFile);
+ } else {
+ initial_url.setPath (initial_url.path () + '/' + append);
+ }
+ initial_url = initial_url.adjusted (QUrl::NormalizePathSegments);
+ }
+ if (initial_url.isLocalFile () || !only_local) {
+ edit->setUrl (initial_url);
+ }
+ connect (edit, &KUrlRequester::textChanged, this, &GetFileNameWidget::locationEditChanged);
+ connect (edit, &KUrlRequester::urlSelected, this, &GetFileNameWidget::updateLastUsedUrl);
+
if (caption.isEmpty ()) edit->setWindowTitle (label);
else edit->setWindowTitle (caption);
}
@@ -75,6 +95,14 @@ void GetFileNameWidget::setFilter (const QString &filter) {
edit->setFilter (filter);
}
+void GetFileNameWidget::updateLastUsedUrl (const QUrl& url) {
+ RK_TRACE (MISC);
+
+ if (!url.isValid ()) return;
+ if (edit->mode () & KFile::Directory) RKSettingsModuleGeneral::updateLastUsedUrl (storage_key, url);
+ else RKSettingsModuleGeneral::updateLastUsedUrl (storage_key, url.adjusted (QUrl::RemoveFilename));
+}
+
void GetFileNameWidget::setLocation (const QString &new_location) {
RK_TRACE (MISC);
diff --git a/rkward/misc/getfilenamewidget.h b/rkward/misc/getfilenamewidget.h
index 64cf7d6..ecbf136 100644
--- a/rkward/misc/getfilenamewidget.h
+++ b/rkward/misc/getfilenamewidget.h
@@ -34,6 +34,7 @@ public:
GetFileNameWidget (QWidget *parent, FileType mode, bool only_local, const QString &label, const QString &caption, const QString &initial);
~GetFileNameWidget ();
+ FileType getMode () const { return (_mode); };
/** set filename pattern filter, e.g. "*.cpp *.cc *.C|C++ Source Files\n*.h *.H|Header files" */
void setFilter (const QString &filter);
@@ -46,6 +47,7 @@ public:
QString getLocation ();
public slots:
void locationEditChanged (const QString &);
+ void updateLastUsedUrl (const QUrl& url);
signals:
void locationChanged ();
#ifdef Q_OS_WIN
@@ -53,6 +55,8 @@ private slots:
void hackOverrideDirDialog ();
#endif
private:
+ FileType _mode;
+ QString storage_key;
KUrlRequester *edit;
};
diff --git a/rkward/plugin/rkpluginbrowser.cpp b/rkward/plugin/rkpluginbrowser.cpp
index cc7e190..8c4e438 100644
--- a/rkward/plugin/rkpluginbrowser.cpp
+++ b/rkward/plugin/rkpluginbrowser.cpp
@@ -18,6 +18,8 @@
#include "rkpluginbrowser.h"
#include <QVBoxLayout>
+#include <QUrl>
+#include <QDir>
#include <klocale.h>
@@ -37,7 +39,7 @@ RKPluginBrowser::RKPluginBrowser (const QDomElement &element, RKComponent *paren
connect (selection, &RKComponentPropertyBase::valueChanged, this, &RKPluginBrowser::textChanged);
setRequired (xml->getBoolAttribute (element, "required", true, DL_INFO));
- connect (requirednessProperty (), &RKComponentPropertyBase::valueChanged, this, &RKPluginBrowser::updateColor);
+ connect (requirednessProperty (), &RKComponentPropertyBase::valueChanged, this, &RKPluginBrowser::validateInput);
QVBoxLayout *vbox = new QVBoxLayout (this);
vbox->setContentsMargins (0, 0, 0, 0);
@@ -48,19 +50,22 @@ RKPluginBrowser::RKPluginBrowser (const QDomElement &element, RKComponent *paren
else if (intmode == 1) mode = GetFileNameWidget::ExistingDirectory;
else mode = GetFileNameWidget::SaveFile;
- bool only_local = !xml->getBoolAttribute (element, "allow_urls", false, DL_INFO);
+ only_local = !xml->getBoolAttribute (element, "allow_urls", false, DL_INFO);
label_string = xml->i18nStringAttribute (element, "label", i18n ("Enter filename"), DL_INFO);
selector = new GetFileNameWidget (this, mode, only_local, label_string, i18n ("Select"), xml->getStringAttribute (element, "initial", QString (), DL_INFO));
QString filter = xml->getStringAttribute (element, "filter", QString (), DL_INFO);
if (!filter.isEmpty ()) {
- filter.append ("\n*|All files");
+ filter.append ("\nAll files (*)");
selector->setFilter (filter);
}
connect (selector, &GetFileNameWidget::locationChanged, this, &RKPluginBrowser::textChangedFromUi);
vbox->addWidget (selector);
+ validation_timer.setSingleShot (true);
+ connect (&validation_timer, &QTimer::timeout, this, &RKPluginBrowser::validateInput);
+
// initialize
updating = false;
textChangedFromUi ();
@@ -76,11 +81,22 @@ void RKPluginBrowser::textChanged (RKComponentPropertyBase *) {
if (updating) return;
updating = true;
- selector->setLocation (fetchStringValue (selection));
+ if (status != RKComponentBase::Processing) {
+ status = RKComponentBase::Processing;
+ changed ();
+ }
+ validation_timer.start (300);
+
+ QUrl url = QUrl::fromUserInput (selection->value ().toString (), QDir::currentPath (), QUrl::AssumeLocalFile);
+ if (!url.isValid ()) url = QUrl (selector->getLocation ());
+ if (url.url () != selection->value ().toString ()) {
+ // NOTE: We refuse to accept relative urls
+ selection->setValue (url.url ());
+ }
+ selector->setLocation (url.url ());
updateColor ();
updating = false;
- changed ();
}
void RKPluginBrowser::textChangedFromUi () {
@@ -89,16 +105,71 @@ void RKPluginBrowser::textChangedFromUi () {
selection->setValue (selector->getLocation ());
}
-bool RKPluginBrowser::isValid () {
- return (!(fetchStringValue (selection).isEmpty ()));
+void RKPluginBrowser::validateInput () {
+ RK_TRACE (PLUGIN);
+
+ QString tip;
+ QUrl url = QUrl::fromUserInput (selection->value ().toString (), QDir::currentPath (), QUrl::AssumeLocalFile);
+ RK_ASSERT (!url.isRelative ());
+ if (url.isValid ()) {
+ if (url.isLocalFile ()) {
+ GetFileNameWidget::FileType mode = selector->getMode ();
+ QFileInfo fi (url.toLocalFile ());
+ if (mode == GetFileNameWidget::ExistingFile || mode == GetFileNameWidget::ExistingDirectory) {
+ if (!fi.exists ()) {
+ tip = i18n ("The file or directory does not exist.");
+ status = RKComponentBase::Unsatisfied;
+ } else if (mode == GetFileNameWidget::ExistingFile && !fi.isFile ()) {
+ tip = i18n ("Only files (not directories) are acceptable, here.");
+ status = RKComponentBase::Unsatisfied;
+ } else if (mode == GetFileNameWidget::ExistingDirectory && !fi.isDir ()) {
+ tip = i18n ("Only directories (not files) are acceptable, here.");
+ status = RKComponentBase::Unsatisfied;
+ } else {
+ status = RKComponentBase::Satisfied;
+ }
+ } else {
+ RK_ASSERT (mode == GetFileNameWidget::SaveFile);
+ if (!(fi.isWritable () || (!fi.exists () && QFileInfo (fi.dir ().absolutePath ()).isWritable ()))) {
+ tip = i18n ("The specified file is not writable.");
+ status = RKComponentBase::Unsatisfied;
+ } else if (fi.isDir ()) {
+ tip = i18n ("You have to specify a filename (not directory) to write to.");
+ status = RKComponentBase::Unsatisfied;
+ } else if (fi.exists ()) {
+ // TODO: soft warning (icon)
+ tip = i18n ("<b>Note:</b> The given file already exists, and will be modified / overwritten.");
+ status = RKComponentBase::Satisfied;
+ } else {
+ status = RKComponentBase::Satisfied;
+ }
+ }
+ } else {
+ if (only_local) {
+ tip = i18n ("Only local files are allowed, here.");
+ status = RKComponentBase::Unsatisfied;
+ } else {
+ tip = i18n ("This url looks valid.");
+ status = RKComponentBase::Satisfied;
+ }
+ }
+ } else {
+ tip = i18n ("The given filename / url is not valid.");
+ status = RKComponentBase::Unsatisfied;
+ }
+ setToolTip (tip);
+ updateColor ();
+ changed ();
}
void RKPluginBrowser::updateColor () {
RK_TRACE (PLUGIN);
if (isEnabled ()) {
- if (isSatisfied ()) {
+ if (status == RKComponentBase::Satisfied) {
selector->setBackgroundColor (QColor (255, 255, 255));
+ } else if (status == RKComponentBase::Processing) {
+ selector->setBackgroundColor (QColor (255, 255, 0));
} else {
selector->setBackgroundColor (QColor (255, 0, 0));
}
diff --git a/rkward/plugin/rkpluginbrowser.h b/rkward/plugin/rkpluginbrowser.h
index f62611a..af05835 100644
--- a/rkward/plugin/rkpluginbrowser.h
+++ b/rkward/plugin/rkpluginbrowser.h
@@ -22,6 +22,8 @@
#include "rkcomponentproperties.h"
+#include <QTimer>
+
class GetFileNameWidget;
class QDomElement;
@@ -40,17 +42,21 @@ public:
~RKPluginBrowser ();
RKComponentPropertyBase *selection;
- QVariant value (const QString &modifier=QString ()) { return (selection->value (modifier)); };
+ QVariant value (const QString &modifier=QString ()) override { return (selection->value (modifier)); };
QStringList getUiLabelPair () const;
- int type () { return ComponentBrowser; };
- bool isValid ();
+ int type () override { return ComponentBrowser; };
+ ComponentStatus recursiveStatus () override { return status; };
public slots:
void textChangedFromUi ();
void textChanged (RKComponentPropertyBase *);
+ void validateInput ();
private:
void updateColor ();
+ QTimer validation_timer;
+ ComponentStatus status;
GetFileNameWidget *selector;
bool updating;
+ bool only_local;
QString label_string;
};
More information about the rkward-tracker
mailing list