Bitcoin Core  31.0.0
P2P Digital Currency
bitcoingui.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-present The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <bitcoin-build-config.h> // IWYU pragma: keep
6 
7 #include <qt/bitcoingui.h>
8 
9 #include <qt/bitcoinunits.h>
10 #include <qt/clientmodel.h>
11 #include <qt/createwalletdialog.h>
12 #include <qt/guiconstants.h>
13 #include <qt/guiutil.h>
14 #include <qt/modaloverlay.h>
15 #include <qt/networkstyle.h>
16 #include <qt/notificator.h>
17 #include <qt/openuridialog.h>
18 #include <qt/optionsdialog.h>
19 #include <qt/optionsmodel.h>
20 #include <qt/platformstyle.h>
21 #include <qt/rpcconsole.h>
22 #include <qt/utilitydialog.h>
23 
24 #ifdef ENABLE_WALLET
25 #include <qt/walletcontroller.h>
26 #include <qt/walletframe.h>
27 #include <qt/walletmodel.h>
28 #include <qt/walletview.h>
29 #endif // ENABLE_WALLET
30 
31 #ifdef Q_OS_MACOS
32 #include <qt/macdockiconhandler.h>
33 #endif
34 
35 #include <chain.h>
36 #include <chainparams.h>
37 #include <common/system.h>
38 #include <interfaces/handler.h>
39 #include <interfaces/node.h>
40 #include <node/interface_ui.h>
41 #include <util/translation.h>
42 #include <validation.h>
43 
44 #include <QAction>
45 #include <QActionGroup>
46 #include <QApplication>
47 #include <QComboBox>
48 #include <QCursor>
49 #include <QDateTime>
50 #include <QDragEnterEvent>
51 #include <QInputDialog>
52 #include <QKeySequence>
53 #include <QListWidget>
54 #include <QMenu>
55 #include <QMenuBar>
56 #include <QMessageBox>
57 #include <QMimeData>
58 #include <QProgressDialog>
59 #include <QScreen>
60 #include <QSettings>
61 #include <QShortcut>
62 #include <QStackedWidget>
63 #include <QStatusBar>
64 #include <QStyle>
65 #include <QSystemTrayIcon>
66 #include <QTimer>
67 #include <QToolBar>
68 #include <QUrlQuery>
69 #include <QVBoxLayout>
70 #include <QWindow>
71 
72 
79 static constexpr int64_t MAX_BLOCK_TIME_GAP = 90 * 60;
80 
81 const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
82 #if defined(Q_OS_MACOS)
83  "macosx"
84 #elif defined(Q_OS_WIN)
85  "windows"
86 #else
87  "other"
88 #endif
89  ;
90 
91 BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
92  QMainWindow(parent),
93  m_node(node),
94  trayIconMenu{new QMenu()},
95  platformStyle(_platformStyle),
96  m_network_style(networkStyle)
97 {
98  QSettings settings;
99  if (!restoreGeometry(settings.value("MainWindowGeometry").toByteArray())) {
100  // Restore failed (perhaps missing setting), center the window
101  move(QGuiApplication::primaryScreen()->availableGeometry().center() - frameGeometry().center());
102  }
103 
104  setContextMenuPolicy(Qt::PreventContextMenu);
105 
106 #ifdef ENABLE_WALLET
107  enableWallet = WalletModel::isWalletEnabled();
108 #endif // ENABLE_WALLET
109  QApplication::setWindowIcon(m_network_style->getTrayAndWindowIcon());
110  setWindowIcon(m_network_style->getTrayAndWindowIcon());
111  updateWindowTitle();
112 
113  rpcConsole = new RPCConsole(node, _platformStyle, nullptr);
114  helpMessageDialog = new HelpMessageDialog(this, false);
115 #ifdef ENABLE_WALLET
116  if(enableWallet)
117  {
119  walletFrame = new WalletFrame(_platformStyle, this);
121  connect(walletFrame, &WalletFrame::message, [this](const QString& title, const QString& message, unsigned int style) {
122  this->message(title, message, style);
123  });
124  connect(walletFrame, &WalletFrame::currentWalletSet, [this] { updateWalletStatus(); });
125  setCentralWidget(walletFrame);
126  } else
127 #endif // ENABLE_WALLET
128  {
129  /* When compiled without wallet or -disablewallet is provided,
130  * the central widget is the rpc console.
131  */
132  setCentralWidget(rpcConsole);
133  Q_EMIT consoleShown(rpcConsole);
134  }
135 
136  modalOverlay = new ModalOverlay(enableWallet, this->centralWidget());
137 
138  // Accept D&D of URIs
139  setAcceptDrops(true);
140 
141  // Create actions for the toolbar, menu bar and tray/dock icon
142  // Needs walletFrame to be initialized
143  createActions();
144 
145  // Create application menu bar
146  createMenuBar();
147 
148  // Create the toolbars
149  createToolBars();
150 
151  // Create system tray icon and notification
152  if (QSystemTrayIcon::isSystemTrayAvailable()) {
153  createTrayIcon();
154  }
155  notificator = new Notificator(QApplication::applicationName(), trayIcon, this);
156 
157  // Create status bar
158  statusBar();
159 
160  // Disable size grip because it looks ugly and nobody needs it
161  statusBar()->setSizeGripEnabled(false);
162 
163  // Status bar notification icons
164  QFrame *frameBlocks = new QFrame();
165  frameBlocks->setContentsMargins(0,0,0,0);
166  frameBlocks->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
167  QHBoxLayout *frameBlocksLayout = new QHBoxLayout(frameBlocks);
168  frameBlocksLayout->setContentsMargins(3,0,3,0);
169  frameBlocksLayout->setSpacing(3);
170  unitDisplayControl = new UnitDisplayStatusBarControl(platformStyle);
171  labelWalletEncryptionIcon = new GUIUtil::ThemedLabel(platformStyle);
172  labelWalletHDStatusIcon = new GUIUtil::ThemedLabel(platformStyle);
173  labelProxyIcon = new GUIUtil::ClickableLabel(platformStyle);
174  connectionsControl = new GUIUtil::ClickableLabel(platformStyle);
175  labelBlocksIcon = new GUIUtil::ClickableLabel(platformStyle);
176  if(enableWallet)
177  {
178  frameBlocksLayout->addStretch();
179  frameBlocksLayout->addWidget(unitDisplayControl);
180  frameBlocksLayout->addStretch();
181  frameBlocksLayout->addWidget(labelWalletEncryptionIcon);
182  labelWalletEncryptionIcon->hide();
183  frameBlocksLayout->addWidget(labelWalletHDStatusIcon);
184  labelWalletHDStatusIcon->hide();
185  }
186  frameBlocksLayout->addWidget(labelProxyIcon);
187  frameBlocksLayout->addStretch();
188  frameBlocksLayout->addWidget(connectionsControl);
189  frameBlocksLayout->addStretch();
190  frameBlocksLayout->addWidget(labelBlocksIcon);
191  frameBlocksLayout->addStretch();
192 
193  // Progress bar and label for blocks download
194  progressBarLabel = new QLabel();
195  progressBarLabel->setVisible(false);
196  progressBar = new GUIUtil::ProgressBar();
197  progressBar->setAlignment(Qt::AlignCenter);
198  progressBar->setVisible(false);
199 
200  // Override style sheet for progress bar for styles that have a segmented progress bar,
201  // as they make the text unreadable (workaround for issue #1071)
202  // See https://doc.qt.io/qt-5/gallery.html
203  QString curStyle = QApplication::style()->metaObject()->className();
204  if(curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle")
205  {
206  progressBar->setStyleSheet("QProgressBar { background-color: #e8e8e8; border: 1px solid grey; border-radius: 7px; padding: 1px; text-align: center; } QProgressBar::chunk { background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #FF8000, stop: 1 orange); border-radius: 7px; margin: 0px; }");
207  }
208 
209  statusBar()->addWidget(progressBarLabel);
210  statusBar()->addWidget(progressBar);
211  statusBar()->addPermanentWidget(frameBlocks);
212 
213  // Install event filter to be able to catch status tip events (QEvent::StatusTip)
214  this->installEventFilter(this);
215 
216  // Initially wallet actions should be disabled
217  setWalletActionsEnabled(false);
218 
219  // Subscribe to notifications from core
220  subscribeToCoreSignals();
221 
222  connect(labelProxyIcon, &GUIUtil::ClickableLabel::clicked, [this] {
223  openOptionsDialogWithTab(OptionsDialog::TAB_NETWORK);
224  });
225 
226  connect(labelBlocksIcon, &GUIUtil::ClickableLabel::clicked, this, &BitcoinGUI::showModalOverlay);
228 
229 #ifdef Q_OS_MACOS
230  m_app_nap_inhibitor = new CAppNapInhibitor;
231 #endif
232 
234 }
235 
237 {
238  // Unsubscribe from notifications from core
240 
241  QSettings settings;
242  settings.setValue("MainWindowGeometry", saveGeometry());
243  if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu)
244  trayIcon->hide();
245 #ifdef Q_OS_MACOS
246  delete m_app_nap_inhibitor;
248 #endif
249 
250  delete rpcConsole;
251 }
252 
254 {
255  QActionGroup *tabGroup = new QActionGroup(this);
256  connect(modalOverlay, &ModalOverlay::triggered, tabGroup, &QActionGroup::setEnabled);
257 
258  overviewAction = new QAction(platformStyle->SingleColorIcon(":/icons/overview"), tr("&Overview"), this);
259  overviewAction->setStatusTip(tr("Show general overview of wallet"));
260  overviewAction->setToolTip(overviewAction->statusTip());
261  overviewAction->setCheckable(true);
262  overviewAction->setShortcut(QKeySequence(QStringLiteral("Alt+1")));
263  tabGroup->addAction(overviewAction);
264 
265  sendCoinsAction = new QAction(platformStyle->SingleColorIcon(":/icons/send"), tr("&Send"), this);
266  sendCoinsAction->setStatusTip(tr("Send coins to a Bitcoin address"));
267  sendCoinsAction->setToolTip(sendCoinsAction->statusTip());
268  sendCoinsAction->setCheckable(true);
269  sendCoinsAction->setShortcut(QKeySequence(QStringLiteral("Alt+2")));
270  tabGroup->addAction(sendCoinsAction);
271 
272  receiveCoinsAction = new QAction(platformStyle->SingleColorIcon(":/icons/receiving_addresses"), tr("&Receive"), this);
273  receiveCoinsAction->setStatusTip(tr("Request payments (generates QR codes and bitcoin: URIs)"));
274  receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip());
275  receiveCoinsAction->setCheckable(true);
276  receiveCoinsAction->setShortcut(QKeySequence(QStringLiteral("Alt+3")));
277  tabGroup->addAction(receiveCoinsAction);
278 
279  historyAction = new QAction(platformStyle->SingleColorIcon(":/icons/history"), tr("&Transactions"), this);
280  historyAction->setStatusTip(tr("Browse transaction history"));
281  historyAction->setToolTip(historyAction->statusTip());
282  historyAction->setCheckable(true);
283  historyAction->setShortcut(QKeySequence(QStringLiteral("Alt+4")));
284  tabGroup->addAction(historyAction);
285 
286 #ifdef ENABLE_WALLET
287  // These showNormalIfMinimized are needed because Send Coins and Receive Coins
288  // can be triggered from the tray menu, and need to show the GUI to be useful.
289  connect(overviewAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
290  connect(overviewAction, &QAction::triggered, this, &BitcoinGUI::gotoOverviewPage);
291  connect(sendCoinsAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
292  connect(sendCoinsAction, &QAction::triggered, [this]{ gotoSendCoinsPage(); });
293  connect(receiveCoinsAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
294  connect(receiveCoinsAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage);
295  connect(historyAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
296  connect(historyAction, &QAction::triggered, this, &BitcoinGUI::gotoHistoryPage);
297 #endif // ENABLE_WALLET
298 
299  quitAction = new QAction(tr("E&xit"), this);
300  quitAction->setStatusTip(tr("Quit application"));
301  quitAction->setShortcut(QKeySequence(tr("Ctrl+Q")));
302  quitAction->setMenuRole(QAction::QuitRole);
303  aboutAction = new QAction(tr("&About %1").arg(CLIENT_NAME), this);
304  aboutAction->setStatusTip(tr("Show information about %1").arg(CLIENT_NAME));
305  aboutAction->setMenuRole(QAction::AboutRole);
306  aboutAction->setEnabled(false);
307  aboutQtAction = new QAction(tr("About &Qt"), this);
308  aboutQtAction->setStatusTip(tr("Show information about Qt"));
309  aboutQtAction->setMenuRole(QAction::AboutQtRole);
310  optionsAction = new QAction(tr("&Options…"), this);
311  optionsAction->setStatusTip(tr("Modify configuration options for %1").arg(CLIENT_NAME));
312  optionsAction->setMenuRole(QAction::PreferencesRole);
313  optionsAction->setEnabled(false);
314 
315  encryptWalletAction = new QAction(tr("&Encrypt Wallet…"), this);
316  encryptWalletAction->setStatusTip(tr("Encrypt the private keys that belong to your wallet"));
317  encryptWalletAction->setCheckable(true);
318  backupWalletAction = new QAction(tr("&Backup Wallet…"), this);
319  backupWalletAction->setStatusTip(tr("Backup wallet to another location"));
320  changePassphraseAction = new QAction(tr("&Change Passphrase…"), this);
321  changePassphraseAction->setStatusTip(tr("Change the passphrase used for wallet encryption"));
322  signMessageAction = new QAction(tr("Sign &message…"), this);
323  signMessageAction->setStatusTip(tr("Sign messages with your Bitcoin addresses to prove you own them"));
324  verifyMessageAction = new QAction(tr("&Verify message…"), this);
325  verifyMessageAction->setStatusTip(tr("Verify messages to ensure they were signed with specified Bitcoin addresses"));
326  m_load_psbt_action = new QAction(tr("&Load PSBT from file…"), this);
327  m_load_psbt_action->setStatusTip(tr("Load Partially Signed Bitcoin Transaction"));
328  m_load_psbt_clipboard_action = new QAction(tr("Load PSBT from &clipboard…"), this);
329  m_load_psbt_clipboard_action->setStatusTip(tr("Load Partially Signed Bitcoin Transaction from clipboard"));
330 
331  openRPCConsoleAction = new QAction(tr("Node window"), this);
332  openRPCConsoleAction->setStatusTip(tr("Open node debugging and diagnostic console"));
333  // initially disable the debug window menu item
334  openRPCConsoleAction->setEnabled(false);
335  openRPCConsoleAction->setObjectName("openRPCConsoleAction");
336 
337  usedSendingAddressesAction = new QAction(tr("&Sending addresses"), this);
338  usedSendingAddressesAction->setStatusTip(tr("Show the list of used sending addresses and labels"));
339  usedReceivingAddressesAction = new QAction(tr("&Receiving addresses"), this);
340  usedReceivingAddressesAction->setStatusTip(tr("Show the list of used receiving addresses and labels"));
341 
342  openAction = new QAction(tr("Open &URI…"), this);
343  openAction->setStatusTip(tr("Open a bitcoin: URI"));
344 
345  m_open_wallet_action = new QAction(tr("Open Wallet"), this);
346  m_open_wallet_action->setEnabled(false);
347  m_open_wallet_action->setStatusTip(tr("Open a wallet"));
348  m_open_wallet_menu = new QMenu(this);
349 
350  m_close_wallet_action = new QAction(tr("Close Wallet…"), this);
351  m_close_wallet_action->setStatusTip(tr("Close wallet"));
352 
353  m_create_wallet_action = new QAction(tr("Create Wallet…"), this);
354  m_create_wallet_action->setEnabled(false);
355  m_create_wallet_action->setStatusTip(tr("Create a new wallet"));
356 
357  //: Name of the menu item that restores wallet from a backup file.
358  m_restore_wallet_action = new QAction(tr("Restore Wallet…"), this);
359  m_restore_wallet_action->setEnabled(false);
360  //: Status tip for Restore Wallet menu item
361  m_restore_wallet_action->setStatusTip(tr("Restore a wallet from a backup file"));
362 
363  m_close_all_wallets_action = new QAction(tr("Close All Wallets…"), this);
364  m_close_all_wallets_action->setStatusTip(tr("Close all wallets"));
365 
366  m_migrate_wallet_action = new QAction(tr("Migrate Wallet"), this);
367  m_migrate_wallet_action->setEnabled(false);
368  m_migrate_wallet_action->setStatusTip(tr("Migrate a wallet"));
369  m_migrate_wallet_menu = new QMenu(this);
370 
371  showHelpMessageAction = new QAction(tr("&Command-line options"), this);
372  showHelpMessageAction->setMenuRole(QAction::NoRole);
373  showHelpMessageAction->setStatusTip(tr("Show the %1 help message to get a list with possible Bitcoin command-line options").arg(CLIENT_NAME));
374 
375  m_mask_values_action = new QAction(tr("&Mask values"), this);
376  m_mask_values_action->setShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_M));
377  m_mask_values_action->setStatusTip(tr("Mask the values in the Overview tab"));
378  m_mask_values_action->setCheckable(true);
379 
380  connect(quitAction, &QAction::triggered, this, &BitcoinGUI::quitRequested);
381  connect(aboutAction, &QAction::triggered, this, &BitcoinGUI::aboutClicked);
382  connect(aboutQtAction, &QAction::triggered, qApp, QApplication::aboutQt);
383  connect(optionsAction, &QAction::triggered, this, &BitcoinGUI::optionsClicked);
384  connect(showHelpMessageAction, &QAction::triggered, this, &BitcoinGUI::showHelpMessageClicked);
385  connect(openRPCConsoleAction, &QAction::triggered, this, &BitcoinGUI::showDebugWindow);
386  // prevents an open debug window from becoming stuck/unusable on client shutdown
387  connect(quitAction, &QAction::triggered, rpcConsole, &QWidget::hide);
388 
389 #ifdef ENABLE_WALLET
390  if(walletFrame)
391  {
392  connect(encryptWalletAction, &QAction::triggered, walletFrame, &WalletFrame::encryptWallet);
393  connect(backupWalletAction, &QAction::triggered, walletFrame, &WalletFrame::backupWallet);
394  connect(changePassphraseAction, &QAction::triggered, walletFrame, &WalletFrame::changePassphrase);
395  connect(signMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
396  connect(signMessageAction, &QAction::triggered, [this]{ gotoSignMessageTab(); });
397  connect(m_load_psbt_action, &QAction::triggered, [this]{ gotoLoadPSBT(); });
398  connect(m_load_psbt_clipboard_action, &QAction::triggered, [this]{ gotoLoadPSBT(true); });
399  connect(verifyMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
400  connect(verifyMessageAction, &QAction::triggered, [this]{ gotoVerifyMessageTab(); });
403  connect(openAction, &QAction::triggered, this, &BitcoinGUI::openClicked);
404  connect(m_open_wallet_menu, &QMenu::aboutToShow, [this] {
405  m_open_wallet_menu->clear();
406  for (const auto& [path, info] : m_wallet_controller->listWalletDir()) {
407  const auto& [loaded, format] = info;
408  QString name = GUIUtil::WalletDisplayName(path);
409  // An single ampersand in the menu item's text sets a shortcut for this item.
410  // Single & are shown when && is in the string. So replace & with &&.
411  name.replace(QChar('&'), QString("&&"));
412  bool is_legacy = format == "bdb";
413  if (is_legacy) {
414  name += " (needs migration)";
415  }
416  QAction* action = m_open_wallet_menu->addAction(name);
417 
418  if (loaded || is_legacy) {
419  // This wallet is already loaded or it is a legacy wallet
420  action->setEnabled(false);
421  continue;
422  }
423 
424  connect(action, &QAction::triggered, [this, path] {
425  auto activity = new OpenWalletActivity(m_wallet_controller, this);
426  connect(activity, &OpenWalletActivity::opened, this, &BitcoinGUI::setCurrentWallet, Qt::QueuedConnection);
427  connect(activity, &OpenWalletActivity::opened, rpcConsole, &RPCConsole::setCurrentWallet, Qt::QueuedConnection);
428  activity->open(path);
429  });
430  }
431  if (m_open_wallet_menu->isEmpty()) {
432  QAction* action = m_open_wallet_menu->addAction(tr("No wallets available"));
433  action->setEnabled(false);
434  }
435  });
436  connect(m_restore_wallet_action, &QAction::triggered, [this] {
437  //: Name of the wallet data file format.
438  QString name_data_file = tr("Wallet Data");
439 
440  //: The title for Restore Wallet File Windows
441  QString title_windows = tr("Load Wallet Backup");
442 
443  QString backup_file = GUIUtil::getOpenFileName(this, title_windows, QString(), name_data_file + QLatin1String(" (*.dat)"), nullptr);
444  if (backup_file.isEmpty()) return;
445 
446  bool wallet_name_ok;
447  /*: Title of pop-up window shown when the user is attempting to
448  restore a wallet. */
449  QString title = tr("Restore Wallet");
450  //: Label of the input field where the name of the wallet is entered.
451  QString label = tr("Wallet Name");
452  QString wallet_name = QInputDialog::getText(this, title, label, QLineEdit::Normal, "", &wallet_name_ok);
453  if (!wallet_name_ok) return;
454  if (wallet_name.isEmpty()) {
455  QMessageBox::critical(nullptr, tr("Invalid Wallet Name"), tr("Wallet name cannot be empty"));
456  return;
457  }
458 
459  auto activity = new RestoreWalletActivity(m_wallet_controller, this);
460  connect(activity, &RestoreWalletActivity::restored, this, &BitcoinGUI::setCurrentWallet, Qt::QueuedConnection);
461  connect(activity, &RestoreWalletActivity::restored, rpcConsole, &RPCConsole::setCurrentWallet, Qt::QueuedConnection);
462 
463  auto backup_file_path = fs::PathFromString(backup_file.toStdString());
464  activity->restore(backup_file_path, wallet_name.toStdString());
465  });
466  connect(m_close_wallet_action, &QAction::triggered, [this] {
468  });
469  connect(m_create_wallet_action, &QAction::triggered, this, &BitcoinGUI::createWallet);
470  connect(m_close_all_wallets_action, &QAction::triggered, [this] {
472  });
473  connect(m_migrate_wallet_menu, &QMenu::aboutToShow, [this] {
474  m_migrate_wallet_menu->clear();
475  for (const auto& [wallet_name, info] : m_wallet_controller->listWalletDir()) {
476  const auto& [loaded, format] = info;
477 
478  if (format != "bdb") { // Skip already migrated wallets
479  continue;
480  }
481 
482  QString name = GUIUtil::WalletDisplayName(wallet_name);
483  // An single ampersand in the menu item's text sets a shortcut for this item.
484  // Single & are shown when && is in the string. So replace & with &&.
485  name.replace(QChar('&'), QString("&&"));
486  QAction* action = m_migrate_wallet_menu->addAction(name);
487 
488  connect(action, &QAction::triggered, [this, wallet_name] {
489  auto activity = new MigrateWalletActivity(m_wallet_controller, this);
490  connect(activity, &MigrateWalletActivity::migrated, this, &BitcoinGUI::setCurrentWallet);
491  activity->migrate(wallet_name);
492  });
493  }
494  if (m_migrate_wallet_menu->isEmpty()) {
495  QAction* action = m_migrate_wallet_menu->addAction(tr("No wallets available"));
496  action->setEnabled(false);
497  }
498  m_migrate_wallet_menu->addSeparator();
499  QAction* restore_migrate_file_action = m_migrate_wallet_menu->addAction(tr("Restore and Migrate Wallet File…"));
500  restore_migrate_file_action->setEnabled(true);
501 
502  connect(restore_migrate_file_action, &QAction::triggered, [this] {
503  QString name_data_file = tr("Wallet Data");
504  QString title_windows = tr("Restore and Migrate Wallet Backup");
505 
506  QString backup_file = GUIUtil::getOpenFileName(this, title_windows, QString(), name_data_file + QLatin1String(" (*.dat)"), nullptr);
507  if (backup_file.isEmpty()) return;
508 
509  bool wallet_name_ok;
510  /*: Title of pop-up window shown when the user is attempting to
511  restore a wallet. */
512  QString title = tr("Restore and Migrate Wallet");
513  //: Label of the input field where the name of the wallet is entered.
514  QString label = tr("Wallet Name");
515  QString wallet_name = QInputDialog::getText(this, title, label, QLineEdit::Normal, "", &wallet_name_ok);
516  if (!wallet_name_ok || wallet_name.isEmpty()) return;
517 
518  auto activity = new MigrateWalletActivity(m_wallet_controller, this);
519  connect(activity, &MigrateWalletActivity::migrated, this, &BitcoinGUI::setCurrentWallet);
520  connect(activity, &MigrateWalletActivity::migrated, rpcConsole, &RPCConsole::setCurrentWallet);
521  auto backup_file_path = fs::PathFromString(backup_file.toStdString());
522  activity->restore_and_migrate(backup_file_path, wallet_name.toStdString());
523  });
524  });
525  connect(m_mask_values_action, &QAction::toggled, this, &BitcoinGUI::setPrivacy);
526  connect(m_mask_values_action, &QAction::toggled, this, &BitcoinGUI::enableHistoryAction);
527  }
528 #endif // ENABLE_WALLET
529 
530  connect(new QShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_C), this), &QShortcut::activated, this, &BitcoinGUI::showDebugWindowActivateConsole);
531  connect(new QShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_D), this), &QShortcut::activated, this, &BitcoinGUI::showDebugWindow);
532 }
533 
535 {
536  appMenuBar = menuBar();
537 
538  // Configure the menus
539  QMenu *file = appMenuBar->addMenu(tr("&File"));
540  if(walletFrame)
541  {
542  file->addAction(m_create_wallet_action);
543  file->addAction(m_open_wallet_action);
544  file->addAction(m_close_wallet_action);
545  file->addAction(m_close_all_wallets_action);
546  file->addAction(m_migrate_wallet_action);
547  file->addSeparator();
548  file->addAction(backupWalletAction);
549  file->addAction(m_restore_wallet_action);
550  file->addSeparator();
551  file->addAction(openAction);
552  file->addAction(signMessageAction);
553  file->addAction(verifyMessageAction);
554  file->addAction(m_load_psbt_action);
555  file->addAction(m_load_psbt_clipboard_action);
556  file->addSeparator();
557  }
558  file->addAction(quitAction);
559 
560  QMenu *settings = appMenuBar->addMenu(tr("&Settings"));
561  if(walletFrame)
562  {
563  settings->addAction(encryptWalletAction);
564  settings->addAction(changePassphraseAction);
565  settings->addSeparator();
566  settings->addAction(m_mask_values_action);
567  settings->addSeparator();
568  }
569  settings->addAction(optionsAction);
570 
571  QMenu* window_menu = appMenuBar->addMenu(tr("&Window"));
572 
573  QAction* minimize_action = window_menu->addAction(tr("&Minimize"));
574  minimize_action->setShortcut(QKeySequence(tr("Ctrl+M")));
575  connect(minimize_action, &QAction::triggered, [] {
576  QApplication::activeWindow()->showMinimized();
577  });
578  connect(qApp, &QApplication::focusWindowChanged, this, [minimize_action] (QWindow* window) {
579  minimize_action->setEnabled(window != nullptr && (window->flags() & Qt::Dialog) != Qt::Dialog && window->windowState() != Qt::WindowMinimized);
580  });
581 
582 #ifdef Q_OS_MACOS
583  QAction* zoom_action = window_menu->addAction(tr("Zoom"));
584  connect(zoom_action, &QAction::triggered, [] {
585  QWindow* window = qApp->focusWindow();
586  if (window->windowState() != Qt::WindowMaximized) {
587  window->showMaximized();
588  } else {
589  window->showNormal();
590  }
591  });
592 
593  connect(qApp, &QApplication::focusWindowChanged, this, [zoom_action] (QWindow* window) {
594  zoom_action->setEnabled(window != nullptr);
595  });
596 #endif
597 
598  if (walletFrame) {
599 #ifdef Q_OS_MACOS
600  window_menu->addSeparator();
601  QAction* main_window_action = window_menu->addAction(tr("Main Window"));
602  connect(main_window_action, &QAction::triggered, [this] {
603  GUIUtil::bringToFront(this);
604  });
605 #endif
606  window_menu->addSeparator();
607  window_menu->addAction(usedSendingAddressesAction);
608  window_menu->addAction(usedReceivingAddressesAction);
609  }
610 
611  window_menu->addSeparator();
612  for (RPCConsole::TabTypes tab_type : rpcConsole->tabs()) {
613  QAction* tab_action = window_menu->addAction(rpcConsole->tabTitle(tab_type));
614  tab_action->setShortcut(rpcConsole->tabShortcut(tab_type));
615  connect(tab_action, &QAction::triggered, [this, tab_type] {
616  rpcConsole->setTabFocus(tab_type);
617  showDebugWindow();
618  });
619  }
620 
621  QMenu *help = appMenuBar->addMenu(tr("&Help"));
622  help->addAction(showHelpMessageAction);
623  help->addSeparator();
624  help->addAction(aboutAction);
625  help->addAction(aboutQtAction);
626 }
627 
629 {
630  if(walletFrame)
631  {
632  QToolBar *toolbar = addToolBar(tr("Tabs toolbar"));
633  appToolBar = toolbar;
634  toolbar->setMovable(false);
635  toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
636  toolbar->addAction(overviewAction);
637  toolbar->addAction(sendCoinsAction);
638  toolbar->addAction(receiveCoinsAction);
639  toolbar->addAction(historyAction);
640  overviewAction->setChecked(true);
641 
642 #ifdef ENABLE_WALLET
643  QWidget *spacer = new QWidget();
644  spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
645  toolbar->addWidget(spacer);
646 
647  m_wallet_selector = new QComboBox();
648  m_wallet_selector->setSizeAdjustPolicy(QComboBox::AdjustToContents);
649  connect(m_wallet_selector, qOverload<int>(&QComboBox::currentIndexChanged), this, &BitcoinGUI::setCurrentWalletBySelectorIndex);
650 
651  m_wallet_selector_label = new QLabel();
652  m_wallet_selector_label->setText(tr("Wallet:") + " ");
654 
657 
658  m_wallet_selector_label_action->setVisible(false);
659  m_wallet_selector_action->setVisible(false);
660 #endif
661  }
662 }
663 
665 {
666  this->clientModel = _clientModel;
667  if(_clientModel)
668  {
669  // Create system tray menu (or setup the dock menu) that late to prevent users from calling actions,
670  // while the client has not yet fully loaded
672 
673  // Keep up to date with client
677  });
679  connect(_clientModel, &ClientModel::networkActiveChanged, this, &BitcoinGUI::setNetworkActive);
680 
681  modalOverlay->setKnownBestHeight(tip_info->header_height, QDateTime::fromSecsSinceEpoch(tip_info->header_time), /*presync=*/false);
682  setNumBlocks(tip_info->block_height, QDateTime::fromSecsSinceEpoch(tip_info->block_time), tip_info->verification_progress, SyncType::BLOCK_SYNC, SynchronizationState::INIT_DOWNLOAD);
683  connect(_clientModel, &ClientModel::numBlocksChanged, this, &BitcoinGUI::setNumBlocks);
684 
685  // Receive and report messages from client model
686  connect(_clientModel, &ClientModel::message, [this](const QString &title, const QString &message, unsigned int style){
687  this->message(title, message, style);
688  });
689 
690  // Show progress dialog
691  connect(_clientModel, &ClientModel::showProgress, this, &BitcoinGUI::showProgress);
692 
693  rpcConsole->setClientModel(_clientModel, tip_info->block_height, tip_info->block_time, tip_info->verification_progress);
694 
695  updateProxyIcon();
696 
697 #ifdef ENABLE_WALLET
698  if(walletFrame)
699  {
700  walletFrame->setClientModel(_clientModel);
701  }
702 #endif // ENABLE_WALLET
704 
705  OptionsModel* optionsModel = _clientModel->getOptionsModel();
706  if (optionsModel && trayIcon) {
707  // be aware of the tray icon disable state change reported by the OptionsModel object.
708  connect(optionsModel, &OptionsModel::showTrayIconChanged, trayIcon, &QSystemTrayIcon::setVisible);
709 
710  // initialize the disable state of the tray icon with the current value in the model.
711  trayIcon->setVisible(optionsModel->getShowTrayIcon());
712  }
713 
714  m_mask_values_action->setChecked(_clientModel->getOptionsModel()->getOption(OptionsModel::OptionID::MaskValues).toBool());
715  } else {
716  // Shutdown requested, disable menus
717  if (trayIconMenu)
718  {
719  // Disable context menu on tray icon
720  trayIconMenu->clear();
721  }
722  // Propagate cleared model to child objects
723  rpcConsole->setClientModel(nullptr);
724 #ifdef ENABLE_WALLET
725  if (walletFrame)
726  {
727  walletFrame->setClientModel(nullptr);
728  }
729 #endif // ENABLE_WALLET
731  // Disable top bar menu actions
732  appMenuBar->clear();
733  }
734 }
735 
736 #ifdef ENABLE_WALLET
737 void BitcoinGUI::enableHistoryAction(bool privacy)
738 {
740  historyAction->setEnabled(!privacy);
741  if (historyAction->isChecked()) gotoOverviewPage();
742  }
743 }
744 
745 void BitcoinGUI::setWalletController(WalletController* wallet_controller, bool show_loading_minimized)
746 {
748  assert(wallet_controller);
749 
750  m_wallet_controller = wallet_controller;
751 
752  m_create_wallet_action->setEnabled(true);
753  m_open_wallet_action->setEnabled(true);
755  m_restore_wallet_action->setEnabled(true);
756  m_migrate_wallet_action->setEnabled(true);
758 
759  GUIUtil::ExceptionSafeConnect(wallet_controller, &WalletController::walletAdded, this, &BitcoinGUI::addWallet);
760  connect(wallet_controller, &WalletController::walletRemoved, this, &BitcoinGUI::removeWallet);
761  connect(wallet_controller, &WalletController::destroyed, this, [this] {
762  // wallet_controller gets destroyed manually, but it leaves our member copy dangling
763  m_wallet_controller = nullptr;
764  });
765 
766  auto activity = new LoadWalletsActivity(m_wallet_controller, this);
767  activity->load(show_loading_minimized);
768 }
769 
770 WalletController* BitcoinGUI::getWalletController()
771 {
772  return m_wallet_controller;
773 }
774 
775 void BitcoinGUI::addWallet(WalletModel* walletModel)
776 {
777  if (!walletFrame || !m_wallet_controller) return;
778 
779  WalletView* wallet_view = new WalletView(walletModel, platformStyle, walletFrame);
780  if (!walletFrame->addView(wallet_view)) return;
781 
782  rpcConsole->addWallet(walletModel);
783  if (m_wallet_selector->count() == 0) {
785  } else if (m_wallet_selector->count() == 1) {
786  m_wallet_selector_label_action->setVisible(true);
787  m_wallet_selector_action->setVisible(true);
788  }
789 
791  connect(wallet_view, &WalletView::transactionClicked, this, &BitcoinGUI::gotoHistoryPage);
792  connect(wallet_view, &WalletView::coinsSent, this, &BitcoinGUI::gotoHistoryPage);
793  connect(wallet_view, &WalletView::message, [this](const QString& title, const QString& message, unsigned int style) {
794  this->message(title, message, style);
795  });
796  connect(wallet_view, &WalletView::encryptionStatusChanged, this, &BitcoinGUI::updateWalletStatus);
797  connect(wallet_view, &WalletView::incomingTransaction, this, &BitcoinGUI::incomingTransaction);
798  connect(this, &BitcoinGUI::setPrivacy, wallet_view, &WalletView::setPrivacy);
799  wallet_view->setPrivacy(isPrivacyModeActivated());
800  const QString display_name = walletModel->getDisplayName();
801  m_wallet_selector->addItem(display_name, QVariant::fromValue(walletModel));
802 }
803 
804 void BitcoinGUI::removeWallet(WalletModel* walletModel)
805 {
806  if (!walletFrame) return;
807 
808  labelWalletHDStatusIcon->hide();
810 
811  int index = m_wallet_selector->findData(QVariant::fromValue(walletModel));
812  m_wallet_selector->removeItem(index);
813  if (m_wallet_selector->count() == 0) {
815  overviewAction->setChecked(true);
816  } else if (m_wallet_selector->count() == 1) {
817  m_wallet_selector_label_action->setVisible(false);
818  m_wallet_selector_action->setVisible(false);
819  }
820  rpcConsole->removeWallet(walletModel);
821  walletFrame->removeWallet(walletModel);
823 }
824 
825 void BitcoinGUI::setCurrentWallet(WalletModel* wallet_model)
826 {
827  if (!walletFrame || !m_wallet_controller) return;
828  walletFrame->setCurrentWallet(wallet_model);
829  for (int index = 0; index < m_wallet_selector->count(); ++index) {
830  if (m_wallet_selector->itemData(index).value<WalletModel*>() == wallet_model) {
831  m_wallet_selector->setCurrentIndex(index);
832  break;
833  }
834  }
836 }
837 
838 void BitcoinGUI::setCurrentWalletBySelectorIndex(int index)
839 {
840  WalletModel* wallet_model = m_wallet_selector->itemData(index).value<WalletModel*>();
841  if (wallet_model) setCurrentWallet(wallet_model);
842 }
843 
844 void BitcoinGUI::removeAllWallets()
845 {
846  if(!walletFrame)
847  return;
850 }
851 #endif // ENABLE_WALLET
852 
854 {
855  overviewAction->setEnabled(enabled);
856  sendCoinsAction->setEnabled(enabled);
857  receiveCoinsAction->setEnabled(enabled);
858  historyAction->setEnabled(enabled && !isPrivacyModeActivated());
859  encryptWalletAction->setEnabled(enabled);
860  backupWalletAction->setEnabled(enabled);
861  changePassphraseAction->setEnabled(enabled);
862  signMessageAction->setEnabled(enabled);
863  verifyMessageAction->setEnabled(enabled);
864  usedSendingAddressesAction->setEnabled(enabled);
865  usedReceivingAddressesAction->setEnabled(enabled);
866  openAction->setEnabled(enabled);
867  m_close_wallet_action->setEnabled(enabled);
868  m_close_all_wallets_action->setEnabled(enabled);
869 }
870 
872 {
873  assert(QSystemTrayIcon::isSystemTrayAvailable());
874 
875 #ifndef Q_OS_MACOS
876  if (QSystemTrayIcon::isSystemTrayAvailable()) {
877  trayIcon = new QSystemTrayIcon(m_network_style->getTrayAndWindowIcon(), this);
878  QString toolTip = tr("%1 client").arg(CLIENT_NAME) + " " + m_network_style->getTitleAddText();
879  trayIcon->setToolTip(toolTip);
880  }
881 #endif
882 }
883 
885 {
886 #ifndef Q_OS_MACOS
887  if (!trayIcon) return;
888 #endif // Q_OS_MACOS
889 
890  // Configuration of the tray icon (or Dock icon) menu.
891  QAction* show_hide_action{nullptr};
892 #ifndef Q_OS_MACOS
893  // Note: On macOS, the Dock icon's menu already has Show / Hide action.
894  show_hide_action = trayIconMenu->addAction(QString(), this, &BitcoinGUI::toggleHidden);
895  trayIconMenu->addSeparator();
896 #endif // Q_OS_MACOS
897 
898  QAction* send_action{nullptr};
899  QAction* receive_action{nullptr};
900  QAction* sign_action{nullptr};
901  QAction* verify_action{nullptr};
902  if (enableWallet) {
903  send_action = trayIconMenu->addAction(sendCoinsAction->text(), sendCoinsAction, &QAction::trigger);
904  receive_action = trayIconMenu->addAction(receiveCoinsAction->text(), receiveCoinsAction, &QAction::trigger);
905  trayIconMenu->addSeparator();
906  sign_action = trayIconMenu->addAction(signMessageAction->text(), signMessageAction, &QAction::trigger);
907  verify_action = trayIconMenu->addAction(verifyMessageAction->text(), verifyMessageAction, &QAction::trigger);
908  trayIconMenu->addSeparator();
909  }
910  QAction* options_action = trayIconMenu->addAction(optionsAction->text(), optionsAction, &QAction::trigger);
911  options_action->setMenuRole(QAction::PreferencesRole);
912  QAction* node_window_action = trayIconMenu->addAction(openRPCConsoleAction->text(), openRPCConsoleAction, &QAction::trigger);
913  QAction* quit_action{nullptr};
914 #ifndef Q_OS_MACOS
915  // Note: On macOS, the Dock icon's menu already has Quit action.
916  trayIconMenu->addSeparator();
917  quit_action = trayIconMenu->addAction(quitAction->text(), quitAction, &QAction::trigger);
918 
919  trayIcon->setContextMenu(trayIconMenu.get());
920  connect(trayIcon, &QSystemTrayIcon::activated, [this](QSystemTrayIcon::ActivationReason reason) {
921  if (reason == QSystemTrayIcon::Trigger) {
922  // Click on system tray icon triggers show/hide of the main window
923  toggleHidden();
924  }
925  });
926 #else
927  // Note: On macOS, the Dock icon is used to provide the tray's functionality.
929  connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, [this] {
930  if (m_node.shutdownRequested()) return; // nothing to show, node is shutting down.
931  show();
932  activateWindow();
933  });
934  trayIconMenu->setAsDockMenu();
935 #endif // Q_OS_MACOS
936 
937  connect(
938  // Using QSystemTrayIcon::Context is not reliable.
939  // See https://bugreports.qt.io/browse/QTBUG-91697
940  trayIconMenu.get(), &QMenu::aboutToShow,
941  [this, show_hide_action, send_action, receive_action, sign_action, verify_action, options_action, node_window_action, quit_action] {
942  if (m_node.shutdownRequested()) return; // nothing to do, node is shutting down.
943 
944  if (show_hide_action) show_hide_action->setText(
945  (!isHidden() && !isMinimized() && !GUIUtil::isObscured(this)) ?
946  tr("&Hide") :
947  tr("S&how"));
948  if (QApplication::activeModalWidget()) {
949  for (QAction* a : trayIconMenu.get()->actions()) {
950  a->setEnabled(false);
951  }
952  } else {
953  if (show_hide_action) show_hide_action->setEnabled(true);
954  if (enableWallet) {
955  send_action->setEnabled(sendCoinsAction->isEnabled());
956  receive_action->setEnabled(receiveCoinsAction->isEnabled());
957  sign_action->setEnabled(signMessageAction->isEnabled());
958  verify_action->setEnabled(verifyMessageAction->isEnabled());
959  }
960  options_action->setEnabled(optionsAction->isEnabled());
961  node_window_action->setEnabled(openRPCConsoleAction->isEnabled());
962  if (quit_action) quit_action->setEnabled(true);
963  }
964  });
965 }
966 
968 {
970 }
971 
973 {
974  if(!clientModel)
975  return;
976 
977  auto dlg = new HelpMessageDialog(this, /*about=*/true);
979 }
980 
982 {
984  Q_EMIT consoleShown(rpcConsole);
985 }
986 
988 {
990  showDebugWindow();
991 }
992 
994 {
996 }
997 
998 #ifdef ENABLE_WALLET
999 void BitcoinGUI::openClicked()
1000 {
1001  OpenURIDialog dlg(platformStyle, this);
1002  if(dlg.exec())
1003  {
1004  Q_EMIT receivedURI(dlg.getURI());
1005  }
1006 }
1007 
1008 void BitcoinGUI::gotoOverviewPage()
1009 {
1010  overviewAction->setChecked(true);
1012 }
1013 
1014 void BitcoinGUI::gotoHistoryPage()
1015 {
1016  historyAction->setChecked(true);
1018 }
1019 
1020 void BitcoinGUI::gotoReceiveCoinsPage()
1021 {
1022  receiveCoinsAction->setChecked(true);
1024 }
1025 
1026 void BitcoinGUI::gotoSendCoinsPage(QString addr)
1027 {
1028  sendCoinsAction->setChecked(true);
1030 }
1031 
1032 void BitcoinGUI::gotoSignMessageTab(QString addr)
1033 {
1035 }
1036 
1037 void BitcoinGUI::gotoVerifyMessageTab(QString addr)
1038 {
1040 }
1041 void BitcoinGUI::gotoLoadPSBT(bool from_clipboard)
1042 {
1043  if (walletFrame) walletFrame->gotoLoadPSBT(from_clipboard);
1044 }
1045 #endif // ENABLE_WALLET
1046 
1048 {
1049  if (!clientModel) return;
1051  QString icon;
1052  switch(count)
1053  {
1054  case 0: icon = ":/icons/connect_0"; break;
1055  case 1: case 2: case 3: icon = ":/icons/connect_1"; break;
1056  case 4: case 5: case 6: icon = ":/icons/connect_2"; break;
1057  case 7: case 8: case 9: icon = ":/icons/connect_3"; break;
1058  default: icon = ":/icons/connect_4"; break;
1059  }
1060 
1061  QString tooltip;
1062 
1063  if (m_node.getNetworkActive()) {
1064  //: A substring of the tooltip.
1065  tooltip = tr("%n active connection(s) to Bitcoin network.", "", count);
1066  } else {
1067  //: A substring of the tooltip.
1068  tooltip = tr("Network activity disabled.");
1069  icon = ":/icons/network_disabled";
1070  }
1071 
1072  // Don't word-wrap this (fixed-width) tooltip
1073  tooltip = QLatin1String("<nobr>") + tooltip + QLatin1String("<br>") +
1074  //: A substring of the tooltip. "More actions" are available via the context menu.
1075  tr("Click for more actions.") + QLatin1String("</nobr>");
1076  connectionsControl->setToolTip(tooltip);
1077 
1079 }
1080 
1082 {
1084 }
1085 
1086 void BitcoinGUI::setNetworkActive(bool network_active)
1087 {
1089  m_network_context_menu->clear();
1090  m_network_context_menu->addAction(
1091  //: A context menu item. The "Peers tab" is an element of the "Node window".
1092  tr("Show Peers tab"),
1093  [this] {
1095  showDebugWindow();
1096  });
1097  m_network_context_menu->addAction(
1098  network_active ?
1099  //: A context menu item.
1100  tr("Disable network activity") :
1101  //: A context menu item. The network activity was disabled previously.
1102  tr("Enable network activity"),
1103  [this, new_state = !network_active] { m_node.setNetworkActive(new_state); });
1104 }
1105 
1107 {
1108  int64_t headersTipTime = clientModel->getHeaderTipTime();
1109  int headersTipHeight = clientModel->getHeaderTipHeight();
1110  int estHeadersLeft = (GetTime() - headersTipTime) / Params().GetConsensus().nPowTargetSpacing;
1111  if (estHeadersLeft > HEADER_HEIGHT_DELTA_SYNC)
1112  progressBarLabel->setText(tr("Syncing Headers (%1%)…").arg(QString::number(100.0 / (headersTipHeight+estHeadersLeft)*headersTipHeight, 'f', 1)));
1113 }
1114 
1115 void BitcoinGUI::updateHeadersPresyncProgressLabel(int64_t height, const QDateTime& blockDate)
1116 {
1117  int estHeadersLeft = blockDate.secsTo(QDateTime::currentDateTime()) / Params().GetConsensus().nPowTargetSpacing;
1118  if (estHeadersLeft > HEADER_HEIGHT_DELTA_SYNC)
1119  progressBarLabel->setText(tr("Pre-syncing Headers (%1%)…").arg(QString::number(100.0 / (height+estHeadersLeft)*height, 'f', 1)));
1120 }
1121 
1123 {
1125  return;
1126 
1127  auto dlg = new OptionsDialog(this, enableWallet);
1129  dlg->setCurrentTab(tab);
1130  dlg->setClientModel(clientModel);
1131  dlg->setModel(clientModel->getOptionsModel());
1133 }
1134 
1135 void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state)
1136 {
1137 // Disabling macOS App Nap on initial sync, disk and reindex operations.
1138 #ifdef Q_OS_MACOS
1139  if (sync_state == SynchronizationState::POST_INIT) {
1140  m_app_nap_inhibitor->enableAppNap();
1141  } else {
1142  m_app_nap_inhibitor->disableAppNap();
1143  }
1144 #endif
1145 
1146  if (modalOverlay)
1147  {
1148  if (synctype != SyncType::BLOCK_SYNC)
1150  else
1151  modalOverlay->tipUpdate(count, blockDate, nVerificationProgress);
1152  }
1153  if (!clientModel)
1154  return;
1155 
1156  // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbled text)
1157  statusBar()->clearMessage();
1158 
1159  // Acquire current block source
1160  BlockSource blockSource{clientModel->getBlockSource()};
1161  switch (blockSource) {
1162  case BlockSource::NETWORK:
1163  if (synctype == SyncType::HEADER_PRESYNC) {
1165  return;
1166  } else if (synctype == SyncType::HEADER_SYNC) {
1168  return;
1169  }
1170  progressBarLabel->setText(tr("Synchronizing with network…"));
1172  break;
1173  case BlockSource::DISK:
1174  if (synctype != SyncType::BLOCK_SYNC) {
1175  progressBarLabel->setText(tr("Indexing blocks on disk…"));
1176  } else {
1177  progressBarLabel->setText(tr("Processing blocks on disk…"));
1178  }
1179  break;
1180  case BlockSource::NONE:
1181  if (synctype != SyncType::BLOCK_SYNC) {
1182  return;
1183  }
1184  progressBarLabel->setText(tr("Connecting to peers…"));
1185  break;
1186  }
1187 
1188  QString tooltip;
1189 
1190  QDateTime currentDate = QDateTime::currentDateTime();
1191  qint64 secs = blockDate.secsTo(currentDate);
1192 
1193  tooltip = tr("Processed %n block(s) of transaction history.", "", count);
1194 
1195  // Set icon state: spinning if catching up, tick otherwise
1196  if (secs < MAX_BLOCK_TIME_GAP) {
1197  tooltip = tr("Up to date") + QString(".<br>") + tooltip;
1198  labelBlocksIcon->setThemedPixmap(QStringLiteral(":/icons/synced"), STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE);
1199 
1200 #ifdef ENABLE_WALLET
1201  if(walletFrame)
1202  {
1204  modalOverlay->showHide(true, true);
1205  }
1206 #endif // ENABLE_WALLET
1207 
1208  progressBarLabel->setVisible(false);
1209  progressBar->setVisible(false);
1210  }
1211  else
1212  {
1213  QString timeBehindText = GUIUtil::formatNiceTimeOffset(secs);
1214 
1215  progressBarLabel->setVisible(true);
1216  progressBar->setFormat(tr("%1 behind").arg(timeBehindText));
1217  progressBar->setMaximum(1000000000);
1218  progressBar->setValue(nVerificationProgress * 1000000000.0 + 0.5);
1219  progressBar->setVisible(true);
1220 
1221  tooltip = tr("Catching up…") + QString("<br>") + tooltip;
1222  if(count != prevBlocks)
1223  {
1225  QString(":/animation/spinner-%1").arg(spinnerFrame, 3, 10, QChar('0')),
1228  }
1229  prevBlocks = count;
1230 
1231 #ifdef ENABLE_WALLET
1232  if(walletFrame)
1233  {
1236  }
1237 #endif // ENABLE_WALLET
1238 
1239  tooltip += QString("<br>");
1240  tooltip += tr("Last received block was generated %1 ago.").arg(timeBehindText);
1241  tooltip += QString("<br>");
1242  tooltip += tr("Transactions after this will not yet be visible.");
1243  }
1244 
1245  // Don't word-wrap this (fixed-width) tooltip
1246  tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
1247 
1248  labelBlocksIcon->setToolTip(tooltip);
1249  progressBarLabel->setToolTip(tooltip);
1250  progressBar->setToolTip(tooltip);
1251 }
1252 
1254 {
1255 #ifdef ENABLE_WALLET
1256  auto activity = new CreateWalletActivity(getWalletController(), this);
1257  connect(activity, &CreateWalletActivity::created, this, &BitcoinGUI::setCurrentWallet);
1258  connect(activity, &CreateWalletActivity::created, rpcConsole, &RPCConsole::setCurrentWallet);
1259  activity->create();
1260 #endif // ENABLE_WALLET
1261 }
1262 
1263 void BitcoinGUI::message(const QString& title, QString message, unsigned int style, bool* ret, const QString& detailed_message)
1264 {
1265  // Default title. On macOS, the window title is ignored (as required by the macOS Guidelines).
1266  QString strTitle{CLIENT_NAME};
1267  // Default to information icon
1268  int nMBoxIcon = QMessageBox::Information;
1269  int nNotifyIcon = Notificator::Information;
1270 
1271  QString msgType;
1272  if (!title.isEmpty()) {
1273  msgType = title;
1274  } else {
1275  switch (style) {
1277  msgType = tr("Error");
1278  message = tr("Error: %1").arg(message);
1279  break;
1281  msgType = tr("Warning");
1282  message = tr("Warning: %1").arg(message);
1283  break;
1285  msgType = tr("Information");
1286  // No need to prepend the prefix here.
1287  break;
1288  default:
1289  break;
1290  }
1291  }
1292 
1293  if (!msgType.isEmpty()) {
1294  strTitle += " - " + msgType;
1295  }
1296 
1297  if (style & CClientUIInterface::ICON_ERROR) {
1298  nMBoxIcon = QMessageBox::Critical;
1299  nNotifyIcon = Notificator::Critical;
1300  } else if (style & CClientUIInterface::ICON_WARNING) {
1301  nMBoxIcon = QMessageBox::Warning;
1302  nNotifyIcon = Notificator::Warning;
1303  }
1304 
1305  if (style & CClientUIInterface::MODAL) {
1306  // Check for buttons, use OK as default, if none was supplied
1307  QMessageBox::StandardButton buttons;
1308  if (!(buttons = (QMessageBox::StandardButton)(style & CClientUIInterface::BTN_MASK)))
1309  buttons = QMessageBox::Ok;
1310 
1312  QMessageBox mBox(static_cast<QMessageBox::Icon>(nMBoxIcon), strTitle, message, buttons, this);
1313  mBox.setTextFormat(Qt::PlainText);
1314  mBox.setDetailedText(detailed_message);
1315  int r = mBox.exec();
1316  if (ret != nullptr)
1317  *ret = r == QMessageBox::Ok;
1318  } else {
1319  notificator->notify(static_cast<Notificator::Class>(nNotifyIcon), strTitle, message);
1320  }
1321 }
1322 
1324 {
1325  if (e->type() == QEvent::PaletteChange) {
1326  overviewAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/overview")));
1327  sendCoinsAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/send")));
1328  receiveCoinsAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/receiving_addresses")));
1329  historyAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/history")));
1330  }
1331 
1332  QMainWindow::changeEvent(e);
1333 
1334 #ifndef Q_OS_MACOS // Ignored on Mac
1335  if(e->type() == QEvent::WindowStateChange)
1336  {
1338  {
1339  QWindowStateChangeEvent *wsevt = static_cast<QWindowStateChangeEvent*>(e);
1340  if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized())
1341  {
1342  QTimer::singleShot(0, this, &BitcoinGUI::hide);
1343  e->ignore();
1344  }
1345  else if((wsevt->oldState() & Qt::WindowMinimized) && !isMinimized())
1346  {
1347  QTimer::singleShot(0, this, &BitcoinGUI::show);
1348  e->ignore();
1349  }
1350  }
1351  }
1352 #endif
1353 }
1354 
1355 void BitcoinGUI::closeEvent(QCloseEvent *event)
1356 {
1357 #ifndef Q_OS_MACOS // Ignored on Mac
1359  {
1361  {
1362  // close rpcConsole in case it was open to make some space for the shutdown window
1363  rpcConsole->close();
1364 
1365  Q_EMIT quitRequested();
1366  }
1367  else
1368  {
1369  QMainWindow::showMinimized();
1370  event->ignore();
1371  }
1372  }
1373 #else
1374  QMainWindow::closeEvent(event);
1375 #endif
1376 }
1377 
1378 void BitcoinGUI::showEvent(QShowEvent *event)
1379 {
1380  // enable the debug window when the main window shows up
1381  openRPCConsoleAction->setEnabled(true);
1382  aboutAction->setEnabled(true);
1383  optionsAction->setEnabled(true);
1384 }
1385 
1386 #ifdef ENABLE_WALLET
1387 void BitcoinGUI::incomingTransaction(const QString& date, BitcoinUnit unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName)
1388 {
1389  // On new transaction, make an info balloon
1390  QString msg = tr("Date: %1\n").arg(date) +
1391  tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(unit, amount, true));
1392  if (m_node.walletLoader().getWallets().size() > 1 && !walletName.isEmpty()) {
1393  msg += tr("Wallet: %1\n").arg(walletName);
1394  }
1395  msg += tr("Type: %1\n").arg(type);
1396  if (!label.isEmpty())
1397  msg += tr("Label: %1\n").arg(label);
1398  else if (!address.isEmpty())
1399  msg += tr("Address: %1\n").arg(address);
1400  message((amount)<0 ? tr("Sent transaction") : tr("Incoming transaction"),
1402 }
1403 #endif // ENABLE_WALLET
1404 
1405 void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
1406 {
1407  // Accept only URIs
1408  if(event->mimeData()->hasUrls())
1409  event->acceptProposedAction();
1410 }
1411 
1412 void BitcoinGUI::dropEvent(QDropEvent *event)
1413 {
1414  if(event->mimeData()->hasUrls())
1415  {
1416  for (const QUrl &uri : event->mimeData()->urls())
1417  {
1418  Q_EMIT receivedURI(uri.toString());
1419  }
1420  }
1421  event->acceptProposedAction();
1422 }
1423 
1424 bool BitcoinGUI::eventFilter(QObject *object, QEvent *event)
1425 {
1426  // Catch status tip events
1427  if (event->type() == QEvent::StatusTip)
1428  {
1429  // Prevent adding text from setStatusTip(), if we currently use the status bar for displaying other stuff
1430  if (progressBarLabel->isVisible() || progressBar->isVisible())
1431  return true;
1432  }
1433  return QMainWindow::eventFilter(object, event);
1434 }
1435 
1436 #ifdef ENABLE_WALLET
1437 bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient)
1438 {
1439  // URI has to be valid
1440  if (walletFrame && walletFrame->handlePaymentRequest(recipient))
1441  {
1443  gotoSendCoinsPage();
1444  return true;
1445  }
1446  return false;
1447 }
1448 
1449 void BitcoinGUI::setHDStatus(bool privkeyDisabled, int hdEnabled)
1450 {
1451  labelWalletHDStatusIcon->setThemedPixmap(privkeyDisabled ? QStringLiteral(":/icons/eye") : hdEnabled ? QStringLiteral(":/icons/hd_enabled") : QStringLiteral(":/icons/hd_disabled"), STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE);
1452  labelWalletHDStatusIcon->setToolTip(privkeyDisabled ? tr("Private key <b>disabled</b>") : hdEnabled ? tr("HD key generation is <b>enabled</b>") : tr("HD key generation is <b>disabled</b>"));
1453  labelWalletHDStatusIcon->show();
1454 }
1455 
1456 void BitcoinGUI::setEncryptionStatus(int status)
1457 {
1458  switch(status)
1459  {
1460  case WalletModel::NoKeys:
1461  labelWalletEncryptionIcon->hide();
1462  encryptWalletAction->setChecked(false);
1463  changePassphraseAction->setEnabled(false);
1464  encryptWalletAction->setEnabled(false);
1465  break;
1467  labelWalletEncryptionIcon->hide();
1468  encryptWalletAction->setChecked(false);
1469  changePassphraseAction->setEnabled(false);
1470  encryptWalletAction->setEnabled(true);
1471  break;
1472  case WalletModel::Unlocked:
1473  labelWalletEncryptionIcon->show();
1474  labelWalletEncryptionIcon->setThemedPixmap(QStringLiteral(":/icons/lock_open"), STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE);
1475  labelWalletEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>unlocked</b>"));
1476  encryptWalletAction->setChecked(true);
1477  changePassphraseAction->setEnabled(true);
1478  encryptWalletAction->setEnabled(false);
1479  break;
1480  case WalletModel::Locked:
1481  labelWalletEncryptionIcon->show();
1482  labelWalletEncryptionIcon->setThemedPixmap(QStringLiteral(":/icons/lock_closed"), STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE);
1483  labelWalletEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>locked</b>"));
1484  encryptWalletAction->setChecked(true);
1485  changePassphraseAction->setEnabled(true);
1486  encryptWalletAction->setEnabled(false);
1487  break;
1488  }
1489 }
1490 
1491 void BitcoinGUI::updateWalletStatus()
1492 {
1494 
1495  WalletView * const walletView = walletFrame->currentWalletView();
1496  if (!walletView) {
1497  return;
1498  }
1499  WalletModel * const walletModel = walletView->getWalletModel();
1500  setEncryptionStatus(walletModel->getEncryptionStatus());
1501  setHDStatus(walletModel->wallet().privateKeysDisabled(), walletModel->wallet().hdEnabled());
1502 }
1503 #endif // ENABLE_WALLET
1504 
1506 {
1507  std::string ip_port;
1508  bool proxy_enabled = clientModel->getProxyInfo(ip_port);
1509 
1510  if (proxy_enabled) {
1512  QString ip_port_q = QString::fromStdString(ip_port);
1514  labelProxyIcon->setToolTip(tr("Proxy is <b>enabled</b>: %1").arg(ip_port_q));
1515  } else {
1516  labelProxyIcon->show();
1517  }
1518  } else {
1519  labelProxyIcon->hide();
1520  }
1521 }
1522 
1524 {
1525  QString window_title = CLIENT_NAME;
1526 #ifdef ENABLE_WALLET
1527  if (walletFrame) {
1528  WalletModel* const wallet_model = walletFrame->currentWalletModel();
1529  if (wallet_model && !wallet_model->getWalletName().isEmpty()) {
1530  window_title += " - " + wallet_model->getDisplayName();
1531  }
1532  }
1533 #endif
1534  if (!m_network_style->getTitleAddText().isEmpty()) {
1535  window_title += " - " + m_network_style->getTitleAddText();
1536  }
1537  setWindowTitle(window_title);
1538 }
1539 
1540 void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
1541 {
1542  if(!clientModel)
1543  return;
1544 
1545  if (!isHidden() && !isMinimized() && !GUIUtil::isObscured(this) && fToggleHidden) {
1546  hide();
1547  } else {
1548  GUIUtil::bringToFront(this);
1549  }
1550 }
1551 
1553 {
1554  showNormalIfMinimized(true);
1555 }
1556 
1558 {
1559  if (m_node.shutdownRequested())
1560  {
1561  if(rpcConsole)
1562  rpcConsole->hide();
1563  Q_EMIT quitRequested();
1564  }
1565 }
1566 
1567 void BitcoinGUI::showProgress(const QString &title, int nProgress)
1568 {
1569  if (nProgress == 0) {
1570  progressDialog = new QProgressDialog(title, QString(), 0, 100);
1572  progressDialog->setWindowModality(Qt::ApplicationModal);
1573  progressDialog->setAutoClose(false);
1574  progressDialog->setValue(0);
1575  } else if (nProgress == 100) {
1576  if (progressDialog) {
1577  progressDialog->close();
1578  progressDialog->deleteLater();
1579  progressDialog = nullptr;
1580  }
1581  } else if (progressDialog) {
1582  progressDialog->setValue(nProgress);
1583  }
1584 }
1585 
1587 {
1588  if (modalOverlay && (progressBar->isVisible() || modalOverlay->isLayerVisible()))
1590 }
1591 
1592 static bool ThreadSafeMessageBox(BitcoinGUI* gui, const bilingual_str& message, unsigned int style)
1593 {
1594  bool modal = (style & CClientUIInterface::MODAL);
1595  // The SECURE flag has no effect in the Qt GUI.
1596  // bool secure = (style & CClientUIInterface::SECURE);
1597  style &= ~CClientUIInterface::SECURE;
1598  bool ret = false;
1599 
1600  QString detailed_message; // This is original message, in English, for googling and referencing.
1601  if (message.original != message.translated) {
1602  detailed_message = BitcoinGUI::tr("Original message:") + "\n" + QString::fromStdString(message.original);
1603  }
1604  // The title is empty for node messages. The fallback title is usually set
1605  // by `style`.
1606  const QString title{};
1607 
1608  // In case of modal message, use blocking connection to wait for user to click a button
1609  bool invoked = QMetaObject::invokeMethod(gui, "message",
1610  modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
1611  Q_ARG(QString, title),
1612  Q_ARG(QString, QString::fromStdString(message.translated)),
1613  Q_ARG(unsigned int, style),
1614  Q_ARG(bool*, &ret),
1615  Q_ARG(QString, detailed_message));
1616  assert(invoked);
1617  return ret;
1618 }
1619 
1621 {
1622  // Connect signals to client
1623  m_handler_message_box = m_node.handleMessageBox([this](const bilingual_str& message, unsigned int style) {
1624  return ThreadSafeMessageBox(this, message, style);
1625  });
1626  m_handler_question = m_node.handleQuestion([this](const bilingual_str& message, const std::string& /*non_interactive_message*/, unsigned int style) {
1627  return ThreadSafeMessageBox(this, message, style);
1628  });
1629 }
1630 
1632 {
1633  // Disconnect signals from client
1634  m_handler_message_box->disconnect();
1635  m_handler_question->disconnect();
1636 }
1637 
1639 {
1641  return m_mask_values_action->isChecked();
1642 }
1643 
1645  : m_platform_style{platformStyle}
1646 {
1647  createContextMenu();
1648  setToolTip(tr("Unit to show amounts in. Click to select another unit."));
1649  QList<BitcoinUnit> units = BitcoinUnits::availableUnits();
1650  int max_width = 0;
1651  const QFontMetrics fm(font());
1652  for (const BitcoinUnit unit : units) {
1653  max_width = qMax(max_width, GUIUtil::TextWidth(fm, BitcoinUnits::longName(unit)));
1654  }
1655  setMinimumSize(max_width, 0);
1656  setAlignment(Qt::AlignRight | Qt::AlignVCenter);
1657  setStyleSheet(QString("QLabel { color : %1 }").arg(m_platform_style->SingleColor().name()));
1658 }
1659 
1662 {
1663  onDisplayUnitsClicked(event->pos());
1664 }
1665 
1667 {
1668  if (e->type() == QEvent::PaletteChange) {
1669  QString style = QString("QLabel { color : %1 }").arg(m_platform_style->SingleColor().name());
1670  if (style != styleSheet()) {
1671  setStyleSheet(style);
1672  }
1673  }
1674 
1675  QLabel::changeEvent(e);
1676 }
1677 
1680 {
1681  menu = new QMenu(this);
1682  for (const BitcoinUnit u : BitcoinUnits::availableUnits()) {
1683  menu->addAction(BitcoinUnits::longName(u))->setData(QVariant::fromValue(u));
1684  }
1685  connect(menu, &QMenu::triggered, this, &UnitDisplayStatusBarControl::onMenuSelection);
1686 }
1687 
1690 {
1691  if (_optionsModel)
1692  {
1693  this->optionsModel = _optionsModel;
1694 
1695  // be aware of a display unit change reported by the OptionsModel object.
1697 
1698  // initialize the display units label with the current value in the model.
1699  updateDisplayUnit(_optionsModel->getDisplayUnit());
1700  }
1701 }
1702 
1705 {
1706  setText(BitcoinUnits::longName(newUnits));
1707 }
1708 
1711 {
1712  QPoint globalPos = mapToGlobal(point);
1713  menu->exec(globalPos);
1714 }
1715 
1718 {
1719  if (action)
1720  {
1721  optionsModel->setDisplayUnit(action->data());
1722  }
1723 }
virtual bool privateKeysDisabled()=0
void subscribeToCoreSignals()
Connect core signals to GUI client.
void unsubscribeFromCoreSignals()
Disconnect core signals from GUI client.
void showEvent(QShowEvent *event) override
bool handlePaymentRequest(const SendCoinsRecipient &recipient)
void message(const QString &title, const QString &message, unsigned int style)
Fired when a message should be reported to the user.
QMenu * m_migrate_wallet_menu
Definition: bitcoingui.h:165
WalletModel * currentWalletModel() const
Predefined combinations for certain default usage cases.
Definition: interface_ui.h:66
int ret
static QList< Unit > availableUnits()
Get list of units, for drop-down box.
QAction * receiveCoinsAction
Definition: bitcoingui.h:146
UnitDisplayStatusBarControl * unitDisplayControl
Definition: bitcoingui.h:123
Local Bitcoin RPC console.
Definition: rpcconsole.h:43
QMenuBar * appMenuBar
Definition: bitcoingui.h:133
void quitRequested()
Unit
Bitcoin units.
Definition: bitcoinunits.h:42
interfaces::Wallet & wallet() const
Definition: walletmodel.h:138
QAction * m_mask_values_action
Definition: bitcoingui.h:163
QAction * signMessageAction
Definition: bitcoingui.h:141
void setThemedPixmap(const QString &image_filename, int width, int height)
Definition: guiutil.cpp:849
void receivedURI(const QString &uri)
Signal raised when a URI was entered or dragged to the GUI.
SynchronizationState
Current sync state passed to tip changed callbacks.
Definition: validation.h:93
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
Get open filename, convenience wrapper for QFileDialog::getOpenFileName.
Definition: guiutil.cpp:353
virtual bool getNetworkActive()=0
Get network active.
QAction * aboutAction
Definition: bitcoingui.h:145
void updateNetworkState()
Update UI with latest network info from model.
assert(!tx.IsCoinBase())
void showNormalIfMinimized()
Show window if hidden, unminimize when minimized, rise when obscured or show if hidden and fToggleHid...
Definition: bitcoingui.h:311
UnitDisplayStatusBarControl(const PlatformStyle *platformStyle)
void createWalletButtonClicked()
QProgressDialog * progressDialog
Definition: bitcoingui.h:131
static bool isWalletEnabled()
void consoleShown(RPCConsole *console)
Signal raised when RPC console shown.
void createTrayIcon()
Create system tray icon and notification.
Definition: bitcoingui.cpp:871
Bilingual messages:
Definition: translation.h:24
void showDebugWindow()
Show debug window.
Definition: bitcoingui.cpp:981
GUIUtil::ClickableLabel * labelProxyIcon
Definition: bitcoingui.h:126
node::NodeContext m_node
Definition: bitcoin-gui.cpp:43
void PopupMenu(QMenu *menu, const QPoint &point, QAction *at_action)
Call QMenu::popup() only on supported QT_QPA_PLATFORM.
Definition: guiutil.cpp:943
ClientModel * clientModel
Definition: bitcoingui.h:120
void createToolBars()
Create the toolbars.
Definition: bitcoingui.cpp:628
int TextWidth(const QFontMetrics &fm, const QString &text)
Returns the distance in pixels appropriate for drawing a subsequent character after text...
Definition: guiutil.cpp:910
void setCurrentWallet(WalletModel *wallet_model)
Definition: walletframe.cpp:91
QAction * m_load_psbt_action
Definition: bitcoingui.h:143
void closeAllWallets(QWidget *parent=nullptr)
void setClientModel(ClientModel *model=nullptr, int bestblock_height=0, int64_t bestblock_date=0, double verification_progress=0.0)
Definition: rpcconsole.cpp:621
ModalOverlay * modalOverlay
Definition: bitcoingui.h:175
void createTrayIconMenu()
Create system tray menu (or setup the dock menu)
Definition: bitcoingui.cpp:884
RPCConsole * rpcConsole
Definition: bitcoingui.h:173
QAction * m_wallet_selector_action
Definition: bitcoingui.h:162
QAction * m_migrate_wallet_action
Definition: bitcoingui.h:164
QAction * overviewAction
Definition: bitcoingui.h:135
int64_t GetTime()
DEPRECATED, see GetTime.
Definition: time.cpp:81
void opened(WalletModel *wallet_model)
QAction * verifyMessageAction
Definition: bitcoingui.h:142
QAction * quitAction
Definition: bitcoingui.h:137
void setPrivacy(bool privacy)
static constexpr int HEADER_HEIGHT_DELTA_SYNC
The required delta of headers to the estimated number of available headers until we show the IBD prog...
Definition: modaloverlay.h:13
QAction * m_open_wallet_action
Definition: bitcoingui.h:156
void triggered(bool hidden)
void usedReceivingAddresses()
Show used receiving addresses.
QAction * m_close_wallet_action
Definition: bitcoingui.h:159
Mask of all available buttons in CClientUIInterface::MessageBoxFlags This needs to be updated...
Definition: interface_ui.h:56
QAction * historyAction
Definition: bitcoingui.h:136
void tipUpdate(int count, const QDateTime &blockDate, double nVerificationProgress)
Qt::ConnectionType blockingGUIThreadConnection()
Get connection type to call object slot in GUI thread with invokeMethod.
Definition: guiutil.cpp:378
void updateHeadersPresyncProgressLabel(int64_t height, const QDateTime &blockDate)
void setWalletActionsEnabled(bool enabled)
Enable or disable all wallet-related actions.
Definition: bitcoingui.cpp:853
void networkActiveChanged(bool networkActive)
BitcoinUnit getDisplayUnit() const
Definition: optionsmodel.h:103
QAction * aboutQtAction
Definition: bitcoingui.h:151
void setClientModel(ClientModel *clientModel=nullptr, interfaces::BlockAndHeaderTipInfo *tip_info=nullptr)
Set the client model.
Definition: bitcoingui.cpp:664
Controller between interfaces::Node, WalletModel instances and the GUI.
OptionsModel * getOptionsModel()
bool getShowTrayIcon() const
Definition: optionsmodel.h:100
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
std::string translated
Definition: translation.h:26
QMenu * m_open_wallet_menu
Definition: bitcoingui.h:157
macOS-specific Dock icon handler.
void outOfSyncWarningClicked()
Notify that the out of sync warning icon has been pressed.
Bitcoin GUI main class.
Definition: bitcoingui.h:67
bool isLayerVisible() const
Definition: modaloverlay.h:33
HelpMessageDialog * helpMessageDialog
Definition: bitcoingui.h:174
QLabel * progressBarLabel
Definition: bitcoingui.h:129
QSystemTrayIcon * trayIcon
Definition: bitcoingui.h:170
QAction * showHelpMessageAction
Definition: bitcoingui.h:154
void ShowModalDialogAsynchronously(QDialog *dialog)
Shows a QDialog instance asynchronously, and deletes it on close.
Definition: guiutil.cpp:978
void format(std::ostream &out, FormatStringCheck< sizeof...(Args)> fmt, const Args &... args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1079
Notify user of potential problem.
Definition: notificator.h:37
Modal overlay to display information about the chain-sync state.
Definition: modaloverlay.h:20
bool isPrivacyModeActivated() const
void changeEvent(QEvent *e) override
const QString & getTitleAddText() const
Definition: networkstyle.h:24
void changeEvent(QEvent *e) override
void numConnectionsChanged(int count)
void setNetworkActive(bool network_active)
Set network state shown in the UI.
Signals for UI communication.
Definition: interface_ui.h:25
void removeAllWallets()
GUIUtil::ClickableLabel * connectionsControl
Definition: bitcoingui.h:127
QAction * backupWalletAction
Definition: bitcoingui.h:149
QAction * m_load_psbt_clipboard_action
Definition: bitcoingui.h:144
void setOptionsModel(OptionsModel *optionsModel)
Lets the control know about the Options Model (and its signals)
void dropEvent(QDropEvent *event) override
void bringToFront(QWidget *w)
Definition: guiutil.cpp:406
QString tabTitle(TabTypes tab_type) const
static QString formatWithUnit(Unit unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD)
Format as string (with unit)
Force blocking, modal message box dialog (not just OS notification)
Definition: interface_ui.h:60
void openOptionsDialogWithTab(OptionsDialog::Tab tab)
Open the OptionsDialog on the specified tab index.
EncryptionStatus getEncryptionStatus() const
virtual std::unique_ptr< Handler > handleMessageBox(MessageBoxFn fn)=0
void showOutOfSyncWarning(bool fShow)
void gotoHistoryPage()
Switch to history (transactions) page.
QAction * usedReceivingAddressesAction
Definition: bitcoingui.h:140
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
void showModalOverlay()
const NetworkStyle *const m_network_style
Definition: bitcoingui.h:188
WalletController * m_wallet_controller
Definition: bitcoingui.h:117
void gotoOverviewPage()
Switch to overview (home) page.
BlockSource getBlockSource() const
Returns the block source of the current importing/syncing state.
const PlatformStyle * platformStyle
Definition: bitcoingui.h:187
void displayUnitChanged(BitcoinUnit unit)
virtual bool hdEnabled()=0
void showProgress(const QString &title, int nProgress)
Show progress dialog e.g.
static MacDockIconHandler * instance()
void setClientModel(ClientModel *clientModel)
Definition: walletframe.cpp:60
bool isObscured(QWidget *w)
Definition: guiutil.cpp:397
QAction * m_wallet_selector_label_action
Definition: bitcoingui.h:161
int getNumConnections(unsigned int flags=CONNECTIONS_ALL) const
Return number of connections, default is in- and outbound (total)
Definition: clientmodel.cpp:84
OptionsModel * optionsModel
Definition: bitcoingui.h:340
void created(WalletModel *wallet_model)
QLabel * m_wallet_selector_label
Definition: bitcoingui.h:167
void optionsClicked()
Show configuration dialog.
Definition: bitcoingui.cpp:967
void setNumBlocks(int count, const QDateTime &blockDate, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state)
Set number of blocks and last block date shown in the UI.
void closeWallet(WalletModel *wallet_model, QWidget *parent=nullptr)
void gotoVerifyMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to verify message tab.
void incomingTransaction(const QString &date, BitcoinUnit unit, const CAmount &amount, const QString &type, const QString &address, const QString &label, const QString &walletName)
Notify that a new transaction appeared.
bool HasPixmap(const QLabel *label)
Returns true if pixmap has been set.
Definition: guiutil.cpp:955
void handleCloseWindowShortcut(QWidget *w)
Definition: guiutil.cpp:424
void notify(Class cls, const QString &title, const QString &text, const QIcon &icon=QIcon(), int millisTimeout=10000)
Show notification message.
const char * name
Definition: rest.cpp:48
QToolBar * appToolBar
Definition: bitcoingui.h:134
BlockSource
Definition: clientmodel.h:36
WalletFrame * walletFrame
Definition: bitcoingui.h:121
WalletView * currentWalletView() const
QAction * usedSendingAddressesAction
Definition: bitcoingui.h:139
void setTabFocus(enum TabTypes tabType)
set which tab has the focus (is visible)
int64_t nPowTargetSpacing
Definition: params.h:120
BitcoinGUI(interfaces::Node &node, const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent=nullptr)
Definition: bitcoingui.cpp:91
void updateDisplayUnit(BitcoinUnit newUnits)
When Display Units are changed on OptionsModel it will refresh the display text of the control on the...
void message(const QString &title, const QString &message, unsigned int style)
Fired when a message should be reported to the user.
void numBlocksChanged(int count, const QDateTime &blockDate, double nVerificationProgress, SyncType header, SynchronizationState sync_state)
void toggleVisibility()
QVariant getOption(OptionID option, const std::string &suffix="") const
bool enableWallet
Definition: bitcoingui.h:95
auto ExceptionSafeConnect(Sender sender, Signal signal, Receiver receiver, Slot method, Qt::ConnectionType type=Qt::AutoConnection)
A drop-in replacement of QObject::connect function (see: https://doc.qt.io/qt-5/qobject.html#connect-3), that guaranties that all exceptions are handled within the slot.
Definition: guiutil.h:369
QAction * openRPCConsoleAction
Definition: bitcoingui.h:152
QAction * m_close_all_wallets_action
Definition: bitcoingui.h:160
void currentWalletSet()
std::vector< TabTypes > tabs() const
Definition: rpcconsole.h:78
static constexpr int64_t MAX_BLOCK_TIME_GAP
Maximum gap between node time and block time used for the "Catching up..." mode in GUI...
Definition: bitcoingui.cpp:79
void detectShutdown()
called by a timer to check if shutdown has been requested
void migrated(WalletModel *wallet_model)
Cross-platform desktop notification client.
Definition: notificator.h:22
void clicked(const QPoint &point)
Emitted when the label is clicked.
Block and header tip information.
Definition: node.h:49
void setKnownBestHeight(int count, const QDateTime &blockDate, bool presync)
GUIUtil::ClickableLabel * labelBlocksIcon
Definition: bitcoingui.h:128
Informational message.
Definition: notificator.h:36
GUIUtil::ClickableProgressBar * progressBar
Definition: bitcoingui.h:130
void updateWindowTitle()
void showHelpMessageClicked()
Show help message dialog.
Definition: bitcoingui.cpp:993
QString getWalletName() const
void walletAdded(WalletModel *wallet_model)
void message(const QString &title, const QString &message, unsigned int style)
Notificator * notificator
Definition: bitcoingui.h:172
void PolishProgressDialog(QProgressDialog *dialog)
Definition: guiutil.cpp:896
void changePassphrase()
Change encrypted wallet passphrase.
Model for Bitcoin network client.
Definition: clientmodel.h:56
An error occurred.
Definition: notificator.h:38
void restored(WalletModel *wallet_model)
const QIcon & getTrayAndWindowIcon() const
Definition: networkstyle.h:23
void mousePressEvent(QMouseEvent *event) override
So that it responds to left-button clicks.
ClickableProgressBar ProgressBar
Definition: guiutil.h:300
void gotoSignMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to sign message tab.
virtual bool shutdownRequested()=0
Return whether shutdown was requested.
virtual std::vector< std::unique_ptr< Wallet > > getWallets()=0
Return interfaces for accessing wallets (if any).
QAction * sendCoinsAction
Definition: bitcoingui.h:138
void showHide(bool hide=false, bool userRequested=false)
QAction * m_create_wallet_action
Definition: bitcoingui.h:155
SyncType
Definition: clientmodel.h:42
QKeySequence tabShortcut(TabTypes tab_type) const
Definition: messages.h:21
static const int STATUSBAR_ICONSIZE
Definition: guiconstants.h:23
void message(const QString &title, QString message, unsigned int style, bool *ret=nullptr, const QString &detailed_message=QString())
Notify the user of an event from the core network or transaction handling code.
QColor SingleColor() const
void encryptionStatusChanged()
Encryption status of wallet changed.
QAction * openAction
Definition: bitcoingui.h:153
bool getMinimizeOnClose() const
Definition: optionsmodel.h:102
void updateProxyIcon()
Set the proxy-enabled icon as shown in the UI.
QAction * changePassphraseAction
Definition: bitcoingui.h:150
void gotoSendCoinsPage(QString addr="")
Switch to send coins page.
virtual std::unique_ptr< Handler > handleQuestion(QuestionFn fn)=0
void encryptWallet()
Encrypt the wallet.
QString WalletDisplayName(const QString &name)
Definition: guiutil.cpp:985
void gotoReceiveCoinsPage()
Switch to receive coins page.
const std::unique_ptr< QMenu > trayIconMenu
Definition: bitcoingui.h:171
QMenu * m_network_context_menu
Definition: bitcoingui.h:177
void setPrivacy(bool privacy)
std::string original
Definition: translation.h:25
Interface from Qt to configuration data structure for Bitcoin client.
Definition: optionsmodel.h:42
std::unique_ptr< interfaces::Handler > m_handler_question
Definition: bitcoingui.h:119
const CChainParams & Params()
Return the currently selected parameters.
bool getMinimizeToTray() const
Definition: optionsmodel.h:101
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:48
virtual WalletLoader & walletLoader()=0
Get wallet loader.
QAction * m_restore_wallet_action
Definition: bitcoingui.h:158
std::map< std::string, std::pair< bool, std::string > > listWalletDir() const
Returns all wallet names in the wallet dir mapped to whether the wallet is loaded.
bool eventFilter(QObject *object, QEvent *event) override
WalletModel * getWalletModel() const noexcept
Definition: walletview.h:46
int prevBlocks
Keep track of previous number of blocks, to detect progress.
Definition: bitcoingui.h:184
void toggleHidden()
Simply calls showNormalIfMinimized(true)
interfaces::Node & m_node
Definition: bitcoingui.h:116
int spinnerFrame
Definition: bitcoingui.h:185
void walletRemoved(WalletModel *wallet_model)
GUIUtil::ThemedLabel * labelWalletEncryptionIcon
Definition: bitcoingui.h:124
void quitOnReset()
static int count
void setNumConnections(int count)
Set number of connections shown in the UI.
QString getDisplayName() const
static bool ThreadSafeMessageBox(BitcoinGUI *gui, const bilingual_str &message, unsigned int style)
"Help message" dialog box
Definition: utilitydialog.h:20
void backupWallet()
Backup the wallet.
void closeEvent(QCloseEvent *event) override
QComboBox * m_wallet_selector
Definition: bitcoingui.h:168
bool addView(WalletView *walletView)
Definition: walletframe.cpp:69
Preferences dialog.
Definition: optionsdialog.h:36
void clicked(const QPoint &point)
Emitted when the progressbar is clicked.
QString formatNiceTimeOffset(qint64 secs)
Definition: guiutil.cpp:782
void createContextMenu()
Creates context menu, its actions, and wires up all the relevant signals for mouse events...
void showDebugWindowActivateConsole()
Show debug window and set focus to the console.
Definition: bitcoingui.cpp:987
void createActions()
Create the main UI actions.
Definition: bitcoingui.cpp:253
QAction * optionsAction
Definition: bitcoingui.h:147
QAction * encryptWalletAction
Definition: bitcoingui.h:148
void aboutClicked()
Show about dialog.
Definition: bitcoingui.cpp:972
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:89
const PlatformStyle * m_platform_style
Definition: bitcoingui.h:342
void createWallet()
Launch the wallet creation modal (no-op if wallet is not compiled)
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:180
void removeWallet(WalletModel *wallet_model)
int getHeaderTipHeight() const
Definition: clientmodel.cpp:98
void updateHeadersSyncProgressLabel()
void gotoLoadPSBT(bool from_clipboard=false)
Load Partially Signed Bitcoin Transaction.
static const std::string DEFAULT_UIPLATFORM
Definition: bitcoingui.h:72
static QString longName(Unit unit)
Long name.
void coinsSent()
virtual void setNetworkActive(bool active)=0
Set network active.
int64_t getHeaderTipTime() const
GUIUtil::ThemedLabel * labelWalletHDStatusIcon
Definition: bitcoingui.h:125
static RPCHelpMan help()
Definition: server.cpp:119
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:69
void transactionClicked()
A container for embedding all wallet-related controls into BitcoinGUI.
Definition: walletframe.h:28
void showProgress(const QString &title, int nProgress)
void usedSendingAddresses()
Show used sending addresses.
void setDisplayUnit(const QVariant &new_unit)
Updates current unit in memory, settings and emits displayUnitChanged(new_unit) signal.
void onDisplayUnitsClicked(const QPoint &point)
Shows context menu with Display Unit options by the mouse coordinates.
void createMenuBar()
Create the menu bar and sub-menus.
Definition: bitcoingui.cpp:534
void onMenuSelection(QAction *action)
Tells underlying optionsModel to update its current display unit.
std::unique_ptr< interfaces::Handler > m_handler_message_box
Definition: bitcoingui.h:118
void showTrayIconChanged(bool)
#define SPINNER_FRAMES
Definition: guiconstants.h:47
void dragEnterEvent(QDragEnterEvent *event) override
bool getProxyInfo(std::string &ip_port) const