File indexing completed on 2024-04-28 05:46:36

0001 /*
0002     SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
0003     SPDX-FileCopyrightText: 2016-2018 Andrius Štikonas <andrius@stikonas.eu>
0004     SPDX-FileCopyrightText: 2018 Yuri Chornoivan <yurchor@ukr.net>
0005 
0006     SPDX-License-Identifier: GPL-3.0-or-later
0007 */
0008 
0009 #include "gui/volumegroupdialog.h"
0010 #include "gui/volumegroupwidget.h"
0011 
0012 #include <core/partitiontable.h>
0013 #include <core/lvmdevice.h>
0014 #include <fs/lvm2_pv.h>
0015 
0016 #include <util/capacity.h>
0017 #include <util/helpers.h>
0018 
0019 #include <KConfigGroup>
0020 #include <KLocalizedString>
0021 #include <KSharedConfig>
0022 
0023 #include <QtGlobal>
0024 #include <QListWidgetItem>
0025 #include <QRegularExpressionValidator>
0026 
0027 /** Creates a new VolumeGroupDialog
0028     @param parent pointer to the parent widget
0029     @param vgName Volume Group name
0030     @param pvList List of LVM Physical Volumes used to create Volume Group
0031 */
0032 VolumeGroupDialog::VolumeGroupDialog(QWidget* parent, QString& vgName, QVector<const Partition*>& pvList) :
0033     QDialog(parent),
0034     m_DialogWidget(new VolumeGroupWidget(this)),
0035     m_TargetName(vgName),
0036     m_TargetPVList(pvList),
0037     m_IsValidSize(false),
0038     m_IsValidName(true),
0039     m_TotalSize(0),
0040     m_TotalUsedSize(0),
0041     m_ExtentSize(0)
0042 {
0043     mainLayout = new QVBoxLayout(this);
0044     setLayout(mainLayout);
0045     mainLayout->addWidget(&dialogWidget());
0046 
0047     dialogButtonBox = new QDialogButtonBox;
0048     okButton = dialogButtonBox->addButton(QDialogButtonBox::Ok);
0049     cancelButton = dialogButtonBox->addButton(QDialogButtonBox::Cancel);
0050     mainLayout->addWidget(dialogButtonBox);
0051 
0052     cancelButton->setFocus();
0053     cancelButton->setDefault(true);
0054 
0055     setupDialog();
0056     setupConstraints();
0057     setupConnections();
0058 }
0059 
0060 /** Destroys a VolumeGroupDialog */
0061 VolumeGroupDialog::~VolumeGroupDialog()
0062 {
0063     KConfigGroup kcg(KSharedConfig::openConfig(), QStringLiteral("createVolumeGroupDialog"));
0064     kcg.writeEntry("Geometry", saveGeometry());
0065 }
0066 
0067 void VolumeGroupDialog::setupDialog()
0068 {
0069     /* LVM Volume group name can consist of: letters numbers _ . - +
0070      * It cannot start with underscore _ and must not be equal to . or .. or any entry in /dev/
0071      * QLineEdit accepts QValidator::Intermediate, so we just disable . at the beginning */
0072     QRegularExpression re(QStringLiteral(R"(^(?!_|\.)[\w\-.+]+)"));
0073     QRegularExpressionValidator *validator = new QRegularExpressionValidator(re, this);
0074     dialogWidget().vgName().setValidator(validator);
0075     dialogWidget().vgName().setText(targetName());
0076 
0077     dialogWidget().volumeType().addItem(QStringLiteral("LVM"));
0078     dialogWidget().volumeType().addItem(QStringLiteral("RAID"));
0079     dialogWidget().volumeType().setCurrentIndex(0);
0080 
0081     setMinimumSize(dialogWidget().size());
0082     resize(dialogWidget().size());
0083 }
0084 
0085 void VolumeGroupDialog::setupConnections()
0086 {
0087     connect(dialogButtonBox, &QDialogButtonBox::accepted, this, &VolumeGroupDialog::accept);
0088     connect(dialogButtonBox, &QDialogButtonBox::rejected, this, &VolumeGroupDialog::reject);
0089     connect(&dialogWidget().volumeType(), &QComboBox::currentIndexChanged, this, &VolumeGroupDialog::onVolumeTypeChanged);
0090     connect(&dialogWidget().listPV().listPhysicalVolumes(), &QListWidget::itemChanged,
0091             this, [=] ( QListWidgetItem*) {
0092                 updateSizeInfos();
0093             });
0094 }
0095 
0096 void VolumeGroupDialog::setupConstraints()
0097 {
0098     updateSizeInfos();
0099     updateOkButtonStatus();
0100 }
0101 
0102 void VolumeGroupDialog::updateOkButtonStatus()
0103 {
0104     bool enable = isValidSize();
0105 
0106     if (dialogWidget().vgName().text().isEmpty() || !isValidName()) {
0107         enable = false;
0108     }
0109     if (dialogWidget().spinPESize().value() <= 0) {
0110         enable = false;
0111     }
0112 
0113     okButton->setEnabled(enable);
0114 }
0115 
0116 void VolumeGroupDialog::updateSectorInfos()
0117 {
0118     qint32 totalSectors = 0;
0119     // we can't use LvmDevice method here because pv that is not in any VG will return 0
0120     m_ExtentSize = dialogWidget().spinPESize().value() * Capacity::unitFactor(Capacity::Unit::Byte, Capacity::Unit::MiB);
0121     if (m_ExtentSize > 0) {
0122         totalSectors = m_TotalSize / m_ExtentSize;
0123     }
0124     dialogWidget().totalSectors().setText(QString::number(totalSectors));
0125 }
0126 
0127 void VolumeGroupDialog::updateSizeInfos()
0128 {
0129     const QVector<const Partition *> checkedPartitions = dialogWidget().listPV().checkedItems();
0130     m_TotalSize = 0;
0131     for (const auto &p : checkedPartitions)
0132         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
0133 
0134     dialogWidget().totalSize().setText(Capacity::formatByteSize(m_TotalSize));
0135 
0136     //Probably a bad design for updating state here; the state should be changed inside the update button function.
0137     m_IsValidSize = m_TotalSize >= m_TotalUsedSize;
0138     updateSectorInfos();
0139     updateOkButtonStatus();
0140 }
0141 
0142 void VolumeGroupDialog::updatePartitionList()
0143 {
0144 }
0145 
0146 void VolumeGroupDialog::onPartitionListChanged()
0147 {
0148 }
0149 
0150 void VolumeGroupDialog::onVolumeTypeChanged(int index)
0151 {
0152     Q_UNUSED(index)
0153     updatePartitionList();
0154 }