File indexing completed on 2024-04-21 05:45:08

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 <config.h>
0022 
0023 #include "PkTransactionWidget.h"
0024 #include "ui_PkTransactionWidget.h"
0025 
0026 #include <KLocalizedString>
0027 #include <QPushButton>
0028 #include <KPixmapSequence>
0029 #include <KPixmapSequenceOverlayPainter>
0030 #include <KIconLoader>
0031 
0032 #include <QLoggingCategory>
0033 
0034 #include <QtDBus/QDBusMessage>
0035 #include <QtDBus/QDBusConnection>
0036 #include <QScrollBar>
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 "Requirements.h"
0047 #include "PkTransaction.h"
0048 #include "TransactionDelegate.h"
0049 #include "PkTransactionProgressModel.h"
0050 #include "PackageModel.h"
0051 
0052 Q_DECLARE_LOGGING_CATEGORY(APPER_LIB)
0053 
0054 class PkTransactionWidgetPrivate
0055 {
0056 public:
0057     ApplicationLauncher *launcher;
0058     Transaction::Role role;
0059     KPixmapSequenceOverlayPainter *busySeq;
0060 };
0061 
0062 PkTransactionWidget::PkTransactionWidget(QWidget *parent) :
0063     QWidget(parent),
0064     m_trans(nullptr),
0065     m_keepScrollBarAtBottom(true),
0066     m_handlingActionRequired(false),
0067     m_showingError(false),
0068     m_status(Transaction::StatusUnknown),
0069     ui(new Ui::PkTransactionWidget),
0070     d(new PkTransactionWidgetPrivate)
0071 {
0072     ui->setupUi(this);
0073 
0074     // Setup the animation sequence
0075     d->busySeq = new KPixmapSequenceOverlayPainter(this);
0076     d->busySeq->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
0077     d->busySeq->setWidget(ui->label);
0078     ui->label->clear();
0079 
0080     // Connect stuff from the progressView
0081     QScrollBar *scrollBar = ui->progressView->verticalScrollBar();
0082     connect(scrollBar, &QScrollBar::sliderMoved, this, &PkTransactionWidget::followBottom);
0083     connect(scrollBar, &QScrollBar::valueChanged, this, &PkTransactionWidget::followBottom);
0084     connect(scrollBar, &QScrollBar::rangeChanged, this, &PkTransactionWidget::rangeChanged);
0085 
0086     ui->progressView->setItemDelegate(new TransactionDelegate(this));
0087     
0088     connect(ui->cancelButton, &QDialogButtonBox::rejected, this, &PkTransactionWidget::cancel);
0089 }
0090 
0091 PkTransactionWidget::~PkTransactionWidget()
0092 {
0093     // DO NOT disconnect the transaction here,
0094     // it might not exist when this happen
0095     delete d;
0096 }
0097 
0098 void PkTransactionWidget::hideCancelButton()
0099 {
0100     // On the session installed we hide the
0101     // cancel button to use the KDialog main one
0102     ui->cancelButton->hide();
0103 }
0104 
0105 void PkTransactionWidget::cancel()
0106 {
0107     if (m_trans) {
0108         m_trans->cancel();
0109     }
0110 }
0111 
0112 void PkTransactionWidget::setTransaction(PkTransaction *trans, Transaction::Role role)
0113 {
0114     Q_ASSERT(trans);
0115 
0116     m_trans = trans;
0117     d->role = role;
0118 
0119     // This makes sure the Columns will properly resize to contents
0120         ui->progressView->header()->setStretchLastSection(false);
0121     if (role == Transaction::RoleRefreshCache) {
0122         trans->progressModel()->setColumnCount(1);
0123         ui->progressView->setModel(trans->progressModel());
0124         ui->progressView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
0125     } else {
0126         trans->progressModel()->setColumnCount(3);
0127         ui->progressView->setModel(trans->progressModel());
0128         ui->progressView->header()->reset();
0129         ui->progressView->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
0130         ui->progressView->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
0131         ui->progressView->header()->setSectionResizeMode(2, QHeaderView::Stretch);
0132     }
0133 
0134     connect(m_trans, &PkTransaction::percentageChanged, this, &PkTransactionWidget::updateUi);
0135     connect(m_trans, &PkTransaction::speedChanged, this, &PkTransactionWidget::updateUi);
0136     connect(m_trans, &PkTransaction::statusChanged, this, &PkTransactionWidget::updateUi);
0137     connect(m_trans, &PkTransaction::downloadSizeRemainingChanged, this, &PkTransactionWidget::updateUi);
0138     connect(m_trans, &PkTransaction::remainingTimeChanged, this, &PkTransactionWidget::updateUi);
0139     connect(m_trans, &PkTransaction::roleChanged, this, &PkTransactionWidget::updateUi);
0140     connect(m_trans, &PkTransaction::allowCancelChanged, this, &PkTransactionWidget::updateUi);
0141     connect(m_trans, &PkTransaction::transactionFlagsChanged, this, &PkTransactionWidget::updateUi);
0142 
0143     // Forward Q_SIGNALS:
0144     connect(m_trans, &PkTransaction::sorry, this, &PkTransactionWidget::sorry);
0145     connect(m_trans, &PkTransaction::errorMessage, this, &PkTransactionWidget::error);
0146     connect(m_trans, &PkTransaction::dialog, this, &PkTransactionWidget::dialog);
0147 
0148     // sets ui
0149     updateUi();
0150 }
0151 
0152 void PkTransactionWidget::unsetTransaction()
0153 {
0154     if (m_trans == nullptr) {
0155         return;
0156     }
0157 
0158     connect(m_trans, &PkTransaction::percentageChanged, this, &PkTransactionWidget::updateUi);
0159     connect(m_trans, &PkTransaction::speedChanged, this, &PkTransactionWidget::updateUi);
0160     connect(m_trans, &PkTransaction::statusChanged, this, &PkTransactionWidget::updateUi);
0161     connect(m_trans, &PkTransaction::downloadSizeRemainingChanged, this, &PkTransactionWidget::updateUi);
0162     connect(m_trans, &PkTransaction::remainingTimeChanged, this, &PkTransactionWidget::updateUi);
0163     connect(m_trans, &PkTransaction::roleChanged, this, &PkTransactionWidget::updateUi);
0164     connect(m_trans, &PkTransaction::allowCancelChanged, this, &PkTransactionWidget::updateUi);
0165     connect(m_trans, &PkTransaction::transactionFlagsChanged, this, &PkTransactionWidget::updateUi);
0166 }
0167 
0168 void PkTransactionWidget::updateUi()
0169 {
0170     // sets the action icon to be the window icon
0171     auto transaction = qobject_cast<PkTransaction*>(sender());
0172     if (transaction == nullptr && (transaction = m_trans) == nullptr) {
0173         qCWarning(APPER_LIB) << "no transaction object";
0174         return;
0175     }
0176 
0177     uint percentage = transaction->percentage();
0178     QString percentageString;
0179     if (percentage <= 100) {
0180         if (ui->progressBar->value() != static_cast<int>(percentage)) {
0181             ui->progressBar->setMaximum(100);
0182             ui->progressBar->setValue(percentage);
0183             percentageString = QString::number(percentage);
0184         }
0185     } else if (ui->progressBar->maximum() != 0) {
0186         ui->progressBar->setMaximum(0);
0187         ui->progressBar->reset();
0188         percentageString = QLatin1String("");
0189     }
0190 
0191     ui->progressBar->setRemaining(transaction->remainingTime());
0192 
0193     // Status & Speed
0194     Transaction::Status status = transaction->status();
0195     uint speed = transaction->speed();
0196     qulonglong downloadSizeRemaining = transaction->downloadSizeRemaining();
0197     if (m_status != status) {
0198         m_status = status;
0199         ui->currentL->setText(PkStrings::status(status,
0200                                                 speed,
0201                                                 downloadSizeRemaining));
0202 
0203         KPixmapSequence sequence = KPixmapSequence(PkIcons::statusAnimation(status),
0204                                                    KIconLoader::SizeLarge);
0205         if (sequence.isValid()) {
0206             d->busySeq->setSequence(sequence);
0207             d->busySeq->start();
0208         }
0209     } else if (status == Transaction::StatusDownload) {
0210         ui->currentL->setText(PkStrings::status(status,
0211                                                 speed,
0212                                                 downloadSizeRemaining));
0213     }
0214 
0215     QString windowTitle;
0216     QString windowTitleProgress;
0217     QIcon windowIcon;
0218     Transaction::Role role = transaction->role();
0219     if (role == Transaction::RoleUnknown) {
0220         windowTitle  = PkStrings::status(Transaction::StatusSetup);
0221         if (percentageString.isEmpty()) {
0222             windowTitleProgress = PkStrings::status(status,
0223                                                     speed,
0224                                                     downloadSizeRemaining);
0225         } else {
0226             QString statusText = PkStrings::status(status,
0227                                                    speed,
0228                                                    downloadSizeRemaining);
0229             windowTitleProgress = i18n("%1 (%2%)", statusText, percentageString);
0230         }
0231         windowIcon = PkIcons::statusIcon(Transaction::StatusSetup);
0232     } else {
0233         windowTitle = PkStrings::action(role, transaction->transactionFlags());
0234         if (percentageString.isEmpty()) {
0235             windowTitleProgress = PkStrings::status(status,
0236                                                     speed,
0237                                                     downloadSizeRemaining);
0238         } else {
0239             QString statusText = PkStrings::status(status,
0240                                                    speed,
0241                                                    downloadSizeRemaining);
0242             windowTitleProgress = i18n("%1 (%2%)", statusText, percentageString);
0243         }
0244         windowIcon = PkIcons::actionIcon(role);
0245     }
0246 
0247     if (d->role != role) {
0248         d->role = role;
0249         setWindowIcon(PkIcons::actionIcon(role));
0250         setWindowTitle(windowTitle);
0251 
0252         emit titleChanged(windowTitle);
0253         emit titleChangedProgress(windowTitleProgress);
0254     } else if (!percentageString.isNull()) {
0255         emit titleChangedProgress(windowTitleProgress);
0256     }
0257 
0258     // check to see if we can cancel
0259     bool cancel = transaction->allowCancel();
0260     emit allowCancel(cancel);
0261     ui->cancelButton->setEnabled(cancel);
0262 }
0263 
0264 bool PkTransactionWidget::isFinished() const
0265 {
0266 //    return d->finished;
0267     return false;
0268 }
0269 
0270 bool PkTransactionWidget::isCancelVisible() const
0271 {
0272     return ui->cancelButton->isVisible();
0273 }
0274 
0275 void PkTransactionWidget::reject()
0276 {
0277 //    d->finished = true;
0278     //    setExitStatus(Cancelled);
0279 }
0280 
0281 void PkTransactionWidget::followBottom(int value)
0282 {
0283     // If the user moves the slider to the bottom
0284     // keep it there as the list expands
0285     QScrollBar *scrollBar = qobject_cast<QScrollBar*>(sender());
0286     m_keepScrollBarAtBottom = value == scrollBar->maximum();
0287 }
0288 
0289 void PkTransactionWidget::rangeChanged(int min, int max)
0290 {
0291     Q_UNUSED(min)
0292     QScrollBar *scrollBar = qobject_cast<QScrollBar*>(sender());
0293     if (m_keepScrollBarAtBottom && scrollBar->value() != max) {
0294         scrollBar->setValue(max);
0295     }
0296 }
0297 
0298 Transaction::Role PkTransactionWidget::role() const
0299 {
0300     return d->role;
0301 }
0302 
0303 PkTransaction *PkTransactionWidget::transaction() const
0304 {
0305     return m_trans;
0306 }
0307 
0308 #include "moc_PkTransactionWidget.cpp"