github.com/jonasnick/go-ethereum@v0.7.12-0.20150216215225-22176f05d387/cmd/mist/assets/qml/main.qml (about)

     1  import QtQuick 2.0
     2  import QtQuick.Controls 1.0;
     3  import QtQuick.Layouts 1.0;
     4  import QtQuick.Dialogs 1.0;
     5  import QtQuick.Window 2.1;
     6  import QtQuick.Controls.Styles 1.1
     7  import Ethereum 1.0
     8  
     9  import "../ext/filter.js" as Eth
    10  import "../ext/http.js" as Http
    11  
    12  
    13  ApplicationWindow {
    14      id: root
    15      
    16      //flags: Qt.FramelessWindowHint
    17      // Use this to make the window frameless. But then you'll need to do move and resize by hand
    18  
    19      property var ethx : Eth.ethx
    20      property var catalog;
    21  
    22      width: 1200
    23      height: 820
    24      minimumHeight: 600
    25      minimumWidth: 800
    26  
    27      title: "Mist"
    28  
    29      TextField {
    30          id: copyElementHax
    31          visible: false
    32      }
    33  
    34      function copyToClipboard(text) {
    35          copyElementHax.text = text
    36          copyElementHax.selectAll()
    37          copyElementHax.copy()
    38      }
    39  
    40      // Takes care of loading all default plugins
    41      Component.onCompleted: {
    42  
    43          catalog = addPlugin("./views/catalog.qml", {noAdd: true, close: false, section: "begin"});
    44          var wallet = addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "ethereum", active: true});
    45  
    46          addPlugin("./views/miner.qml", {noAdd: true, close: false, section: "ethereum", active: true});
    47          addPlugin("./views/transaction.qml", {noAdd: true, close: false, section: "legacy"});
    48          addPlugin("./views/whisper.qml", {noAdd: true, close: false, section: "legacy"});
    49          addPlugin("./views/chain.qml", {noAdd: true, close: false, section: "legacy"});
    50          addPlugin("./views/pending_tx.qml", {noAdd: true, close: false, section: "legacy"});
    51          addPlugin("./views/info.qml", {noAdd: true, close: false, section: "legacy"});
    52  
    53          mainSplit.setView(catalog.view, catalog.menuItem);
    54  
    55          //newBrowserTab("http://ethereum-dapp-catalog.meteor.com");
    56  
    57          // Command setup
    58          gui.sendCommand(0)
    59      }
    60  
    61      function activeView(view, menuItem) {
    62          mainSplit.setView(view, menuItem)
    63          if (view.hideUrl) {
    64              //urlPane.visible = false;
    65              //mainView.anchors.top = rootView.top
    66          } else {
    67              //urlPane.visible = true;
    68              //mainView.anchors.top = divider.bottom
    69          }
    70      }
    71  
    72      function addViews(view, path, options) {
    73          var views = mainSplit.addComponent(view, options)
    74          views.menuItem.path = path
    75  
    76          mainSplit.views.push(views);
    77  
    78          if(!options.noAdd) {
    79              gui.addPlugin(path)
    80          }
    81  
    82          return views
    83      }
    84  
    85      function addPlugin(path, options) {
    86          try {
    87              if(typeof(path) === "string" && /^https?/.test(path)) {
    88                  console.log('load http')
    89                  Http.request(path, function(o) {
    90                      if(o.status === 200) {
    91                          var view = Qt.createQmlObject(o.responseText, mainView, path)
    92                          addViews(view, path, options)
    93                      }
    94                  })
    95  
    96                  return
    97              }
    98  
    99              var component = Qt.createComponent(path);
   100              if(component.status != Component.Ready) {
   101                  if(component.status == Component.Error) {
   102                      ethx.note("error: ", component.errorString());
   103                  }
   104  
   105                  return
   106              }
   107  
   108              var view = mainView.createView(component, options)
   109              var views = addViews(view, path, options)
   110  
   111              return views
   112          } catch(e) {
   113              console.log(e)
   114          }
   115      }
   116  
   117      function newBrowserTab(url) {
   118          
   119          var urlMatches = url.toString().match(/^[a-z]*\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
   120          var requestedDomain = urlMatches && urlMatches[1];
   121  
   122          var domainAlreadyOpen = false;
   123  
   124          console.log("requested: " + requestedDomain )
   125  
   126          for(var i = 0; i < mainSplit.views.length; i++) {
   127              if (mainSplit.views[i].view.url) {
   128                  var matches = mainSplit.views[i].view.url.toString().match(/^[a-z]*\:\/\/(?:www\.)?([^\/?#]+)(?:[\/?#]|$)/i);
   129                  var existingDomain = matches && matches[1];
   130                  console.log("exists: " + existingDomain);
   131                  if (requestedDomain == existingDomain) {
   132                      domainAlreadyOpen = true;
   133                      mainSplit.views[i].view.url = url;
   134                      activeView(mainSplit.views[i].view, mainSplit.views[i].menuItem);
   135                  }
   136              }
   137          }  
   138  
   139          if (!domainAlreadyOpen) {            
   140              var window = addPlugin("./views/browser.qml", {noAdd: true, close: true, section: "apps", active: true});
   141              window.view.url = url;
   142              window.menuItem.title = "Mist";
   143              activeView(window.view, window.menuItem);
   144          }
   145      }
   146  
   147  
   148  
   149      menuBar: MenuBar {
   150          Menu {
   151              title: "File"
   152              MenuItem {
   153                  text: "New tab"
   154                  shortcut: "Ctrl+t"
   155                  onTriggered: {
   156  	            activeView(catalog.view, catalog.menuItem);
   157                  }
   158              }
   159  
   160              MenuSeparator {}
   161  
   162              MenuItem {
   163                  text: "Import key"
   164                  shortcut: "Ctrl+i"
   165                  onTriggered: {
   166                      generalFileDialog.show(true, function(path) {
   167                          gui.importKey(path)
   168                      })
   169                  }
   170              }
   171  
   172              MenuItem {
   173                  text: "Export keys"
   174                  shortcut: "Ctrl+e"
   175                  onTriggered: {
   176                      generalFileDialog.show(false, function(path) {
   177                      })
   178                  }
   179              }
   180  
   181          }
   182  
   183          Menu {
   184              title: "Developer"
   185              MenuItem {
   186                  iconSource: "../icecream.png"
   187                  text: "Debugger"
   188                  shortcut: "Ctrl+d"
   189                  onTriggered: eth.startDebugger()
   190              }
   191  
   192              MenuItem {
   193                  text: "Import Tx"
   194                  onTriggered: {
   195                      txImportDialog.visible = true
   196                  }
   197              }
   198  
   199              MenuItem {
   200                  text: "Run JS file"
   201                  onTriggered: {
   202                      generalFileDialog.show(true, function(path) {
   203                          eth.evalJavascriptFile(path)
   204                      })
   205                  }
   206              }
   207  
   208              MenuItem {
   209                  text: "Dump state"
   210                  onTriggered: {
   211                      generalFileDialog.show(false, function(path) {
   212                          // Empty hash for latest
   213                          gui.dumpState("", path)
   214                      })
   215                  }
   216              }
   217  
   218              MenuSeparator {}
   219          }
   220  
   221          Menu {
   222              title: "Network"
   223              MenuItem {
   224                  text: "Add Peer"
   225                  shortcut: "Ctrl+p"
   226                  onTriggered: {
   227                      addPeerWin.visible = true
   228                  }
   229              }
   230              MenuItem {
   231                  text: "Show Peers"
   232                  shortcut: "Ctrl+e"
   233                  onTriggered: {
   234                      peerWindow.visible = true
   235                  }
   236              }
   237          }
   238  
   239          Menu {
   240              title: "Help"
   241              MenuItem {
   242                  text: "About"
   243                  onTriggered: {
   244                      aboutWin.visible = true
   245                  }
   246              }
   247          }
   248      }
   249  
   250      statusBar: StatusBar {
   251          //height: 32
   252          visible: false
   253  
   254          id: statusBar
   255          Label {
   256              //y: 6
   257              id: walletValueLabel
   258  
   259              font.pixelSize: 10
   260              styleColor: "#797979"
   261          }
   262  
   263  	/*
   264          Label {
   265              //y: 6
   266              objectName: "miningLabel"
   267              visible: true
   268              font.pixelSize: 10
   269              anchors.right: lastBlockLabel.left
   270              anchors.rightMargin: 5
   271          }
   272  
   273          Label {
   274              id: lastBlockLabel
   275              objectName: "lastBlockLabel"
   276              visible: true
   277              text: "---"
   278              font.pixelSize: 10
   279              anchors.right: peerGroup.left
   280              anchors.rightMargin: 5
   281          }
   282  	*/
   283  
   284          ProgressBar {
   285              visible: false
   286              id: downloadIndicator
   287              value: 0
   288              objectName: "downloadIndicator"
   289              y: -4
   290              x: statusBar.width / 2 - this.width / 2
   291              width: 160
   292          }
   293  
   294          Label {
   295              visible: false
   296              objectName: "downloadLabel"
   297              //y: 7
   298              anchors.left: downloadIndicator.right
   299              anchors.leftMargin: 5
   300              font.pixelSize: 10
   301              text: "0 / 0"
   302          }
   303  
   304  
   305          RowLayout {
   306              id: peerGroup
   307              //y: 7
   308              anchors.right: parent.right
   309              MouseArea {
   310                  onDoubleClicked:  peerWindow.visible = true
   311                  anchors.fill: parent
   312              }
   313  
   314              Label {
   315                  id: peerCounterLabel
   316                  font.pixelSize: 10
   317                  text: "0 / 0"
   318              }
   319          }
   320      }
   321  
   322  
   323      property var blockModel: ListModel {
   324          id: blockModel
   325      }
   326  
   327      SplitView {
   328          property var views: [];
   329  
   330          id: mainSplit
   331          anchors.fill: parent
   332          //resizing: false  // this is NOT where we remove that damning resizing handle..
   333          handleDelegate: Item {
   334              //This handle is a way to remove the line between the split views
   335              Rectangle {
   336                  anchors.fill: parent
   337              }
   338           }
   339  
   340          function setView(view, menu) {
   341              for(var i = 0; i < views.length; i++) {
   342                  views[i].view.visible = false
   343                  views[i].menuItem.setSelection(false)
   344              }
   345              view.visible = true
   346              menu.setSelection(true)
   347          }
   348  
   349          function addComponent(view, options) {
   350              view.visible = false
   351              view.anchors.fill = mainView
   352  
   353              var menuItem = menu.createMenuItem(view, options);
   354              if( view.hasOwnProperty("menuItem") ) {
   355                  view.menuItem = menuItem;
   356              }
   357  
   358              if( view.hasOwnProperty("onReady") ) {
   359                  view.onReady.call(view)
   360              }
   361  
   362              if( options.active ) {
   363                  setView(view, menuItem)
   364              }
   365  
   366  
   367              return {view: view, menuItem: menuItem}
   368          }
   369  
   370          /*********************
   371           * Main menu.
   372           ********************/
   373           Rectangle {
   374               id: menu
   375               Layout.minimumWidth: 192
   376               Layout.maximumWidth: 192
   377  
   378              FontLoader { 
   379                 id: sourceSansPro
   380                 source: "fonts/SourceSansPro-Regular.ttf" 
   381              }
   382              FontLoader { 
   383                 source: "fonts/SourceSansPro-Semibold.ttf" 
   384              }            
   385              FontLoader { 
   386                 source: "fonts/SourceSansPro-Bold.ttf" 
   387              } 
   388              FontLoader { 
   389                 source: "fonts/SourceSansPro-Black.ttf" 
   390              }            
   391              FontLoader { 
   392                 source: "fonts/SourceSansPro-Light.ttf" 
   393              }              
   394              FontLoader { 
   395                 source: "fonts/SourceSansPro-ExtraLight.ttf" 
   396              }  
   397              FontLoader { 
   398                 id: simpleLineIcons
   399                 source: "fonts/Simple-Line-Icons.ttf" 
   400              }
   401  
   402              Rectangle {
   403                  color: "steelblue"
   404                  anchors.fill: parent
   405  
   406                  MouseArea {
   407                      anchors.fill: parent
   408                      property real lastMouseX: 0
   409                      property real lastMouseY: 0
   410                      onPressed: {
   411                          lastMouseX = mouseX
   412                          lastMouseY = mouseY
   413                      }
   414                      onPositionChanged: {
   415                          root.x += (mouseX - lastMouseX)
   416                          root.y += (mouseY - lastMouseY)
   417                      }
   418                      /*onDoubleClicked: {
   419                          //!maximized ? view.set_max() : view.set_normal()}
   420                          visibility = "Minimized"
   421                      }*/
   422                  }
   423              }
   424  
   425  
   426  
   427               anchors.top: parent.top
   428               Rectangle {
   429                       width: parent.height
   430                       height: parent.width
   431                       anchors.centerIn: parent
   432                       rotation: 90
   433  
   434                       gradient: Gradient {
   435                           GradientStop { position: 0.0; color: "#E2DEDE" }
   436                           GradientStop { position: 0.1; color: "#EBE8E8" }
   437                           GradientStop { position: 1.0; color: "#EBE8E8" }
   438                       }
   439               }
   440  
   441               Component {
   442                   id: menuItemTemplate
   443                   Rectangle {
   444                       id: menuItem
   445                       property var view;
   446                       property var path;
   447                       property var closable;
   448  
   449                       property alias title: label.text
   450                       property alias icon: icon.source
   451                       property alias secondaryTitle: secondary.text
   452                       function setSelection(on) {
   453                           sel.visible = on
   454                           
   455                           if (this.closable == true) {
   456                                  closeIcon.visible = on
   457                           }
   458                       }
   459  
   460                       function setAsBigButton(on) {
   461                          newAppButton.visible = on
   462                          label.visible = !on
   463                          buttonLabel.visible = on
   464                       }
   465  
   466                       width: 192
   467                       height: 55
   468                       color: "#00000000"
   469  
   470                       anchors {
   471                           left: parent.left
   472                           leftMargin: 4
   473                       }
   474  
   475                       Rectangle {
   476                           // New App Button
   477                           id: newAppButton
   478                           visible: false 
   479                           anchors.fill: parent
   480                           anchors.rightMargin: 8
   481                           border.width: 0
   482                           radius: 5
   483                           height: 55
   484                           width: 180
   485                           color: "#F3F1F3"
   486                       }
   487  
   488                       Rectangle {
   489                           id: sel
   490                           visible: false
   491                           anchors.fill: parent
   492                           color: "#00000000"
   493                           Rectangle {
   494                               id: r
   495                               anchors.fill: parent
   496                               border.width: 0
   497                               radius: 5
   498                               color: "#FAFAFA"
   499                           }
   500                           Rectangle {
   501                               anchors {
   502                                   top: r.top
   503                                   bottom: r.bottom
   504                                   right: r.right
   505                               }
   506                               width: 10
   507                               color: "#FAFAFA"
   508                               border.width:0
   509  
   510                               Rectangle {
   511                                  // Small line on top of selection. What's this for?
   512                                   anchors {
   513                                       left: parent.left
   514                                       right: parent.right
   515                                       top: parent.top
   516                                   }
   517                                   height: 1
   518                                   color: "#FAFAFA"
   519                               }
   520  
   521                               Rectangle {
   522                                  // Small line on bottom of selection. What's this for again?
   523                                   anchors {
   524                                       left: parent.left
   525                                       right: parent.right
   526                                       bottom: parent.bottom
   527                                   }
   528                                   height: 1
   529                                   color: "#FAFAFA"
   530                               }
   531                           }
   532                       }
   533  
   534                       MouseArea {
   535                           anchors.fill: parent
   536                           hoverEnabled: true
   537                           onClicked: {
   538                               activeView(view, menuItem);
   539                           }
   540                           onEntered: {
   541                              if (parent.closable == true) {
   542                                  closeIcon.visible = sel.visible
   543                              }
   544                              
   545                           }
   546                           onExited:  {
   547                              closeIcon.visible = false
   548                           }
   549                       }
   550  
   551                       Image {
   552                           id: icon
   553                           height: 24
   554                           width: 24
   555                           anchors {
   556                               left: parent.left
   557                               verticalCenter: parent.verticalCenter
   558                               leftMargin: 6
   559                           }
   560                       }
   561  
   562                       Text {
   563                          id: buttonLabel
   564                          visible: false
   565                          text: "GO TO NEW APP"
   566                          font.family: sourceSansPro.name 
   567                          font.weight: Font.DemiBold
   568                          anchors.horizontalCenter: parent.horizontalCenter
   569                          anchors.verticalCenter: parent.verticalCenter
   570                          color: "#AAA0A0"
   571                       }   
   572  
   573                      Text {
   574                           id: label
   575                           font.family: sourceSansPro.name 
   576                           font.weight: Font.DemiBold
   577                           anchors {
   578                               left: icon.right
   579                               verticalCenter: parent.verticalCenter
   580                               leftMargin: 6
   581                               // verticalCenterOffset: -10
   582                           }
   583                           x:250
   584                           color: "#665F5F"
   585                           font.pixelSize: 14
   586                       }
   587  
   588  
   589                       Text {
   590                           id: secondary
   591                           font.family: sourceSansPro.name 
   592                           font.weight: Font.Light
   593                           anchors {
   594                               left: icon.right
   595                               leftMargin: 6
   596                               top: label.bottom
   597                           }
   598                           color: "#6691C2"
   599                           font.pixelSize: 12
   600                       }
   601  
   602                       Rectangle {
   603                          id: closeIcon
   604                          visible: false
   605                          width: 10
   606                          height: 10
   607                          color: "#FFFFFF"
   608                          anchors {
   609                              fill: icon
   610                          }
   611  
   612                          MouseArea {
   613                               anchors.fill: parent
   614                               onClicked: {
   615                                   menuItem.closeApp()
   616                               }
   617                           }
   618  
   619                          Text {
   620                               
   621                               font.family: simpleLineIcons.name 
   622                               anchors {
   623                                   centerIn: parent
   624                               }
   625                               color: "#665F5F"
   626                               font.pixelSize: 18
   627                               text: "\ue082"
   628                           }
   629                       }
   630                       
   631  
   632  
   633                       function closeApp() {
   634                           if(!this.closable) { return; }
   635  
   636                           if(this.view.hasOwnProperty("onDestroy")) {
   637                               this.view.onDestroy.call(this.view)
   638                           }
   639  
   640                           this.view.destroy()
   641                           this.destroy()
   642                           for (var i = 0; i < mainSplit.views.length; i++) {
   643                               var view = mainSplit.views[i];
   644                               if (view.menuItem === this) {
   645                                   mainSplit.views.splice(i, 1);
   646                                   break;
   647                               }
   648                           }
   649                           gui.removePlugin(this.path)
   650                           activeView(mainSplit.views[0].view, mainSplit.views[0].menuItem);
   651                       }
   652                   }
   653               }
   654  
   655               function createMenuItem(view, options) {
   656                   if(options === undefined) {
   657                       options = {};
   658                   }
   659  
   660                   var section;
   661                   switch(options.section) {
   662                       case "begin":
   663                       section = menuBegin
   664                       break;
   665                       case "ethereum":
   666                       section = menuDefault;
   667                       break;
   668                       case "legacy":
   669                       section = menuLegacy;
   670                       break;
   671                       default:
   672                       section = menuApps;
   673                       break;
   674                   }
   675  
   676                   var comp = menuItemTemplate.createObject(section)
   677                   comp.view = view
   678                   comp.title = view.title
   679  
   680                   if(view.hasOwnProperty("iconSource")) {
   681                       comp.icon = view.iconSource;
   682                   }
   683                   comp.closable = options.close;
   684  
   685                   if (options.section === "begin") {
   686                      comp.setAsBigButton(true)
   687                   }
   688  
   689                   return comp
   690               }
   691  
   692               ColumnLayout {
   693                   id: menuColumn
   694                   y: 10
   695                   width: parent.width
   696                   anchors.left: parent.left
   697                   anchors.right: parent.right
   698                   spacing: 3
   699                  
   700  
   701  
   702                  ColumnLayout {
   703                       id: menuBegin
   704                       spacing: 3
   705                       anchors {
   706                           left: parent.left
   707                           right: parent.right
   708                       }
   709                   }
   710  
   711                   Rectangle {
   712                       height: 55
   713                       color: "transparent"
   714                       Text {
   715                           text: "ETHEREUM"
   716                           font.family: sourceSansPro.name 
   717                           font.weight: Font.DemiBold
   718                           anchors {
   719                               left: parent.left
   720                               top: parent.verticalCenter
   721                               leftMargin: 16
   722                           }
   723                           color: "#AAA0A0"
   724                       }
   725                   }
   726  
   727  
   728                   ColumnLayout {
   729                       id: menuDefault
   730                       spacing: 3
   731                       anchors {
   732                           left: parent.left
   733                           right: parent.right
   734                       }
   735                   }
   736  
   737                   Rectangle {
   738                       height: 55
   739                       color: "transparent"
   740                       Text {
   741                           text: "APPS"
   742                           font.family: sourceSansPro.name 
   743                           font.weight: Font.DemiBold
   744                           anchors {
   745                               left: parent.left
   746                               top: parent.verticalCenter
   747                               leftMargin: 16
   748                           }
   749                           color: "#AAA0A0"
   750                       }
   751                   }
   752  
   753                   ColumnLayout {
   754                       id: menuApps
   755                       spacing: 3
   756                       anchors {
   757                           left: parent.left
   758                           right: parent.right
   759                       }
   760                   }
   761  
   762                   Rectangle {
   763                       height: 55
   764                       color: "transparent"
   765                       Text {
   766                           text: "DEBUG"
   767                           font.family: sourceSansPro.name 
   768                           font.weight: Font.DemiBold
   769                           anchors {
   770                               left: parent.left
   771                               top: parent.verticalCenter
   772                               leftMargin: 16
   773                           }
   774                           color: "#AAA0A0"
   775                       }
   776                   }
   777  
   778  
   779                   ColumnLayout {
   780                       id: menuLegacy
   781                       spacing: 3
   782                       anchors {
   783                           left: parent.left
   784                           right: parent.right
   785                       }
   786                   }
   787               }
   788           }
   789  
   790           /*********************
   791            * Main view
   792            ********************/
   793            Rectangle {
   794                id: rootView
   795                anchors.right: parent.right
   796                anchors.left: menu.right
   797                anchors.bottom: parent.bottom
   798                anchors.top: parent.top
   799                color: "#00000000"             
   800  
   801                /*Rectangle {
   802                    id: urlPane
   803                    height: 40
   804                    color: "#00000000"
   805                    anchors {
   806                        left: parent.left
   807                        right: parent.right
   808                        leftMargin: 5
   809                        rightMargin: 5
   810                        top: parent.top
   811                        topMargin: 5
   812                    }
   813                    TextField {
   814                        id: url
   815                        objectName: "url"
   816                        placeholderText: "DApp URL"
   817                        anchors {
   818                            left: parent.left
   819                            right: parent.right
   820                            top: parent.top
   821                            topMargin: 5
   822                            rightMargin: 5
   823                            leftMargin: 5
   824                        }
   825  
   826                        Keys.onReturnPressed: {
   827                            if(/^https?/.test(this.text)) {
   828                                newBrowserTab(this.text);
   829                            } else {
   830                                addPlugin(this.text, {close: true, section: "apps"})
   831                            }
   832                        }
   833                    }
   834  
   835                }
   836  
   837                // Border
   838                Rectangle {
   839                    id: divider
   840                    anchors {
   841                        left: parent.left
   842                        right: parent.right
   843                        top: urlPane.bottom
   844                    }
   845                    z: -1
   846                    height: 1
   847                    color: "#CCCCCC"
   848                }*/
   849  
   850                Rectangle {
   851                    id: mainView
   852                    color: "#00000000"
   853                    anchors.right: parent.right
   854                    anchors.left: parent.left
   855                    anchors.bottom: parent.bottom
   856                    anchors.top: parent.top
   857  
   858                    function createView(component) {
   859                        var view = component.createObject(mainView)
   860  
   861                        return view;
   862                    }
   863                }
   864            }
   865        }
   866  
   867  
   868        /******************
   869         * Dialogs
   870         *****************/
   871         FileDialog {
   872             id: generalFileDialog
   873             property var callback;
   874             onAccepted: {
   875                 var path = this.fileUrl.toString();
   876                 callback.call(this, path);
   877             }
   878  
   879             function show(selectExisting, callback) {
   880                 generalFileDialog.callback = callback;
   881                 generalFileDialog.selectExisting = selectExisting;
   882  
   883                 this.open();
   884             }
   885         }
   886  
   887  
   888         /******************
   889          * Wallet functions
   890          *****************/
   891          function importApp(path) {
   892              var ext = path.split('.').pop()
   893              if(ext == "html" || ext == "htm") {
   894                  eth.openHtml(path)
   895              }else if(ext == "qml"){
   896                  addPlugin(path, {close: true, section: "apps"})
   897              }
   898          }
   899  
   900          function setWalletValue(value) {
   901              walletValueLabel.text = value
   902          }
   903  
   904          function loadPlugin(name) {
   905              console.log("Loading plugin" + name)
   906              var view = mainView.addPlugin(name)
   907          }
   908  
   909          function clearPeers() { peerModel.clear() }
   910          function addPeer(peer) { peerModel.append(peer) }
   911  
   912          function setPeerCounters(text) {
   913              peerCounterLabel.text = text
   914          }
   915  
   916          function timeAgo(unixTs){
   917              var lapsed = (Date.now() - new Date(unixTs*1000)) / 1000
   918              return  (lapsed + " seconds ago")
   919          }
   920  
   921          function convertToPretty(unixTs){
   922              var a = new Date(unixTs*1000);
   923              var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
   924              var year = a.getFullYear();
   925              var month = months[a.getMonth()];
   926              var date = a.getDate();
   927              var hour = a.getHours();
   928              var min = a.getMinutes();
   929              var sec = a.getSeconds();
   930              var time = date+' '+month+' '+year+' '+hour+':'+min+':'+sec ;
   931              return time;
   932          }
   933  
   934          /**********************
   935           * Windows
   936           *********************/
   937           Window {
   938               id: peerWindow
   939               //flags: Qt.CustomizeWindowHint | Qt.Tool | Qt.WindowCloseButtonHint
   940               height: 200
   941               width: 700
   942               Rectangle {
   943                   anchors.fill: parent
   944                   property var peerModel: ListModel {
   945                       id: peerModel
   946                   }
   947                   TableView {
   948                       anchors.fill: parent
   949                       id: peerTable
   950                       model: peerModel
   951                       TableViewColumn{width: 180; role: "addr" ; title: "Remote Address" }
   952                       TableViewColumn{width: 280; role: "nodeID" ; title: "Node ID" }
   953                       TableViewColumn{width: 180; role: "caps" ; title: "Capabilities" }
   954                   }
   955               }
   956           }
   957  
   958           Window {
   959               id: aboutWin
   960               visible: false
   961               title: "About"
   962               minimumWidth: 350
   963               maximumWidth: 350
   964               maximumHeight: 280
   965               minimumHeight: 280
   966  
   967               Image {
   968                   id: aboutIcon
   969                   height: 150
   970                   width: 150
   971                   fillMode: Image.PreserveAspectFit
   972                   smooth: true
   973                   source: "../facet.png"
   974                   x: 10
   975                   y: 30
   976               }
   977  
   978               Text {
   979                   anchors.left: aboutIcon.right
   980                   anchors.leftMargin: 10
   981                   anchors.top: parent.top
   982                   anchors.topMargin: 30
   983                   font.pointSize: 12
   984                   text: "<h2>Mist (0.7.10)</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor TrĂ³n<br>Felix Lange<br>Taylor Gerring<br>Daniel Nagy<br><h3>UX</h3>Alex van de Sande<br>"
   985               }
   986           }
   987  
   988           Window {
   989               id: txImportDialog
   990               minimumWidth: 270
   991               maximumWidth: 270
   992               maximumHeight: 50
   993               minimumHeight: 50
   994               TextField {
   995                   id: txImportField
   996                   width: 170
   997                   anchors.verticalCenter: parent.verticalCenter
   998                   anchors.left: parent.left
   999                   anchors.leftMargin: 10
  1000                   onAccepted: {
  1001                   }
  1002               }
  1003               Button {
  1004                   anchors.left: txImportField.right
  1005                   anchors.verticalCenter: parent.verticalCenter
  1006                   anchors.leftMargin: 5
  1007                   text: "Import"
  1008                   onClicked: {
  1009                       eth.importTx(txImportField.text)
  1010                       txImportField.visible = false
  1011                   }
  1012               }
  1013               Component.onCompleted: {
  1014                   addrField.focus = true
  1015               }
  1016           }
  1017  
  1018           Window {
  1019               id: addPeerWin
  1020               visible: false
  1021               minimumWidth: 400
  1022               maximumWidth: 400
  1023               maximumHeight: 50
  1024               minimumHeight: 50
  1025               title: "Connect to peer"
  1026  
  1027               TextField {
  1028                   id: addrField
  1029                   anchors.verticalCenter: parent.verticalCenter
  1030                   anchors.left: parent.left
  1031                   anchors.right: addPeerButton.left
  1032                   anchors.leftMargin: 10
  1033                   anchors.rightMargin: 10
  1034  		 placeholderText: "enode://<hex node id>:<IP address>:<port>"
  1035                   onAccepted: {
  1036  	             if(addrField.text.length != 0) {
  1037  			eth.connectToPeer(addrField.text)
  1038  			addPeerWin.visible = false
  1039  		     }
  1040                   }
  1041               }
  1042  
  1043               Button {
  1044                   id: addPeerButton
  1045                   anchors.right: parent.right
  1046                   anchors.verticalCenter: parent.verticalCenter
  1047                   anchors.rightMargin: 10
  1048                   text: "Connect"
  1049                   onClicked: {
  1050  	             if(addrField.text.length != 0) {
  1051  			eth.connectToPeer(addrField.text)
  1052  			addPeerWin.visible = false
  1053  		     }
  1054                   }
  1055               }
  1056               Component.onCompleted: {
  1057                   addrField.focus = true
  1058               }
  1059           }
  1060       }