URI: 
       tqt: show addresses and utxos in separate tabs - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 7af5d42324041204967b7d9c0865ddb8c2eb2712
   DIR parent 1358bebd37a1784b40d4459d6f535e29b7c78fa0
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Sun,  8 Jan 2017 13:00:57 +0100
       
       qt: show addresses and utxos in separate tabs
       
       Diffstat:
         M gui/qt/address_list.py              |      15 +--------------
         M gui/qt/main_window.py               |      44 ++++++++++++++++++++-----------
         A gui/qt/utxo_list.py                 |      66 +++++++++++++++++++++++++++++++
         M lib/wallet.py                       |       7 +++++--
       
       4 files changed, 100 insertions(+), 32 deletions(-)
       ---
   DIR diff --git a/gui/qt/address_list.py b/gui/qt/address_list.py
       t@@ -84,15 +84,6 @@ class AddressList(MyTreeWidget):
                                seq_item.addChild(address_item)
                            if address == current_address:
                                self.setCurrentItem(address_item)
       -                    # add utxos
       -                    utxos = self.wallet.get_addr_utxo(address)
       -                    for x in utxos:
       -                        h = x.get('prevout_hash')
       -                        s = h + ":%d"%x.get('prevout_n')
       -                        label = self.wallet.get_label(h)
       -                        utxo_item = QTreeWidgetItem([s, label, self.parent.format_amount(x['value'])])
       -                        utxo_item.setFont(0, QFont(MONOSPACE_FONT))
       -                        address_item.addChild(utxo_item)
        
            def create_menu(self, position):
                from electrum.wallet import Multisig_Wallet
       t@@ -110,11 +101,7 @@ class AddressList(MyTreeWidget):
                        return
                    addr = addrs[0]
                    if not is_address(addr):
       -                k = str(item.data(0,32).toString())
       -                if k:
       -                    self.create_account_menu(position, k, item)
       -                else:
       -                    item.setExpanded(not item.isExpanded())
       +                item.setExpanded(not item.isExpanded())
                        return
        
                menu = QMenu()
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -129,6 +129,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                self.addresses_tab = self.create_addresses_tab()
                if self.config.get('show_addresses_tab', False):
                    tabs.addTab(self.addresses_tab, _('Addresses'))
       +        self.utxo_tab = self.create_utxo_tab()
       +        if self.config.get('show_utxo_tab', False):
       +            tabs.addTab(self.utxo_tab, _('Coins'))
                tabs.addTab(self.create_contacts_tab(), _('Contacts') )
                tabs.addTab(self.create_console_tab(), _('Console') )
                tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
       t@@ -198,14 +201,23 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                    self.history_list.update()
        
            def toggle_addresses_tab(self):
       -        show_addr = not self.config.get('show_addresses_tab', False)
       -        self.config.set_key('show_addresses_tab', show_addr)
       -        if show_addr:
       +        show = not self.config.get('show_addresses_tab', False)
       +        self.config.set_key('show_addresses_tab', show)
       +        if show:
                    self.tabs.insertTab(3, self.addresses_tab, _('Addresses'))
                else:
                    i = self.tabs.indexOf(self.addresses_tab)
                    self.tabs.removeTab(i)
        
       +    def toggle_utxo_tab(self):
       +        show = not self.config.get('show_utxo_tab', False)
       +        self.config.set_key('show_utxo_tab', show)
       +        if show:
       +            self.tabs.insertTab(3, self.utxo_tab, _('Coins'))
       +        else:
       +            i = self.tabs.indexOf(self.utxo_tab)
       +            self.tabs.removeTab(i)
       +
            def push_top_level_window(self, window):
                '''Used for e.g. tx dialog box to ensure new dialogs are appropriately
                parented.  This used to be done by explicitly providing the parent
       t@@ -436,6 +448,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
        
                wallet_menu.addAction(_("Find"), self.toggle_search).setShortcut(QKeySequence("Ctrl+F"))
                wallet_menu.addAction(_("Addresses"), self.toggle_addresses_tab).setShortcut(QKeySequence("Ctrl+A"))
       +        wallet_menu.addAction(_("Coins"), self.toggle_utxo_tab).setShortcut(QKeySequence("Ctrl+C"))
        
                tools_menu = menubar.addMenu(_("&Tools"))
        
       t@@ -660,6 +673,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                self.history_list.update()
                self.request_list.update()
                self.address_list.update()
       +        self.utxo_list.update()
                self.contact_list.update()
                self.invoice_list.update()
                self.update_completions()
       t@@ -1059,6 +1073,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                vbox.addWidget(self.invoices_label)
                vbox.addWidget(self.invoice_list)
                vbox.setStretchFactor(self.invoice_list, 1000)
       +
                # Defer this until grid is parented to avoid ugly flash during startup
                run_hook('create_send_tab', grid)
                return w
       t@@ -1122,8 +1137,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                menu.addAction(_("Remove"), lambda: self.from_list_delete(item))
                menu.exec_(self.from_list.viewport().mapToGlobal(position))
        
       -    def set_pay_from(self, domain = None):
       -        self.pay_from = [] if domain == [] else self.wallet.get_spendable_coins(domain)
       +    def set_pay_from(self, coins):
       +        self.pay_from = coins
                self.redraw_from_list()
        
            def redraw_from_list(self):
       t@@ -1133,7 +1148,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
        
                def format(x):
                    h = x.get('prevout_hash')
       -            return h[0:8] + '...' + h[-8:] + ":%d"%x.get('prevout_n') + u'\t' + "%s"%x.get('address')
       +            return h[0:10] + '...' + h[-10:] + ":%d"%x.get('prevout_n') + u'\t' + "%s"%x.get('address')
        
                for item in self.pay_from:
                    self.from_list.addTopLevelItem(QTreeWidgetItem( [format(item), self.format_amount(item['value']) ]))
       t@@ -1469,6 +1484,11 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                self.address_list = l = AddressList(self)
                return self.create_list_tab(l)
        
       +    def create_utxo_tab(self):
       +        from utxo_list import UTXOList
       +        self.utxo_list = l = UTXOList(self)
       +        return self.create_list_tab(l)
       +
            def create_contacts_tab(self):
                from contact_list import ContactList
                self.contact_list = l = ContactList(self)
       t@@ -1480,13 +1500,6 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                    self.address_list.update()
                    self.history_list.update()
        
       -    def edit_account_label(self, k):
       -        text, ok = QInputDialog.getText(self, _('Rename account'), _('Name') + ':', text = self.wallet.labels.get(k,''))
       -        if ok:
       -            label = unicode(text)
       -            self.wallet.set_label(k,label)
       -            self.address_list.update()
       -
            def get_coins(self):
                if self.pay_from:
                    return self.pay_from
       t@@ -1494,9 +1507,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                    domain = self.wallet.get_addresses()
                    return self.wallet.get_spendable_coins(domain)
        
       -
       -    def send_from_addresses(self, addrs):
       -        self.set_pay_from(addrs)
       +    def spend_coins(self, coins):
       +        self.set_pay_from(coins)
                self.tabs.setCurrentIndex(1)
                self.update_fee()
        
   DIR diff --git a/gui/qt/utxo_list.py b/gui/qt/utxo_list.py
       t@@ -0,0 +1,66 @@
       +#!/usr/bin/env python
       +#
       +# Electrum - lightweight Bitcoin client
       +# Copyright (C) 2015 Thomas Voegtlin
       +#
       +# Permission is hereby granted, free of charge, to any person
       +# obtaining a copy of this software and associated documentation files
       +# (the "Software"), to deal in the Software without restriction,
       +# including without limitation the rights to use, copy, modify, merge,
       +# publish, distribute, sublicense, and/or sell copies of the Software,
       +# and to permit persons to whom the Software is furnished to do so,
       +# subject to the following conditions:
       +#
       +# The above copyright notice and this permission notice shall be
       +# included in all copies or substantial portions of the Software.
       +#
       +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
       +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
       +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
       +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
       +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
       +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
       +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
       +# SOFTWARE.
       +
       +from util import *
       +from electrum.i18n import _
       +
       +
       +class UTXOList(MyTreeWidget):
       +
       +    def __init__(self, parent=None):
       +        MyTreeWidget.__init__(self, parent, self.create_menu, [ _('Output'), _('Address'), _('Label'), _('Amount'), ''], 2)
       +        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
       +
       +    def get_name(self, x):
       +        return x.get('prevout_hash') + ":%d"%x.get('prevout_n')
       +
       +    def on_update(self):
       +        self.wallet = self.parent.wallet
       +        item = self.currentItem()
       +        self.clear()
       +        self.utxos = self.wallet.get_utxos()
       +        for x in self.utxos:
       +            address = x.get('address')
       +            name = self.get_name(x)
       +            label = self.wallet.get_label(x.get('prevout_hash'))
       +            amount = self.parent.format_amount(x['value'])
       +            utxo_item = QTreeWidgetItem([name[0:10]+'...'+name[-10:], address, label, amount])
       +            utxo_item.setFont(0, QFont(MONOSPACE_FONT))
       +            utxo_item.setFont(1, QFont(MONOSPACE_FONT))
       +            utxo_item.setData(0, Qt.UserRole, name)
       +            if self.wallet.is_frozen(address):
       +                utxo_item.setBackgroundColor(0, QColor('lightblue'))
       +            self.addChild(utxo_item)
       +
       +    def create_menu(self, position):
       +        from electrum.wallet import Multisig_Wallet
       +        selected = [ x.data(0, Qt.UserRole).toString() for x in self.selectedItems()]
       +        if not selected:
       +            return
       +        coins = filter(lambda x: self.get_name(x) in selected, self.utxos)
       +        menu = QMenu()
       +        menu.addAction(_("Spend"), lambda: self.parent.spend_coins(coins))
       +        menu.exec_(self.viewport().mapToGlobal(position))
       +
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -532,7 +532,10 @@ class Abstract_Wallet(PrintError):
                            u -= v
                return c, u, x
        
       -    def get_spendable_coins(self, domain = None, exclude_frozen = True):
       +    def get_spendable_coins(self, domain = None):
       +        return self.get_utxos(self, domain, exclude_frozen=True, mature=True)
       +
       +    def get_utxos(self, domain = None, exclude_frozen = False, mature = False):
                coins = []
                if domain is None:
                    domain = self.get_addresses()
       t@@ -541,7 +544,7 @@ class Abstract_Wallet(PrintError):
                for addr in domain:
                    utxos = self.get_addr_utxo(addr)
                    for x in utxos:
       -                if x['coinbase'] and x['height'] + COINBASE_MATURITY > self.get_local_height():
       +                if mature and x['coinbase'] and x['height'] + COINBASE_MATURITY > self.get_local_height():
                            continue
                        coins.append(x)
                        continue