import QtQuick 2.0 import QtWebKit 3.0 import QtWebKit.experimental 1.0 import QtQuick.Controls 1.0; import QtQuick.Controls.Styles 1.0 import QtQuick.Layouts 1.0; import QtQuick.Window 2.1; import Ethereum 1.0 //ApplicationWindow { Rectangle { id: window property var title: "Browser" property var iconSource: "../browser.png" property var menuItem //width: 1000 //height: 800 //minimumHeight: 300 property alias url: webview.url property alias webView: webview Component.onCompleted: { webview.url = "http://etherian.io" } Item { objectName: "root" id: root anchors.fill: parent state: "inspectorShown" RowLayout { id: navBar height: 40 anchors { left: parent.left right: parent.right leftMargin: 7 } Button { id: back onClicked: { webview.goBack() } style: ButtonStyle { background: Image { source: "../back.png" width: 30 height: 30 } } } TextField { anchors { left: back.right right: toggleInspector.left leftMargin: 5 rightMargin: 5 } text: "http://etherian.io" id: uriNav y: parent.height / 2 - this.height / 2 Keys.onReturnPressed: { webview.url = this.text; } } Button { id: toggleInspector anchors { right: parent.right } iconSource: "../bug.png" onClicked: { if(inspector.visible == true){ inspector.visible = false }else{ inspector.visible = true inspector.url = webview.experimental.remoteInspectorUrl } } } } WebView { objectName: "webView" id: webview anchors { left: parent.left right: parent.right bottom: parent.bottom top: navBar.bottom } onTitleChanged: { window.title = title } property var cleanPath: false onNavigationRequested: { if(!this.cleanPath) { var uri = request.url.toString(); if(!/.*\:\/\/.*/.test(uri)) { uri = "http://" + uri; } var reg = /(^https?\:\/\/(?:www\.)?)([a-zA-Z0-9_\-]*\.eth)(.*)/ if(reg.test(uri)) { uri.replace(reg, function(match, pre, domain, path) { uri = pre; var lookup = ui.lookupDomain(domain.substring(0, domain.length - 4)); var ip = []; for(var i = 0, l = lookup.length; i < l; i++) { ip.push(lookup.charCodeAt(i)) } if(ip.length != 0) { uri += lookup; } else { uri += domain; } uri += path; }); } this.cleanPath = true; webview.url = uri; } else { // Prevent inf loop. this.cleanPath = false; } } experimental.preferences.javascriptEnabled: true experimental.preferences.navigatorQtObjectEnabled: true experimental.preferences.developerExtrasEnabled: true experimental.userScripts: ["../ext/pre.js", "../ext/big.js", "../ext/string.js", "../ext/ethereum.js"] experimental.onMessageReceived: { console.log("[onMessageReceived]: ", message.data) // TODO move to messaging.js var data = JSON.parse(message.data) try { switch(data.call) { case "getCoinBase": postData(data._seed, eth.coinBase()) break case "getIsListening": postData(data._seed, eth.isListening()) break case "getIsMining": postData(data._seed, eth.isMining()) break case "getPeerCount": postData(data._seed, eth.peerCount()) break case "getTxCountAt": require(1) postData(data._seed, eth.txCountAt(data.args[0])) break case "getBlockByNumber": var block = eth.blockByNumber(data.args[0]) postData(data._seed, block) break case "getBlockByHash": var block = eth.blockByHash(data.args[0]) postData(data._seed, block) break case "transact": require(5) var tx = eth.transact(data.args[0], data.args[1], data.args[2],data.args[3],data.args[4],data.args[5]) postData(data._seed, tx) break case "getStorage": require(2); var stateObject = eth.stateObject(data.args[0]) var storage = stateObject.storageAt(data.args[1]) postData(data._seed, storage) break case "getEachStorage": require(1); var storage = JSON.parse(eth.eachStorage(data.args[0])) postData(data._seed, storage) break case "getTransactionsFor": require(1); var txs = eth.transactionsFor(data.args[0], true) postData(data._seed, txs) break case "getBalance": require(1); postData(data._seed, eth.stateObject(data.args[0]).value()); break case "getKey": var key = eth.key().privateKey; postData(data._seed, key) break /* case "watch": require(1) eth.watch(data.args[0], data.args[1]); break */ case "watch": require(2) eth.watch(data.args[0], data.args[1]) case "disconnect": require(1) postData(data._seed, null) break; case "getSecretToAddress": require(1) postData(data._seed, eth.secretToAddress(data.args[0])) break; case "messages": require(1); var messages = JSON.parse(eth.getMessages(data.args[0])) postData(data._seed, messages) break case "mutan": require(1) var code = eth.compileMutan(data.args[0]) postData(data._seed, "0x"+code) break; } } catch(e) { console.log(data.call + ": " + e) postData(data._seed, null); } } function post(seed, data) { console.log("data", data) postData(data._seed, data) } function require(args, num) { if(args.length < num) { throw("required argument count of "+num+" got "+args.length); } } function postData(seed, data) { webview.experimental.postMessage(JSON.stringify({data: data, _seed: seed})) } function postEvent(event, data) { webview.experimental.postMessage(JSON.stringify({data: data, _event: event})) } function onWatchedCb(data, id) { var messages = JSON.parse(data) postEvent("watched:"+id, messages) } function onNewBlockCb(block) { postEvent("block:new", block) } function onObjectChangeCb(stateObject) { postEvent("object:"+stateObject.address(), stateObject) } function onStorageChangeCb(storageObject) { var ev = ["storage", storageObject.stateAddress, storageObject.address].join(":"); postEvent(ev, [storageObject.address, storageObject.value]) } } Rectangle { id: sizeGrip color: "gray" visible: false height: 10 anchors { left: root.left right: root.right } y: Math.round(root.height * 2 / 3) MouseArea { anchors.fill: parent drag.target: sizeGrip drag.minimumY: 0 drag.maximumY: root.height drag.axis: Drag.YAxis } } WebView { id: inspector visible: false anchors { left: root.left right: root.right top: sizeGrip.bottom bottom: root.bottom } } states: [ State { name: "inspectorShown" PropertyChanges { target: inspector } } ] } }