File indexing completed on 2024-03-24 05:47:52
0001 /*************************************************************************** 0002 * Copyright (C) 2008-2011 by Daniel Nicoletti * 0003 * dantti12@gmail.com * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; see the file COPYING. If not, write to * 0017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * 0018 * Boston, MA 02110-1301, USA. * 0019 ***************************************************************************/ 0020 0021 #include "Updater.h" 0022 #include "ui_Updater.h" 0023 0024 #include "UpdateDetails.h" 0025 #include "DistroUpgrade.h" 0026 #include "CheckableHeader.h" 0027 0028 #include <QMenu> 0029 //#include <KGenericFactory> 0030 #include <KPixmapSequence> 0031 #include <KAboutData> 0032 #include <KIconLoader> 0033 #include <KConfigGroup> 0034 0035 #include <ApplicationsDelegate.h> 0036 #include <PkStrings.h> 0037 #include <PkIcons.h> 0038 #include <PackageModel.h> 0039 #include <ApplicationSortFilterModel.h> 0040 0041 #include <QDBusConnection> 0042 0043 #include <KConfig> 0044 #include <KFormat> 0045 #include <KMessageBox> 0046 #include <QLoggingCategory> 0047 0048 #include <Daemon> 0049 0050 Q_DECLARE_LOGGING_CATEGORY(APPER) 0051 0052 Updater::Updater(Transaction::Roles roles, QWidget *parent) : 0053 QWidget(parent), 0054 ui(new Ui::Updater), 0055 m_roles(roles) 0056 { 0057 ui->setupUi(this); 0058 updatePallete(); 0059 // connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), 0060 // this, SLOT(updatePallete())); 0061 0062 m_updatesModel = new PackageModel(this); 0063 m_updatesModel->setCheckable(true); 0064 auto proxyModel = new ApplicationSortFilterModel(this); 0065 proxyModel->setSourceModel(m_updatesModel); 0066 ui->packageView->setModel(proxyModel); 0067 0068 m_delegate = new ApplicationsDelegate(ui->packageView); 0069 m_delegate->setCheckable(true); 0070 ui->packageView->setItemDelegate(m_delegate); 0071 ui->packageView->sortByColumn(PackageModel::NameCol, Qt::AscendingOrder); 0072 connect(m_updatesModel, &PackageModel::changed, this, &Updater::checkEnableUpdateButton); 0073 0074 //initialize the model, delegate, client and connect it's signals 0075 m_header = new CheckableHeader(Qt::Horizontal, this); 0076 connect(m_header, &CheckableHeader::toggled, m_updatesModel, &PackageModel::setAllChecked); 0077 m_header->setCheckBoxVisible(false); 0078 m_header->setDefaultAlignment(Qt::AlignCenter); 0079 ui->packageView->setHeaderHidden(false); 0080 ui->packageView->setHeader(m_header); 0081 0082 // This must be set AFTER the model is set, otherwise it doesn't work 0083 m_header->setSectionResizeMode(PackageModel::NameCol, QHeaderView::Stretch); 0084 m_header->setSectionResizeMode(PackageModel::VersionCol, QHeaderView::ResizeToContents); 0085 m_header->setSectionResizeMode(PackageModel::CurrentVersionCol, QHeaderView::ResizeToContents); 0086 m_header->setSectionResizeMode(PackageModel::ArchCol, QHeaderView::ResizeToContents); 0087 m_header->setSectionResizeMode(PackageModel::OriginCol, QHeaderView::ResizeToContents); 0088 m_header->setSectionResizeMode(PackageModel::SizeCol, QHeaderView::ResizeToContents); 0089 m_header->setStretchLastSection(false); 0090 0091 // Setup the busy cursor 0092 m_busySeq = new KPixmapSequenceOverlayPainter(this); 0093 m_busySeq->setSequence(KIconLoader::global()->loadPixmapSequence(QLatin1String("process-working"), KIconLoader::SizeSmallMedium)); 0094 m_busySeq->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 0095 m_busySeq->setWidget(ui->packageView->viewport()); 0096 0097 // hide distro Upgrade container and line 0098 ui->distroUpgrade->hide(); 0099 0100 KConfig config(QLatin1String("apper")); 0101 KConfigGroup viewGroup(&config, "UpdateView"); 0102 0103 // versions 0104 ui->packageView->header()->setSectionHidden(PackageModel::VersionCol, true); 0105 m_showPackageVersion = new QAction(i18n("Show Versions"), this); 0106 m_showPackageVersion->setCheckable(true); 0107 connect(m_showPackageVersion, &QAction::toggled, this, &Updater::showVersions); 0108 m_showPackageVersion->setChecked(viewGroup.readEntry("ShowVersions", true)); 0109 0110 // versions 0111 ui->packageView->header()->setSectionHidden(PackageModel::CurrentVersionCol, true); 0112 m_showPackageCurrentVersion = new QAction(i18n("Show Current Versions"), this); 0113 m_showPackageCurrentVersion->setCheckable(true); 0114 connect(m_showPackageCurrentVersion, &QAction::toggled, this, &Updater::showCurrentVersions); 0115 m_showPackageCurrentVersion->setChecked(viewGroup.readEntry("ShowCurrentVersions", false)); 0116 0117 // Arch 0118 ui->packageView->header()->setSectionHidden(PackageModel::ArchCol, true); 0119 m_showPackageArch = new QAction(i18n("Show Architectures"), this); 0120 m_showPackageArch->setCheckable(true); 0121 connect(m_showPackageArch, &QAction::toggled, this, &Updater::showArchs); 0122 m_showPackageArch->setChecked(viewGroup.readEntry("ShowArchs", false)); 0123 0124 // Origin 0125 ui->packageView->header()->setSectionHidden(PackageModel::OriginCol, true); 0126 m_showPackageOrigin = new QAction(i18n("Show Origins"), this); 0127 m_showPackageOrigin->setCheckable(true); 0128 connect(m_showPackageOrigin, &QAction::toggled, this, &Updater::showOrigins); 0129 m_showPackageOrigin->setChecked(viewGroup.readEntry("ShowOrigins", false)); 0130 0131 // Sizes 0132 ui->packageView->header()->setSectionHidden(PackageModel::SizeCol, true); 0133 m_showPackageSize = new QAction(i18n("Show Sizes"), this); 0134 m_showPackageSize->setCheckable(true); 0135 connect(m_showPackageSize, &QAction::toggled, this, &Updater::showSizes); 0136 m_showPackageSize->setChecked(viewGroup.readEntry("ShowSizes", true)); 0137 } 0138 0139 Updater::~Updater() 0140 { 0141 delete ui; 0142 } 0143 0144 void Updater::showVersions(bool enabled) 0145 { 0146 KConfig config(QLatin1String("apper")); 0147 KConfigGroup viewGroup(&config, "UpdateView"); 0148 viewGroup.writeEntry("ShowVersions", enabled); 0149 ui->packageView->header()->setSectionHidden(PackageModel::VersionCol, !enabled); 0150 } 0151 0152 void Updater::showCurrentVersions(bool enabled) 0153 { 0154 KConfig config(QLatin1String("apper")); 0155 KConfigGroup viewGroup(&config, "UpdateView"); 0156 viewGroup.writeEntry("ShowCurrentVersions", enabled); 0157 ui->packageView->header()->setSectionHidden(PackageModel::CurrentVersionCol, !enabled); 0158 if (enabled) { 0159 m_updatesModel->fetchCurrentVersions(); 0160 } 0161 } 0162 0163 void Updater::showArchs(bool enabled) 0164 { 0165 KConfig config(QLatin1String("apper")); 0166 KConfigGroup viewGroup(&config, "UpdateView"); 0167 viewGroup.writeEntry("ShowArchs", enabled); 0168 ui->packageView->header()->setSectionHidden(PackageModel::ArchCol, !enabled); 0169 } 0170 0171 void Updater::showOrigins(bool enabled) 0172 { 0173 KConfig config(QLatin1String("apper")); 0174 KConfigGroup viewGroup(&config, "UpdateView"); 0175 viewGroup.writeEntry("showOrigins", enabled); 0176 ui->packageView->header()->setSectionHidden(PackageModel::OriginCol, !enabled); 0177 } 0178 0179 void Updater::showSizes(bool enabled) 0180 { 0181 KConfig config(QLatin1String("apper")); 0182 KConfigGroup viewGroup(&config, "UpdateView"); 0183 viewGroup.writeEntry("ShowSizes", enabled); 0184 ui->packageView->header()->setSectionHidden(PackageModel::SizeCol, !enabled); 0185 if (enabled) { 0186 m_updatesModel->fetchSizes(); 0187 } 0188 } 0189 0190 void Updater::updatePallete() 0191 { 0192 QPalette pal; 0193 pal.setColor(QPalette::Window, pal.base().color()); 0194 pal.setColor(QPalette::WindowText, pal.text().color()); 0195 ui->backgroundFrame->setPalette(pal); 0196 } 0197 0198 void Updater::on_packageView_clicked(const QModelIndex &index) 0199 { 0200 QString pkgId = index.data(PackageModel::IdRole).toString(); 0201 auto pkgInfo = index.data(PackageModel::InfoRole).value<Transaction::Info>(); 0202 ui->updateDetails->setPackage(pkgId, pkgInfo); 0203 } 0204 0205 //TODO: We should add some kind of configuration to let users show unstable distributions 0206 //That way, by default, users only see stable ones. 0207 void Updater::distroUpgrade(PackageKit::Transaction::DistroUpgrade type, const QString &name, const QString &description) 0208 { 0209 // TODO name should be used to do a upgrade to a different type 0210 Q_UNUSED(name) 0211 if (type != Transaction::DistroUpgradeStable) { 0212 // Ignore unstable distros upgrades for now 0213 return; 0214 } 0215 0216 ui->distroUpgrade->setName(description); 0217 ui->distroUpgrade->animatedShow(); 0218 } 0219 0220 bool Updater::hasChanges() const 0221 { 0222 return m_updatesModel->hasChanges(); 0223 } 0224 0225 void Updater::checkEnableUpdateButton() 0226 { 0227 qCDebug(APPER) << "updates has changes" << hasChanges(); 0228 emit changed(hasChanges()); 0229 int selectedSize = m_updatesModel->selectedPackagesToInstall().size(); 0230 int updatesSize = m_updatesModel->rowCount(); 0231 if (selectedSize == 0) { 0232 m_header->setCheckState(Qt::Unchecked); 0233 } else if (selectedSize == updatesSize) { 0234 m_header->setCheckState(Qt::Checked); 0235 } else { 0236 m_header->setCheckState(Qt::PartiallyChecked); 0237 } 0238 0239 unsigned long dwSize = m_updatesModel->downloadSize(); 0240 if (dwSize) { 0241 emit downloadSize(i18n("Estimated download size: %1", 0242 KFormat().formatByteSize(dwSize))); 0243 } else { 0244 emit downloadSize(QString()); 0245 } 0246 // if we don't have any upates let's disable the button 0247 m_header->setCheckBoxVisible(m_updatesModel->rowCount() != 0); 0248 ui->packageView->setHeaderHidden(m_updatesModel->rowCount() == 0); 0249 } 0250 0251 void Updater::load() 0252 { 0253 // set focus on the updates view 0254 ui->packageView->setFocus(Qt::OtherFocusReason); 0255 emit downloadSize(QString()); 0256 // If the model already has some packages 0257 // let's just clear the selection 0258 if (m_updatesModel->rowCount()) { 0259 m_updatesModel->setAllChecked(false); 0260 } else { 0261 getUpdates(); 0262 } 0263 } 0264 0265 void Updater::getUpdatesFinished() 0266 { 0267 m_updatesT = nullptr; 0268 m_updatesModel->clearSelectedNotPresent(); 0269 checkEnableUpdateButton(); 0270 if (m_updatesModel->rowCount() == 0) { 0271 // Set the info page 0272 ui->stackedWidget->setCurrentIndex(1); 0273 uint lastTime = Daemon::global()->getTimeSinceAction(Transaction::RoleRefreshCache); 0274 ui->titleL->setText(PkStrings::lastCacheRefreshTitle(lastTime)); 0275 ui->descriptionL->setText(PkStrings::lastCacheRefreshSubTitle(lastTime)); 0276 ui->iconL->setPixmap(QIcon::fromTheme(PkIcons::lastCacheRefreshIconName(lastTime)).pixmap(128, 128)); 0277 } 0278 } 0279 0280 QStringList Updater::packagesToUpdate() const 0281 { 0282 return m_updatesModel->selectedPackagesToInstall(); 0283 } 0284 0285 void Updater::getUpdates() 0286 { 0287 if (m_updatesT) { 0288 // There is a getUpdates running ignore this call 0289 return; 0290 } 0291 0292 if (ui->stackedWidget->currentIndex() != 0) { 0293 ui->stackedWidget->setCurrentIndex(0); 0294 } 0295 0296 // clears the model 0297 ui->packageView->setHeaderHidden(true); 0298 m_updatesModel->clear(); 0299 ui->updateDetails->hide(); 0300 m_updatesT = Daemon::getUpdates(); 0301 connect(m_updatesT, &Transaction::package, m_updatesModel, &PackageModel::addSelectedPackage); 0302 connect(m_updatesT, &Transaction::errorCode, this, &Updater::errorCode); 0303 connect(m_updatesT, &Transaction::finished, m_busySeq, &KPixmapSequenceOverlayPainter::stop); 0304 connect(m_updatesT, &Transaction::finished, m_updatesModel, &PackageModel::finished); 0305 0306 // This is required to estimate download size 0307 connect(m_updatesT, &Transaction::finished, m_updatesModel, &PackageModel::fetchSizes); 0308 0309 if (m_showPackageCurrentVersion->isChecked()) { 0310 connect(m_updatesT, &Transaction::finished, m_updatesModel, &PackageModel::fetchCurrentVersions); 0311 } 0312 connect(m_updatesT, &Transaction::finished, this, &Updater::getUpdatesFinished); 0313 m_busySeq->start(); 0314 0315 // Hide the distribution upgrade information 0316 ui->distroUpgrade->animatedHide(); 0317 0318 if (m_roles & Transaction::RoleGetDistroUpgrades) { 0319 // Check for distribution Upgrades 0320 Transaction *t = Daemon::getDistroUpgrades(); 0321 connect(m_updatesT, &Transaction::distroUpgrade, this, &Updater::distroUpgrade); 0322 connect(m_updatesT, &Transaction::finished, t, &Transaction::deleteLater); 0323 } 0324 } 0325 0326 void Updater::on_packageView_customContextMenuRequested(const QPoint &pos) 0327 { 0328 auto menu = new QMenu(this); 0329 menu->addAction(m_showPackageVersion); 0330 menu->addAction(m_showPackageCurrentVersion); 0331 menu->addAction(m_showPackageArch); 0332 menu->addAction(m_showPackageOrigin); 0333 menu->addAction(m_showPackageSize); 0334 QAction *action; 0335 action = menu->addAction(i18n("Check for new updates")); 0336 action->setIcon(QIcon::fromTheme(QLatin1String("view-refresh"))); 0337 connect(action, &QAction::triggered, this, &Updater::refreshCache); 0338 menu->exec(ui->packageView->viewport()->mapToGlobal(pos)); 0339 delete menu; 0340 } 0341 0342 void Updater::errorCode(PackageKit::Transaction::Error error, const QString &details) 0343 { 0344 KMessageBox::detailedError(this, 0345 PkStrings::errorMessage(error), 0346 details, 0347 PkStrings::error(error), 0348 KMessageBox::Notify); 0349 } 0350 0351 #include "moc_Updater.cpp"