tgui simplification - electrum - Electrum Bitcoin wallet
 (HTM) git clone https://git.parazyd.org/electrum
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
       ---
 (DIR) commit 93250b10417299e8b8c6681df8cb5b4120d0f582
 (DIR) parent b8a72180c7a5d3198b2f8d299d9247b8eabda952
 (HTM) Author: ThomasV <thomasv@gitorious>
       Date:   Sat,  4 Apr 2015 20:59:57 +0200
       
       gui simplification
       
       Diffstat:
         A gui/qt/history_widget.py            |     100 +++++++++++++++++++++++++++++++
         M gui/qt/main_window.py               |      97 ++++---------------------------
         M gui/qt/util.py                      |      52 +++++++++++++++++++++++++++++--
       
       3 files changed, 159 insertions(+), 90 deletions(-)
       ---
 (DIR) diff --git a/gui/qt/history_widget.py b/gui/qt/history_widget.py
       t@@ -0,0 +1,100 @@
       +#!/usr/bin/env python
       +#
       +# Electrum - lightweight Bitcoin client
       +# Copyright (C) 2015 Thomas Voegtlin
       +#
       +# This program is free software: you can redistribute it and/or modify
       +# it under the terms of the GNU General Public License as published by
       +# the Free Software Foundation, either version 3 of the License, or
       +# (at your option) any later version.
       +#
       +# This program is distributed in the hope that it will be useful,
       +# but WITHOUT ANY WARRANTY; without even the implied warranty of
       +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
       +# GNU General Public License for more details.
       +#
       +# You should have received a copy of the GNU General Public License
       +# along with this program. If not, see <http://www.gnu.org/licenses/>.
       +
       +
       +import webbrowser
       +
       +from util import *
       +from electrum.i18n import _
       +from electrum.util import format_satoshis, format_time
       +from electrum.plugins import run_hook
       +
       +
       +class HistoryWidget(MyTreeWidget):
       +
       +    def __init__(self, parent=None):
       +        MyTreeWidget.__init__(self, parent, self.create_menu, [ '', _('Date'), _('Description') , _('Amount'), _('Balance')], [40, 140, None, 140, 140])
       +        self.config = self.parent.config
       +
       +    def update(self, h):
       +        self.wallet = self.parent.wallet
       +        item = self.currentItem()
       +        current_tx = item.data(0, Qt.UserRole).toString() if item else None
       +        self.clear()
       +        for item in h:
       +            tx_hash, conf, value, timestamp, balance = item
       +            time_str = _("unknown")
       +            if conf is None and timestamp is None:
       +                continue  # skip history in offline mode
       +            if conf > 0:
       +                time_str = format_time(timestamp)
       +            if conf == -1:
       +                time_str = 'unverified'
       +                icon = QIcon(":icons/unconfirmed.png")
       +            elif conf == 0:
       +                time_str = 'pending'
       +                icon = QIcon(":icons/unconfirmed.png")
       +            elif conf < 6:
       +                icon = QIcon(":icons/clock%d.png"%conf)
       +            else:
       +                icon = QIcon(":icons/confirmed.png")
       +            v_str = self.parent.format_amount(value, True, whitespaces=True)
       +            balance_str = self.parent.format_amount(balance, whitespaces=True)
       +            label, is_default_label = self.wallet.get_label(tx_hash)
       +            item = QTreeWidgetItem( [ '', time_str, label, v_str, balance_str] )
       +            item.setFont(2, QFont(MONOSPACE_FONT))
       +            item.setFont(3, QFont(MONOSPACE_FONT))
       +            item.setFont(4, QFont(MONOSPACE_FONT))
       +            if value < 0:
       +                item.setForeground(3, QBrush(QColor("#BC1E1E")))
       +            if tx_hash:
       +                item.setData(0, Qt.UserRole, tx_hash)
       +            if is_default_label:
       +                item.setForeground(2, QBrush(QColor('grey')))
       +            item.setIcon(0, icon)
       +            self.insertTopLevelItem(0, item)
       +            if current_tx == tx_hash:
       +                self.setCurrentItem(item)
       +
       +        run_hook('history_tab_update')
       +
       +
       +    def create_menu(self, position):
       +        self.selectedIndexes()
       +        item = self.currentItem()
       +        be = self.config.get('block_explorer', 'Blockchain.info')
       +        if be == 'Blockchain.info':
       +            block_explorer = 'https://blockchain.info/tx/'
       +        elif be == 'Blockr.io':
       +            block_explorer = 'https://blockr.io/tx/info/'
       +        elif be == 'Insight.is':
       +            block_explorer = 'http://live.insight.is/tx/'
       +        elif be == "Blocktrail.com":
       +            block_explorer = 'https://www.blocktrail.com/BTC/tx/'
       +        if not item:
       +            return
       +        tx_hash = str(item.data(0, Qt.UserRole).toString())
       +        if not tx_hash:
       +            return
       +        menu = QMenu()
       +        menu.addAction(_("Copy ID to Clipboard"), lambda: self.parent.app.clipboard().setText(tx_hash))
       +        menu.addAction(_("Details"), lambda: self.parent.show_transaction(self.wallet.transactions.get(tx_hash)))
       +        menu.addAction(_("Edit description"), lambda: self.edit_label(item, 2))
       +        menu.addAction(_("View on block explorer"), lambda: webbrowser.open(block_explorer + tx_hash))
       +        menu.exec_(self.viewport().mapToGlobal(position))
       +
 (DIR) diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -556,41 +556,6 @@ class ElectrumWindow(QMainWindow):
                d = transaction_dialog.TxDialog(tx, self)
                d.exec_()
        
       -    def edit_label(self, is_recv):
       -        l = self.address_list if is_recv else self.contacts_list
       -        item = l.currentItem()
       -        item.setFlags(Qt.ItemIsEditable|Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled)
       -        l.editItem( item, 1 )
       -        item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled)
       -
       -    def address_label_clicked(self, item, column, l, column_addr, column_label):
       -        if column == column_label and item.isSelected():
       -            is_editable = item.data(0, 32).toBool()
       -            if not is_editable:
       -                return
       -            addr = unicode( item.text(column_addr) )
       -            label = unicode( item.text(column_label) )
       -            item.setFlags(Qt.ItemIsEditable|Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled)
       -            l.editItem( item, column )
       -            item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled)
       -
       -    def address_label_changed(self, item, column, l, column_addr, column_label):
       -        if column == column_label:
       -            addr = unicode( item.text(column_addr) )
       -            text = unicode( item.text(column_label) )
       -            is_editable = item.data(0, 32).toBool()
       -            if not is_editable:
       -                return
       -            changed = self.wallet.set_label(addr, text)
       -            if changed:
       -                self.update_history_tab()
       -                self.update_completions()
       -            self.current_item_changed(item)
       -        run_hook('item_changed', item, column)
       -
       -    def current_item_changed(self, a):
       -        run_hook('current_item_changed', a)
       -
            def update_history_tab(self):
                domain = self.wallet.get_account_addresses(self.current_account)
                h = self.wallet.get_history(domain)
       t@@ -645,11 +610,9 @@ class ElectrumWindow(QMainWindow):
                grid.setRowStretch(6, 1)
        
                self.receive_requests_label = QLabel(_('Saved Requests'))
       -        self.receive_list = MyTreeWidget(self)
       -        self.receive_list.customContextMenuRequested.connect(self.receive_list_menu)
       +        self.receive_list = MyTreeWidget(self, self.receive_list_menu, [_('Date'), _('Account'), _('Address'), _('Message'), _('Amount')], [])
                self.receive_list.currentItemChanged.connect(self.receive_item_changed)
                self.receive_list.itemClicked.connect(self.receive_item_changed)
       -        self.receive_list.setHeaderLabels( [_('Date'), _('Account'), _('Address'), _('Message'), _('Amount')] )
                self.receive_list.setSortingEnabled(True)
                self.receive_list.setColumnWidth(0, 180)
                self.receive_list.hideColumn(1)     # the update will show it if necessary
       t@@ -843,14 +806,9 @@ class ElectrumWindow(QMainWindow):
        
                self.from_label = QLabel(_('From'))
                grid.addWidget(self.from_label, 3, 0)
       -        self.from_list = MyTreeWidget(self)
       -        self.from_list.setColumnCount(2)
       -        self.from_list.setColumnWidth(0, 350)
       -        self.from_list.setColumnWidth(1, 50)
       +        self.from_list = MyTreeWidget(self, self.from_list_menu, ['',''], [350, 50])
                self.from_list.setHeaderHidden(True)
                self.from_list.setMaximumHeight(80)
       -        self.from_list.setContextMenuPolicy(Qt.CustomContextMenu)
       -        self.from_list.customContextMenuRequested.connect(self.from_list_menu)
                grid.addWidget(self.from_list, 3, 1, 1, 3)
                self.set_pay_from([])
        
       t@@ -1242,13 +1200,7 @@ class ElectrumWindow(QMainWindow):
                        self.wallet.freeze(addr)
                self.update_address_tab()
        
       -
       -
       -    def create_list_tab(self, headers):
       -        "generic tab creation method"
       -        l = MyTreeWidget(self)
       -        l.setColumnCount( len(headers) )
       -        l.setHeaderLabels( headers )
       +    def create_list_tab(self, l):
                w = QWidget()
                vbox = QVBoxLayout()
                w.setLayout(vbox)
       t@@ -1257,52 +1209,23 @@ class ElectrumWindow(QMainWindow):
                vbox.addWidget(l)
                buttons = QWidget()
                vbox.addWidget(buttons)
       -        return l, w
       +        return w
        
            def create_addresses_tab(self):
       -        column_width = [370, 200, 130]
       -        l, w = self.create_list_tab([ _('Address'), _('Label'), _('Balance'), _('Tx')])
       -        l.header().setResizeMode(1, QHeaderView.Stretch);
       -        l.header().setStretchLastSection(False)
       -        for i,width in enumerate(column_width):
       -            l.setColumnWidth(i, width)
       -        l.setContextMenuPolicy(Qt.CustomContextMenu)
       -        l.customContextMenuRequested.connect(self.create_receive_menu)
       +        l = MyTreeWidget(self, self.create_receive_menu, [ _('Address'), _('Label'), _('Balance'), _('Tx')], [370, None, 130])
                l.setSelectionMode(QAbstractItemView.ExtendedSelection)
       -        l.itemDoubleClicked.connect(lambda a, b: self.address_label_clicked(a,b,l,0,1))
       -        l.itemChanged.connect(lambda a,b: self.address_label_changed(a,b,l,0,1))
       -        l.currentItemChanged.connect(lambda a,b: self.current_item_changed(a))
                self.address_list = l
       -        return w
       +        return self.create_list_tab(l)
        
            def create_contacts_tab(self):
       -        column_width = [350,330]
       -        l, w = self.create_list_tab([_('Address'), _('Label'), _('Tx')])
       -        l.header().setResizeMode(1, QHeaderView.Stretch);
       -        l.header().setStretchLastSection(False)
       -        l.setContextMenuPolicy(Qt.CustomContextMenu)
       -        l.customContextMenuRequested.connect(self.create_contact_menu)
       -        for i,width in enumerate(column_width):
       -            l.setColumnWidth(i, width)
       -        l.itemDoubleClicked.connect(lambda a, b: self.address_label_clicked(a,b,l,0,1))
       -        l.itemChanged.connect(lambda a,b: self.address_label_changed(a,b,l,0,1))
       +        l = MyTreeWidget(self, self.create_contact_menu, [_('Address'), _('Label'), _('Tx')], [350, None])
                self.contacts_list = l
       -        return w
       -
       +        return self.create_list_tab(l)
        
            def create_invoices_tab(self):
       -        l, w = self.create_list_tab([_('Date'), _('Requestor'), _('Memo'), _('Amount'), _('Status')])
       -        l.setColumnWidth(0, 150)
       -        l.setColumnWidth(1, 150)
       -        l.setColumnWidth(3, 150)
       -        l.setColumnWidth(4, 40)
       -        h = l.header()
       -        h.setStretchLastSection(False)
       -        h.setResizeMode(2, QHeaderView.Stretch)
       -        l.setContextMenuPolicy(Qt.CustomContextMenu)
       -        l.customContextMenuRequested.connect(self.create_invoice_menu)
       +        l = MyTreeWidget(self, self.create_invoice_menu, [_('Date'), _('Requestor'), _('Memo'), _('Amount'), _('Status')], [150, 150, None, 150, 40])
                self.invoices_list = l
       -        return w
       +        return self.create_list_tab(l)
        
            def update_invoices_tab(self):
                invoices = self.wallet.storage.get('invoices', {})
 (DIR) diff --git a/gui/qt/util.py b/gui/qt/util.py
       t@@ -253,16 +253,34 @@ def filename_field(parent, config, defaultname, select_msg):
        
        class MyTreeWidget(QTreeWidget):
        
       -    def __init__(self, parent):
       +    def __init__(self, parent, create_menu, headers, column_width):
                QTreeWidget.__init__(self, parent)
       +        self.parent = parent
       +        self.setColumnCount(len(headers))
       +        self.setHeaderLabels(headers)
       +        self.header().setStretchLastSection(False)
                self.setContextMenuPolicy(Qt.CustomContextMenu)
                self.itemActivated.connect(self.on_activated)
       +        self.customContextMenuRequested.connect(create_menu)
                # extend the syntax for consistency
                self.addChild = self.addTopLevelItem
                self.insertChild = self.insertTopLevelItem
       +        # editable column
       +        self.is_edit = False
       +        self.edit_column = None
       +        self.itemDoubleClicked.connect(self.edit_label)
       +        self.itemChanged.connect(self.label_changed)
       +        # set column width
       +        for i, width in enumerate(column_width):
       +            if width is None:
       +                self.header().setResizeMode(i, QHeaderView.Stretch)
       +                self.edit_column = i
       +            else:
       +                self.setColumnWidth(i, width)
        
            def on_activated(self, item):
       -        if not item: return
       +        if not item:
       +            return
                for i in range(0,self.viewport().height()/5):
                    if self.itemAt(QPoint(0,i*5)) == item:
                        break
       t@@ -273,7 +291,35 @@ class MyTreeWidget(QTreeWidget):
                        break
                self.emit(SIGNAL('customContextMenuRequested(const QPoint&)'), QPoint(50, i*5 + j - 1))
        
       -
       +    def edit_label(self, item, column):
       +        if column==self.edit_column and item.isSelected():
       +            text = unicode(item.text(column))
       +            tx_hash = str(item.data(0, Qt.UserRole).toString())
       +            self.is_edit = True
       +            if text == self.parent.wallet.get_default_label(tx_hash):
       +                item.setText(column, '')
       +            item.setFlags(Qt.ItemIsEditable|Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled)
       +            self.editItem(item, column)
       +            item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsDragEnabled)
       +            self.is_edit = False
       +
       +    def label_changed(self, item, column):
       +        if self.is_edit:
       +            return
       +        self.is_edit = True
       +        key = str(item.data(0, Qt.UserRole).toString())
       +        text = unicode(item.text(self.edit_column))
       +        changed = self.parent.wallet.set_label(key, text)
       +        if text:
       +            item.setForeground(self.edit_column, QBrush(QColor('black')))
       +        else:
       +            text = self.wallet.get_default_label(key)
       +            item.setText(self.edit_column, text)
       +            item.setForeground(self.edit_column, QBrush(QColor('gray')))
       +        self.is_edit = False
       +        if changed:
       +            self.parent.update_history_tab()
       +            self.parent.update_completions()
        
        
        if __name__ == "__main__":