Browse Source

qt history list: use OrderedDictWithIndex for txns

master
SomberNight 7 years ago
parent
commit
65e8eef87f
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
  1. 54
      electrum/gui/qt/history_list.py
  2. 26
      electrum/util.py

54
electrum/gui/qt/history_list.py

@ -32,7 +32,7 @@ import threading
from electrum.address_synchronizer import TX_HEIGHT_LOCAL
from electrum.i18n import _
from electrum.util import (block_explorer_URL, profiler, print_error, TxMinedInfo,
PrintError)
OrderedDictWithIndex, PrintError)
from .util import *
@ -71,14 +71,16 @@ class HistorySortModel(QSortFilterProxyModel):
class HistoryModel(QAbstractItemModel, PrintError):
NUM_COLUMNS = 8
def __init__(self, parent):
super().__init__(parent)
self.parent = parent
self.transactions = []
self.transactions = OrderedDictWithIndex()
self.tx_status_cache = {} # type: Dict[str, Tuple[int, str]]
def columnCount(self, parent: QModelIndex):
return 8
return self.NUM_COLUMNS
def rowCount(self, parent: QModelIndex):
return len(self.transactions)
@ -92,15 +94,15 @@ class HistoryModel(QAbstractItemModel, PrintError):
# assert self.checkIndex(index, indexIsValid)
assert index.isValid()
col = index.column()
tx_item = self.transactions[index.row()]
tx_item = self.transactions.value_from_pos(index.row())
tx_hash = tx_item['txid']
conf = tx_item['confirmations']
txpos = tx_item['txpos_in_block'] or 0
try:
status, status_str = self.tx_status_cache[tx_hash]
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)
tx_mined_info = self.tx_mined_info_from_tx_item(tx_item)
status, status_str = self.parent.wallet.get_tx_status(tx_hash, tx_mined_info)
if role == Qt.UserRole:
# for sorting
d = {
@ -164,7 +166,7 @@ class HistoryModel(QAbstractItemModel, PrintError):
return not index.isValid()
def update_label(self, row):
tx_item = self.transactions[row]
tx_item = self.transactions.value_from_pos(row)
tx_item['label'] = self.parent.wallet.get_label(tx_item['txid'])
topLeft = bottomRight = self.createIndex(row, 2)
self.dataChanged.emit(topLeft, bottomRight, [Qt.DisplayRole])
@ -183,7 +185,7 @@ class HistoryModel(QAbstractItemModel, PrintError):
fx = self.parent.fx
if fx: fx.history_used_spot = False
r = self.parent.wallet.get_full_history(domain=self.get_domain(), from_timestamp=None, to_timestamp=None, fx=fx)
if r['transactions'] == self.transactions:
if r['transactions'] == list(self.transactions.values()):
return
old_length = len(self.transactions)
if old_length != 0:
@ -191,7 +193,9 @@ class HistoryModel(QAbstractItemModel, PrintError):
self.transactions.clear()
self.endRemoveRows()
self.beginInsertRows(QModelIndex(), 0, len(r['transactions'])-1)
self.transactions = r['transactions']
for tx_item in r['transactions']:
txid = tx_item['txid']
self.transactions[txid] = tx_item
self.endInsertRows()
if selected_row:
self.parent.history_list.selectionModel().select(self.createIndex(selected_row, 0), QItemSelectionModel.Rows | QItemSelectionModel.SelectCurrent)
@ -204,18 +208,15 @@ class HistoryModel(QAbstractItemModel, PrintError):
start_date = date.today()
end_date = date.today()
if len(self.transactions) > 0:
start_date = self.transactions[0].get('date') or start_date
end_date = self.transactions[-1].get('date') or end_date
start_date = self.transactions.value_from_pos(0).get('date') or start_date
end_date = self.transactions.value_from_pos(len(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.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']
tx_mined_status = TxMinedInfo(height=tx_item['height'],
conf=tx_item['confirmations'],
timestamp=tx_item['timestamp'])
self.tx_status_cache[txid] = self.parent.wallet.get_tx_status(txid, tx_mined_status)
for txid, tx_item in self.transactions.items():
tx_mined_info = self.tx_mined_info_from_tx_item(tx_item)
self.tx_status_cache[txid] = self.parent.wallet.get_tx_status(txid, tx_mined_info)
history = self.parent.fx.show_history()
cap_gains = self.parent.fx.get_history_capital_gains_config()
@ -235,7 +236,7 @@ class HistoryModel(QAbstractItemModel, PrintError):
hide(7)
def update_fiat(self, row, idx):
tx_item = self.transactions[row]
tx_item = self.transactions.value_from_pos(row)
key = tx_item['txid']
fee = tx_item.get('fee')
value = tx_item['value'].value
@ -276,12 +277,19 @@ class HistoryModel(QAbstractItemModel, PrintError):
extra_flags |= Qt.ItemIsEditable
return super().flags(idx) | extra_flags
@staticmethod
def tx_mined_info_from_tx_item(tx_item):
tx_mined_info = TxMinedInfo(height=tx_item['height'],
conf=tx_item['confirmations'],
timestamp=tx_item['timestamp'])
return tx_mined_info
class HistoryList(MyTreeView, AcceptFileDragDrop):
filter_columns = [1, 2, 3] # Date, Description, Amount
def tx_item_from_proxy_row(self, proxy_row):
hm_idx = self.model().mapToSource(self.model().index(proxy_row, 0))
return self.hm.transactions[hm_idx.row()]
return self.hm.transactions.value_from_pos(hm_idx.row())
def should_hide(self, proxy_row):
if self.start_timestamp and self.end_timestamp:
@ -439,7 +447,7 @@ class HistoryList(MyTreeView, AcceptFileDragDrop):
_("Perhaps some dependencies are missing...") + " (matplotlib?)")
return
try:
plt = plot_history(list(self.transactions.values()))
plt = plot_history(list(self.hm.transactions.values()))
plt.show()
except NothingToPlotException as e:
self.parent.show_message(str(e))
@ -447,7 +455,7 @@ class HistoryList(MyTreeView, AcceptFileDragDrop):
def on_edited(self, index, user_role, text):
index = self.model().mapToSource(index)
row, column = index.row(), index.column()
tx_item = self.hm.transactions[row]
tx_item = self.hm.transactions.value_from_pos(row)
key = tx_item['txid']
# fixme
if column == 2:
@ -485,7 +493,7 @@ class HistoryList(MyTreeView, AcceptFileDragDrop):
if not idx.isValid():
# can happen e.g. before list is populated for the first time
return
tx_item = self.hm.transactions[idx.row()]
tx_item = self.hm.transactions.value_from_pos(idx.row())
column = idx.column()
if column == 0:
column_title = _('Transaction ID')
@ -614,5 +622,5 @@ class HistoryList(MyTreeView, AcceptFileDragDrop):
def text_txid_from_coordinate(self, row, col):
idx = self.model().mapToSource(self.model().index(row, col))
tx_item = self.hm.transactions[idx.row()]
tx_item = self.hm.transactions.value_from_pos(idx.row())
return self.hm.data(idx, Qt.DisplayRole).value(), tx_item['txid']

26
electrum/util.py

@ -1010,46 +1010,54 @@ class OrderedDictWithIndex(OrderedDict):
def __init__(self):
super().__init__()
self._key_to_pos = {}
self._pos_to_key = {}
def _recalc_key_to_pos(self):
def _recalc_index(self):
self._key_to_pos = {key: pos for (pos, key) in enumerate(self.keys())}
self._pos_to_key = {pos: key for (pos, key) in enumerate(self.keys())}
def get_pos_of_key(self, key):
def pos_from_key(self, key):
return self._key_to_pos[key]
def value_from_pos(self, pos):
key = self._pos_to_key[pos]
return self[key]
def popitem(self, *args, **kwargs):
ret = super().popitem(*args, **kwargs)
self._recalc_key_to_pos()
self._recalc_index()
return ret
def move_to_end(self, *args, **kwargs):
ret = super().move_to_end(*args, **kwargs)
self._recalc_key_to_pos()
self._recalc_index()
return ret
def clear(self):
ret = super().clear()
self._recalc_key_to_pos()
self._recalc_index()
return ret
def pop(self, *args, **kwargs):
ret = super().pop(*args, **kwargs)
self._recalc_key_to_pos()
self._recalc_index()
return ret
def update(self, *args, **kwargs):
ret = super().update(*args, **kwargs)
self._recalc_key_to_pos()
self._recalc_index()
return ret
def __delitem__(self, *args, **kwargs):
ret = super().__delitem__(*args, **kwargs)
self._recalc_key_to_pos()
self._recalc_index()
return ret
def __setitem__(self, key, *args, **kwargs):
is_new_key = key not in self
ret = super().__setitem__(key, *args, **kwargs)
if is_new_key:
self._key_to_pos[key] = len(self) - 1
pos = len(self) - 1
self._key_to_pos[key] = pos
self._pos_to_key[pos] = key
return ret

Loading…
Cancel
Save