Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Respect dialog modality and fix a regression in wallet unlock #509

Merged
merged 11 commits into from
Feb 15, 2022
Merged
2 changes: 1 addition & 1 deletion src/qt/addressbookpage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
6 changes: 5 additions & 1 deletion src/qt/bitcoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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]{
Copy link
Member

@Sjors Sjors Feb 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cda881a : on macOS when I'm in coin control, before and after this commit, Command + Q is ignored (not delayed). Same with Stop from the tray menu. (that's fine by the way, a delayed shutdown seems confusing)

But when I hit ctrl + c in the terminal, before this commit it would shut QT down, with this commit it indeed delays the shutdown until the dialog is closed. (that's also fine, because this method of shutdown is probably only used by developers)

if (!QApplication::activeModalWidget()) {
window->detectShutdown();
}
});
}

void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
Expand Down
126 changes: 66 additions & 60 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,21 +261,13 @@ 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());
receiveCoinsAction->setCheckable(true);
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());
Expand All @@ -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
Expand All @@ -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"));
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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"));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fd667e7: you may want to delay this keyboard shortcut, because we're past the translation cut-off?

if (QApplication::activeModalWidget()) {
for (QAction* a : trayIconMenu.get()->actions()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

97692af: I don't see any difference in behavior on macOS; before and after this commit, if I open coin selection, it disables everything except the macOS standard items (Options, Show all windows, Hide, Stop)

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()
{
Expand All @@ -847,7 +853,7 @@ void BitcoinGUI::aboutClicked()
return;

auto dlg = new HelpMessageDialog(this, /* about */ true);
GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
GUIUtil::ShowModalDialogAsynchronously(dlg);
}

void BitcoinGUI::showDebugWindow()
Expand Down Expand Up @@ -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)
Expand Down
10 changes: 0 additions & 10 deletions src/qt/bitcoingui.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ class BitcoinGUI : public QMainWindow
QAction* historyAction = nullptr;
QAction* quitAction = nullptr;
QAction* sendCoinsAction = nullptr;
QAction* sendCoinsMenuAction = nullptr;
QAction* usedSendingAddressesAction = nullptr;
QAction* usedReceivingAddressesAction = nullptr;
QAction* signMessageAction = nullptr;
Expand All @@ -146,9 +145,7 @@ class BitcoinGUI : public QMainWindow
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;
Expand Down Expand Up @@ -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); }
Expand Down
2 changes: 1 addition & 1 deletion src/qt/guiutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/qt/guiutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
2 changes: 1 addition & 1 deletion src/qt/sendcoinsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/qt/transactionview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ void TransactionView::editLabel()
: EditAddressDialog::EditSendingAddress, this);
dlg->setModel(addressBook);
dlg->loadRow(idx);
GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
GUIUtil::ShowModalDialogAsynchronously(dlg);
}
else
{
Expand All @@ -520,7 +520,7 @@ void TransactionView::editLabel()
this);
dlg->setModel(addressBook);
dlg->setAddress(address);
GUIUtil::ShowModalDialogAndDeleteOnClose(dlg);
GUIUtil::ShowModalDialogAsynchronously(dlg);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/qt/walletframe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
12 changes: 7 additions & 5 deletions src/qt/walletview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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();
}
}

Expand Down