File indexing completed on 2024-03-24 05:48:39
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 //Krazy 0019 //krazy:excludeall=cpp 0020 0021 //Own 0022 #include "removeDlg.h" 0023 0024 //Qt 0025 #include <QFile> 0026 #include <QTextStream> 0027 #include <QTimer> 0028 #include <QIcon> 0029 #include <QProgressDialog> 0030 #include <QPushButton> 0031 0032 //KDE 0033 #include <KLocalizedString> 0034 #include <KMessageBox> 0035 0036 //Project 0037 #include "entry.h" 0038 0039 //Ui 0040 #include "ui_removeDlg.h" 0041 0042 RemoveDialog::RemoveDialog(const QList<Entry> &entries, QWidget *parent) : QDialog(parent) 0043 { 0044 QWidget *widget = new QWidget(this); 0045 ui = new Ui::RemoveDialog; 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, &RemoveDialog::slotAccepted); 0051 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); 0052 m_okButton = buttonBox->button(QDialogButtonBox::Ok); 0053 m_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", "Remove Old Entries")); 0061 setWindowIcon(QIcon::fromTheme(QStringLiteral("list-remove"))); 0062 0063 m_progressDlg = nullptr; 0064 0065 #if HAVE_QAPT 0066 m_backend = new QAptBackend; 0067 #elif HAVE_QPACKAGEKIT 0068 m_backend = new QPkBackend; 0069 #endif 0070 0071 detectCurrentKernelImage(); 0072 QProgressDialog progressDlg(this); 0073 progressDlg.setWindowTitle(i18nc("@title:window", "Finding Old Entries")); 0074 progressDlg.setLabelText(i18nc("@info:progress", "Finding Old Entries...")); 0075 progressDlg.setCancelButton(nullptr); 0076 progressDlg.setModal(true); 0077 progressDlg.show(); 0078 bool found = false; 0079 for (int i = 0; i < entries.size(); i++) { 0080 progressDlg.setValue(100. / entries.size() * (i + 1)); 0081 QString file = entries.at(i).kernel(); 0082 if (file.isEmpty() || file == m_currentKernelImage) { 0083 continue; 0084 } 0085 QStringList package = m_backend->ownerPackage(file); 0086 if (package.size() < 2) { 0087 continue; 0088 } 0089 found = true; 0090 const QString packageName = package.takeFirst(); 0091 const QString packageVersion = package.takeFirst(); 0092 QTreeWidgetItem *item = nullptr; 0093 for (int j = 0; j < ui->treeWidget->topLevelItemCount(); j++) { 0094 if (ui->treeWidget->topLevelItem(j)->data(0, Qt::UserRole).toString() == packageName && ui->treeWidget->topLevelItem(j)->data(0, Qt::UserRole + 1).toString() == packageVersion) { 0095 item = ui->treeWidget->topLevelItem(j); 0096 break; 0097 } 0098 } 0099 if (!item) { 0100 item = new QTreeWidgetItem(ui->treeWidget, QStringList(i18nc("@item:inlistbox", "Kernel %1", packageVersion))); 0101 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); 0102 item->setData(0, Qt::UserRole, packageName); 0103 item->setData(0, Qt::UserRole + 1, packageVersion); 0104 item->setCheckState(0, Qt::Checked); 0105 ui->treeWidget->addTopLevelItem(item); 0106 } 0107 item->addChild(new QTreeWidgetItem(QStringList(entries.at(i).prettyTitle()))); 0108 } 0109 if (found) { 0110 ui->treeWidget->expandAll(); 0111 ui->treeWidget->resizeColumnToContents(0); 0112 ui->treeWidget->setMinimumWidth(ui->treeWidget->columnWidth(0) + ui->treeWidget->sizeHintForRow(0)); 0113 connect(ui->treeWidget, &QTreeWidget::itemChanged, this, &RemoveDialog::slotItemChanged); 0114 m_okButton->setEnabled(true); 0115 } else { 0116 KMessageBox::information(this, i18nc("@info", "No removable entries were found.")); 0117 QTimer::singleShot(0, this, &QDialog::reject); 0118 } 0119 } 0120 RemoveDialog::~RemoveDialog() 0121 { 0122 delete m_backend; 0123 delete ui; 0124 } 0125 void RemoveDialog::slotAccepted() 0126 { 0127 for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) { 0128 if (ui->treeWidget->topLevelItem(i)->checkState(0) == Qt::Checked) { 0129 QString packageName = ui->treeWidget->topLevelItem(i)->data(0, Qt::UserRole).toString(); 0130 m_backend->markForRemoval(packageName); 0131 if (ui->checkBox_headers->isChecked()) { 0132 packageName.replace(QLatin1String("image"), QLatin1String("headers")); 0133 m_backend->markForRemoval(packageName); 0134 } 0135 } 0136 } 0137 if (KMessageBox::questionYesNoList(this, i18nc("@info", "Are you sure you want to remove the following packages?"), m_backend->markedForRemoval()) == KMessageBox::Yes) { 0138 #if HAVE_QAPT 0139 connect(m_backend, &QAptBackend::progress, this, &RemoveDialog::slotProgress); 0140 connect(m_backend, &QAptBackend::finished, this, &RemoveDialog::slotFinished); 0141 #elif HAVE_QPACKAGEKIT 0142 connect(m_backend, &QPkBackend::progress, this, &RemoveDialog::slotProgress); 0143 connect(m_backend, &QPkBackend::finished, this, &RemoveDialog::slotFinished); 0144 #endif 0145 m_backend->removePackages(); 0146 } else { 0147 m_backend->undoChanges(); 0148 } 0149 0150 accept(); 0151 } 0152 void RemoveDialog::slotItemChanged() 0153 { 0154 for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) { 0155 if (ui->treeWidget->topLevelItem(i)->checkState(0) == Qt::Checked) { 0156 m_okButton->setEnabled(true); 0157 return; 0158 } 0159 } 0160 m_okButton->setEnabled(false); 0161 } 0162 void RemoveDialog::slotProgress(const QString &status, int percentage) 0163 { 0164 if (!m_progressDlg) { 0165 m_progressDlg = new QProgressDialog(this); 0166 m_progressDlg->setWindowTitle(i18nc("@title:window", "Removing Old Entries")); 0167 m_progressDlg->setCancelButton(nullptr); 0168 m_progressDlg->setModal(true); 0169 m_progressDlg->show(); 0170 } 0171 m_progressDlg->setLabelText(status); 0172 m_progressDlg->setValue(percentage); 0173 } 0174 void RemoveDialog::slotFinished(bool success) 0175 { 0176 if (success) { 0177 accept(); 0178 } else { 0179 KMessageBox::error(this, i18nc("@info", "Package removal failed.")); 0180 reject(); 0181 } 0182 } 0183 void RemoveDialog::detectCurrentKernelImage() 0184 { 0185 QFile file(QStringLiteral("/proc/cmdline")); 0186 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { 0187 return; 0188 } 0189 0190 const QStringList args = QTextStream(&file).readAll().split(QRegExp(QLatin1String("\\s+"))); 0191 for (const QString &argument : args) { 0192 if (argument.startsWith(QLatin1String("BOOT_IMAGE"))) { 0193 m_currentKernelImage = argument.section(QLatin1Char('='), 1); 0194 return; 0195 } 0196 } 0197 }