|
|
|
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
|
|
|
|
import "js/TransactionHelper.js" as TransactionHelper
|
|
|
|
|
|
|
|
Window {
|
|
|
|
id: modalTransactionDialog
|
|
|
|
modality: Qt.WindowModal
|
|
|
|
width:640
|
|
|
|
height:640
|
|
|
|
visible: false
|
|
|
|
|
|
|
|
property int transactionIndex
|
|
|
|
property alias transactionParams: paramsModel;
|
|
|
|
property alias gas: gasField.value;
|
|
|
|
property alias gasPrice: gasPriceField.value;
|
|
|
|
property alias transactionValue: valueField.value;
|
|
|
|
property alias functionId: functionComboBox.currentText;
|
|
|
|
property var itemParams;
|
|
|
|
property bool isConstructorTransaction;
|
|
|
|
property bool useTransactionDefaultValue: false
|
|
|
|
property var qType;
|
|
|
|
|
|
|
|
signal accepted;
|
|
|
|
|
|
|
|
function open(index, item) {
|
|
|
|
qType = [];
|
|
|
|
rowFunction.visible = !useTransactionDefaultValue;
|
|
|
|
rowValue.visible = !useTransactionDefaultValue;
|
|
|
|
rowGas.visible = !useTransactionDefaultValue;
|
|
|
|
rowGasPrice.visible = !useTransactionDefaultValue;
|
|
|
|
|
|
|
|
transactionIndex = index;
|
|
|
|
gasField.value = item.gas;
|
|
|
|
gasPriceField.value = item.gasPrice;
|
|
|
|
valueField.value = item.value;
|
|
|
|
var functionId = item.functionId;
|
|
|
|
isConstructorTransaction = item.executeConstructor;
|
|
|
|
rowFunction.visible = !item.executeConstructor;
|
|
|
|
|
|
|
|
itemParams = item.parameters !== undefined ? item.parameters : {};
|
|
|
|
functionsModel.clear();
|
|
|
|
var functionIndex = -1;
|
|
|
|
var functions = codeModel.code.contract.functions;
|
|
|
|
for (var f = 0; f < functions.length; f++) {
|
|
|
|
functionsModel.append({ text: functions[f].name });
|
|
|
|
if (functions[f].name === item.functionId)
|
|
|
|
functionIndex = f;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (functionIndex == -1 && functionsModel.count > 0)
|
|
|
|
functionIndex = 0; //@todo suggest unused function
|
|
|
|
|
|
|
|
functionComboBox.currentIndex = functionIndex;
|
|
|
|
paramsModel.clear();
|
|
|
|
if (!item.executeConstructor)
|
|
|
|
loadParameters();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var parameters = codeModel.code.contract.constructor.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].value() : "" });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
visible = true;
|
|
|
|
valueField.focus = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
function loadParameters() {
|
|
|
|
paramsModel.clear();
|
|
|
|
if (!paramsModel)
|
|
|
|
return;
|
|
|
|
if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) {
|
|
|
|
var func = codeModel.code.contract.functions[functionComboBox.currentIndex];
|
|
|
|
var parameters = func.parameters;
|
|
|
|
for (var p = 0; p < parameters.length; p++) {
|
|
|
|
var pname = parameters[p].name;
|
|
|
|
var varComponent;
|
|
|
|
var type = parameters[p].type;
|
|
|
|
|
|
|
|
if (type.indexOf("int") !== -1)
|
|
|
|
varComponent = Qt.createComponent("qrc:/qml/QIntType.qml");
|
|
|
|
else if (type.indexOf("real") !== -1)
|
|
|
|
varComponent = Qt.createComponent("qrc:/qml/QRealType.qml");
|
|
|
|
else if (type.indexOf("string") !== -1 || type.indexOf("text") !== -1)
|
|
|
|
varComponent = Qt.createComponent("qrc:/qml/QStringType.qml");
|
|
|
|
else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1)
|
|
|
|
varComponent = Qt.createComponent("qrc:/qml/QHashType.qml");
|
|
|
|
else if (type.indexOf("bool") !== -1)
|
|
|
|
varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml");
|
|
|
|
|
|
|
|
var param = varComponent.createObject(modalTransactionDialog);
|
|
|
|
var value = itemParams[pname] !== undefined ? itemParams[pname] : "";
|
|
|
|
|
|
|
|
param.setValue(value);
|
|
|
|
param.setDeclaration(parameters[p]);
|
|
|
|
qType.push({ name: pname, value: param });
|
|
|
|
paramsModel.append({ name: pname, type: parameters[p].type, value: value });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function close()
|
|
|
|
{
|
|
|
|
visible = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
function qTypeParam(name)
|
|
|
|
{
|
|
|
|
for (var k in qType)
|
|
|
|
{
|
|
|
|
if (qType[k].name === name)
|
|
|
|
return qType[k].value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function getItem()
|
|
|
|
{
|
|
|
|
var item;
|
|
|
|
if (!useTransactionDefaultValue)
|
|
|
|
{
|
|
|
|
item = {
|
|
|
|
functionId: transactionDialog.functionId,
|
|
|
|
gas: transactionDialog.gas,
|
|
|
|
gasPrice: transactionDialog.gasPrice,
|
|
|
|
value: transactionDialog.transactionValue,
|
|
|
|
parameters: {},
|
|
|
|
executeConstructor: isConstructorTransaction
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
item = TransactionHelper.defaultTransaction();
|
|
|
|
item.functionId = transactionDialog.functionId;
|
|
|
|
item.executeConstructor = isConstructorTransaction;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isConstructorTransaction)
|
|
|
|
item.functionId = qsTr("Constructor");
|
|
|
|
|
|
|
|
var orderedQType = [];
|
|
|
|
for (var p = 0; p < transactionDialog.transactionParams.count; p++) {
|
|
|
|
var parameter = transactionDialog.transactionParams.get(p);
|
|
|
|
var qtypeParam = qTypeParam(parameter.name);
|
|
|
|
qtypeParam.setValue(parameter.value);
|
|
|
|
orderedQType.push(qtypeParam);
|
|
|
|
item.parameters[parameter.name] = parameter.value;
|
|
|
|
}
|
|
|
|
item.qType = orderedQType;
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
|
|
|
ColumnLayout {
|
|
|
|
id: dialogContent
|
|
|
|
width: parent.width
|
|
|
|
anchors.left: parent.left
|
|
|
|
anchors.right: parent.right
|
|
|
|
anchors.margins: 10
|
|
|
|
spacing: 30
|
|
|
|
RowLayout
|
|
|
|
{
|
|
|
|
id: rowFunction
|
|
|
|
Layout.fillWidth: true
|
|
|
|
height: 150
|
|
|
|
Label {
|
|
|
|
Layout.preferredWidth: 75
|
|
|
|
text: qsTr("Function")
|
|
|
|
}
|
|
|
|
ComboBox {
|
|
|
|
id: functionComboBox
|
|
|
|
Layout.fillWidth: true
|
|
|
|
currentIndex: -1
|
|
|
|
textRole: "text"
|
|
|
|
editable: false
|
|
|
|
model: ListModel {
|
|
|
|
id: functionsModel
|
|
|
|
}
|
|
|
|
onCurrentIndexChanged: {
|
|
|
|
loadParameters();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RowLayout
|
|
|
|
{
|
|
|
|
id: rowValue
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Label {
|
|
|
|
Layout.preferredWidth: 75
|
|
|
|
text: qsTr("Value")
|
|
|
|
}
|
|
|
|
Rectangle
|
|
|
|
{
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Ether {
|
|
|
|
id: valueField
|
|
|
|
edit: true
|
|
|
|
displayFormattedValue: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RowLayout
|
|
|
|
{
|
|
|
|
id: rowGas
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Label {
|
|
|
|
Layout.preferredWidth: 75
|
|
|
|
text: qsTr("Gas")
|
|
|
|
}
|
|
|
|
Rectangle
|
|
|
|
{
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Ether {
|
|
|
|
id: gasField
|
|
|
|
edit: true
|
|
|
|
displayFormattedValue: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RowLayout
|
|
|
|
{
|
|
|
|
id: rowGasPrice
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Label {
|
|
|
|
Layout.preferredWidth: 75
|
|
|
|
text: qsTr("Gas Price")
|
|
|
|
}
|
|
|
|
Rectangle
|
|
|
|
{
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Ether {
|
|
|
|
id: gasPriceField
|
|
|
|
edit: true
|
|
|
|
displayFormattedValue: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RowLayout
|
|
|
|
{
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Label {
|
|
|
|
text: qsTr("Parameters")
|
|
|
|
Layout.preferredWidth: 75
|
|
|
|
}
|
|
|
|
TableView {
|
|
|
|
model: paramsModel
|
|
|
|
Layout.preferredWidth: 120 * 2 + 240
|
|
|
|
Layout.minimumHeight: 150
|
|
|
|
Layout.preferredHeight: 400
|
|
|
|
Layout.maximumHeight: 600
|
|
|
|
TableViewColumn {
|
|
|
|
role: "name"
|
|
|
|
title: qsTr("Name")
|
|
|
|
width: 120
|
|
|
|
}
|
|
|
|
TableViewColumn {
|
|
|
|
role: "type"
|
|
|
|
title: qsTr("Type")
|
|
|
|
width: 120
|
|
|
|
}
|
|
|
|
TableViewColumn {
|
|
|
|
role: "value"
|
|
|
|
title: qsTr("Value")
|
|
|
|
width: 240
|
|
|
|
}
|
|
|
|
|
|
|
|
rowDelegate: rowDelegate
|
|
|
|
itemDelegate: editableDelegate
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RowLayout
|
|
|
|
{
|
|
|
|
anchors.bottom: parent.bottom
|
|
|
|
anchors.right: parent.right;
|
|
|
|
|
|
|
|
Button {
|
|
|
|
text: qsTr("OK");
|
|
|
|
onClicked: {
|
|
|
|
close();
|
|
|
|
accepted();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Button {
|
|
|
|
text: qsTr("Cancel");
|
|
|
|
onClicked: close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ListModel {
|
|
|
|
id: paramsModel
|
|
|
|
}
|
|
|
|
|
|
|
|
Component {
|
|
|
|
id: rowDelegate
|
|
|
|
Item {
|
|
|
|
height: 100
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component {
|
|
|
|
id: editableDelegate
|
|
|
|
Item {
|
|
|
|
Loader {
|
|
|
|
id: loaderEditor
|
|
|
|
anchors.fill: parent
|
|
|
|
anchors.margins: 4
|
|
|
|
Connections {
|
|
|
|
target: loaderEditor.item
|
|
|
|
onTextChanged: {
|
|
|
|
if (styleData.role === "value" && styleData.row < paramsModel.count)
|
|
|
|
loaderEditor.updateValue(styleData.row, styleData.role, loaderEditor.item.text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function updateValue(row, role, value)
|
|
|
|
{
|
|
|
|
paramsModel.setProperty(styleData.row, styleData.role, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
sourceComponent:
|
|
|
|
{
|
|
|
|
if (styleData.role === "value")
|
|
|
|
{
|
|
|
|
if (paramsModel.get(styleData.row) === undefined)
|
|
|
|
return null;
|
|
|
|
if (paramsModel.get(styleData.row).type.indexOf("int") !== -1)
|
|
|
|
return intViewComp;
|
|
|
|
else if (paramsModel.get(styleData.row).type.indexOf("bool") !== -1)
|
|
|
|
return boolViewComp;
|
|
|
|
else if (paramsModel.get(styleData.row).type.indexOf("string") !== -1)
|
|
|
|
return stringViewComp;
|
|
|
|
else if (paramsModel.get(styleData.row).type.indexOf("hash") !== -1)
|
|
|
|
return hashViewComp;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return editor;
|
|
|
|
}
|
|
|
|
|
|
|
|
Component
|
|
|
|
{
|
|
|
|
id: intViewComp
|
|
|
|
QIntTypeView
|
|
|
|
{
|
|
|
|
id: intView
|
|
|
|
text: styleData.value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component
|
|
|
|
{
|
|
|
|
id: boolViewComp
|
|
|
|
QBoolTypeView
|
|
|
|
{
|
|
|
|
id: boolView
|
|
|
|
defaultValue: "1"
|
|
|
|
Component.onCompleted:
|
|
|
|
{
|
|
|
|
loaderEditor.updateValue(styleData.row, styleData.role,
|
|
|
|
(paramsModel.get(styleData.row).value === "" ? defaultValue :
|
|
|
|
paramsModel.get(styleData.row).value));
|
|
|
|
text = (paramsModel.get(styleData.row).value === "" ? defaultValue : paramsModel.get(styleData.row).value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component
|
|
|
|
{
|
|
|
|
id: stringViewComp
|
|
|
|
QStringTypeView
|
|
|
|
{
|
|
|
|
id: stringView
|
|
|
|
text: styleData.value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Component
|
|
|
|
{
|
|
|
|
id: hashViewComp
|
|
|
|
QHashTypeView
|
|
|
|
{
|
|
|
|
id: hashView
|
|
|
|
text: styleData.value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component {
|
|
|
|
id: editor
|
|
|
|
TextInput {
|
|
|
|
id: textinput
|
|
|
|
readOnly: true
|
|
|
|
color: styleData.textColor
|
|
|
|
text: styleData.value
|
|
|
|
MouseArea {
|
|
|
|
id: mouseArea
|
|
|
|
anchors.fill: parent
|
|
|
|
hoverEnabled: true
|
|
|
|
onClicked: textinput.forceActiveFocus()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|