File indexing completed on 2024-04-21 09:36:42

0001 /*******************************************************************************
0002  * Copyright (C) 2008-2013 Konstantinos Smanis <konstantinos.smanis@gmail.com> *
0003  *                                                                             *
0004  * This program is free software: you can redistribute it and/or modify it     *
0005  * under the terms of the GNU General Public License as published by the Free  *
0006  * Software Foundation, either version 3 of the License, or (at your option)   *
0007  * any later version.                                                          *
0008  *                                                                             *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT *
0010  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
0011  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
0012  * more details.                                                               *
0013  *                                                                             *
0014  * You should have received a copy of the GNU General Public License along     *
0015  * with this program. If not, see <http://www.gnu.org/licenses/>.              *
0016  *******************************************************************************/
0017 
0018 //Own
0019 #include "installDlg.h"
0020 
0021 //Qt
0022 #include <QFile>
0023 #include <QRadioButton>
0024 #include <QPushButton>
0025 #include <QIcon>
0026 #include <QProgressDialog>
0027 
0028 //KDE
0029 #include <KFormat>
0030 #include <KLocalizedString>
0031 #include <KMessageBox>
0032 #include <KAuth/Action>
0033 #include <KAuth/ExecuteJob>
0034 using namespace KAuth;
0035 #include <Solid/Device>
0036 #include <Solid/StorageAccess>
0037 #include <Solid/StorageVolume>
0038 
0039 //Ui
0040 #include "ui_installDlg.h"
0041 
0042 InstallDialog::InstallDialog(QWidget *parent) : QDialog(parent)
0043 {
0044     QWidget *widget = new QWidget(this);
0045     ui = new Ui::InstallDialog;
0046     ui->setupUi(widget);
0047     ui->gridLayout->setContentsMargins(0, 0, 0, 0);
0048 
0049     auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
0050     connect(buttonBox, &QDialogButtonBox::accepted, this, &InstallDialog::slotAccepted);
0051     connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
0052     auto *okButton = buttonBox->button(QDialogButtonBox::Ok);
0053     okButton->setEnabled(false);
0054 
0055     QVBoxLayout *mainLayout = new QVBoxLayout;
0056     setLayout(mainLayout);
0057     mainLayout->addWidget(widget);
0058     mainLayout->addWidget(buttonBox);
0059 
0060     setWindowTitle(i18nc("@title:window", "Install/Recover Bootloader"));
0061     setWindowIcon(QIcon::fromTheme(QStringLiteral("system-software-update")));
0062     if (parent) {
0063         resize(parent->size());
0064     }
0065 
0066     ui->treeWidget_recover->headerItem()->setText(0, QString());
0067     ui->treeWidget_recover->header()->setSectionResizeMode(QHeaderView::Stretch);
0068     ui->treeWidget_recover->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
0069     const auto devices = Solid::Device::listFromType(Solid::DeviceInterface::StorageAccess);
0070     for (const Solid::Device &device : devices) {
0071         if (!device.is<Solid::StorageAccess>() || !device.is<Solid::StorageVolume>()) {
0072             continue;
0073         }
0074         const Solid::StorageAccess *partition = device.as<Solid::StorageAccess>();
0075         if (!partition) {
0076             continue;
0077         }
0078         const Solid::StorageVolume *volume = device.as<Solid::StorageVolume>();
0079         if (!volume || volume->usage() != Solid::StorageVolume::FileSystem) {
0080             continue;
0081         }
0082 
0083         QString uuidDir = QStringLiteral("/dev/disk/by-uuid/"), uuid = volume->uuid(), name;
0084         name = (QFile::exists((name = uuidDir + uuid)) || QFile::exists((name = uuidDir + uuid.toLower())) || QFile::exists((name = uuidDir + uuid.toUpper())) ? QFile::symLinkTarget(name) : QString());
0085         QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget_recover, QStringList() << QString() << name << partition->filePath() << volume->label() << volume->fsType() << KFormat().formatByteSize(volume->size()));
0086         item->setIcon(1, QIcon::fromTheme(device.icon()));
0087         item->setTextAlignment(5, Qt::AlignRight | Qt::AlignVCenter);
0088         ui->treeWidget_recover->addTopLevelItem(item);
0089         QRadioButton *radio = new QRadioButton(ui->treeWidget_recover);
0090         connect(radio, &QRadioButton::clicked, okButton, &QWidget::setEnabled);
0091         ui->treeWidget_recover->setItemWidget(item, 0, radio);
0092     }
0093 }
0094 InstallDialog::~InstallDialog()
0095 {
0096     delete ui;
0097 }
0098 
0099 void InstallDialog::slotAccepted()
0100 {
0101     Action installAction(QStringLiteral("org.kde.kcontrol.kcmgrub2.install"));
0102     installAction.setHelperId(QStringLiteral("org.kde.kcontrol.kcmgrub2"));
0103     for (int i = 0; i < ui->treeWidget_recover->topLevelItemCount(); i++) {
0104         QRadioButton *radio = qobject_cast<QRadioButton *>(ui->treeWidget_recover->itemWidget(ui->treeWidget_recover->topLevelItem(i), 0));
0105         if (radio && radio->isChecked()) {
0106             installAction.addArgument(QStringLiteral("partition"), ui->treeWidget_recover->topLevelItem(i)->text(1));
0107             installAction.addArgument(QStringLiteral("mountPoint"), ui->treeWidget_recover->topLevelItem(i)->text(2));
0108             installAction.addArgument(QStringLiteral("mbrInstall"), !ui->checkBox_partition->isChecked());
0109             break;
0110         }
0111     }
0112     if (installAction.arguments().value(QStringLiteral("partition")).toString().isEmpty()) {
0113         KMessageBox::error(this, i18nc("@info", "Sorry, you have to select a partition with a proper name!"));
0114         return;
0115     }
0116     installAction.setParentWidget(this);
0117 
0118     KAuth::ExecuteJob *installJob = installAction.execute(KAuth::Action::AuthorizeOnlyMode);
0119     if (!installJob->exec()) {
0120         return;
0121     }
0122 
0123     QProgressDialog progressDlg(this);
0124     progressDlg.setWindowTitle(i18nc("@title:window", "Installing"));
0125     progressDlg.setLabelText(i18nc("@info:progress", "Installing GRUB..."));
0126     progressDlg.setCancelButton(nullptr);
0127     progressDlg.setModal(true);
0128     progressDlg.setMinimum(0);
0129     progressDlg.setMaximum(0);
0130     progressDlg.show();
0131     installJob = installAction.execute();
0132     connect(installJob, &KJob::finished, &progressDlg, &QWidget::hide);
0133 
0134     if (installJob->exec()) {
0135         QDialog *dialog = new QDialog(this);
0136         dialog->setWindowTitle(i18nc("@title:window", "Information"));
0137         dialog->setModal(true);
0138         dialog->setAttribute(Qt::WA_DeleteOnClose);
0139 
0140         QPushButton *detailsButton = new QPushButton;
0141         detailsButton->setObjectName(QStringLiteral("detailsButton"));
0142         detailsButton->setText(QApplication::translate("KMessageBox", "&Details") + QStringLiteral(" >>"));
0143         detailsButton->setIcon(QIcon::fromTheme(QStringLiteral("help-about")));
0144 
0145         QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
0146         buttonBox->addButton(detailsButton, QDialogButtonBox::HelpRole);
0147         buttonBox->addButton(QDialogButtonBox::Ok);
0148         buttonBox->button(QDialogButtonBox::Ok)->setFocus();
0149 
0150         KMessageBox::createKMessageBox(dialog, buttonBox, QMessageBox::Information, i18nc("@info", "Successfully installed GRUB."),
0151                                        QStringList(), QString(), nullptr, KMessageBox::Notify,
0152                                        QString::fromUtf8(installJob->data().value(QStringLiteral("output")).toByteArray())); // krazy:exclude=qclasses
0153     } else {
0154         KMessageBox::detailedError(this, i18nc("@info", "Failed to install GRUB."), installJob->errorText());
0155     }
0156 
0157     accept();
0158 }