diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index ab15f55ca..7bc25fd3f 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -81,7 +81,7 @@ ClientModel::ClientModel(): qRegisterMetaType("QInstruction"); qRegisterMetaType("QCode"); qRegisterMetaType("QCallData"); - qRegisterMetaType("RecordLogEntry*"); + qRegisterMetaType("RecordLogEntry*"); } ClientModel::~ClientModel() @@ -236,6 +236,7 @@ void ClientModel::setupScenario(QVariantMap _scenario) QVariantList blocks = _scenario.value("blocks").toList(); QVariantList stateAccounts = _scenario.value("accounts").toList(); + QVariantList stateContracts = _scenario.value("contracts").toList(); m_accounts.clear(); m_accountsSecret.clear(); @@ -258,6 +259,19 @@ void ClientModel::setupScenario(QVariantMap _scenario) } m_ethAccounts->setAccounts(m_accountsSecret); + for (auto const& c: stateContracts) + { + QVariantMap contract = c.toMap(); + Address address = Address(fromHex(contract.value("address").toString().toStdString())); + Account account(qvariant_cast(contract.value("balance"))->toU256Wei(), Account::ContractConception); + bytes code = fromHex(contract.value("code").toString().toStdString()); + account.setCode(std::move(code)); + QVariantMap storageMap = contract.value("storage").toMap(); + for(auto s = storageMap.cbegin(); s != storageMap.cend(); ++s) + account.setStorage(fromBigEndian(fromHex(s.key().toStdString())), fromBigEndian(fromHex(s.value().toString().toStdString()))); + m_accounts[address] = account; + } + bool trToExecute = false; for (auto const& b: blocks) { @@ -891,7 +905,7 @@ void ClientModel::onNewTransaction() QVariantMap accountBalances; for (auto const& ctr : m_contractAddresses) { - u256 wei = m_client->balanceAt(ctr.second, PendingBlock); + u256 wei = m_client->balanceAt(ctr.second, PendingBlock); accountBalances.insert("0x" + QString::fromStdString(ctr.second.hex()), QEther(wei, QEther::Wei).format()); } for (auto const& account : m_accounts) diff --git a/mix/ContractCallDataEncoder.cpp b/mix/ContractCallDataEncoder.cpp index 5ed014088..ed215d342 100644 --- a/mix/ContractCallDataEncoder.cpp +++ b/mix/ContractCallDataEncoder.cpp @@ -21,6 +21,7 @@ */ #include +#include #include #include #include @@ -101,9 +102,9 @@ void ContractCallDataEncoder::encode(QVariant const& _data, SolidityType const& bytes empty(32); size_t sizePos = m_dynamicData.size(); m_dynamicData += empty; //reserve space for count - u256 count = encodeSingleItem(_data.toString(), _type, m_dynamicData); + encodeSingleItem(_data.toString(), _type, m_dynamicData); vector_ref sizeRef(m_dynamicData.data() + sizePos, 32); - toBigEndian(count, sizeRef); + toBigEndian(_data.toString().size(), sizeRef); m_staticOffsetMap.push_back(std::make_pair(m_encodedData.size(), sizePos)); m_encodedData += empty; //reserve space for offset } @@ -223,11 +224,7 @@ dev::bytes ContractCallDataEncoder::decodeBytes(dev::bytes const& _rawValue) QString ContractCallDataEncoder::toString(dev::bytes const& _b) { - QString str; - if (asString(_b, str)) - return "\"" + str + "\" " + QString::fromStdString(dev::toJS(_b)); - else - return QString::fromStdString(dev::toJS(_b)); + return QString::fromStdString(dev::toJS(_b)); } QString ContractCallDataEncoder::toChar(dev::bytes const& _b) @@ -242,8 +239,6 @@ QJsonValue ContractCallDataEncoder::decodeArrayContent(SolidityType const& _type if (_type.baseType->array) { QJsonArray sub = decodeArray(*_type.baseType, _value, pos); - if (_type.baseType->dynamicSize) - pos = pos + 32; return sub; } else @@ -262,6 +257,8 @@ QJsonArray ContractCallDataEncoder::decodeArray(SolidityType const& _type, bytes QJsonArray array; bytesConstRef value(&_value); int count = 0; + bigint offset = pos; + int valuePosition = pos; if (!_type.dynamicSize) count = _type.count; else @@ -269,14 +266,33 @@ QJsonArray ContractCallDataEncoder::decodeArray(SolidityType const& _type, bytes bytesConstRef value(_value.data() + pos, 32); // offset bytes rawParam(32); value.populate(&rawParam); - bigint offset = decodeInt(rawParam); - pos = static_cast(offset) + 32; - value = bytesConstRef(_value.data() + static_cast(offset), 32); // offset + offset = decodeInt(rawParam); + valuePosition = static_cast(offset) + 32; + pos += 32; + value = bytesConstRef(_value.data() + static_cast(offset), 32); // count value.populate(&rawParam); count = static_cast(decodeInt(rawParam)); } - for (int k = 0; k < count; ++k) - array.append(decodeArrayContent(_type, _value, pos)); + if (_type.type == QSolidityType::Type::Bytes || _type.type == QSolidityType::Type::String) + { + bytesConstRef value(_value.data() + (static_cast(offset) + 32), 32); + bytes rawParam(count); + value.populate(&rawParam); + if (_type.type == QSolidityType::Type::Bytes) + array.append(toString(decodeBytes(rawParam))); + else + array.append(toChar(decodeBytes(rawParam))); + } + else + { + for (int k = 0; k < count; ++k) + { + if (_type.dynamicSize) + array.append(decodeArrayContent(_type, _value, valuePosition)); + else + array.append(decodeArrayContent(_type, _value, pos)); + } + } return array; } @@ -329,18 +345,14 @@ QStringList ContractCallDataEncoder::decode(QList const& QJsonArray array = decodeArray(type, _v, readPosition); QJsonDocument jsonDoc = QJsonDocument::fromVariant(array.toVariantList()); r.append(jsonDoc.toJson(QJsonDocument::Compact)); - if (type.dynamicSize) - readPosition++; - else - readPosition = type.count; } else { - bytesConstRef value(_value.data() + (readPosition * 32), 32); + bytesConstRef value(_value.data() + readPosition, 32); bytes rawParam(32); value.populate(&rawParam); r.append(decode(type, rawParam).toString()); - readPosition++; + readPosition += 32; } } return r; diff --git a/mix/qml/Application.qml b/mix/qml/Application.qml index 5ae12b816..188d87be9 100644 --- a/mix/qml/Application.qml +++ b/mix/qml/Application.qml @@ -108,12 +108,14 @@ ApplicationWindow { title: qsTr("Deploy") MenuItem { action: mineAction } MenuSeparator {} - MenuItem { action: editStatesAction } - MenuSeparator {} MenuItem { action: deployViaRpcAction } MenuSeparator {} MenuItem { action: toggleRunOnLoadAction } } + Menu { + title: qsTr("Scenario") + MenuItem { action: editStatesAction } + } Menu { title: qsTr("Debug") MenuItem { action: debugRunAction } @@ -184,7 +186,7 @@ ApplicationWindow { Action { id: editStatesAction - text: qsTr("Edit States") + text: qsTr("Edit Scenarii") shortcut: "Ctrl+Alt+E" onTriggered: stateList.open(); } diff --git a/mix/qml/Block.qml b/mix/qml/Block.qml index 383cb85e8..be540919a 100644 --- a/mix/qml/Block.qml +++ b/mix/qml/Block.qml @@ -22,6 +22,7 @@ ColumnLayout property int blockIndex property variant scenario property string labelColor: "#414141" + property int scenarioIndex signal txSelected(var txIndex) function calculateHeight() @@ -45,6 +46,11 @@ ColumnLayout transactionDialog.open(txIndex, blockIndex, transactions.get(txIndex)) } + function select(txIndex) + { + transactionRepeater.itemAt(txIndex).select() + } + onOpenedTrChanged: { Layout.preferredHeight = calculateHeight() @@ -90,7 +96,7 @@ ColumnLayout text: { if (number === -2) - return qsTr("STARTING PARAMETERS") + return qsTr("GENESIS PARAMETERS") else if (status === "mined") return qsTr("BLOCK") + " " + number else @@ -105,13 +111,14 @@ ColumnLayout anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right anchors.rightMargin: 14 - visible: false + visible: number === -2 MouseArea { anchors.fill: parent onClicked: { // load edit block panel + projectModel.stateListModel.editState(scenarioIndex) } } } @@ -127,6 +134,12 @@ ColumnLayout id: rowTransaction Layout.preferredHeight: trHeight spacing: 0 + + function select() + { + rowContentTr.select() + } + function displayContent() { logsText.text = "" @@ -220,6 +233,15 @@ ColumnLayout } } + function select() + { + rowContentTr.selected = true + rowContentTr.color = "#4F4F4F" + hash.color = "#EAB920" + func.color = "#EAB920" + txSelected(index) + } + function deselect() { rowContentTr.selected = false @@ -233,13 +255,7 @@ ColumnLayout anchors.fill: parent onClicked: { if (!rowContentTr.selected) - { - rowContentTr.selected = true - rowContentTr.color = "#4F4F4F" - hash.color = "#EAB920" - func.color = "#EAB920" - txSelected(index) - } + rowContentTr.select() else rowContentTr.deselect() diff --git a/mix/qml/BlockChain.qml b/mix/qml/BlockChain.qml index 960d95ebf..2c247d282 100644 --- a/mix/qml/BlockChain.qml +++ b/mix/qml/BlockChain.qml @@ -16,6 +16,7 @@ ColumnLayout { property alias trDialog: transactionDialog property alias blockChainRepeater: blockChainRepeater property variant model + property int scenarioIndex property var states: ({}) spacing: 0 property int previousWidth @@ -26,6 +27,25 @@ ColumnLayout { signal rebuilding signal accountAdded(string address, string amount) + Connections + { + target: projectModel.stateListModel + onAccountsValidated: + { + if (rebuild.accountsSha3 !== codeModel.sha3(JSON.stringify(_accounts))) + rebuild.needRebuild("AccountsChanged") + else + rebuild.notNeedRebuild("AccountsChanged") + } + onContractsValidated: + { + if (rebuild.contractsSha3 !== codeModel.sha3(JSON.stringify(_contracts))) + rebuild.needRebuild("ContractsChanged") + else + rebuild.notNeedRebuild("ContractsChanged") + } + } + Connections { target: codeModel @@ -94,13 +114,15 @@ ColumnLayout { return states[record] } - function load(scenario) + function load(scenario, index) { if (!scenario) return; if (model) rebuild.startBlinking() model = scenario + scenarioIndex = index + genesis.scenarioIndex = index states = [] blockModel.clear() for (var b in model.blocks) @@ -138,6 +160,20 @@ ColumnLayout { width: parent.width spacing: 20 + Block + { + id: genesis + scenario: blockChainPanel.model + scenarioIndex: scenarioIndex + Layout.preferredWidth: blockChainScrollView.width + Layout.preferredHeight: 60 + blockIndex: -1 + transactions: [] + status: "" + number: -2 + trHeight: 60 + } + Repeater // List of blocks { id: blockChainRepeater @@ -148,6 +184,11 @@ ColumnLayout { itemAt(blockIndex).editTx(txIndex) } + function select(blockIndex, txIndex) + { + itemAt(blockIndex).select(txIndex) + } + Block { Connections @@ -264,6 +305,8 @@ ColumnLayout { roundRight: true property variant contractsHex: ({}) property variant txSha3: ({}) + property variant accountsSha3 + property variant contractsSha3 property variant txChanged: [] property var blinkReasons: [] @@ -352,10 +395,22 @@ ColumnLayout { ensureNotFuturetime.start() takeCodeSnapshot() takeTxSnaphot() + takeAccountsSnapshot() + takeContractsSnapShot() blinkReasons = [] clientModel.setupScenario(model); } + function takeContractsSnapShot() + { + contractsSha3 = codeModel.sha3(JSON.stringify(model.contracts)) + } + + function takeAccountsSnapshot() + { + accountsSha3 = codeModel.sha3(JSON.stringify(model.accounts)) + } + function takeCodeSnapshot() { contractsHex = {} @@ -395,19 +450,22 @@ ColumnLayout { text: qsTr("Add Tx") onClicked: { - var lastBlock = model.blocks[model.blocks.length - 1]; - if (lastBlock.status === "mined") + if (model && model.blocks) { - var newblock = projectModel.stateListModel.createEmptyBlock() - blockModel.appendBlock(newblock) - model.blocks.push(newblock); - } + var lastBlock = model.blocks[model.blocks.length - 1]; + if (lastBlock.status === "mined") + { + var newblock = projectModel.stateListModel.createEmptyBlock() + blockModel.appendBlock(newblock) + model.blocks.push(newblock); + } - var item = TransactionHelper.defaultTransaction() - transactionDialog.stateAccounts = model.accounts - transactionDialog.execute = true - transactionDialog.editMode = false - transactionDialog.open(model.blocks[model.blocks.length - 1].transactions.length, model.blocks.length - 1, item) + var item = TransactionHelper.defaultTransaction() + transactionDialog.stateAccounts = model.accounts + transactionDialog.execute = true + transactionDialog.editMode = false + transactionDialog.open(model.blocks[model.blocks.length - 1].transactions.length, model.blocks.length - 1, item) + } } width: 100 height: 30 @@ -516,6 +574,7 @@ ColumnLayout { trModel.sender = _r.sender trModel.returnParameters = _r.returnParameters blockModel.setTransaction(blockIndex, trIndex, trModel) + blockChainRepeater.select(blockIndex, trIndex) return; } } @@ -537,6 +596,7 @@ ColumnLayout { itemTr.returnParameters = _r.returnParameters model.blocks[model.blocks.length - 1].transactions.push(itemTr) blockModel.appendTransaction(itemTr) + blockChainRepeater.select(blockIndex, trIndex) } onNewState: { diff --git a/mix/qml/DeployContractStep.qml b/mix/qml/DeployContractStep.qml index 01f06e4f2..9bdcd765c 100644 --- a/mix/qml/DeployContractStep.qml +++ b/mix/qml/DeployContractStep.qml @@ -36,6 +36,19 @@ Rectangle { accountsList.currentIndex = 0 } + verifyDeployedContract() + + deployedAddresses.refresh() + worker.renewCtx() + + worker.pooler.onTriggered.connect(function() { + if (root.visible) + verifyDeployedContract(); + }) + } + + function verifyDeployedContract() + { if (projectModel.deployBlockNumber !== -1) { worker.verifyHashes(projectModel.deploymentTrHashes, function (bn, trLost) @@ -43,8 +56,6 @@ Rectangle { root.updateVerification(bn, trLost) }); } - deployedAddresses.refresh() - worker.renewCtx() } function updateVerification(blockNumber, trLost) @@ -112,14 +123,10 @@ Rectangle { for (var k = 0; k < projectModel.stateListModel.get(currentIndex).blocks.count; k++) { for (var j = 0; j < projectModel.stateListModel.get(currentIndex).blocks.get(k).transactions.count; j++) - { trListModel.append(projectModel.stateListModel.get(currentIndex).blocks.get(k).transactions.get(j)); - } } for (var k = 0; k < trListModel.count; k++) - { trList.itemAt(k).init() - } ctrDeployCtrLabel.calculateContractDeployGas(); } } @@ -166,9 +173,7 @@ Rectangle { if (trListModel.get(index).parameters) { for (var k in trListModel.get(index).parameters) - { paramList.append({ "name": k, "value": trListModel.get(index).parameters[k] }) - } } } @@ -220,7 +225,6 @@ Rectangle { } } - ColumnLayout { anchors.top: parent.top @@ -486,7 +490,8 @@ Rectangle { id: clearDeployAction onTriggered: { worker.forceStopPooling() - fileIo.deleteDir(projectModel.deploymentDir) + if (projectModel.deploymentDir && projectModel.deploymentDir !== "") + fileIo.deleteDir(projectModel.deploymentDir) projectModel.cleanDeploymentStatus() deploymentDialog.steps.reset() } diff --git a/mix/qml/DeploymentDialog.qml b/mix/qml/DeploymentDialog.qml index 280ce0d07..b80a823f2 100644 --- a/mix/qml/DeploymentDialog.qml +++ b/mix/qml/DeploymentDialog.qml @@ -27,6 +27,7 @@ Dialog { function close() { visible = false; + worker.pooler.running = false } function open() @@ -36,6 +37,7 @@ Dialog { registerStep.visible = false steps.init() worker.renewCtx() + worker.pooler.running = true visible = true; } diff --git a/mix/qml/DeploymentWorker.qml b/mix/qml/DeploymentWorker.qml index c7532c840..76e981d8c 100644 --- a/mix/qml/DeploymentWorker.qml +++ b/mix/qml/DeploymentWorker.qml @@ -19,6 +19,7 @@ Item property alias gasPriceInt: gasPriceInt property variant balances: ({}) property variant accounts: [] + property alias pooler: pooler signal gasPriceLoaded() function renewCtx() @@ -169,10 +170,11 @@ Item { if (!clientModelGasEstimation.running) { - var ctr = projectModel.codeEditor.getContracts() - for (var k in ctr) + for (var si = 0; si < projectModel.listModel.count; si++) { - codeModelGasEstimation.registerCodeChange(ctr[k].document.documentId, ctr[k].getText()); + var document = projectModel.listModel.get(si); + if (document.isContract) + codeModelGasEstimation.registerCodeChange(document.documentId, fileIo.readFile(document.path)); } gasEstimationConnect.callback = callback clientModelGasEstimation.setupScenario(scenario) @@ -193,7 +195,8 @@ Item id: codeModelGasEstimation } - ClientModel { + ClientModel + { id: clientModelGasEstimation codeModel: codeModelGasEstimation Component.onCompleted: @@ -202,6 +205,14 @@ Item } } + Timer + { + id: pooler + interval: 5000 + repeat: true + running: false + } + Timer { id: poolLog diff --git a/mix/qml/RegisteringStep.qml b/mix/qml/RegisteringStep.qml index e275e1434..3201b9827 100644 --- a/mix/qml/RegisteringStep.qml +++ b/mix/qml/RegisteringStep.qml @@ -32,6 +32,14 @@ Rectangle { visible = true + worker.pooler.onTriggered.connect(function() { + if (root.visible) + verifyRegistering(); + }) + } + + function verifyRegistering() + { verificationEthUrl.text = "" if (projectModel.registerContentHashTrHash !== "" && projectModel.registerContentHashBlockNumber !== -1) { diff --git a/mix/qml/ScenarioExecution.qml b/mix/qml/ScenarioExecution.qml index 00c09f4cf..dde32fa97 100644 --- a/mix/qml/ScenarioExecution.qml +++ b/mix/qml/ScenarioExecution.qml @@ -70,7 +70,7 @@ Rectangle { onLoaded: { watchers.clear() - blockChain.load(scenario) + blockChain.load(scenario, loader.selectedScenarioIndex) } } @@ -85,13 +85,15 @@ Rectangle { target: blockChain property var currentSelectedBlock property var currentSelectedTx - onTxSelected: { + onTxSelected: + { currentSelectedBlock = blockIndex currentSelectedTx = txIndex updateWatchers(blockIndex, txIndex) } - function updateWatchers(blockIndex, txIndex){ + function updateWatchers(blockIndex, txIndex) + { var tx = blockChain.model.blocks[blockIndex].transactions[txIndex] var state = blockChain.getState(tx.recordIndex) watchers.updateWidthTx(tx, state, blockIndex, txIndex) diff --git a/mix/qml/ScenarioLoader.qml b/mix/qml/ScenarioLoader.qml index 8b6886c93..24b5962c1 100644 --- a/mix/qml/ScenarioLoader.qml +++ b/mix/qml/ScenarioLoader.qml @@ -20,6 +20,7 @@ ColumnLayout signal loaded(variant scenario) signal renamed(variant scenario) signal deleted() + property alias selectedScenarioIndex: scenarioList.currentIndex spacing: 0 function init() { @@ -80,15 +81,14 @@ ColumnLayout } } - Label - { - anchors.left: editImg.right - text: "X" - height: parent.height - color: "#cccccc" + Image { + source: "qrc:/qml/img/delete_sign.png" + height: parent.height - 16 + fillMode: Image.PreserveAspectFit id: deleteImg + anchors.left: editImg.right anchors.top: parent.top - anchors.topMargin: 7 + anchors.topMargin: 8 visible: projectModel.stateListModel.count > 1 MouseArea { @@ -98,13 +98,37 @@ ColumnLayout if (projectModel.stateListModel.count > 1) { projectModel.stateListModel.deleteState(scenarioList.currentIndex) - scenarioList.currentIndex = 0 - deleted() + scenarioList.init() } } } } + Label + { + + MouseArea + { + anchors.fill: parent + onClicked: + { + if (projectModel.stateListModel.count > 1) + { + projectModel.stateListModel.deleteState(scenarioList.currentIndex) + scenarioList.init() + } + } + } + } + + Connections + { + target: projectModel.stateListModel + onStateDeleted: { + scenarioList.init() + } + } + ComboBox { id: scenarioList @@ -122,6 +146,12 @@ ColumnLayout restoreScenario.restore() } + function init() + { + scenarioList.currentIndex = 0 + deleted() + } + function load() { var state = projectModel.stateListModel.getState(currentIndex) @@ -291,7 +321,7 @@ ColumnLayout text: qsTr("Restore") function restore() { - var state = projectModel.stateListModel.reloadStateFromFromProject(scenarioList.currentIndex) + var state = projectModel.stateListModel.reloadStateFromProject(scenarioList.currentIndex) if (state) { restored(state) @@ -302,7 +332,6 @@ ColumnLayout roundLeft: true } - Rectangle { width: 1 diff --git a/mix/qml/StateDialog.qml b/mix/qml/StateDialog.qml index 404a524f4..56be75a09 100644 --- a/mix/qml/StateDialog.qml +++ b/mix/qml/StateDialog.qml @@ -18,12 +18,8 @@ Dialog { title: qsTr("Edit State") visible: false - property alias stateTitle: titleField.text property alias isDefault: defaultCheckBox.checked - property alias model: transactionsModel - property alias transactionDialog: transactionDialog property alias minerComboBox: comboMiner - property alias newAccAction: newAccountAction property int stateIndex property var stateTransactions: [] property var stateAccounts: [] @@ -36,16 +32,6 @@ Dialog { function open(index, item, setDefault) { stateIndex = index - stateTitle = item.title - transactionsModel.clear() - - stateTransactions = [] - var transactions = item.transactions - for (var t = 0; t < transactions.length; t++) { - transactionsModel.append(item.transactions[t]) - stateTransactions.push(item.transactions[t]) - } - accountsModel.clear() stateAccounts = [] var miner = 0 @@ -66,8 +52,8 @@ Dialog { visible = true isDefault = setDefault - titleField.focus = true - defaultCheckBox.enabled = !isDefault + console.log(isDefault) + defaultCheckBox.checked = isDefault comboMiner.model = stateAccounts comboMiner.currentIndex = miner forceActiveFocus() @@ -84,8 +70,6 @@ Dialog { function getItem() { var item = { - title: stateDialog.stateTitle, - transactions: stateTransactions, accounts: stateAccounts, contracts: stateContracts } @@ -95,6 +79,7 @@ Dialog { break } } + item.defaultState = defaultCheckBox.checked return item } @@ -111,21 +96,6 @@ Dialog { ColumnLayout { id: dialogContent anchors.top: parent.top - RowLayout { - Layout.fillWidth: true - DefaultLabel { - Layout.preferredWidth: 85 - text: qsTr("Title") - } - DefaultTextField { - id: titleField - Layout.fillWidth: true - } - } - - CommonSeparator { - Layout.fillWidth: true - } RowLayout { Layout.fillWidth: true @@ -258,30 +228,6 @@ Dialog { Layout.preferredWidth: 85 text: qsTr("Accounts") } - - Button { - id: newAccountButton - anchors.top: accountsLabel.bottom - anchors.topMargin: 10 - iconSource: "qrc:/qml/img/plus.png" - action: newAccountAction - } - - Action { - id: newAccountAction - tooltip: qsTr("Add new Account") - onTriggered: { - add() - } - - function add() { - var account = stateListModel.newAccount( - "1000000", QEther.Ether) - stateAccounts.push(account) - accountsModel.append(account) - return account - } - } } MessageDialog { @@ -313,21 +259,8 @@ Dialog { id: deleteAccountAction tooltip: qsTr("Delete Account") onTriggered: { - if (transactionsModel.isUsed( - stateAccounts[styleData.row].secret)) - alertAlreadyUsed.open() - else { - if (stateAccounts[styleData.row].name - === comboMiner.currentText) - comboMiner.currentIndex = 0 - stateAccounts.splice( - styleData.row, - 1) - accountsModel.remove( - styleData.row) - comboMiner.model = stateAccounts //TODO: filter accounts wo private keys - comboMiner.update() - } + stateAccounts.splice(styleData.row, 1) + accountsView.model.remove(styleData.row) } } @@ -405,115 +338,17 @@ Dialog { Layout.fillWidth: true } - RowLayout { - Layout.fillWidth: true - - Rectangle { - Layout.preferredWidth: 85 - DefaultLabel { - id: transactionsLabel - Layout.preferredWidth: 85 - text: qsTr("Transactions") - } - - Button { - anchors.top: transactionsLabel.bottom - anchors.topMargin: 10 - iconSource: "qrc:/qml/img/plus.png" - action: newTrAction - } - - Action { - id: newTrAction - tooltip: qsTr("Create a new transaction") - onTriggered: transactionsModel.addTransaction() - } - } - - TableView { - id: transactionsView - Layout.fillWidth: true - model: transactionsModel - headerVisible: false - TableViewColumn { - role: "label" - title: qsTr("Name") - width: 150 - delegate: Item { - RowLayout { - height: 30 - width: parent.width - Button { - iconSource: "qrc:/qml/img/delete_sign.png" - action: deleteTransactionAction - } - - Action { - id: deleteTransactionAction - tooltip: qsTr("Delete") - onTriggered: transactionsModel.deleteTransaction( - styleData.row) - } - - Button { - iconSource: "qrc:/qml/img/edit.png" - action: editAction - visible: styleData.row - >= 0 ? !transactionsModel.get( - styleData.row).stdContract : false - width: 10 - height: 10 - Action { - id: editAction - tooltip: qsTr("Edit") - onTriggered: transactionsModel.editTransaction( - styleData.row) - } - } - - DefaultLabel { - Layout.preferredWidth: 150 - text: { - if (styleData.row >= 0) - return transactionsModel.get( - styleData.row).label - else - return "" - } - } - } - } - } - rowDelegate: Rectangle { - color: styleData.alternate ? "transparent" : "#f0f0f0" - height: 30 - } - } - } } RowLayout { anchors.bottom: parent.bottom anchors.right: parent.right - Button { - text: qsTr("Delete") - enabled: !modalStateDialog.isDefault - onClicked: { - projectModel.stateListModel.deleteState(stateIndex) - close() - } - } Button { text: qsTr("OK") onClicked: { - if (titleField.text === "") - alertDialog.open() - else - { - close() - accepted() - } + close() + accepted() } } Button { @@ -522,21 +357,6 @@ Dialog { } } - MessageDialog - { - id: alertDialog - text: qsTr("Please provide a name.") - } - - ListModel { - id: accountsModel - - function removeAccount(_i) { - accountsModel.remove(_i) - stateAccounts.splice(_i, 1) - } - } - ListModel { id: contractsModel @@ -547,50 +367,11 @@ Dialog { } ListModel { - id: transactionsModel - - function editTransaction(index) { - transactionDialog.stateAccounts = stateAccounts - transactionDialog.open(index, - transactionsModel.get(index)) - } - - 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 = TransactionHelper.defaultTransaction() - transactionDialog.stateAccounts = stateAccounts - transactionDialog.open(transactionsModel.count, item) - } - - function deleteTransaction(index) { - stateTransactions.splice(index, 1) - transactionsModel.remove(index) - } - - function isUsed(secret) { - for (var i in stateTransactions) { - if (stateTransactions[i].sender === secret) - return true - } - return false - } - } + id: accountsModel - TransactionDialog { - id: transactionDialog - onAccepted: { - var item = transactionDialog.getItem() - if (transactionDialog.transactionIndex < transactionsModel.count) { - transactionsModel.set( - transactionDialog.transactionIndex, - item) - stateTransactions[transactionDialog.transactionIndex] = item - } else { - transactionsModel.append(item) - stateTransactions.push(item) - } + function removeAccount(_i) { + accountsModel.remove(_i) + stateAccounts.splice(_i, 1) } } } diff --git a/mix/qml/StateList.qml b/mix/qml/StateList.qml index 39567feac..e081947e2 100644 --- a/mix/qml/StateList.qml +++ b/mix/qml/StateList.qml @@ -27,7 +27,7 @@ Dialog { frameVisible: false TableViewColumn { role: "title" - title: qsTr("State") + title: qsTr("Scenario") width: list.width } } @@ -37,10 +37,6 @@ Dialog { anchors.bottom: parent.bottom anchors.right: parent.right anchors.rightMargin: 10 - Button { - action: addStateAction - } - Button { action: closeAction } @@ -71,25 +67,12 @@ Dialog { Layout.fillHeight: true onClicked: list.model.deleteState(styleData.row); } - ToolButton { - text: qsTr("Run"); - Layout.fillHeight: true - onClicked: list.model.runState(styleData.row); - } } } } Row { - Action { - id: addStateAction - text: qsTr("Add State") - shortcut: "Ctrl+T" - enabled: codeModel.hasContract && !clientModel.running; - onTriggered: list.model.addState(); - } - Action { id: closeAction text: qsTr("Close") diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index e7b092463..f144560cf 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -186,12 +186,13 @@ Item { onProjectLoading: stateListModel.loadStatesFromProject(projectData); onProjectFileSaving: { projectData.states = [] - for(var i = 0; i < stateListModel.count; i++) { + for(var i = 0; i < stateListModel.count; i++) + { projectData.states.push(toPlainStateItem(stateList[i])); + stateListModel.set(i, stateList[i]); } projectData.defaultStateIndex = stateListModel.defaultStateIndex; stateListModel.data = projectData - } onNewProject: { var state = toPlainStateItem(stateListModel.createDefaultState()); @@ -221,20 +222,19 @@ Item { function saveState(item) { - if (stateDialog.stateIndex < stateListModel.count) { - if (stateDialog.isDefault) - stateListModel.defaultStateIndex = stateIndex; - stateList[stateDialog.stateIndex] = item; - stateListModel.set(stateDialog.stateIndex, item); - } else { - if (stateDialog.isDefault) - stateListModel.defaultStateIndex = 0; - stateList.push(item); - stateListModel.append(item); + stateList[stateDialog.stateIndex].accounts = item.accounts + stateList[stateDialog.stateIndex].contracts = item.contracts + stateListModel.get(stateDialog.stateIndex).accounts = item.accounts + stateListModel.get(stateDialog.stateIndex).contracts = item.contracts + stateListModel.accountsValidated(item.accounts) + stateListModel.contractsValidated(item.contracts) + stateListModel.get(stateDialog.stateIndex).miner = item.miner + stateList[stateDialog.stateIndex].miner = item.miner + if (item.defaultState) + { + stateListModel.defaultStateIndex = stateDialog.stateIndex + stateListModel.defaultStateChanged() } - if (stateDialog.isDefault) - stateListModel.defaultStateChanged(); - stateListModel.save(); } } @@ -242,12 +242,15 @@ Item { id: stateListModel property int defaultStateIndex: 0 property variant data + signal accountsValidated(var _accounts) + signal contractsValidated(var _contracts) signal defaultStateChanged; signal stateListModelReady; signal stateRun(int index) signal stateDeleted(int index) - function defaultTransactionItem() { + function defaultTransactionItem() + { return TransactionHelper.defaultTransaction(); } @@ -409,7 +412,7 @@ Item { return "" } - function reloadStateFromFromProject(index) + function reloadStateFromProject(index) { if (data) { diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index e47bd9ed2..cc2ca2e79 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -125,7 +125,7 @@ Dialog { function loadParameters() { paramsModel = [] if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) { - var contract = codeModel.contracts[TransactionHelper.contractFromToken(contractCreationComboBox.currentValue())]; + var contract = codeModel.contracts[TransactionHelper.contractFromToken(recipientsAccount.currentValue())]; if (contract) { var func = getFunction(functionComboBox.currentText, contract); if (func) { @@ -498,9 +498,7 @@ Dialog { paramScroll.visible = paramsModel.length > 0 paramScroll.Layout.preferredHeight = paramsModel.length < 6 ? paramsModel.length * 30 : 205 if (paramsModel.length === 0) - { paramScroll.height = 0 - } } }