From f01a5889e6f8720c82c4cef9bb8aeb11de1f2d12 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Mon, 13 Jul 2015 15:41:06 -0400 Subject: [PATCH] Added ability to fetch accounts --- programs/light_client/ClientDataModel.cpp | 103 ++++++++++++++++++++-- programs/light_client/ClientDataModel.hpp | 67 +++++++++++--- 2 files changed, 150 insertions(+), 20 deletions(-) diff --git a/programs/light_client/ClientDataModel.cpp b/programs/light_client/ClientDataModel.cpp index f40f9b6d..3c3fcfd3 100644 --- a/programs/light_client/ClientDataModel.cpp +++ b/programs/light_client/ClientDataModel.cpp @@ -10,20 +10,94 @@ using namespace graphene::app; ChainDataModel::ChainDataModel( fc::thread& t, QObject* parent ) :QObject(parent),m_thread(&t){} -Account* ChainDataModel::getAccount(quint64 id) const +Account* ChainDataModel::getAccount(qint64 id) { - auto acct = new Account; + auto itr = m_accounts.find( id ); + if( itr != m_accounts.end() ) + return *itr; + + auto acct = new Account(this); acct->setProperty("id", id); - acct->setProperty("name", "joe"); + acct->setProperty("name", "LOADING"); + auto insert_result = m_accounts.insert( acct ); + + /** execute in app thread */ + m_thread->async( [=](){ + try { + auto result = m_db_api->get_accounts( {account_id_type(id)} ); + if( result.size() && result.front().valid() ) + { + QString name = QString::fromStdString( result.front()->name ); + /** execute in main */ + Q_EMIT queueExecute( [=](){ + this->m_accounts.modify( insert_result.first, + [=]( Account* a ){ a->setProperty("name", name ); } + ); + }); + } + else + { + /** execute in main */ + Q_EMIT queueExecute( [=](){ + acct->deleteLater(); + m_accounts.erase( insert_result.first ); + }); + } + } + catch ( const fc::exception& e ) + { + Q_EMIT exceptionThrown( QString::fromStdString(e.to_string()) ); + } + }); + return acct; } -Account*ChainDataModel::getAccount(QString name) const +Account* ChainDataModel::getAccount(QString name) { - auto acct = new Account; - acct->setProperty("id", 800); + auto itr = m_accounts.get<::by_name>().find(name); + if( itr != m_accounts.get<::by_name>().end() ) + { + return *itr; + } + + + auto acct = new Account(this); + acct->setProperty("id", --m_account_query_num ); acct->setProperty("name", name); - return acct; + auto insert_result = m_accounts.insert( acct ); + + /** execute in app thread */ + m_thread->async( [=](){ + try { + auto result = m_db_api->lookup_account_names( {name.toStdString()} ); + if( result.size() && result.front().valid() ) + { + /** execute in main */ + Q_EMIT queueExecute( [=](){ + this->m_accounts.modify( insert_result.first, + [=]( Account* a ){ + a->setProperty("id", result.front()->id.instance() ); + } + ); + }); + } + else + { + /** execute in main */ + Q_EMIT queueExecute( [=](){ + acct->deleteLater(); + m_accounts.erase( insert_result.first ); + }); + } + } + catch ( const fc::exception& e ) + { + Q_EMIT exceptionThrown( QString::fromStdString(e.to_string()) ); + } + }); + + return nullptr; } QQmlListProperty Account::balances() @@ -38,6 +112,12 @@ GrapheneApplication::GrapheneApplication( QObject* parent ) this, &GrapheneApplication::execute ); m_model = new ChainDataModel( m_thread, this ); + + connect( m_model, &ChainDataModel::queueExecute, + this, &GrapheneApplication::execute ); + + connect( m_model, &ChainDataModel::exceptionThrown, + this, &GrapheneApplication::exceptionThrown ); } GrapheneApplication::~GrapheneApplication() @@ -64,17 +144,22 @@ void GrapheneApplication::start( QString apiurl, QString user, QString pass ) auto con = m_client.connect( apiurl.toStdString() ); auto apic = std::make_shared(*con); auto remote_api = apic->get_remote_api< login_api >(1); + auto db_api = apic->get_remote_api< database_api >(0); if( !remote_api->login( user.toStdString(), pass.toStdString() ) ) { - // TODO: emit error + Q_EMIT loginFailed(); return; } + queueExecute( [=](){ + m_model->setDatabaseAPI( db_api ); + }); + queueExecute( [=](){setIsConnected( true );} ); } catch ( const fc::exception& e ) { - + Q_EMIT exceptionThrown( QString::fromStdString(e.to_string()) ); } } Q_SLOT void GrapheneApplication::execute( const std::function& func )const diff --git a/programs/light_client/ClientDataModel.hpp b/programs/light_client/ClientDataModel.hpp index 95ecf6e8..2ff7214f 100644 --- a/programs/light_client/ClientDataModel.hpp +++ b/programs/light_client/ClientDataModel.hpp @@ -1,11 +1,21 @@ #pragma once #pragma GCC diagnostic ignored "-Wunknown-pragmas" + +#include +#include +#include +#include +#include + #include #include +#include #include #include +using boost::multi_index_container; +using namespace boost::multi_index; Q_DECLARE_METATYPE(std::function) @@ -14,11 +24,11 @@ class Asset : public QObject { Q_OBJECT Q_PROPERTY(QString symbol MEMBER symbol) - Q_PROPERTY(quint64 id MEMBER id) + Q_PROPERTY(qint64 id MEMBER id) Q_PROPERTY(quint8 precision MEMBER precision) QString symbol; - quint64 id; + qint64 id; quint8 precision; }; @@ -27,46 +37,79 @@ class Balance : public QObject { Q_PROPERTY(Asset* type MEMBER type) Q_PROPERTY(qint64 amount MEMBER amount) - Q_PROPERTY(quint64 id MEMBER id) + Q_PROPERTY(qint64 id MEMBER id) Asset* type; qint64 amount; - quint64 id; + qint64 id; }; class Account : public QObject { Q_OBJECT Q_PROPERTY(QString name MEMBER name) - Q_PROPERTY(quint64 id MEMBER id) + Q_PROPERTY(qint64 id MEMBER id) Q_PROPERTY(QQmlListProperty balances READ balances) QString name; - quint64 id; + qint64 id; QList m_balances; public: Account(QObject* parent = nullptr) : QObject(parent){} + const QString& getName()const { return name; } + qint64 getId()const { return id; } + QQmlListProperty balances(); }; +struct by_id; +struct by_name; +/** + * @ingroup object_index + */ +typedef multi_index_container< + Account*, + indexed_by< + hashed_unique< tag, const_mem_fun >, + ordered_non_unique< tag, const_mem_fun > + > +> account_multi_index_type; + + + + class ChainDataModel : public QObject { Q_OBJECT public: - Q_INVOKABLE Account* getAccount(quint64 id)const; - Q_INVOKABLE Account* getAccount(QString name)const; + Q_INVOKABLE Account* getAccount(qint64 id); + Q_INVOKABLE Account* getAccount(QString name); ChainDataModel(){} ChainDataModel( fc::thread& t, QObject* parent = nullptr ); + void setDatabaseAPI( fc::api dbapi ){ m_db_api = dbapi; } + +Q_SIGNALS: + void queueExecute( const std::function& ); + void exceptionThrown( QString message ); + private: - fc::thread* m_thread = nullptr; - std::string m_api_url; + fc::thread* m_thread = nullptr; + std::string m_api_url; + fc::api m_db_api; + + qint64 m_account_query_num = -1; + account_multi_index_type m_accounts; }; + + + + class GrapheneApplication : public QObject { Q_OBJECT @@ -102,7 +145,9 @@ public: return m_isConnected; } -signals: +Q_SIGNALS: + void exceptionThrown( QString message ); + void loginFailed(); void isConnectedChanged(bool isConnected); void queueExecute( const std::function& ); };