Compare commits
33 Commits
master
...
raid-suppo
Author | SHA1 | Date |
---|---|---|
Andrius Štikonas | 8d2ebfeaed | |
Andrius Štikonas | b5e6e1e544 | |
Caio Carvalho | 0dcf87d1c4 | |
Andrius Štikonas | 6b9dfa2d1e | |
Caio Carvalho | c8da38aef5 | |
Caio Carvalho | bbe392b5d2 | |
Caio Carvalho | e8cb85a15f | |
Caio Carvalho | 5727717776 | |
Caio Carvalho | 495b2d5b42 | |
Caio Carvalho | a680ad0be2 | |
Caio Carvalho | 14b286ede7 | |
Caio Carvalho | bdc0a24508 | |
Caio Carvalho | 702a34d6a4 | |
Caio Carvalho | 45217f4b7e | |
Caio Carvalho | 170a0fadde | |
Caio Carvalho | 3c79839152 | |
Caio Carvalho | 8eb4393ded | |
Caio Carvalho | 7b1ca5fe72 | |
Andrius Štikonas | 863e7cafaa | |
Caio Carvalho | 94d1c1d9c6 | |
Caio Carvalho | 57a2072686 | |
Caio Carvalho | c8cdebf5fb | |
Caio Carvalho | fa0b7b838c | |
Caio Carvalho | 4312ce3e7f | |
Caio Carvalho | 04db81aaba | |
Caio Carvalho | 39d0477ca0 | |
Caio Carvalho | a8ae8d5419 | |
Caio Carvalho | eec9801582 | |
Caio Carvalho | f81f6fbff2 | |
Caio Carvalho | 4365a0e9d2 | |
Caio Carvalho | a7680ae169 | |
Caio Carvalho | 50af43636d | |
Caio Carvalho | a87f042468 |
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2010 Volker Lanz <vl@fidra.de>
|
||||
SPDX-FileCopyrightText: 2014-2017 Andrius Štikonas <andrius@stikonas.eu>
|
||||
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
@ -11,16 +12,20 @@
|
|||
#include <util/helpers.h>
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include <KPluginMetaData>
|
||||
|
||||
#include <config.h>
|
||||
#include <kpmcore/core/softwareraid.h>
|
||||
|
||||
AdvancedPageWidget::AdvancedPageWidget(QWidget* parent) :
|
||||
QWidget(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
setupDialog();
|
||||
|
||||
connect(selectRaidFileButton, &QPushButton::clicked, this, &AdvancedPageWidget::searchForRaidConfigFile);
|
||||
}
|
||||
|
||||
QString AdvancedPageWidget::backend() const
|
||||
|
@ -48,4 +53,36 @@ void AdvancedPageWidget::setupDialog()
|
|||
comboBackend().addItem(backend.name());
|
||||
|
||||
setBackend(Config::backend());
|
||||
setRaidConfigurationFile(Config::raidConfigurationFilePath());
|
||||
}
|
||||
|
||||
QString AdvancedPageWidget::raidConfigurationFile() const
|
||||
{
|
||||
return raidConfigFilePath->text().trimmed();
|
||||
}
|
||||
|
||||
void AdvancedPageWidget::setRaidConfigurationFile(const QString &file)
|
||||
{
|
||||
raidConfigFilePath->clear();
|
||||
raidConfigFilePath->insert(file);
|
||||
}
|
||||
|
||||
void AdvancedPageWidget::searchForRaidConfigFile()
|
||||
{
|
||||
QPointer<QFileDialog> dialog = new QFileDialog(this, QStringLiteral("Select Software RAID configuration file"),
|
||||
QStringLiteral("/"));
|
||||
|
||||
dialog->setFileMode(QFileDialog::FileMode::ExistingFile);
|
||||
dialog->setNameFilter(QStringLiteral("Configuration files (*.conf)"));
|
||||
|
||||
auto updateConfig = [this](const QString& file){
|
||||
if (!file.isEmpty()) {
|
||||
raidConfigFilePath->clear();
|
||||
raidConfigFilePath->insert(file);
|
||||
}
|
||||
};
|
||||
|
||||
connect(dialog, &QFileDialog::fileSelected, updateConfig);
|
||||
|
||||
dialog->exec();
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2010 Volker Lanz <vl@fidra.de>
|
||||
SPDX-FileCopyrightText: 2014-2017 Andrius Štikonas <andrius@stikonas.eu>
|
||||
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#if !defined(ADVANCEDPAGEWIDGET_H)
|
||||
|
||||
#ifndef ADVANCEDPAGEWIDGET_H
|
||||
#define ADVANCEDPAGEWIDGET_H
|
||||
|
||||
#include "ui_configurepageadvanced.h"
|
||||
|
@ -30,10 +30,19 @@ public:
|
|||
const QComboBox& comboBackend() const {
|
||||
return *m_ComboBackend;
|
||||
}
|
||||
const QLineEdit& raidConfigurationLine() const {
|
||||
return *raidConfigFilePath;
|
||||
}
|
||||
|
||||
QString backend() const;
|
||||
void setBackend(const QString& name);
|
||||
|
||||
QString raidConfigurationFile() const;
|
||||
void setRaidConfigurationFile(const QString& file);
|
||||
|
||||
protected Q_SLOTS:
|
||||
void searchForRaidConfigFile();
|
||||
|
||||
private:
|
||||
void setupDialog();
|
||||
};
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <QIcon>
|
||||
|
||||
#include <config.h>
|
||||
#include <kpmcore/core/softwareraid.h>
|
||||
|
||||
ConfigureOptionsDialog::ConfigureOptionsDialog(QWidget* parent, const OperationStack& ostack, const QString& name) :
|
||||
KConfigDialog(parent, name, Config::self()),
|
||||
|
@ -49,6 +50,7 @@ ConfigureOptionsDialog::ConfigureOptionsDialog(QWidget* parent, const OperationS
|
|||
addPage(&advancedPageWidget(), xi18nc("@title:tab advanced application settings", "Advanced"), QStringLiteral("preferences-other"), i18n("Advanced Settings"));
|
||||
|
||||
connect(&advancedPageWidget().comboBackend(), qOverload<int>(&QComboBox::activated), this, &ConfigureOptionsDialog::onComboDefaultFileSystemActivated);
|
||||
connect(&advancedPageWidget().raidConfigurationLine(), &QLineEdit::textChanged, this, &ConfigureOptionsDialog::onRaidConfigFilePathActivated);
|
||||
|
||||
KConfigGroup kcg(KSharedConfig::openConfig(), "configureOptionsDialogs");
|
||||
restoreGeometry(kcg.readEntry<QByteArray>("Geometry", QByteArray()));
|
||||
|
@ -83,6 +85,11 @@ void ConfigureOptionsDialog::updateSettings()
|
|||
changed = true;
|
||||
}
|
||||
|
||||
if (advancedPageWidget().raidConfigurationFile() != Config::raidConfigurationFilePath()) {
|
||||
Config::setRaidConfigurationFilePath(advancedPageWidget().raidConfigurationFile());
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
Q_EMIT KConfigDialog::settingsChanged(i18n("General Settings"));
|
||||
}
|
||||
|
@ -98,6 +105,9 @@ bool ConfigureOptionsDialog::hasChanged()
|
|||
if (advancedPageWidget().isVisible()) {
|
||||
kcItem = Config::self()->findItem(QStringLiteral("backend"));
|
||||
result = result || !kcItem->isEqual(advancedPageWidget().backend());
|
||||
|
||||
kcItem = Config::self()->findItem(QStringLiteral("raidConfigurationFilePath"));
|
||||
result = result || !kcItem->isEqual(advancedPageWidget().raidConfigurationFile());
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -122,8 +132,10 @@ void ConfigureOptionsDialog::updateWidgetsDefault()
|
|||
generalPageWidget().setDefaultFileSystem(GuiHelpers::defaultFileSystem());
|
||||
generalPageWidget().radioButton->setChecked(true);
|
||||
|
||||
if (advancedPageWidget().isVisible())
|
||||
if (advancedPageWidget().isVisible()) {
|
||||
advancedPageWidget().setBackend(CoreBackendManager::defaultBackendName());
|
||||
advancedPageWidget().setRaidConfigurationFile(SoftwareRAID::getDefaultRaidConfigFile());
|
||||
}
|
||||
|
||||
Config::self()->useDefaults(useDefaults);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,9 @@ protected:
|
|||
void onShredSourceActivated() {
|
||||
settingsChangedSlot();
|
||||
}
|
||||
void onRaidConfigFilePathActivated() {
|
||||
settingsChangedSlot();
|
||||
}
|
||||
void onComboBackendActivated(int);
|
||||
|
||||
GeneralPageWidget& generalPageWidget() {
|
||||
|
|
|
@ -12,12 +12,18 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>449</width>
|
||||
<width>511</width>
|
||||
<height>420</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>420</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
|
@ -32,7 +38,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Active backend:</string>
|
||||
<string>Acti&ve backend:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_ComboBackend</cstring>
|
||||
|
@ -45,7 +51,47 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Software RAID configuration</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Configuration file:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>raidConfigFilePath</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="raidConfigFilePath">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="selectRaidFileButton">
|
||||
<property name="text">
|
||||
<string>Select File</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_6">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
|
@ -56,11 +102,11 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<property name="title">
|
||||
<string>Units</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Preferred unit:</string>
|
||||
<string>Preferred &unit:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_ComboBackend</cstring>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <core/device.h>
|
||||
#include <core/lvmdevice.h>
|
||||
#include <core/partitiontable.h>
|
||||
#include <core/softwareraid.h>
|
||||
|
||||
#include <fs/lvm2_pv.h>
|
||||
|
||||
|
@ -29,9 +30,14 @@
|
|||
#include <KLocalizedString>
|
||||
#include <KSharedConfig>
|
||||
|
||||
CreateVolumeGroupDialog::CreateVolumeGroupDialog(QWidget* parent, QString& vgName, QVector<const Partition*>& partList, qint32& peSize, QList<Device*> devices, QList<Operation*> pendingOps)
|
||||
CreateVolumeGroupDialog::CreateVolumeGroupDialog(QWidget* parent, QString& vgName, QVector<const Partition*>& partList,
|
||||
QString& type, qint32& raidLevel, qint32& chunkSize, qint32& peSize,
|
||||
QList<Device*> devices, QList<Operation*> pendingOps)
|
||||
: VolumeGroupDialog(parent, vgName, partList)
|
||||
, m_type(type)
|
||||
, m_PESize(peSize)
|
||||
, m_raidLevel(raidLevel)
|
||||
, m_chunkSize(chunkSize)
|
||||
, m_Devices(devices)
|
||||
, m_PendingOps(pendingOps)
|
||||
{
|
||||
|
@ -41,15 +47,26 @@ CreateVolumeGroupDialog::CreateVolumeGroupDialog(QWidget* parent, QString& vgNam
|
|||
setupConstraints();
|
||||
setupConnections();
|
||||
|
||||
// disable volume type and PE size for now, until the features are implemented.
|
||||
dialogWidget().volumeType().setEnabled(false);
|
||||
|
||||
KConfigGroup kcg(KSharedConfig::openConfig(), "createVolumeDialog");
|
||||
restoreGeometry(kcg.readEntry<QByteArray>("Geometry", QByteArray()));
|
||||
}
|
||||
|
||||
void CreateVolumeGroupDialog::setupDialog()
|
||||
{
|
||||
updatePartitionList();
|
||||
}
|
||||
|
||||
void CreateVolumeGroupDialog::setupConnections()
|
||||
{
|
||||
connect(&dialogWidget().vgName(), &QLineEdit::textChanged, this, &CreateVolumeGroupDialog::onVGNameChanged);
|
||||
connect(&dialogWidget().spinPESize(), qOverload<int>(&QSpinBox::valueChanged), this, &CreateVolumeGroupDialog::onSpinPESizeChanged);
|
||||
}
|
||||
|
||||
void CreateVolumeGroupDialog::updatePartitionList()
|
||||
{
|
||||
if (dialogWidget().volumeType().currentText() == QStringLiteral("LVM")) {
|
||||
dialogWidget().listPV().clear();
|
||||
|
||||
for (const auto &p : std::as_const(LVM::pvList::list())) {
|
||||
bool toBeDeleted = false;
|
||||
|
||||
|
@ -64,13 +81,13 @@ void CreateVolumeGroupDialog::setupDialog()
|
|||
if (toBeDeleted)
|
||||
continue;
|
||||
|
||||
if (!p.isLuks() && p.vgName().isEmpty() && !LvmDevice::s_DirtyPVs.contains(p.partition()))
|
||||
if (!p.isLuks() && p.vgName() == QString() && !LvmDevice::s_DirtyPVs.contains(p.partition()))
|
||||
dialogWidget().listPV().addPartition(*p.partition(), false);
|
||||
}
|
||||
|
||||
for (const Device *d : std::as_const(m_Devices)) {
|
||||
for (const Device *d : qAsConst(m_Devices)) {
|
||||
if (d->partitionTable() != nullptr) {
|
||||
for (const Partition *p : std::as_const(d->partitionTable()->children())) {
|
||||
for (const Partition *p : qAsConst(d->partitionTable()->children())) {
|
||||
// Looking if there is another VG creation that contains this partition
|
||||
if (LvmDevice::s_DirtyPVs.contains(p))
|
||||
continue;
|
||||
|
@ -93,12 +110,21 @@ void CreateVolumeGroupDialog::setupDialog()
|
|||
for (const Partition *p : std::as_const(LvmDevice::s_OrphanPVs))
|
||||
if (!LvmDevice::s_DirtyPVs.contains(p))
|
||||
dialogWidget().listPV().addPartition(*p, false);
|
||||
}
|
||||
|
||||
void CreateVolumeGroupDialog::setupConnections()
|
||||
{
|
||||
connect(&dialogWidget().vgName(), &QLineEdit::textChanged, this, &CreateVolumeGroupDialog::onVGNameChanged);
|
||||
connect(&dialogWidget().spinPESize(), qOverload<int>(&QSpinBox::valueChanged), this, &CreateVolumeGroupDialog::onSpinPESizeChanged);
|
||||
}
|
||||
else if (dialogWidget().volumeType().currentText() == QStringLiteral("RAID")) {
|
||||
for (const Device *d : std::as_const(m_Devices)) {
|
||||
if (d->type() != Device::Type::SoftwareRAID_Device && d->partitionTable() != nullptr) {
|
||||
for (const Partition *p : std::as_const(d->partitionTable()->children())) {
|
||||
if (((p->fileSystem().type() == FileSystem::Type::LinuxRaidMember &&
|
||||
SoftwareRAID::getRaidArrayName(p->partitionPath()).isEmpty()) ||
|
||||
p->fileSystem().type() == FileSystem::Type::Unformatted ||
|
||||
p->fileSystem().type() == FileSystem::Type::Unknown) &&
|
||||
!p->roles().has(PartitionRole::Role::Unallocated))
|
||||
dialogWidget().listPV().addPartition(*p, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreateVolumeGroupDialog::accept()
|
||||
|
@ -108,9 +134,18 @@ void CreateVolumeGroupDialog::accept()
|
|||
|
||||
targetPVList().append(dialogWidget().listPV().checkedItems());
|
||||
|
||||
QString& vgType = type();
|
||||
vgType = dialogWidget().volumeType().currentText();
|
||||
|
||||
qint32& pesize = peSize();
|
||||
pesize = dialogWidget().spinPESize().value();
|
||||
|
||||
qint32& raidlvl = raidLevel();
|
||||
raidlvl = dialogWidget().raidLevel().currentText().toInt();
|
||||
|
||||
qint32& chunk = chunkSize();
|
||||
chunk = dialogWidget().chunkSize().value();
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
|
@ -118,14 +153,27 @@ void CreateVolumeGroupDialog::updateOkButtonStatus()
|
|||
{
|
||||
VolumeGroupDialog::updateOkButtonStatus();
|
||||
|
||||
if (okButton->isEnabled())
|
||||
if (okButton->isEnabled()) {
|
||||
okButton->setEnabled(!dialogWidget().listPV().checkedItems().empty());
|
||||
|
||||
if (dialogWidget().volumeType().currentText() == QStringLiteral("RAID")) {
|
||||
bool ok = dialogWidget().listPV().checkedItems().count() >= 2 &&
|
||||
dialogWidget().vgName().text().length() > 2;
|
||||
|
||||
QString name = dialogWidget().vgName().text();
|
||||
|
||||
if (ok)
|
||||
ok = dialogWidget().vgName().text().startsWith(
|
||||
name.back().isDigit() ? QStringLiteral("md") : QStringLiteral("md/"));
|
||||
|
||||
okButton->setEnabled(ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreateVolumeGroupDialog::onVGNameChanged(const QString& vgName)
|
||||
{
|
||||
for (const auto &d : m_Devices) {
|
||||
if (dynamic_cast<LvmDevice*>(d)) {
|
||||
if (d->name() == vgName) {
|
||||
m_IsValidName = false;
|
||||
break;
|
||||
|
@ -133,7 +181,6 @@ void CreateVolumeGroupDialog::onVGNameChanged(const QString& vgName)
|
|||
else
|
||||
m_IsValidName = true;
|
||||
}
|
||||
}
|
||||
updateOkButtonStatus();
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CREATEVOLUMEGROUPDIALOG_H
|
||||
#define CREATEVOLUMEGROUPDIALOG_H
|
||||
|
||||
|
@ -23,23 +22,42 @@ class CreateVolumeGroupDialog : public VolumeGroupDialog
|
|||
Q_DISABLE_COPY(CreateVolumeGroupDialog)
|
||||
|
||||
public:
|
||||
CreateVolumeGroupDialog(QWidget* parent, QString& vgName, QVector<const Partition*>& pvList, qint32& peSize, QList<Device*> devices, QList<Operation*> pendingOps = QList<Operation *>());
|
||||
CreateVolumeGroupDialog(QWidget* parent, QString& vgName, QVector<const Partition*>& pvList, QString& type,
|
||||
qint32& raidLevel, qint32& chunkSize, qint32& peSize, QList<Device*> devices,
|
||||
QList<Operation*> pendingOps = QList<Operation *>());
|
||||
|
||||
protected:
|
||||
void accept() override;
|
||||
void setupDialog() override;
|
||||
void setupConnections() override;
|
||||
void updatePartitionList() override;
|
||||
|
||||
protected:
|
||||
virtual void updateOkButtonStatus() override;
|
||||
void onVGNameChanged(const QString& vgname);
|
||||
void onSpinPESizeChanged(int newsize);
|
||||
|
||||
qint32& peSize() {
|
||||
QString& type() const {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
qint32& peSize() const {
|
||||
return m_PESize;
|
||||
}
|
||||
|
||||
qint32& raidLevel() const {
|
||||
return m_raidLevel;
|
||||
}
|
||||
|
||||
qint32& chunkSize() const {
|
||||
return m_chunkSize;
|
||||
}
|
||||
|
||||
QString& m_type;
|
||||
|
||||
qint32& m_PESize;
|
||||
qint32& m_raidLevel;
|
||||
qint32& m_chunkSize;
|
||||
|
||||
private:
|
||||
const QList<Device*> m_Devices; // List of all devices found on the system
|
||||
|
|
|
@ -75,6 +75,10 @@ void DevicePropsDialog::setupDialog()
|
|||
type = (device().partitionTable()->isReadOnly())
|
||||
? xi18nc("@label device", "%1 (read only)", device().partitionTable()->typeName())
|
||||
: device().partitionTable()->typeName();
|
||||
|
||||
if (device().type() == Device::Type::SoftwareRAID_Device)
|
||||
type += QStringLiteral(" [Software RAID Device]");
|
||||
|
||||
maxPrimaries = QStringLiteral("%1/%2").arg(device().partitionTable()->numPrimaries()).arg(device().partitionTable()->maxPrimaries());
|
||||
|
||||
dialogWidget().partTableWidget().setReadOnly(true);
|
||||
|
@ -121,9 +125,7 @@ void DevicePropsDialog::setupDialog()
|
|||
} else {
|
||||
if (device().type() == Device::Type::LVM_Device)
|
||||
dialogWidget().type().setText(xi18nc("@label device", "LVM Volume Group"));
|
||||
else if (device().type() == Device::Type::SoftwareRAID_Device)
|
||||
dialogWidget().type().setText(xi18nc("@label device", "Software RAID Device"));
|
||||
else
|
||||
else if (device().type() != Device::Type::SoftwareRAID_Device)
|
||||
dialogWidget().type().setText(xi18nc("@label device", "Volume Manager Device"));
|
||||
//TODO: add Volume Manger Device info
|
||||
dialogWidget().smartStatusText().setVisible(false);
|
||||
|
|
|
@ -24,6 +24,11 @@ void ListPhysicalVolumes::addPartition(const Partition& p, bool checked)
|
|||
listPhysicalVolumes().addItem(item);
|
||||
}
|
||||
|
||||
void ListPhysicalVolumes::clear()
|
||||
{
|
||||
listPhysicalVolumes().clear();
|
||||
}
|
||||
|
||||
QVector<const Partition *> ListPhysicalVolumes::checkedItems()
|
||||
{
|
||||
QVector<const Partition *> partitionList;
|
||||
|
|
|
@ -41,6 +41,8 @@ public:
|
|||
|
||||
void addPartition(const Partition& p, bool checked);
|
||||
|
||||
void clear();
|
||||
|
||||
QVector<const Partition *> checkedItems();
|
||||
|
||||
QListWidget& listPhysicalVolumes() {
|
||||
|
|
|
@ -11,7 +11,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>249</width>
|
||||
<height>300</height>
|
||||
<height>410</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QListWidget" name="m_ListPhysicalVolumes">
|
||||
|
@ -20,7 +20,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>251</width>
|
||||
<height>301</height>
|
||||
<height>410</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <core/smartstatus.h>
|
||||
|
||||
#include <ops/operation.h>
|
||||
#include <ops/activateraidoperation.h>
|
||||
#include <ops/createpartitiontableoperation.h>
|
||||
#include <ops/createvolumegroupoperation.h>
|
||||
#include <ops/resizevolumegroupoperation.h>
|
||||
|
@ -82,6 +83,8 @@
|
|||
#include <KJobWidgets>
|
||||
#include "config.h"
|
||||
|
||||
#include <kpmcore/core/softwareraid.h>
|
||||
|
||||
/** Creates a new MainWindow instance.
|
||||
@param parent the parent widget
|
||||
*/
|
||||
|
@ -257,6 +260,15 @@ void MainWindow::setupActions()
|
|||
//actionCollection()->setDefaultShortcut(resizeVolumeGroup, QKeySequence(/*SHORTCUT KEY HERE*/));
|
||||
resizeVolumeGroup->setIcon(QIcon::fromTheme(QStringLiteral("arrow-right-double")));
|
||||
|
||||
QAction* activateRAID = actionCollection()->addAction(QStringLiteral("activateRAID"));
|
||||
connect(activateRAID, &QAction::triggered, this, &MainWindow::onActivateRAID);
|
||||
activateRAID->setEnabled(false);
|
||||
activateRAID->setVisible(false);
|
||||
activateRAID->setText(i18nc("@action:inmenu", "Activate RAID"));
|
||||
activateRAID->setToolTip(i18nc("@info:tooltip", "Activate selected RAID device"));
|
||||
activateRAID->setStatusTip(i18nc("@info:status", "Activate selected RAID device"));
|
||||
activateRAID->setIcon(QIcon::fromTheme(QStringLiteral("answer")).pixmap(IconSize(KIconLoader::Toolbar)));
|
||||
|
||||
QAction* deactivateVolumeGroup = actionCollection()->addAction(QStringLiteral("deactivateVolumeGroup"));
|
||||
connect(deactivateVolumeGroup, &QAction::triggered, this, &MainWindow::onDeactivateVolumeGroup);
|
||||
deactivateVolumeGroup->setEnabled(false);
|
||||
|
@ -506,22 +518,38 @@ void MainWindow::enableActions()
|
|||
actionCollection()->action(QStringLiteral("createVolumeGroup"))
|
||||
->setEnabled(CreateVolumeGroupOperation::canCreate());
|
||||
|
||||
bool lvmDevice = pmWidget().selectedDevice() && pmWidget().selectedDevice()->type() == Device::Type::LVM_Device;
|
||||
bool vgDevice = pmWidget().selectedDevice() &&
|
||||
(pmWidget().selectedDevice()->type() == Device::Type::LVM_Device ||
|
||||
pmWidget().selectedDevice()->type() == Device::Type::SoftwareRAID_Device);
|
||||
bool removable = false;
|
||||
|
||||
if (lvmDevice)
|
||||
removable = RemoveVolumeGroupOperation::isRemovable(dynamic_cast<LvmDevice*>(pmWidget().selectedDevice()));
|
||||
if (vgDevice)
|
||||
removable = RemoveVolumeGroupOperation::isRemovable(dynamic_cast<VolumeManagerDevice*>(pmWidget().selectedDevice()));
|
||||
|
||||
actionCollection()->action(QStringLiteral("removeVolumeGroup"))->setEnabled(removable);
|
||||
actionCollection()->action(QStringLiteral("removeVolumeGroup"))->setVisible(lvmDevice);
|
||||
actionCollection()->action(QStringLiteral("removeVolumeGroup"))->setVisible(vgDevice);
|
||||
|
||||
bool deactivatable = lvmDevice ?
|
||||
DeactivateVolumeGroupOperation::isDeactivatable(dynamic_cast<LvmDevice*>(pmWidget().selectedDevice())) : false;
|
||||
bool isRaid = vgDevice &&
|
||||
pmWidget().selectedDevice()->type() == Device::Type::SoftwareRAID_Device;
|
||||
|
||||
bool canActivateRAID = isRaid &&
|
||||
static_cast< SoftwareRAID* >(pmWidget().selectedDevice())->status() == SoftwareRAID::Status::Inactive;
|
||||
|
||||
actionCollection()->action(QStringLiteral("activateRAID"))->setEnabled(canActivateRAID);
|
||||
actionCollection()->action(QStringLiteral("activateRAID"))->setVisible(isRaid);
|
||||
|
||||
bool deactivatable = vgDevice ?
|
||||
DeactivateVolumeGroupOperation::isDeactivatable(dynamic_cast<VolumeManagerDevice*>(pmWidget().selectedDevice())) : false;
|
||||
actionCollection()->action(QStringLiteral("deactivateVolumeGroup"))->setEnabled(deactivatable);
|
||||
actionCollection()->action(QStringLiteral("deactivateVolumeGroup"))->setVisible(lvmDevice);
|
||||
actionCollection()->action(QStringLiteral("deactivateVolumeGroup"))->setVisible(vgDevice);
|
||||
|
||||
actionCollection()->action(QStringLiteral("resizeVolumeGroup"))->setEnabled(lvmDevice);
|
||||
actionCollection()->action(QStringLiteral("resizeVolumeGroup"))->setVisible(lvmDevice);
|
||||
bool canResizeVG = vgDevice;
|
||||
|
||||
if (isRaid)
|
||||
canResizeVG = static_cast<SoftwareRAID*>(pmWidget().selectedDevice())->status() == SoftwareRAID::Status::Active;
|
||||
|
||||
actionCollection()->action(QStringLiteral("resizeVolumeGroup"))->setEnabled(canResizeVG);
|
||||
actionCollection()->action(QStringLiteral("resizeVolumeGroup"))->setVisible(canResizeVG);
|
||||
|
||||
const Partition* part = pmWidget().selectedPartition();
|
||||
|
||||
|
@ -1105,19 +1133,30 @@ void MainWindow::onCreateNewVolumeGroup()
|
|||
{
|
||||
QString vgName;
|
||||
QVector<const Partition*> pvList;
|
||||
QString type;
|
||||
qint32 raidLevel = 0;
|
||||
qint32 peSize = 4;
|
||||
qint32 chunkSize = 512;
|
||||
// *NOTE*: vgName & pvList will be modified and validated by the dialog
|
||||
QPointer<CreateVolumeGroupDialog> dlg = new CreateVolumeGroupDialog(this, vgName, pvList, peSize, operationStack().previewDevices(), operationStack().operations());
|
||||
QPointer<CreateVolumeGroupDialog> dlg = new CreateVolumeGroupDialog(this, vgName, pvList, type, raidLevel, chunkSize,
|
||||
peSize, operationStack().previewDevices(),
|
||||
operationStack().operations());
|
||||
if (dlg->exec() == QDialog::Accepted)
|
||||
operationStack().push(new CreateVolumeGroupOperation(vgName, pvList, peSize));
|
||||
{
|
||||
if (type == QStringLiteral("LVM"))
|
||||
operationStack().push(new CreateVolumeGroupOperation(vgName, pvList, Device::Type::LVM_Device, peSize));
|
||||
else if (type == QStringLiteral("RAID"))
|
||||
operationStack().push(new CreateVolumeGroupOperation(vgName, pvList, Device::Type::SoftwareRAID_Device, raidLevel, chunkSize));
|
||||
}
|
||||
|
||||
delete dlg;
|
||||
}
|
||||
|
||||
void MainWindow::onResizeVolumeGroup()
|
||||
{
|
||||
if (pmWidget().selectedDevice()->type() == Device::Type::LVM_Device) {
|
||||
LvmDevice* d = dynamic_cast<LvmDevice*>(pmWidget().selectedDevice());
|
||||
if (pmWidget().selectedDevice()->type() == Device::Type::LVM_Device ||
|
||||
pmWidget().selectedDevice()->type() == Device::Type::SoftwareRAID_Device) {
|
||||
VolumeManagerDevice* d = dynamic_cast<VolumeManagerDevice*>(pmWidget().selectedDevice());
|
||||
|
||||
QVector<const Partition*> pvList;
|
||||
// *NOTE*: pvList will be modified and validated by the dialog
|
||||
|
@ -1133,23 +1172,50 @@ void MainWindow::onResizeVolumeGroup()
|
|||
void MainWindow::onRemoveVolumeGroup()
|
||||
{
|
||||
Device* tmpDev = pmWidget().selectedDevice();
|
||||
if (tmpDev->type() == Device::Type::LVM_Device) {
|
||||
operationStack().push(new RemoveVolumeGroupOperation(*(dynamic_cast<LvmDevice*>(tmpDev))));
|
||||
if (tmpDev->type() == Device::Type::LVM_Device ||
|
||||
tmpDev->type() == Device::Type::SoftwareRAID_Device) {
|
||||
operationStack().push(new RemoveVolumeGroupOperation(*(dynamic_cast<VolumeManagerDevice*>(tmpDev))));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onDeactivateVolumeGroup()
|
||||
{
|
||||
Device* tmpDev = pmWidget().selectedDevice();
|
||||
if (tmpDev->type() == Device::Type::LVM_Device) {
|
||||
DeactivateVolumeGroupOperation* deactivate = new DeactivateVolumeGroupOperation( *(dynamic_cast<LvmDevice*>(tmpDev)) );
|
||||
Report* tmpReport = new Report(nullptr);
|
||||
if (deactivate->execute(*tmpReport)) {
|
||||
if (tmpDev->type() == Device::Type::LVM_Device || tmpDev->type() == Device::Type::SoftwareRAID_Device) {
|
||||
DeactivateVolumeGroupOperation* deactivate = new DeactivateVolumeGroupOperation( *(dynamic_cast<VolumeManagerDevice*>(tmpDev)) );
|
||||
Report tmpReport(nullptr);
|
||||
if (deactivate->execute(tmpReport)) {
|
||||
deactivate->preview();
|
||||
actionCollection()->action(QStringLiteral("resizeVolumeGroup"))->setEnabled(false);
|
||||
actionCollection()->action(QStringLiteral("deactivateVolumeGroup"))->setEnabled(false);
|
||||
}
|
||||
delete tmpReport;
|
||||
pmWidget().updatePartitions();
|
||||
enableActions();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onActivateRAID()
|
||||
{
|
||||
Device* dev = pmWidget().selectedDevice();
|
||||
|
||||
if (dev->type() == Device::Type::SoftwareRAID_Device) {
|
||||
ActivateRaidOperation activate(static_cast<SoftwareRAID*>(dev));
|
||||
|
||||
Report report(nullptr);
|
||||
|
||||
if (activate.execute(report))
|
||||
activate.preview();
|
||||
|
||||
Device *tmp = CoreBackendManager::self()->backend()->scanDevice(dev->deviceNode());
|
||||
|
||||
if (tmp) {
|
||||
PartitionTable* ptable = new PartitionTable(*tmp->partitionTable());
|
||||
|
||||
dev->setPartitionTable(ptable);
|
||||
}
|
||||
|
||||
delete tmp;
|
||||
|
||||
pmWidget().updatePartitions();
|
||||
enableActions();
|
||||
}
|
||||
|
@ -1169,7 +1235,15 @@ void MainWindow::onShowAboutKPMcore()
|
|||
|
||||
void MainWindow::onSettingsChanged()
|
||||
{
|
||||
bool raidChanged = false, backendChanged = false;
|
||||
|
||||
if (SoftwareRAID::raidConfigurationFilePath() != Config::raidConfigurationFilePath()) {
|
||||
raidChanged = true;
|
||||
loadRaidConfiguration();
|
||||
}
|
||||
|
||||
if (CoreBackendManager::self()->backend()->id() != Config::backend()) {
|
||||
backendChanged = true;
|
||||
CoreBackendManager::self()->unload();
|
||||
// FIXME: if loadBackend() fails to load the configured backend and loads the default
|
||||
// one instead it also sets the default backend in the config; the config dialog will
|
||||
|
@ -1182,6 +1256,9 @@ void MainWindow::onSettingsChanged()
|
|||
close();
|
||||
}
|
||||
|
||||
if (raidChanged && !backendChanged)
|
||||
scanDevices();
|
||||
|
||||
enableActions();
|
||||
pmWidget().updatePartitions();
|
||||
|
||||
|
|
|
@ -235,6 +235,7 @@ protected:
|
|||
void onRemoveVolumeGroup();
|
||||
void onResizeVolumeGroup();
|
||||
void onDeactivateVolumeGroup();
|
||||
void onActivateRAID();
|
||||
void onExportPartitionTable();
|
||||
void onImportPartitionTable();
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<Action name="importPartitionTable"/>
|
||||
<separator/>
|
||||
<Action name="resizeVolumeGroup"/>
|
||||
<Action name="activateRAID"/>
|
||||
<Action name="deactivateVolumeGroup"/>
|
||||
<Action name="removeVolumeGroup"/>
|
||||
<separator/>
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include <core/lvmdevice.h>
|
||||
#include <core/volumemanagerdevice.h>
|
||||
#include <core/partitiontable.h>
|
||||
#include <core/softwareraid.h>
|
||||
|
||||
#include <fs/lvm2_pv.h>
|
||||
|
||||
#include <ops/deleteoperation.h>
|
||||
|
@ -26,6 +28,8 @@
|
|||
#include <KLocalizedString>
|
||||
#include <KSharedConfig>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
/** Creates a new ResizeVolumeGroupDialog
|
||||
@param parent pointer to the parent widget
|
||||
@param d the Device to show properties for
|
||||
|
@ -47,8 +51,15 @@ ResizeVolumeGroupDialog::ResizeVolumeGroupDialog(QWidget* parent, VolumeManagerD
|
|||
|
||||
void ResizeVolumeGroupDialog::setupDialog()
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
if (device()->type() == Device::Type::LVM_Device) {
|
||||
dialogWidget().volumeType().setCurrentIndex(0);
|
||||
|
||||
for (const auto &p : qAsConst(LVM::pvList::list())) {
|
||||
=======
|
||||
if (dialogWidget().volumeType().currentText() == QStringLiteral("LVM")) {
|
||||
for (const auto &p : std::as_const(LVM::pvList::list())) {
|
||||
>>>>>>> master
|
||||
bool toBeDeleted = false;
|
||||
|
||||
// Ignore partitions that are going to be deleted
|
||||
|
@ -59,11 +70,9 @@ void ResizeVolumeGroupDialog::setupDialog()
|
|||
}
|
||||
}
|
||||
|
||||
if (toBeDeleted)
|
||||
if (toBeDeleted || p.isLuks())
|
||||
continue;
|
||||
|
||||
if (p.isLuks())
|
||||
continue;
|
||||
if (p.vgName() == device()->name())
|
||||
dialogWidget().listPV().addPartition(*p.partition(), true);
|
||||
else if (p.vgName().isEmpty() && !LvmDevice::s_DirtyPVs.contains(p.partition())) // TODO: Remove LVM PVs in current VG
|
||||
|
@ -95,17 +104,56 @@ void ResizeVolumeGroupDialog::setupDialog()
|
|||
for (const Partition *p : std::as_const(LvmDevice::s_OrphanPVs))
|
||||
if (!LvmDevice::s_DirtyPVs.contains(p))
|
||||
dialogWidget().listPV().addPartition(*p, false);
|
||||
}
|
||||
|
||||
//update used size and LV infos
|
||||
qint32 totalLV = 0;
|
||||
LvmDevice *lvmDevice = dynamic_cast<LvmDevice *>(device());
|
||||
if (lvmDevice != nullptr) {
|
||||
LvmDevice *lvmDevice = static_cast<LvmDevice*>(device());
|
||||
|
||||
m_TotalUsedSize = lvmDevice->allocatedPE() * lvmDevice->peSize();
|
||||
totalLV = lvmDevice->partitionTable()->children().count();
|
||||
}
|
||||
|
||||
dialogWidget().totalUsedSize().setText(Capacity::formatByteSize(m_TotalUsedSize));
|
||||
}
|
||||
else if (device()->type() == Device::Type::SoftwareRAID_Device) {
|
||||
dialogWidget().volumeType().setCurrentIndex(1);
|
||||
|
||||
for (const Device *d : qAsConst(m_Devices)) {
|
||||
if (d != device() && d->partitionTable() != nullptr) {
|
||||
for (const Partition *p : qAsConst(d->partitionTable()->children())) {
|
||||
QString arrayName = SoftwareRAID::getRaidArrayName(p->partitionPath());
|
||||
if (arrayName == device()->deviceNode())
|
||||
dialogWidget().listPV().addPartition(*p, true);
|
||||
else if (((p->fileSystem().type() == FileSystem::Type::LinuxRaidMember &&
|
||||
arrayName.isEmpty()) || p->fileSystem().type() == FileSystem::Type::Unformatted ||
|
||||
p->fileSystem().type() == FileSystem::Type::Unknown) && !p->roles().has(PartitionRole::Role::Unallocated))
|
||||
dialogWidget().listPV().addPartition(*p, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SoftwareRAID* raid = static_cast<SoftwareRAID*>(device());
|
||||
|
||||
m_TotalUsedSize = 0;
|
||||
|
||||
for (const Partition* p : device()->partitionTable()->children())
|
||||
if (!p->roles().has(PartitionRole::Unallocated))
|
||||
m_TotalUsedSize += p->used();
|
||||
|
||||
dialogWidget().totalUsedSize().setText(Capacity::formatByteSize(m_TotalUsedSize));
|
||||
|
||||
int index = dialogWidget().raidLevel().findText(QString::number(raid->raidLevel()));
|
||||
|
||||
if (index != -1)
|
||||
dialogWidget().raidLevel().setCurrentIndex(index);
|
||||
|
||||
dialogWidget().chunkSize().setValue(raid->chunkSize());
|
||||
}
|
||||
|
||||
int totalLV = 0;
|
||||
|
||||
if (device()->partitionTable()) {
|
||||
for (const Partition* p : device()->partitionTable()->children())
|
||||
if (!p->roles().has(PartitionRole::Role::Unallocated))
|
||||
totalLV++;
|
||||
}
|
||||
|
||||
dialogWidget().totalLV().setText(QString::number(totalLV));
|
||||
}
|
||||
|
||||
|
@ -114,6 +162,11 @@ void ResizeVolumeGroupDialog::setupConstraints()
|
|||
dialogWidget().vgName().setEnabled(false);
|
||||
dialogWidget().spinPESize().setEnabled(false);
|
||||
dialogWidget().volumeType().setEnabled(false);
|
||||
|
||||
// set constraints for raid
|
||||
dialogWidget().raidLevel().setEnabled(false);
|
||||
dialogWidget().chunkSize().setEnabled(false);
|
||||
|
||||
VolumeGroupDialog::setupConstraints();
|
||||
}
|
||||
|
||||
|
|
|
@ -66,18 +66,16 @@ VolumeGroupDialog::~VolumeGroupDialog()
|
|||
|
||||
void VolumeGroupDialog::setupDialog()
|
||||
{
|
||||
/* LVM Volume group name can consist of: letters numbers _ . - +
|
||||
* It cannot start with underscore _ and must not be equal to . or .. or any entry in /dev/
|
||||
* QLineEdit accepts QValidator::Intermediate, so we just disable . at the beginning */
|
||||
QRegularExpression re(QStringLiteral(R"(^(?!_|\.)[\w\-.+]+)"));
|
||||
QRegularExpressionValidator *validator = new QRegularExpressionValidator(re, this);
|
||||
dialogWidget().vgName().setValidator(validator);
|
||||
dialogWidget().vgName().setText(targetName());
|
||||
|
||||
dialogWidget().volumeType().addItem(QStringLiteral("LVM"));
|
||||
dialogWidget().volumeType().addItem(QStringLiteral("RAID"));
|
||||
dialogWidget().volumeType().addItems({ QStringLiteral("LVM"), QStringLiteral("RAID") });
|
||||
dialogWidget().volumeType().setCurrentIndex(0);
|
||||
|
||||
dialogWidget().raidLevel().addItems({ QStringLiteral("0"), QStringLiteral("1"),
|
||||
QStringLiteral("4"), QStringLiteral("5"),
|
||||
QStringLiteral("6"), QStringLiteral("10") });
|
||||
|
||||
updateNameValidator();
|
||||
updateComponents();
|
||||
|
||||
setMinimumSize(dialogWidget().size());
|
||||
resize(dialogWidget().size());
|
||||
}
|
||||
|
@ -116,20 +114,35 @@ void VolumeGroupDialog::updateOkButtonStatus()
|
|||
void VolumeGroupDialog::updateSectorInfos()
|
||||
{
|
||||
qint32 totalSectors = 0;
|
||||
|
||||
if (dialogWidget().volumeType().currentText() == QStringLiteral("LVM")) {
|
||||
// we can't use LvmDevice method here because pv that is not in any VG will return 0
|
||||
m_ExtentSize = dialogWidget().spinPESize().value() * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
|
||||
if (m_ExtentSize > 0) {
|
||||
|
||||
if (m_ExtentSize > 0)
|
||||
totalSectors = m_TotalSize / m_ExtentSize;
|
||||
}
|
||||
else if (dialogWidget().volumeType().currentText() == QStringLiteral("RAID")) {
|
||||
m_ExtentSize = dialogWidget().chunkSize().value() * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::KiB);
|
||||
|
||||
if (m_ExtentSize > 0)
|
||||
totalSectors = m_TotalSize / m_ExtentSize;
|
||||
}
|
||||
|
||||
dialogWidget().totalSectors().setText(QString::number(totalSectors));
|
||||
}
|
||||
|
||||
void VolumeGroupDialog::updateSizeInfos()
|
||||
{
|
||||
QString type = dialogWidget().volumeType().currentText();
|
||||
const QVector<const Partition *> checkedPartitions = dialogWidget().listPV().checkedItems();
|
||||
m_TotalSize = 0;
|
||||
for (const auto &p : checkedPartitions)
|
||||
m_TotalSize += p->capacity() - p->capacity() % (dialogWidget().spinPESize().value() * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB)); // subtract space which is too small to hold PE
|
||||
m_TotalSize += p->capacity() - p->capacity() %
|
||||
(type == QStringLiteral("LVM") ?
|
||||
(dialogWidget().spinPESize().value() * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB)) :
|
||||
(dialogWidget().chunkSize().value() * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::KiB)));
|
||||
// subtract space which is too small to hold PE
|
||||
|
||||
dialogWidget().totalSize().setText(Capacity::formatByteSize(m_TotalSize));
|
||||
|
||||
|
@ -143,6 +156,23 @@ void VolumeGroupDialog::updatePartitionList()
|
|||
{
|
||||
}
|
||||
|
||||
void VolumeGroupDialog::updateNameValidator()
|
||||
{
|
||||
if (dialogWidget().volumeType().currentText() == QStringLiteral("LVM")) {
|
||||
/* LVM Volume group name can consist of: letters numbers _ . - +
|
||||
* It cannot start with underscore _ and must not be equal to . or .. or any entry in /dev/
|
||||
* QLineEdit accepts QValidator::Intermediate, so we just disable . at the beginning */
|
||||
|
||||
QRegularExpression re(QStringLiteral(R"(^(?!_|\.)[\w\-.+]+)"));
|
||||
QRegularExpressionValidator *validator = new QRegularExpressionValidator(re, this);
|
||||
dialogWidget().vgName().setValidator(validator);
|
||||
dialogWidget().vgName().setText(targetName());
|
||||
}
|
||||
else if (dialogWidget().volumeType().currentText() == QStringLiteral("RAID")) {
|
||||
// TODO: See how Software RAID names should be validated.
|
||||
}
|
||||
}
|
||||
|
||||
void VolumeGroupDialog::onPartitionListChanged()
|
||||
{
|
||||
}
|
||||
|
@ -150,5 +180,17 @@ void VolumeGroupDialog::onPartitionListChanged()
|
|||
void VolumeGroupDialog::onVolumeTypeChanged(int index)
|
||||
{
|
||||
Q_UNUSED(index)
|
||||
updateNameValidator();
|
||||
updatePartitionList();
|
||||
updateComponents();
|
||||
}
|
||||
|
||||
void VolumeGroupDialog::updateComponents()
|
||||
{
|
||||
dialogWidget().spinPESize().setVisible(dialogWidget().volumeType().currentText() == QStringLiteral("LVM"));
|
||||
dialogWidget().textTotalPESize().setVisible(dialogWidget().volumeType().currentText() == QStringLiteral("LVM"));
|
||||
dialogWidget().raidLevel().setVisible(dialogWidget().volumeType().currentText() == QStringLiteral("RAID"));
|
||||
dialogWidget().textRaidLevel().setVisible(dialogWidget().volumeType().currentText() == QStringLiteral("RAID"));
|
||||
dialogWidget().chunkSize().setVisible(dialogWidget().volumeType().currentText() == QStringLiteral("RAID"));
|
||||
dialogWidget().textChunkSize().setVisible(dialogWidget().volumeType().currentText() == QStringLiteral("RAID"));
|
||||
}
|
||||
|
|
|
@ -36,7 +36,9 @@ protected:
|
|||
virtual void updateSizeInfos();
|
||||
virtual void updateSectorInfos();
|
||||
virtual void updatePartitionList();
|
||||
virtual void updateNameValidator();
|
||||
|
||||
virtual void onPartitionListChanged();
|
||||
virtual void onVolumeTypeChanged(int index);
|
||||
|
||||
VolumeGroupWidget& dialogWidget() {
|
||||
|
@ -72,8 +74,8 @@ protected:
|
|||
return m_IsValidName;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void onPartitionListChanged();
|
||||
private:
|
||||
void updateComponents();
|
||||
|
||||
protected:
|
||||
VolumeGroupWidget* m_DialogWidget;
|
||||
|
|
|
@ -25,82 +25,101 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
QLineEdit& vgName() {
|
||||
QLineEdit& vgName() const {
|
||||
Q_ASSERT(m_EditVGName);
|
||||
return *m_EditVGName;
|
||||
}
|
||||
|
||||
QComboBox& volumeType() {
|
||||
QComboBox& volumeType() const {
|
||||
Q_ASSERT(m_ComboVolumeType);
|
||||
return *m_ComboVolumeType;
|
||||
}
|
||||
|
||||
QSpinBox& spinPESize() {
|
||||
QSpinBox& spinPESize() const {
|
||||
Q_ASSERT(m_SpinPESize);
|
||||
return *m_SpinPESize;
|
||||
|
||||
}
|
||||
ListPhysicalVolumes& listPV() {
|
||||
|
||||
ListPhysicalVolumes& listPV() const {
|
||||
Q_ASSERT(m_ListPV);
|
||||
return *m_ListPV;
|
||||
}
|
||||
|
||||
QLabel& totalSize() {
|
||||
QLabel& totalSize() const {
|
||||
Q_ASSERT(m_LabelTotalSize);
|
||||
return *m_LabelTotalSize;
|
||||
}
|
||||
|
||||
|
||||
QLabel& totalSectors() {
|
||||
QLabel& totalSectors() const {
|
||||
Q_ASSERT(m_LabelTotalSectors);
|
||||
return *m_LabelTotalSectors;
|
||||
}
|
||||
|
||||
QLabel& totalUsedSize() {
|
||||
QLabel& totalUsedSize() const {
|
||||
Q_ASSERT(m_LabelTotalUsedSize);
|
||||
return *m_LabelTotalUsedSize;
|
||||
}
|
||||
|
||||
QLabel& totalLV() {
|
||||
QLabel& totalLV() const {
|
||||
Q_ASSERT(m_LabelTotalLV);
|
||||
return *m_LabelTotalLV;
|
||||
}
|
||||
|
||||
QLabel& textVGName() {
|
||||
QLabel& textVGName() const {
|
||||
Q_ASSERT(m_LabelTextVGName);
|
||||
return *m_LabelTextVGName;
|
||||
}
|
||||
|
||||
QLabel& textVolumeType() {
|
||||
QLabel& textVolumeType() const {
|
||||
Q_ASSERT(m_LabelTextVolumeType);
|
||||
return *m_LabelTextVolumeType;
|
||||
}
|
||||
|
||||
QLabel& textTotalSize() {
|
||||
QLabel& textTotalSize() const {
|
||||
Q_ASSERT(m_LabelTextTotalSize);
|
||||
return *m_LabelTextTotalSize;
|
||||
}
|
||||
|
||||
QLabel& textTotalSectors() {
|
||||
QLabel& textTotalSectors() const {
|
||||
Q_ASSERT(m_LabelTextTotalSectors);
|
||||
return *m_LabelTextTotalSectors;
|
||||
}
|
||||
|
||||
QLabel& textTotalUsedSize() {
|
||||
QLabel& textTotalUsedSize() const {
|
||||
Q_ASSERT(m_LabelTextTotalUsedSize);
|
||||
return *m_LabelTextTotalUsedSize;
|
||||
}
|
||||
|
||||
QLabel& textTotalLV() {
|
||||
QLabel& textTotalLV() const {
|
||||
Q_ASSERT(m_LabelTextTotalLV);
|
||||
return *m_LabelTextTotalLV;
|
||||
}
|
||||
|
||||
QLabel& textTotalPESize() {
|
||||
QLabel& textTotalPESize() const {
|
||||
Q_ASSERT(m_LabelTextPESize);
|
||||
return *m_LabelTextPESize;
|
||||
}
|
||||
|
||||
QSpinBox& chunkSize() const {
|
||||
Q_ASSERT(m_ChunkSize);
|
||||
return *m_ChunkSize;
|
||||
}
|
||||
|
||||
QComboBox& raidLevel() const {
|
||||
Q_ASSERT(m_RaidLevel);
|
||||
return *m_RaidLevel;
|
||||
}
|
||||
|
||||
QLabel& textChunkSize() const {
|
||||
Q_ASSERT(m_LabelChunkSize);
|
||||
return *m_LabelChunkSize;
|
||||
}
|
||||
|
||||
QLabel& textRaidLevel() const {
|
||||
Q_ASSERT(m_LabelRaidLevel);
|
||||
return *m_LabelRaidLevel;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,7 +11,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>831</width>
|
||||
<height>512</height>
|
||||
<height>480</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
|
@ -21,14 +21,17 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="m_EditVGName"/>
|
||||
<item row="0" column="0" rowspan="7">
|
||||
<widget class="ListPhysicalVolumes" name="m_ListPV" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>410</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="m_LabelTextVGName">
|
||||
<property name="text">
|
||||
<string>Volume Group Name: </string>
|
||||
|
@ -36,12 +39,35 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="m_EditVGName"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="m_LabelTextVolumeType">
|
||||
<property name="text">
|
||||
<string>Volume Group Type: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="1" column="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QComboBox" name="m_ComboVolumeType"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="m_LabelTextPESize">
|
||||
<property name="text">
|
||||
<string>Physical Extent Size: </string>
|
||||
|
@ -49,30 +75,32 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QLabel" name="m_LabelTotalSectors">
|
||||
<property name="text">
|
||||
<string>---</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QComboBox" name="m_ComboVolumeType"/>
|
||||
<widget class="QLabel" name="m_LabelRaidLevel">
|
||||
<property name="text">
|
||||
<string>RAID level:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="m_LabelChunkSize">
|
||||
<property name="text">
|
||||
<string>Chunk Size:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item row="2" column="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_1">
|
||||
<item>
|
||||
<widget class="QSpinBox" name="m_SpinPESize">
|
||||
<property name="suffix">
|
||||
|
@ -89,52 +117,28 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="m_RaidLevel"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="m_ChunkSize">
|
||||
<property name="suffix">
|
||||
<string> KiB</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>2048</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>512</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" rowspan="7">
|
||||
<widget class="ListPhysicalVolumes" name="m_ListPV" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QLabel" name="m_LabelTextTotalLV">
|
||||
<property name="text">
|
||||
<string>Total LV: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<widget class="QLabel" name="m_LabelTotalLV">
|
||||
<property name="text">
|
||||
<string>---</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="m_LabelTextVolumeType">
|
||||
<property name="text">
|
||||
<string>Volume Group Type: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="m_LabelTextTotalSize">
|
||||
<property name="text">
|
||||
<string>Total Size: </string>
|
||||
|
@ -142,45 +146,19 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="m_LabelTextTotalSectors">
|
||||
<property name="text">
|
||||
<string>Total Sectors: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="m_LabelTotalSize">
|
||||
<property name="text">
|
||||
<string>---</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="m_LabelTotalUsedSize">
|
||||
<property name="text">
|
||||
<string>---</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="m_LabelTextTotalUsedSize">
|
||||
<property name="text">
|
||||
<string>Used Size: </string>
|
||||
|
@ -188,8 +166,55 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="m_LabelTotalUsedSize">
|
||||
<property name="text">
|
||||
<string>---</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="m_LabelTextTotalSectors">
|
||||
<property name="text">
|
||||
<string>Total Sectors: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="m_LabelTotalSectors">
|
||||
<property name="text">
|
||||
<string>---</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="m_LabelTextTotalLV">
|
||||
<property name="text">
|
||||
<string>Total LV: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QLabel" name="m_LabelTotalLV">
|
||||
<property name="text">
|
||||
<string>---</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -71,6 +71,8 @@ int Q_DECL_IMPORT main(int argc, char* argv[])
|
|||
if (!loadBackend())
|
||||
return 0;
|
||||
|
||||
loadRaidConfiguration();
|
||||
|
||||
MainWindow* mainWindow = new MainWindow();
|
||||
Q_UNUSED(mainWindow)
|
||||
|
||||
|
|
|
@ -167,5 +167,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
</choices>
|
||||
<default>random</default>
|
||||
</entry>
|
||||
<entry key="raidConfigurationFilePath" type="String">
|
||||
<default>/etc/mdadm.conf</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <kpmcore/core/softwareraid.h>
|
||||
|
||||
QIcon createFileSystemColor(FileSystem::Type type, quint32 size)
|
||||
{
|
||||
QPixmap pixmap(size, size);
|
||||
|
@ -65,6 +67,11 @@ bool loadBackend()
|
|||
return true;
|
||||
}
|
||||
|
||||
void loadRaidConfiguration()
|
||||
{
|
||||
SoftwareRAID::setRaidConfigurationFilePath(Config::raidConfigurationFilePath());
|
||||
}
|
||||
|
||||
Capacity::Unit preferredUnit()
|
||||
{
|
||||
return static_cast<Capacity::Unit>(Config::preferredUnit());
|
||||
|
|
|
@ -19,6 +19,7 @@ class QString;
|
|||
class QTreeWidget;
|
||||
|
||||
bool loadBackend();
|
||||
void loadRaidConfiguration();
|
||||
QIcon createFileSystemColor(FileSystem::Type type, quint32 size);
|
||||
Capacity::Unit preferredUnit();
|
||||
void showColumnsContextMenu(const QPoint& p, QTreeWidget& tree);
|
||||
|
|
Loading…
Reference in New Issue