aboutsummaryrefslogtreecommitdiff
path: root/src/qt
diff options
context:
space:
mode:
authorHennadii Stepanov <32963518+hebasto@users.noreply.github.com>2022-02-15 08:32:59 +0200
committerHennadii Stepanov <32963518+hebasto@users.noreply.github.com>2022-02-15 08:38:57 +0200
commit1695d6661bf25d82694774011164ddbfbfb51fdd (patch)
treed9de4820f9cbf68e724cc0c04263126d4f859041 /src/qt
parent8fe6f5a6fbcd8083d916cb630f35f8f5980d6825 (diff)
parentf730bd7d580502ae3c3b5953ada3724b59f5cd9b (diff)
Merge bitcoin-core/gui#509: Respect dialog modality and fix a regression in wallet unlock
f730bd7d580502ae3c3b5953ada3724b59f5cd9b scripted-diff: Rename ShowModalDialogAndDeleteOnClose (Hennadii Stepanov) 5d7666b15164a16aaf3af49af8f73ff4bd392f6a qt: Revert 7fa91e831227e556bd8a7ae3da64bd59d4f30d5f partially (Hennadii Stepanov) 89c277a6fca1149f10f8b55874c702c341679765 qt: Delay shutdown while a modal dialog is active (Hennadii Stepanov) 8c0eb80f41bca7b08c94de0f08692fac23e3e9f0 qt: Disable tray icon menu when a modal dialog is active (Hennadii Stepanov) 92427354dd5f80cb5c042e7afbcd386968161be4 qt, refactor: Use local QAction instances for the tray icon menu (Hennadii Stepanov) 58e16035c1fc513fce0b09e02c7d863c63ec990d qt, refactor: Drop BitcoinGUI::{send,receive}CoinsMenuAction members (Hennadii Stepanov) fd667e73cd109bbfc14011f8c2c08556648b4c50 qt: Make show_hide_action dependent on the main window actual state (Hennadii Stepanov) ee151d032789fa03daa44ab44dd0fd70e51b145c qt: Drop BitcoinGUI::toggleHideAction member (Hennadii Stepanov) 78189daac8d13870ab6ed8421b9ed067cf7ebac5 qt, refactor: Fill up trayIconMenu before connections (Hennadii Stepanov) 66afa286e519deda2fcfd580f190b7af13407e72 qt, refactor: Replace BitcoinGUI::trayIconActivated with a lambda (Hennadii Stepanov) c3ca8364b2a8de8c73ecc0c7eed9608bd30e7e02 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 (4ad59042b359f473d5888ecee0c9288dcf98f1c9) it is possible to switch to the "Receive" tab while the GUI is waiting for a password for the "Send" tab: ![Screenshot from 2021-12-17 18-59-51](https://user-images.githubusercontent.com/32963518/146580710-0a755f24-a166-414b-be60-7863232ac778.png) This is confusing and must be avoided. Fixes bitcoin/bitcoin#23790. ACKs for top commit: prayank23: tACK https://github.com/bitcoin-core/gui/pull/509/commits/f730bd7d580502ae3c3b5953ada3724b59f5cd9b Tree-SHA512: 2b68275754190e4a9831b96e882d3c5b005e03909aeb6f2c5846da07199bb3efbb74ce87a9d25bb139f643c43d377a2051b221d553281fa5aefdd3181a58077f
Diffstat (limited to 'src/qt')
-rw-r--r--src/qt/addressbookpage.cpp2
-rw-r--r--src/qt/bitcoin.cpp6
-rw-r--r--src/qt/bitcoingui.cpp126
-rw-r--r--src/qt/bitcoingui.h10
-rw-r--r--src/qt/guiutil.cpp2
-rw-r--r--src/qt/guiutil.h2
-rw-r--r--src/qt/sendcoinsdialog.cpp2
-rw-r--r--src/qt/transactionview.cpp4
-rw-r--r--src/qt/walletframe.cpp2
-rw-r--r--src/qt/walletview.cpp12
10 files changed, 85 insertions, 83 deletions
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index a180b03c08..d59a4345f3 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -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()
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 6a2781079c..eb31287c56 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -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)
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 0baacfe58c..7c22880dd1 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -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;
-
- 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
+ if (!trayIcon) return;
+#endif // Q_OS_MAC
- // 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
+#endif // Q_OS_MAC
+
+ QAction* send_action{nullptr};
+ QAction* receive_action{nullptr};
+ QAction* sign_action{nullptr};
+ QAction* verify_action{nullptr};
if (enableWallet) {
- trayIconMenu->addAction(sendCoinsMenuAction);
- trayIconMenu->addAction(receiveCoinsMenuAction);
+ send_action = trayIconMenu->addAction(sendCoinsAction->text(), sendCoinsAction, &QAction::trigger);
+ receive_action = trayIconMenu->addAction(receiveCoinsAction->text(), receiveCoinsAction, &QAction::trigger);
trayIconMenu->addSeparator();
- trayIconMenu->addAction(signMessageAction);
- trayIconMenu->addAction(verifyMessageAction);
+ sign_action = trayIconMenu->addAction(signMessageAction->text(), signMessageAction, &QAction::trigger);
+ verify_action = trayIconMenu->addAction(verifyMessageAction->text(), verifyMessageAction, &QAction::trigger);
trayIconMenu->addSeparator();
}
- trayIconMenu->addAction(optionsAction);
- trayIconMenu->addAction(openRPCConsoleAction);
-#ifndef Q_OS_MAC // This is built-in on macOS
+ 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();
- trayIconMenu->addAction(quitAction);
-#endif
-}
+ quit_action = trayIconMenu->addAction(quitAction->text(), quitAction, &QAction::trigger);
-#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();
- }
-}
+ 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)
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 658ab5a210..0ae5f7331e 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -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); }
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index dc73bcd911..9565fa508f 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -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);
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 9b25b77325..0224b18b4e 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -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)
{
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index e37168830e..579ef0c3fd 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -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
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index 1ab1333b72..778ef04b77 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -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);
}
}
}
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index 08190f0b9f..91ce420a33 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -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()
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index 7954a66995..e7ec54721a 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -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();
}
}