diff --git a/programs/light_client/ClientDataModel.cpp b/programs/light_client/ClientDataModel.cpp index b89e2a98..4db9a153 100644 --- a/programs/light_client/ClientDataModel.cpp +++ b/programs/light_client/ClientDataModel.cpp @@ -52,6 +52,50 @@ Asset* ChainDataModel::getAsset(QString symbol) return *itr; } +void ChainDataModel::processUpdatedObject(const fc::variant& update) +{ + if (update.is_null()) + return; + if (&fc::thread::current() == m_rpc_thread) + { + ilog("Proxying object update to app thread."); + Q_EMIT queueExecute([this,update]{processUpdatedObject(update);}); + return; + } + + idump((update)); + try { + auto id = update.as()["id"].as(); + if (id.space() == protocol_ids) { + switch (id.type()) { + default: + wlog("Update procedure for ${update} is not yet implemented.", ("update", update)); + break; + } + } else if (id.space() == implementation_ids) { + switch (id.type()) { + case impl_account_balance_object_type: { + account_balance_object balance = update.as(); + auto owner = m_accounts.find(balance.owner.instance.value); + if (owner != m_accounts.end()) + (*owner)->update(balance); + else + elog("Got unexpected balance update:\n${u}\nfor an account I don't have.", + ("u", update)); + break; + } + + default: + wlog("Update procedure for ${update} is not yet implemented.", ("update", update)); + break; + } + } else + wlog("Update procedure for ${update} is not yet implemented.", ("update", update)); + } catch (const fc::exception& e) { + elog("Caught exception while updating object: ${e}", ("e", e.to_detail_string())); + } +} + void ChainDataModel::getAssetImpl(QString assetIdentifier, Asset* const * assetInContainer) { try { @@ -86,8 +130,8 @@ void ChainDataModel::getAccountImpl(QString accountIdentifier, Account* const * { try { ilog("Fetching account ${acct}", ("acct", accountIdentifier.toStdString())); - auto result = m_db_api->get_full_accounts([](const fc::variant& v) { - idump((v)); + auto result = m_db_api->get_full_accounts([this](const fc::variant& v) { + processUpdatedObject(v); }, {accountIdentifier.toStdString()}); fc::optional accountPackage; @@ -203,6 +247,27 @@ QQmlListProperty Account::balances() return QQmlListProperty(this, this, count, at); } +void Account::update(const account_balance_object& balance) +{ + auto balanceItr = std::find_if(m_balances.begin(), m_balances.end(), + [&balance](Balance* b) { return b->type()->id() == balance.asset_type.instance.value; }); + + if (balanceItr != m_balances.end()) { + ilog("Updating ${a}'s balance: ${b}", ("a", m_name.toStdString())("b", balance)); + (*balanceItr)->update(balance); + Q_EMIT balancesChanged(); + } else { + ilog("Adding to ${a}'s new balance: ${b}", ("a", m_name.toStdString())("b", balance)); + Balance* newBalance = new Balance; + newBalance->setParent(this); + auto model = qobject_cast(parent()); + newBalance->setProperty("type", QVariant::fromValue(model->getAsset(balance.asset_type.instance.value))); + newBalance->setProperty("amount", QVariant::fromValue(balance.balance.value)); + m_balances.append(newBalance); + Q_EMIT balancesChanged(); + } +} + GrapheneApplication::GrapheneApplication(QObject* parent) :QObject(parent),m_thread("app") { @@ -268,3 +333,11 @@ Q_SLOT void GrapheneApplication::execute(const std::function& func)const { func(); } + +void Balance::update(const account_balance_object& update) +{ + if (update.balance != amount) { + amount = update.balance.value; + emit amountChanged(); + } +} diff --git a/programs/light_client/ClientDataModel.hpp b/programs/light_client/ClientDataModel.hpp index 5f6c99da..7c1db5e0 100644 --- a/programs/light_client/ClientDataModel.hpp +++ b/programs/light_client/ClientDataModel.hpp @@ -97,18 +97,24 @@ typedef multi_index_container< class Balance : public GrapheneObject { Q_OBJECT - Q_PROPERTY(Asset* type MEMBER type NOTIFY typeChanged) + Q_PROPERTY(Asset* type MEMBER m_type READ type NOTIFY typeChanged) Q_PROPERTY(qint64 amount MEMBER amount NOTIFY amountChanged) - Asset* type; + Asset* m_type; qint64 amount; public: // This ultimately needs to be replaced with a string equivalent Q_INVOKABLE qreal amountReal() const { - return amount / qreal(type->precisionPower()); + return amount / qreal(m_type->precisionPower()); } + Asset* type()const { + return m_type; + } + + void update(const graphene::app::account_balance_object& update); + Q_SIGNALS: void typeChanged(); void amountChanged(); @@ -138,6 +144,8 @@ public: } } + void update(const graphene::app::account_balance_object& balance); + Q_SIGNALS: void nameChanged(); void balancesChanged(); @@ -155,6 +163,8 @@ typedef multi_index_container< class ChainDataModel : public QObject { Q_OBJECT + void processUpdatedObject(const fc::variant& update); + void getAssetImpl(QString assetIdentifier, Asset* const * assetInContainer); void getAccountImpl(QString accountIdentifier, Account* const * accountInContainer);