gui simplification

This commit is contained in:
ThomasV 2015-04-04 20:59:57 +02:00
parent b8a72180c7
commit 93250b1041
3 changed files with 158 additions and 89 deletions

100
gui/qt/history_widget.py Normal file
View File

@ -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))

View File

@ -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)
@ -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
@ -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([])
@ -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)
@ -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', {})

View File

@ -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
@ -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__":