Browse Source

Ethereum QML types: #612

cl-refactor
yann300 10 years ago
committed by yann300
parent
commit
5fa32387d5
  1. 1
      mix/AppContext.cpp
  2. 26
      mix/ClientModel.cpp
  3. 23
      mix/ClientModel.h
  4. 59
      mix/QBigInt.cpp
  5. 88
      mix/QBigInt.h
  6. 55
      mix/QEther.cpp
  7. 86
      mix/QEther.h
  8. 2
      mix/qml.qrc
  9. 106
      mix/qml/Ether.qml
  10. 12
      mix/qml/EtherValue.qml
  11. 28
      mix/qml/StateDialog.qml
  12. 7
      mix/qml/StateList.qml
  13. 60
      mix/qml/TransactionDialog.qml

1
mix/AppContext.cpp

@ -49,6 +49,7 @@ AppContext::AppContext(QQmlApplicationEngine* _engine)
m_applicationEngine->rootContext()->setContextProperty("appContext", this);
qmlRegisterType<FileIo>("org.ethereum.qml", 1, 0, "FileIo");
qmlRegisterSingletonType(QUrl("qrc:/qml/ProjectModel.qml"), "org.ethereum.qml.ProjectModel", 1, 0, "ProjectModel");
qmlRegisterType<QEther>("org.ethereum.qml.QEther", 1, 0, "QEther");
m_applicationEngine->rootContext()->setContextProperty("codeModel", m_codeModel.get());
m_applicationEngine->rootContext()->setContextProperty("fileIo", m_fileIo.get());

26
mix/ClientModel.cpp

@ -37,23 +37,11 @@ using namespace dev;
using namespace dev::eth;
using namespace dev::mix;
/// @todo Move this to QML
dev::u256 fromQString(QString const& _s)
{
return dev::jsToU256(_s.toStdString());
}
/// @todo Move this to QML
QString toQString(dev::u256 _value)
{
std::ostringstream s;
s << _value;
return QString::fromStdString(s.str());
}
ClientModel::ClientModel(AppContext* _context):
m_context(_context), m_running(false)
{
qRegisterMetaType<QBigInt*>("QBigInt*");
qRegisterMetaType<QBigInt*>("QEther*");
qRegisterMetaType<QVariableDefinition*>("QVariableDefinition*");
qRegisterMetaType<QVariableDefinitionList*>("QVariableDefinitionList*");
qRegisterMetaType<QList<QVariableDefinition*>>("QList<QVariableDefinition*>");
@ -74,7 +62,7 @@ void ClientModel::debugDeployment()
void ClientModel::debugState(QVariantMap _state)
{
u256 balance = fromQString(_state.value("balance").toString());
u256 balance = (qvariant_cast<QEther*>(_state.value("balance")))->toU256Wei();
QVariantList transactions = _state.value("transactions").toList();
std::vector<TransactionSettings> transactionSequence;
@ -84,14 +72,14 @@ void ClientModel::debugState(QVariantMap _state)
QVariantMap transaction = t.toMap();
QString functionId = transaction.value("functionId").toString();
u256 value = fromQString(transaction.value("value").toString());
u256 gas = fromQString(transaction.value("gas").toString());
u256 gasPrice = fromQString(transaction.value("gasPrice").toString());
u256 gas = (qvariant_cast<QEther*>(_state.value("gas")))->toU256Wei();
u256 value = (qvariant_cast<QEther*>(_state.value("value")))->toU256Wei();
u256 gasPrice = (qvariant_cast<QEther*>(_state.value("gasPrice")))->toU256Wei();
QVariantMap params = transaction.value("parameters").toMap();
TransactionSettings transactionSettings(functionId, value, gas, gasPrice);
for (auto p = params.cbegin(); p != params.cend(); ++p)
transactionSettings.parameterValues.insert(std::make_pair(p.key(), fromQString(p.value().toString())));
transactionSettings.parameterValues.insert(std::make_pair(p.key(), (qvariant_cast<QEther*>(p.value()))->toU256Wei()));
transactionSequence.push_back(transactionSettings);
}

23
mix/ClientModel.h

@ -1,18 +1,18 @@
/*
This file is part of cpp-ethereum.
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file ClientModel.h
* @author Yann yann@ethdev.com
@ -26,6 +26,7 @@
#include <atomic>
#include "DebuggingStateWrapper.h"
#include "MixClient.h"
#include "QEther.h"
using AssemblyDebuggerData = std::tuple<QList<QObject*>, dev::mix::QQMLMap*>;

59
mix/QBigInt.cpp

@ -0,0 +1,59 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QBigInt.cpp
* @author Yann yann@ethdev.com
* @date 2015
*/
#include "boost/variant/multivisitors.hpp"
#include "boost/variant.hpp"
#include <libdevcore/CommonJS.h>
#include "QBigInt.h"
using namespace dev;
using namespace dev::mix;
QString QBigInt::value() const
{
std::ostringstream s;
s << m_internalValue;
return QString::fromStdString(s.str());
}
QBigInt* QBigInt::subtract(QBigInt* const& _value) const
{
BigIntVariant toSubtract = _value->internalValue();
return new QBigInt(boost::apply_visitor(mix::subtract(), m_internalValue, toSubtract));
}
QBigInt* QBigInt::add(QBigInt* const& _value) const
{
BigIntVariant toAdd = _value->internalValue();
return new QBigInt(boost::apply_visitor(mix::add(), m_internalValue, toAdd));
}
QBigInt* QBigInt::multiply(QBigInt* const& _value) const
{
BigIntVariant toMultiply = _value->internalValue();
return new QBigInt(boost::apply_visitor(mix::multiply(), m_internalValue, toMultiply));
}
QBigInt* QBigInt::divide(QBigInt* const& _value) const
{
BigIntVariant toDivide = _value->internalValue();
return new QBigInt(boost::apply_visitor(mix::divide(), m_internalValue, toDivide));
}

88
mix/QBigInt.h

@ -0,0 +1,88 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QBigInt.h
* @author Yann yann@ethdev.com
* @date 2015
* Represent a big integer (u256, bigint, ...) to be used in QML.
*/
#pragma once
#include "boost/variant.hpp"
#include "boost/variant/multivisitors.hpp"
#include <QObject>
#include <libdevcore/CommonJS.h>
#include <libdevcore/Common.h>
using namespace dev;
namespace dev
{
namespace mix
{
using BigIntVariant = boost::variant<dev::u256, dev::bigint>;
struct add: public boost::static_visitor<BigIntVariant>
{
template<class T1, class T2>
BigIntVariant operator()(T1 _value, T2 _otherValue) const { return _value + _otherValue; }
};
struct subtract: public boost::static_visitor<BigIntVariant>
{
template<class T1, class T2>
BigIntVariant operator()(T1 _value, T2 _otherValue) const { return _value - _otherValue; }
};
struct multiply: public boost::static_visitor<BigIntVariant>
{
template<class T1, class T2>
BigIntVariant operator()(T1 _value, T2 _otherValue) const { return _value * _otherValue; }
};
struct divide: public boost::static_visitor<BigIntVariant>
{
template<class T1, class T2>
BigIntVariant operator()(T1 _value, T2 _otherValue) const { return _value / _otherValue; }
};
class QBigInt: public QObject
{
Q_OBJECT
public:
QBigInt(dev::u256 const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value) {}
QBigInt(dev::bigint const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value) {}
QBigInt(BigIntVariant const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value){}
~QBigInt() {}
BigIntVariant internalValue() { return m_internalValue; }
Q_INVOKABLE QString value() const;
Q_INVOKABLE QBigInt* subtract(QBigInt* const& _value) const;
Q_INVOKABLE QBigInt* add(QBigInt* const& _value) const;
Q_INVOKABLE QBigInt* multiply(QBigInt* const& _value) const;
Q_INVOKABLE QBigInt* divide(QBigInt* const& _value) const;
protected:
BigIntVariant m_internalValue;
};
}
}

55
mix/QEther.cpp

@ -0,0 +1,55 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QEther.cpp
* @author Yann yann@ethdev.com
* @date 2014
*/
#include <QMetaEnum>
#include "QEther.h"
using namespace dev::mix;
QString QEther::format() const
{
return QString::fromStdString(dev::eth::formatBalance(boost::get<dev::u256>(toWei()->internalValue())));
}
QString QEther::unit() const
{
QMetaEnum units = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("EtherUnit"));
const char* key = units.valueToKey(m_currentUnit);
return QString(key);
}
void QEther::setUnit(QString const& _unit)
{
QMetaEnum units = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("EtherUnit"));
m_currentUnit = static_cast<EtherUnit>(units.keysToValue(_unit.toStdString().c_str()));
}
QBigInt* QEther::toWei() const
{
QMetaEnum units = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("EtherUnit"));
const char* key = units.valueToKey(m_currentUnit);
for (std::pair<dev::u256, std::string> rawUnit: dev::eth::units())
{
if (rawUnit.second == QString(key).toStdString())
return multiply(new QBigInt(rawUnit.first));
}
return new QBigInt(dev::u256(0));
}

86
mix/QEther.h

@ -0,0 +1,86 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file QEther.h
* @author Yann yann@ethdev.com
* @date 2014
* Represent an Ether value in QML (mapped to u256 in c++).
*/
#pragma once
#include <QObject>
#include <libethcore/CommonEth.h>
#include "QBigInt.h"
namespace dev
{
namespace mix
{
class QEther: public QBigInt
{
Q_OBJECT
Q_ENUMS(EtherUnit)
Q_PROPERTY(QString value READ value WRITE setValue NOTIFY valueChanged)
Q_PROPERTY(QString unit READ unit WRITE setUnit NOTIFY unitChanged)
public:
enum EtherUnit
{
Uether,
Vether,
Dether,
Nether,
Yether,
Zether,
Eether,
Pether,
Tether,
Gether,
Mether,
grand,
ether,
finney,
szabo,
Gwei,
Mwei,
Kwei,
wei
};
QEther(QObject* _parent = 0): QBigInt(dev::u256(0), _parent), m_currentUnit(EtherUnit::ether) {}
QEther(dev::u256 _value, EtherUnit _unit, QObject* _parent = 0): QBigInt(_value, _parent), m_currentUnit(_unit) {}
~QEther() {}
Q_INVOKABLE QString format() const;
Q_INVOKABLE QBigInt* toWei() const;
Q_INVOKABLE void setValue(QString const& _value) { m_internalValue = dev::jsToU256(_value.toStdString()); }
Q_INVOKABLE QString unit() const;
Q_INVOKABLE void setUnit(QString const& _unit);
dev::u256 toU256Wei() { return boost::get<dev::u256>(toWei()->internalValue()); }
private:
EtherUnit m_currentUnit;
signals:
void valueChanged();
void unitChanged();
};
}
}

2
mix/qml.qrc

@ -40,5 +40,7 @@
<file>qml/CodeEditorView.qml</file>
<file>qml/js/ProjectModel.js</file>
<file>qml/WebPreview.qml</file>
<file>qml/Ether.qml</file>
<file>qml/EtherValue.qml</file>
</qresource>
</RCC>

106
mix/qml/Ether.qml

@ -0,0 +1,106 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.1
Rectangle {
id: etherEdition
property bool displayFormattedValue;
property bool edit;
property variant value;
onValueChanged: update()
Component.onCompleted: update()
function update()
{
etherValueEdit.text = value.value;
selectUnit(value.unit);
}
function selectUnit(unit)
{
for(var i = 0; i < unitsModel.count; ++i)
{
if (unitsModel.get(i).text === unit)
{
units.currentIndex = i;
return;
}
}
}
RowLayout
{
anchors.fill: parent;
id: row
width: 200
height: parent.height
Rectangle
{
width : 200
color: edit ? "blue" : "white"
TextField
{
onTextChanged:
{
value.setValue(text)
formattedValue.text = value.format();
}
width: parent.width
readOnly: !edit
visible: edit
id: etherValueEdit;
}
}
Rectangle
{
Layout.fillWidth: true
id: unitContainer
width: 20
anchors.verticalCenter: parent.verticalCenter
ComboBox
{
id: units
onCurrentTextChanged:
{
value.setUnit(currentText);
formattedValue.text = value.format();
}
model: ListModel {
id: unitsModel
ListElement { text: "wei"; }
ListElement { text: "Kwei"; }
ListElement { text: "Mwei"; }
ListElement { text: "Gwei"; }
ListElement { text: "szabo"; }
ListElement { text: "finney"; }
ListElement { text: "ether"; }
ListElement { text: "grand"; }
ListElement { text: "Mether"; }
ListElement { text: "Gether"; }
ListElement { text: "Tether"; }
ListElement { text: "Pether"; }
ListElement { text: "Eether"; }
ListElement { text: "Zether"; }
ListElement { text: "Yether"; }
ListElement { text: "Nether"; }
ListElement { text: "Dether"; }
ListElement { text: "Vether"; }
ListElement { text: "Uether"; }
}
}
Rectangle
{
anchors.verticalCenter: parent.verticalCenter
anchors.left: units.right
visible: displayFormattedValue
width: 20
Text
{
id: formattedValue
}
}
}
}
}

12
mix/qml/EtherValue.qml

@ -0,0 +1,12 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.1
import org.ethereum.qml.QEther 1.0
QEther
{
id: basicEther
value: "1000000"
unit: "ether"
}

28
mix/qml/StateDialog.qml

@ -2,6 +2,7 @@ import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import QtQuick.Window 2.0
import org.ethereum.qml.QEther 1.0
Window {
modality: Qt.WindowModal
@ -12,7 +13,7 @@ Window {
visible: false
property alias stateTitle: titleField.text
property alias stateBalance: balanceField.text
property alias stateBalance: balanceField.value
property int stateIndex
property var stateTransactions: []
signal accepted
@ -20,7 +21,7 @@ Window {
function open(index, item) {
stateIndex = index;
stateTitle = item.title;
stateBalance = item.balance;
balanceField.value = item.balance;
transactionsModel.clear();
stateTransactions = [];
var transactions = item.transactions;
@ -66,9 +67,15 @@ Window {
Label {
text: qsTr("Balance")
}
TextField {
Ether {
id: balanceField
edit: true
displayFormattedValue: true
Layout.fillWidth: true
value: QEther {
value: "100000"
unit: "ether"
}
}
Label {
@ -114,16 +121,25 @@ Window {
transactionDialog.open(index, transactionsModel.get(index));
}
function ether(_value, _unit)
{
var etherComponent = Qt.createComponent("qrc:/qml/EtherValue.qml");
var ether = etherComponent.createObject(transactionsModel);
ether.setValue(_value);
ether.setUnit(_unit);
return ether;
}
function addTransaction() {
// Set next id here to work around Qt bug
// https://bugreports.qt-project.org/browse/QTBUG-41327
// Second call to signal handler would just edit the item that was just created, no harm done
var item = {
value: "0",
value: ether("0", "ether"),
functionId: "",
gas: "125000",
gasPrice: "100000"
gas: ether("125000", "ether"),
gasPrice: ether("100000", "ether")
};
transactionDialog.open(transactionsModel.count, item);

7
mix/qml/StateList.qml

@ -4,6 +4,7 @@ import QtQuick.Controls 1.1
import QtQuick.Dialogs 1.1
import QtQuick.Layouts 1.1
import org.ethereum.qml.ProjectModel 1.0
import org.ethereum.qml.QEther 1.0
Rectangle {
color: "#ededed"
@ -67,9 +68,13 @@ Rectangle {
id: stateListModel
function addState() {
var etherComponent = Qt.createComponent("qrc:/qml/EtherValue.qml");
var ether = etherComponent.createObject(stateListModel);
ether.setValue("100000000000000000000000000");
ether.setUnit("ether");
var item = {
title: "",
balance: "100000000000000000000000000",
balance: ether,
transactions: []
};
stateDialog.open(stateListModel.count, item);

60
mix/qml/TransactionDialog.qml

@ -2,6 +2,7 @@ import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import QtQuick.Window 2.0
import org.ethereum.qml.QEther 1.0
Window {
modality: Qt.WindowModal
@ -11,9 +12,9 @@ Window {
property int transactionIndex
property alias transactionParams: paramsModel;
property alias gas: gasField.text;
property alias gasPrice: gasPriceField.text;
property alias transactionValue: valueField.text;
property alias gas: gasField.value;
property alias gasPrice: gasPriceField.value;
property alias transactionValue: valueField.value;
property alias functionId: functionComboBox.currentText;
property var itemParams;
@ -21,9 +22,9 @@ Window {
function open(index, item) {
transactionIndex = index;
gas = item.gas;
gasPrice = item.gasPrice;
transactionValue = item.value;
gasField.value = item.gas;
gasPriceField.value = item.gasPrice;
valueField.value = item.value;
var functionId = item.functionId;
itemParams = item.parameters !== undefined ? item.parameters : {};
functionsModel.clear();
@ -53,7 +54,7 @@ Window {
var parameters = func.parameters;
for (var p = 0; p < parameters.length; p++) {
var pname = parameters[p].name;
paramsModel.append({ name: pname, type: parameters[p].type, value: itemParams[pname] !== undefined ? itemParams[pname] : "" });
paramsModel.append({ name: pname, type: parameters[p].type, value: itemParams[pname] !== undefined ? itemParams[pname].value() : "" });
}
}
}
@ -74,7 +75,11 @@ Window {
}
for (var p = 0; p < transactionDialog.transactionParams.count; p++) {
var parameter = transactionDialog.transactionParams.get(p);
item.parameters[parameter.name] = parameter.value;
var etherComponent = Qt.createComponent("qrc:/qml/EtherValue.qml");
var param = etherComponent.createObject(stateListModel);
ether.setValue(parameter.value);
ether.setUnit("ether");
item.parameters[parameter.name] = param;
}
return item;
}
@ -107,25 +112,52 @@ Window {
Label {
text: qsTr("Value")
}
TextField {
id: valueField
Rectangle
{
Layout.fillWidth: true
Ether {
id: valueField
edit: true
displayFormattedValue: true
value: QEther {
value: "100000"
unit: "ether"
}
}
}
Label {
text: qsTr("Gas")
}
TextField {
id: gasField
Rectangle
{
Layout.fillWidth: true
Ether {
id: gasField
edit: true
displayFormattedValue: true
value: QEther {
value: "100000"
unit: "ether"
}
}
}
Label {
text: qsTr("Gas price")
}
TextField {
id: gasPriceField
Rectangle
{
Layout.fillWidth: true
Ether {
id: gasPriceField
edit: true
displayFormattedValue: true
value: QEther {
value: "100000"
unit: "ether"
}
}
}
Label {

Loading…
Cancel
Save