Marek Kotewicz
10 years ago
62 changed files with 2281 additions and 600 deletions
@ -0,0 +1,56 @@ |
|||
/*
|
|||
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 RLPXSocket.h
|
|||
* @author Alex Leverington <nessence@gmail.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include "Common.h" |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace p2p |
|||
{ |
|||
|
|||
/**
|
|||
* @brief Shared pointer wrapper for ASIO TCP socket. |
|||
* |
|||
* Thread Safety |
|||
* Distinct Objects: Safe. |
|||
* Shared objects: Unsafe. |
|||
* * an instance method must not be called concurrently |
|||
*/ |
|||
class RLPXSocket: public std::enable_shared_from_this<RLPXSocket> |
|||
{ |
|||
public: |
|||
/// Constructor. Dereferences and takes ownership of _socket.
|
|||
RLPXSocket(bi::tcp::socket* _socket): m_socket(std::move(*_socket)) {} |
|||
~RLPXSocket() { close(); } |
|||
|
|||
bool isConnected() const { return m_socket.is_open(); } |
|||
void close() { try { boost::system::error_code ec; m_socket.shutdown(bi::tcp::socket::shutdown_both, ec); if (m_socket.is_open()) m_socket.close(); } catch (...){} } |
|||
bi::tcp::endpoint remoteEndpoint() { try { return m_socket.remote_endpoint(); } catch (...){ return bi::tcp::endpoint(); } } |
|||
bi::tcp::socket& ref() { return m_socket; } |
|||
|
|||
protected: |
|||
bi::tcp::socket m_socket; |
|||
}; |
|||
|
|||
} |
|||
} |
@ -0,0 +1,346 @@ |
|||
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 "js/Debugger.js" as Debugger |
|||
import "js/ErrorLocationFormater.js" as ErrorLocationFormater |
|||
import "." |
|||
|
|||
ColumnLayout |
|||
{ |
|||
id: root |
|||
property variant transactions |
|||
property string status |
|||
property int number |
|||
property int blockWidth: Layout.preferredWidth - statusWidth - horizontalMargin |
|||
property int horizontalMargin: 10 |
|||
property int trHeight: 30 |
|||
spacing: 0 |
|||
property int openedTr: 0 |
|||
property int blockIndex |
|||
property variant scenario |
|||
|
|||
function calculateHeight() |
|||
{ |
|||
if (transactions) |
|||
{ |
|||
if (index >= 0) |
|||
return 30 + 30 * transactions.count + openedTr |
|||
else |
|||
return 30 |
|||
} |
|||
else |
|||
return 30 |
|||
} |
|||
|
|||
onOpenedTrChanged: |
|||
{ |
|||
Layout.preferredHeight = calculateHeight() |
|||
height = calculateHeight() |
|||
} |
|||
|
|||
|
|||
|
|||
RowLayout |
|||
{ |
|||
Layout.preferredHeight: trHeight |
|||
Layout.preferredWidth: blockWidth |
|||
id: rowHeader |
|||
Rectangle |
|||
{ |
|||
color: "#DEDCDC" |
|||
Layout.preferredWidth: blockWidth |
|||
Layout.preferredHeight: trHeight |
|||
radius: 4 |
|||
anchors.left: parent.left |
|||
anchors.leftMargin: statusWidth + 5 |
|||
Label { |
|||
anchors.verticalCenter: parent.verticalCenter |
|||
anchors.left: parent.left |
|||
anchors.leftMargin: horizontalMargin |
|||
text: |
|||
{ |
|||
if (status === "mined") |
|||
return qsTr("BLOCK") + " " + number |
|||
else |
|||
return qsTr("BLOCK") + " pending" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
Repeater // List of transactions |
|||
{ |
|||
id: transactionRepeater |
|||
model: transactions |
|||
|
|||
RowLayout |
|||
{ |
|||
id: rowTransaction |
|||
Layout.preferredHeight: trHeight |
|||
function displayContent() |
|||
{ |
|||
logsText.text = "" |
|||
if (index >= 0 && transactions.get(index).logs && transactions.get(index).logs.count) |
|||
{ |
|||
for (var k = 0; k < transactions.get(index).logs.count; k++) |
|||
{ |
|||
var log = transactions.get(index).logs.get(k) |
|||
if (log.name) |
|||
logsText.text += log.name + ":\n" |
|||
else |
|||
logsText.text += "log:\n" |
|||
|
|||
if (log.param) |
|||
for (var i = 0; i < log.param.count; i++) |
|||
{ |
|||
var p = log.param.get(i) |
|||
logsText.text += p.name + " = " + p.value + " - indexed:" + p.indexed + "\n" |
|||
} |
|||
else{ |
|||
logsText.text += "From : " + log.address + "\n" |
|||
} |
|||
} |
|||
logsText.text += "\n\n" |
|||
} |
|||
rowDetailedContent.visible = !rowDetailedContent.visible |
|||
} |
|||
|
|||
Rectangle |
|||
{ |
|||
id: trSaveStatus |
|||
Layout.preferredWidth: statusWidth |
|||
Layout.preferredHeight: trHeight |
|||
color: "transparent" |
|||
anchors.top: parent.top |
|||
property bool saveStatus |
|||
|
|||
Image { |
|||
id: saveStatusImage |
|||
source: "qrc:/qml/img/recyclediscard@2x.png" |
|||
width: statusWidth |
|||
fillMode: Image.PreserveAspectFit |
|||
anchors.verticalCenter: parent.verticalCenter |
|||
anchors.horizontalCenter: parent.horizontalCenter |
|||
} |
|||
|
|||
Component.onCompleted: |
|||
{ |
|||
if (index >= 0) |
|||
saveStatus = transactions.get(index).saveStatus |
|||
} |
|||
|
|||
onSaveStatusChanged: |
|||
{ |
|||
if (saveStatus) |
|||
saveStatusImage.source = "qrc:/qml/img/recyclekeep@2x.png" |
|||
else |
|||
saveStatusImage.source = "qrc:/qml/img/recyclediscard@2x.png" |
|||
|
|||
if (index >= 0) |
|||
transactions.get(index).saveStatus = saveStatus |
|||
} |
|||
|
|||
MouseArea { |
|||
id: statusMouseArea |
|||
anchors.fill: parent |
|||
onClicked: |
|||
{ |
|||
parent.saveStatus = !parent.saveStatus |
|||
} |
|||
} |
|||
} |
|||
|
|||
Rectangle |
|||
{ |
|||
Layout.preferredWidth: blockWidth |
|||
Layout.preferredHeight: parent.height |
|||
color: "#DEDCDC" |
|||
id: rowContentTr |
|||
anchors.top: parent.top |
|||
ColumnLayout |
|||
{ |
|||
anchors.top: parent.top |
|||
spacing: 10 |
|||
RowLayout |
|||
{ |
|||
anchors.top: parent.top |
|||
anchors.verticalCenter: parent.verticalCenter |
|||
spacing: cellSpacing |
|||
Text |
|||
{ |
|||
id: hash |
|||
anchors.left: parent.left |
|||
anchors.leftMargin: horizontalMargin |
|||
Layout.preferredWidth: fromWidth |
|||
elide: Text.ElideRight |
|||
maximumLineCount: 1 |
|||
text: { |
|||
if (index >= 0) |
|||
return transactions.get(index).sender |
|||
else |
|||
return "" |
|||
} |
|||
} |
|||
|
|||
Text |
|||
{ |
|||
id: func |
|||
text: { |
|||
if (index >= 0) |
|||
parent.userFrienldyToken(transactions.get(index).label) |
|||
else |
|||
return "" |
|||
} |
|||
elide: Text.ElideRight |
|||
maximumLineCount: 1 |
|||
Layout.preferredWidth: toWidth |
|||
} |
|||
|
|||
function userFrienldyToken(value) |
|||
{ |
|||
if (value && value.indexOf("<") === 0) |
|||
{ |
|||
if (value.split("> ")[1] === " - ") |
|||
return value.split(" - ")[0].replace("<", "") |
|||
else |
|||
return value.split(" - ")[0].replace("<", "") + "." + value.split("> ")[1] + "()"; |
|||
} |
|||
else |
|||
return value |
|||
} |
|||
|
|||
Text |
|||
{ |
|||
id: returnValue |
|||
elide: Text.ElideRight |
|||
maximumLineCount: 1 |
|||
Layout.preferredWidth: valueWidth |
|||
text: { |
|||
if (index >= 0 && transactions.get(index).returned) |
|||
return transactions.get(index).returned |
|||
else |
|||
return "" |
|||
} |
|||
} |
|||
|
|||
Rectangle |
|||
{ |
|||
Layout.preferredWidth: logsWidth |
|||
Layout.preferredHeight: trHeight - 10 |
|||
width: logsWidth |
|||
color: "transparent" |
|||
Text |
|||
{ |
|||
id: logs |
|||
anchors.left: parent.left |
|||
anchors.leftMargin: 10 |
|||
text: { |
|||
if (index >= 0 && transactions.get(index).logs && transactions.get(index).logs.count) |
|||
return transactions.get(index).logs.count |
|||
else |
|||
return "" |
|||
} |
|||
} |
|||
MouseArea { |
|||
anchors.fill: parent |
|||
onClicked: { |
|||
rowTransaction.displayContent(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
Rectangle |
|||
{ |
|||
Layout.preferredWidth: debugActionWidth |
|||
Layout.preferredHeight: trHeight - 10 |
|||
color: "transparent" |
|||
|
|||
Image { |
|||
source: "qrc:/qml/img/edit.png" |
|||
width: 18 |
|||
fillMode: Image.PreserveAspectFit |
|||
anchors.verticalCenter: parent.verticalCenter |
|||
anchors.horizontalCenter: parent.horizontalCenter |
|||
} |
|||
MouseArea |
|||
{ |
|||
anchors.fill: parent |
|||
onClicked: |
|||
{ |
|||
transactionDialog.stateAccounts = scenario.accounts |
|||
transactionDialog.execute = false |
|||
transactionDialog.open(index, blockIndex, transactions.get(index)) |
|||
} |
|||
} |
|||
} |
|||
|
|||
Rectangle |
|||
{ |
|||
Layout.preferredWidth: debugActionWidth |
|||
Layout.preferredHeight: trHeight - 10 |
|||
color: "transparent" |
|||
|
|||
Image { |
|||
id: debugImg |
|||
source: "qrc:/qml/img/rightarrow@2x.png" |
|||
width: statusWidth |
|||
fillMode: Image.PreserveAspectFit |
|||
anchors.verticalCenter: parent.verticalCenter |
|||
anchors.horizontalCenter: parent.horizontalCenter |
|||
visible: transactions.get(index).recordIndex !== undefined |
|||
} |
|||
MouseArea |
|||
{ |
|||
anchors.fill: parent |
|||
onClicked: |
|||
{ |
|||
if (transactions.get(index).recordIndex !== undefined) |
|||
{ |
|||
debugTrRequested = [ blockIndex, index ] |
|||
clientModel.debugRecord(transactions.get(index).recordIndex); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
RowLayout |
|||
{ |
|||
id: rowDetailedContent |
|||
visible: false |
|||
Layout.preferredHeight:{ |
|||
if (index >= 0 && transactions.get(index).logs) |
|||
return 100 * transactions.get(index).logs.count |
|||
else |
|||
return 100 |
|||
} |
|||
onVisibleChanged: |
|||
{ |
|||
var lognb = transactions.get(index).logs.count |
|||
if (visible) |
|||
{ |
|||
rowContentTr.Layout.preferredHeight = trHeight + 100 * lognb |
|||
openedTr += 100 * lognb |
|||
} |
|||
else |
|||
{ |
|||
rowContentTr.Layout.preferredHeight = trHeight |
|||
openedTr -= 100 * lognb |
|||
} |
|||
} |
|||
|
|||
Text { |
|||
anchors.left: parent.left |
|||
anchors.leftMargin: horizontalMargin |
|||
id: logsText |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
@ -0,0 +1,480 @@ |
|||
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 { |
|||
id: blockChainPanel |
|||
property variant model |
|||
spacing: 0 |
|||
property int previousWidth |
|||
property variant debugTrRequested: [] |
|||
signal chainChanged |
|||
|
|||
onChainChanged: { |
|||
reBuildNeeded.start() |
|||
} |
|||
|
|||
onWidthChanged: |
|||
{ |
|||
|
|||
if (width <= 630 || previousWidth <= 630) |
|||
{ |
|||
fromWidth = 100 |
|||
toWidth = 100 |
|||
valueWidth = 200 |
|||
} |
|||
else |
|||
{ |
|||
var diff = (width - previousWidth) / 3; |
|||
fromWidth = fromWidth + diff < 100 ? 100 : fromWidth + diff |
|||
toWidth = toWidth + diff < 100 ? 100 : toWidth + diff |
|||
valueWidth = valueWidth + diff < 200 ? 200 : valueWidth + diff |
|||
} |
|||
previousWidth = width |
|||
} |
|||
|
|||
function load(scenario) |
|||
{ |
|||
if (!scenario) |
|||
return; |
|||
if (model) |
|||
chainChanged() |
|||
model = scenario |
|||
blockModel.clear() |
|||
for (var b in model.blocks) |
|||
blockModel.append(model.blocks[b]) |
|||
previousWidth = width |
|||
} |
|||
|
|||
property int statusWidth: 30 |
|||
property int fromWidth: 100 |
|||
property int toWidth: 100 |
|||
property int valueWidth: 200 |
|||
property int logsWidth: 50 |
|||
property int debugActionWidth: 50 |
|||
property int horizontalMargin: 10 |
|||
property int cellSpacing: 10 |
|||
|
|||
RowLayout |
|||
{ |
|||
id: header |
|||
spacing: 0 |
|||
Layout.preferredHeight: 25 |
|||
Image { |
|||
id: debugImage |
|||
source: "qrc:/qml/img/recycleicon@2x.png" |
|||
Layout.preferredWidth: statusWidth |
|||
Layout.preferredHeight: 25 |
|||
fillMode: Image.PreserveAspectFit |
|||
} |
|||
Rectangle |
|||
{ |
|||
Layout.preferredWidth: fromWidth + cellSpacing |
|||
Label |
|||
{ |
|||
anchors.verticalCenter: parent.verticalCenter |
|||
text: "From" |
|||
anchors.left: parent.left |
|||
anchors.leftMargin: horizontalMargin + 5 |
|||
} |
|||
} |
|||
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 |
|||
anchors.topMargin: 10 |
|||
ColumnLayout |
|||
{ |
|||
id: blockChainLayout |
|||
width: parent.width |
|||
spacing: 10 |
|||
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 |
|||
{ |
|||
width: 4 * 100 |
|||
anchors.top: parent.top |
|||
anchors.topMargin: 10 |
|||
spacing: 0 |
|||
ScenarioButton { |
|||
id: rebuild |
|||
text: qsTr("Rebuild") |
|||
onClicked: |
|||
{ |
|||
if (ensureNotFuturetime.running) |
|||
return; |
|||
reBuildNeeded.stop() |
|||
var retBlocks = []; |
|||
var bAdded = 0; |
|||
for (var j = 0; j < model.blocks.length; j++) |
|||
{ |
|||
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) |
|||
{ |
|||
bAdded++ |
|||
block.number = bAdded |
|||
block.status = "mined" |
|||
retBlocks.push(block) |
|||
} |
|||
|
|||
} |
|||
if (retBlocks.length === 0) |
|||
retBlocks.push(projectModel.stateListModel.createEmptyBlock()) |
|||
else |
|||
{ |
|||
var last = retBlocks[retBlocks.length - 1] |
|||
last.number = -1 |
|||
last.status = "pending" |
|||
} |
|||
|
|||
model.blocks = retBlocks |
|||
blockModel.clear() |
|||
for (var j = 0; j < model.blocks.length; j++) |
|||
blockModel.append(model.blocks[j]) |
|||
|
|||
ensureNotFuturetime.start() |
|||
clientModel.setupScenario(model); |
|||
} |
|||
|
|||
Layout.preferredWidth: 100 |
|||
Layout.preferredHeight: 30 |
|||
buttonShortcut: "" |
|||
sourceImg: "qrc:/qml/img/recycleicon@2x.png" |
|||
Timer |
|||
{ |
|||
id: reBuildNeeded |
|||
repeat: true |
|||
interval: 1000 |
|||
running: false |
|||
onTriggered: { |
|||
if (!parent.fillColor || parent.fillColor === "white") |
|||
parent.fillColor = "orange" |
|||
else |
|||
parent.fillColor = "white" |
|||
} |
|||
onRunningChanged: { |
|||
if (!running) |
|||
parent.fillColor = "white" |
|||
} |
|||
} |
|||
} |
|||
|
|||
ScenarioButton { |
|||
id: addTransaction |
|||
text: qsTr("Add Transaction") |
|||
onClicked: |
|||
{ |
|||
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.open(model.blocks[model.blocks.length - 1].transactions.length, model.blocks.length - 1, item) |
|||
} |
|||
Layout.preferredWidth: 100 |
|||
Layout.preferredHeight: 30 |
|||
buttonShortcut: "" |
|||
sourceImg: "qrc:/qml/img/sendtransactionicon@2x.png" |
|||
} |
|||
|
|||
Timer |
|||
{ |
|||
id: ensureNotFuturetime |
|||
interval: 1000 |
|||
repeat: false |
|||
running: false |
|||
} |
|||
|
|||
ScenarioButton { |
|||
id: addBlockBtn |
|||
text: qsTr("Add Block") |
|||
onClicked: |
|||
{ |
|||
if (ensureNotFuturetime.running) |
|||
return |
|||
if (clientModel.mining || clientModel.running) |
|||
return |
|||
if (model.blocks.length > 0) |
|||
{ |
|||
var lastBlock = model.blocks[model.blocks.length - 1] |
|||
if (lastBlock.status === "pending") |
|||
{ |
|||
ensureNotFuturetime.start() |
|||
clientModel.mine() |
|||
} |
|||
else |
|||
addNewBlock() |
|||
} |
|||
else |
|||
addNewBlock() |
|||
|
|||
} |
|||
|
|||
function addNewBlock() |
|||
{ |
|||
var block = projectModel.stateListModel.createEmptyBlock() |
|||
model.blocks.push(block) |
|||
blockModel.appendBlock(block) |
|||
} |
|||
Layout.preferredWidth: 100 |
|||
Layout.preferredHeight: 30 |
|||
buttonShortcut: "" |
|||
sourceImg: "qrc:/qml/img/addblock@2x.png" |
|||
} |
|||
|
|||
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 |
|||
text: qsTr("New Account") |
|||
onClicked: { |
|||
model.accounts.push(projectModel.stateListModel.newAccount("1000000", QEther.Ether)) |
|||
} |
|||
Layout.preferredWidth: 100 |
|||
Layout.preferredHeight: 30 |
|||
buttonShortcut: "" |
|||
sourceImg: "qrc:/qml/img/newaccounticon@2x.png" |
|||
} |
|||
} |
|||
} |
|||
|
|||
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() |
|||
} |
|||
|
|||
} |
|||
} |
|||
} |
|||
|
|||
|
@ -0,0 +1,67 @@ |
|||
import QtQuick 2.2 |
|||
import QtQuick.Controls 1.1 |
|||
import QtQuick.Layouts 1.0 |
|||
import QtQuick.Controls.Styles 1.1 |
|||
|
|||
Rectangle { |
|||
id: buttonActionContainer |
|||
property string text |
|||
property string buttonShortcut |
|||
property string sourceImg |
|||
property string fillColor |
|||
signal clicked |
|||
|
|||
Rectangle { |
|||
id: contentRectangle |
|||
anchors.fill: parent |
|||
border.color: "#cccccc" |
|||
border.width: 1 |
|||
radius: 4 |
|||
color: parent.fillColor ? parent.fillColor : "white" |
|||
Image { |
|||
id: debugImage |
|||
anchors { |
|||
left: parent.left |
|||
right: parent.right |
|||
top: parent.top |
|||
bottom: parent.bottom |
|||
bottomMargin: debugImg.pressed ? 0 : 2; |
|||
topMargin: debugImg.pressed ? 2 : 0; |
|||
} |
|||
source: sourceImg |
|||
fillMode: Image.PreserveAspectFit |
|||
height: 30 |
|||
} |
|||
|
|||
Button { |
|||
anchors.fill: parent |
|||
id: debugImg |
|||
action: buttonAction |
|||
style: ButtonStyle { |
|||
background: Rectangle { |
|||
color: "transparent" |
|||
} |
|||
} |
|||
} |
|||
|
|||
Action { |
|||
id: buttonAction |
|||
shortcut: buttonShortcut |
|||
onTriggered: { |
|||
buttonActionContainer.clicked(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
Rectangle |
|||
{ |
|||
anchors.top: contentRectangle.bottom |
|||
anchors.topMargin: 15 |
|||
width: parent.width |
|||
Text |
|||
{ |
|||
text: buttonActionContainer.text |
|||
anchors.centerIn: parent |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,57 @@ |
|||
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 "js/Debugger.js" as Debugger |
|||
import "js/ErrorLocationFormater.js" as ErrorLocationFormater |
|||
import "." |
|||
|
|||
Rectangle { |
|||
color: "#ededed" |
|||
property alias bc: blockChain |
|||
|
|||
Connections |
|||
{ |
|||
target: projectModel |
|||
onProjectLoaded: { |
|||
loader.init() |
|||
} |
|||
|
|||
} |
|||
|
|||
Column |
|||
{ |
|||
anchors.margins: 10 |
|||
anchors.fill: parent |
|||
spacing: 10 |
|||
ScenarioLoader |
|||
{ |
|||
height: 70 |
|||
width: parent.width |
|||
id: loader |
|||
} |
|||
|
|||
Rectangle |
|||
{ |
|||
width: parent.width |
|||
height: 1 |
|||
color: "#cccccc" |
|||
} |
|||
|
|||
Connections |
|||
{ |
|||
target: loader |
|||
onLoaded: { |
|||
blockChain.load(scenario) |
|||
} |
|||
} |
|||
|
|||
BlockChain |
|||
{ |
|||
id: blockChain |
|||
width: parent.width |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,175 @@ |
|||
import QtQuick 2.2 |
|||
import QtQuick.Controls 1.1 |
|||
import QtQuick.Controls.Styles 1.1 |
|||
import QtQuick.Layouts 1.1 |
|||
import QtQuick.Dialogs 1.2 |
|||
import QtQuick.Window 2.0 |
|||
import QtQuick.Dialogs 1.1 |
|||
import Qt.labs.settings 1.0 |
|||
import "js/Debugger.js" as Debugger |
|||
import "js/ErrorLocationFormater.js" as ErrorLocationFormater |
|||
import "." |
|||
|
|||
RowLayout |
|||
{ |
|||
signal restored(variant scenario) |
|||
signal saved(variant scenario) |
|||
signal duplicated(variant scenario) |
|||
signal loaded(variant scenario) |
|||
spacing: 0 |
|||
function init() |
|||
{ |
|||
scenarioList.load() |
|||
} |
|||
|
|||
id: blockChainSelector |
|||
|
|||
Dialog { |
|||
id: newStateWin |
|||
modality: Qt.ApplicationModal |
|||
title: qsTr("New Project"); |
|||
|
|||
width: 320 |
|||
height: 120 |
|||
|
|||
visible: false |
|||
|
|||
contentItem: Rectangle { |
|||
anchors.fill: parent |
|||
anchors.margins: 10 |
|||
RowLayout { |
|||
anchors.verticalCenter: parent.verticalCenter |
|||
Text { |
|||
text: qsTr("Name:") |
|||
} |
|||
|
|||
Rectangle |
|||
{ |
|||
Layout.preferredWidth: 250 |
|||
Layout.preferredHeight: parent.height |
|||
border.width: 1 |
|||
border.color: "#cccccc" |
|||
TextInput |
|||
{ |
|||
anchors.fill: parent |
|||
id: stateName |
|||
} |
|||
} |
|||
} |
|||
RowLayout |
|||
{ |
|||
anchors.bottom: parent.bottom |
|||
anchors.right: parent.right; |
|||
function acceptAndClose() |
|||
{ |
|||
var item = projectModel.stateListModel.createDefaultState(); |
|||
item.title = stateName.text |
|||
projectModel.stateListModel.appendState(item) |
|||
projectModel.stateListModel.save() |
|||
close() |
|||
scenarioList.currentIndex = projectModel.stateListModel.count - 1 |
|||
} |
|||
|
|||
function close() |
|||
{ |
|||
newStateWin.close() |
|||
stateName.text = "" |
|||
} |
|||
|
|||
Button { |
|||
id: okButton; |
|||
enabled: stateName.text !== "" |
|||
text: qsTr("OK"); |
|||
onClicked: { |
|||
parent.acceptAndClose(); |
|||
} |
|||
} |
|||
Button { |
|||
text: qsTr("Cancel"); |
|||
onClicked: parent.close(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
ComboBox |
|||
{ |
|||
id: scenarioList |
|||
model: projectModel.stateListModel |
|||
textRole: "title" |
|||
onCurrentIndexChanged: |
|||
{ |
|||
restoreScenario.restore() |
|||
} |
|||
|
|||
function load() |
|||
{ |
|||
var state = projectModel.stateListModel.getState(currentIndex) |
|||
loaded(state) |
|||
} |
|||
} |
|||
|
|||
Row |
|||
{ |
|||
Layout.preferredWidth: 100 * 4 |
|||
Layout.preferredHeight: 30 |
|||
spacing: 0 |
|||
ScenarioButton { |
|||
id: restoreScenario |
|||
width: 100 |
|||
height: 30 |
|||
buttonShortcut: "" |
|||
sourceImg: "qrc:/qml/img/restoreicon@2x.png" |
|||
onClicked: { |
|||
restore() |
|||
} |
|||
text: qsTr("Restore") |
|||
function restore() |
|||
{ |
|||
var state = projectModel.stateListModel.reloadStateFromFromProject(scenarioList.currentIndex) |
|||
restored(state) |
|||
loaded(state) |
|||
} |
|||
} |
|||
|
|||
ScenarioButton { |
|||
id: saveScenario |
|||
text: qsTr("Save") |
|||
onClicked: { |
|||
projectModel.saveProjectFile() |
|||
saved(state) |
|||
} |
|||
width: 100 |
|||
height: 30 |
|||
buttonShortcut: "" |
|||
sourceImg: "qrc:/qml/img/saveicon@2x.png" |
|||
} |
|||
|
|||
ScenarioButton |
|||
{ |
|||
id: duplicateScenario |
|||
text: qsTr("Duplicate") |
|||
onClicked: { |
|||
projectModel.stateListModel.duplicateState(scenarioList.currentIndex) |
|||
duplicated(state) |
|||
} |
|||
width: 100 |
|||
height: 30 |
|||
buttonShortcut: "" |
|||
sourceImg: "qrc:/qml/img/duplicateicon@2x.png" |
|||
} |
|||
|
|||
ScenarioButton { |
|||
id: addScenario |
|||
width: 100 |
|||
height: 30 |
|||
buttonShortcut: "" |
|||
sourceImg: "qrc:/qml/img/plus.png" |
|||
onClicked: { |
|||
newStateWin.open() |
|||
} |
|||
text: qsTr("New") |
|||
} |
|||
} |
|||
|
|||
} |
After Width: | Height: | Size: 801 B |
After Width: | Height: | Size: 1.7 KiB |
Loading…
Reference in new issue