File indexing completed on 2024-04-28 05:46:32
0001 /* 0002 SPDX-FileCopyrightText: 2010 Volker Lanz <vl@fidra.de> 0003 SPDX-FileCopyrightText: 2014-2020 Andrius Štikonas <andrius@stikonas.eu> 0004 SPDX-FileCopyrightText: 2018 Abhijeet Sharma <sharma.abhijeet2096@gmail.com> 0005 0006 SPDX-License-Identifier: GPL-3.0-or-later 0007 */ 0008 0009 #include "gui/editmountpointdialogwidget.h" 0010 #include "gui/editmountoptionsdialog.h" 0011 0012 #include <core/partition.h> 0013 0014 #include <fs/filesystem.h> 0015 #include <fs/luks.h> 0016 0017 #include <KLocalizedString> 0018 #include <KMessageBox> 0019 0020 #include <QDebug> 0021 #include <QFile> 0022 #include <QFileDialog> 0023 #include <QPointer> 0024 #include <QString> 0025 0026 EditMountPointDialogWidget::EditMountPointDialogWidget(QWidget* parent, Partition& p) : 0027 QWidget(parent), 0028 m_Partition(p) 0029 { 0030 m_fstabEntries = readFstabEntries(); 0031 0032 setupUi(this); 0033 0034 m_deviceNode = partition().deviceNode(); 0035 if (partition().roles().has(PartitionRole::Luks) && partition().fileSystem().type() != FileSystem::Type::Luks) { 0036 const FS::luks* luksFs = dynamic_cast<const FS::luks*>(&partition().fileSystem()); 0037 m_deviceNode = luksFs->mapperName(); 0038 } 0039 labelName().setText(m_deviceNode); 0040 labelType().setText(partition().fileSystem().name()); 0041 0042 bool entryFound = false; 0043 editPath().setEditable(true); 0044 for (auto &e : m_fstabEntries) { 0045 QString canonicalEntryPath = QFileInfo(e.deviceNode()).canonicalFilePath(); 0046 QString canonicalDevicePath = QFileInfo(m_deviceNode).canonicalFilePath(); 0047 if (canonicalEntryPath == canonicalDevicePath) { 0048 entryFound = true; 0049 entry.push_back(&e); 0050 mountPointList = possibleMountPoints(e.deviceNode()); 0051 } 0052 } 0053 0054 if (!entryFound) { 0055 FileSystem::Type type = partition().fileSystem().type(); 0056 QString fsName; 0057 switch (type) { 0058 case FileSystem::Type::LinuxSwap: 0059 fsName = QStringLiteral("swap"); 0060 break; 0061 case FileSystem::Type::Fat16: 0062 case FileSystem::Type::Fat32: 0063 fsName = QStringLiteral("vfat"); 0064 break; 0065 default: 0066 fsName = partition().fileSystem().name({QStringLiteral("C")}); 0067 } 0068 0069 m_fstabEntries.push_back(FstabEntry(m_deviceNode, QString(), fsName, QString())); 0070 entry.push_back(&m_fstabEntries.back()); 0071 } 0072 currentEntry = entry[0]; 0073 editPath().addItems(mountPointList); 0074 spinDumpFreq().setValue(currentEntry->dumpFreq()); 0075 spinPassNumber().setValue(currentEntry->passNumber()); 0076 0077 boxOptions()[QStringLiteral("ro")] = m_CheckReadOnly; 0078 boxOptions()[QStringLiteral("users")] = m_CheckUsers; 0079 boxOptions()[QStringLiteral("noauto")] = m_CheckNoAuto; 0080 boxOptions()[QStringLiteral("noatime")] = m_CheckNoAtime; 0081 boxOptions()[QStringLiteral("nodiratime")] = m_CheckNoDirAtime; 0082 boxOptions()[QStringLiteral("sync")] = m_CheckSync; 0083 boxOptions()[QStringLiteral("noexec")] = m_CheckNoExec; 0084 boxOptions()[QStringLiteral("relatime")] = m_CheckRelAtime; 0085 0086 setupRadio(currentEntry->entryType()); 0087 setupOptions(currentEntry->options()); 0088 0089 connect(m_ButtonMore, &QPushButton::clicked, this, &EditMountPointDialogWidget::buttonMoreClicked); 0090 connect(m_ButtonSelect, &QPushButton::clicked, this, &EditMountPointDialogWidget::buttonSelectClicked); 0091 connect(m_EditPath, QOverload<int>::of(&QComboBox::currentIndexChanged), 0092 [=](int index){ currentEntry = entry[index]; 0093 spinDumpFreq().setValue(currentEntry->dumpFreq()); 0094 spinPassNumber().setValue(currentEntry->passNumber()); 0095 setupRadio(currentEntry->entryType()); 0096 for (iterator_BoxOptions = boxOptions().begin(); iterator_BoxOptions != boxOptions().end(); ++iterator_BoxOptions){ 0097 boxOptions()[iterator_BoxOptions->first]->setChecked(false); 0098 } 0099 setupOptions(currentEntry->options()); 0100 }); 0101 connect(m_EditPath, &QComboBox::currentTextChanged, this, &EditMountPointDialogWidget::currentPathChanged); 0102 currentPathChanged(m_EditPath->currentText()); 0103 } 0104 0105 EditMountPointDialogWidget::~EditMountPointDialogWidget() 0106 { 0107 } 0108 0109 bool EditMountPointDialogWidget::isValid() const 0110 { 0111 return m_valid; 0112 } 0113 0114 void EditMountPointDialogWidget::setupOptions(const QStringList& options) 0115 { 0116 QStringList optTmpList; 0117 for (const auto &o : options) { 0118 if (boxOptions().find(o) != boxOptions().end()) 0119 boxOptions()[o]->setChecked(true); 0120 else 0121 optTmpList.append(o); 0122 } 0123 0124 m_Options = optTmpList.join(QLatin1Char(',')); 0125 } 0126 0127 void EditMountPointDialogWidget::setupRadio(const FstabEntry::Type entryType) 0128 { 0129 if (partition().fileSystem().uuid().isEmpty()) { 0130 radioUUID().setEnabled(false); 0131 if (radioUUID().isChecked()) 0132 radioDeviceNode().setChecked(true); 0133 } 0134 0135 if (partition().fileSystem().label().isEmpty()) { 0136 radioLabel().setEnabled(false); 0137 if (radioLabel().isChecked()) 0138 radioDeviceNode().setChecked(true); 0139 } 0140 switch (entryType) { 0141 case FstabEntry::Type::uuid: 0142 radioUUID().setChecked(true); 0143 break; 0144 0145 case FstabEntry::Type::label: 0146 radioLabel().setChecked(true); 0147 break; 0148 0149 case FstabEntry::Type::partuuid: 0150 radioUUID().setChecked(true); 0151 break; 0152 0153 case FstabEntry::Type::partlabel: 0154 radioLabel().setChecked(true); 0155 break; 0156 0157 case FstabEntry::Type::deviceNode: 0158 radioDeviceNode().setChecked(true); 0159 break; 0160 case FstabEntry::Type::comment: 0161 break; 0162 default: 0163 break; 0164 } 0165 } 0166 0167 void EditMountPointDialogWidget::buttonSelectClicked(bool) 0168 { 0169 const QString s = QFileDialog::getExistingDirectory(this, editPath().currentText()); 0170 if (!s.isEmpty()) 0171 editPath().setCurrentText(s); 0172 } 0173 0174 void EditMountPointDialogWidget::removeMountPoint() 0175 { 0176 for (auto it = fstabEntries().begin(); it != fstabEntries().end(); ++it) { 0177 if (editPath().count() <= 1 && ( 0178 (it->fsSpec().contains(partition().deviceNode()) && !partition().deviceNode().isEmpty() ) || 0179 (it->fsSpec().contains(partition().fileSystem().uuid()) && !partition().fileSystem().uuid().isEmpty() ) || 0180 (it->fsSpec().contains(partition().fileSystem().label()) && !partition().fileSystem().label().isEmpty()) || 0181 (it->fsSpec().contains(partition().label()) && !partition().label().isEmpty() ) || 0182 (it->fsSpec().contains(partition().uuid()) && !partition().uuid().isEmpty() ))) 0183 { 0184 fstabEntries().erase(it); 0185 partition().setMountPoint(QString()); 0186 } 0187 else if (editPath().count() > 1 && (&*it == currentEntry)) 0188 { 0189 fstabEntries().erase(it); 0190 editPath().removeItem(editPath().currentIndex()); 0191 partition().setMountPoint(editPath().itemText(editPath().currentIndex())); 0192 break; 0193 } 0194 } 0195 0196 } 0197 0198 void EditMountPointDialogWidget::buttonMoreClicked(bool) 0199 { 0200 QPointer<EditMountOptionsDialog> dlg = new EditMountOptionsDialog(this, m_Options.split(QLatin1Char(','))); 0201 0202 if (dlg->exec() == QDialog::Accepted) 0203 setupOptions(dlg->options()); 0204 0205 delete dlg; 0206 } 0207 0208 QStringList EditMountPointDialogWidget::options() const 0209 { 0210 QStringList optList = m_Options.split(QLatin1Char(','), Qt::SkipEmptyParts); 0211 0212 const auto keys = boxOptions(); 0213 for (const auto &s : keys) 0214 if (s.second->isChecked()) 0215 optList.append(s.first); 0216 0217 return optList; 0218 } 0219 0220 void EditMountPointDialogWidget::acceptChanges() 0221 { 0222 currentEntry->setDumpFreq(spinDumpFreq().value()); 0223 currentEntry->setPassNumber(spinPassNumber().value()); 0224 currentEntry->setMountPoint(editPath().currentText()); 0225 currentEntry->setOptions(options()); 0226 0227 if (radioUUID().isChecked() && !partition().fileSystem().uuid().isEmpty()) 0228 currentEntry->setFsSpec(QStringLiteral("UUID=") + partition().fileSystem().uuid()); 0229 else if (radioLabel().isChecked() && !partition().fileSystem().label().isEmpty()) 0230 currentEntry->setFsSpec(QStringLiteral("LABEL=") + partition().fileSystem().label()); 0231 else 0232 currentEntry->setFsSpec(m_deviceNode); 0233 } 0234 0235 void EditMountPointDialogWidget::currentPathChanged(const QString &newPath) 0236 { 0237 auto path = newPath.trimmed().toLower(); 0238 if (path.isEmpty() || path == QStringLiteral("none")) { 0239 m_valid = false; 0240 m_PathMessage->setVisible(true); 0241 } else { 0242 m_valid = true; 0243 m_PathMessage->setVisible(false); 0244 } 0245 Q_EMIT isValidChanged(m_valid); 0246 }