File indexing completed on 2024-05-05 17:43:13

0001 /*
0002  *   SPDX-FileCopyrightText: 2017 Ivan Cukic <ivan.cukic (at) kde.org>
0003  *
0004  *   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "directorypairchooserwidget.h"
0008 #include "ui_directorypairchooserwidget.h"
0009 
0010 #include "backend_p.h"
0011 #include "vault.h"
0012 
0013 #include <QStandardPaths>
0014 
0015 class DirectoryPairChooserWidget::Private
0016 {
0017 public:
0018     Ui::DirectoryPairChooserWidget ui;
0019     const DirectoryPairChooserWidget::Flags flags;
0020 
0021     DirectoryPairChooserWidget *const q;
0022 
0023     class DirectoryValidator
0024     {
0025     public:
0026         bool requireEmptyDirectory;
0027         bool requireExisting;
0028         bool valid = false;
0029         QString defaultPath;
0030         std::function<void()> update;
0031 
0032         KMessageWidget *widget = nullptr;
0033 
0034         DirectoryValidator(bool requireEmptyDirectory, bool requireExisting, QString defaultPath, std::function<void()> update)
0035             : requireEmptyDirectory(requireEmptyDirectory)
0036             , requireExisting(requireExisting)
0037             , valid(!requireEmptyDirectory && !requireExisting)
0038             , defaultPath(defaultPath)
0039             , update(update)
0040         {
0041         }
0042 
0043         bool isValid(const QUrl &url) const
0044         {
0045             if (url.isEmpty()) {
0046                 widget->hide();
0047                 return false;
0048             }
0049 
0050             if (url.toLocalFile() == defaultPath) {
0051                 widget->hide();
0052                 return true;
0053             }
0054 
0055             QDir dir(url.toLocalFile());
0056 
0057             if (!dir.exists()) {
0058                 widget->setText(i18n("The specified path does not exist"));
0059                 widget->show();
0060                 return false;
0061             }
0062 
0063             if (requireEmptyDirectory && !dir.isEmpty()) {
0064                 widget->setText(i18n("The specified directory is not empty"));
0065                 widget->show();
0066                 return false;
0067             }
0068 
0069             if (requireExisting && dir.isEmpty()) {
0070                 widget->setText(i18n("The specified directory is empty"));
0071                 widget->show();
0072                 return false;
0073             }
0074 
0075             widget->hide();
0076             return true;
0077         }
0078 
0079         void updateFor(const QUrl &url)
0080         {
0081             bool newValid = isValid(url);
0082 
0083             if (valid != newValid) {
0084                 valid = newValid;
0085                 update();
0086             }
0087         }
0088     };
0089 
0090     DirectoryValidator deviceValidator;
0091     DirectoryValidator mountPointValidator;
0092     bool allValid;
0093 
0094     void updateValidity()
0095     {
0096         bool newAllValid = deviceValidator.valid && mountPointValidator.valid;
0097 
0098         if (allValid != newAllValid) {
0099             allValid = newAllValid;
0100             q->setIsValid(allValid);
0101         }
0102     }
0103 
0104     Private(DirectoryPairChooserWidget *parent, DirectoryPairChooserWidget::Flags flags)
0105         : flags(flags)
0106         , q(parent)
0107         , deviceValidator(flags & RequireEmptyDevice,
0108                           flags & RequireExistingDevice,
0109                           nullptr,
0110                           [&] {
0111                               updateValidity();
0112                           })
0113         , mountPointValidator(flags & RequireEmptyMountPoint,
0114                               flags & RequireExistingMountPoint,
0115                               nullptr,
0116                               [&] {
0117                                   updateValidity();
0118                               })
0119         , allValid(deviceValidator.valid && mountPointValidator.valid)
0120     {
0121     }
0122 };
0123 
0124 DirectoryPairChooserWidget::DirectoryPairChooserWidget(DirectoryPairChooserWidget::Flags flags)
0125     : DialogDsl::DialogModule(false)
0126     , d(new Private(this, flags))
0127 {
0128     d->ui.setupUi(this);
0129 
0130     d->deviceValidator.widget = d->ui.messageDevice;
0131     d->mountPointValidator.widget = d->ui.messageMountPoint;
0132 
0133     if (!(flags & DirectoryPairChooserWidget::ShowDevicePicker)) {
0134         d->ui.editDevice->setVisible(false);
0135         d->ui.labelDevice->setVisible(false);
0136     }
0137 
0138     if (!(flags & DirectoryPairChooserWidget::ShowMountPointPicker)) {
0139         d->ui.editMountPoint->setVisible(false);
0140         d->ui.labelMountPoint->setVisible(false);
0141     }
0142 
0143     d->ui.messageDevice->hide();
0144     d->ui.messageMountPoint->hide();
0145 
0146     connect(d->ui.editDevice, &KUrlRequester::textEdited, this, [&]() {
0147         d->deviceValidator.updateFor(d->ui.editDevice->url());
0148     });
0149 
0150     connect(d->ui.editMountPoint, &KUrlRequester::textEdited, this, [&]() {
0151         d->mountPointValidator.updateFor(d->ui.editMountPoint->url());
0152     });
0153 }
0154 
0155 DirectoryPairChooserWidget::~DirectoryPairChooserWidget()
0156 {
0157 }
0158 
0159 PlasmaVault::Vault::Payload DirectoryPairChooserWidget::fields() const
0160 {
0161     return {
0162         {KEY_DEVICE, d->ui.editDevice->url().toLocalFile()},
0163         {KEY_MOUNT_POINT, d->ui.editMountPoint->url().toLocalFile()},
0164     };
0165 }
0166 
0167 void DirectoryPairChooserWidget::init(const PlasmaVault::Vault::Payload &payload)
0168 {
0169     if (d->flags & DirectoryPairChooserWidget::AutoFillPaths) {
0170         const QString basePath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/plasma-vault");
0171 
0172         const auto name = payload[KEY_NAME].toString();
0173 
0174         Q_ASSERT(!name.isEmpty());
0175 
0176         QString path = QString("%1/%2.enc").arg(basePath).arg(name);
0177         int index = 1;
0178         while (QDir(path).exists()) {
0179             path = QString("%1/%2_%3.enc").arg(basePath).arg(name).arg(index++);
0180         }
0181 
0182         d->ui.editDevice->setText(path);
0183         d->ui.editMountPoint->setText(QDir::homePath() + QStringLiteral("/Vaults/") + name);
0184 
0185         d->deviceValidator.defaultPath = path;
0186         d->mountPointValidator.defaultPath = QDir::homePath() + QStringLiteral("/Vaults/") + name;
0187     }
0188 
0189     d->deviceValidator.updateFor(d->ui.editDevice->url());
0190     d->mountPointValidator.updateFor(d->ui.editMountPoint->url());
0191     setIsValid(d->allValid);
0192 }