From 05c353eca0c4e01457412dd643529200816ab159 Mon Sep 17 00:00:00 2001 From: obscuren Date: Fri, 21 Feb 2014 12:37:40 +0100 Subject: [PATCH] Added a basic UI --- config.go | 2 ++ ethereum.go | 76 ++++++++++++++++++++++++++++-------------------- ui/gui.go | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++ wallet.qml | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 211 insertions(+), 31 deletions(-) create mode 100644 ui/gui.go create mode 100644 wallet.qml diff --git a/config.go b/config.go index 573f5ded2..c25c8f2a3 100644 --- a/config.go +++ b/config.go @@ -15,11 +15,13 @@ var GenAddr bool var UseSeed bool var ImportKey string var ExportKey bool +var UseGui bool func Init() { flag.BoolVar(&StartConsole, "c", false, "debug and testing console") flag.BoolVar(&StartMining, "m", false, "start dagger mining") flag.BoolVar(&ShowGenesis, "g", false, "prints genesis header and exits") + flag.BoolVar(&UseGui, "gui", false, "use the gui") flag.BoolVar(&UseUPnP, "upnp", false, "enable UPnP support") flag.BoolVar(&UseSeed, "seed", true, "seed peers") flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key") diff --git a/ethereum.go b/ethereum.go index 36700a6d4..5eda09a44 100644 --- a/ethereum.go +++ b/ethereum.go @@ -5,6 +5,8 @@ import ( "github.com/ethereum/eth-go" "github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethutil" + "github.com/ethereum/go-ethereum/ui" + "github.com/niemeyer/qml" "github.com/obscuren/secp256k1-go" "log" "os" @@ -76,9 +78,16 @@ pubk: %x } func main() { - runtime.GOMAXPROCS(runtime.NumCPU()) Init() + // Qt has to be initialized in the main thread or it will throw errors + // It has to be called BEFORE setting the maximum procs. + if UseGui { + qml.Init(nil) + } + + runtime.GOMAXPROCS(runtime.NumCPU()) + ethchain.InitFees() ethutil.ReadConfig(".ethereum") ethutil.Config.Seed = UseSeed @@ -156,41 +165,46 @@ func main() { go console.Start() } - RegisterInterupts(ethereum) + if UseGui { + gui := ethui.New(ethereum) + gui.Start() + //ethereum.Stop() + } else { + RegisterInterupts(ethereum) + ethereum.Start() - ethereum.Start() + if StartMining { + log.Printf("Miner started\n") - if StartMining { - log.Printf("Miner started\n") + // Fake block mining. It broadcasts a new block every 5 seconds + go func() { + pow := ðchain.EasyPow{} + data, _ := ethutil.Config.Db.Get([]byte("KeyRing")) + keyRing := ethutil.NewValueFromBytes(data) + addr := keyRing.Get(1).Bytes() - // Fake block mining. It broadcasts a new block every 5 seconds - go func() { - pow := ðchain.EasyPow{} - data, _ := ethutil.Config.Db.Get([]byte("KeyRing")) - keyRing := ethutil.NewValueFromBytes(data) - addr := keyRing.Get(1).Bytes() + for { + txs := ethereum.TxPool.Flush() + // Create a new block which we're going to mine + block := ethereum.BlockManager.BlockChain().NewBlock(addr, txs) + // Apply all transactions to the block + ethereum.BlockManager.ApplyTransactions(block, block.Transactions()) - for { - txs := ethereum.TxPool.Flush() - // Create a new block which we're going to mine - block := ethereum.BlockManager.BlockChain().NewBlock(addr, txs) - // Apply all transactions to the block - ethereum.BlockManager.ApplyTransactions(block, block.Transactions()) + ethereum.BlockManager.AccumelateRewards(block, block) - ethereum.BlockManager.AccumelateRewards(block, block) - - // Search the nonce - block.Nonce = pow.Search(block) - err := ethereum.BlockManager.ProcessBlock(block) - if err != nil { - log.Println(err) - } else { - log.Println("\n+++++++ MINED BLK +++++++\n", ethereum.BlockManager.BlockChain().CurrentBlock) + // Search the nonce + block.Nonce = pow.Search(block) + err := ethereum.BlockManager.ProcessBlock(block) + if err != nil { + log.Println(err) + } else { + log.Println("\n+++++++ MINED BLK +++++++\n", ethereum.BlockManager.BlockChain().CurrentBlock) + } } - } - }() - } + }() + } - // Wait for shutdown - ethereum.WaitForShutdown() + // Wait for shutdown + ethereum.WaitForShutdown() + } } diff --git a/ui/gui.go b/ui/gui.go new file mode 100644 index 000000000..b2a8dad73 --- /dev/null +++ b/ui/gui.go @@ -0,0 +1,83 @@ +package ethui + +import ( + "bufio" + "encoding/hex" + "fmt" + "github.com/ethereum/eth-go" + "github.com/ethereum/eth-go/ethchain" + "github.com/ethereum/eth-go/ethutil" + "github.com/niemeyer/qml" + "strings" +) + +type Gui struct { + win *qml.Window + engine *qml.Engine + component *qml.Common + eth *eth.Ethereum +} + +func New(ethereum *eth.Ethereum) *Gui { + return &Gui{eth: ethereum} +} + +type Block struct { + Number int + Hash string +} + +func NewBlockFromBlock(block *ethchain.Block) *Block { + info := block.BlockInfo() + hash := hex.EncodeToString(block.Hash()) + + return &Block{Number: int(info.Number), Hash: hash} +} + +func (ui *Gui) Start() { + qml.RegisterTypes("GoExtensions", 1, 0, []qml.TypeSpec{{ + Init: func(p *Block, obj qml.Object) { p.Number = 0; p.Hash = "" }, + }}) + + ethutil.Config.Log.Infoln("[GUI] Starting GUI") + ui.engine = qml.NewEngine() + component, err := ui.engine.LoadFile("wallet.qml") + if err != nil { + panic(err) + } + + ui.win = component.CreateWindow(nil) + root := ui.win.Root() + + context := ui.engine.Context() + context.SetVar("tester", &Tester{root: root}) + + ui.eth.BlockManager.SecondaryBlockProcessor = ui + ui.eth.Start() + + ui.win.Show() + ui.win.Wait() +} + +func (ui *Gui) ProcessBlock(block *ethchain.Block) { + ui.win.Root().Call("addBlock", NewBlockFromBlock(block)) +} + +type Tester struct { + root qml.Object +} + +func (t *Tester) Compile(area qml.Object) { + fmt.Println(area) + ethutil.Config.Log.Infoln("[TESTER] Compiling") + + code := area.String("text") + + scanner := bufio.NewScanner(strings.NewReader(code)) + scanner.Split(bufio.ScanLines) + + var lines []string + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } +} diff --git a/wallet.qml b/wallet.qml new file mode 100644 index 000000000..2bf4e4576 --- /dev/null +++ b/wallet.qml @@ -0,0 +1,81 @@ +import QtQuick 2.0 +import QtQuick.Controls 1.0; +import QtQuick.Layouts 1.0; +import GoExtensions 1.0 + +ApplicationWindow { + id: root + + width: 800 + height: 600 + minimumHeight: 300 + + title: "Ethereal" + + toolBar: ToolBar { + id: mainToolbar + + RowLayout { + width: parent.width + Button { + text: "Send" + onClicked: tester.compile(codeView) + } + + TextField { + width: 200 + placeholderText: "Amount" + } + + TextField { + width: 300 + placeholderText: "Receiver Address (or empty for contract)" + Layout.fillWidth: true + } + + } + } + + SplitView { + id: splitView + height: 200 + anchors.top: parent.top + anchors.right: parent.right + anchors.left: parent.left + + TextArea { + id: codeView + width: parent.width /2 + } + + TextArea { + readOnly: true + } + } + + property var blockModel: ListModel { + id: blockModel + } + + TableView { + width: parent.width + height: 100 + anchors.bottom: parent.bottom + anchors.top: splitView.bottom + TableViewColumn{ role: "number" ; title: "#" ; width: 100 } + TableViewColumn{ role: "hash" ; title: "Hash" ; width: 560 } + + model: blockModel + } + + + statusBar: StatusBar { + RowLayout { + Label { text: "0.0.1" } + } + } + + function addBlock(block) { + blockModel.append({number: block.number, hash: block.hash}) + } +}