File indexing completed on 2024-04-14 15:48:58

0001 /***************************************************************************
0002  *   Copyright (C) 2009-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 "SessionTask.h"
0022 #include "ui_SessionTask.h"
0023 
0024 #include "IntroDialog.h"
0025 #include "InfoWidget.h"
0026 #include "ReviewChanges.h"
0027 #include "ApplicationLauncher.h"
0028 
0029 #include <PkStrings.h>
0030 #include <PackageModel.h>
0031 #include <PkTransactionWidget.h>
0032 
0033 #include <limits.h>
0034 #include <QtDBus/QDBusConnection>
0035 #include <QTimer>
0036 #include <QStringList>
0037 #include <QFile>
0038 #include <QSignalMapper>
0039 #include <QStringBuilder>
0040 #include <QDialogButtonBox>
0041 
0042 //#include <KWindowSystem>
0043 #include <KLocalizedString>
0044 //#include <KGlobalSettings>
0045 #include <QPushButton>
0046 //#include <KGlobal>
0047 
0048 #include <QLoggingCategory>
0049 
0050 #include <Daemon>
0051 
0052 Q_DECLARE_LOGGING_CATEGORY(APPER_SESSION)
0053 
0054 using namespace PackageKit;
0055 
0056 SessionTask::SessionTask(uint xid, const QString &interaction, const QDBusMessage &message, QWidget *parent) :
0057     QDialog(parent),
0058     m_xid(xid),
0059     m_message(message),
0060     ui(new Ui::SessionTask)
0061 {
0062     ui->setupUi(this);
0063     setAttribute(Qt::WA_DeleteOnClose);
0064 
0065     m_model = new PackageModel(this);
0066 
0067 //    connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()),
0068 //            this, SLOT(updatePallete()));
0069     updatePallete();
0070 
0071     setWindowIcon(QIcon::fromTheme(QLatin1String("system-software-install")));
0072     QPushButton *okButton = ui->buttonBox->button(QDialogButtonBox::Ok);
0073     okButton->setText(i18n("Continue"));
0074     okButton->setIcon(QIcon::fromTheme(QLatin1String("go-next")));
0075     enableButtonOk(false);
0076     connect(okButton, &QPushButton::clicked, this, &SessionTask::slotContinueClicked);
0077 
0078     QPushButton *cancelButton = ui->buttonBox->button(QDialogButtonBox::Cancel);
0079     connect(cancelButton, &QPushButton::clicked, this, &SessionTask::slotCancelClicked);
0080 
0081 
0082 
0083     Daemon::global()->setHints(QLatin1String("locale=") + QLocale::system().name() + QLatin1String(".UTF-8"));
0084 
0085     // Defaults to always
0086     m_interactions = ConfirmSearch
0087                    | ConfirmDeps
0088                    | ConfirmInstall
0089                    | Progress
0090                    | Finished
0091                    | Warning;
0092     m_timeout = 0;
0093     parseInteraction(interaction);
0094 
0095     QString cmdline;
0096     uint pid;
0097     // TODO as we are running on the session it might
0098     // be useless to check the PID on the system
0099     if ((pid = getPidSession()) != UINT_MAX) {
0100         cmdline = getCmdLine(pid);
0101     } else if ((pid = getPidSystem()) != UINT_MAX) {
0102         cmdline = getCmdLine(pid);
0103     }
0104 
0105     if (!cmdline.isNull()) {
0106         setExec(cmdline);
0107     }
0108 
0109     setMinimumSize(QSize(430,280));
0110 //    KConfig config("apper");
0111 //    KConfigGroup configGroup(&config, "SessionInstaller");
0112 //    restoreDialogSize(configGroup);
0113 }
0114 
0115 SessionTask::~SessionTask()
0116 {
0117 //    KConfig config("apper");
0118 //    KConfigGroup configGroup(&config, "SessionInstaller");
0119 //    saveDialogSize(configGroup);
0120 
0121     delete ui;
0122 }
0123 
0124 void SessionTask::addPackage(Transaction::Info info, const QString &packageID, const QString &summary)
0125 {
0126     m_model->addSelectedPackage(info, packageID, summary);
0127 }
0128 
0129 void SessionTask::searchFinished(PkTransaction::ExitStatus status)
0130 {
0131     if (m_pkTransaction) {
0132         // Disconnect so it can be connected to commitFinished latter
0133         disconnect(m_pkTransaction->transaction(), &PkTransaction::finished, this, &SessionTask::searchFinished);
0134     }
0135 
0136     if (status == PkTransaction::Success) {
0137         m_model->finished();
0138         if (m_model->rowCount() == 0) {
0139             notFound();
0140             showCloseButton();
0141         } else {
0142             searchSuccess();
0143         }
0144     } else if (status == PkTransaction::Cancelled) {
0145         cancelClicked();
0146     } else {
0147         searchFailed();
0148         showCloseButton();
0149     }
0150 }
0151 
0152 void SessionTask::commitFinished(PkTransaction::ExitStatus status)
0153 {
0154     if (m_pkTransaction) {
0155         // Disconnect so it can be connected to something else latter
0156         disconnect(m_pkTransaction->transaction(), &PkTransaction::finished, this, &SessionTask::searchFinished);
0157     }
0158 
0159     if (status == PkTransaction::Success) {
0160         if (!m_removePackages.isEmpty()) {
0161             removePackages();
0162         } else {
0163             commitSuccess();
0164             showCloseButton();
0165         }
0166     } else if (status == PkTransaction::Cancelled) {
0167         cancelClicked();
0168     } else {
0169         commitFailed();
0170         showCloseButton();
0171     }
0172 }
0173 
0174 void SessionTask::updatePallete()
0175 {
0176     QPalette pal;
0177 //    pal.setColor(QPalette::Window, KGlobalSettings::activeTitleColor());
0178 //    pal.setColor(QPalette::WindowText, KGlobalSettings::activeTextColor());
0179     ui->backgroundFrame->setPalette(pal);
0180 }
0181 
0182 void SessionTask::setDialog(QDialog *dialog)
0183 {
0184     // Store the current values
0185     QWidget *widget = ui->stackedWidget->currentWidget();
0186 
0187     if (qobject_cast<ApplicationLauncher*>(dialog)) {
0188         // TODO if there is a removal after instalation
0189         // this will break it, but we don't have
0190         // this case yet...
0191         commitSuccess(dialog);
0192     } else {
0193         // Set the new ones
0194         setMainWidget(dialog);
0195 //        setTitle(dialog->windowTitle()); // must come after
0196         connect(this, &SessionTask::continueClicked, dialog, &QDialog::accept);
0197 //        connect(this, &SessionTask::continueClicked, dia, &QDialog::accept);
0198 //        connect(this, SIGNAL(okClicked()),
0199 //                dialog->mainWidget(), SLOT(deleteLater()));
0200 //        connect(this, SIGNAL(okClicked()),
0201 //                dialog, SLOT(deleteLater()));
0202 
0203         // Make sure we see the last widget and title
0204         auto mapper = new QSignalMapper(this);
0205         mapper->setMapping(this, widget);
0206         connect(this, &SessionTask::continueClicked, mapper, QOverload<>::of(&QSignalMapper::map));
0207         connect(mapper, QOverload<QWidget*>::of(&QSignalMapper::mapped), this, &SessionTask::setMainWidget);
0208         enableButtonOk(true);
0209     }
0210 }
0211 
0212 void SessionTask::setMainWidget(QWidget *widget)
0213 {
0214     if (widget != mainWidget()) {
0215         ui->stackedWidget->addWidget(widget);
0216         ui->stackedWidget->setCurrentWidget(widget);
0217         setTitle(widget->windowTitle());
0218     }
0219 }
0220 
0221 QWidget* SessionTask::mainWidget()
0222 {
0223     return ui->stackedWidget->currentWidget();
0224 }
0225 
0226 void SessionTask::setInfo(const QString &title, const QString &text, const QString &details)
0227 {
0228     auto info = new InfoWidget(this);
0229     info->setWindowTitle(title);
0230     info->setDescription(text);
0231     info->setDetails(details);
0232     setMainWidget(info);
0233     showCloseButton();
0234 
0235     if (qobject_cast<PkTransaction*>(sender())) {
0236         // if we have a sender this method was caller by PkTransaction
0237         // be carefull because QSignalMapper from KDialog also calls this method
0238         sender()->disconnect();
0239         sendErrorFinished(Failed, text);
0240     }
0241 }
0242 
0243 void SessionTask::setError(const QString &title, const QString &text, const QString &details)
0244 {
0245     auto info = new InfoWidget(this);
0246     info->setWindowTitle(title);
0247     info->setDescription(text);
0248     info->setIcon(QIcon::fromTheme(QLatin1String("dialog-error")));
0249     info->setDetails(details);
0250     setMainWidget(info);
0251     showCloseButton();
0252 
0253     if (qobject_cast<PkTransaction*>(sender())) {
0254         // if we have a sender this method was caller by PkTransaction
0255         // be carefull because QSignalMapper from KDialog also calls this method
0256         sender()->disconnect();
0257         sendErrorFinished(Failed, text);
0258     }
0259 }
0260 
0261 void SessionTask::setFinish(const QString &title, const QString &text, QWidget *widget)
0262 {
0263     auto info = new InfoWidget(this);
0264     info->setWindowTitle(title);
0265     info->setDescription(text);
0266     info->setIcon(QIcon::fromTheme(QLatin1String("dialog-ok-apply")));
0267     info->addWidget(widget);
0268     setMainWidget(info);
0269     showCloseButton();
0270 }
0271 
0272 void SessionTask::setTitle(const QString &title)
0273 {
0274     ui->titleL->setText(title);
0275 }
0276 
0277 void SessionTask::setExec(const QString &exec)
0278 {
0279     if (pathIsTrusted(exec)) {
0280         // Get from X11 the window title
0281 //        KWindowInfo info = KWindowSystem::windowInfo(m_xid, NET::WMVisibleName);
0282 //        parentTitle = info.visibleName();
0283     } else {
0284         parentTitle = exec;
0285     }
0286 }
0287 
0288 bool SessionTask::pathIsTrusted(const QString &exec)
0289 {
0290     // special case the plugin helper -- it's trusted
0291     return exec == QLatin1String("/usr/libexec/gst-install-plugins-helper") ||
0292            exec == QLatin1String("/usr/libexec/pk-gstreamer-install") ||
0293            exec == QLatin1String("/usr/bin/gstreamer-codec-install") ||
0294            exec == QLatin1String("/usr/lib/packagekit/pk-gstreamer-install") ||
0295            exec == QLatin1String("/usr/bin/plasma-desktop") ||
0296            exec == QLatin1String("/usr/bin/apper");
0297 }
0298 
0299 QString SessionTask::getCmdLine(uint pid)
0300 {
0301     QFile file(QString(QLatin1String("/proc/%1/cmdline")).arg(pid));
0302     QString line;
0303     if (file.open(QFile::ReadOnly)) {
0304         char buf[1024];
0305         qint64 lineLength = file.readLine(buf, sizeof(buf));
0306         if (lineLength != -1) {
0307             // the line is available in buf
0308             line = QString::fromLocal8Bit(buf);
0309             if (!line.contains(QLatin1String("(deleted)"))) {
0310                 return line;
0311             }
0312         }
0313     }
0314     return QString();
0315 }
0316 
0317 uint SessionTask::getPidSystem()
0318 {
0319     QDBusMessage msg;
0320     msg = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.DBus"),
0321                                          QLatin1String("/org/freedesktop/DBus/Bus"),
0322                                          QLatin1String("org.freedesktop.DBus"),
0323                                          QLatin1String("GetConnectionUnixProcessID"));
0324     msg << m_message.service();
0325     QDBusMessage reply = QDBusConnection::systemBus().call(msg);
0326     if (reply.type() != QDBusMessage::ReplyMessage) {
0327         qCWarning(APPER_SESSION) << "Message did not receive a reply";
0328     }
0329 
0330     if (reply.arguments().size() == 1) {
0331         return reply.arguments().at(0).toUInt();
0332     }
0333 
0334     return UINT_MAX;
0335 }
0336 
0337 uint SessionTask::getPidSession()
0338 {
0339     QDBusMessage msg;
0340     msg = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.DBus"),
0341                                          QLatin1String("/org/freedesktop/DBus/Bus"),
0342                                          QLatin1String("org.freedesktop.DBus"),
0343                                          QLatin1String("GetConnectionUnixProcessID"));
0344     msg << m_message.service();
0345     QDBusMessage reply = QDBusConnection::sessionBus().call(msg);
0346     if (reply.type() != QDBusMessage::ReplyMessage) {
0347         qCWarning(APPER_SESSION) << "Message did not receive a reply";
0348     }
0349 
0350     if (reply.arguments().size() == 1) {
0351         return reply.arguments().at(0).toUInt();
0352     }
0353 
0354     return UINT_MAX;
0355 }
0356 
0357 void SessionTask::search()
0358 {
0359     qCDebug(APPER_SESSION) << "virtual method called, falling back to commit()";
0360     commit();
0361 }
0362 
0363 void SessionTask::commit()
0364 {
0365     qCDebug(APPER_SESSION) << "virtual method called";
0366     if (m_reviewChanges) {
0367         QStringList installPackages = m_reviewChanges->model()->selectedPackagesToInstall();
0368         m_removePackages = m_reviewChanges->model()->selectedPackagesToRemove();
0369 
0370         if (installPackages.isEmpty() && m_removePackages.isEmpty()) {
0371             setInfo(i18n("There are no packages to Install or Remove"),
0372                     i18n("This action should not happen"));
0373             sendErrorFinished(Failed, QLatin1String("to install or remove due to empty lists"));
0374         } else if (!installPackages.isEmpty()) {
0375             // Install Packages
0376             auto transaction = new PkTransaction(this);
0377             setTransaction(Transaction::RoleInstallPackages, transaction);
0378             connect(transaction, &PkTransaction::finished, this, &SessionTask::commitFinished, Qt::UniqueConnection);
0379             transaction->installPackages(installPackages);
0380         } else {
0381             // Remove them
0382             removePackages();
0383         }
0384     }
0385 }
0386 
0387 void SessionTask::removePackages()
0388 {
0389     // Remove Packages
0390     auto transaction = new PkTransaction(this);
0391     setTransaction(Transaction::RoleRemovePackages, transaction);
0392     connect(transaction, &PkTransaction::finished, this, &SessionTask::commitFinished, Qt::UniqueConnection);
0393     transaction->removePackages(m_removePackages);
0394     m_removePackages.clear();
0395 }
0396 
0397 void SessionTask::notFound()
0398 {
0399     qCDebug(APPER_SESSION) << "virtual method called";
0400     if (showWarning()) {
0401         setInfo(i18n("Could not find"),
0402                 i18n("No packages were found that meet the request"));
0403     }
0404     sendErrorFinished(NoPackagesFound, QLatin1String("no package found"));
0405 }
0406 
0407 void SessionTask::searchFailed()
0408 {
0409     qCDebug(APPER_SESSION) << "virtual method called";
0410     setInfo(i18n("Failed to find"),
0411             i18n("No packages were found that meet the request"));
0412     sendErrorFinished(Failed, QLatin1String("failed to search"));
0413 }
0414 
0415 void SessionTask::searchSuccess()
0416 {
0417     qCDebug(APPER_SESSION) << "virtual method called";
0418     enableButtonOk(true);
0419     m_reviewChanges = new ReviewChanges(m_model, this);
0420     connect(m_reviewChanges, &ReviewChanges::hasSelectedPackages, this, &SessionTask::enableButtonOk);
0421     setMainWidget(m_reviewChanges);
0422 }
0423 
0424 void SessionTask::commitFailed()
0425 {
0426     qCDebug(APPER_SESSION) << "virtual method called";
0427     // This should not be used to display stuff as the transaction should
0428     // emit error() or info()
0429 //    setInfo(i18n("Failed to commit transaction"),
0430 //            PkStrings::errsearchFailedorMessage(m_pkTransaction->error()));
0431     sendErrorFinished(Failed, i18n("Transaction did not finish with success"));
0432 }
0433 
0434 void SessionTask::commitSuccess(QWidget *widget)
0435 {
0436     qCDebug(APPER_SESSION) << "virtual method called";
0437     setFinish(i18n("Task completed"), i18n("All operations were committed successfully"), widget);
0438     finishTaskOk();
0439 }
0440 
0441 void SessionTask::showCloseButton()
0442 {
0443     ui->buttonBox->setStandardButtons(QDialogButtonBox::Close);
0444     QPushButton *closeBt = ui->buttonBox->button(QDialogButtonBox::Close);
0445     closeBt->setDefault(true);
0446     connect(closeBt, &QPushButton::clicked, this, &SessionTask::accept);
0447 }
0448 
0449 void SessionTask::sendErrorFinished(DBusError error, const QString &msg)
0450 {
0451     QString dbusError;
0452     switch (error) {
0453     case Failed:
0454         dbusError = QLatin1String("org.freedesktop.PackageKit.Failed");
0455         break;
0456     case InternalError:
0457         dbusError = QLatin1String("org.freedesktop.PackageKit.InternalError");
0458         break;
0459     case NoPackagesFound:
0460         dbusError = QLatin1String("org.freedesktop.PackageKit.NoPackagesFound");
0461         break;
0462     case Forbidden:
0463         dbusError = QLatin1String("org.freedesktop.PackageKit.Forbidden");
0464         break;
0465     case Cancelled:
0466         dbusError = QLatin1String("org.freedesktop.PackageKit.Cancelled");
0467         break;
0468     }
0469     QDBusMessage reply = m_message.createErrorReply(dbusError, msg);
0470     QDBusConnection::sessionBus().send(reply);
0471 }
0472 
0473 bool SessionTask::sendMessageFinished(const QDBusMessage &message)
0474 {
0475 //    emit finished();
0476     return QDBusConnection::sessionBus().send(message);
0477 }
0478 
0479 uint SessionTask::parentWId() const
0480 {
0481     return m_xid;
0482 }
0483 
0484 void SessionTask::slotContinueClicked()
0485 {
0486     if (qobject_cast<IntroDialog*>(mainWidget())) {
0487         enableButtonOk(false);
0488         search();
0489     } else if (qobject_cast<ReviewChanges*>(mainWidget())) {
0490         enableButtonOk(false);
0491         commit();
0492     } else {
0493 //        emit okClicked();
0494     }
0495 }
0496 
0497 void SessionTask::slotCancelClicked()
0498 {
0499     emit cancelClicked();
0500     sendErrorFinished(Cancelled, QLatin1String("Aborted by the user"));
0501     reject();
0502 
0503 }
0504 
0505 void SessionTask::enableButtonOk(bool enable)
0506 {
0507     QPushButton *okButton = ui->buttonBox->button(QDialogButtonBox::Ok);
0508     okButton->setEnabled(enable);
0509     if (enable) {
0510         // When enabling the Continue button put focus on it
0511         okButton->setFocus();
0512     }
0513 }
0514 
0515 void SessionTask::parseInteraction(const QString &interaction)
0516 {
0517     QStringList interactions = interaction.split(QLatin1Char(','));
0518 
0519     // Enable or disable all options
0520     if (interactions.contains(QLatin1String("always"))) {
0521         m_interactions = ConfirmSearch
0522                        | ConfirmDeps
0523                        | ConfirmInstall
0524                        | Progress
0525                        | Finished
0526                        | Warning;
0527     } else if (interactions.contains(QLatin1String("never"))) {
0528         m_interactions = {};
0529     }
0530 
0531     // show custom options
0532     if (interactions.contains(QLatin1String("show-confirm-search"))) {
0533         m_interactions |= ConfirmSearch;
0534     }
0535     if (interactions.contains(QLatin1String("show-confirm-deps"))) {
0536         m_interactions |= ConfirmDeps;
0537     }
0538     if (interactions.contains(QLatin1String("show-confirm-install"))) {
0539         m_interactions |= ConfirmInstall;
0540     }
0541     if (interactions.contains(QLatin1String("show-progress"))) {
0542         m_interactions |= Progress;
0543     }
0544     if (interactions.contains(QLatin1String("show-finished"))) {
0545         m_interactions |= Finished;
0546     }
0547     if (interactions.contains(QLatin1String("show-warning"))) {
0548         m_interactions |= Warning;
0549     }
0550 
0551     // hide custom options
0552     if (interactions.contains(QLatin1String("hide-confirm-search"))) {
0553         m_interactions &= ~ConfirmSearch;
0554     }
0555     if (interactions.contains(QLatin1String("hide-confirm-deps"))) {
0556         m_interactions &= ~ConfirmDeps;
0557     }
0558     if (interactions.contains(QLatin1String("hide-confirm-install"))) {
0559         m_interactions &= ~ConfirmInstall;
0560     }
0561     if (interactions.contains(QLatin1String("hide-progress"))) {
0562         m_interactions &= ~Progress;
0563     }
0564     if (interactions.contains(QLatin1String("hide-finished"))) {
0565         m_interactions &= ~Finished;
0566     }
0567     if (interactions.contains(QLatin1String("hide-warning"))) {
0568         m_interactions &= ~Warning;
0569     }
0570 
0571     int index;
0572     QRegExp rx(QLatin1String("^timeout=(\\d+)$"));
0573     index = interactions.indexOf(rx);
0574     if (index != -1) {
0575         if (rx.indexIn(interactions.at(index)) != -1) {
0576             m_timeout = rx.cap(1).toUInt();
0577         }
0578     }
0579 }
0580 
0581 bool SessionTask::foundPackages() const
0582 {
0583     return m_model->rowCount();
0584 }
0585 
0586 int SessionTask::foundPackagesSize() const
0587 {
0588     return m_model->rowCount();
0589 }
0590 
0591 PackageModel *SessionTask::model() const
0592 {
0593     return m_model;
0594 }
0595 
0596 void SessionTask::setTransaction(Transaction::Role role, PkTransaction *t)
0597 {
0598     if (m_pkTransaction == nullptr) {
0599         m_pkTransaction = new PkTransactionWidget(this);
0600         m_pkTransaction->hideCancelButton();
0601 
0602         ui->stackedWidget->addWidget(m_pkTransaction);
0603         connect(m_pkTransaction, &PkTransactionWidget::titleChanged, this, &SessionTask::setTitle);
0604         connect(this, &SessionTask::cancelClicked, m_pkTransaction, &PkTransactionWidget::cancel);
0605         connect(m_pkTransaction, &PkTransactionWidget::dialog, this, &SessionTask::setDialog);
0606         connect(m_pkTransaction, &PkTransactionWidget::sorry, this, &SessionTask::setInfo);
0607         connect(m_pkTransaction, &PkTransactionWidget::error, this, &SessionTask::setError);
0608     }
0609     if (t) {
0610         m_pkTransaction->setTransaction(t, role);
0611 //        setTitle(m_pkTransaction->title());
0612     }
0613 
0614     // avoid changing the current widget
0615     if (mainWidget() != m_pkTransaction) {
0616         ui->stackedWidget->setCurrentWidget(m_pkTransaction);
0617     }
0618 }
0619 
0620 void SessionTask::finishTaskOk()
0621 {
0622     sendMessageFinished(m_message.createReply());
0623 }
0624 
0625 SessionTask::Interactions SessionTask::interactions() const
0626 {
0627     return m_interactions;
0628 }
0629 
0630 uint SessionTask::timeout() const
0631 {
0632     return m_timeout;
0633 }
0634 
0635 bool SessionTask::showConfirmSearch() const
0636 {
0637     return m_interactions & ConfirmSearch;
0638 }
0639 
0640 bool SessionTask::showConfirmDeps() const
0641 {
0642     return m_interactions & ConfirmDeps;
0643 }
0644 
0645 bool SessionTask::showConfirmInstall() const
0646 {
0647     return m_interactions & ConfirmInstall;
0648 }
0649 
0650 bool SessionTask::showProgress() const
0651 {
0652     return m_interactions & Progress;
0653 }
0654 
0655 bool SessionTask::showFinished() const
0656 {
0657     return m_interactions & Finished;
0658 }
0659 
0660 bool SessionTask::showWarning() const
0661 {
0662     return m_interactions & Warning;
0663 }
0664 
0665 #include "moc_SessionTask.cpp"