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