Commit ad0c705a authored by Aleix Pol Gonzalez's avatar Aleix Pol Gonzalez 🐧

Make it possible for the ProgressView to include resource-less transactions

parent a4332eba
......@@ -30,13 +30,14 @@ Kirigami.BasicListItem {
readonly property var v1: Connections {
target: TransactionModel
onTransactionAdded: {
if(listItem.enabled && trans.resource && progressModel.appAt(trans.resource)<0)
progressModel.append({app: trans.resource})
if(listItem.enabled && progressModel.applicationAt(trans.resource)<0) {
progressModel.append({ transaction: trans })
}
}
onTransactionRemoved: {
if (trans.status == Transaction.CancelledStatus) {
var id = progressModel.appAt(trans.resource)
if (trans.status == Transaction.CancelledStatus || !trans.resource) {
var id = progressModel.applicationAt(trans.resource)
if(id>=0)
progressModel.remove(id)
}
......@@ -45,38 +46,43 @@ Kirigami.BasicListItem {
readonly property var v2: ListModel {
id: progressModel
function appAt(app) {
function applicationAt(app) {
for(var i=0; i<progressModel.count; i++) {
if(progressModel.get(i).app==app) {
if(progressModel.get(i).application==app) {
return i
}
}
return -1
}
}
readonly property var v3: Kirigami.OverlaySheet {
id: sheet
contentItem: ColumnLayout {
spacing: 0
Component {
id: listenerComp
TransactionListener {
onCancelled: progressModel.remove(index)
}
}
Repeater {
model: progressModel
delegate: Kirigami.AbstractListItem {
id: del
separatorVisible: false
onClicked: {
Navigation.clearStack()
Navigation.openApplication(model.app)
Navigation.openApplication(model.application)
}
readonly property QtObject listener: listenerComp.createObject(del, (model.transaction.resource ? {resource: model.transaction.resource} : {transaction: model.transaction}))
ColumnLayout {
width: parent.width
TransactionListener {
id: listener
resource: model.app
onCancelled: progressModel.remove(index)
}
RowLayout {
Layout.fillWidth: true
......@@ -84,13 +90,14 @@ Kirigami.BasicListItem {
Kirigami.Icon {
Layout.fillHeight: true
Layout.minimumWidth: height
source: model.app.icon
source: model.transaction.icon
}
Label {
anchors.verticalCenter: parent.verticalCenter
Layout.fillWidth: true
elide: Text.ElideRight
text: model.app.name + (listener.isActive ? " "+listener.statusText : "")
text: model.transaction.name + (listener.isActive ? " "+listener.statusText : "")
}
ToolButton {
iconName: "dialog-cancel"
......@@ -99,9 +106,9 @@ Kirigami.BasicListItem {
}
ToolButton {
iconName: "system-run"
visible: model.app.isInstalled && !listener.isActive && model.app.canExecute
visible: model.application != undefined && model.application.isInstalled && !listener.isActive && model.application.canExecute
onClicked: {
model.app.invokeApplication()
model.application.invokeApplication()
model.remove(index)
}
}
......
......@@ -20,6 +20,7 @@
#include "Transaction.h"
#include <resources/AbstractResource.h>
#include "TransactionModel.h"
#include <QDebug>
......@@ -107,3 +108,13 @@ bool Transaction::isActive() const
{
return m_status == DownloadingStatus || m_status == CommittingStatus;
}
QString Transaction::name() const
{
return m_resource->name();
}
QVariant Transaction::icon() const
{
return m_resource->icon();
}
......@@ -43,6 +43,8 @@ class DISCOVERCOMMON_EXPORT Transaction : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QVariant icon READ icon CONSTANT)
Q_PROPERTY(AbstractResource* resource READ resource CONSTANT)
Q_PROPERTY(Role role READ role CONSTANT)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
......@@ -136,6 +138,12 @@ public:
Q_SCRIPTABLE virtual void proceed() {}
/** @returns a name that identifies the transaction */
virtual QString name() const;
/** @returns an icon that describes the transaction */
virtual QVariant icon() const;
private:
AbstractResource * const m_resource;
const Role m_role;
......
......@@ -36,17 +36,11 @@ TransactionListener::TransactionListener(QObject *parent)
void TransactionListener::cancel()
{
if(!isCancellable()) {
qWarning() << "cannot cancel the transaction" << m_transaction;
return;
}
m_transaction->cancel();
}
AbstractResource *TransactionListener::resource() const
{
return m_resource;
}
bool TransactionListener::isCancellable() const
{
return m_transaction && m_transaction->isCancellable();
......@@ -65,15 +59,18 @@ QString TransactionListener::statusText() const
}
void TransactionListener::setResource(AbstractResource *resource)
{
setResourceInternal(resource);
// Catch already-started transactions
setTransaction(TransactionModel::global()->transactionFromResource(resource));
}
void TransactionListener::setResourceInternal(AbstractResource* resource)
{
if (m_resource == resource)
return;
m_resource = resource;
// Catch already-started transactions
setTransaction(TransactionModel::global()->transactionFromResource(resource));
emit resourceChanged();
}
......@@ -112,7 +109,6 @@ private:
void TransactionListener::setTransaction(Transaction* trans)
{
Q_ASSERT(!trans || trans->resource()==m_resource);
if (m_transaction == trans) {
return;
}
......@@ -131,7 +127,9 @@ void TransactionListener::setTransaction(Transaction* trans)
connect(m_transaction, &Transaction::cancellableChanged, this, &TransactionListener::cancellableChanged);
connect(m_transaction, &Transaction::statusChanged, this, &TransactionListener::transactionStatusChanged);
connect(m_transaction, &Transaction::progressChanged, this, &TransactionListener::progressChanged);
setResourceInternal(trans->resource());
}
Q_EMIT transactionChanged(trans);
}
void TransactionListener::transactionStatusChanged(Transaction::Status status)
......
......@@ -22,7 +22,7 @@
#ifndef TRANSACTIONLISTENER_H
#define TRANSACTIONLISTENER_H
#include <QtCore/QObject>
#include <QObject>
#include "Transaction.h"
#include "discovercommon_export.h"
......@@ -33,6 +33,7 @@ class DISCOVERCOMMON_EXPORT TransactionListener : public QObject
{
Q_OBJECT
Q_PROPERTY(AbstractResource* resource READ resource WRITE setResource NOTIFY resourceChanged)
Q_PROPERTY(Transaction* transaction READ transaction WRITE setTransaction NOTIFY transactionChanged)
Q_PROPERTY(bool isCancellable READ isCancellable NOTIFY cancellableChanged)
Q_PROPERTY(bool isActive READ isActive NOTIFY isActiveChanged)
Q_PROPERTY(QString statusText READ statusText NOTIFY statusTextChanged)
......@@ -40,7 +41,8 @@ class DISCOVERCOMMON_EXPORT TransactionListener : public QObject
public:
explicit TransactionListener(QObject *parent = nullptr);
AbstractResource *resource() const;
AbstractResource *resource() const { return m_resource; }
Transaction *transaction() const { return m_transaction; }
bool isCancellable() const;
bool isActive() const;
QString statusText() const;
......@@ -49,17 +51,16 @@ public:
Q_SCRIPTABLE void cancel();
void setResource(AbstractResource* resource);
void setTransaction(Transaction *trans);
private:
void setTransaction(Transaction *trans);
void setResourceInternal(AbstractResource* resource);
AbstractResource *m_resource;
Transaction *m_transaction;
Transaction* m_transaction;
private Q_SLOTS:
void transactionAdded(Transaction *trans);
void transactionRemoved(Transaction* trans);
void transactionCancelled(Transaction* trans);
void transactionStatusChanged(Transaction::Status status);
Q_SIGNALS:
......@@ -69,6 +70,7 @@ Q_SIGNALS:
void statusTextChanged();
void cancelled();
void progressChanged();
void transactionChanged(Transaction* transaction);
};
#endif // TRANSACTIONLISTENER_H
......@@ -60,6 +60,7 @@ public:
bool contains(Transaction* transaction) const { return m_transactions.contains(transaction); }
int progress() const;
QVector<Transaction *> transactions() const { return m_transactions; }
private:
QVector<Transaction *> m_transactions;
......
......@@ -203,7 +203,7 @@ void DummyTest::testInstallAddons()
QVERIFY(m.hasChanges());
m.applyChanges();
QSignalSpy sR(TransactionModel::global(), SIGNAL(transactionRemoved(Transaction* )));
QSignalSpy sR(TransactionModel::global(), &TransactionModel::transactionRemoved);
QVERIFY(sR.wait());
QVERIFY(!m.hasChanges());
......
......@@ -105,8 +105,10 @@ private Q_SLOTS:
QCOMPARE(m->hasUpdates(), true);
rum->prepare();
spy.clear();
rum->updateAll();
QVERIFY(spy.wait());
QVERIFY(spy.count() || spy.wait());
QCOMPARE(rum->isProgressing(), true);
QTest::qWait(20);
......
......@@ -34,6 +34,71 @@
#include <KLocalizedString>
#include <KFormat>
class UpdateTransaction : public Transaction
{
Q_OBJECT
public:
UpdateTransaction(ResourcesUpdatesModel* parent)
: Transaction(nullptr, nullptr, Transaction::InstallRole)
, m_allUpdaters(parent->updaters())
{
bool cancelable = false;
foreach(auto updater, parent->updaters()) {
connect(updater, &AbstractBackendUpdater::progressingChanged, this, &UpdateTransaction::slotProgressingChanged);
connect(updater, &AbstractBackendUpdater::passiveMessage, this, &Transaction::passiveMessage);
connect(updater, &AbstractBackendUpdater::proceedRequest, this, &UpdateTransaction::processProceedRequest);
cancelable |= updater->isCancelable();
}
setCancellable(cancelable);
}
void processProceedRequest(const QString &title, const QString& message) {
m_updatersWaitingForFeedback += qobject_cast<AbstractBackendUpdater*>(sender());
Q_EMIT proceedRequest(title, message);
}
void cancel() override {
QVector<AbstractBackendUpdater*> toCancel = m_updatersWaitingForFeedback.isEmpty() ? m_allUpdaters : m_updatersWaitingForFeedback;
foreach(auto updater, m_updatersWaitingForFeedback) {
updater->cancel();
}
}
void proceed() override {
m_updatersWaitingForFeedback.takeFirst()->proceed();
}
bool isProgressing() const
{
bool progressing = false;
foreach(AbstractBackendUpdater* upd, m_allUpdaters) {
progressing |= upd->isProgressing();
}
return progressing;
}
void slotProgressingChanged()
{
if (status() < DoneStatus && !isProgressing()) {
setStatus(Transaction::DoneStatus);
Q_EMIT finished();
qDebug() << "finished!" << this << sender();
deleteLater();
}
}
QVariant icon() const override { return QStringLiteral("update-low"); }
QString name() const override { return i18n("Update"); }
Q_SIGNALS:
void finished();
private:
QVector<AbstractBackendUpdater*> m_updatersWaitingForFeedback;
const QVector<AbstractBackendUpdater*> m_allUpdaters;
};
ResourcesUpdatesModel::ResourcesUpdatesModel(QObject* parent)
: QStandardItemModel(parent)
, m_lastIsProgressing(false)
......@@ -51,13 +116,11 @@ void ResourcesUpdatesModel::init()
foreach(AbstractResourcesBackend* b, backends) {
AbstractBackendUpdater* updater = b->backendUpdater();
if(updater && !m_updaters.contains(updater)) {
connect(updater, &AbstractBackendUpdater::progressingChanged, this, &ResourcesUpdatesModel::slotProgressingChanged);
connect(updater, &AbstractBackendUpdater::progressChanged, this, &ResourcesUpdatesModel::progressChanged);
connect(updater, &AbstractBackendUpdater::statusMessageChanged, this, &ResourcesUpdatesModel::message);
connect(updater, &AbstractBackendUpdater::statusDetailChanged, this, &ResourcesUpdatesModel::message);
connect(updater, &AbstractBackendUpdater::remainingTimeChanged, this, &ResourcesUpdatesModel::etaChanged);
connect(updater, &AbstractBackendUpdater::downloadSpeedChanged, this, &ResourcesUpdatesModel::downloadSpeedChanged);
connect(updater, &AbstractBackendUpdater::cancelableChanged, this, &ResourcesUpdatesModel::cancelableChanged);
connect(updater, &AbstractBackendUpdater::resourceProgressed, this, &ResourcesUpdatesModel::resourceProgressed);
connect(updater, &AbstractBackendUpdater::destroyed, this, &ResourcesUpdatesModel::updaterDestroyed);
m_updaters += updater;
......@@ -65,6 +128,14 @@ void ResourcesUpdatesModel::init()
m_lastIsProgressing |= updater->isProgressing();
}
}
auto tm = TransactionModel::global();
foreach(auto t, tm->transactions()) {
auto updateTransaction = qobject_cast<UpdateTransaction*>(t);
if (updateTransaction) {
setTransaction(updateTransaction);
}
}
}
void ResourcesUpdatesModel::updaterDestroyed(QObject* obj)
......@@ -72,26 +143,6 @@ void ResourcesUpdatesModel::updaterDestroyed(QObject* obj)
m_updaters.removeAll(static_cast<AbstractBackendUpdater*>(obj));
}
void ResourcesUpdatesModel::slotProgressingChanged()
{
const bool newProgressing = isProgressing();
if (newProgressing != m_lastIsProgressing) {
m_lastIsProgressing = newProgressing;
if (!newProgressing && m_transaction) {
m_transaction->setStatus(Transaction::DoneStatus);
m_transaction->deleteLater();
}
emit progressingChanged(newProgressing);
if (!newProgressing) {
Q_EMIT finished();
}
}
}
qreal ResourcesUpdatesModel::progress() const
{
if (m_updaters.isEmpty())
......@@ -123,52 +174,12 @@ void ResourcesUpdatesModel::prepare()
}
}
class UpdateTransaction : public Transaction
{
public:
UpdateTransaction(ResourcesUpdatesModel* parent)
: Transaction(parent, nullptr, Transaction::InstallRole)
, m_updater(parent)
{
setCancellable(m_updater->isCancelable());
connect(m_updater, &ResourcesUpdatesModel::cancelableChanged, this, [this]() {
setCancellable(m_updater->isCancelable());
});
foreach(auto updater, parent->updaters()) {
connect(updater, &AbstractBackendUpdater::passiveMessage, this, &Transaction::passiveMessage);
connect(updater, &AbstractBackendUpdater::proceedRequest, this, &UpdateTransaction::processProceedRequest);
}
}
void processProceedRequest(const QString &title, const QString& message) {
m_updatersWaitingForFeedback += qobject_cast<AbstractBackendUpdater*>(sender());
Q_EMIT proceedRequest(title, message);
}
void cancel() override {
foreach(auto updater, m_updatersWaitingForFeedback) {
updater->cancel();
}
m_updater->cancel();
}
void proceed() override {
m_updatersWaitingForFeedback.takeFirst()->proceed();
}
private:
ResourcesUpdatesModel* m_updater;
QVector<AbstractBackendUpdater*> m_updatersWaitingForFeedback;
};
void ResourcesUpdatesModel::updateAll()
{
if(m_updaters.isEmpty())
slotProgressingChanged();
else {
if (!m_updaters.isEmpty()) {
delete m_transaction;
m_transaction = new UpdateTransaction(this);
setTransaction(m_transaction);
TransactionModel::global()->addTransaction(m_transaction);
Q_FOREACH (AbstractBackendUpdater* upd, m_updaters) {
if (upd->hasUpdates())
......@@ -194,25 +205,9 @@ QString ResourcesUpdatesModel::remainingTime() const
return i18nc("@item:intext Remaining time", "%1 remaining", KFormat().formatDuration(maxEta));
}
bool ResourcesUpdatesModel::isCancelable() const
{
bool cancelable = false;
foreach(AbstractBackendUpdater* upd, m_updaters) {
cancelable |= upd->isCancelable();
}
return cancelable;
}
bool ResourcesUpdatesModel::isProgressing() const
{
if (m_updaters.isEmpty())
return true;
bool progressing = false;
foreach(AbstractBackendUpdater* upd, m_updaters) {
progressing |= upd->isProgressing();
}
return progressing;
return m_transaction && m_transaction->status()<Transaction::DoneStatus;
}
QList<AbstractResource*> ResourcesUpdatesModel::toUpdate() const
......@@ -260,17 +255,18 @@ QDateTime ResourcesUpdatesModel::lastUpdate() const
return ret;
}
void ResourcesUpdatesModel::cancel()
qint64 ResourcesUpdatesModel::secsToLastUpdate() const
{
foreach(AbstractBackendUpdater* upd, m_updaters) {
if(upd->isCancelable())
upd->cancel();
else
qWarning() << "tried to cancel " << upd->metaObject()->className() << "which is not cancelable";
}
return lastUpdate().secsTo(QDateTime::currentDateTime());
}
qint64 ResourcesUpdatesModel::secsToLastUpdate() const
void ResourcesUpdatesModel::setTransaction(UpdateTransaction* transaction)
{
return lastUpdate().secsTo(QDateTime::currentDateTime());
m_transaction = transaction;
connect(m_transaction, &UpdateTransaction::finished, this, &ResourcesUpdatesModel::finished);
connect(m_transaction, &UpdateTransaction::finished, this, &ResourcesUpdatesModel::progressingChanged);
Q_EMIT progressingChanged();
}
#include "ResourcesUpdatesModel.moc"
......@@ -32,14 +32,13 @@ class QAction;
class AbstractBackendUpdater;
class ResourcesModel;
class QDBusInterface;
class Transaction;
class UpdateTransaction;
class DISCOVERCOMMON_EXPORT ResourcesUpdatesModel : public QStandardItemModel
{
Q_OBJECT
Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
Q_PROPERTY(QString remainingTime READ remainingTime NOTIFY etaChanged)
Q_PROPERTY(bool isCancelable READ isCancelable NOTIFY cancelableChanged)
Q_PROPERTY(bool isProgressing READ isProgressing NOTIFY progressingChanged)
Q_PROPERTY(QDateTime lastUpdate READ lastUpdate NOTIFY progressingChanged)
Q_PROPERTY(qint64 secsToLastUpdate READ secsToLastUpdate NOTIFY progressingChanged)
......@@ -51,8 +50,6 @@ class DISCOVERCOMMON_EXPORT ResourcesUpdatesModel : public QStandardItemModel
quint64 downloadSpeed() const;
Q_SCRIPTABLE void prepare();
///checks if any of them is cancelable
bool isCancelable() const;
bool isProgressing() const;
QList<AbstractResource*> toUpdate() const;
QDateTime lastUpdate() const;
......@@ -66,27 +63,25 @@ class DISCOVERCOMMON_EXPORT ResourcesUpdatesModel : public QStandardItemModel
void downloadSpeedChanged();
void progressChanged();
void etaChanged();
void cancelableChanged();
void progressingChanged(bool progressing);
void progressingChanged();
void finished();
void resourceProgressed(AbstractResource* resource, qreal progress);
public Q_SLOTS:
void cancel();
void updateAll();
private Q_SLOTS:
void updaterDestroyed(QObject* obj);
void message(const QString& msg);
void slotProgressingChanged();
private:
void init();
void updateFinished();
void setTransaction(UpdateTransaction* transaction);
QVector<AbstractBackendUpdater*> m_updaters;
bool m_lastIsProgressing;
QPointer<Transaction> m_transaction;
QPointer<UpdateTransaction> m_transaction;
};
#endif // RESOURCESUPDATESMODEL_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment