Browse Source

QML stuff.

cl-refactor
Gav Wood 11 years ago
parent
commit
084aabfb02
  1. 4
      libethereum/Client.h
  2. 204
      walleth/MainWin.cpp
  3. 79
      walleth/MainWin.h
  4. 30
      walleth/Simple.qml

4
libethereum/Client.h

@ -121,6 +121,8 @@ public:
void connect(std::string const& _seedHost, unsigned short _port = 30303);
/// Stop the network subsystem.
void stopNetwork();
/// Is the network subsystem up?
bool haveNetwork() { return !!m_net; }
/// Get access to the peer server object. This will be null if the network isn't online.
PeerServer* peerServer() const { return m_net.get(); }
@ -134,6 +136,8 @@ public:
void startMining();
/// Stop mining.
void stopMining();
/// Are we mining now?
bool isMining() { return m_doMine; }
/// Check the progress of the mining.
MineProgress miningProgress() const { return m_mineProgress; }

204
walleth/MainWin.cpp

@ -51,57 +51,132 @@ using eth::g_logPost;
using eth::g_logVerbosity;
using eth::c_instructionInfo;
// Horrible global for the mainwindow. Needed for the QEthereums to find the Main window which acts as multiplexer for now.
// Can get rid of this once we've sorted out ITC for signalling & multiplexed querying.
Main* g_main = nullptr;
#define ADD_QUOTES_HELPER(s) #s
#define ADD_QUOTES(s) ADD_QUOTES_HELPER(s)
QEthereum::QEthereum(QObject* _p): QObject(_p)
{
m_client.reset(new Client("Walleth", Address(), eth::getDataDir() + "/Walleth"));
startTimer(200);
connect(g_main, SIGNAL(changed()), SIGNAL(changed()));
}
QEthereum::~QEthereum()
{
}
Address QEthereum::address() const
Client* QEthereum::client() const
{
return g_main->client();
}
Address QEthereum::coinbase() const
{
return client()->address();
}
void QEthereum::setCoinbase(Address _a)
{
if (client()->address() != _a)
{
client()->setAddress(_a);
changed();
}
}
QAccount::QAccount(QObject* _p)
{
return m_client->address();
}
void QEthereum::setAddress(Address _a)
QAccount::~QAccount()
{
if (m_client->address() != _a)
}
void QAccount::setEthereum(QEthereum* _eth)
{
m_client->setAddress(_a);
if (m_eth == _eth)
return;
if (m_eth)
disconnect(m_eth, SIGNAL(changed()), this, SIGNAL(changed()));
m_eth = _eth;
if (m_eth)
connect(m_eth, SIGNAL(changed()), this, SIGNAL(changed()));
ethChanged();
changed();
}
u256 QAccount::balance() const
{
if (m_eth)
return m_eth->balanceAt(m_address);
return 0;
}
uint64_t QAccount::txCount() const
{
if (m_eth)
return m_eth->txCountAt(m_address);
return 0;
}
u256 QEthereum::balance() const
bool QAccount::isContract() const
{
return m_client->postState().balance(address());
if (m_eth)
return m_eth->isContractAt(m_address);
return 0;
}
u256 QEthereum::balanceAt(Address _a) const
{
return m_client->postState().balance(_a);
return client()->postState().balance(_a);
}
unsigned QEthereum::peerCount() const
bool QEthereum::isContractAt(Address _a) const
{
return m_client->peerCount();
return client()->postState().isContractAddress(_a);
}
void QEthereum::transact(Secret _secret, Address _dest, u256 _amount)
bool QEthereum::isMining() const
{
m_client->transact(_secret, _dest, _amount);
return client()->isMining();
}
void QEthereum::timerEvent(QTimerEvent *)
bool QEthereum::isListening() const
{
if (m_client->changed())
changed();
return client()->haveNetwork();
}
void QEthereum::setMining(bool _l)
{
if (_l)
client()->startMining();
else
client()->stopMining();
}
void QEthereum::setListening(bool _l)
{
if (_l)
client()->startNetwork();
else
client()->stopNetwork();
}
uint64_t QEthereum::txCountAt(Address _a) const
{
return (uint64_t)client()->postState().transactionsFrom(_a);
}
unsigned QEthereum::peerCount() const
{
return client()->peerCount();
}
void QEthereum::transact(Secret _secret, Address _dest, u256 _amount)
{
client()->transact(_secret, _dest, _amount);
}
Main::Main(QWidget *parent) :
@ -110,56 +185,42 @@ Main::Main(QWidget *parent) :
{
setWindowFlags(Qt::Window);
ui->setupUi(this);
setWindowIcon(QIcon(":/Ethereum.png"));
g_main = this;
m_client.reset(new Client("Walleth", Address(), eth::getDataDir() + "/Walleth"));
qRegisterMetaType<eth::u256>("eth::u256");
qRegisterMetaType<eth::KeyPair>("eth::KeyPair");
qRegisterMetaType<eth::Secret>("eth::Secret");
qRegisterMetaType<eth::Address>("eth::Address");
qRegisterMetaType<QAccount*>("QAccount*");
qRegisterMetaType<QEthereum*>("QEthereum*");
qmlRegisterType<QEthereum>("org.ethereum", 1, 0, "Ethereum");
qmlRegisterType<QAccount>("org.ethereum", 1, 0, "Account");
qmlRegisterSingletonType<U256Helper>("org.ethereum", 1, 0, "Balance", QEthereum::constructU256Helper);
qmlRegisterSingletonType<KeyHelper>("org.ethereum", 1, 0, "Key", QEthereum::constructKeyHelper);
/*
ui->librariesView->setModel(m_libraryMan);
ui->graphsView->setModel(m_graphMan);
setWindowIcon(QIcon(":/Noted.png"));
*/
// TODO: Figure out why not working.
// qmlRegisterSingletonType<U256Helper>("org.ethereum", 1, 0, "balance", QEthereum::constructU256Helper);
// qmlRegisterSingletonType<KeyHelper>("org.ethereum", 1, 0, "key", QEthereum::constructKeyHelper);
/* qmlRegisterType<GraphItem>("com.llr", 1, 0, "Graph");
qmlRegisterType<CursorGraphItem>("com.llr", 1, 0, "CursorGraph");
qmlRegisterType<IntervalItem>("com.llr", 1, 0, "Interval");
qmlRegisterType<CursorItem>("com.llr", 1, 0, "Cursor");
qmlRegisterType<TimelinesItem>("com.llr", 1, 0, "Timelines");
qmlRegisterType<TimeLabelsItem>("com.llr", 1, 0, "TimeLabels");
qmlRegisterType<XLabelsItem>("com.llr", 1, 0, "XLabels");
qmlRegisterType<XScaleItem>("com.llr", 1, 0, "XScale");
qmlRegisterType<YLabelsItem>("com.llr", 1, 0, "YLabels");
qmlRegisterType<YScaleItem>("com.llr", 1, 0, "YScale");
*/
m_view = new QQuickView();
QQmlContext* context = m_view->rootContext();
m_eth = new QEthereum();
context->setContextProperty("eth", m_eth);
// TODO: should be singletons.
context->setContextProperty("u256", new U256Helper(this));
context->setContextProperty("key", new KeyHelper(this));
m_view = new QQuickView();
/* context->setContextProperty("compute", compute());
context->setContextProperty("data", data());
context->setContextProperty("graphs", graphs());
context->setContextProperty("audio", audio());
context->setContextProperty("view", view());
*/ m_view->setSource(QUrl("qrc:/Simple.qml"));
// QQmlContext* context = m_view->rootContext();
// context->setContextProperty("u256", new U256Helper(this));
m_view->setSource(QUrl("qrc:/Simple.qml"));
QWidget* w = QWidget::createWindowContainer(m_view);
m_view->setResizeMode(QQuickView::SizeRootObjectToView);
ui->fullDisplay->insertWidget(0, w);
m_view->create();
/*
m_timelinesItem = m_view->rootObject()->findChild<TimelinesItem*>("timelines");
qDebug() << m_view->rootObject();
*/
// m_timelinesItem = m_view->rootObject()->findChild<TimelinesItem*>("timelines");
readSettings();
refresh();
@ -167,6 +228,7 @@ Main::Main(QWidget *parent) :
m_refreshNetwork = new QTimer(this);
connect(m_refreshNetwork, SIGNAL(timeout()), SLOT(refreshNetwork()));
m_refreshNetwork->start(1000);
connect(this, SIGNAL(changed()), SLOT(refresh()));
connect(&m_webCtrl, &QNetworkAccessManager::finished, [&](QNetworkReply* _r)
@ -183,6 +245,8 @@ Main::Main(QWidget *parent) :
m_webCtrl.get(r);
srand(time(0));
startTimer(200);
statusBar()->addPermanentWidget(ui->balance);
statusBar()->addPermanentWidget(ui->peerCount);
statusBar()->addPermanentWidget(ui->blockCount);
@ -193,9 +257,15 @@ Main::~Main()
writeSettings();
}
void Main::timerEvent(QTimerEvent *)
{
if (m_client->changed())
changed();
}
void Main::on_about_triggered()
{
QMessageBox::about(this, "About Walleth PoC-" + QString(ADD_QUOTES(ETH_VERSION)).section('.', 1, 1), "AlethZero/v" ADD_QUOTES(ETH_VERSION) "/" ADD_QUOTES(ETH_BUILD_TYPE) "/" ADD_QUOTES(ETH_BUILD_PLATFORM) "\nBy Gav Wood, 2014.\nBased on a design by Vitalik Buterin.\n\nTeam Ethereum++ includes: Tim Hughes, Eric Lombrozo, Marko Simovic, Alex Leverington and several others.");
QMessageBox::about(this, "About Walleth PoC-" + QString(ADD_QUOTES(ETH_VERSION)).section('.', 1, 1), "Walleth/v" ADD_QUOTES(ETH_VERSION) "/" ADD_QUOTES(ETH_BUILD_TYPE) "/" ADD_QUOTES(ETH_BUILD_PLATFORM) "\nBy Gav Wood, 2014.\nBased on a design by Vitalik Buterin.\n\nTeam Ethereum++ includes: Tim Hughes, Eric Lombrozo, Marko Simovic, Alex Leverington and several others.");
}
void Main::writeSettings()
@ -216,9 +286,9 @@ void Main::writeSettings()
s.setValue("idealPeers", m_idealPeers);
s.setValue("port", m_port);
if (m_eth->client()->peerServer())
if (client()->peerServer())
{
bytes d = m_eth->client()->peerServer()->savePeers();
bytes d = client()->peerServer()->savePeers();
m_peers = QByteArray((char*)d.data(), (int)d.size());
}
@ -248,7 +318,7 @@ void Main::readSettings()
m_myKeys.append(KeyPair(k));
}
}
m_eth->setAddress(m_myKeys.last().address());
//m_eth->setAddress(m_myKeys.last().address());
m_peers = s.value("peers").toByteArray();
ui->upnp->setChecked(s.value("upnp", true).toBool());
m_clientName = s.value("clientName", "").toString();
@ -258,22 +328,22 @@ void Main::readSettings()
void Main::refreshNetwork()
{
auto ps = m_eth->client()->peers();
auto ps = client()->peers();
ui->peerCount->setText(QString::fromStdString(toString(ps.size())) + " peer(s)");
}
eth::State const& Main::state() const
{
return ui->preview->isChecked() ? m_eth->client()->postState() : m_eth->client()->state();
return ui->preview->isChecked() ? client()->postState() : client()->state();
}
void Main::refresh()
{
eth::ClientGuard l(m_eth->client());
eth::ClientGuard l(client());
auto const& st = state();
auto d = m_eth->client()->blockChain().details();
auto diff = BlockInfo(m_eth->client()->blockChain().block()).difficulty;
auto d = client()->blockChain().details();
auto diff = BlockInfo(client()->blockChain().block()).difficulty;
ui->blockCount->setText(QString("#%1 @%3 T%2").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)));
m_keysChanged = false;
@ -292,21 +362,21 @@ void Main::on_net_triggered(bool _auto)
if (m_clientName.size())
n += "/" + m_clientName.toStdString();
n += "/" ADD_QUOTES(ETH_BUILD_TYPE) "/" ADD_QUOTES(ETH_BUILD_PLATFORM);
m_eth->client()->setClientVersion(n);
client()->setClientVersion(n);
if (ui->net->isChecked())
{
if (_auto)
{
QString s = m_servers[rand() % m_servers.size()];
m_eth->client()->startNetwork(m_port, s.section(':', 0, 0).toStdString(), s.section(':', 1).toInt(), NodeMode::Full, m_idealPeers, std::string(), ui->upnp->isChecked());
client()->startNetwork(m_port, s.section(':', 0, 0).toStdString(), s.section(':', 1).toInt(), NodeMode::Full, m_idealPeers, std::string(), ui->upnp->isChecked());
}
else
m_eth->client()->startNetwork(m_port, string(), 0, NodeMode::Full, m_idealPeers, std::string(), ui->upnp->isChecked());
client()->startNetwork(m_port, string(), 0, NodeMode::Full, m_idealPeers, std::string(), ui->upnp->isChecked());
if (m_peers.size())
m_eth->client()->peerServer()->restorePeers(bytesConstRef((byte*)m_peers.data(), m_peers.size()));
client()->peerServer()->restorePeers(bytesConstRef((byte*)m_peers.data(), m_peers.size()));
}
else
m_eth->client()->stopNetwork();
client()->stopNetwork();
}
void Main::on_connect_triggered()
@ -322,7 +392,7 @@ void Main::on_connect_triggered()
{
string host = s.section(":", 0, 0).toStdString();
unsigned short port = s.section(":", 1).toInt();
m_eth->client()->connect(host, port);
client()->connect(host, port);
}
}
@ -330,11 +400,11 @@ void Main::on_mine_triggered()
{
if (ui->mine->isChecked())
{
m_eth->client()->setAddress(m_myKeys.last().address());
m_eth->client()->startMining();
client()->setAddress(m_myKeys.last().address());
client()->startMining();
}
else
m_eth->client()->stopMining();
client()->stopMining();
}
void Main::on_create_triggered()

79
walleth/MainWin.h

@ -17,14 +17,18 @@ class State;
}
class QQuickView;
class QEthereum;
class QQmlEngine;
class QJSEngine;
class QEthereum;
class QAccount;
Q_DECLARE_METATYPE(eth::u256)
Q_DECLARE_METATYPE(eth::Address)
Q_DECLARE_METATYPE(eth::Secret)
Q_DECLARE_METATYPE(eth::KeyPair)
Q_DECLARE_METATYPE(QEthereum*)
Q_DECLARE_METATYPE(QAccount*)
class U256Helper: public QObject
{
@ -74,6 +78,39 @@ public:
Q_INVOKABLE QString toAbridged(eth::Address _a) const { return QString::fromStdString(_a.abridged()); }
};
class QAccount: public QObject
{
Q_OBJECT
public:
QAccount(QObject* _p = nullptr);
virtual ~QAccount();
Q_INVOKABLE QEthereum* ethereum() const { return m_eth; }
Q_INVOKABLE eth::u256 balance() const;
Q_INVOKABLE uint64_t txCount() const;
Q_INVOKABLE bool isContract() const;
// TODO: past transactions models.
public slots:
void setEthereum(QEthereum* _eth);
signals:
void changed();
void ethChanged();
private:
QEthereum* m_eth = nullptr;
eth::Address m_address;
Q_PROPERTY(eth::u256 balance READ balance NOTIFY changed STORED false)
Q_PROPERTY(uint64_t txCount READ txCount NOTIFY changed STORED false)
Q_PROPERTY(bool isContract READ isContract NOTIFY changed STORED false)
Q_PROPERTY(eth::Address address MEMBER m_address NOTIFY changed)
Q_PROPERTY(QEthereum* ethereum READ ethereum WRITE setEthereum NOTIFY ethChanged)
};
class QEthereum: public QObject
{
Q_OBJECT
@ -82,33 +119,41 @@ public:
QEthereum(QObject* _p = nullptr);
virtual ~QEthereum();
eth::Client* client() const { return m_client.get(); }
eth::Client* client() const;
static QObject* constructU256Helper(QQmlEngine*, QJSEngine*) { return new U256Helper; }
static QObject* constructKeyHelper(QQmlEngine*, QJSEngine*) { return new KeyHelper; }
eth::u256 balance() const;
Q_INVOKABLE eth::Address coinbase() const;
Q_INVOKABLE bool isListening() const;
Q_INVOKABLE bool isMining() const;
Q_INVOKABLE eth::Address address() const;
Q_INVOKABLE eth::u256 balanceAt(eth::Address _a) const;
Q_INVOKABLE uint64_t txCountAt(eth::Address _a) const;
Q_INVOKABLE bool isContractAt(eth::Address _a) const;
Q_INVOKABLE unsigned peerCount() const;
Q_INVOKABLE QEthereum* self() { return this; }
public slots:
void transact(eth::Secret _secret, eth::Address _dest, eth::u256 _amount);
void setAddress(eth::Address);
void setCoinbase(eth::Address);
void setMining(bool _l);
void setListening(bool _l);
signals:
void changed();
protected:
virtual void timerEvent(QTimerEvent *);
// void netChanged();
// void miningChanged();
private:
Q_PROPERTY(eth::u256 balance READ balance NOTIFY changed)
Q_PROPERTY(eth::Address address READ address WRITE setAddress NOTIFY changed)
std::unique_ptr<eth::Client> m_client;
Q_PROPERTY(eth::Address coinbase READ coinbase WRITE setCoinbase NOTIFY changed)
Q_PROPERTY(bool listening READ isListening WRITE setListening)
Q_PROPERTY(bool mining READ isMining WRITE setMining)
};
class Main : public QMainWindow
@ -119,6 +164,8 @@ public:
explicit Main(QWidget *parent = 0);
~Main();
eth::Client* client() const { return m_client.get(); }
private slots:
void on_connect_triggered();
void on_mine_triggered();
@ -131,6 +178,12 @@ private slots:
void refresh();
void refreshNetwork();
signals:
void changed();
protected:
virtual void timerEvent(QTimerEvent *);
private:
/* QString pretty(eth::Address _a) const;
QString render(eth::Address _a) const;
@ -163,7 +216,7 @@ private:
QNetworkAccessManager m_webCtrl;
QEthereum* m_eth;
std::unique_ptr<eth::Client> m_client;
};
#endif // MAIN_H

30
walleth/Simple.qml

@ -1,14 +1,36 @@
import QtQml 2.2
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
//import org.ethereum 1.0
import Qt.labs.settings 1.0
import org.ethereum 1.0
Label {
Item {
id: main
anchors.fill: parent
anchors.margins: 9
Label {
text: "Balance: " + u256.stringOf(eth.balance) + "\nAccount: " + key.stringOf(eth.address)
Qt.application.name: "Walleth"
Qt.application.organization: "Ethereum"
Qt.application.domain: "org.ethereum"
Ethereum {
id: eth
}
Account {
id: myAccount
address: Key.addressOf("84fc4ba9373c30bfe32d8c5a502854e7f1175878")
ethereum: eth
// TODO: state: eth.latest // could be eth.pending
// will provide balance, txCount, isContract, incomingTransactions (list model), outgoingTransactions (list model).
// transaction lists' items will provide value, from, to, final balance.
}
// KeyPair provides makeTransaction(recvAddress, value, data (array))
Text {
text: "Balance: " + Balance.stringOf(myAccount.balance) + "[" + myAccount.txCount + "]" + "\nAccount: " + Key.stringOf(myAccount.address)
Layout.minimumHeight: 30
Layout.fillHeight: true
Layout.fillWidth: true

Loading…
Cancel
Save