Commit 91ca5d72 authored by obscuren's avatar obscuren

Reworked filters

parent 893e9256
var ethx = {
prototype: Object,
watch: function(options) {
return new Filter(options);
},
note: function() {
var args = Array.prototype.slice.call(arguments, 0);
var o = []
for(var i = 0; i < args.length; i++) {
o.push(args[i].toString())
}
eth.notef(o);
},
};
var Filter = function(options) { var Filter = function(options) {
this.callbacks = {}; this.callbacks = [];
this.seed = Math.floor(Math.random() * 1000000);
this.options = options; this.options = options;
if(options === "chain") { if(options === "chain") {
eth.registerFilterString(options, this.seed); this.id = eth.newFilterString(options);
} else if(typeof options === "object") { } else if(typeof options === "object") {
eth.registerFilter(options, this.seed); this.id = eth.newFilter(options);
} }
}; };
Filter.prototype.changed = function(callback) { Filter.prototype.changed = function(callback) {
var cbseed = Math.floor(Math.random() * 1000000); this.callbacks.push(callback);
eth.registerFilterCallback(this.seed, cbseed);
var self = this; var self = this;
message.connect(function(messages, seed, callbackSeed) { message.connect(function(messages, id) {
if(seed == self.seed && callbackSeed == cbseed) { if(id == self.id) {
callback.call(self, messages); for(var i = 0; i < self.callbacks.length; i++) {
self.callbacks[i].call(self, messages);
}
} }
}); });
}; };
Filter.prototype.uninstall = function() { Filter.prototype.uninstall = function() {
eth.uninstallFilter(this.seed) eth.uninstallFilter(this.id)
} }
Filter.prototype.messages = function() { Filter.prototype.messages = function() {
return JSON.parse(eth.messages(this.options)) return eth.messages(this.id)
} }
...@@ -5,7 +5,6 @@ import QtQuick.Dialogs 1.0; ...@@ -5,7 +5,6 @@ import QtQuick.Dialogs 1.0;
import QtQuick.Window 2.1; import QtQuick.Window 2.1;
import QtQuick.Controls.Styles 1.1 import QtQuick.Controls.Styles 1.1
import Ethereum 1.0 import Ethereum 1.0
import "../../ext/filter.js" as Eth
Rectangle { Rectangle {
id: root id: root
...@@ -152,7 +151,7 @@ Rectangle { ...@@ -152,7 +151,7 @@ Rectangle {
model: ListModel { model: ListModel {
id: txModel id: txModel
Component.onCompleted: { Component.onCompleted: {
var filter = new Eth.Filter({latest: -1, from: eth.key().address}) var filter = ethx.watch({latest: -1, from: eth.key().address});
filter.changed(addTxs) filter.changed(addTxs)
addTxs(filter.messages()) addTxs(filter.messages())
...@@ -160,7 +159,7 @@ Rectangle { ...@@ -160,7 +159,7 @@ Rectangle {
function addTxs(messages) { function addTxs(messages) {
for(var i = 0; i < messages.length; i++) { for(var i = 0; i < messages.length; i++) {
var message = messages[i]; var message = messages.get(i);
txModel.insert(0, {num: txModel.count, from: message.from, to: message.to, value: eth.numberToHuman(message.value)}) txModel.insert(0, {num: txModel.count, from: message.from, to: message.to, value: eth.numberToHuman(message.value)})
} }
} }
......
...@@ -9,747 +9,748 @@ import Ethereum 1.0 ...@@ -9,747 +9,748 @@ import Ethereum 1.0
import "../ext/filter.js" as Eth import "../ext/filter.js" as Eth
ApplicationWindow { ApplicationWindow {
id: root id: root
property alias miningButtonText: miningButton.text property alias miningButtonText: miningButton.text
property var ethx : Eth.ethx
width: 900 width: 900
height: 600 height: 600
minimumHeight: 300 minimumHeight: 300
title: "Ethegate" title: "Ether Browser"
// This signal is used by the filter API. The filter API connects using this signal handler from // This signal is used by the filter API. The filter API connects using this signal handler from
// the different QML files and plugins. // the different QML files and plugins.
signal message(var callback, int seed, int seedCallback); signal message(var callback, int seed);
function invokeFilterCallback(data, receiverSeed, callbackSeed) { function invokeFilterCallback(data, receiverSeed) {
var messages = JSON.parse(data) //var messages = JSON.parse(data)
// Signal handler // Signal handler
message(messages, receiverSeed, callbackSeed); message(data, receiverSeed);
} }
TextField { TextField {
id: copyElementHax id: copyElementHax
visible: false visible: false
} }
function copyToClipboard(text) { function copyToClipboard(text) {
copyElementHax.text = text copyElementHax.text = text
copyElementHax.selectAll() copyElementHax.selectAll()
copyElementHax.copy() copyElementHax.copy()
} }
// Takes care of loading all default plugins // Takes care of loading all default plugins
Component.onCompleted: { Component.onCompleted: {
var walletView = addPlugin("./views/wallet.qml", {noAdd: true, section: "ethereum", active: true}) addPlugin("./views/wallet.qml", {noAdd: true, section: "ethereum", active: true});
var newTxView = addPlugin("./views/transaction.qml", {noAdd: true, section: "legacy"})
var chainView = addPlugin("./views/chain.qml", {noAdd: true, section: "legacy"}) addPlugin("./views/transaction.qml", {noAdd: true, section: "legacy"});
var infoView = addPlugin("./views/info.qml", {noAdd: true, section: "legacy"}) addPlugin("./views/chain.qml", {noAdd: true, section: "legacy"});
var pendingTxView = addPlugin("./views/pending_tx.qml", {noAdd: true, section: "legacy"}) addPlugin("./views/info.qml", {noAdd: true, section: "legacy"});
var pendingTxView = addPlugin("./views/javascript.qml", {noAdd: true, section: "legacy"}) addPlugin("./views/pending_tx.qml", {noAdd: true, section: "legacy"});
addPlugin("./views/javascript.qml", {noAdd: true, section: "legacy"});
// Call the ready handler
gui.done() // Call the ready handler
gui.done();
} }
function addPlugin(path, options) { function addPlugin(path, options) {
try { try {
var component = Qt.createComponent(path); var component = Qt.createComponent(path);
if(component.status != Component.Ready) { if(component.status != Component.Ready) {
if(component.status == Component.Error) { if(component.status == Component.Error) {
console.debug("Error:"+ component.errorString()); ethx.note("error: ", component.errorString());
} }
return return
} }
var views = mainSplit.addComponent(component, options) var views = mainSplit.addComponent(component, options)
views.menuItem.path = path views.menuItem.path = path
mainSplit.views.push(views); mainSplit.views.push(views);
if(!options.noAdd) { if(!options.noAdd) {
gui.addPlugin(path) gui.addPlugin(path)
} }
return views.view return views.view
} catch(e) { } catch(e) {
} eth.note(e)
} }
}
MenuBar {
Menu { MenuBar {
title: "File" Menu {
MenuItem { title: "File"
text: "Import App" MenuItem {
shortcut: "Ctrl+o" text: "Import App"
onTriggered: { shortcut: "Ctrl+o"
generalFileDialog.show(true, importApp) onTriggered: {
} generalFileDialog.show(true, importApp)
} }
}
MenuItem {
text: "Browser" MenuItem {
onTriggered: eth.openBrowser() text: "Browser"
} onTriggered: eth.openBrowser()
}
MenuItem {
text: "Add plugin" MenuItem {
onTriggered: { text: "Add plugin"
generalFileDialog.show(true, function(path) { onTriggered: {
addPlugin(path, {canClose: true, section: "apps"}) generalFileDialog.show(true, function(path) {
}) addPlugin(path, {canClose: true, section: "apps"})
} })
} }
}
MenuSeparator {}
MenuSeparator {}
MenuItem {
text: "Import key" MenuItem {
shortcut: "Ctrl+i" text: "Import key"
onTriggered: { shortcut: "Ctrl+i"
generalFileDialog.show(true, function(path) { onTriggered: {
gui.importKey(path) generalFileDialog.show(true, function(path) {
}) gui.importKey(path)
} })
} }
}
MenuItem {
text: "Export keys" MenuItem {
shortcut: "Ctrl+e" text: "Export keys"
onTriggered: { shortcut: "Ctrl+e"
generalFileDialog.show(false, function(path) { onTriggered: {
}) generalFileDialog.show(false, function(path) {
} })
} }
} }
}
Menu {
title: "Developer" Menu {
MenuItem { title: "Developer"
text: "Debugger" MenuItem {
shortcut: "Ctrl+d" text: "Debugger"
onTriggered: eth.startDebugger() shortcut: "Ctrl+d"
} onTriggered: eth.startDebugger()
}
MenuItem {
text: "Import Tx" MenuItem {
onTriggered: { text: "Import Tx"
txImportDialog.visible = true onTriggered: {
} txImportDialog.visible = true
} }
}
MenuItem {
text: "Run JS file" MenuItem {
onTriggered: { text: "Run JS file"
generalFileDialog.show(true, function(path) { onTriggered: {
eth.evalJavascriptFile(path) generalFileDialog.show(true, function(path) {
}) eth.evalJavascriptFile(path)
} })
} }
}
MenuItem {
text: "Dump state" MenuItem {
onTriggered: { text: "Dump state"
generalFileDialog.show(false, function(path) { onTriggered: {
// Empty hash for latest generalFileDialog.show(false, function(path) {
gui.dumpState("", path) // Empty hash for latest
}) gui.dumpState("", path)
} })
} }
}
MenuSeparator {}
MenuSeparator {}
MenuItem {
id: miningSpeed MenuItem {
text: "Mining: Turbo" id: miningSpeed
onTriggered: { text: "Mining: Turbo"
gui.toggleTurboMining() onTriggered: {
if(text == "Mining: Turbo") { gui.toggleTurboMining()
text = "Mining: Normal"; if(text == "Mining: Turbo") {
} else { text = "Mining: Normal";
text = "Mining: Turbo"; } else {
} text = "Mining: Turbo";
} }
} }
} }
}
Menu {
title: "Network" Menu {
MenuItem { title: "Network"
text: "Add Peer" MenuItem {
shortcut: "Ctrl+p" text: "Add Peer"
onTriggered: { shortcut: "Ctrl+p"
addPeerWin.visible = true onTriggered: {
} addPeerWin.visible = true
} }
MenuItem { }
text: "Show Peers" MenuItem {
shortcut: "Ctrl+e" text: "Show Peers"
onTriggered: { shortcut: "Ctrl+e"
peerWindow.visible = true onTriggered: {
} peerWindow.visible = true
} }
} }
}
Menu {
title: "Help" Menu {
MenuItem { title: "Help"
text: "About" MenuItem {
onTriggered: { text: "About"
aboutWin.visible = true onTriggered: {
} aboutWin.visible = true
} }
} }
}
}
}
statusBar: StatusBar {
height: 32 statusBar: StatusBar {
RowLayout { height: 32
Button { RowLayout {
id: miningButton Button {
text: "Start Mining" id: miningButton
onClicked: { text: "Start Mining"
gui.toggleMining() onClicked: {
} gui.toggleMining()
} }
}
Button {
id: importAppButton Button {
text: "Browser" id: importAppButton
onClicked: { text: "Browser"
eth.openBrowser() onClicked: {
} eth.openBrowser()
} }
}
RowLayout {
Label { RowLayout {
id: walletValueLabel Label {
id: walletValueLabel
font.pixelSize: 10
styleColor: "#797979" font.pixelSize: 10
} styleColor: "#797979"
} }
} }
}
Label {
y: 6 Label {
objectName: "miningLabel" y: 6
visible: true objectName: "miningLabel"
font.pixelSize: 10 visible: true
anchors.right: lastBlockLabel.left font.pixelSize: 10
anchors.rightMargin: 5 anchors.right: lastBlockLabel.left
} anchors.rightMargin: 5
}
Label {
y: 6 Label {
id: lastBlockLabel y: 6
objectName: "lastBlockLabel" id: lastBlockLabel
visible: true objectName: "lastBlockLabel"
text: "" visible: true
font.pixelSize: 10 text: ""
anchors.right: peerGroup.left font.pixelSize: 10
anchors.rightMargin: 5 anchors.right: peerGroup.left
} anchors.rightMargin: 5
}
ProgressBar {
id: syncProgressIndicator ProgressBar {
visible: false id: syncProgressIndicator
objectName: "syncProgressIndicator" visible: false
y: 3 objectName: "syncProgressIndicator"
width: 140 y: 3
indeterminate: true width: 140
anchors.right: peerGroup.left indeterminate: true
anchors.rightMargin: 5 anchors.right: peerGroup.left
} anchors.rightMargin: 5
}
RowLayout {
id: peerGroup RowLayout {
y: 7 id: peerGroup
anchors.right: parent.right y: 7
MouseArea { anchors.right: parent.right
onDoubleClicked: peerWindow.visible = true MouseArea {
anchors.fill: parent onDoubleClicked: peerWindow.visible = true
} anchors.fill: parent
}
Label {
id: peerLabel Label {
font.pixelSize: 8 id: peerLabel
text: "0 / 0" font.pixelSize: 8
} text: "0 / 0"
Image { }
id: peerImage Image {
width: 10; height: 10 id: peerImage
source: "../network.png" width: 10; height: 10
} source: "../network.png"
} }
} }
}
property var blockModel: ListModel {
id: blockModel property var blockModel: ListModel {
} id: blockModel
}
SplitView {
property var views: []; SplitView {
property var views: [];
id: mainSplit
anchors.fill: parent id: mainSplit
resizing: false anchors.fill: parent
resizing: false
function setView(view, menu) {
for(var i = 0; i < views.length; i++) { function setView(view, menu) {
views[i].view.visible = false for(var i = 0; i < views.length; i++) {
views[i].view.visible = false
views[i].menuItem.border.color = "#00000000"
views[i].menuItem.color = "#00000000" views[i].menuItem.border.color = "#00000000"
} views[i].menuItem.color = "#00000000"
view.visible = true }
view.visible = true
menu.border.color = "#CCCCCC"
menu.color = "#FFFFFFFF" menu.border.color = "#CCCCCC"
} menu.color = "#FFFFFFFF"
}
function addComponent(component, options) {
var view = mainView.createView(component, options) function addComponent(component, options) {
view.visible = false var view = mainView.createView(component, options)
view.anchors.fill = mainView view.visible = false
view.anchors.fill = mainView
if( !view.hasOwnProperty("iconSource") ) {
console.log("Could not load plugin. Property 'iconSourc' not found on view."); if( !view.hasOwnProperty("iconSource") ) {
return; console.log("Could not load plugin. Property 'iconSourc' not found on view.");
} return;
}
var menuItem = menu.createMenuItem(view.iconSource, view, options);
if( view.hasOwnProperty("menuItem") ) { var menuItem = menu.createMenuItem(view.iconSource, view, options);
view.menuItem = menuItem; if( view.hasOwnProperty("menuItem") ) {
} view.menuItem = menuItem;
}
if( view.hasOwnProperty("onReady") ) {
view.onReady.call(view) if( view.hasOwnProperty("onReady") ) {
} view.onReady.call(view)
}
if( options.active ) {
setView(view, menuItem) if( options.active ) {
} setView(view, menuItem)
}
return {view: view, menuItem: menuItem}
} return {view: view, menuItem: menuItem}
}
/*********************
* Main menu. /*********************
********************/ * Main menu.
Rectangle { ********************/
id: menu Rectangle {
Layout.minimumWidth: 180 id: menu
Layout.maximumWidth: 180 Layout.minimumWidth: 180
anchors.top: parent.top Layout.maximumWidth: 180
color: "#ececec" anchors.top: parent.top
color: "#ececec"
Component {
id: menuItemTemplate Component {
Rectangle { id: menuItemTemplate
id: menuItem Rectangle {
property var view; id: menuItem
property var path; property var view;
property var path;
property alias title: label.text
property alias icon: icon.source property alias title: label.text
property alias secondaryTitle: secondary.text property alias icon: icon.source
property alias secondaryTitle: secondary.text
width: 180
height: 28 width: 180
border.color: "#00000000" height: 28
border.width: 1 border.color: "#00000000"
radius: 5 border.width: 1
color: "#00000000" radius: 5
color: "#00000000"
anchors {
left: parent.left anchors {
leftMargin: 4 left: parent.left
} leftMargin: 4
}
MouseArea {
anchors.fill: parent MouseArea {
onClicked: { anchors.fill: parent
mainSplit.setView(view, menuItem) onClicked: {
} mainSplit.setView(view, menuItem)
} }
}
Image {
id: icon Image {
height: 20 id: icon
width: 20 height: 20
anchors { width: 20
left: parent.left anchors {
verticalCenter: parent.verticalCenter left: parent.left
leftMargin: 3 verticalCenter: parent.verticalCenter
} leftMargin: 3
MouseArea { }
anchors.fill: parent MouseArea {
onClicked: { anchors.fill: parent
menuItem.closeApp() onClicked: {
} menuItem.closeApp()
} }
} }
}
Text {
id: label Text {
anchors { id: label
left: icon.right anchors {
verticalCenter: parent.verticalCenter left: icon.right
leftMargin: 3 verticalCenter: parent.verticalCenter
} leftMargin: 3
}
color: "#0D0A01"
font.pixelSize: 12 color: "#0D0A01"
} font.pixelSize: 12
}
Text {
id: secondary Text {
anchors { id: secondary
right: parent.right anchors {
rightMargin: 8 right: parent.right
verticalCenter: parent.verticalCenter rightMargin: 8
} verticalCenter: parent.verticalCenter
color: "#AEADBE" }
font.pixelSize: 12 color: "#AEADBE"
} font.pixelSize: 12
}
function closeApp() {
if(this.view.hasOwnProperty("onDestroy")) { function closeApp() {
this.view.onDestroy.call(this.view) if(this.view.hasOwnProperty("onDestroy")) {
} this.view.onDestroy.call(this.view)
}
this.view.destroy()
this.destroy() this.view.destroy()
gui.removePlugin(this.path) this.destroy()
} gui.removePlugin(this.path)
} }
} }
}
function createMenuItem(icon, view, options) {
if(options === undefined) { function createMenuItem(icon, view, options) {
options = {}; if(options === undefined) {
} options = {};
}
var section;
switch(options.section) { var section;
case "ethereum": switch(options.section) {
section = menuDefault; case "ethereum":
break; section = menuDefault;
case "legacy": break;
section = menuLegacy; case "legacy":
break; section = menuLegacy;
default: break;
section = menuApps; default:
break; section = menuApps;
} break;
}
var comp = menuItemTemplate.createObject(section)
var comp = menuItemTemplate.createObject(section)
comp.view = view
comp.title = view.title comp.view = view
comp.icon = view.iconSource comp.title = view.title
/* comp.icon = view.iconSource
if(view.secondary !== undefined) { /*
comp.secondary = view.secondary if(view.secondary !== undefined) {
} comp.secondary = view.secondary
*/ }
*/
return comp
return comp
/*
if(options.canClose) { /*
//comp.closeButton.visible = options.canClose if(options.canClose) {
} //comp.closeButton.visible = options.canClose
*/ }
} */
}
ColumnLayout {
id: menuColumn ColumnLayout {
y: 10 id: menuColumn
width: parent.width y: 10
anchors.left: parent.left width: parent.width
anchors.right: parent.right anchors.left: parent.left
spacing: 3 anchors.right: parent.right
spacing: 3
Text {
text: "ETHEREUM" Text {
font.bold: true text: "ETHEREUM"
anchors { font.bold: true
left: parent.left anchors {
leftMargin: 5 left: parent.left
} leftMargin: 5
color: "#888888" }
} color: "#888888"
}
ColumnLayout {
id: menuDefault ColumnLayout {
spacing: 3 id: menuDefault
anchors { spacing: 3
left: parent.left anchors {
right: parent.right left: parent.left
} right: parent.right
} }
}
Text {
text: "APPS" Text {
font.bold: true text: "APPS"
anchors { font.bold: true
left: parent.left anchors {
leftMargin: 5 left: parent.left
} leftMargin: 5
color: "#888888" }
} color: "#888888"
}
ColumnLayout {
id: menuApps ColumnLayout {
spacing: 3 id: menuApps
anchors { spacing: 3
left: parent.left anchors {
right: parent.right left: parent.left
} right: parent.right
} }
}
Text {
text: "DEBUG" Text {
font.bold: true text: "DEBUG"
anchors { font.bold: true
left: parent.left anchors {
leftMargin: 5 left: parent.left
} leftMargin: 5
color: "#888888" }
} color: "#888888"
}
ColumnLayout {
id: menuLegacy ColumnLayout {
spacing: 3 id: menuLegacy
anchors { spacing: 3
left: parent.left anchors {
right: parent.right left: parent.left
} right: parent.right
} }
} }
} }
}
/*********************
* Main view /*********************
********************/ * Main view
Rectangle { ********************/
id: mainView Rectangle {
color: "#00000000" id: mainView
color: "#00000000"
anchors.right: parent.right
anchors.left: menu.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.left: menu.right
anchors.top: parent.top anchors.bottom: parent.bottom
anchors.top: parent.top
function createView(component) {
var view = component.createObject(mainView) function createView(component) {
var view = component.createObject(mainView)
return view;
} return view;
} }
}
}
}
/******************
* Dialogs /******************
*****************/ * Dialogs
FileDialog { *****************/
id: generalFileDialog FileDialog {
property var callback; id: generalFileDialog
onAccepted: { property var callback;
var path = this.fileUrl.toString(); onAccepted: {
callback.call(this, path); var path = this.fileUrl.toString();
} callback.call(this, path);
}
function show(selectExisting, callback) {
generalFileDialog.callback = callback; function show(selectExisting, callback) {
generalFileDialog.selectExisting = selectExisting; generalFileDialog.callback = callback;
generalFileDialog.selectExisting = selectExisting;
this.open();
} this.open();
} }
}
/******************
* Wallet functions /******************
*****************/ * Wallet functions
function importApp(path) { *****************/
var ext = path.split('.').pop() function importApp(path) {
if(ext == "html" || ext == "htm") { var ext = path.split('.').pop()
eth.openHtml(path) if(ext == "html" || ext == "htm") {
}else if(ext == "qml"){ eth.openHtml(path)
addPlugin(path, {canClose: true, section: "apps"}) }else if(ext == "qml"){
} addPlugin(path, {canClose: true, section: "apps"})
} }
}
function setWalletValue(value) {
walletValueLabel.text = value function setWalletValue(value) {
} walletValueLabel.text = value
}
function loadPlugin(name) {
console.log("Loading plugin" + name) function loadPlugin(name) {
var view = mainView.addPlugin(name) console.log("Loading plugin" + name)
} var view = mainView.addPlugin(name)
}
function setPeers(text) {
peerLabel.text = text 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 function addPeer(peer) {
peerModel.append({ip: peer.ip, port: peer.port, lastResponse:timeAgo(peer.lastSend), latency: peer.latency, version: peer.version}) // 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 resetPeers(){
} peerModel.clear()
}
function timeAgo(unixTs){
var lapsed = (Date.now() - new Date(unixTs*1000)) / 1000 function timeAgo(unixTs){
return (lapsed + " seconds ago") var lapsed = (Date.now() - new Date(unixTs*1000)) / 1000
} return (lapsed + " seconds ago")
}
function convertToPretty(unixTs){
var a = new Date(unixTs*1000); function convertToPretty(unixTs){
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; var a = new Date(unixTs*1000);
var year = a.getFullYear(); var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var month = months[a.getMonth()]; var year = a.getFullYear();
var date = a.getDate(); var month = months[a.getMonth()];
var hour = a.getHours(); var date = a.getDate();
var min = a.getMinutes(); var hour = a.getHours();
var sec = a.getSeconds(); var min = a.getMinutes();
var time = date+' '+month+' '+year+' '+hour+':'+min+':'+sec ; var sec = a.getSeconds();
return time; var time = date+' '+month+' '+year+' '+hour+':'+min+':'+sec ;
} return time;
}
/**********************
* Windows /**********************
*********************/ * Windows
Window { *********************/
id: peerWindow Window {
//flags: Qt.CustomizeWindowHint | Qt.Tool | Qt.WindowCloseButtonHint id: peerWindow
height: 200 //flags: Qt.CustomizeWindowHint | Qt.Tool | Qt.WindowCloseButtonHint
width: 700 height: 200
Rectangle { width: 700
anchors.fill: parent Rectangle {
property var peerModel: ListModel { anchors.fill: parent
id: peerModel property var peerModel: ListModel {
} id: peerModel
TableView { }
anchors.fill: parent TableView {
id: peerTable anchors.fill: parent
model: peerModel id: peerTable
TableViewColumn{width: 100; role: "ip" ; title: "IP" } model: peerModel
TableViewColumn{width: 60; role: "port" ; title: "Port" } TableViewColumn{width: 100; role: "ip" ; title: "IP" }
TableViewColumn{width: 140; role: "lastResponse"; title: "Last event" } TableViewColumn{width: 60; role: "port" ; title: "Port" }
TableViewColumn{width: 100; role: "latency"; title: "Latency" } TableViewColumn{width: 140; role: "lastResponse"; title: "Last event" }
TableViewColumn{width: 260; role: "version" ; title: "Version" } TableViewColumn{width: 100; role: "latency"; title: "Latency" }
} TableViewColumn{width: 260; role: "version" ; title: "Version" }
} }
} }
}
Window {
id: aboutWin Window {
visible: false id: aboutWin
title: "About" visible: false
minimumWidth: 350 title: "About"
maximumWidth: 350 minimumWidth: 350
maximumHeight: 200 maximumWidth: 350
minimumHeight: 200 maximumHeight: 200
minimumHeight: 200
Image {
id: aboutIcon Image {
height: 150 id: aboutIcon
width: 150 height: 150
fillMode: Image.PreserveAspectFit width: 150
smooth: true fillMode: Image.PreserveAspectFit
source: "../facet.png" smooth: true
x: 10 source: "../facet.png"
y: 10 x: 10
} y: 10
}
Text {
anchors.left: aboutIcon.right Text {
anchors.leftMargin: 10 anchors.left: aboutIcon.right
font.pointSize: 12 anchors.leftMargin: 10
text: "<h2>Ethereal - Aitne</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Maran Hidskes<br>Viktor Trón<br>" font.pointSize: 12
} text: "<h2>Ethereal - Aitne</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Maran Hidskes<br>Viktor Trón<br>"
} }
}
Window {
id: txImportDialog Window {
minimumWidth: 270 id: txImportDialog
maximumWidth: 270 minimumWidth: 270
maximumHeight: 50 maximumWidth: 270
minimumHeight: 50 maximumHeight: 50
TextField { minimumHeight: 50
id: txImportField TextField {
width: 170 id: txImportField
anchors.verticalCenter: parent.verticalCenter width: 170
anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 10 anchors.left: parent.left
onAccepted: { anchors.leftMargin: 10
} onAccepted: {
} }
Button { }
anchors.left: txImportField.right Button {
anchors.verticalCenter: parent.verticalCenter anchors.left: txImportField.right
anchors.leftMargin: 5 anchors.verticalCenter: parent.verticalCenter
text: "Import" anchors.leftMargin: 5
onClicked: { text: "Import"
eth.importTx(txImportField.text) onClicked: {
txImportField.visible = false eth.importTx(txImportField.text)
} txImportField.visible = false
} }
Component.onCompleted: { }
addrField.focus = true Component.onCompleted: {
} addrField.focus = true
} }
}
Window {
id: addPeerWin Window {
visible: false id: addPeerWin
minimumWidth: 230 visible: false
maximumWidth: 230 minimumWidth: 230
maximumHeight: 50 maximumWidth: 230
minimumHeight: 50 maximumHeight: 50
minimumHeight: 50
TextField {
id: addrField TextField {
anchors.verticalCenter: parent.verticalCenter id: addrField
anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 10 anchors.left: parent.left
placeholderText: "address:port" anchors.leftMargin: 10
onAccepted: { placeholderText: "address:port"
eth.connectToPeer(addrField.text) onAccepted: {
addPeerWin.visible = false eth.connectToPeer(addrField.text)
} addPeerWin.visible = false
} }
Button { }
anchors.left: addrField.right Button {
anchors.verticalCenter: parent.verticalCenter anchors.left: addrField.right
anchors.leftMargin: 5 anchors.verticalCenter: parent.verticalCenter
text: "Add" anchors.leftMargin: 5
onClicked: { text: "Add"
eth.connectToPeer(addrField.text) onClicked: {
addPeerWin.visible = false eth.connectToPeer(addrField.text)
} addPeerWin.visible = false
} }
Component.onCompleted: { }
addrField.focus = true Component.onCompleted: {
} addrField.focus = true
} }
}
} }
package main package main
// #include "/Users/jeffrey/go/src/github.com/go-qml/qml/cpp/capi.h"
import "C"
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
...@@ -10,7 +13,9 @@ import ( ...@@ -10,7 +13,9 @@ import (
"strconv" "strconv"
"strings" "strings"
"time" "time"
"unsafe"
"bitbucket.org/binet/go-ffi/pkg/ffi"
"github.com/ethereum/eth-go" "github.com/ethereum/eth-go"
"github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethdb" "github.com/ethereum/eth-go/ethdb"
...@@ -23,6 +28,29 @@ import ( ...@@ -23,6 +28,29 @@ import (
"gopkg.in/qml.v1" "gopkg.in/qml.v1"
) )
func LoadExtension(path string) (uintptr, error) {
lib, err := ffi.NewLibrary(path)
if err != nil {
return 0, err
}
so, err := lib.Fct("sharedObject", ffi.Pointer, nil)
if err != nil {
return 0, err
}
ptr := so()
/*
err = lib.Close()
if err != nil {
return 0, err
}
*/
return ptr.Interface().(uintptr), nil
}
var logger = ethlog.NewLogger("GUI") var logger = ethlog.NewLogger("GUI")
type Gui struct { type Gui struct {
...@@ -91,6 +119,14 @@ func (gui *Gui) Start(assetPath string) { ...@@ -91,6 +119,14 @@ func (gui *Gui) Start(assetPath string) {
context.SetVar("gui", gui) context.SetVar("gui", gui)
context.SetVar("eth", gui.uiLib) context.SetVar("eth", gui.uiLib)
vec, errr := LoadExtension("/Users/jeffrey/Desktop/build-libqmltest-Desktop_Qt_5_2_1_clang_64bit-Debug/liblibqmltest_debug.dylib")
fmt.Printf("Fetched vec with addr: %#x\n", vec)
if errr != nil {
fmt.Println(errr)
} else {
context.SetVar("vec", (unsafe.Pointer)(vec))
}
// Load the main QML interface // Load the main QML interface
data, _ := ethutil.Config.Db.Get([]byte("KeyRing")) data, _ := ethutil.Config.Db.Get([]byte("KeyRing"))
......
...@@ -37,15 +37,15 @@ type UiLib struct { ...@@ -37,15 +37,15 @@ type UiLib struct {
jsEngine *javascript.JSRE jsEngine *javascript.JSRE
filterCallbacks map[int][]int filterCallbacks map[int][]int
filters map[int]*GuiFilter //filters map[int]*ethpipe.JSFilter
} }
func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib { func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib {
return &UiLib{JSPipe: ethpipe.NewJSPipe(eth), engine: engine, eth: eth, assetPath: assetPath, jsEngine: javascript.NewJSRE(eth), filterCallbacks: make(map[int][]int), filters: make(map[int]*GuiFilter)} return &UiLib{JSPipe: ethpipe.NewJSPipe(eth), engine: engine, eth: eth, assetPath: assetPath, jsEngine: javascript.NewJSRE(eth), filterCallbacks: make(map[int][]int)} //, filters: make(map[int]*ethpipe.JSFilter)}
} }
func (self *UiLib) Note(msg string) { func (self *UiLib) Notef(args []interface{}) {
logger.Infoln(msg) logger.Infoln(args...)
} }
func (self *UiLib) LookupDomain(domain string) string { func (self *UiLib) LookupDomain(domain string) string {
...@@ -164,46 +164,37 @@ func (self *UiLib) StartDebugger() { ...@@ -164,46 +164,37 @@ func (self *UiLib) StartDebugger() {
dbWindow.Show() dbWindow.Show()
} }
func (self *UiLib) RegisterFilter(object map[string]interface{}, seed int) { func (self *UiLib) NewFilter(object map[string]interface{}) int {
filter := &GuiFilter{ethpipe.NewJSFilterFromMap(object, self.eth), seed} filter, id := self.eth.InstallFilter(object)
self.filters[seed] = filter
filter.MessageCallback = func(messages ethstate.Messages) { filter.MessageCallback = func(messages ethstate.Messages) {
for _, callbackSeed := range self.filterCallbacks[seed] { self.win.Root().Call("invokeFilterCallback", ethpipe.ToJSMessages(messages), id)
self.win.Root().Call("invokeFilterCallback", filter.MessagesToJson(messages), seed, callbackSeed)
}
} }
return id
} }
func (self *UiLib) RegisterFilterString(typ string, seed int) { func (self *UiLib) NewFilterString(typ string) int {
filter := &GuiFilter{ethpipe.NewJSFilterFromMap(nil, self.eth), seed} filter, id := self.eth.InstallFilter(nil)
self.filters[seed] = filter filter.BlockCallback = func(block *ethchain.Block) {
self.win.Root().Call("invokeFilterCallback", "{}", id)
if typ == "chain" {
filter.BlockCallback = func(block *ethchain.Block) {
for _, callbackSeed := range self.filterCallbacks[seed] {
self.win.Root().Call("invokeFilterCallback", "{}", seed, callbackSeed)
}
}
} }
}
func (self *UiLib) RegisterFilterCallback(seed, cbSeed int) { return id
self.filterCallbacks[seed] = append(self.filterCallbacks[seed], cbSeed)
} }
func (self *UiLib) UninstallFilter(seed int) { func (self *UiLib) Messages(id int) *ethutil.List {
filter := self.filters[seed] filter := self.eth.GetFilter(id)
if filter != nil { if filter != nil {
filter.Uninstall() messages := filter.Find()
delete(self.filters, seed)
return ethpipe.ToJSMessages(messages)
} }
return ethutil.EmptyList()
} }
type GuiFilter struct { func (self *UiLib) UninstallFilter(id int) {
*ethpipe.JSFilter self.eth.UninstallFilter(id)
seed int
} }
func (self *UiLib) Transact(object map[string]interface{}) (*ethpipe.JSReceipt, error) { func (self *UiLib) Transact(object map[string]interface{}) (*ethpipe.JSReceipt, error) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment