File indexing completed on 2024-04-14 05:38:11
0001 /*************************************************************************** 0002 * Copyright (C) 2008-2018 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 <config.h> 0022 0023 #include "PkTransaction.h" 0024 0025 #include <KLocalizedString> 0026 #include <KMessageBox> 0027 #include <QPushButton> 0028 #include <KPixmapSequence> 0029 #include <KConfig> 0030 #include <KConfigGroup> 0031 0032 #include <QLoggingCategory> 0033 0034 #include <QtDBus/QDBusMessage> 0035 #include <QtDBus/QDBusConnection> 0036 #include <QTreeView> 0037 0038 #include <Daemon> 0039 0040 #include "Enum.h" 0041 #include "PkStrings.h" 0042 #include "RepoSig.h" 0043 #include "LicenseAgreement.h" 0044 #include "PkIcons.h" 0045 #include "ApplicationLauncher.h" 0046 #include "PackageModel.h" 0047 #include "Requirements.h" 0048 #include "PkTransactionProgressModel.h" 0049 #include "PkTransactionWidget.h" 0050 0051 Q_DECLARE_LOGGING_CATEGORY(APPER_LIB) 0052 0053 class PkTransactionPrivate 0054 { 0055 public: 0056 bool allowDeps; 0057 bool jobWatcher; 0058 bool handlingActionRequired; 0059 bool showingError; //This might replace the above 0060 qulonglong downloadSizeRemaining; 0061 PkTransaction::ExitStatus exitStatus; 0062 Transaction::Status status; 0063 Transaction::TransactionFlags flags; 0064 Transaction::Role originalRole; 0065 Transaction::Error error; 0066 Transaction::Role role; 0067 QStringList packages; 0068 ApplicationLauncher *launcher; 0069 QStringList files; 0070 QStringList newPackages; 0071 PackageModel *simulateModel; 0072 PkTransactionProgressModel *progressModel; 0073 QWidget *parentWindow; 0074 QDBusObjectPath tid; 0075 Transaction *transaction; 0076 }; 0077 0078 PkTransaction::PkTransaction(QObject *parent) : 0079 QObject(parent), 0080 d(new PkTransactionPrivate) 0081 { 0082 // for sanity we are finished till some transaction is set 0083 d->allowDeps = false; 0084 d->jobWatcher = false; 0085 d->handlingActionRequired = false; 0086 d->showingError = false; 0087 d->downloadSizeRemaining = 0; 0088 d->exitStatus = Success; 0089 d->status = Transaction::StatusUnknown; 0090 // for sanity we are trusted till an error is given and the user accepts 0091 d->flags = Transaction::TransactionFlagOnlyTrusted; 0092 d->originalRole = Transaction::RoleUnknown; 0093 d->role = Transaction::RoleUnknown; 0094 d->error = Transaction::ErrorUnknown; 0095 d->launcher = nullptr; 0096 d->simulateModel = nullptr; 0097 d->progressModel = new PkTransactionProgressModel(this); 0098 d->parentWindow = qobject_cast<QWidget*>(parent); 0099 d->transaction = nullptr; 0100 } 0101 0102 PkTransaction::~PkTransaction() 0103 { 0104 // DO NOT disconnect the transaction here, 0105 // it might not exist when this happen 0106 delete d; 0107 } 0108 0109 void PkTransaction::installFiles(const QStringList &files) 0110 { 0111 // if (Daemon::global()->roles() & Transaction::RoleInstallFiles) { 0112 d->originalRole = Transaction::RoleInstallFiles; 0113 d->files = files; 0114 d->flags = Transaction::TransactionFlagOnlyTrusted | Transaction::TransactionFlagSimulate; 0115 0116 setupTransaction(Daemon::installFiles(files, d->flags)); 0117 // } else { 0118 // showError(i18n("Current backend does not support installing files."), i18n("Error")); 0119 // } 0120 } 0121 0122 void PkTransaction::installPackages(const QStringList &packages) 0123 { 0124 // if (Daemon::global()->roles() & Transaction::RoleInstallPackages) { 0125 d->originalRole = Transaction::RoleInstallPackages; 0126 d->packages = packages; 0127 d->flags = Transaction::TransactionFlagOnlyTrusted | Transaction::TransactionFlagSimulate; 0128 0129 setupTransaction(Daemon::installPackages(d->packages, d->flags)); 0130 // } else { 0131 // showError(i18n("Current backend does not support installing packages."), i18n("Error")); 0132 // } 0133 } 0134 0135 void PkTransaction::removePackages(const QStringList &packages) 0136 { 0137 // if (Daemon::global()->roles() & Transaction::RoleRemovePackages) { 0138 d->originalRole = Transaction::RoleRemovePackages; 0139 d->allowDeps = true; // *was* false, Default to avoid dependencies removal unless simulate says so, except for https://bugs.kde.org/show_bug.cgi?id=315063 0140 d->packages = packages; 0141 d->flags = Transaction::TransactionFlagOnlyTrusted | Transaction::TransactionFlagSimulate; 0142 0143 setupTransaction(Daemon::removePackages(d->packages, d->allowDeps, AUTOREMOVE, d->flags)); 0144 // } else { 0145 // showError(i18n("The current backend does not support removing packages."), i18n("Error")); 0146 // } 0147 } 0148 0149 void PkTransaction::updatePackages(const QStringList &packages, bool downloadOnly) 0150 { 0151 // if (Daemon::global()->roles() & Transaction::RoleUpdatePackages) { 0152 d->originalRole = Transaction::RoleUpdatePackages; 0153 d->packages = packages; 0154 if (downloadOnly) { 0155 // Don't simulate if we are just downloading 0156 d->flags = Transaction::TransactionFlagOnlyDownload; 0157 } else { 0158 d->flags = Transaction::TransactionFlagOnlyTrusted | Transaction::TransactionFlagSimulate; 0159 } 0160 0161 setupTransaction(Daemon::updatePackages(d->packages, d->flags)); 0162 // } else { 0163 // showError(i18n("The current backend does not support updating packages."), i18n("Error")); 0164 // } 0165 } 0166 0167 void PkTransaction::refreshCache(bool force) 0168 { 0169 setupTransaction(Daemon::refreshCache(force)); 0170 } 0171 0172 void PkTransaction::installPackages() 0173 { 0174 setupTransaction(Daemon::installPackages(d->packages, d->flags)); 0175 } 0176 0177 void PkTransaction::installFiles() 0178 { 0179 setupTransaction(Daemon::installFiles(d->files, d->flags)); 0180 } 0181 0182 void PkTransaction::removePackages() 0183 { 0184 setupTransaction(Daemon::removePackages(d->packages, d->allowDeps, AUTOREMOVE, d->flags)); 0185 } 0186 0187 void PkTransaction::updatePackages() 0188 { 0189 setupTransaction(Daemon::updatePackages(d->packages, d->flags)); 0190 } 0191 0192 void PkTransaction::requeueTransaction() 0193 { 0194 auto requires = qobject_cast<Requirements *>(sender()); 0195 if (requires) { 0196 // As we have requires allow deps removal 0197 d->allowDeps = true; 0198 if (!requires->trusted()) { 0199 // Set only trusted to false, to do as the user asked 0200 setTrusted(false); 0201 } 0202 } 0203 0204 // Delete the simulate model 0205 if (d->simulateModel) { 0206 d->simulateModel->deleteLater(); 0207 d->simulateModel = nullptr; 0208 } 0209 0210 // We are not handling any required action yet for the requeued transaction. 0211 // Without this a second license agreement f.e. does not get shown, 0212 // see http://bugs.kde.org/show_bug.cgi?id=326619 0213 d->handlingActionRequired = false; 0214 0215 switch (d->originalRole) { 0216 case Transaction::RoleRemovePackages: 0217 removePackages(); 0218 break; 0219 case Transaction::RoleInstallPackages: 0220 installPackages(); 0221 break; 0222 case Transaction::RoleInstallFiles: 0223 installFiles(); 0224 break; 0225 case Transaction::RoleUpdatePackages: 0226 updatePackages(); 0227 break; 0228 default : 0229 setExitStatus(Failed); 0230 return; 0231 } 0232 } 0233 0234 void PkTransaction::slotErrorCode(Transaction::Error error, const QString &details) 0235 { 0236 qCDebug(APPER_LIB) << "errorCode: " << error << details; 0237 d->error = error; 0238 0239 if (d->handlingActionRequired) { 0240 // We are already handling required actions 0241 // like eulaRequired() and repoSignatureRequired() 0242 return; 0243 } 0244 0245 switch (error) { 0246 case Transaction::ErrorTransactionCancelled: 0247 case Transaction::ErrorProcessKill: 0248 // these errors should be ignored 0249 break; 0250 case Transaction::ErrorGpgFailure: 0251 case Transaction::ErrorBadGpgSignature: 0252 case Transaction::ErrorMissingGpgSignature: 0253 case Transaction::ErrorCannotInstallRepoUnsigned: 0254 case Transaction::ErrorCannotUpdateRepoUnsigned: 0255 { 0256 if (d->role == Transaction::RoleRefreshCache) { 0257 // We are not installing anything 0258 KMessageBox::information(d->parentWindow, details, PkStrings::error(error)); 0259 return; 0260 } 0261 0262 d->handlingActionRequired = true; 0263 int ret = KMessageBox::warningYesNo(d->parentWindow, 0264 i18n("You are about to install unsigned packages that can compromise your system, " 0265 "as it is impossible to verify if the software came from a trusted " 0266 "source.\n\nAre you sure you want to proceed with the installation?"), 0267 i18n("Installing unsigned software")); 0268 if (ret == KMessageBox::Yes) { 0269 // Set only trusted to false, to do as the user asked 0270 setTrusted(false); 0271 requeueTransaction(); 0272 } else { 0273 setExitStatus(Cancelled); 0274 } 0275 d->handlingActionRequired = false; 0276 return; 0277 } 0278 default: 0279 d->showingError = true; 0280 showSorry(PkStrings::error(error), PkStrings::errorMessage(error), QString(details).replace(QLatin1Char('\n'), QLatin1String("<br>"))); 0281 0282 // when we receive an error we are done 0283 setExitStatus(Failed); 0284 } 0285 } 0286 0287 void PkTransaction::slotEulaRequired(const QString &eulaID, const QString &packageID, const QString &vendor, const QString &licenseAgreement) 0288 { 0289 if (d->handlingActionRequired) { 0290 // if its true means that we alread passed here 0291 d->handlingActionRequired = false; 0292 return; 0293 } else { 0294 d->handlingActionRequired = true; 0295 } 0296 0297 auto eula = new LicenseAgreement(eulaID, packageID, vendor, licenseAgreement, d->parentWindow); 0298 connect(eula, &LicenseAgreement::accepted, this, [this, eula] () { 0299 qCDebug(APPER_LIB) << "Accepting EULA" << eula->id(); 0300 setupTransaction(Daemon::acceptEula(eula->id())); 0301 }); 0302 connect(eula, &LicenseAgreement::rejected, this, &PkTransaction::reject); 0303 showDialog(eula); 0304 } 0305 0306 void PkTransaction::slotChanged() 0307 { 0308 auto transaction = qobject_cast<Transaction*>(sender()); 0309 d->downloadSizeRemaining = transaction->downloadSizeRemaining(); 0310 d->role = transaction->role(); 0311 0312 if (!d->jobWatcher) { 0313 return; 0314 } 0315 0316 QDBusObjectPath _tid = transaction->tid(); 0317 if (d->tid != _tid && !(d->flags & Transaction::TransactionFlagSimulate)) { 0318 d->tid = _tid; 0319 // if the transaction changed and 0320 // the user wants the watcher send the tid 0321 QDBusMessage message; 0322 message = QDBusMessage::createMethodCall(QLatin1String("org.kde.apperd"), 0323 QLatin1String("/"), 0324 QLatin1String("org.kde.apperd"), 0325 QLatin1String("WatchTransaction")); 0326 // Use our own cached tid to avoid crashes 0327 message << qVariantFromValue(_tid); 0328 if (!QDBusConnection::sessionBus().send(message)) { 0329 qCWarning(APPER_LIB) << "Failed to put WatchTransaction on the DBus queue"; 0330 } 0331 } 0332 } 0333 0334 void PkTransaction::slotMediaChangeRequired(Transaction::MediaType type, const QString &id, const QString &text) 0335 { 0336 Q_UNUSED(id) 0337 0338 d->handlingActionRequired = true; 0339 int ret = KMessageBox::questionYesNo(d->parentWindow, 0340 PkStrings::mediaMessage(type, text), 0341 i18n("A media change is required"), 0342 KStandardGuiItem::cont(), 0343 KStandardGuiItem::cancel()); 0344 d->handlingActionRequired = false; 0345 0346 // if the user clicked continue we got yes 0347 if (ret == KMessageBox::Yes) { 0348 requeueTransaction(); 0349 } else { 0350 setExitStatus(Cancelled); 0351 } 0352 } 0353 0354 void PkTransaction::slotRepoSignature(const QString &packageID, 0355 const QString &repoName, 0356 const QString &keyUrl, 0357 const QString &keyUserid, 0358 const QString &keyId, 0359 const QString &keyFingerprint, 0360 const QString &keyTimestamp, 0361 Transaction::SigType type) 0362 { 0363 if (d->handlingActionRequired) { 0364 // if its true means that we alread passed here 0365 d->handlingActionRequired = false; 0366 return; 0367 } else { 0368 d->handlingActionRequired = true; 0369 } 0370 0371 auto repoSig = new RepoSig(packageID, repoName, keyUrl, keyUserid, keyId, keyFingerprint, keyTimestamp, type, d->parentWindow); 0372 connect(repoSig, &RepoSig::accepted, this, [this, repoSig] () { 0373 qCDebug(APPER_LIB) << "Installing Signature" << repoSig->keyID(); 0374 setupTransaction(Daemon::installSignature(repoSig->sigType(), repoSig->keyID(), repoSig->packageID())); 0375 }); 0376 connect(repoSig, &RepoSig::rejected, this, &PkTransaction::reject); 0377 showDialog(repoSig); 0378 } 0379 0380 void PkTransaction::slotFinished(Transaction::Exit status) 0381 { 0382 // Clear the model to don't keep trash when reusing the transaction 0383 d->progressModel->clear(); 0384 0385 Requirements *requires = nullptr; 0386 Transaction::Role _role = qobject_cast<Transaction*>(sender())->role(); 0387 d->transaction = nullptr; // Will be deleted later 0388 qCDebug(APPER_LIB) << status << _role; 0389 0390 switch (_role) { 0391 case Transaction::RoleInstallSignature: 0392 case Transaction::RoleAcceptEula: 0393 if (status == Transaction::ExitSuccess) { 0394 // if the required action was performed with success 0395 // requeue our main transaction 0396 requeueTransaction(); 0397 return; 0398 } 0399 break; 0400 default: 0401 break; 0402 } 0403 0404 switch(status) { 0405 case Transaction::ExitSuccess: 0406 // Check if we are just simulating 0407 if (d->flags & Transaction::TransactionFlagSimulate) { 0408 // Disable the simulate flag 0409 d->flags ^= Transaction::TransactionFlagSimulate; 0410 d->simulateModel->finished(); 0411 0412 // Remove the transaction packages 0413 for (const QString &packageID : qAsConst(d->packages)) { 0414 d->simulateModel->removePackage(packageID); 0415 } 0416 0417 d->newPackages = d->simulateModel->packagesWithInfo(Transaction::InfoInstalling); 0418 if (_role == Transaction::RoleInstallPackages) { 0419 d->newPackages << d->packages; 0420 d->newPackages.removeDuplicates(); 0421 } 0422 0423 requires = new Requirements(d->simulateModel, d->parentWindow); 0424 requires->setDownloadSizeRemaining(d->downloadSizeRemaining); 0425 connect(requires, &Requirements::accepted, this, &PkTransaction::requeueTransaction); 0426 connect(requires, &Requirements::rejected, this, &PkTransaction::reject); 0427 if (requires->shouldShow()) { 0428 showDialog(requires); 0429 } else { 0430 requires->deleteLater(); 0431 0432 // Since we removed the Simulate Flag this will procced 0433 // with the actual action 0434 requeueTransaction(); 0435 } 0436 } else { 0437 KConfig config(QLatin1String("apper")); 0438 KConfigGroup transactionGroup(&config, "Transaction"); 0439 bool showApp = transactionGroup.readEntry("ShowApplicationLauncher", true); 0440 if (showApp && 0441 !d->newPackages.isEmpty() && 0442 (_role == Transaction::RoleInstallPackages || 0443 _role == Transaction::RoleInstallFiles || 0444 _role == Transaction::RoleRemovePackages || 0445 _role == Transaction::RoleUpdatePackages)) { 0446 // When installing files or updates that involves new packages 0447 // try to resolve the available packages at simulation time 0448 // to maybe show the user the new applications that where installed 0449 if (d->launcher) { 0450 delete d->launcher; 0451 } 0452 d->launcher = new ApplicationLauncher(d->parentWindow); 0453 connect(d->transaction, &Transaction::files, d->launcher, &ApplicationLauncher::files); 0454 0455 setupTransaction(Daemon::getFiles(d->newPackages)); 0456 d->newPackages.clear(); 0457 return; // avoid the exit code 0458 } else if (_role == Transaction::RoleGetFiles && 0459 d->launcher && 0460 d->launcher->hasApplications()) { 0461 // if we have a launcher and the laucher has applications 0462 // show them to the user 0463 showDialog(d->launcher); 0464 connect(d->launcher, &ApplicationLauncher::finished, this, &PkTransaction::setExitStatus); 0465 return; 0466 } 0467 setExitStatus(Success); 0468 } 0469 break; 0470 case Transaction::ExitNeedUntrusted: 0471 case Transaction::ExitKeyRequired: 0472 case Transaction::ExitEulaRequired: 0473 case Transaction::ExitMediaChangeRequired: 0474 qCDebug(APPER_LIB) << "finished KeyRequired or EulaRequired: " << status; 0475 if (!d->handlingActionRequired) { 0476 qCDebug(APPER_LIB) << "Not Handling Required Action"; 0477 setExitStatus(Failed); 0478 } 0479 break; 0480 case Transaction::ExitCancelled: 0481 // Avoid crash in case we are showing an error 0482 if (!d->showingError) { 0483 setExitStatus(Cancelled); 0484 } 0485 break; 0486 case Transaction::ExitFailed: 0487 if (!d->handlingActionRequired && !d->showingError) { 0488 qCDebug(APPER_LIB) << "Yep, we failed."; 0489 setExitStatus(Failed); 0490 } 0491 break; 0492 default : 0493 qCDebug(APPER_LIB) << "finished default" << status; 0494 setExitStatus(Failed); 0495 break; 0496 } 0497 } 0498 0499 PkTransaction::ExitStatus PkTransaction::exitStatus() const 0500 { 0501 return d->exitStatus; 0502 } 0503 0504 bool PkTransaction::isFinished() const 0505 { 0506 qCDebug(APPER_LIB) << d->transaction->status() << d->transaction->role(); 0507 return d->transaction->status() == Transaction::StatusFinished; 0508 } 0509 0510 PackageModel *PkTransaction::simulateModel() const 0511 { 0512 return d->simulateModel; 0513 } 0514 0515 uint PkTransaction::percentage() const 0516 { 0517 if (d->transaction) { 0518 return d->transaction->percentage(); 0519 } 0520 return 0; 0521 } 0522 0523 uint PkTransaction::remainingTime() const 0524 { 0525 if (d->transaction) { 0526 return d->transaction->remainingTime(); 0527 } 0528 return 0; 0529 } 0530 0531 uint PkTransaction::speed() const 0532 { 0533 if (d->transaction) { 0534 return d->transaction->speed(); 0535 } 0536 return 0; 0537 } 0538 0539 qulonglong PkTransaction::downloadSizeRemaining() const 0540 { 0541 if (d->transaction) { 0542 return d->transaction->downloadSizeRemaining(); 0543 } 0544 return 0; 0545 } 0546 0547 Transaction::Status PkTransaction::status() const 0548 { 0549 if (d->transaction) { 0550 return d->transaction->status(); 0551 } 0552 return Transaction::StatusUnknown; 0553 } 0554 0555 Transaction::Role PkTransaction::role() const 0556 { 0557 if (d->transaction) { 0558 return d->transaction->role(); 0559 } 0560 return Transaction::RoleUnknown; 0561 } 0562 0563 bool PkTransaction::allowCancel() const 0564 { 0565 if (d->transaction) { 0566 return d->transaction->allowCancel(); 0567 } 0568 return false; 0569 } 0570 0571 Transaction::TransactionFlags PkTransaction::transactionFlags() const 0572 { 0573 if (d->transaction) { 0574 return d->transaction->transactionFlags(); 0575 } 0576 return Transaction::TransactionFlagNone; 0577 } 0578 0579 void PkTransaction::getUpdateDetail(const QString &packageID) 0580 { 0581 setupTransaction(Daemon::getUpdateDetail(packageID)); 0582 } 0583 0584 void PkTransaction::getUpdates() 0585 { 0586 setupTransaction(Daemon::getUpdates()); 0587 } 0588 0589 void PkTransaction::cancel() 0590 { 0591 if (d->transaction) { 0592 d->transaction->cancel(); 0593 } 0594 } 0595 0596 void PkTransaction::setTrusted(bool trusted) 0597 { 0598 if (trusted) { 0599 d->flags |= Transaction::TransactionFlagOnlyTrusted; 0600 } else { 0601 d->flags ^= Transaction::TransactionFlagOnlyTrusted; 0602 } 0603 } 0604 0605 void PkTransaction::setExitStatus(int status) 0606 { 0607 qCDebug(APPER_LIB) << status; 0608 if (d->launcher) { 0609 d->launcher->deleteLater(); 0610 d->launcher = nullptr; 0611 } 0612 0613 d->exitStatus = static_cast<PkTransaction::ExitStatus>(status); 0614 if (!d->handlingActionRequired || !d->showingError) { 0615 emit finished(d->exitStatus); 0616 } 0617 } 0618 0619 void PkTransaction::reject() 0620 { 0621 setExitStatus(Cancelled); 0622 } 0623 0624 void PkTransaction::setupTransaction(Transaction *transaction) 0625 { 0626 // Clear the model to don't keep trash when reusing the transaction 0627 d->progressModel->clear(); 0628 0629 d->transaction = transaction; 0630 if (!(transaction->transactionFlags() & Transaction::TransactionFlagSimulate) && 0631 transaction->role() != Transaction::RoleGetUpdates && 0632 transaction->role() != Transaction::RoleGetUpdateDetail) { 0633 connect(transaction, &Transaction::repoDetail, d->progressModel, &PkTransactionProgressModel::currentRepo); 0634 connect(transaction, &Transaction::package, d->progressModel, &PkTransactionProgressModel::currentPackage); 0635 connect(transaction, &Transaction::itemProgress, d->progressModel, &PkTransactionProgressModel::itemProgress); 0636 } 0637 0638 connect(transaction, &Transaction::updateDetail, this, &PkTransaction::updateDetail); 0639 connect(transaction, &Transaction::package, this, &PkTransaction::package); 0640 connect(transaction, &Transaction::errorCode, this, &PkTransaction::errorCode); 0641 0642 // Required actions 0643 connect(transaction, &Transaction::allowCancelChanged, this, &PkTransaction::allowCancelChanged); 0644 connect(transaction, &Transaction::downloadSizeRemainingChanged, this, &PkTransaction::downloadSizeRemainingChanged); 0645 connect(transaction, &Transaction::elapsedTimeChanged, this, &PkTransaction::elapsedTimeChanged); 0646 connect(transaction, &Transaction::isCallerActiveChanged, this, &PkTransaction::isCallerActiveChanged); 0647 connect(transaction, &Transaction::lastPackageChanged, this, &PkTransaction::lastPackageChanged); 0648 connect(transaction, &Transaction::percentageChanged, this, &PkTransaction::percentageChanged); 0649 connect(transaction, &Transaction::remainingTimeChanged, this, &PkTransaction::remainingTimeChanged); 0650 connect(transaction, &Transaction::roleChanged, this, &PkTransaction::roleChanged); 0651 connect(transaction, &Transaction::speedChanged, this, &PkTransaction::speedChanged); 0652 connect(transaction, &Transaction::statusChanged, this, &PkTransaction::statusChanged); 0653 connect(transaction, &Transaction::transactionFlagsChanged, this, &PkTransaction::transactionFlagsChanged); 0654 connect(transaction, &Transaction::uidChanged, this, &PkTransaction::uidChanged); 0655 0656 connect(transaction, &Transaction::downloadSizeRemainingChanged, this, &PkTransaction::slotChanged); 0657 connect(transaction, &Transaction::errorCode, this, &PkTransaction::slotErrorCode); 0658 connect(transaction, &Transaction::eulaRequired, this, &PkTransaction::slotEulaRequired); 0659 connect(transaction, &Transaction::mediaChangeRequired, this, &PkTransaction::slotMediaChangeRequired); 0660 connect(transaction, &Transaction::repoSignatureRequired, this, &PkTransaction::slotRepoSignature); 0661 0662 connect(transaction, &Transaction::finished, this, &PkTransaction::slotFinished); 0663 0664 if (d->flags & Transaction::TransactionFlagSimulate) { 0665 d->simulateModel = new PackageModel(this); 0666 connect(d->transaction, &Transaction::package, d->simulateModel, &PackageModel::addNotSelectedPackage); 0667 } 0668 0669 #ifdef HAVE_DEBCONFKDE 0670 QString _tid = transaction->tid().path(); 0671 QString socket; 0672 // Build a socket path like /tmp/1761_edeceabd_data_debconf 0673 socket = QLatin1String("/tmp") % _tid % QLatin1String("_debconf"); 0674 QDBusMessage message; 0675 message = QDBusMessage::createMethodCall(QLatin1String("org.kde.apperd"), 0676 QLatin1String("/"), 0677 QLatin1String("org.kde.apperd"), 0678 QLatin1String("SetupDebconfDialog")); 0679 // Use our own cached tid to avoid crashes 0680 message << qVariantFromValue(_tid); 0681 message << qVariantFromValue(socket); 0682 if (d->parentWindow) { 0683 message << qVariantFromValue(static_cast<uint>(d->parentWindow->effectiveWinId())); 0684 } else { 0685 message << qVariantFromValue(0u); 0686 } 0687 0688 if (!QDBusConnection::sessionBus().send(message)) { 0689 qCWarning(APPER_LIB) << "Failed to put SetupDebconfDialog message in DBus queue"; 0690 } 0691 0692 transaction->setHints(QLatin1String("frontend-socket=") % socket); 0693 #endif //HAVE_DEBCONFKDE 0694 } 0695 0696 void PkTransaction::showDialog(QDialog *dlg) 0697 { 0698 auto widget = qobject_cast<PkTransactionWidget *>(d->parentWindow); 0699 if (!widget || widget->isCancelVisible()) { 0700 dlg->setModal(d->parentWindow); 0701 dlg->show(); 0702 } else { 0703 dlg->setProperty("embedded", true); 0704 emit dialog(dlg); 0705 } 0706 } 0707 0708 void PkTransaction::showError(const QString &title, const QString &description, const QString &details) 0709 { 0710 auto widget = qobject_cast<PkTransactionWidget *>(d->parentWindow); 0711 if (!widget || widget->isCancelVisible()) { 0712 if (details.isEmpty()) { 0713 if (d->parentWindow) { 0714 KMessageBox::error(d->parentWindow, description, title); 0715 } else { 0716 KMessageBox::errorWId(0, description, title); 0717 } 0718 } else { 0719 KMessageBox::detailedError(d->parentWindow, description, details, title); 0720 } 0721 } else { 0722 emit errorMessage(title, description, details); 0723 } 0724 } 0725 0726 void PkTransaction::showSorry(const QString &title, const QString &description, const QString &details) 0727 { 0728 auto widget = qobject_cast<PkTransactionWidget *>(d->parentWindow); 0729 if (!widget || widget->isCancelVisible()) { 0730 if (details.isEmpty()) { 0731 KMessageBox::error(d->parentWindow, description, title); 0732 } else { 0733 KMessageBox::detailedError(d->parentWindow, description, details, title); 0734 } 0735 } else { 0736 emit sorry(title, description, details); 0737 } 0738 } 0739 0740 QString PkTransaction::title() const 0741 { 0742 return PkStrings::action(d->originalRole, d->flags); 0743 } 0744 0745 Transaction::Role PkTransaction::cachedRole() const 0746 { 0747 return d->role; 0748 } 0749 0750 Transaction::TransactionFlags PkTransaction::flags() const 0751 { 0752 return d->flags; 0753 } 0754 0755 PkTransactionProgressModel *PkTransaction::progressModel() const 0756 { 0757 return d->progressModel; 0758 } 0759 0760 void PkTransaction::enableJobWatcher(bool enable) 0761 { 0762 d->jobWatcher = enable; 0763 } 0764 0765 #include "moc_PkTransaction.cpp"