Browse Source

qt history list: performance optimisations

3.3.3.1
SomberNight 6 years ago
parent
commit
1c0c21159b
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 58
      electrum/gui/qt/history_list.py
  2. 2
      electrum/gui/qt/main_window.py

58
electrum/gui/qt/history_list.py

@ -26,7 +26,7 @@
import webbrowser import webbrowser
import datetime import datetime
from datetime import date from datetime import date
from typing import TYPE_CHECKING from typing import TYPE_CHECKING, Tuple, Dict
from electrum.address_synchronizer import TX_HEIGHT_LOCAL from electrum.address_synchronizer import TX_HEIGHT_LOCAL
from electrum.i18n import _ from electrum.i18n import _
@ -72,6 +72,7 @@ class HistoryModel(QAbstractItemModel):
super().__init__(parent) super().__init__(parent)
self.parent = parent self.parent = parent
self.transactions = [] self.transactions = []
self.tx_status_cache = {} # type: Dict[str, Tuple[int, str]]
def columnCount(self, parent: QModelIndex): def columnCount(self, parent: QModelIndex):
return 8 return 8
@ -79,25 +80,27 @@ class HistoryModel(QAbstractItemModel):
def rowCount(self, parent: QModelIndex): def rowCount(self, parent: QModelIndex):
return len(self.transactions) return len(self.transactions)
def index(self, row: int, column: int, parent : QModelIndex): def index(self, row: int, column: int, parent: QModelIndex):
return self.createIndex(row,column) return self.createIndex(row, column)
def data(self, index: QModelIndex, role: Qt.ItemDataRole): def data(self, index: QModelIndex, role: Qt.ItemDataRole):
# requires PyQt5 5.11 # requires PyQt5 5.11
# indexIsValid = QAbstractItemModel.CheckIndexOptions(QAbstractItemModel.CheckIndexOption.IndexIsValid.value) # indexIsValid = QAbstractItemModel.CheckIndexOptions(QAbstractItemModel.CheckIndexOption.IndexIsValid.value)
# assert self.checkIndex(index, indexIsValid) # assert self.checkIndex(index, indexIsValid)
assert index.isValid() assert index.isValid()
col = index.column()
tx_item = self.transactions[index.row()] tx_item = self.transactions[index.row()]
tx_hash = tx_item['txid'] tx_hash = tx_item['txid']
height = tx_item['height']
conf = tx_item['confirmations'] conf = tx_item['confirmations']
timestamp = tx_item['timestamp'] try:
tx_mined_info = TxMinedInfo(height=height, conf=conf, timestamp=timestamp) status, status_str = self.tx_status_cache[tx_hash]
status, status_str = self.parent.wallet.get_tx_status(tx_hash, tx_mined_info) except KeyError:
tx_mined_status = TxMinedInfo(height=tx_item['height'], conf=conf, timestamp=tx_item['timestamp'])
status, status_str = self.parent.wallet.get_tx_status(tx_hash, tx_mined_status)
if role == Qt.UserRole: if role == Qt.UserRole:
# for sorting # for sorting
d = { d = {
0: (status, conf), 0: (status, conf), # FIXME tx_pos needed as tie-breaker
1: status_str, 1: status_str,
2: tx_item['label'], 2: tx_item['label'],
3: tx_item['value'].value, 3: tx_item['value'].value,
@ -106,46 +109,46 @@ class HistoryModel(QAbstractItemModel):
6: tx_item['acquisition_price'].value if 'acquisition_price' in tx_item else None, 6: tx_item['acquisition_price'].value if 'acquisition_price' in tx_item else None,
7: tx_item['capital_gain'].value if 'capital_gain' in tx_item else None, 7: tx_item['capital_gain'].value if 'capital_gain' in tx_item else None,
} }
return QVariant(d[index.column()]) return QVariant(d[col])
if role not in (Qt.DisplayRole, Qt.EditRole): if role not in (Qt.DisplayRole, Qt.EditRole):
if index.column() == 0 and role == Qt.DecorationRole: if col == 0 and role == Qt.DecorationRole:
return QVariant(self.parent.history_list.icon_cache.get(":icons/" + TX_ICONS[status])) return QVariant(self.parent.history_list.icon_cache.get(":icons/" + TX_ICONS[status]))
elif index.column() == 0 and role == Qt.ToolTipRole: elif col == 0 and role == Qt.ToolTipRole:
return QVariant(str(conf) + _(" confirmation" + ("s" if conf != 1 else ""))) return QVariant(str(conf) + _(" confirmation" + ("s" if conf != 1 else "")))
elif index.column() > 2 and role == Qt.TextAlignmentRole: elif col > 2 and role == Qt.TextAlignmentRole:
return QVariant(Qt.AlignRight | Qt.AlignVCenter) return QVariant(Qt.AlignRight | Qt.AlignVCenter)
elif index.column() != 1 and role == Qt.FontRole: elif col != 1 and role == Qt.FontRole:
monospace_font = QFont(MONOSPACE_FONT) monospace_font = QFont(MONOSPACE_FONT)
return QVariant(monospace_font) return QVariant(monospace_font)
elif index.column() == 2 and role == Qt.DecorationRole and self.parent.wallet.invoices.paid.get(tx_hash): elif col == 2 and role == Qt.DecorationRole and self.parent.wallet.invoices.paid.get(tx_hash):
return QVariant(self.parent.history_list.icon_cache.get(":icons/seal")) return QVariant(self.parent.history_list.icon_cache.get(":icons/seal"))
elif index.column() in (2, 3) and role == Qt.ForegroundRole and tx_item['value'].value < 0: elif col in (2, 3) and role == Qt.ForegroundRole and tx_item['value'].value < 0:
red_brush = QBrush(QColor("#BC1E1E")) red_brush = QBrush(QColor("#BC1E1E"))
return QVariant(red_brush) return QVariant(red_brush)
elif index.column() == 5 and role == Qt.ForegroundRole and not tx_item.get('fiat_default') and tx_item.get('fiat_value') is not None: elif col == 5 and role == Qt.ForegroundRole and not tx_item.get('fiat_default') and tx_item.get('fiat_value') is not None:
blue_brush = QBrush(QColor("#1E1EFF")) blue_brush = QBrush(QColor("#1E1EFF"))
return QVariant(blue_brush) return QVariant(blue_brush)
return None return None
if index.column() == 1: if col == 1:
return QVariant(status_str) return QVariant(status_str)
elif index.column() == 2: elif col == 2:
return QVariant(tx_item['label']) return QVariant(tx_item['label'])
elif index.column() == 3: elif col == 3:
value = tx_item['value'].value value = tx_item['value'].value
v_str = self.parent.format_amount(value, is_diff=True, whitespaces=True) v_str = self.parent.format_amount(value, is_diff=True, whitespaces=True)
return QVariant(v_str) return QVariant(v_str)
elif index.column() == 4: elif col == 4:
balance = tx_item['balance'].value balance = tx_item['balance'].value
balance_str = self.parent.format_amount(balance, whitespaces=True) balance_str = self.parent.format_amount(balance, whitespaces=True)
return QVariant(balance_str) return QVariant(balance_str)
elif index.column() == 5 and 'fiat_value' in tx_item: elif col == 5 and 'fiat_value' in tx_item:
value_str = self.parent.fx.format_fiat(tx_item['fiat_value'].value) value_str = self.parent.fx.format_fiat(tx_item['fiat_value'].value)
return QVariant(value_str) return QVariant(value_str)
elif index.column() == 6 and tx_item['value'].value < 0 and 'acquisition_price' in tx_item: elif col == 6 and tx_item['value'].value < 0 and 'acquisition_price' in tx_item:
# fixme: should use is_mine # fixme: should use is_mine
acq = tx_item['acquisition_price'].value acq = tx_item['acquisition_price'].value
return QVariant(self.parent.fx.format_fiat(acq)) return QVariant(self.parent.fx.format_fiat(acq))
elif index.column() == 7 and 'capital_gain' in tx_item: elif col == 7 and 'capital_gain' in tx_item:
cg = tx_item['capital_gain'].value cg = tx_item['capital_gain'].value
return QVariant(self.parent.fx.format_fiat(cg)) return QVariant(self.parent.fx.format_fiat(cg))
return None return None
@ -199,6 +202,15 @@ class HistoryModel(QAbstractItemModel):
end_date = self.transactions[-1].get('date') or end_date end_date = self.transactions[-1].get('date') or end_date
self.parent.history_list.years = [str(i) for i in range(start_date.year, end_date.year + 1)] self.parent.history_list.years = [str(i) for i in range(start_date.year, end_date.year + 1)]
self.parent.history_list.period_combo.insertItems(1, self.parent.history_list.years) self.parent.history_list.period_combo.insertItems(1, self.parent.history_list.years)
# update tx_status_cache
self.tx_status_cache.clear()
for tx_item in self.transactions:
txid = tx_item['txid']
height = tx_item['height']
conf = tx_item['confirmations']
timestamp = tx_item['timestamp']
tx_mined_status = TxMinedInfo(height=height, conf=conf, timestamp=timestamp)
self.tx_status_cache[txid] = self.parent.wallet.get_tx_status(txid, tx_mined_status)
history = self.parent.fx.show_history() history = self.parent.fx.show_history()
cap_gains = self.parent.fx.get_history_capital_gains_config() cap_gains = self.parent.fx.get_history_capital_gains_config()

2
electrum/gui/qt/main_window.py

@ -345,7 +345,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
self.console.showMessage(args[0]) self.console.showMessage(args[0])
elif event == 'verified': elif event == 'verified':
wallet, tx_hash, tx_mined_status = args wallet, tx_hash, tx_mined_status = args
if wallet == self.wallet: if wallet == self.wallet and wallet.up_to_date:
self.history_model.update_item(tx_hash, tx_mined_status) self.history_model.update_item(tx_hash, tx_mined_status)
elif event == 'fee': elif event == 'fee':
if self.config.is_dynfee(): if self.config.is_dynfee():

Loading…
Cancel
Save