Merge pull request #10467 from f321x/fix_10464

qt: MyTreeView: close menu if its context changes
This commit is contained in:
ghost43
2026-03-03 16:53:45 +00:00
committed by GitHub
8 changed files with 36 additions and 12 deletions
+7 -2
View File
@@ -100,6 +100,7 @@ class AddressList(MyTreeView):
editable_columns=[self.Columns.LABEL],
)
self.wallet = self.main_window.wallet
self._address_list_status = 0 # type: int
self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
self.setSortingEnabled(True)
self.show_change = AddressTypeFilter.ALL # type: AddressTypeFilter
@@ -186,9 +187,9 @@ class AddressList(MyTreeView):
self.proxy.setDynamicSortFilter(False) # temp. disable re-sorting after every change
self.std_model.clear()
self.refresh_headers()
fx = self.main_window.fx
set_address = None
num_shown = 0
new_address_list_status = 0
self.addresses_beyond_gap_limit = self.wallet.get_all_known_addresses_beyond_gap_limit()
for address in addr_list:
c, u, x = self.wallet.get_addr_balance(address)
@@ -203,6 +204,7 @@ class AddressList(MyTreeView):
if self.show_used == AddressUsageStateFilter.FUNDED_OR_UNUSED and is_used_and_empty:
continue
num_shown += 1
new_address_list_status = hash((new_address_list_status, address, c, u, x, is_used_and_empty))
labels = [""] * len(self.Columns)
labels[self.Columns.ADDRESS] = address
address_item = [QStandardItem(e) for e in labels]
@@ -239,6 +241,9 @@ class AddressList(MyTreeView):
self.showColumn(self.Columns.FIAT_BALANCE)
else:
self.hideColumn(self.Columns.FIAT_BALANCE)
if self._address_list_status != new_address_list_status:
self._address_list_status = new_address_list_status
self.close_menu()
self.filter()
self.proxy.setDynamicSortFilter(True)
# update counter
@@ -343,7 +348,7 @@ class AddressList(MyTreeView):
menu.addAction(_("Add to coin control"), lambda: self.main_window.utxo_list.add_to_coincontrol(coins))
run_hook('receive_menu', menu, addrs, self.wallet)
menu.exec(self.viewport().mapToGlobal(position))
self.open_menu(menu, position)
def place_text_on_clipboard(self, text: str, *, title: str = None) -> None:
if is_address(text):
+1 -1
View File
@@ -281,7 +281,7 @@ class ChannelsList(MyTreeView):
menu.addAction(_("Delete"), lambda: self.remove_channel_backup(channel_id))
else:
menu.addAction(_("Delete"), lambda: self.remove_channel(channel_id))
menu.exec(self.viewport().mapToGlobal(position))
self.open_menu(menu, position)
@QtCore.pyqtSlot(Abstract_Wallet, AbstractChannel)
def do_update_single_row(self, wallet: Abstract_Wallet, chan: AbstractChannel):
+1 -1
View File
@@ -101,7 +101,7 @@ class ContactList(MyTreeView):
menu.addAction(_("View on block explorer"), lambda: [webopen(u) for u in URLs])
run_hook('create_contact_menu', menu, selected_keys)
menu.exec(self.viewport().mapToGlobal(position))
self.open_menu(menu, position)
def update(self):
if self.maybe_defer_update():
+1 -1
View File
@@ -799,7 +799,7 @@ class HistoryList(MyTreeView, AcceptFileDragDrop):
menu_invs.addAction(_("View invoice"), lambda inv=inv: self.main_window.show_onchain_invoice(inv))
if tx_URL:
menu.addAction(_("View on block explorer"), lambda: webopen(tx_URL))
menu.exec(self.viewport().mapToGlobal(position))
self.open_menu(menu, position)
def remove_local_tx(self, tx_hash: str):
num_child_txs = len(self.wallet.adb.get_depending_transactions(tx_hash))
+1 -1
View File
@@ -195,7 +195,7 @@ class InvoiceList(MyTreeView):
if log:
menu.addAction(_("View log"), lambda: self.show_log(key, log))
menu.addAction(_("Delete"), lambda: self.delete_invoices([key]))
menu.exec(self.viewport().mapToGlobal(position))
self.open_menu(menu, position)
def show_log(self, key, log: Sequence[HtlcLog]):
d = WindowModalDialog(self, _("Payment log"))
+14
View File
@@ -256,12 +256,26 @@ class MyTreeView(QTreeView):
self._pending_update = False
self._forced_update = False
self._currently_open_menu = None # type: Optional[QMenu]
self._default_bg_brush = QStandardItem().background()
self.proxy = None # history, and address tabs use a proxy
def create_menu(self, position: QPoint) -> None:
pass
def open_menu(self, menu: QMenu, position) -> None:
try:
self._currently_open_menu = menu
menu.exec(self.viewport().mapToGlobal(position))
finally:
self._currently_open_menu = None
def close_menu(self):
if self._currently_open_menu:
self._currently_open_menu.close()
self._currently_open_menu = None
def set_editability(self, items):
for idx, i in enumerate(items):
i.setEditable(idx in self.editable_columns)
+1 -1
View File
@@ -209,7 +209,7 @@ class RequestList(MyTreeView):
# menu.addAction(_("View in web browser"), lambda: webopen(req['view_url']))
menu.addAction(_("Delete"), lambda: self.delete_requests([key]))
run_hook('receive_list_menu', self.main_window, menu, key)
menu.exec(self.viewport().mapToGlobal(position))
self.open_menu(menu, position)
def delete_requests(self, keys):
self.wallet.delete_requests(keys)
+10 -5
View File
@@ -230,12 +230,17 @@ class UTXOList(MyTreeView):
return copy.deepcopy(utxos) # copy so that side-effects don't affect utxo_dict
def _maybe_reset_coincontrol(self, current_wallet_utxos: Sequence[PartialTxInput]) -> None:
if not bool(self._spend_set):
if not self._spend_set and not self._currently_open_menu:
return
# if we spent one of the selected UTXOs, just reset selection
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]):
self._spend_set.clear()
if self._currently_open_menu:
# if we spent one of the qt-highlighted UTXOs, close context-menu
if not all(prevout_str in utxo_set for prevout_str in self.get_selected_outpoints()):
self.close_menu()
if self._spend_set:
# if we spent one of the green-marked UTXOs, just reset selection
if not all([prevout_str in utxo_set for prevout_str in self._spend_set]):
self._spend_set.clear()
def can_swap_coins(self, coins):
# fixme: min and max_amounts are known only after first request
@@ -369,7 +374,7 @@ class UTXOList(MyTreeView):
act.setToolTip(MSG_FREEZE_ADDRESS)
run_hook('qt_utxo_menu', menu, coins, self.wallet)
menu.exec(self.viewport().mapToGlobal(position))
self.open_menu(menu, position)
def get_filter_data_from_coordinate(self, row, col):
if col == self.Columns.OUTPOINT: