diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 5ff1da8eb..655be1c08 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -392,6 +392,7 @@ void CodeModel::gasEstimation(solidity::CompilerStack const& _cs) } eth::AssemblyItems const& runtimeAssembly = *_cs.getRuntimeAssemblyItems(n); + QString contractName = QString::fromStdString(contractDefinition.getName()); // Functional gas costs (per function, but also for accessors) for (auto it: contractDefinition.getInterfaceFunctions()) { @@ -399,13 +400,15 @@ void CodeModel::gasEstimation(solidity::CompilerStack const& _cs) continue; SourceLocation loc = it.second->getDeclaration().getLocation(); GasMeter::GasConsumption cost = GasEstimator::functionalEstimation(runtimeAssembly, it.second->externalSignature()); - m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Function); + m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Function, + contractName, QString::fromStdString(it.second->getDeclaration().getName())); } if (auto const* fallback = contractDefinition.getFallbackFunction()) { SourceLocation loc = fallback->getLocation(); GasMeter::GasConsumption cost = GasEstimator::functionalEstimation(runtimeAssembly, "INVALID"); - m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Function); + m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Function, + contractName, "fallback"); } for (auto const& it: contractDefinition.getDefinedFunctions()) { @@ -416,13 +419,15 @@ void CodeModel::gasEstimation(solidity::CompilerStack const& _cs) GasEstimator::GasConsumption cost = GasEstimator::GasConsumption::infinite(); if (entry > 0) cost = GasEstimator::functionalEstimation(runtimeAssembly, entry, *it); - m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Function); + m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Function, + contractName, QString::fromStdString(it->getName())); } if (auto const* constructor = contractDefinition.getConstructor()) { SourceLocation loc = constructor->getLocation(); GasMeter::GasConsumption cost = GasEstimator::functionalEstimation(*_cs.getAssemblyItems(n)); - m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Constructor); + m_gasCostsMaps->push(sourceName, loc.start, loc.end, gasToString(cost), cost.isInfinite, GasMap::type::Constructor, + contractName, contractName); } } } @@ -435,6 +440,14 @@ QVariantList CodeModel::gasCostByDocumentId(QString const& _documentId) const return QVariantList(); } +QVariantList CodeModel::gasCostBy(QString const& _contractName, QString const& _functionName) const +{ + if (m_gasCostsMaps) + return m_gasCostsMaps->gasCostsBy(_contractName, _functionName); + else + return QVariantList(); +} + void CodeModel::collectContracts(dev::solidity::CompilerStack const& _cs, std::vector const& _sourceNames) { Guard pl(x_pendingContracts); @@ -643,9 +656,9 @@ void CodeModel::setOptimizeCode(bool _value) emit scheduleCompilationJob(++m_backgroundJobId); } -void GasMapWrapper::push(QString _source, int _start, int _end, QString _value, bool _isInfinite, GasMap::type _type) +void GasMapWrapper::push(QString _source, int _start, int _end, QString _value, bool _isInfinite, GasMap::type _type, QString _contractName, QString _functionName) { - GasMap* gas = new GasMap(_start, _end, _value, _isInfinite, _type, this); + GasMap* gas = new GasMap(_start, _end, _value, _isInfinite, _type, _contractName, _functionName, this); m_gasMaps.find(_source).value().push_back(QVariant::fromValue(gas)); } @@ -668,3 +681,17 @@ QVariantList GasMapWrapper::gasCostsByDocId(QString _source) return QVariantList(); } +QVariantList GasMapWrapper::gasCostsBy(QString _contractName, QString _functionName) +{ + QVariantList gasMap; + for (auto const& map: m_gasMaps) + { + for (auto const& gas: map) + { + if (gas.value()->contractName() == _contractName && (_functionName.isEmpty() || gas.value()->functionName() == _functionName)) + gasMap.push_back(gas); + } + } + return gasMap; +} + diff --git a/mix/CodeModel.h b/mix/CodeModel.h index 7841c7142..e51eabf51 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "SolidityType.h" #include "QBigInt.h" @@ -140,6 +141,8 @@ class GasMap: public QObject Q_PROPERTY(QString gas MEMBER m_gas CONSTANT) Q_PROPERTY(bool isInfinite MEMBER m_isInfinite CONSTANT) Q_PROPERTY(QString codeBlockType READ codeBlockType CONSTANT) + Q_PROPERTY(QString contractName MEMBER m_contractName CONSTANT) + Q_PROPERTY(QString functionName MEMBER m_functionName CONSTANT) public: @@ -150,13 +153,19 @@ public: Constructor }; - GasMap(int _start, int _end, QString _gas, bool _isInfinite, type _type, QObject* _parent): QObject(_parent), m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite), m_type(_type) {} + GasMap(int _start, int _end, QString _gas, bool _isInfinite, type _type, QString _contractName, QString _functionName, QObject* _parent): QObject(_parent), + m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite), m_type(_type), m_contractName(_contractName), m_functionName(_functionName) {} + QString contractName() { return m_contractName; } + QString functionName() { return m_functionName; } +private: int m_start; int m_end; QString m_gas; bool m_isInfinite; type m_type; + QString m_contractName; + QString m_functionName; QString codeBlockType() const { @@ -178,10 +187,11 @@ class GasMapWrapper: public QObject public: GasMapWrapper(QObject* _parent = nullptr): QObject(_parent){} - void push(QString _source, int _start, int _end, QString _value, bool _isInfinite, GasMap::type _type); + void push(QString _source, int _start, int _end, QString _value, bool _isInfinite, GasMap::type _type, QString _contractName = "", QString _functionName = ""); bool contains(QString _key); void insert(QString _source, QVariantList _variantList); QVariantList gasCostsByDocId(QString _source); + QVariantList gasCostsBy(QString _contractName, QString _functionName = ""); private: GasCostsMaps m_gasMaps; @@ -200,6 +210,8 @@ public: Q_PROPERTY(bool compiling READ isCompiling NOTIFY stateChanged) Q_PROPERTY(bool hasContract READ hasContract NOTIFY codeChanged) Q_PROPERTY(bool optimizeCode MEMBER m_optimizeCode WRITE setOptimizeCode) + Q_PROPERTY(int callStipend READ callStipend) + Q_PROPERTY(int txGas READ txGas) /// @returns latest compilation results for contracts QVariantMap contracts() const; @@ -234,7 +246,10 @@ public: void gasEstimation(solidity::CompilerStack const& _cs); /// Gas cost by doc id Q_INVOKABLE QVariantList gasCostByDocumentId(QString const& _documentId) const; + Q_INVOKABLE QVariantList gasCostBy(QString const& _contractName, QString const& _functionName) const; Q_INVOKABLE void setOptimizeCode(bool _value); + int txGas() { return static_cast(dev::eth::c_txGas); } + int callStipend() { return static_cast(dev::eth::c_callStipend); } signals: /// Emited on compilation state change diff --git a/mix/qml/QAddressView.qml b/mix/qml/QAddressView.qml index e879468e6..56aefcf3e 100644 --- a/mix/qml/QAddressView.qml +++ b/mix/qml/QAddressView.qml @@ -102,7 +102,6 @@ Row } Rectangle { - //anchors.fill: parent radius: 4 anchors.verticalCenter: parent.verticalCenter height: 20 diff --git a/mix/qml/QBoolTypeView.qml b/mix/qml/QBoolTypeView.qml index a95c12040..12c932762 100644 --- a/mix/qml/QBoolTypeView.qml +++ b/mix/qml/QBoolTypeView.qml @@ -21,16 +21,19 @@ Item value = value === "true" ? "1" : value value = value === "false" ? "0" : value; + var setValue = "1" if (value === "") - boolCombo.currentIndex = parseInt(defaultValue); + setValue = parseInt(defaultValue); else - boolCombo.currentIndex = parseInt(value); + setValue = parseInt(value); + boolCombo.checked = setValue === "1" ? true: false boolCombo.enabled = !readOnly; } Rectangle { + color: "transparent" anchors.fill: parent - ComboBox + CheckBox { property bool inited; Component.onCompleted: @@ -41,17 +44,13 @@ Item id: boolCombo anchors.fill: parent - onCurrentIndexChanged: + onCheckedChanged: { if (inited) - value = comboModel.get(currentIndex).value; - } - model: ListModel - { - id: comboModel - ListElement { text: qsTr("False"); value: "0" } - ListElement { text: qsTr("True"); value: "1" } + value = checked ? "1" : "0" + } + text: qsTr("True") } } } diff --git a/mix/qml/StructView.qml b/mix/qml/StructView.qml index 75888d812..e486ec6fd 100644 --- a/mix/qml/StructView.qml +++ b/mix/qml/StructView.qml @@ -13,14 +13,11 @@ Column property int transactionIndex property string context Layout.fillWidth: true - spacing: 5 - + spacing: 15 Repeater { id: repeater visible: model.length > 0 - //height: parent.height - RowLayout { id: row @@ -42,7 +39,9 @@ Column Label { height: 20 id: typeLabel - text: "(" + modelData.type.name + ")" + text: " (" + modelData.type.name + ")" + font.italic: true + font.weight: Font.Light } } } diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 183b42352..edd19906d 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -7,13 +7,14 @@ import QtQuick.Controls.Styles 1.3 import org.ethereum.qml.QEther 1.0 import "js/TransactionHelper.js" as TransactionHelper import "js/InputValidator.js" as InputValidator +import "js/NetworkDeployment.js" as NetworkDeployment import "." Dialog { id: modalTransactionDialog modality: Qt.ApplicationModal width: 630 - height: 550 + height: 500 visible: false title: qsTr("Edit Transaction") property int transactionIndex @@ -59,6 +60,7 @@ Dialog { load(item.isContractCreation, item.isFunctionCall, functionId, contractId) + estimatedGas.updateView() visible = true; } @@ -273,217 +275,223 @@ Dialog { contentItem: Rectangle { color: transactionDialogStyle.generic.backgroundColor anchors.fill: parent - ColumnLayout { - width: modalTransactionDialog.width - 30 - anchors.horizontalCenter: parent.horizontalCenter + ScrollView + { anchors.top: parent.top - anchors.topMargin: 20 - - RowLayout - { - Layout.fillWidth: true - Rectangle + anchors.fill: parent + ColumnLayout { + width: modalTransactionDialog.width - 30 + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + anchors.topMargin: 10 + spacing: 10 + RowLayout { - Layout.preferredWidth: 150 - Label { - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - text: qsTr("Sender Account") + Layout.fillWidth: true + Rectangle + { + Layout.preferredWidth: 150 + Label { + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + text: qsTr("Sender Account") + } } - } - ComboBox { - function select(secret) - { - for (var i in model) - if (model[i].secret === secret) - { - currentIndex = i; - break; - } + ComboBox { + function select(secret) + { + for (var i in model) + if (model[i].secret === secret) + { + currentIndex = i; + break; + } + } + Layout.preferredWidth: 350 + id: senderComboBox + currentIndex: 0 + textRole: "name" + editable: false } - Layout.preferredWidth: 350 - id: senderComboBox - currentIndex: 0 - textRole: "name" - editable: false } - } - RowLayout - { - Layout.fillWidth: true - Rectangle + RowLayout { - Layout.preferredWidth: 150 - Layout.preferredHeight: 80 - color: "transparent" - Label + Layout.fillWidth: true + Rectangle { - anchors.verticalCenter: parent.verticalCenter - anchors.top: parent.top - anchors.right: parent.right - text: qsTr("Type of Transaction") + Layout.preferredWidth: 150 + Layout.preferredHeight: 80 + color: "transparent" + Label + { + anchors.verticalCenter: parent.verticalCenter + anchors.top: parent.top + anchors.right: parent.right + text: qsTr("Type of Transaction") + } } - } - Column - { - Layout.preferredWidth: 150 - Layout.preferredHeight: 90 - ExclusiveGroup { - id: rbbuttonList - onCurrentChanged: { - if (current) - { - if (current.objectName === "trTypeSend") - { - recipientsAccount.visible = true - contractCreationComboBox.visible = false - modalTransactionDialog.load(false, false) - } - else if (current.objectName === "trTypeCreate") - { - contractCreationComboBox.visible = true - recipientsAccount.visible = false - modalTransactionDialog.load(true, true) - } - else if (current.objectName === "trTypeExecute") + Column + { + Layout.preferredWidth: 150 + Layout.preferredHeight: 90 + ExclusiveGroup { + id: rbbuttonList + onCurrentChanged: { + if (current) { - recipientsAccount.visible = true - contractCreationComboBox.visible = false - modalTransactionDialog.load(false, true) + if (current.objectName === "trTypeSend") + { + recipientsAccount.visible = true + contractCreationComboBox.visible = false + modalTransactionDialog.load(false, false) + } + else if (current.objectName === "trTypeCreate") + { + contractCreationComboBox.visible = true + recipientsAccount.visible = false + modalTransactionDialog.load(true, true) + } + else if (current.objectName === "trTypeExecute") + { + recipientsAccount.visible = true + contractCreationComboBox.visible = false + modalTransactionDialog.load(false, true) + } } } } - } - RadioButton { - id: trTypeSend - objectName: "trTypeSend" - exclusiveGroup: rbbuttonList - height: 30 - text: qsTr("Send ether to account") + RadioButton { + id: trTypeSend + objectName: "trTypeSend" + exclusiveGroup: rbbuttonList + height: 30 + text: qsTr("Send ether to account") - } + } - RadioButton { - id: trTypeCreate - objectName: "trTypeCreate" - exclusiveGroup: rbbuttonList - height: 30 - text: qsTr("Create Contract") - } + RadioButton { + id: trTypeCreate + objectName: "trTypeCreate" + exclusiveGroup: rbbuttonList + height: 30 + text: qsTr("Create Contract") + } - RadioButton { - id: trTypeExecute - objectName: "trTypeExecute" - exclusiveGroup: rbbuttonList - height: 30 - text: qsTr("Execute Contract") + RadioButton { + id: trTypeExecute + objectName: "trTypeExecute" + exclusiveGroup: rbbuttonList + height: 30 + text: qsTr("Execute Contract") + } } } - } - RowLayout - { - Layout.fillWidth: true - Rectangle + RowLayout { - Layout.preferredWidth: 150 - Label { - id: labelRecipient - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - text: qsTr("Recipient Account") + Layout.fillWidth: true + Rectangle + { + Layout.preferredWidth: 150 + Label { + id: labelRecipient + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + text: qsTr("Recipient Account") + } } - } - QAddressView - { - id: recipientsAccount - displayInput: false - onIndexChanged: + QAddressView { - if (rbbuttonList.current.objectName === "trTypeExecute") - loadFunctions(contractFromToken(currentValue())) + id: recipientsAccount + displayInput: false + onIndexChanged: + { + if (rbbuttonList.current.objectName === "trTypeExecute") + loadFunctions(contractFromToken(currentValue())) + } } - } - ComboBox { - id: contractCreationComboBox - function currentValue() { - return (currentIndex >=0 && currentIndex < contractsModel.count) ? contractsModel.get(currentIndex).cid : ""; - } - Layout.preferredWidth: 350 - currentIndex: -1 - textRole: "text" - editable: false - model: ListModel { - id: contractsModel - } - onCurrentIndexChanged: { - loadCtorParameters(currentValue()); + ComboBox { + id: contractCreationComboBox + function currentValue() { + return (currentIndex >=0 && currentIndex < contractsModel.count) ? contractsModel.get(currentIndex).cid : ""; + } + Layout.preferredWidth: 350 + currentIndex: -1 + textRole: "text" + editable: false + model: ListModel { + id: contractsModel + } + onCurrentIndexChanged: { + loadCtorParameters(currentValue()); + } } } - } - RowLayout - { - Layout.fillWidth: true - Rectangle + RowLayout { - Layout.preferredWidth: 150 - id: functionRect - - function hide() + Layout.fillWidth: true + Rectangle { - functionRect.visible = false - functionComboBox.visible = false - } + Layout.preferredWidth: 150 + id: functionRect - function show() - { - functionRect.visible = true - functionComboBox.visible = true - } + function hide() + { + functionRect.visible = false + functionComboBox.visible = false + } - Label { - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - text: qsTr("Function") - } - } + function show() + { + functionRect.visible = true + functionComboBox.visible = true + } - ComboBox { - id: functionComboBox - Layout.preferredWidth: 350 - currentIndex: -1 - textRole: "text" - editable: false - model: ListModel { - id: functionsModel + Label { + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + text: qsTr("Function") + } } - onCurrentIndexChanged: { - loadParameters(); + + ComboBox { + id: functionComboBox + Layout.preferredWidth: 350 + currentIndex: -1 + textRole: "text" + editable: false + model: ListModel { + id: functionsModel + } + onCurrentIndexChanged: { + loadParameters(); + } } } - } - RowLayout - { - Layout.fillWidth: true - ScrollView + RowLayout { id: paramScroll - anchors.topMargin: 10 Layout.fillWidth: true function updateView() { - paramScroll.height = paramsModel.length < 4 ? paramsModel.length * 20 : 145 - paramScroll.parent.Layout.preferredHeight = paramsModel.length < 4 ? paramsModel.length * 20 : 145 - paramScroll.visible = paramsModel.length !== 0 + paramScroll.visible = paramsModel.length > 0 + typeLoader.visible = paramsModel.length > 0 + paramScroll.height = paramsModel.length < 6 ? paramsModel.length * 30 : 190 + typeLoader.height = paramsModel.length < 6 ? paramsModel.length * 30 : 190 + if (paramsModel.length === 0) + { + paramScroll.height = 0 + typeLoader.height = 0 + } } StructView @@ -495,135 +503,212 @@ Dialog { context: "parameter" } } - } - RowLayout - { - Layout.fillWidth: true - Rectangle + RowLayout { - Layout.preferredWidth: 150 - Label { - id: amountLabel - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - text: qsTr("Amount") + Layout.fillWidth: true + Rectangle + { + Layout.preferredWidth: 150 + Label { + id: amountLabel + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + text: qsTr("Amount") + } } - } - Ether { - id: valueField - edit: true - displayFormattedValue: true + Ether { + id: valueField + edit: true + displayFormattedValue: false + displayUnitSelection: true + } } - } - - Rectangle - { - color: "#cccccc" - height: 1 - Layout.fillWidth: true - } - Rectangle - { - width: parent.width - height: 20 - color: "transparent" - Label { - text: qsTr("Transaction fees") - anchors.horizontalCenter: parent.horizontalCenter + Rectangle + { + Layout.preferredHeight: 30 + Layout.fillWidth: true + color: "transparent" + Rectangle + { + color: "#cccccc" + height: 1 + width: parent.width + anchors.verticalCenter: parent.verticalCenter + } } - } - RowLayout - { - Layout.fillWidth: true Rectangle { - Layout.preferredWidth: 150 + width: parent.width + height: 20 + color: "transparent" Label { - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - text: qsTr("Gas") + text: qsTr("Transaction fees") + anchors.horizontalCenter: parent.horizontalCenter } } - Row + RowLayout { - DefaultTextField + Layout.fillWidth: true + Layout.preferredHeight: 40 + + Rectangle { - property variant gasValue - onGasValueChanged: text = gasValue.value(); - onTextChanged: gasValue.setValue(text); - implicitWidth: 200 - enabled: !gasAutoCheck.checked - id: gasValueEdit; + Layout.preferredWidth: 150 + Label { + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + text: qsTr("Gas") + } } - CheckBox + Row { - id: gasAutoCheck - checked: true - text: qsTr("Auto"); + DefaultTextField + { + property variant gasValue + onGasValueChanged: text = gasValue.value(); + onTextChanged: gasValue.setValue(text); + implicitWidth: 200 + enabled: !gasAutoCheck.checked + id: gasValueEdit; + + Label + { + id: estimatedGas + anchors.top: parent.bottom + text: "" + Connections + { + target: functionComboBox + onCurrentIndexChanged: + { + estimatedGas.displayGas(contractFromToken(recipientsAccount.currentValue()), functionComboBox.currentText) + } + } + + function displayGas(contractName, functionName) + { + var gasCost = codeModel.gasCostBy(contractName, functionName); + if (gasCost && gasCost.length > 0) + estimatedGas.text = qsTr("Estimated cost: ") + gasCost[0].gas + " gas" + } + + function updateView() + { + if (rbbuttonList.current.objectName === "trTypeExecute") + estimatedGas.displayGas(contractFromToken(recipientsAccount.currentValue()), functionComboBox.currentText) + else if (rbbuttonList.current.objectName === "trTypeCreate") + { + var contractName = contractCreationComboBox.currentValue() + estimatedGas.displayGas(contractName, contractName) + } + else if (rbbuttonList.current.objectName === "trTypeSend") + { + var gas = codeModel.txGas + codeModel.callStipend + estimatedGas.text = qsTr("Estimated cost: ") + gas + " gas" + } + } + + Connections + { + target: rbbuttonList + onCurrentChanged: { + estimatedGas.updateView() + } + } + } + } + + CheckBox + { + id: gasAutoCheck + checked: true + text: qsTr("Auto"); + } } } - } - RowLayout - { - Layout.fillWidth: true - Rectangle + RowLayout { - Layout.preferredWidth: 150 - Label { - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - text: qsTr("Gas Price") + Layout.fillWidth: true + Layout.preferredHeight: 40 + Rectangle + { + Layout.preferredWidth: 150 + Label { + id: gasPriceLabel + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + text: qsTr("Gas Price") + } + + Label { + id: gasPriceMarket + anchors.top: gasPriceLabel.bottom + Component.onCompleted: + { + NetworkDeployment.gasPrice(function(result) + { + gasPriceMarket.text = qsTr("Current market: ") + " " + result + " Wei"; + }, function (){}); + } + } } - } - Ether { - id: gasPriceField - edit: true - displayFormattedValue: true + Ether { + id: gasPriceField + edit: true + displayFormattedValue: false + displayUnitSelection: true + } } - } - RowLayout - { - anchors.bottom: parent.bottom - anchors.right: parent.right; - - Button { - text: qsTr("OK"); - onClicked: { - var invalid = InputValidator.validate(paramsModel, paramValues); - if (invalid.length === 0) - { - close(); - accepted(); - } - else - { - errorDialog.text = qsTr("Some parameters are invalid:\n"); - for (var k in invalid) - errorDialog.text += invalid[k].message + "\n"; - errorDialog.open(); + RowLayout + { + anchors.right: parent.right + + Button { + text: qsTr("Cancel"); + onClicked: close(); + } + + Button { + text: qsTr("Update"); + onClicked: { + var invalid = InputValidator.validate(paramsModel, paramValues); + if (invalid.length === 0) + { + close(); + accepted(); + } + else + { + errorDialog.text = qsTr("Some parameters are invalid:\n"); + for (var k in invalid) + errorDialog.text += invalid[k].message + "\n"; + errorDialog.open(); + } } } - } - Button { - text: qsTr("Cancel"); - onClicked: close(); + + MessageDialog { + id: errorDialog + standardButtons: StandardButton.Ok + icon: StandardIcon.Critical + } } - MessageDialog { - id: errorDialog - standardButtons: StandardButton.Ok - icon: StandardIcon.Critical + RowLayout + { + anchors.bottom: parent.bottom + Layout.preferredHeight: 20 } } } diff --git a/mix/qml/js/NetworkDeployment.js b/mix/qml/js/NetworkDeployment.js index 8a833e144..94d83460f 100644 --- a/mix/qml/js/NetworkDeployment.js +++ b/mix/qml/js/NetworkDeployment.js @@ -201,7 +201,7 @@ function executeTrNextStep(trIndex, state, ctrAddresses, callBack) callBack(); } -function gasPrice(callBack) +function gasPrice(callBack, error) { var requests = [{ jsonrpc: "2.0", @@ -210,7 +210,9 @@ function gasPrice(callBack) id: jsonRpcRequestId }]; rpcCall(requests, function (httpCall, response){ - callBack(JSON.parse(response)[0].result); + callBack(JSON.parse(response)[0].result) + }, function(message){ + error(message) }); } diff --git a/mix/qml/js/TransactionHelper.js b/mix/qml/js/TransactionHelper.js index f8bad03ed..ea91a40d7 100644 --- a/mix/qml/js/TransactionHelper.js +++ b/mix/qml/js/TransactionHelper.js @@ -17,7 +17,7 @@ function defaultTransaction() }; } -function rpcCall(requests, callBack) +function rpcCall(requests, callBack, error) { var jsonRpcUrl = "http://localhost:8545"; var rpcRequest = JSON.stringify(requests); @@ -33,7 +33,7 @@ function rpcCall(requests, callBack) { var errorText = qsTr("Unable to initiate request to the live network. Please verify your ethereum node is up.") + qsTr(" Error status: ") + httpRequest.status; console.log(errorText); - deploymentError(errorText); + error(errorText); } else {