|
|
|
@ -58,7 +58,7 @@ class UTXOList(MyTreeView): |
|
|
|
super().__init__(parent, self.create_menu, |
|
|
|
super().__init__(parent, self.create_menu, |
|
|
|
stretch_column=self.Columns.LABEL, |
|
|
|
stretch_column=self.Columns.LABEL, |
|
|
|
editable_columns=[]) |
|
|
|
editable_columns=[]) |
|
|
|
self._spend_set = set() # type: Set[str] # coins selected by the user to spend from |
|
|
|
self._spend_set = None # type: Optional[Set[str]] # coins selected by the user to spend from |
|
|
|
self.setModel(QStandardItemModel(self)) |
|
|
|
self.setModel(QStandardItemModel(self)) |
|
|
|
self.setSelectionMode(QAbstractItemView.ExtendedSelection) |
|
|
|
self.setSelectionMode(QAbstractItemView.ExtendedSelection) |
|
|
|
self.setSortingEnabled(True) |
|
|
|
self.setSortingEnabled(True) |
|
|
|
@ -75,12 +75,12 @@ class UTXOList(MyTreeView): |
|
|
|
self.insert_utxo(idx, utxo) |
|
|
|
self.insert_utxo(idx, utxo) |
|
|
|
self.filter() |
|
|
|
self.filter() |
|
|
|
# update coincontrol status bar |
|
|
|
# update coincontrol status bar |
|
|
|
coins = [self.utxo_dict[x] for x in self._spend_set] or utxos |
|
|
|
if self._spend_set is not None: |
|
|
|
coins = self._filter_frozen_coins(coins) |
|
|
|
coins = [self.utxo_dict[x] for x in self._spend_set] |
|
|
|
amount = sum(x.value_sats() for x in coins) |
|
|
|
coins = self._filter_frozen_coins(coins) |
|
|
|
amount_str = self.parent.format_amount_and_units(amount) |
|
|
|
amount = sum(x.value_sats() for x in coins) |
|
|
|
num_outputs_str = _("{} outputs available ({} total)").format(len(coins), len(utxos)) |
|
|
|
amount_str = self.parent.format_amount_and_units(amount) |
|
|
|
if self._spend_set: |
|
|
|
num_outputs_str = _("{} outputs available ({} total)").format(len(coins), len(utxos)) |
|
|
|
self.parent.set_coincontrol_msg(_("Coin control active") + f': {num_outputs_str}, {amount_str}') |
|
|
|
self.parent.set_coincontrol_msg(_("Coin control active") + f': {num_outputs_str}, {amount_str}') |
|
|
|
else: |
|
|
|
else: |
|
|
|
self.parent.set_coincontrol_msg(None) |
|
|
|
self.parent.set_coincontrol_msg(None) |
|
|
|
@ -101,7 +101,7 @@ class UTXOList(MyTreeView): |
|
|
|
utxo_item[self.Columns.OUTPOINT].setFont(QFont(MONOSPACE_FONT)) |
|
|
|
utxo_item[self.Columns.OUTPOINT].setFont(QFont(MONOSPACE_FONT)) |
|
|
|
utxo_item[self.Columns.ADDRESS].setData(name, Qt.UserRole) |
|
|
|
utxo_item[self.Columns.ADDRESS].setData(name, Qt.UserRole) |
|
|
|
SELECTED_TO_SPEND_TOOLTIP = _('Coin selected to be spent') |
|
|
|
SELECTED_TO_SPEND_TOOLTIP = _('Coin selected to be spent') |
|
|
|
if name in self._spend_set: |
|
|
|
if name in (self._spend_set or set()): |
|
|
|
for col in utxo_item: |
|
|
|
for col in utxo_item: |
|
|
|
col.setBackground(ColorScheme.GREEN.as_color(True)) |
|
|
|
col.setBackground(ColorScheme.GREEN.as_color(True)) |
|
|
|
if col != self.Columns.OUTPOINT: |
|
|
|
if col != self.Columns.OUTPOINT: |
|
|
|
@ -113,7 +113,7 @@ class UTXOList(MyTreeView): |
|
|
|
utxo_item[self.Columns.OUTPOINT].setBackground(ColorScheme.BLUE.as_color(True)) |
|
|
|
utxo_item[self.Columns.OUTPOINT].setBackground(ColorScheme.BLUE.as_color(True)) |
|
|
|
utxo_item[self.Columns.OUTPOINT].setToolTip(f"{name}\n{_('Coin is frozen')}") |
|
|
|
utxo_item[self.Columns.OUTPOINT].setToolTip(f"{name}\n{_('Coin is frozen')}") |
|
|
|
else: |
|
|
|
else: |
|
|
|
tooltip = ("\n" + SELECTED_TO_SPEND_TOOLTIP) if name in self._spend_set else "" |
|
|
|
tooltip = ("\n" + SELECTED_TO_SPEND_TOOLTIP) if name in (self._spend_set or set()) else "" |
|
|
|
utxo_item[self.Columns.OUTPOINT].setToolTip(name + tooltip) |
|
|
|
utxo_item[self.Columns.OUTPOINT].setToolTip(name + tooltip) |
|
|
|
self.model().insertRow(idx, utxo_item) |
|
|
|
self.model().insertRow(idx, utxo_item) |
|
|
|
|
|
|
|
|
|
|
|
@ -121,8 +121,6 @@ class UTXOList(MyTreeView): |
|
|
|
if not self.model(): |
|
|
|
if not self.model(): |
|
|
|
return None |
|
|
|
return None |
|
|
|
items = self.selected_in_column(self.Columns.ADDRESS) |
|
|
|
items = self.selected_in_column(self.Columns.ADDRESS) |
|
|
|
if not items: |
|
|
|
|
|
|
|
return None |
|
|
|
|
|
|
|
return [x.data(Qt.UserRole) for x in items] |
|
|
|
return [x.data(Qt.UserRole) for x in items] |
|
|
|
|
|
|
|
|
|
|
|
def _filter_frozen_coins(self, coins: List[PartialTxInput]) -> List[PartialTxInput]: |
|
|
|
def _filter_frozen_coins(self, coins: List[PartialTxInput]) -> List[PartialTxInput]: |
|
|
|
@ -131,29 +129,39 @@ class UTXOList(MyTreeView): |
|
|
|
not self.wallet.is_frozen_coin(utxo))] |
|
|
|
not self.wallet.is_frozen_coin(utxo))] |
|
|
|
return coins |
|
|
|
return coins |
|
|
|
|
|
|
|
|
|
|
|
def set_spend_list(self, coins: List[PartialTxInput]): |
|
|
|
def set_spend_list(self, coins: Optional[List[PartialTxInput]]): |
|
|
|
coins = self._filter_frozen_coins(coins) |
|
|
|
if coins is not None: |
|
|
|
self._spend_set = {utxo.prevout.to_str() for utxo in coins} |
|
|
|
coins = self._filter_frozen_coins(coins) |
|
|
|
|
|
|
|
self._spend_set = {utxo.prevout.to_str() for utxo in coins} |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
self._spend_set = None |
|
|
|
self.update() |
|
|
|
self.update() |
|
|
|
|
|
|
|
|
|
|
|
def get_spend_list(self) -> Sequence[PartialTxInput]: |
|
|
|
def get_spend_list(self) -> Optional[Sequence[PartialTxInput]]: |
|
|
|
|
|
|
|
if self._spend_set is None: |
|
|
|
|
|
|
|
return None |
|
|
|
return [self.utxo_dict[x] for x in self._spend_set] |
|
|
|
return [self.utxo_dict[x] for x in self._spend_set] |
|
|
|
|
|
|
|
|
|
|
|
def _maybe_reset_spend_list(self, current_wallet_utxos: Sequence[PartialTxInput]) -> None: |
|
|
|
def _maybe_reset_spend_list(self, current_wallet_utxos: Sequence[PartialTxInput]) -> None: |
|
|
|
|
|
|
|
if self._spend_set is None: |
|
|
|
|
|
|
|
return |
|
|
|
# if we spent one of the selected UTXOs, just reset selection |
|
|
|
# if we spent one of the selected UTXOs, just reset selection |
|
|
|
utxo_set = {utxo.prevout.to_str() for utxo in current_wallet_utxos} |
|
|
|
utxo_set = {utxo.prevout.to_str() for utxo in current_wallet_utxos} |
|
|
|
if not all([prevout_str in utxo_set for prevout_str in self._spend_set]): |
|
|
|
if not all([prevout_str in utxo_set for prevout_str in self._spend_set]): |
|
|
|
self._spend_set = set() |
|
|
|
self._spend_set = None |
|
|
|
|
|
|
|
|
|
|
|
def create_menu(self, position): |
|
|
|
def create_menu(self, position): |
|
|
|
selected = self.get_selected_outpoints() |
|
|
|
selected = self.get_selected_outpoints() |
|
|
|
if not selected: |
|
|
|
if selected is None: |
|
|
|
return |
|
|
|
return |
|
|
|
menu = QMenu() |
|
|
|
menu = QMenu() |
|
|
|
menu.setSeparatorsCollapsible(True) # consecutive separators are merged together |
|
|
|
menu.setSeparatorsCollapsible(True) # consecutive separators are merged together |
|
|
|
coins = [self.utxo_dict[name] for name in selected] |
|
|
|
coins = [self.utxo_dict[name] for name in selected] |
|
|
|
menu.addAction(_("Spend"), lambda: self.set_spend_list(coins)) |
|
|
|
if len(coins) == 0: |
|
|
|
assert len(coins) >= 1, len(coins) |
|
|
|
menu.addAction(_("Spend (select none)"), lambda: self.set_spend_list(coins)) |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
menu.addAction(_("Spend"), lambda: self.set_spend_list(coins)) |
|
|
|
|
|
|
|
|
|
|
|
if len(coins) == 1: |
|
|
|
if len(coins) == 1: |
|
|
|
utxo = coins[0] |
|
|
|
utxo = coins[0] |
|
|
|
addr = utxo.address |
|
|
|
addr = utxo.address |
|
|
|
@ -184,8 +192,7 @@ class UTXOList(MyTreeView): |
|
|
|
menu.addAction(_("Address is frozen"), lambda: None).setEnabled(False) |
|
|
|
menu.addAction(_("Address is frozen"), lambda: None).setEnabled(False) |
|
|
|
menu.addAction(_("Unfreeze Address"), lambda: self.parent.set_frozen_state_of_addresses([addr], False)) |
|
|
|
menu.addAction(_("Unfreeze Address"), lambda: self.parent.set_frozen_state_of_addresses([addr], False)) |
|
|
|
menu.addSeparator() |
|
|
|
menu.addSeparator() |
|
|
|
else: |
|
|
|
elif len(coins) > 1: # multiple items selected |
|
|
|
# multiple items selected |
|
|
|
|
|
|
|
menu.addSeparator() |
|
|
|
menu.addSeparator() |
|
|
|
addrs = [utxo.address for utxo in coins] |
|
|
|
addrs = [utxo.address for utxo in coins] |
|
|
|
is_coin_frozen = [self.wallet.is_frozen_coin(utxo) for utxo in coins] |
|
|
|
is_coin_frozen = [self.wallet.is_frozen_coin(utxo) for utxo in coins] |
|
|
|
|