527 lines
11 KiB

import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Dialogs 1.1
import QtQuick.Layouts 1.1
import Qt.labs.settings 1.0
import org.ethereum.qml.QEther 1.0
import "js/Debugger.js" as Debugger
import "js/ErrorLocationFormater.js" as ErrorLocationFormater
import "js/TransactionHelper.js" as TransactionHelper
import "js/QEtherHelper.js" as QEtherHelper
import "."
ColumnLayout {
10 years ago
id: blockChainPanel
property variant model
spacing: 0
property int previousWidth
property variant debugTrRequested: []
signal chainChanged
signal chainReloaded
Connections
{
target: codeModel
onContractRenamed: {
rebuild.startBlinking()
}
onNewContractCompiled: {
rebuild.startBlinking()
}
}
10 years ago
onChainChanged: {
rebuild.startBlinking()
10 years ago
}
onWidthChanged:
{
10 years ago
var minWidth = scenarioMinWidth - 20 // margin
if (width <= minWidth || previousWidth <= minWidth)
10 years ago
{
10 years ago
fromWidth = 100
10 years ago
toWidth = 100
10 years ago
valueWidth = 200
10 years ago
}
else
{
var diff = (width - previousWidth) / 3;
10 years ago
fromWidth = fromWidth + diff < 100 ? 100 : fromWidth + diff
10 years ago
toWidth = toWidth + diff < 100 ? 100 : toWidth + diff
10 years ago
valueWidth = valueWidth + diff < 200 ? 200 : valueWidth + diff
10 years ago
}
previousWidth = width
}
function load(scenario)
{
if (!scenario)
return;
if (model)
rebuild.startBlinking()
10 years ago
model = scenario
blockModel.clear()
for (var b in model.blocks)
blockModel.append(model.blocks[b])
previousWidth = width
}
10 years ago
property int statusWidth: 30
10 years ago
property int fromWidth: 150
10 years ago
property int toWidth: 100
10 years ago
property int valueWidth: 200
property int logsWidth: 40
property int debugActionWidth: 40
10 years ago
property int horizontalMargin: 10
property int cellSpacing: 10
RowLayout
{
id: header
spacing: 0
10 years ago
Layout.preferredHeight: 30
Rectangle
{
10 years ago
Layout.preferredWidth: statusWidth
Layout.preferredHeight: parent.height
10 years ago
color: "transparent"
Image {
id: debugImage
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
source: "qrc:/qml/img/recycleicon@2x.png"
width: statusWidth + 20
fillMode: Image.PreserveAspectFit
}
10 years ago
}
Rectangle
{
10 years ago
Layout.preferredWidth: fromWidth
10 years ago
Label
{
anchors.verticalCenter: parent.verticalCenter
text: "From"
anchors.left: parent.left
10 years ago
anchors.leftMargin: horizontalMargin
10 years ago
}
}
Label
{
text: "To"
Layout.preferredWidth: toWidth + cellSpacing
}
Label
{
text: "Value"
Layout.preferredWidth: valueWidth + cellSpacing
}
Label
{
text: "Logs"
Layout.preferredWidth: logsWidth + cellSpacing
}
Label
{
text: ""
Layout.preferredWidth: debugActionWidth
}
}
Rectangle
{
Layout.preferredHeight: 500
Layout.preferredWidth: parent.width
border.color: "#cccccc"
border.width: 2
color: "white"
ScrollView
{
id: blockChainScrollView
anchors.fill: parent
10 years ago
anchors.topMargin: 8
10 years ago
ColumnLayout
{
id: blockChainLayout
width: parent.width
10 years ago
spacing: 20
Block
{
scenario: blockChainPanel.model
Layout.preferredWidth: blockChainScrollView.width
Layout.preferredHeight: 60
blockIndex: -1
transactions: []
status: ""
number: -2
trHeight: 60
}
10 years ago
Repeater // List of blocks
{
id: blockChainRepeater
model: blockModel
Block
{
scenario: blockChainPanel.model
Layout.preferredWidth: blockChainScrollView.width
Layout.preferredHeight:
{
return calculateHeight()
}
blockIndex: index
transactions:
{
if (index >= 0)
return blockModel.get(index).transactions
else
return []
}
status:
{
if (index >= 0)
return blockModel.get(index).status
else
return ""
}
number:
{
if (index >= 0)
return blockModel.get(index).number
else
return 0
}
}
}
}
}
}
ListModel
{
id: blockModel
function appendBlock(block)
{
blockModel.append(block);
}
function appendTransaction(tr)
{
blockModel.get(blockModel.count - 1).transactions.append(tr)
}
function removeTransaction(blockIndex, trIndex)
{
blockModel.get(blockIndex).transactions.remove(trIndex)
}
function removeLastBlock()
{
blockModel.remove(blockModel.count - 1)
}
function removeBlock(index)
{
blockModel.remove(index)
}
function getTransaction(block, tr)
{
return blockModel.get(block).transactions.get(tr)
}
function setTransaction(blockIndex, trIndex, tr)
{
blockModel.get(blockIndex).transactions.set(trIndex, tr)
}
function setTransactionProperty(blockIndex, trIndex, propertyName, value)
{
blockModel.get(blockIndex).transactions.set(trIndex, { propertyName: value })
}
}
Rectangle
{
Layout.preferredWidth: parent.width
RowLayout
{
10 years ago
anchors.horizontalCenter: parent.horizontalCenter
10 years ago
anchors.top: parent.top
anchors.topMargin: 10
10 years ago
spacing: 20
Rectangle {
Layout.preferredWidth: 100
Layout.preferredHeight: 30
ScenarioButton {
id: rebuild
text: qsTr("Rebuild")
width: 100
height: 30
roundLeft: true
roundRight: true
onClicked:
10 years ago
{
10 years ago
if (ensureNotFuturetime.running)
return;
stopBlinking()
var retBlocks = [];
var bAdded = 0;
for (var j = 0; j < model.blocks.length; j++)
10 years ago
{
10 years ago
var b = model.blocks[j];
var block = {
hash: b.hash,
number: b.number,
transactions: [],
status: b.status
}
for (var k = 0; k < model.blocks[j].transactions.length; k++)
{
if (blockModel.get(j).transactions.get(k).saveStatus)
{
var tr = model.blocks[j].transactions[k]
tr.saveStatus = true
block.transactions.push(tr);
}
}
if (block.transactions.length > 0)
10 years ago
{
10 years ago
bAdded++
block.number = bAdded
block.status = "mined"
retBlocks.push(block)
10 years ago
}
}
10 years ago
if (retBlocks.length === 0)
retBlocks.push(projectModel.stateListModel.createEmptyBlock())
else
10 years ago
{
10 years ago
var last = retBlocks[retBlocks.length - 1]
last.number = -1
last.status = "pending"
10 years ago
}
10 years ago
model.blocks = retBlocks
blockModel.clear()
for (var j = 0; j < model.blocks.length; j++)
blockModel.append(model.blocks[j])
10 years ago
10 years ago
ensureNotFuturetime.start()
clientModel.setupScenario(model);
}
buttonShortcut: ""
sourceImg: "qrc:/qml/img/recycleicon@2x.png"
10 years ago
}
10 years ago
}
10 years ago
Rectangle
{
Layout.preferredWidth: 200
Layout.preferredHeight: 30
color: "transparent"
10 years ago
10 years ago
ScenarioButton {
id: addTransaction
text: qsTr("Add Tx")
onClicked:
10 years ago
{
10 years ago
var lastBlock = model.blocks[model.blocks.length - 1];
if (lastBlock.status === "mined")
{
var newblock = projectModel.stateListModel.createEmptyBlock()
blockModel.appendBlock(newblock)
model.blocks.push(newblock);
}
10 years ago
10 years ago
var item = TransactionHelper.defaultTransaction()
transactionDialog.stateAccounts = model.accounts
transactionDialog.execute = true
transactionDialog.open(model.blocks[model.blocks.length - 1].transactions.length, model.blocks.length - 1, item)
}
width: 100
height: 30
buttonShortcut: ""
sourceImg: "qrc:/qml/img/sendtransactionicon@2x.png"
roundLeft: true
roundRight: false
10 years ago
}
10 years ago
Timer
{
id: ensureNotFuturetime
interval: 1000
repeat: false
running: false
}
10 years ago
10 years ago
Rectangle
10 years ago
{
10 years ago
width: 1
height: parent.height
anchors.right: addBlockBtn.left
color: "#ededed"
}
ScenarioButton {
id: addBlockBtn
text: qsTr("Add Block..")
anchors.left: addTransaction.right
roundLeft: false
roundRight: true
onClicked:
10 years ago
{
10 years ago
if (ensureNotFuturetime.running)
return
if (clientModel.mining || clientModel.running)
return
if (model.blocks.length > 0)
10 years ago
{
10 years ago
var lastBlock = model.blocks[model.blocks.length - 1]
if (lastBlock.status === "pending")
{
ensureNotFuturetime.start()
clientModel.mine()
}
else
addNewBlock()
10 years ago
}
else
addNewBlock()
10 years ago
10 years ago
}
10 years ago
function addNewBlock()
{
var block = projectModel.stateListModel.createEmptyBlock()
model.blocks.push(block)
blockModel.appendBlock(block)
}
width: 100
height: 30
10 years ago
10 years ago
buttonShortcut: ""
sourceImg: "qrc:/qml/img/addblock@2x.png"
10 years ago
}
}
10 years ago
10 years ago
Connections
{
target: clientModel
onNewBlock:
{
if (!clientModel.running)
{
var lastBlock = model.blocks[model.blocks.length - 1]
lastBlock.status = "mined"
lastBlock.number = model.blocks.length
var lastB = blockModel.get(model.blocks.length - 1)
lastB.status = "mined"
lastB.number = model.blocks.length
addBlockBtn.addNewBlock()
}
}
onStateCleared:
{
}
onNewRecord:
{
var blockIndex = parseInt(_r.transactionIndex.split(":")[0]) - 1
var trIndex = parseInt(_r.transactionIndex.split(":")[1])
if (blockIndex <= model.blocks.length - 1)
{
var item = model.blocks[blockIndex]
if (trIndex <= item.transactions.length - 1)
{
var tr = item.transactions[trIndex]
tr.returned = _r.returned
tr.recordIndex = _r.recordIndex
tr.logs = _r.logs
tr.sender = _r.sender
var trModel = blockModel.getTransaction(blockIndex, trIndex)
trModel.returned = _r.returned
trModel.recordIndex = _r.recordIndex
trModel.logs = _r.logs
trModel.sender = _r.sender
blockModel.setTransaction(blockIndex, trIndex, trModel)
return;
}
}
// tr is not in the list.
var itemTr = TransactionHelper.defaultTransaction()
itemTr.saveStatus = false
itemTr.functionId = _r.function
itemTr.contractId = _r.contract
itemTr.gasAuto = true
itemTr.parameters = _r.parameters
itemTr.isContractCreation = itemTr.functionId === itemTr.contractId
itemTr.label = _r.label
itemTr.isFunctionCall = itemTr.functionId !== ""
itemTr.returned = _r.returned
itemTr.value = QEtherHelper.createEther(_r.value, QEther.Wei)
itemTr.sender = _r.sender
itemTr.recordIndex = _r.recordIndex
itemTr.logs = _r.logs
model.blocks[model.blocks.length - 1].transactions.push(itemTr)
blockModel.appendTransaction(itemTr)
}
onMiningComplete:
{
}
}
ScenarioButton {
id: newAccount
10 years ago
text: qsTr("New Account..")
10 years ago
onClicked: {
model.accounts.push(projectModel.stateListModel.newAccount("1000000", QEther.Ether))
}
Layout.preferredWidth: 100
Layout.preferredHeight: 30
buttonShortcut: ""
sourceImg: "qrc:/qml/img/newaccounticon@2x.png"
10 years ago
roundLeft: true
roundRight: true
10 years ago
}
}
}
TransactionDialog {
id: transactionDialog
property bool execute
onAccepted: {
var item = transactionDialog.getItem()
if (execute)
{
var lastBlock = model.blocks[model.blocks.length - 1];
if (lastBlock.status === "mined")
{
var newBlock = projectModel.stateListModel.createEmptyBlock();
model.blocks.push(newBlock);
blockModel.appendBlock(newBlock)
}
if (!clientModel.running)
clientModel.executeTr(item)
}
else {
model.blocks[blockIndex].transactions[transactionIndex] = item
blockModel.setTransaction(blockIndex, transactionIndex, item)
chainChanged()
}
}
}
}