mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-05-20 07:00:44 +02:00
Merge bitcoin-core/gui#509: Respect dialog modality and fix a regression in wallet unlock
f730bd7d58
scripted-diff: Rename ShowModalDialogAndDeleteOnClose (Hennadii Stepanov)5d7666b151
qt: Revert7fa91e8312
partially (Hennadii Stepanov)89c277a6fc
qt: Delay shutdown while a modal dialog is active (Hennadii Stepanov)8c0eb80f41
qt: Disable tray icon menu when a modal dialog is active (Hennadii Stepanov)92427354dd
qt, refactor: Use local QAction instances for the tray icon menu (Hennadii Stepanov)58e16035c1
qt, refactor: Drop BitcoinGUI::{send,receive}CoinsMenuAction members (Hennadii Stepanov)fd667e73cd
qt: Make show_hide_action dependent on the main window actual state (Hennadii Stepanov)ee151d0327
qt: Drop BitcoinGUI::toggleHideAction member (Hennadii Stepanov)78189daac8
qt, refactor: Fill up trayIconMenu before connections (Hennadii Stepanov)66afa286e5
qt, refactor: Replace BitcoinGUI::trayIconActivated with a lambda (Hennadii Stepanov)c3ca8364b2
qt, refactor: Replace BitcoinGUI::macosDockIconActivated with a lambda (Hennadii Stepanov) Pull request description: As pointed in bitcoin/bitcoin#23790 a regression in wallet unlock was introduced in bitcoin-core/gui#336 when a synchronous `AskPassphraseDialog` has been replaced with an asynchronous one. This PR reverts a call back to a synchronous mode. To make synchronous dialogs behave nice during shutdown some additional changes were made. Please note that disabling the tray icon menu when a modal dialog is active is useful itself as on master (4ad59042b3
) it is possible to switch to the "Receive" tab while the GUI is waiting for a password for the "Send" tab:  This is confusing and must be avoided. Fixes bitcoin/bitcoin#23790. ACKs for top commit: prayank23: tACKf730bd7d58
Tree-SHA512: 2b68275754190e4a9831b96e882d3c5b005e03909aeb6f2c5846da07199bb3efbb74ce87a9d25bb139f643c43d377a2051b221d553281fa5aefdd3181a58077f
This commit is contained in:
commit
1695d6661b
@ -189,7 +189,7 @@ void AddressBookPage::onEditAction()
|
||||
dlg->setModel(model);
|
||||
QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
|
||||
dlg->loadRow(origIndex.row());
|
||||
GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
|
||||
GUIUtil::ShowModalDialogAsynchronously(dlg);
|
||||
}
|
||||
|
||||
void AddressBookPage::on_newAddress_clicked()
|
||||
|
@ -268,7 +268,11 @@ void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
|
||||
connect(window, &BitcoinGUI::quitRequested, this, &BitcoinApplication::requestShutdown);
|
||||
|
||||
pollShutdownTimer = new QTimer(window);
|
||||
connect(pollShutdownTimer, &QTimer::timeout, window, &BitcoinGUI::detectShutdown);
|
||||
connect(pollShutdownTimer, &QTimer::timeout, [this]{
|
||||
if (!QApplication::activeModalWidget()) {
|
||||
window->detectShutdown();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
|
||||
|
@ -261,10 +261,6 @@ void BitcoinGUI::createActions()
|
||||
sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
|
||||
tabGroup->addAction(sendCoinsAction);
|
||||
|
||||
sendCoinsMenuAction = new QAction(sendCoinsAction->text(), this);
|
||||
sendCoinsMenuAction->setStatusTip(sendCoinsAction->statusTip());
|
||||
sendCoinsMenuAction->setToolTip(sendCoinsMenuAction->statusTip());
|
||||
|
||||
receiveCoinsAction = new QAction(platformStyle->SingleColorIcon(":/icons/receiving_addresses"), tr("&Receive"), this);
|
||||
receiveCoinsAction->setStatusTip(tr("Request payments (generates QR codes and bitcoin: URIs)"));
|
||||
receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip());
|
||||
@ -272,10 +268,6 @@ void BitcoinGUI::createActions()
|
||||
receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
|
||||
tabGroup->addAction(receiveCoinsAction);
|
||||
|
||||
receiveCoinsMenuAction = new QAction(receiveCoinsAction->text(), this);
|
||||
receiveCoinsMenuAction->setStatusTip(receiveCoinsAction->statusTip());
|
||||
receiveCoinsMenuAction->setToolTip(receiveCoinsMenuAction->statusTip());
|
||||
|
||||
historyAction = new QAction(platformStyle->SingleColorIcon(":/icons/history"), tr("&Transactions"), this);
|
||||
historyAction->setStatusTip(tr("Browse transaction history"));
|
||||
historyAction->setToolTip(historyAction->statusTip());
|
||||
@ -290,12 +282,8 @@ void BitcoinGUI::createActions()
|
||||
connect(overviewAction, &QAction::triggered, this, &BitcoinGUI::gotoOverviewPage);
|
||||
connect(sendCoinsAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
|
||||
connect(sendCoinsAction, &QAction::triggered, [this]{ gotoSendCoinsPage(); });
|
||||
connect(sendCoinsMenuAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
|
||||
connect(sendCoinsMenuAction, &QAction::triggered, [this]{ gotoSendCoinsPage(); });
|
||||
connect(receiveCoinsAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
|
||||
connect(receiveCoinsAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage);
|
||||
connect(receiveCoinsMenuAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
|
||||
connect(receiveCoinsMenuAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage);
|
||||
connect(historyAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
|
||||
connect(historyAction, &QAction::triggered, this, &BitcoinGUI::gotoHistoryPage);
|
||||
#endif // ENABLE_WALLET
|
||||
@ -315,8 +303,6 @@ void BitcoinGUI::createActions()
|
||||
optionsAction->setStatusTip(tr("Modify configuration options for %1").arg(PACKAGE_NAME));
|
||||
optionsAction->setMenuRole(QAction::PreferencesRole);
|
||||
optionsAction->setEnabled(false);
|
||||
toggleHideAction = new QAction(tr("&Show / Hide"), this);
|
||||
toggleHideAction->setStatusTip(tr("Show or hide the main Window"));
|
||||
|
||||
encryptWalletAction = new QAction(tr("&Encrypt Wallet…"), this);
|
||||
encryptWalletAction->setStatusTip(tr("Encrypt the private keys that belong to your wallet"));
|
||||
@ -376,7 +362,6 @@ void BitcoinGUI::createActions()
|
||||
connect(aboutAction, &QAction::triggered, this, &BitcoinGUI::aboutClicked);
|
||||
connect(aboutQtAction, &QAction::triggered, qApp, QApplication::aboutQt);
|
||||
connect(optionsAction, &QAction::triggered, this, &BitcoinGUI::optionsClicked);
|
||||
connect(toggleHideAction, &QAction::triggered, this, &BitcoinGUI::toggleHidden);
|
||||
connect(showHelpMessageAction, &QAction::triggered, this, &BitcoinGUI::showHelpMessageClicked);
|
||||
connect(openRPCConsoleAction, &QAction::triggered, this, &BitcoinGUI::showDebugWindow);
|
||||
// prevents an open debug window from becoming stuck/unusable on client shutdown
|
||||
@ -627,8 +612,6 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH
|
||||
trayIcon->setVisible(optionsModel->getShowTrayIcon());
|
||||
}
|
||||
} else {
|
||||
// Disable possibility to show main window via action
|
||||
toggleHideAction->setEnabled(false);
|
||||
if(trayIconMenu)
|
||||
{
|
||||
// Disable context menu on tray icon
|
||||
@ -752,9 +735,7 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
|
||||
{
|
||||
overviewAction->setEnabled(enabled);
|
||||
sendCoinsAction->setEnabled(enabled);
|
||||
sendCoinsMenuAction->setEnabled(enabled);
|
||||
receiveCoinsAction->setEnabled(enabled);
|
||||
receiveCoinsMenuAction->setEnabled(enabled);
|
||||
historyAction->setEnabled(enabled);
|
||||
encryptWalletAction->setEnabled(enabled);
|
||||
backupWalletAction->setEnabled(enabled);
|
||||
@ -784,57 +765,82 @@ void BitcoinGUI::createTrayIcon()
|
||||
void BitcoinGUI::createTrayIconMenu()
|
||||
{
|
||||
#ifndef Q_OS_MAC
|
||||
// return if trayIcon is unset (only on non-macOSes)
|
||||
if (!trayIcon)
|
||||
return;
|
||||
if (!trayIcon) return;
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
trayIcon->setContextMenu(trayIconMenu.get());
|
||||
connect(trayIcon, &QSystemTrayIcon::activated, this, &BitcoinGUI::trayIconActivated);
|
||||
#else
|
||||
// Note: On macOS, the Dock icon is used to provide the tray's functionality.
|
||||
MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance();
|
||||
connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, this, &BitcoinGUI::macosDockIconActivated);
|
||||
trayIconMenu->setAsDockMenu();
|
||||
#endif
|
||||
|
||||
// Configuration of the tray icon (or Dock icon) menu
|
||||
// Configuration of the tray icon (or Dock icon) menu.
|
||||
QAction* show_hide_action{nullptr};
|
||||
#ifndef Q_OS_MAC
|
||||
// Note: On macOS, the Dock icon's menu already has Show / Hide action.
|
||||
trayIconMenu->addAction(toggleHideAction);
|
||||
show_hide_action = trayIconMenu->addAction(QString(), this, &BitcoinGUI::toggleHidden);
|
||||
trayIconMenu->addSeparator();
|
||||
#endif
|
||||
if (enableWallet) {
|
||||
trayIconMenu->addAction(sendCoinsMenuAction);
|
||||
trayIconMenu->addAction(receiveCoinsMenuAction);
|
||||
trayIconMenu->addSeparator();
|
||||
trayIconMenu->addAction(signMessageAction);
|
||||
trayIconMenu->addAction(verifyMessageAction);
|
||||
trayIconMenu->addSeparator();
|
||||
}
|
||||
trayIconMenu->addAction(optionsAction);
|
||||
trayIconMenu->addAction(openRPCConsoleAction);
|
||||
#ifndef Q_OS_MAC // This is built-in on macOS
|
||||
trayIconMenu->addSeparator();
|
||||
trayIconMenu->addAction(quitAction);
|
||||
#endif
|
||||
}
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
|
||||
{
|
||||
if(reason == QSystemTrayIcon::Trigger)
|
||||
{
|
||||
// Click on system tray icon triggers show/hide of the main window
|
||||
toggleHidden();
|
||||
QAction* send_action{nullptr};
|
||||
QAction* receive_action{nullptr};
|
||||
QAction* sign_action{nullptr};
|
||||
QAction* verify_action{nullptr};
|
||||
if (enableWallet) {
|
||||
send_action = trayIconMenu->addAction(sendCoinsAction->text(), sendCoinsAction, &QAction::trigger);
|
||||
receive_action = trayIconMenu->addAction(receiveCoinsAction->text(), receiveCoinsAction, &QAction::trigger);
|
||||
trayIconMenu->addSeparator();
|
||||
sign_action = trayIconMenu->addAction(signMessageAction->text(), signMessageAction, &QAction::trigger);
|
||||
verify_action = trayIconMenu->addAction(verifyMessageAction->text(), verifyMessageAction, &QAction::trigger);
|
||||
trayIconMenu->addSeparator();
|
||||
}
|
||||
}
|
||||
QAction* options_action = trayIconMenu->addAction(optionsAction->text(), optionsAction, &QAction::trigger);
|
||||
options_action->setMenuRole(QAction::PreferencesRole);
|
||||
QAction* node_window_action = trayIconMenu->addAction(openRPCConsoleAction->text(), openRPCConsoleAction, &QAction::trigger);
|
||||
QAction* quit_action{nullptr};
|
||||
#ifndef Q_OS_MAC
|
||||
// Note: On macOS, the Dock icon's menu already has Quit action.
|
||||
trayIconMenu->addSeparator();
|
||||
quit_action = trayIconMenu->addAction(quitAction->text(), quitAction, &QAction::trigger);
|
||||
|
||||
trayIcon->setContextMenu(trayIconMenu.get());
|
||||
connect(trayIcon, &QSystemTrayIcon::activated, [this](QSystemTrayIcon::ActivationReason reason) {
|
||||
if (reason == QSystemTrayIcon::Trigger) {
|
||||
// Click on system tray icon triggers show/hide of the main window
|
||||
toggleHidden();
|
||||
}
|
||||
});
|
||||
#else
|
||||
void BitcoinGUI::macosDockIconActivated()
|
||||
{
|
||||
show();
|
||||
activateWindow();
|
||||
// Note: On macOS, the Dock icon is used to provide the tray's functionality.
|
||||
MacDockIconHandler* dockIconHandler = MacDockIconHandler::instance();
|
||||
connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, [this] {
|
||||
show();
|
||||
activateWindow();
|
||||
});
|
||||
trayIconMenu->setAsDockMenu();
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
connect(
|
||||
// Using QSystemTrayIcon::Context is not reliable.
|
||||
// See https://bugreports.qt.io/browse/QTBUG-91697
|
||||
trayIconMenu.get(), &QMenu::aboutToShow,
|
||||
[this, show_hide_action, send_action, receive_action, sign_action, verify_action, options_action, node_window_action, quit_action] {
|
||||
if (show_hide_action) show_hide_action->setText(
|
||||
(!isHidden() && !isMinimized() && !GUIUtil::isObscured(this)) ?
|
||||
tr("&Hide") :
|
||||
tr("S&how"));
|
||||
if (QApplication::activeModalWidget()) {
|
||||
for (QAction* a : trayIconMenu.get()->actions()) {
|
||||
a->setEnabled(false);
|
||||
}
|
||||
} else {
|
||||
if (show_hide_action) show_hide_action->setEnabled(true);
|
||||
if (enableWallet) {
|
||||
send_action->setEnabled(sendCoinsAction->isEnabled());
|
||||
receive_action->setEnabled(receiveCoinsAction->isEnabled());
|
||||
sign_action->setEnabled(signMessageAction->isEnabled());
|
||||
verify_action->setEnabled(verifyMessageAction->isEnabled());
|
||||
}
|
||||
options_action->setEnabled(optionsAction->isEnabled());
|
||||
node_window_action->setEnabled(openRPCConsoleAction->isEnabled());
|
||||
if (quit_action) quit_action->setEnabled(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
void BitcoinGUI::optionsClicked()
|
||||
{
|
||||
@ -847,7 +853,7 @@ void BitcoinGUI::aboutClicked()
|
||||
return;
|
||||
|
||||
auto dlg = new HelpMessageDialog(this, /* about */ true);
|
||||
GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
|
||||
GUIUtil::ShowModalDialogAsynchronously(dlg);
|
||||
}
|
||||
|
||||
void BitcoinGUI::showDebugWindow()
|
||||
@ -992,7 +998,7 @@ void BitcoinGUI::openOptionsDialogWithTab(OptionsDialog::Tab tab)
|
||||
connect(dlg, &OptionsDialog::quitOnReset, this, &BitcoinGUI::quitRequested);
|
||||
dlg->setCurrentTab(tab);
|
||||
dlg->setModel(clientModel->getOptionsModel());
|
||||
GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
|
||||
GUIUtil::ShowModalDialogAsynchronously(dlg);
|
||||
}
|
||||
|
||||
void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool header, SynchronizationState sync_state)
|
||||
|
@ -137,7 +137,6 @@ private:
|
||||
QAction* historyAction = nullptr;
|
||||
QAction* quitAction = nullptr;
|
||||
QAction* sendCoinsAction = nullptr;
|
||||
QAction* sendCoinsMenuAction = nullptr;
|
||||
QAction* usedSendingAddressesAction = nullptr;
|
||||
QAction* usedReceivingAddressesAction = nullptr;
|
||||
QAction* signMessageAction = nullptr;
|
||||
@ -146,9 +145,7 @@ private:
|
||||
QAction* m_load_psbt_clipboard_action = nullptr;
|
||||
QAction* aboutAction = nullptr;
|
||||
QAction* receiveCoinsAction = nullptr;
|
||||
QAction* receiveCoinsMenuAction = nullptr;
|
||||
QAction* optionsAction = nullptr;
|
||||
QAction* toggleHideAction = nullptr;
|
||||
QAction* encryptWalletAction = nullptr;
|
||||
QAction* backupWalletAction = nullptr;
|
||||
QAction* changePassphraseAction = nullptr;
|
||||
@ -302,13 +299,6 @@ public Q_SLOTS:
|
||||
void showDebugWindowActivateConsole();
|
||||
/** Show help message dialog */
|
||||
void showHelpMessageClicked();
|
||||
#ifndef Q_OS_MAC
|
||||
/** Handle tray icon clicked */
|
||||
void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
|
||||
#else
|
||||
/** Handle macOS Dock icon clicked */
|
||||
void macosDockIconActivated();
|
||||
#endif
|
||||
|
||||
/** Show window if hidden, unminimize when minimized, rise when obscured or show if hidden and fToggleHidden is true */
|
||||
void showNormalIfMinimized() { showNormalIfMinimized(false); }
|
||||
|
@ -984,7 +984,7 @@ void PrintSlotException(
|
||||
PrintExceptionContinue(exception, description.c_str());
|
||||
}
|
||||
|
||||
void ShowModalDialogAndDeleteOnClose(QDialog* dialog)
|
||||
void ShowModalDialogAsynchronously(QDialog* dialog)
|
||||
{
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
dialog->setWindowModality(Qt::ApplicationModal);
|
||||
|
@ -426,7 +426,7 @@ namespace GUIUtil
|
||||
/**
|
||||
* Shows a QDialog instance asynchronously, and deletes it on close.
|
||||
*/
|
||||
void ShowModalDialogAndDeleteOnClose(QDialog* dialog);
|
||||
void ShowModalDialogAsynchronously(QDialog* dialog);
|
||||
|
||||
inline bool IsEscapeOrBack(int key)
|
||||
{
|
||||
|
@ -930,7 +930,7 @@ void SendCoinsDialog::coinControlButtonClicked()
|
||||
{
|
||||
auto dlg = new CoinControlDialog(*m_coin_control, model, platformStyle);
|
||||
connect(dlg, &QDialog::finished, this, &SendCoinsDialog::coinControlUpdateLabels);
|
||||
GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
|
||||
GUIUtil::ShowModalDialogAsynchronously(dlg);
|
||||
}
|
||||
|
||||
// Coin Control: checkbox custom change address
|
||||
|
@ -511,7 +511,7 @@ void TransactionView::editLabel()
|
||||
: EditAddressDialog::EditSendingAddress, this);
|
||||
dlg->setModel(addressBook);
|
||||
dlg->loadRow(idx);
|
||||
GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
|
||||
GUIUtil::ShowModalDialogAsynchronously(dlg);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -520,7 +520,7 @@ void TransactionView::editLabel()
|
||||
this);
|
||||
dlg->setModel(addressBook);
|
||||
dlg->setAddress(address);
|
||||
GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
|
||||
GUIUtil::ShowModalDialogAsynchronously(dlg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ void WalletFrame::gotoLoadPSBT(bool from_clipboard)
|
||||
|
||||
auto dlg = new PSBTOperationsDialog(this, currentWalletModel(), clientModel);
|
||||
dlg->openWithPSBT(psbtx);
|
||||
GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
|
||||
GUIUtil::ShowModalDialogAsynchronously(dlg);
|
||||
}
|
||||
|
||||
void WalletFrame::encryptWallet()
|
||||
|
@ -208,7 +208,7 @@ void WalletView::encryptWallet()
|
||||
auto dlg = new AskPassphraseDialog(AskPassphraseDialog::Encrypt, this);
|
||||
dlg->setModel(walletModel);
|
||||
connect(dlg, &QDialog::finished, this, &WalletView::encryptionStatusChanged);
|
||||
GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
|
||||
GUIUtil::ShowModalDialogAsynchronously(dlg);
|
||||
}
|
||||
|
||||
void WalletView::backupWallet()
|
||||
@ -235,16 +235,18 @@ void WalletView::changePassphrase()
|
||||
{
|
||||
auto dlg = new AskPassphraseDialog(AskPassphraseDialog::ChangePass, this);
|
||||
dlg->setModel(walletModel);
|
||||
GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
|
||||
GUIUtil::ShowModalDialogAsynchronously(dlg);
|
||||
}
|
||||
|
||||
void WalletView::unlockWallet()
|
||||
{
|
||||
// Unlock wallet when requested by wallet model
|
||||
if (walletModel->getEncryptionStatus() == WalletModel::Locked) {
|
||||
auto dlg = new AskPassphraseDialog(AskPassphraseDialog::Unlock, this);
|
||||
dlg->setModel(walletModel);
|
||||
GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
|
||||
AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, this);
|
||||
dlg.setModel(walletModel);
|
||||
// A modal dialog must be synchronous here as expected
|
||||
// in the WalletModel::requestUnlock() function.
|
||||
dlg.exec();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user