Commit b8411a5c authored by Ivan Čukić's avatar Ivan Čukić 👁

Better design for the directory chooser

Refactor of the DPCW flags -- what choices should be shown, does
it require new or existing directories.
parent 108d408d
......@@ -58,17 +58,6 @@ Backend::Ptr Backend::instance(const QString &backend)
bool Backend::isDirectoryEmpty(const QString &path)
{
QDir dir(path);
if (!dir.exists()) return true;
return dir.entryInfoList(QDir::NoDotAndDotDot|QDir::AllEntries).count() == 0;
}
QString Backend::formatMessageLine(
const QString &command,
const QPair<bool, QString> &result) const
......
......@@ -24,6 +24,7 @@
#include <QList>
#include <QString>
#include <QStringList>
#include <QDir>
#include <memory>
......@@ -70,8 +71,13 @@ public:
const QString &command,
const QPair<bool, QString> &result) const;
protected:
static bool isDirectoryEmpty(const QString &path);
static inline bool directoryExists(const QString &path)
{
QDir dir(path);
return !dir.exists() ? false
: !dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot).isEmpty();
}
};
......
......@@ -123,7 +123,7 @@ FutureResult<> FuseBackend::initialize(const QString &name,
errorResult(Error::BackendError,
i18n("This directory already contains encrypted data")) :
!isDirectoryEmpty(device) || !isDirectoryEmpty(mountPoint) ?
directoryExists(device) || directoryExists(mountPoint) ?
errorResult(Error::BackendError,
i18n("You need to select empty directories for the encrypted storage and for the mount point")) :
......
......@@ -32,7 +32,7 @@ static std::shared_ptr<BackendType> instance()
static std::mutex s_instanceMutex;
static std::weak_ptr<BackendType> s_instance;
std::unique_lock<std::mutex> locker;
std::unique_lock<std::mutex> locker(s_instanceMutex);
auto ptr = s_instance.lock();
......
......@@ -460,7 +460,7 @@ FutureResult<> Vault::forceClose()
| onError([this] {
d->updateMessage(i18n("Failed to fetch the list of applications using this vault"));
})
| onSuccess([this] (const QString &result) {
| onSuccess([] (const QString &result) {
// based on ksolidnotify.cpp
QStringList blockApps;
......
......@@ -22,6 +22,7 @@
#include "ui_directorypairchooserwidget.h"
#include "vault.h"
#include "backend_p.h"
#include <QStandardPaths>
......@@ -30,54 +31,83 @@ public:
Ui::DirectoryPairChooserWidget ui;
const DirectoryPairChooserWidget::Flags flags;
bool mountPointValid = false;
bool encryptedLocationValid = false;
DirectoryPairChooserWidget *const q;
Private(DirectoryPairChooserWidget *parent, DirectoryPairChooserWidget::Flags flags)
: flags(flags), q(parent)
{
if (flags & DirectoryPairChooserWidget::SkipDevicePicker)
encryptedLocationValid = true;
}
void setEncryptedLocationValid(bool valid)
{
if (encryptedLocationValid == valid) return;
class DirectoryValidator {
public:
bool requireNew;
bool requireExisting;
bool valid = false;
std::function<void()> update;
DirectoryValidator(bool requireNew, bool requireExisting,
std::function<void()> update)
: requireNew(requireNew)
, requireExisting(requireExisting)
, valid(!requireNew && !requireExisting)
, update(update)
{
}
encryptedLocationValid = valid;
bool isValid(const QUrl &url) const
{
if (url.isEmpty()) return false;
// We only change the global valid state if
// the mount point was already valid
if (mountPointValid) {
q->setIsValid(valid);
}
}
const bool directoryExists
= PlasmaVault::Backend::directoryExists(url.toLocalFile());
void setMountPointValid(bool valid)
{
if (mountPointValid == valid) return;
if (requireNew && directoryExists) {
return false;
}
mountPointValid = valid;
if (requireExisting && !directoryExists) {
return false;
}
// We only change the global valid state if
// the enc location was already valid
if (encryptedLocationValid) {
q->setIsValid(valid);
return true;
}
}
bool isDirectoryValid(const QUrl &url) const
{
if (url.isEmpty()) return false;
// TODO check the vaults database to see if another vault already uses this dir
void updateFor(const QUrl &url)
{
bool newValid = isValid(url);
if (valid != newValid) {
valid = newValid;
update();
}
}
};
DirectoryValidator deviceValidator;
DirectoryValidator mountPointValidator;
bool allValid;
QDir directory(url.toString());
void updateValidity()
{
bool newAllValid = deviceValidator.valid && mountPointValidator.valid;
// TODO: Support alternative flags once they are needed
if (!directory.exists() || directory.entryList().isEmpty()) return true;
if (allValid != newAllValid) {
allValid = newAllValid;
q->setIsValid(allValid);
}
}
return false;
Private(DirectoryPairChooserWidget *parent,
DirectoryPairChooserWidget::Flags flags)
: flags(flags)
, q(parent)
, deviceValidator(
flags & RequireNewDevice,
flags & RequireExistingDevice,
[&] { updateValidity(); }
)
, mountPointValidator(
flags & RequireNewMountPoint,
flags & RequireExistingMountPoint,
[&] { updateValidity(); }
)
, allValid(deviceValidator.valid && mountPointValidator.valid)
{
}
};
......@@ -86,19 +116,25 @@ DirectoryPairChooserWidget::DirectoryPairChooserWidget(
: DialogDsl::DialogModule(false), d(new Private(this, flags))
{
d->ui.setupUi(this);
if (flags & DirectoryPairChooserWidget::SkipDevicePicker) {
if (!(flags & DirectoryPairChooserWidget::ShowDevicePicker)) {
d->ui.editDevice->setVisible(false);
d->ui.labelDevice->setVisible(false);
} else {
connect(d->ui.editDevice, &KUrlRequester::textEdited,
this, [&] () {
d->setEncryptedLocationValid(d->isDirectoryValid(d->ui.editDevice->url()));
});
}
if (!(flags & DirectoryPairChooserWidget::ShowMountPointPicker)) {
d->ui.editMountPoint->setVisible(false);
d->ui.labelMountPoint->setVisible(false);
}
connect(d->ui.editDevice, &KUrlRequester::textEdited,
this, [&] () {
d->deviceValidator.updateFor(d->ui.editDevice->url());
});
connect(d->ui.editMountPoint, &KUrlRequester::textEdited,
this, [&] () {
d->setMountPointValid(d->isDirectoryValid(d->ui.editMountPoint->url()));
d->mountPointValidator.updateFor(d->ui.editMountPoint->url());
});
}
......@@ -121,22 +157,26 @@ PlasmaVault::Vault::Payload DirectoryPairChooserWidget::fields() const
void DirectoryPairChooserWidget::init(
const PlasmaVault::Vault::Payload &payload)
{
const QString basePath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
+ QStringLiteral("/plasma-vault");
if (d->flags & DirectoryPairChooserWidget::AutoFillPaths) {
const QString basePath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
+ QStringLiteral("/plasma-vault");
const auto name = payload[KEY_NAME].toString();
const auto name = payload[KEY_NAME].toString();
Q_ASSERT(!name.isEmpty());
Q_ASSERT(!name.isEmpty());
QString path = QString("%1/%2.enc").arg(basePath).arg(name);
int index = 1;
while (QDir(path).exists()) {
path = QString("%1/%2_%3.enc").arg(basePath).arg(name).arg(index++);
}
QString path = QString("%1/%2.enc").arg(basePath).arg(name);
int index = 1;
while (QDir(path).exists()) {
path = QString("%1/%2_%3.enc").arg(basePath).arg(name).arg(index++);
}
d->ui.editDevice->setText(path);
d->ui.editMountPoint->setText(QDir::homePath() + QStringLiteral("/Vaults/") + name);
d->ui.editDevice->setText(path);
d->ui.editMountPoint->setText(QDir::homePath() + QStringLiteral("/Vaults/") + name);
}
d->setEncryptedLocationValid(d->isDirectoryValid(d->ui.editDevice->url()));
d->setMountPointValid(d->isDirectoryValid(d->ui.editMountPoint->url()));
d->deviceValidator.updateFor(d->ui.editDevice->url());
d->mountPointValidator.updateFor(d->ui.editMountPoint->url());
setIsValid(d->allValid);
}
......@@ -28,10 +28,17 @@ class DirectoryPairChooserWidget: public DialogDsl::DialogModule {
Q_OBJECT
public:
enum Flags {
NoFlags = 0,
SkipDevicePicker = 1
enum Flag {
ShowDevicePicker = 1,
ShowMountPointPicker = 2,
RequireNewDevice = 4,
RequireExistingDevice = 8,
RequireNewMountPoint = 16,
RequireExistingMountPoint = 32,
AutoFillPaths = 64
};
Q_DECLARE_FLAGS(Flags, Flag)
DirectoryPairChooserWidget(Flags flags);
~DirectoryPairChooserWidget();
......@@ -44,12 +51,14 @@ private:
QScopedPointer<Private> d;
};
inline DialogDsl::ModuleFactory directoryPairChooser(DirectoryPairChooserWidget::Flags flags = DirectoryPairChooserWidget::NoFlags)
inline DialogDsl::ModuleFactory directoryPairChooser(DirectoryPairChooserWidget::Flags flags)
{
return [=] {
return new DirectoryPairChooserWidget(flags);
};
}
Q_DECLARE_OPERATORS_FOR_FLAGS(DirectoryPairChooserWidget::Flags)
#endif // include guard
......@@ -21,7 +21,7 @@
<item row="0" column="1">
<widget class="KUrlRequester" name="editDevice">
<property name="mode">
<set>KFile::Directory|KFile::File|KFile::LocalOnly</set>
<set>KFile::Directory|KFile::LocalOnly</set>
</property>
</widget>
</item>
......@@ -35,7 +35,7 @@
<item row="1" column="1">
<widget class="KUrlRequester" name="editMountPoint">
<property name="mode">
<set>KFile::Directory|KFile::File</set>
<set>KFile::Directory|KFile::LocalOnly</set>
</property>
</widget>
</item>
......
......@@ -81,7 +81,11 @@ public:
See <a href='http://defuse.ca/audits/encfs.htm'>defuse.ca/audits/encfs.htm</a> for more information."))
},
step { passwordChooser() },
step { directoryPairChooser(DirectoryPairChooserWidget::SkipDevicePicker) },
step { directoryPairChooser(
DirectoryPairChooserWidget::AutoFillPaths |
DirectoryPairChooserWidget::ShowMountPointPicker |
DirectoryPairChooserWidget::RequireNewMountPoint
) },
step {
activitiesChooser(),
offlineOnlyChooser()
......@@ -107,7 +111,13 @@ public:
which confirms this."))
},
step { passwordChooser() },
step { directoryPairChooser() },
step { directoryPairChooser(
DirectoryPairChooserWidget::AutoFillPaths |
DirectoryPairChooserWidget::ShowDevicePicker |
DirectoryPairChooserWidget::ShowMountPointPicker |
DirectoryPairChooserWidget::RequireNewDevice |
DirectoryPairChooserWidget::RequireNewMountPoint
) },
step {
cryfsCypherChooser(),
activitiesChooser(),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment