Vlad Gluhovsky
10 years ago
90 changed files with 2969 additions and 6292 deletions
Before Width: | Height: | Size: 171 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 34 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -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