forked from mirror/go-ethereum
commit
0adfa489de
After Width: | Height: | Size: 2.8 KiB |
@ -0,0 +1,35 @@ |
|||||||
|
import QtQuick 2.0 |
||||||
|
import QtQuick.Controls 1.0; |
||||||
|
import QtQuick.Layouts 1.0; |
||||||
|
import Ethereum 1.0 |
||||||
|
|
||||||
|
ApplicationWindow { |
||||||
|
minimumWidth: 500 |
||||||
|
maximumWidth: 500 |
||||||
|
maximumHeight: 100 |
||||||
|
minimumHeight: 100 |
||||||
|
|
||||||
|
title: "Ethereum Dice" |
||||||
|
|
||||||
|
TextField { |
||||||
|
id: textField |
||||||
|
anchors.verticalCenter: parent.verticalCenter |
||||||
|
anchors.horizontalCenter: parent.horizontalCenter |
||||||
|
placeholderText: "Amount" |
||||||
|
} |
||||||
|
Label { |
||||||
|
id: txHash |
||||||
|
anchors.bottom: textField.top |
||||||
|
anchors.bottomMargin: 5 |
||||||
|
anchors.horizontalCenter: parent.horizontalCenter |
||||||
|
} |
||||||
|
Button { |
||||||
|
anchors.top: textField.bottom |
||||||
|
anchors.horizontalCenter: parent.horizontalCenter |
||||||
|
anchors.topMargin: 5 |
||||||
|
text: "Place bet" |
||||||
|
onClicked: { |
||||||
|
txHash.text = eth.createTx("e6716f9544a56c530d868e4bfbacb172315bdead", textField.text) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
import QtQuick 2.0 |
||||||
|
import QtQuick.Controls 1.0; |
||||||
|
import QtQuick.Layouts 1.0; |
||||||
|
|
||||||
|
Rectangle { |
||||||
|
id: transactionView |
||||||
|
visible: false |
||||||
|
Text { text: "TX VIEW" } |
||||||
|
} |
@ -0,0 +1,217 @@ |
|||||||
|
package ethui |
||||||
|
|
||||||
|
import ( |
||||||
|
"bytes" |
||||||
|
"encoding/hex" |
||||||
|
"fmt" |
||||||
|
"github.com/ethereum/eth-go" |
||||||
|
"github.com/ethereum/eth-go/ethchain" |
||||||
|
"github.com/ethereum/eth-go/ethdb" |
||||||
|
"github.com/ethereum/eth-go/ethutil" |
||||||
|
"github.com/niemeyer/qml" |
||||||
|
"math/big" |
||||||
|
"strings" |
||||||
|
) |
||||||
|
|
||||||
|
// Block interface exposed to QML
|
||||||
|
type Block struct { |
||||||
|
Number int |
||||||
|
Hash string |
||||||
|
} |
||||||
|
|
||||||
|
type Tx struct { |
||||||
|
Value, Hash, Address string |
||||||
|
} |
||||||
|
|
||||||
|
func NewTxFromTransaction(tx *ethchain.Transaction) *Tx { |
||||||
|
hash := hex.EncodeToString(tx.Hash()) |
||||||
|
sender := hex.EncodeToString(tx.Recipient) |
||||||
|
|
||||||
|
return &Tx{Hash: hash, Value: ethutil.CurrencyToString(tx.Value), Address: sender} |
||||||
|
} |
||||||
|
|
||||||
|
// Creates a new QML Block from a chain block
|
||||||
|
func NewBlockFromBlock(block *ethchain.Block) *Block { |
||||||
|
info := block.BlockInfo() |
||||||
|
hash := hex.EncodeToString(block.Hash()) |
||||||
|
|
||||||
|
return &Block{Number: int(info.Number), Hash: hash} |
||||||
|
} |
||||||
|
|
||||||
|
type Gui struct { |
||||||
|
// The main application window
|
||||||
|
win *qml.Window |
||||||
|
// QML Engine
|
||||||
|
engine *qml.Engine |
||||||
|
component *qml.Common |
||||||
|
// The ethereum interface
|
||||||
|
eth *eth.Ethereum |
||||||
|
|
||||||
|
// The public Ethereum library
|
||||||
|
lib *EthLib |
||||||
|
|
||||||
|
txDb *ethdb.LDBDatabase |
||||||
|
|
||||||
|
addr []byte |
||||||
|
} |
||||||
|
|
||||||
|
// Create GUI, but doesn't start it
|
||||||
|
func New(ethereum *eth.Ethereum) *Gui { |
||||||
|
lib := &EthLib{blockManager: ethereum.BlockManager, blockChain: ethereum.BlockManager.BlockChain(), txPool: ethereum.TxPool} |
||||||
|
db, err := ethdb.NewLDBDatabase("tx_database") |
||||||
|
if err != nil { |
||||||
|
panic(err) |
||||||
|
} |
||||||
|
|
||||||
|
key := ethutil.Config.Db.GetKeys()[0] |
||||||
|
addr := key.Address() |
||||||
|
|
||||||
|
ethereum.BlockManager.WatchAddr(addr) |
||||||
|
|
||||||
|
return &Gui{eth: ethereum, lib: lib, txDb: db, addr: addr} |
||||||
|
} |
||||||
|
|
||||||
|
func (ui *Gui) Start() { |
||||||
|
defer ui.txDb.Close() |
||||||
|
|
||||||
|
// Register ethereum functions
|
||||||
|
qml.RegisterTypes("Ethereum", 1, 0, []qml.TypeSpec{{ |
||||||
|
Init: func(p *Block, obj qml.Object) { p.Number = 0; p.Hash = "" }, |
||||||
|
}, { |
||||||
|
Init: func(p *Tx, obj qml.Object) { p.Value = ""; p.Hash = ""; p.Address = "" }, |
||||||
|
}}) |
||||||
|
|
||||||
|
ethutil.Config.Log.Infoln("[GUI] Starting GUI") |
||||||
|
// Create a new QML engine
|
||||||
|
ui.engine = qml.NewEngine() |
||||||
|
// Load the main QML interface
|
||||||
|
component, err := ui.engine.LoadFile("wallet.qml") |
||||||
|
if err != nil { |
||||||
|
panic(err) |
||||||
|
} |
||||||
|
ui.engine.LoadFile("transactions.qml") |
||||||
|
|
||||||
|
ui.win = component.CreateWindow(nil) |
||||||
|
|
||||||
|
context := ui.engine.Context() |
||||||
|
|
||||||
|
// Expose the eth library and the ui library to QML
|
||||||
|
context.SetVar("eth", ui.lib) |
||||||
|
context.SetVar("ui", &UiLib{engine: ui.engine, eth: ui.eth}) |
||||||
|
|
||||||
|
// Register the ui as a block processor
|
||||||
|
ui.eth.BlockManager.SecondaryBlockProcessor = ui |
||||||
|
//ui.eth.TxPool.SecondaryProcessor = ui
|
||||||
|
|
||||||
|
// Add the ui as a log system so we can log directly to the UGI
|
||||||
|
ethutil.Config.Log.AddLogSystem(ui) |
||||||
|
|
||||||
|
// Loads previous blocks
|
||||||
|
go ui.setInitialBlockChain() |
||||||
|
go ui.readPreviousTransactions() |
||||||
|
go ui.update() |
||||||
|
|
||||||
|
ui.win.Show() |
||||||
|
ui.win.Wait() |
||||||
|
|
||||||
|
ui.eth.Stop() |
||||||
|
} |
||||||
|
|
||||||
|
func (ui *Gui) setInitialBlockChain() { |
||||||
|
// Load previous 10 blocks
|
||||||
|
chain := ui.eth.BlockManager.BlockChain().GetChain(ui.eth.BlockManager.BlockChain().CurrentBlock.Hash(), 10) |
||||||
|
for _, block := range chain { |
||||||
|
ui.ProcessBlock(block) |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
func (ui *Gui) readPreviousTransactions() { |
||||||
|
it := ui.txDb.Db().NewIterator(nil, nil) |
||||||
|
for it.Next() { |
||||||
|
tx := ethchain.NewTransactionFromBytes(it.Value()) |
||||||
|
|
||||||
|
ui.win.Root().Call("addTx", NewTxFromTransaction(tx)) |
||||||
|
} |
||||||
|
it.Release() |
||||||
|
} |
||||||
|
|
||||||
|
func (ui *Gui) ProcessBlock(block *ethchain.Block) { |
||||||
|
ui.win.Root().Call("addBlock", NewBlockFromBlock(block)) |
||||||
|
} |
||||||
|
|
||||||
|
// Simple go routine function that updates the list of peers in the GUI
|
||||||
|
func (ui *Gui) update() { |
||||||
|
txChan := make(chan ethchain.TxMsg, 1) |
||||||
|
ui.eth.TxPool.Subscribe(txChan) |
||||||
|
|
||||||
|
account := ui.eth.BlockManager.GetAddrState(ui.addr).Account |
||||||
|
unconfirmedFunds := new(big.Int) |
||||||
|
ui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(account.Amount))) |
||||||
|
for { |
||||||
|
select { |
||||||
|
case txMsg := <-txChan: |
||||||
|
tx := txMsg.Tx |
||||||
|
|
||||||
|
if txMsg.Type == ethchain.TxPre { |
||||||
|
if bytes.Compare(tx.Sender(), ui.addr) == 0 { |
||||||
|
ui.win.Root().Call("addTx", NewTxFromTransaction(tx)) |
||||||
|
ui.txDb.Put(tx.Hash(), tx.RlpEncode()) |
||||||
|
|
||||||
|
ui.eth.BlockManager.GetAddrState(ui.addr).Nonce += 1 |
||||||
|
unconfirmedFunds.Sub(unconfirmedFunds, tx.Value) |
||||||
|
} else if bytes.Compare(tx.Recipient, ui.addr) == 0 { |
||||||
|
ui.win.Root().Call("addTx", NewTxFromTransaction(tx)) |
||||||
|
ui.txDb.Put(tx.Hash(), tx.RlpEncode()) |
||||||
|
|
||||||
|
unconfirmedFunds.Add(unconfirmedFunds, tx.Value) |
||||||
|
} |
||||||
|
|
||||||
|
pos := "+" |
||||||
|
if unconfirmedFunds.Cmp(big.NewInt(0)) >= 0 { |
||||||
|
pos = "-" |
||||||
|
} |
||||||
|
val := ethutil.CurrencyToString(new(big.Int).Abs(ethutil.BigCopy(unconfirmedFunds))) |
||||||
|
str := fmt.Sprintf("%v (%s %v)", ethutil.CurrencyToString(account.Amount), pos, val) |
||||||
|
|
||||||
|
ui.win.Root().Call("setWalletValue", str) |
||||||
|
} else { |
||||||
|
amount := account.Amount |
||||||
|
if bytes.Compare(tx.Sender(), ui.addr) == 0 { |
||||||
|
amount.Sub(account.Amount, tx.Value) |
||||||
|
} else if bytes.Compare(tx.Recipient, ui.addr) == 0 { |
||||||
|
amount.Add(account.Amount, tx.Value) |
||||||
|
} |
||||||
|
|
||||||
|
ui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(amount))) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
accountAmount := ui.eth.BlockManager.GetAddrState(ui.addr).Account.Amount |
||||||
|
ui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", accountAmount)) |
||||||
|
|
||||||
|
ui.win.Root().Call("setPeers", fmt.Sprintf("%d / %d", ui.eth.Peers().Len(), ui.eth.MaxPeers)) |
||||||
|
|
||||||
|
time.Sleep(1 * time.Second) |
||||||
|
*/ |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Logging functions that log directly to the GUI interface
|
||||||
|
func (ui *Gui) Println(v ...interface{}) { |
||||||
|
str := strings.TrimRight(fmt.Sprintln(v...), "\n") |
||||||
|
lines := strings.Split(str, "\n") |
||||||
|
for _, line := range lines { |
||||||
|
ui.win.Root().Call("addLog", line) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (ui *Gui) Printf(format string, v ...interface{}) { |
||||||
|
str := strings.TrimRight(fmt.Sprintf(format, v...), "\n") |
||||||
|
lines := strings.Split(str, "\n") |
||||||
|
for _, line := range lines { |
||||||
|
ui.win.Root().Call("addLog", line) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,60 @@ |
|||||||
|
package ethui |
||||||
|
|
||||||
|
import ( |
||||||
|
"encoding/hex" |
||||||
|
"fmt" |
||||||
|
"github.com/ethereum/eth-go/ethchain" |
||||||
|
"github.com/ethereum/eth-go/ethutil" |
||||||
|
"strings" |
||||||
|
) |
||||||
|
|
||||||
|
type EthLib struct { |
||||||
|
blockManager *ethchain.BlockManager |
||||||
|
blockChain *ethchain.BlockChain |
||||||
|
txPool *ethchain.TxPool |
||||||
|
} |
||||||
|
|
||||||
|
func (lib *EthLib) CreateTx(receiver, a, data string) string { |
||||||
|
var hash []byte |
||||||
|
if len(receiver) == 0 { |
||||||
|
hash = ethchain.ContractAddr |
||||||
|
} else { |
||||||
|
var err error |
||||||
|
hash, err = hex.DecodeString(receiver) |
||||||
|
if err != nil { |
||||||
|
return err.Error() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
k, _ := ethutil.Config.Db.Get([]byte("KeyRing")) |
||||||
|
keyRing := ethutil.NewValueFromBytes(k) |
||||||
|
|
||||||
|
amount := ethutil.Big(a) |
||||||
|
code := ethchain.Compile(strings.Split(data, "\n")) |
||||||
|
tx := ethchain.NewTransaction(hash, amount, code) |
||||||
|
tx.Nonce = lib.blockManager.GetAddrState(keyRing.Get(1).Bytes()).Nonce |
||||||
|
|
||||||
|
tx.Sign(keyRing.Get(0).Bytes()) |
||||||
|
|
||||||
|
lib.txPool.QueueTransaction(tx) |
||||||
|
|
||||||
|
if len(receiver) == 0 { |
||||||
|
ethutil.Config.Log.Infof("Contract addr %x", tx.Hash()[12:]) |
||||||
|
} else { |
||||||
|
ethutil.Config.Log.Infof("Tx hash %x", tx.Hash()) |
||||||
|
} |
||||||
|
|
||||||
|
return ethutil.Hex(tx.Hash()) |
||||||
|
} |
||||||
|
|
||||||
|
func (lib *EthLib) GetBlock(hexHash string) *Block { |
||||||
|
hash, err := hex.DecodeString(hexHash) |
||||||
|
if err != nil { |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
block := lib.blockChain.GetBlock(hash) |
||||||
|
fmt.Println(block) |
||||||
|
|
||||||
|
return &Block{Number: int(block.BlockInfo().Number), Hash: ethutil.Hex(block.Hash())} |
||||||
|
} |
@ -0,0 +1,40 @@ |
|||||||
|
package ethui |
||||||
|
|
||||||
|
import ( |
||||||
|
"github.com/ethereum/eth-go" |
||||||
|
"github.com/ethereum/eth-go/ethutil" |
||||||
|
"github.com/niemeyer/qml" |
||||||
|
) |
||||||
|
|
||||||
|
// UI Library that has some basic functionality exposed
|
||||||
|
type UiLib struct { |
||||||
|
engine *qml.Engine |
||||||
|
eth *eth.Ethereum |
||||||
|
connected bool |
||||||
|
} |
||||||
|
|
||||||
|
// Opens a QML file (external application)
|
||||||
|
func (ui *UiLib) Open(path string) { |
||||||
|
component, err := ui.engine.LoadFile(path[7:]) |
||||||
|
if err != nil { |
||||||
|
ethutil.Config.Log.Debugln(err) |
||||||
|
} |
||||||
|
win := component.CreateWindow(nil) |
||||||
|
|
||||||
|
go func() { |
||||||
|
win.Show() |
||||||
|
win.Wait() |
||||||
|
}() |
||||||
|
} |
||||||
|
|
||||||
|
func (ui *UiLib) Connect(button qml.Object) { |
||||||
|
if !ui.connected { |
||||||
|
ui.eth.Start() |
||||||
|
ui.connected = true |
||||||
|
button.Set("enabled", false) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (ui *UiLib) ConnectToPeer(addr string) { |
||||||
|
ui.eth.ConnectToPeer(addr) |
||||||
|
} |
@ -0,0 +1,357 @@ |
|||||||
|
import QtQuick 2.0 |
||||||
|
import QtQuick.Controls 1.0; |
||||||
|
import QtQuick.Layouts 1.0; |
||||||
|
import QtQuick.Dialogs 1.0; |
||||||
|
import QtQuick.Window 2.1; |
||||||
|
import QtQuick.Controls.Styles 1.1 |
||||||
|
import Ethereum 1.0 |
||||||
|
|
||||||
|
ApplicationWindow { |
||||||
|
id: root |
||||||
|
|
||||||
|
width: 900 |
||||||
|
height: 600 |
||||||
|
minimumHeight: 300 |
||||||
|
|
||||||
|
title: "Ethereal" |
||||||
|
|
||||||
|
MenuBar { |
||||||
|
Menu { |
||||||
|
title: "File" |
||||||
|
MenuItem { |
||||||
|
text: "Import App" |
||||||
|
shortcut: "Ctrl+o" |
||||||
|
onTriggered: openAppDialog.open() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Menu { |
||||||
|
title: "Network" |
||||||
|
MenuItem { |
||||||
|
text: "Add Peer" |
||||||
|
shortcut: "Ctrl+p" |
||||||
|
onTriggered: { |
||||||
|
addPeerWin.visible = true |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
MenuItem { |
||||||
|
text: "Start" |
||||||
|
onTriggered: ui.connect() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Menu { |
||||||
|
title: "Help" |
||||||
|
MenuItem { |
||||||
|
text: "About" |
||||||
|
onTriggered: { |
||||||
|
aboutWin.visible = true |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
property var blockModel: ListModel { |
||||||
|
id: blockModel |
||||||
|
} |
||||||
|
|
||||||
|
function setView(view) { |
||||||
|
networkView.visible = false |
||||||
|
historyView.visible = false |
||||||
|
newTxView.visible = false |
||||||
|
view.visible = true |
||||||
|
//root.title = "Ethereal - " = view.title |
||||||
|
} |
||||||
|
|
||||||
|
SplitView { |
||||||
|
anchors.fill: parent |
||||||
|
resizing: false |
||||||
|
|
||||||
|
Rectangle { |
||||||
|
id: menu |
||||||
|
Layout.minimumWidth: 80 |
||||||
|
Layout.maximumWidth: 80 |
||||||
|
anchors.bottom: parent.bottom |
||||||
|
anchors.top: parent.top |
||||||
|
//color: "#D9DDE7" |
||||||
|
color: "#252525" |
||||||
|
|
||||||
|
ColumnLayout { |
||||||
|
y: 50 |
||||||
|
anchors.left: parent.left |
||||||
|
anchors.right: parent.right |
||||||
|
height: 200 |
||||||
|
Image { |
||||||
|
source: "tx.png" |
||||||
|
anchors.horizontalCenter: parent.horizontalCenter |
||||||
|
MouseArea { |
||||||
|
anchors.fill: parent |
||||||
|
onClicked: { |
||||||
|
setView(historyView) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
Image { |
||||||
|
source: "new.png" |
||||||
|
anchors.horizontalCenter: parent.horizontalCenter |
||||||
|
MouseArea { |
||||||
|
anchors.fill: parent |
||||||
|
onClicked: { |
||||||
|
setView(newTxView) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
Image { |
||||||
|
source: "net.png" |
||||||
|
anchors.horizontalCenter: parent.horizontalCenter |
||||||
|
MouseArea { |
||||||
|
anchors.fill: parent |
||||||
|
onClicked: { |
||||||
|
setView(networkView) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
property var txModel: ListModel { |
||||||
|
id: txModel |
||||||
|
} |
||||||
|
|
||||||
|
Rectangle { |
||||||
|
id: historyView |
||||||
|
property var title: "Transactions" |
||||||
|
anchors.right: parent.right |
||||||
|
anchors.left: menu.right |
||||||
|
anchors.bottom: parent.bottom |
||||||
|
anchors.top: parent.top |
||||||
|
TableView { |
||||||
|
id: txTableView |
||||||
|
anchors.fill: parent |
||||||
|
TableViewColumn{ role: "value" ; title: "Value" ; width: 100 } |
||||||
|
TableViewColumn{ role: "address" ; title: "Address" ; width: 430 } |
||||||
|
|
||||||
|
model: txModel |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Rectangle { |
||||||
|
id: newTxView |
||||||
|
property var title: "New transaction" |
||||||
|
visible: false |
||||||
|
anchors.right: parent.right |
||||||
|
anchors.left: menu.right |
||||||
|
anchors.bottom: parent.bottom |
||||||
|
anchors.top: parent.top |
||||||
|
color: "#00000000" |
||||||
|
|
||||||
|
ColumnLayout { |
||||||
|
width: 400 |
||||||
|
anchors.left: parent.left |
||||||
|
anchors.top: parent.top |
||||||
|
anchors.leftMargin: 5 |
||||||
|
anchors.topMargin: 5 |
||||||
|
TextField { |
||||||
|
id: txAmount |
||||||
|
width: 200 |
||||||
|
placeholderText: "Amount" |
||||||
|
} |
||||||
|
|
||||||
|
TextField { |
||||||
|
id: txReceiver |
||||||
|
placeholderText: "Receiver Address (or empty for contract)" |
||||||
|
Layout.fillWidth: true |
||||||
|
} |
||||||
|
|
||||||
|
Label { |
||||||
|
text: "Transaction data" |
||||||
|
} |
||||||
|
TextArea { |
||||||
|
id: codeView |
||||||
|
anchors.topMargin: 5 |
||||||
|
Layout.fillWidth: true |
||||||
|
width: parent.width /2 |
||||||
|
} |
||||||
|
|
||||||
|
Button { |
||||||
|
text: "Send" |
||||||
|
onClicked: { |
||||||
|
console.log(eth.createTx(txReceiver.text, txAmount.text, codeView.text)) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
Rectangle { |
||||||
|
id: networkView |
||||||
|
property var title: "Network" |
||||||
|
visible: false |
||||||
|
anchors.right: parent.right |
||||||
|
anchors.bottom: parent.bottom |
||||||
|
anchors.top: parent.top |
||||||
|
|
||||||
|
TableView { |
||||||
|
id: blockTable |
||||||
|
width: parent.width |
||||||
|
anchors.top: parent.top |
||||||
|
anchors.bottom: logView.top |
||||||
|
TableViewColumn{ role: "number" ; title: "#" ; width: 100 } |
||||||
|
TableViewColumn{ role: "hash" ; title: "Hash" ; width: 560 } |
||||||
|
|
||||||
|
model: blockModel |
||||||
|
|
||||||
|
onDoubleClicked: { |
||||||
|
popup.visible = true |
||||||
|
popup.block = eth.getBlock(blockModel.get(row).hash) |
||||||
|
popup.hashLabel.text = popup.block.hash |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
property var logModel: ListModel { |
||||||
|
id: logModel |
||||||
|
} |
||||||
|
|
||||||
|
TableView { |
||||||
|
id: logView |
||||||
|
width: parent.width |
||||||
|
height: 150 |
||||||
|
anchors.bottom: parent.bottom |
||||||
|
TableViewColumn{ role: "description" ; title: "log" } |
||||||
|
|
||||||
|
model: logModel |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
FileDialog { |
||||||
|
id: openAppDialog |
||||||
|
title: "Open QML Application" |
||||||
|
onAccepted: { |
||||||
|
ui.open(openAppDialog.fileUrl.toString()) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
statusBar: StatusBar { |
||||||
|
RowLayout { |
||||||
|
anchors.fill: parent |
||||||
|
Button { |
||||||
|
property var enabled: true |
||||||
|
id: connectButton |
||||||
|
onClicked: { |
||||||
|
if(this.enabled) { |
||||||
|
ui.connect(this) |
||||||
|
} |
||||||
|
} |
||||||
|
text: "Connect" |
||||||
|
} |
||||||
|
Button { |
||||||
|
id: importAppButton |
||||||
|
anchors.left: connectButton.right |
||||||
|
anchors.leftMargin: 5 |
||||||
|
onClicked: openAppDialog.open() |
||||||
|
text: "Import App" |
||||||
|
} |
||||||
|
|
||||||
|
Label { |
||||||
|
anchors.left: importAppButton.right |
||||||
|
anchors.leftMargin: 5 |
||||||
|
id: walletValueLabel |
||||||
|
} |
||||||
|
|
||||||
|
Label { |
||||||
|
anchors.right: peerImage.left |
||||||
|
anchors.rightMargin: 5 |
||||||
|
id: peerLabel |
||||||
|
font.pixelSize: 8 |
||||||
|
text: "0 / 0" |
||||||
|
} |
||||||
|
Image { |
||||||
|
id: peerImage |
||||||
|
anchors.right: parent.right |
||||||
|
width: 10; height: 10 |
||||||
|
source: "network.png" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Window { |
||||||
|
id: popup |
||||||
|
visible: false |
||||||
|
property var block |
||||||
|
Label { |
||||||
|
id: hashLabel |
||||||
|
anchors.horizontalCenter: parent.horizontalCenter |
||||||
|
anchors.verticalCenter: parent.verticalCenter |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Window { |
||||||
|
id: addPeerWin |
||||||
|
visible: false |
||||||
|
minimumWidth: 230 |
||||||
|
maximumWidth: 230 |
||||||
|
maximumHeight: 50 |
||||||
|
minimumHeight: 50 |
||||||
|
|
||||||
|
TextField { |
||||||
|
id: addrField |
||||||
|
anchors.verticalCenter: parent.verticalCenter |
||||||
|
anchors.left: parent.left |
||||||
|
anchors.leftMargin: 10 |
||||||
|
placeholderText: "address:port" |
||||||
|
} |
||||||
|
Button { |
||||||
|
anchors.left: addrField.right |
||||||
|
anchors.verticalCenter: parent.verticalCenter |
||||||
|
anchors.leftMargin: 5 |
||||||
|
text: "Add" |
||||||
|
onClicked: { |
||||||
|
ui.connectToPeer(addrField.text) |
||||||
|
addPeerWin.visible = false |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Window { |
||||||
|
id: aboutWin |
||||||
|
visible: false |
||||||
|
title: "About" |
||||||
|
minimumWidth: 300 |
||||||
|
maximumWidth: 300 |
||||||
|
maximumHeight: 200 |
||||||
|
minimumHeight: 200 |
||||||
|
|
||||||
|
Text { |
||||||
|
font.pointSize: 18 |
||||||
|
text: "Eth Go" |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
function setWalletValue(value) { |
||||||
|
walletValueLabel.text = value |
||||||
|
} |
||||||
|
|
||||||
|
function addTx(tx) { |
||||||
|
txModel.insert(0, {hash: tx.hash, address: tx.address, value: tx.value}) |
||||||
|
} |
||||||
|
|
||||||
|
function addBlock(block) { |
||||||
|
blockModel.insert(0, {number: block.number, hash: block.hash}) |
||||||
|
} |
||||||
|
|
||||||
|
function addLog(str) { |
||||||
|
if(str.len != 0) { |
||||||
|
logModel.append({description: str}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function setPeers(text) { |
||||||
|
peerLabel.text = text |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue