File indexing completed on 2024-05-12 05:29:05

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 
0061     m_resource = resource;
0062     Q_EMIT resourceChanged();
0063 }
0064 
0065 void TransactionListener::transactionAdded(Transaction *trans)
0066 {
0067     if (trans->resource() != m_resource) {
0068         return;
0069     }
0070 
0071     setTransaction(trans);
0072 }
0073 
0074 class CheckChange
0075 {
0076 public:
0077     CheckChange(QObject *obj, const QByteArray &prop)
0078         : m_object(obj)
0079         , m_prop(obj->metaObject()->property(obj->metaObject()->indexOfProperty(prop.constData())))
0080         , m_oldValue(m_prop.read(obj))
0081     {
0082         Q_ASSERT(obj->metaObject()->indexOfProperty(prop.constData()) >= 0);
0083     }
0084 
0085     ~CheckChange()
0086     {
0087         const QVariant newValue = m_prop.read(m_object);
0088         if (newValue != m_oldValue) {
0089             QMetaMethod m = m_prop.notifySignal();
0090             m.invoke(m_object, Qt::DirectConnection);
0091         }
0092     }
0093 
0094 private:
0095     QObject *m_object;
0096     QMetaProperty m_prop;
0097     QVariant m_oldValue;
0098 };
0099 
0100 void TransactionListener::setTransaction(Transaction *trans)
0101 {
0102     if (m_transaction == trans) {
0103         return;
0104     }
0105 
0106     if (m_transaction) {
0107         disconnect(m_transaction, nullptr, this, nullptr);
0108     }
0109 
0110     CheckChange change1(this, "isCancellable");
0111     CheckChange change2(this, "isActive");
0112     CheckChange change3(this, "statusText");
0113     CheckChange change4(this, "progress");
0114 
0115     m_transaction = trans;
0116     if (m_transaction) {
0117         connect(m_transaction, &Transaction::cancellableChanged, this, &TransactionListener::cancellableChanged);
0118         connect(m_transaction, &Transaction::statusChanged, this, &TransactionListener::transactionStatusChanged);
0119         connect(m_transaction, &Transaction::progressChanged, this, &TransactionListener::progressChanged);
0120         connect(m_transaction, &QObject::destroyed, this, [this]() {
0121             qCDebug(LIBDISCOVER_LOG) << "destroyed transaction before finishing";
0122             setTransaction(nullptr);
0123         });
0124         setResourceInternal(trans->resource());
0125     }
0126     Q_EMIT transactionChanged(trans);
0127 }
0128 
0129 void TransactionListener::transactionStatusChanged(Transaction::Status status)
0130 {
0131     switch (status) {
0132     case Transaction::CancelledStatus:
0133         setTransaction(nullptr);
0134         Q_EMIT cancelled();
0135         break;
0136     case Transaction::DoneWithErrorStatus:
0137     case Transaction::DoneStatus:
0138         setTransaction(nullptr);
0139         break;
0140     default:
0141         break;
0142     }
0143 
0144     Q_EMIT statusTextChanged();
0145 }
0146 
0147 int TransactionListener::progress() const
0148 {
0149     return m_transaction ? m_transaction->progress() : 0;
0150 }
0151 
0152 #include "moc_TransactionListener.cpp"