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