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 property alias miningButtonText: miningButton.text width: 900 height: 600 minimumHeight: 300 title: "Ethereal" // Takes care of loading all default plugins Component.onCompleted: { var historyView = addPlugin("./views/history.qml") var newTxView = addPlugin("./views/transaction.qml") var chainView = addPlugin("./views/chain.qml") var infoView = addPlugin("./views/info.qml") var pendingTxView = addPlugin("./views/pending_tx.qml") // Call the ready handler eth.done() } function addPlugin(path, options) { var component = Qt.createComponent(path); if(component.status != Component.Ready) { if(component.status == Component.Error) { console.debug("Error:"+ component.errorString()); } return } return mainSplit.addComponent(component, {objectName: objectName}) } MenuBar { Menu { title: "File" MenuItem { text: "Import App" shortcut: "Ctrl+o" onTriggered: openAppDialog.open() } MenuItem { text: "Browser" onTriggered: ui.openBrowser() } MenuItem { text: "Add plugin" onTriggered: { mainSplit.addPlugin("test") } } MenuSeparator {} MenuItem { text: "Import key" shortcut: "Ctrl+i" onTriggered: importDialog.open() } MenuItem { text: "Export keys" shortcut: "Ctrl+e" onTriggered: exportDialog.open() } //MenuSeparator {} } Menu { title: "Developer" MenuItem { text: "Debugger" shortcut: "Ctrl+d" onTriggered: ui.startDebugger() } MenuItem { text: "Import Tx" onTriggered: { txImportDialog.visible = true } } MenuItem { text: "Run JS file" onTriggered: { generalFileDialog.callback = function(path) { eth.evalJavascriptFile(path) } generalFileDialog.open() } } } Menu { title: "Network" MenuItem { text: "Add Peer" shortcut: "Ctrl+p" onTriggered: { addPeerWin.visible = true } } MenuItem { text: "Show Peers" shortcut: "Ctrl+e" onTriggered: { peerWindow.visible = true } } } Menu { title: "Help" MenuItem { text: "About" onTriggered: { aboutWin.visible = true } } } } property var blockModel: ListModel { id: blockModel } SplitView { property var views: []; id: mainSplit anchors.fill: parent resizing: false function setView(view) { for(var i = 0; i < views.length; i++) { views[i].visible = false } view.visible = true } function addComponent(component, options) { var view = mainView.createView(component, options) if(!view.hasOwnProperty("iconFile")) { console.log("Could not load plugin. Property 'iconFile' not found on view."); return; } menu.createMenuItem(view.iconFile, view); mainSplit.views.push(view); return view } Rectangle { id: menu Layout.minimumWidth: 80 Layout.maximumWidth: 80 anchors.top: parent.top color: "#252525" Component { id: menuItemTemplate Image { property var view; anchors.horizontalCenter: parent.horizontalCenter MouseArea { anchors.fill: parent onClicked: { mainSplit.setView(view) } } } } function createMenuItem(icon, view) { var comp = menuItemTemplate.createObject(menuColumn) comp.view = view comp.source = icon } ColumnLayout { id: menuColumn y: 50 anchors.left: parent.left anchors.right: parent.right } } Rectangle { id: mainView color: "#00000000" anchors.right: parent.right anchors.left: menu.right anchors.bottom: parent.bottom anchors.top: parent.top function createView(component) { var view = component.createObject(mainView) return view; } } } FileDialog { id: openAppDialog title: "Open QML Application" onAccepted: { var path = openAppDialog.fileUrl.toString() var ext = path.split('.').pop() if(ext == "html" || ext == "htm") { ui.openHtml(path) }else if(ext == "qml"){ ui.openQml(path) } } } FileDialog { id: exportDialog title: "Export keys" onAccepted: { } } FileDialog { id: generalFileDialog property var callback; onAccepted: { var path = this.fileUrl.toString() callback.call(this, path) } } FileDialog { id: importDialog title: "Import key" onAccepted: { var path = this.fileUrl.toString() ui.importKey(path) } } statusBar: StatusBar { height: 30 RowLayout { Button { id: miningButton onClicked: { eth.toggleMining() } text: "Start Mining" } Button { property var enabled: true id: debuggerWindow onClicked: { ui.startDebugger() } text: "Debugger" } Button { id: importAppButton anchors.left: debuggerWindow.right anchors.leftMargin: 5 onClicked: openAppDialog.open() text: "Import App" } Label { anchors.left: importAppButton.right anchors.leftMargin: 5 id: walletValueLabel } } Label { y: 6 id: lastBlockLabel objectName: "lastBlockLabel" visible: true text: "" font.pixelSize: 10 anchors.right: peerGroup.left anchors.rightMargin: 5 } ProgressBar { id: syncProgressIndicator visible: false objectName: "syncProgressIndicator" y: 3 width: 140 indeterminate: true anchors.right: peerGroup.left anchors.rightMargin: 5 } RowLayout { id: peerGroup y: 7 anchors.right: parent.right MouseArea { onDoubleClicked: peerWindow.visible = true anchors.fill: parent } Label { id: peerLabel font.pixelSize: 8 text: "0 / 0" } Image { id: peerImage width: 10; height: 10 source: "../network.png" } } } function setWalletValue(value) { walletValueLabel.text = value } function loadPlugin(name) { console.log("Loading plugin" + name) mainView.addPlugin(name) } function setPeers(text) { peerLabel.text = text } function addPeer(peer) { // We could just append the whole peer object but it cries if you try to alter them peerModel.append({ip: peer.ip, port: peer.port, lastResponse:timeAgo(peer.lastSend), latency: peer.latency, version: peer.version}) } function resetPeers(){ peerModel.clear() } function timeAgo(unixTs){ var lapsed = (Date.now() - new Date(unixTs*1000)) / 1000 return (lapsed + " seconds ago") } function convertToPretty(unixTs){ var a = new Date(unixTs*1000); var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; var year = a.getFullYear(); var month = months[a.getMonth()]; var date = a.getDate(); var hour = a.getHours(); var min = a.getMinutes(); var sec = a.getSeconds(); var time = date+' '+month+' '+year+' '+hour+':'+min+':'+sec ; return time; } // ****************************************** // Windows // ****************************************** Window { id: peerWindow //flags: Qt.CustomizeWindowHint | Qt.Tool | Qt.WindowCloseButtonHint height: 200 width: 700 Rectangle { anchors.fill: parent property var peerModel: ListModel { id: peerModel } TableView { anchors.fill: parent id: peerTable model: peerModel TableViewColumn{width: 100; role: "ip" ; title: "IP" } TableViewColumn{width: 60; role: "port" ; title: "Port" } TableViewColumn{width: 140; role: "lastResponse"; title: "Last event" } TableViewColumn{width: 100; role: "latency"; title: "Latency" } TableViewColumn{width: 260; role: "version" ; title: "Version" } } } } Window { id: aboutWin visible: false title: "About" minimumWidth: 350 maximumWidth: 350 maximumHeight: 200 minimumHeight: 200 Image { id: aboutIcon height: 150 width: 150 fillMode: Image.PreserveAspectFit smooth: true source: "../facet.png" x: 10 y: 10 } Text { anchors.left: aboutIcon.right anchors.leftMargin: 10 font.pointSize: 12 text: "

Ethereal - Adrastea


Development

Jeffrey Wilcke
Maran Hidskes
Viktor TrĂ³n
" } } Window { id: txImportDialog minimumWidth: 270 maximumWidth: 270 maximumHeight: 50 minimumHeight: 50 TextField { id: txImportField width: 170 anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left anchors.leftMargin: 10 onAccepted: { } } Button { anchors.left: txImportField.right anchors.verticalCenter: parent.verticalCenter anchors.leftMargin: 5 text: "Import" onClicked: { eth.importTx(txImportField.text) txImportField.visible = false } } Component.onCompleted: { addrField.focus = true } } 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" onAccepted: { ui.connectToPeer(addrField.text) addPeerWin.visible = false } } Button { anchors.left: addrField.right anchors.verticalCenter: parent.verticalCenter anchors.leftMargin: 5 text: "Add" onClicked: { ui.connectToPeer(addrField.text) addPeerWin.visible = false } } Component.onCompleted: { addrField.focus = true } } }