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