qt history list: use OrderedDictWithIndex for txns
This commit is contained in:
parent
8bb930dd04
commit
65e8eef87f
@ -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']
|
||||
|
||||
@ -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…
Reference in New Issue
Block a user