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 }