File indexing completed on 2024-05-05 17:33:23

0001 /*
0002  *   SPDX-FileCopyrightText: 2010 Jonathan Thomas <echidnaman@kubuntu.org>
0003  *   SPDX-FileCopyrightText: 2012 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
0004  *
0005  *   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006  */
0007 
0008 #include "TransactionListener.h"
0009 
0010 #include "../resources/AbstractResource.h"
0011 #include "TransactionModel.h"
0012 #include "libdiscover_debug.h"
0013 #include <QMetaProperty>
0014 
0015 TransactionListener::TransactionListener(QObject *parent)
0016     : QObject(parent)
0017     , m_resource(nullptr)
0018     , m_transaction(nullptr)
0019 {
0020     connect(TransactionModel::global(), &TransactionModel::transactionAdded, this, &TransactionListener::transactionAdded);
0021 }
0022 
0023 void TransactionListener::cancel()
0024 {
0025     if (!isCancellable()) {
0026         return;
0027     }
0028     m_transaction->cancel();
0029 }
0030 
0031 bool TransactionListener::isCancellable() const
0032 {
0033     return m_transaction && m_transaction->isCancellable();
0034 }
0035 
0036 bool TransactionListener::isActive() const
0037 {
0038     return m_transaction && m_transaction->status() != Transaction::SetupStatus;
0039 }
0040 
0041 QString TransactionListener::statusText() const
0042 {
0043     QModelIndex index = TransactionModel::global()->indexOf(m_resource);
0044 
0045     return index.data(TransactionModel::StatusTextRole).toString();
0046 }
0047 
0048 void TransactionListener::setResource(AbstractResource *resource)
0049 {
0050     setResourceInternal(resource);
0051     // Catch already-started transactions
0052     setTransaction(TransactionModel::global()->transactionFromResource(resource));
0053 }
0054 
0055 void TransactionListener::setResourceInternal(AbstractResource *resource)
0056 {
0057     if (m_resource == resource)
0058         return;
0059 
0060     m_resource = resource;
0061     Q_EMIT resourceChanged();
0062 }
0063 
0064 void TransactionListener::transactionAdded(Transaction *trans)
0065 {
0066     if (trans->resource() != m_resource)
0067         return;
0068 
0069     setTransaction(trans);
0070 }
0071 
0072 class CheckChange
0073 {
0074 public:
0075     CheckChange(QObject *obj, const QByteArray &prop)
0076         : m_object(obj)
0077         , m_prop(obj->metaObject()->property(obj->metaObject()->indexOfProperty(prop.constData())))
0078         , m_oldValue(m_prop.read(obj))
0079     {
0080         Q_ASSERT(obj->metaObject()->indexOfProperty(prop.constData()) >= 0);
0081     }
0082 
0083     ~CheckChange()
0084     {
0085         const QVariant newValue = m_prop.read(m_object);
0086         if (newValue != m_oldValue) {
0087             QMetaMethod m = m_prop.notifySignal();
0088             m.invoke(m_object, Qt::DirectConnection);
0089         }
0090     }
0091 
0092 private:
0093     QObject *m_object;
0094     QMetaProperty m_prop;
0095     QVariant m_oldValue;
0096 };
0097 
0098 void TransactionListener::setTransaction(Transaction *trans)
0099 {
0100     if (m_transaction == trans) {
0101         return;
0102     }
0103 
0104     if (m_transaction) {
0105         disconnect(m_transaction, nullptr, this, nullptr);
0106     }
0107 
0108     CheckChange change1(this, "isCancellable");
0109     CheckChange change2(this, "isActive");
0110     CheckChange change3(this, "statusText");
0111     CheckChange change4(this, "progress");
0112 
0113     m_transaction = trans;
0114     if (m_transaction) {
0115         connect(m_transaction, &Transaction::cancellableChanged, this, &TransactionListener::cancellableChanged);
0116         connect(m_transaction, &Transaction::statusChanged, this, &TransactionListener::transactionStatusChanged);
0117         connect(m_transaction, &Transaction::progressChanged, this, &TransactionListener::progressChanged);
0118         connect(m_transaction, &QObject::destroyed, this, [this]() {
0119             qCDebug(LIBDISCOVER_LOG) << "destroyed transaction before finishing";
0120             setTransaction(nullptr);
0121         });
0122         setResourceInternal(trans->resource());
0123     }
0124     Q_EMIT transactionChanged(trans);
0125 }
0126 
0127 void TransactionListener::transactionStatusChanged(Transaction::Status status)
0128 {
0129     switch (status) {
0130     case Transaction::CancelledStatus:
0131         setTransaction(nullptr);
0132         Q_EMIT cancelled();
0133         break;
0134     case Transaction::DoneWithErrorStatus:
0135     case Transaction::DoneStatus:
0136         setTransaction(nullptr);
0137         break;
0138     default:
0139         break;
0140     }
0141 
0142     Q_EMIT statusTextChanged();
0143 }
0144 
0145 int TransactionListener::progress() const
0146 {
0147     return m_transaction ? m_transaction->progress() : 0;
0148 }
0149 
0150 #include "moc_TransactionListener.cpp"