Bitcoin Core 28.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 <bitcoin-build-config.h> // IWYU pragma: keep
6
7#include <qt/bitcoingui.h>
8
9#include <qt/bitcoinunits.h>
10#include <qt/clientmodel.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
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
75const 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
85BitcoinGUI::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
138
139 // Create application menu bar
141
142 // Create the toolbars
144
145 // Create system tray icon and notification
146 if (QSystemTrayIcon::isSystemTrayAvailable()) {
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);
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(CLIENT_NAME), this);
298 aboutAction->setStatusTip(tr("Show information about %1").arg(CLIENT_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(CLIENT_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 m_migrate_wallet_menu = new QMenu(this);
364
365 showHelpMessageAction = new QAction(tr("&Command-line options"), this);
366 showHelpMessageAction->setMenuRole(QAction::NoRole);
367 showHelpMessageAction->setStatusTip(tr("Show the %1 help message to get a list with possible Bitcoin command-line options").arg(CLIENT_NAME));
368
369 m_mask_values_action = new QAction(tr("&Mask values"), this);
370 m_mask_values_action->setShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_M));
371 m_mask_values_action->setStatusTip(tr("Mask the values in the Overview tab"));
372 m_mask_values_action->setCheckable(true);
373
374 connect(quitAction, &QAction::triggered, this, &BitcoinGUI::quitRequested);
375 connect(aboutAction, &QAction::triggered, this, &BitcoinGUI::aboutClicked);
376 connect(aboutQtAction, &QAction::triggered, qApp, QApplication::aboutQt);
377 connect(optionsAction, &QAction::triggered, this, &BitcoinGUI::optionsClicked);
378 connect(showHelpMessageAction, &QAction::triggered, this, &BitcoinGUI::showHelpMessageClicked);
379 connect(openRPCConsoleAction, &QAction::triggered, this, &BitcoinGUI::showDebugWindow);
380 // prevents an open debug window from becoming stuck/unusable on client shutdown
381 connect(quitAction, &QAction::triggered, rpcConsole, &QWidget::hide);
382
383#ifdef ENABLE_WALLET
384 if(walletFrame)
385 {
386 connect(encryptWalletAction, &QAction::triggered, walletFrame, &WalletFrame::encryptWallet);
387 connect(backupWalletAction, &QAction::triggered, walletFrame, &WalletFrame::backupWallet);
389 connect(signMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
390 connect(signMessageAction, &QAction::triggered, [this]{ gotoSignMessageTab(); });
391 connect(m_load_psbt_action, &QAction::triggered, [this]{ gotoLoadPSBT(); });
392 connect(m_load_psbt_clipboard_action, &QAction::triggered, [this]{ gotoLoadPSBT(true); });
393 connect(verifyMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
394 connect(verifyMessageAction, &QAction::triggered, [this]{ gotoVerifyMessageTab(); });
397 connect(openAction, &QAction::triggered, this, &BitcoinGUI::openClicked);
398 connect(m_open_wallet_menu, &QMenu::aboutToShow, [this] {
399 m_open_wallet_menu->clear();
400 for (const auto& [path, info] : m_wallet_controller->listWalletDir()) {
401 const auto& [loaded, _] = info;
402 QString name = GUIUtil::WalletDisplayName(path);
403 // An single ampersand in the menu item's text sets a shortcut for this item.
404 // Single & are shown when && is in the string. So replace & with &&.
405 name.replace(QChar('&'), QString("&&"));
406 QAction* action = m_open_wallet_menu->addAction(name);
407
408 if (loaded) {
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_menu, &QMenu::aboutToShow, [this] {
460 m_migrate_wallet_menu->clear();
461 for (const auto& [wallet_name, info] : m_wallet_controller->listWalletDir()) {
462 const auto& [loaded, format] = info;
463
464 if (format != "bdb") { // Skip already migrated wallets
465 continue;
466 }
467
468 QString name = GUIUtil::WalletDisplayName(wallet_name);
469 // An single ampersand in the menu item's text sets a shortcut for this item.
470 // Single & are shown when && is in the string. So replace & with &&.
471 name.replace(QChar('&'), QString("&&"));
472 QAction* action = m_migrate_wallet_menu->addAction(name);
473
474 connect(action, &QAction::triggered, [this, wallet_name] {
475 auto activity = new MigrateWalletActivity(m_wallet_controller, this);
476 connect(activity, &MigrateWalletActivity::migrated, this, &BitcoinGUI::setCurrentWallet);
477 activity->migrate(wallet_name);
478 });
479 }
480 if (m_migrate_wallet_menu->isEmpty()) {
481 QAction* action = m_migrate_wallet_menu->addAction(tr("No wallets available"));
482 action->setEnabled(false);
483 }
484 });
485 connect(m_mask_values_action, &QAction::toggled, this, &BitcoinGUI::setPrivacy);
486 connect(m_mask_values_action, &QAction::toggled, this, &BitcoinGUI::enableHistoryAction);
487 }
488#endif // ENABLE_WALLET
489
490 connect(new QShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_C), this), &QShortcut::activated, this, &BitcoinGUI::showDebugWindowActivateConsole);
491 connect(new QShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_D), this), &QShortcut::activated, this, &BitcoinGUI::showDebugWindow);
492}
493
495{
496 appMenuBar = menuBar();
497
498 // Configure the menus
499 QMenu *file = appMenuBar->addMenu(tr("&File"));
500 if(walletFrame)
501 {
502 file->addAction(m_create_wallet_action);
503 file->addAction(m_open_wallet_action);
504 file->addAction(m_close_wallet_action);
505 file->addAction(m_close_all_wallets_action);
506 file->addAction(m_migrate_wallet_action);
507 file->addSeparator();
508 file->addAction(backupWalletAction);
509 file->addAction(m_restore_wallet_action);
510 file->addSeparator();
511 file->addAction(openAction);
512 file->addAction(signMessageAction);
513 file->addAction(verifyMessageAction);
514 file->addAction(m_load_psbt_action);
515 file->addAction(m_load_psbt_clipboard_action);
516 file->addSeparator();
517 }
518 file->addAction(quitAction);
519
520 QMenu *settings = appMenuBar->addMenu(tr("&Settings"));
521 if(walletFrame)
522 {
523 settings->addAction(encryptWalletAction);
524 settings->addAction(changePassphraseAction);
525 settings->addSeparator();
526 settings->addAction(m_mask_values_action);
527 settings->addSeparator();
528 }
529 settings->addAction(optionsAction);
530
531 QMenu* window_menu = appMenuBar->addMenu(tr("&Window"));
532
533 QAction* minimize_action = window_menu->addAction(tr("&Minimize"));
534 minimize_action->setShortcut(QKeySequence(tr("Ctrl+M")));
535 connect(minimize_action, &QAction::triggered, [] {
536 QApplication::activeWindow()->showMinimized();
537 });
538 connect(qApp, &QApplication::focusWindowChanged, this, [minimize_action] (QWindow* window) {
539 minimize_action->setEnabled(window != nullptr && (window->flags() & Qt::Dialog) != Qt::Dialog && window->windowState() != Qt::WindowMinimized);
540 });
541
542#ifdef Q_OS_MACOS
543 QAction* zoom_action = window_menu->addAction(tr("Zoom"));
544 connect(zoom_action, &QAction::triggered, [] {
545 QWindow* window = qApp->focusWindow();
546 if (window->windowState() != Qt::WindowMaximized) {
547 window->showMaximized();
548 } else {
549 window->showNormal();
550 }
551 });
552
553 connect(qApp, &QApplication::focusWindowChanged, this, [zoom_action] (QWindow* window) {
554 zoom_action->setEnabled(window != nullptr);
555 });
556#endif
557
558 if (walletFrame) {
559#ifdef Q_OS_MACOS
560 window_menu->addSeparator();
561 QAction* main_window_action = window_menu->addAction(tr("Main Window"));
562 connect(main_window_action, &QAction::triggered, [this] {
564 });
565#endif
566 window_menu->addSeparator();
567 window_menu->addAction(usedSendingAddressesAction);
568 window_menu->addAction(usedReceivingAddressesAction);
569 }
570
571 window_menu->addSeparator();
572 for (RPCConsole::TabTypes tab_type : rpcConsole->tabs()) {
573 QAction* tab_action = window_menu->addAction(rpcConsole->tabTitle(tab_type));
574 tab_action->setShortcut(rpcConsole->tabShortcut(tab_type));
575 connect(tab_action, &QAction::triggered, [this, tab_type] {
576 rpcConsole->setTabFocus(tab_type);
578 });
579 }
580
581 QMenu *help = appMenuBar->addMenu(tr("&Help"));
582 help->addAction(showHelpMessageAction);
583 help->addSeparator();
584 help->addAction(aboutAction);
585 help->addAction(aboutQtAction);
586}
587
589{
590 if(walletFrame)
591 {
592 QToolBar *toolbar = addToolBar(tr("Tabs toolbar"));
593 appToolBar = toolbar;
594 toolbar->setMovable(false);
595 toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
596 toolbar->addAction(overviewAction);
597 toolbar->addAction(sendCoinsAction);
598 toolbar->addAction(receiveCoinsAction);
599 toolbar->addAction(historyAction);
600 overviewAction->setChecked(true);
601
602#ifdef ENABLE_WALLET
603 QWidget *spacer = new QWidget();
604 spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
605 toolbar->addWidget(spacer);
606
607 m_wallet_selector = new QComboBox();
608 m_wallet_selector->setSizeAdjustPolicy(QComboBox::AdjustToContents);
609 connect(m_wallet_selector, qOverload<int>(&QComboBox::currentIndexChanged), this, &BitcoinGUI::setCurrentWalletBySelectorIndex);
610
611 m_wallet_selector_label = new QLabel();
612 m_wallet_selector_label->setText(tr("Wallet:") + " ");
614
617
618 m_wallet_selector_label_action->setVisible(false);
619 m_wallet_selector_action->setVisible(false);
620#endif
621 }
622}
623
625{
626 this->clientModel = _clientModel;
627 if(_clientModel)
628 {
629 // Create system tray menu (or setup the dock menu) that late to prevent users from calling actions,
630 // while the client has not yet fully loaded
632
633 // Keep up to date with client
637 });
640
641 modalOverlay->setKnownBestHeight(tip_info->header_height, QDateTime::fromSecsSinceEpoch(tip_info->header_time), /*presync=*/false);
642 setNumBlocks(tip_info->block_height, QDateTime::fromSecsSinceEpoch(tip_info->block_time), tip_info->verification_progress, SyncType::BLOCK_SYNC, SynchronizationState::INIT_DOWNLOAD);
643 connect(_clientModel, &ClientModel::numBlocksChanged, this, &BitcoinGUI::setNumBlocks);
644
645 // Receive and report messages from client model
646 connect(_clientModel, &ClientModel::message, [this](const QString &title, const QString &message, unsigned int style){
647 this->message(title, message, style);
648 });
649
650 // Show progress dialog
651 connect(_clientModel, &ClientModel::showProgress, this, &BitcoinGUI::showProgress);
652
653 rpcConsole->setClientModel(_clientModel, tip_info->block_height, tip_info->block_time, tip_info->verification_progress);
654
656
657#ifdef ENABLE_WALLET
658 if(walletFrame)
659 {
660 walletFrame->setClientModel(_clientModel);
661 }
662#endif // ENABLE_WALLET
664
665 OptionsModel* optionsModel = _clientModel->getOptionsModel();
666 if (optionsModel && trayIcon) {
667 // be aware of the tray icon disable state change reported by the OptionsModel object.
668 connect(optionsModel, &OptionsModel::showTrayIconChanged, trayIcon, &QSystemTrayIcon::setVisible);
669
670 // initialize the disable state of the tray icon with the current value in the model.
671 trayIcon->setVisible(optionsModel->getShowTrayIcon());
672 }
673
674 m_mask_values_action->setChecked(_clientModel->getOptionsModel()->getOption(OptionsModel::OptionID::MaskValues).toBool());
675 } else {
676 // Shutdown requested, disable menus
677 if (trayIconMenu)
678 {
679 // Disable context menu on tray icon
680 trayIconMenu->clear();
681 }
682 // Propagate cleared model to child objects
683 rpcConsole->setClientModel(nullptr);
684#ifdef ENABLE_WALLET
685 if (walletFrame)
686 {
687 walletFrame->setClientModel(nullptr);
688 }
689#endif // ENABLE_WALLET
691 // Disable top bar menu actions
692 appMenuBar->clear();
693 }
694}
695
696#ifdef ENABLE_WALLET
697void BitcoinGUI::enableHistoryAction(bool privacy)
698{
700 historyAction->setEnabled(!privacy);
701 if (historyAction->isChecked()) gotoOverviewPage();
702 }
703}
704
705void BitcoinGUI::setWalletController(WalletController* wallet_controller, bool show_loading_minimized)
706{
708 assert(wallet_controller);
709
710 m_wallet_controller = wallet_controller;
711
712 m_create_wallet_action->setEnabled(true);
713 m_open_wallet_action->setEnabled(true);
715 m_restore_wallet_action->setEnabled(true);
716 m_migrate_wallet_action->setEnabled(true);
718
719 GUIUtil::ExceptionSafeConnect(wallet_controller, &WalletController::walletAdded, this, &BitcoinGUI::addWallet);
720 connect(wallet_controller, &WalletController::walletRemoved, this, &BitcoinGUI::removeWallet);
721 connect(wallet_controller, &WalletController::destroyed, this, [this] {
722 // wallet_controller gets destroyed manually, but it leaves our member copy dangling
723 m_wallet_controller = nullptr;
724 });
725
726 auto activity = new LoadWalletsActivity(m_wallet_controller, this);
727 activity->load(show_loading_minimized);
728}
729
730WalletController* BitcoinGUI::getWalletController()
731{
732 return m_wallet_controller;
733}
734
735void BitcoinGUI::addWallet(WalletModel* walletModel)
736{
737 if (!walletFrame || !m_wallet_controller) return;
738
739 WalletView* wallet_view = new WalletView(walletModel, platformStyle, walletFrame);
740 if (!walletFrame->addView(wallet_view)) return;
741
742 rpcConsole->addWallet(walletModel);
743 if (m_wallet_selector->count() == 0) {
745 } else if (m_wallet_selector->count() == 1) {
746 m_wallet_selector_label_action->setVisible(true);
747 m_wallet_selector_action->setVisible(true);
748 }
749
751 connect(wallet_view, &WalletView::transactionClicked, this, &BitcoinGUI::gotoHistoryPage);
752 connect(wallet_view, &WalletView::coinsSent, this, &BitcoinGUI::gotoHistoryPage);
753 connect(wallet_view, &WalletView::message, [this](const QString& title, const QString& message, unsigned int style) {
754 this->message(title, message, style);
755 });
756 connect(wallet_view, &WalletView::encryptionStatusChanged, this, &BitcoinGUI::updateWalletStatus);
757 connect(wallet_view, &WalletView::incomingTransaction, this, &BitcoinGUI::incomingTransaction);
758 connect(this, &BitcoinGUI::setPrivacy, wallet_view, &WalletView::setPrivacy);
759 const bool privacy = isPrivacyModeActivated();
760 wallet_view->setPrivacy(privacy);
761 enableHistoryAction(privacy);
762 const QString display_name = walletModel->getDisplayName();
763 m_wallet_selector->addItem(display_name, QVariant::fromValue(walletModel));
764}
765
766void BitcoinGUI::removeWallet(WalletModel* walletModel)
767{
768 if (!walletFrame) return;
769
772
773 int index = m_wallet_selector->findData(QVariant::fromValue(walletModel));
774 m_wallet_selector->removeItem(index);
775 if (m_wallet_selector->count() == 0) {
777 overviewAction->setChecked(true);
778 } else if (m_wallet_selector->count() == 1) {
779 m_wallet_selector_label_action->setVisible(false);
780 m_wallet_selector_action->setVisible(false);
781 }
782 rpcConsole->removeWallet(walletModel);
783 walletFrame->removeWallet(walletModel);
785}
786
787void BitcoinGUI::setCurrentWallet(WalletModel* wallet_model)
788{
789 if (!walletFrame || !m_wallet_controller) return;
790 walletFrame->setCurrentWallet(wallet_model);
791 for (int index = 0; index < m_wallet_selector->count(); ++index) {
792 if (m_wallet_selector->itemData(index).value<WalletModel*>() == wallet_model) {
793 m_wallet_selector->setCurrentIndex(index);
794 break;
795 }
796 }
798}
799
800void BitcoinGUI::setCurrentWalletBySelectorIndex(int index)
801{
802 WalletModel* wallet_model = m_wallet_selector->itemData(index).value<WalletModel*>();
803 if (wallet_model) setCurrentWallet(wallet_model);
804}
805
806void BitcoinGUI::removeAllWallets()
807{
808 if(!walletFrame)
809 return;
812}
813#endif // ENABLE_WALLET
814
816{
817 overviewAction->setEnabled(enabled);
818 sendCoinsAction->setEnabled(enabled);
819 receiveCoinsAction->setEnabled(enabled);
820 historyAction->setEnabled(enabled);
821 encryptWalletAction->setEnabled(enabled);
822 backupWalletAction->setEnabled(enabled);
823 changePassphraseAction->setEnabled(enabled);
824 signMessageAction->setEnabled(enabled);
825 verifyMessageAction->setEnabled(enabled);
826 usedSendingAddressesAction->setEnabled(enabled);
827 usedReceivingAddressesAction->setEnabled(enabled);
828 openAction->setEnabled(enabled);
829 m_close_wallet_action->setEnabled(enabled);
830 m_close_all_wallets_action->setEnabled(enabled);
831}
832
834{
835 assert(QSystemTrayIcon::isSystemTrayAvailable());
836
837#ifndef Q_OS_MACOS
838 if (QSystemTrayIcon::isSystemTrayAvailable()) {
839 trayIcon = new QSystemTrayIcon(m_network_style->getTrayAndWindowIcon(), this);
840 QString toolTip = tr("%1 client").arg(CLIENT_NAME) + " " + m_network_style->getTitleAddText();
841 trayIcon->setToolTip(toolTip);
842 }
843#endif
844}
845
847{
848#ifndef Q_OS_MACOS
849 if (!trayIcon) return;
850#endif // Q_OS_MACOS
851
852 // Configuration of the tray icon (or Dock icon) menu.
853 QAction* show_hide_action{nullptr};
854#ifndef Q_OS_MACOS
855 // Note: On macOS, the Dock icon's menu already has Show / Hide action.
856 show_hide_action = trayIconMenu->addAction(QString(), this, &BitcoinGUI::toggleHidden);
857 trayIconMenu->addSeparator();
858#endif // Q_OS_MACOS
859
860 QAction* send_action{nullptr};
861 QAction* receive_action{nullptr};
862 QAction* sign_action{nullptr};
863 QAction* verify_action{nullptr};
864 if (enableWallet) {
865 send_action = trayIconMenu->addAction(sendCoinsAction->text(), sendCoinsAction, &QAction::trigger);
866 receive_action = trayIconMenu->addAction(receiveCoinsAction->text(), receiveCoinsAction, &QAction::trigger);
867 trayIconMenu->addSeparator();
868 sign_action = trayIconMenu->addAction(signMessageAction->text(), signMessageAction, &QAction::trigger);
869 verify_action = trayIconMenu->addAction(verifyMessageAction->text(), verifyMessageAction, &QAction::trigger);
870 trayIconMenu->addSeparator();
871 }
872 QAction* options_action = trayIconMenu->addAction(optionsAction->text(), optionsAction, &QAction::trigger);
873 options_action->setMenuRole(QAction::PreferencesRole);
874 QAction* node_window_action = trayIconMenu->addAction(openRPCConsoleAction->text(), openRPCConsoleAction, &QAction::trigger);
875 QAction* quit_action{nullptr};
876#ifndef Q_OS_MACOS
877 // Note: On macOS, the Dock icon's menu already has Quit action.
878 trayIconMenu->addSeparator();
879 quit_action = trayIconMenu->addAction(quitAction->text(), quitAction, &QAction::trigger);
880
881 trayIcon->setContextMenu(trayIconMenu.get());
882 connect(trayIcon, &QSystemTrayIcon::activated, [this](QSystemTrayIcon::ActivationReason reason) {
883 if (reason == QSystemTrayIcon::Trigger) {
884 // Click on system tray icon triggers show/hide of the main window
885 toggleHidden();
886 }
887 });
888#else
889 // Note: On macOS, the Dock icon is used to provide the tray's functionality.
891 connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, [this] {
892 if (m_node.shutdownRequested()) return; // nothing to show, node is shutting down.
893 show();
894 activateWindow();
895 });
896 trayIconMenu->setAsDockMenu();
897#endif // Q_OS_MACOS
898
899 connect(
900 // Using QSystemTrayIcon::Context is not reliable.
901 // See https://bugreports.qt.io/browse/QTBUG-91697
902 trayIconMenu.get(), &QMenu::aboutToShow,
903 [this, show_hide_action, send_action, receive_action, sign_action, verify_action, options_action, node_window_action, quit_action] {
904 if (m_node.shutdownRequested()) return; // nothing to do, node is shutting down.
905
906 if (show_hide_action) show_hide_action->setText(
907 (!isHidden() && !isMinimized() && !GUIUtil::isObscured(this)) ?
908 tr("&Hide") :
909 tr("S&how"));
910 if (QApplication::activeModalWidget()) {
911 for (QAction* a : trayIconMenu.get()->actions()) {
912 a->setEnabled(false);
913 }
914 } else {
915 if (show_hide_action) show_hide_action->setEnabled(true);
916 if (enableWallet) {
917 send_action->setEnabled(sendCoinsAction->isEnabled());
918 receive_action->setEnabled(receiveCoinsAction->isEnabled());
919 sign_action->setEnabled(signMessageAction->isEnabled());
920 verify_action->setEnabled(verifyMessageAction->isEnabled());
921 }
922 options_action->setEnabled(optionsAction->isEnabled());
923 node_window_action->setEnabled(openRPCConsoleAction->isEnabled());
924 if (quit_action) quit_action->setEnabled(true);
925 }
926 });
927}
928
930{
932}
933
935{
936 if(!clientModel)
937 return;
938
939 auto dlg = new HelpMessageDialog(this, /*about=*/true);
941}
942
944{
946 Q_EMIT consoleShown(rpcConsole);
947}
948
950{
953}
954
956{
958}
959
960#ifdef ENABLE_WALLET
961void BitcoinGUI::openClicked()
962{
963 OpenURIDialog dlg(platformStyle, this);
964 if(dlg.exec())
965 {
966 Q_EMIT receivedURI(dlg.getURI());
967 }
968}
969
970void BitcoinGUI::gotoOverviewPage()
971{
972 overviewAction->setChecked(true);
974}
975
976void BitcoinGUI::gotoHistoryPage()
977{
978 historyAction->setChecked(true);
980}
981
982void BitcoinGUI::gotoReceiveCoinsPage()
983{
984 receiveCoinsAction->setChecked(true);
986}
987
988void BitcoinGUI::gotoSendCoinsPage(QString addr)
989{
990 sendCoinsAction->setChecked(true);
992}
993
994void BitcoinGUI::gotoSignMessageTab(QString addr)
995{
997}
998
999void BitcoinGUI::gotoVerifyMessageTab(QString addr)
1000{
1002}
1003void BitcoinGUI::gotoLoadPSBT(bool from_clipboard)
1004{
1005 if (walletFrame) walletFrame->gotoLoadPSBT(from_clipboard);
1006}
1007#endif // ENABLE_WALLET
1008
1010{
1011 if (!clientModel) return;
1013 QString icon;
1014 switch(count)
1015 {
1016 case 0: icon = ":/icons/connect_0"; break;
1017 case 1: case 2: case 3: icon = ":/icons/connect_1"; break;
1018 case 4: case 5: case 6: icon = ":/icons/connect_2"; break;
1019 case 7: case 8: case 9: icon = ":/icons/connect_3"; break;
1020 default: icon = ":/icons/connect_4"; break;
1021 }
1022
1023 QString tooltip;
1024
1025 if (m_node.getNetworkActive()) {
1026 //: A substring of the tooltip.
1027 tooltip = tr("%n active connection(s) to Bitcoin network.", "", count);
1028 } else {
1029 //: A substring of the tooltip.
1030 tooltip = tr("Network activity disabled.");
1031 icon = ":/icons/network_disabled";
1032 }
1033
1034 // Don't word-wrap this (fixed-width) tooltip
1035 tooltip = QLatin1String("<nobr>") + tooltip + QLatin1String("<br>") +
1036 //: A substring of the tooltip. "More actions" are available via the context menu.
1037 tr("Click for more actions.") + QLatin1String("</nobr>");
1038 connectionsControl->setToolTip(tooltip);
1039
1041}
1042
1044{
1046}
1047
1048void BitcoinGUI::setNetworkActive(bool network_active)
1049{
1051 m_network_context_menu->clear();
1052 m_network_context_menu->addAction(
1053 //: A context menu item. The "Peers tab" is an element of the "Node window".
1054 tr("Show Peers tab"),
1055 [this] {
1058 });
1059 m_network_context_menu->addAction(
1060 network_active ?
1061 //: A context menu item.
1062 tr("Disable network activity") :
1063 //: A context menu item. The network activity was disabled previously.
1064 tr("Enable network activity"),
1065 [this, new_state = !network_active] { m_node.setNetworkActive(new_state); });
1066}
1067
1069{
1070 int64_t headersTipTime = clientModel->getHeaderTipTime();
1071 int headersTipHeight = clientModel->getHeaderTipHeight();
1072 int estHeadersLeft = (GetTime() - headersTipTime) / Params().GetConsensus().nPowTargetSpacing;
1073 if (estHeadersLeft > HEADER_HEIGHT_DELTA_SYNC)
1074 progressBarLabel->setText(tr("Syncing Headers (%1%)…").arg(QString::number(100.0 / (headersTipHeight+estHeadersLeft)*headersTipHeight, 'f', 1)));
1075}
1076
1077void BitcoinGUI::updateHeadersPresyncProgressLabel(int64_t height, const QDateTime& blockDate)
1078{
1079 int estHeadersLeft = blockDate.secsTo(QDateTime::currentDateTime()) / Params().GetConsensus().nPowTargetSpacing;
1080 if (estHeadersLeft > HEADER_HEIGHT_DELTA_SYNC)
1081 progressBarLabel->setText(tr("Pre-syncing Headers (%1%)…").arg(QString::number(100.0 / (height+estHeadersLeft)*height, 'f', 1)));
1082}
1083
1085{
1087 return;
1088
1089 auto dlg = new OptionsDialog(this, enableWallet);
1091 dlg->setCurrentTab(tab);
1092 dlg->setClientModel(clientModel);
1093 dlg->setModel(clientModel->getOptionsModel());
1095}
1096
1097void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state)
1098{
1099// Disabling macOS App Nap on initial sync, disk and reindex operations.
1100#ifdef Q_OS_MACOS
1101 if (sync_state == SynchronizationState::POST_INIT) {
1102 m_app_nap_inhibitor->enableAppNap();
1103 } else {
1104 m_app_nap_inhibitor->disableAppNap();
1105 }
1106#endif
1107
1108 if (modalOverlay)
1109 {
1110 if (synctype != SyncType::BLOCK_SYNC)
1112 else
1113 modalOverlay->tipUpdate(count, blockDate, nVerificationProgress);
1114 }
1115 if (!clientModel)
1116 return;
1117
1118 // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbled text)
1119 statusBar()->clearMessage();
1120
1121 // Acquire current block source
1122 BlockSource blockSource{clientModel->getBlockSource()};
1123 switch (blockSource) {
1125 if (synctype == SyncType::HEADER_PRESYNC) {
1127 return;
1128 } else if (synctype == SyncType::HEADER_SYNC) {
1130 return;
1131 }
1132 progressBarLabel->setText(tr("Synchronizing with network…"));
1134 break;
1135 case BlockSource::DISK:
1136 if (synctype != SyncType::BLOCK_SYNC) {
1137 progressBarLabel->setText(tr("Indexing blocks on disk…"));
1138 } else {
1139 progressBarLabel->setText(tr("Processing blocks on disk…"));
1140 }
1141 break;
1142 case BlockSource::NONE:
1143 if (synctype != SyncType::BLOCK_SYNC) {
1144 return;
1145 }
1146 progressBarLabel->setText(tr("Connecting to peers…"));
1147 break;
1148 }
1149
1150 QString tooltip;
1151
1152 QDateTime currentDate = QDateTime::currentDateTime();
1153 qint64 secs = blockDate.secsTo(currentDate);
1154
1155 tooltip = tr("Processed %n block(s) of transaction history.", "", count);
1156
1157 // Set icon state: spinning if catching up, tick otherwise
1158 if (secs < MAX_BLOCK_TIME_GAP) {
1159 tooltip = tr("Up to date") + QString(".<br>") + tooltip;
1160 labelBlocksIcon->setThemedPixmap(QStringLiteral(":/icons/synced"), STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE);
1161
1162#ifdef ENABLE_WALLET
1163 if(walletFrame)
1164 {
1166 modalOverlay->showHide(true, true);
1167 }
1168#endif // ENABLE_WALLET
1169
1170 progressBarLabel->setVisible(false);
1171 progressBar->setVisible(false);
1172 }
1173 else
1174 {
1175 QString timeBehindText = GUIUtil::formatNiceTimeOffset(secs);
1176
1177 progressBarLabel->setVisible(true);
1178 progressBar->setFormat(tr("%1 behind").arg(timeBehindText));
1179 progressBar->setMaximum(1000000000);
1180 progressBar->setValue(nVerificationProgress * 1000000000.0 + 0.5);
1181 progressBar->setVisible(true);
1182
1183 tooltip = tr("Catching up…") + QString("<br>") + tooltip;
1184 if(count != prevBlocks)
1185 {
1187 QString(":/animation/spinner-%1").arg(spinnerFrame, 3, 10, QChar('0')),
1190 }
1191 prevBlocks = count;
1192
1193#ifdef ENABLE_WALLET
1194 if(walletFrame)
1195 {
1198 }
1199#endif // ENABLE_WALLET
1200
1201 tooltip += QString("<br>");
1202 tooltip += tr("Last received block was generated %1 ago.").arg(timeBehindText);
1203 tooltip += QString("<br>");
1204 tooltip += tr("Transactions after this will not yet be visible.");
1205 }
1206
1207 // Don't word-wrap this (fixed-width) tooltip
1208 tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
1209
1210 labelBlocksIcon->setToolTip(tooltip);
1211 progressBarLabel->setToolTip(tooltip);
1212 progressBar->setToolTip(tooltip);
1213}
1214
1216{
1217#ifdef ENABLE_WALLET
1218#ifndef USE_SQLITE
1219 // Compiled without sqlite support (required for descriptor wallets)
1220 message(tr("Error creating wallet"), tr("Cannot create new wallet, the software was compiled without sqlite support (required for descriptor wallets)"), CClientUIInterface::MSG_ERROR);
1221 return;
1222#endif // USE_SQLITE
1223 auto activity = new CreateWalletActivity(getWalletController(), this);
1224 connect(activity, &CreateWalletActivity::created, this, &BitcoinGUI::setCurrentWallet);
1225 connect(activity, &CreateWalletActivity::created, rpcConsole, &RPCConsole::setCurrentWallet);
1226 activity->create();
1227#endif // ENABLE_WALLET
1228}
1229
1230void BitcoinGUI::message(const QString& title, QString message, unsigned int style, bool* ret, const QString& detailed_message)
1231{
1232 // Default title. On macOS, the window title is ignored (as required by the macOS Guidelines).
1233 QString strTitle{CLIENT_NAME};
1234 // Default to information icon
1235 int nMBoxIcon = QMessageBox::Information;
1236 int nNotifyIcon = Notificator::Information;
1237
1238 QString msgType;
1239 if (!title.isEmpty()) {
1240 msgType = title;
1241 } else {
1242 switch (style) {
1244 msgType = tr("Error");
1245 message = tr("Error: %1").arg(message);
1246 break;
1248 msgType = tr("Warning");
1249 message = tr("Warning: %1").arg(message);
1250 break;
1252 msgType = tr("Information");
1253 // No need to prepend the prefix here.
1254 break;
1255 default:
1256 break;
1257 }
1258 }
1259
1260 if (!msgType.isEmpty()) {
1261 strTitle += " - " + msgType;
1262 }
1263
1264 if (style & CClientUIInterface::ICON_ERROR) {
1265 nMBoxIcon = QMessageBox::Critical;
1266 nNotifyIcon = Notificator::Critical;
1267 } else if (style & CClientUIInterface::ICON_WARNING) {
1268 nMBoxIcon = QMessageBox::Warning;
1269 nNotifyIcon = Notificator::Warning;
1270 }
1271
1272 if (style & CClientUIInterface::MODAL) {
1273 // Check for buttons, use OK as default, if none was supplied
1274 QMessageBox::StandardButton buttons;
1275 if (!(buttons = (QMessageBox::StandardButton)(style & CClientUIInterface::BTN_MASK)))
1276 buttons = QMessageBox::Ok;
1277
1279 QMessageBox mBox(static_cast<QMessageBox::Icon>(nMBoxIcon), strTitle, message, buttons, this);
1280 mBox.setTextFormat(Qt::PlainText);
1281 mBox.setDetailedText(detailed_message);
1282 int r = mBox.exec();
1283 if (ret != nullptr)
1284 *ret = r == QMessageBox::Ok;
1285 } else {
1286 notificator->notify(static_cast<Notificator::Class>(nNotifyIcon), strTitle, message);
1287 }
1288}
1289
1291{
1292 if (e->type() == QEvent::PaletteChange) {
1293 overviewAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/overview")));
1294 sendCoinsAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/send")));
1295 receiveCoinsAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/receiving_addresses")));
1296 historyAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/history")));
1297 }
1298
1299 QMainWindow::changeEvent(e);
1300
1301#ifndef Q_OS_MACOS // Ignored on Mac
1302 if(e->type() == QEvent::WindowStateChange)
1303 {
1305 {
1306 QWindowStateChangeEvent *wsevt = static_cast<QWindowStateChangeEvent*>(e);
1307 if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized())
1308 {
1309 QTimer::singleShot(0, this, &BitcoinGUI::hide);
1310 e->ignore();
1311 }
1312 else if((wsevt->oldState() & Qt::WindowMinimized) && !isMinimized())
1313 {
1314 QTimer::singleShot(0, this, &BitcoinGUI::show);
1315 e->ignore();
1316 }
1317 }
1318 }
1319#endif
1320}
1321
1322void BitcoinGUI::closeEvent(QCloseEvent *event)
1323{
1324#ifndef Q_OS_MACOS // Ignored on Mac
1326 {
1328 {
1329 // close rpcConsole in case it was open to make some space for the shutdown window
1330 rpcConsole->close();
1331
1332 Q_EMIT quitRequested();
1333 }
1334 else
1335 {
1336 QMainWindow::showMinimized();
1337 event->ignore();
1338 }
1339 }
1340#else
1341 QMainWindow::closeEvent(event);
1342#endif
1343}
1344
1345void BitcoinGUI::showEvent(QShowEvent *event)
1346{
1347 // enable the debug window when the main window shows up
1348 openRPCConsoleAction->setEnabled(true);
1349 aboutAction->setEnabled(true);
1350 optionsAction->setEnabled(true);
1351}
1352
1353#ifdef ENABLE_WALLET
1354void BitcoinGUI::incomingTransaction(const QString& date, BitcoinUnit unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName)
1355{
1356 // On new transaction, make an info balloon
1357 QString msg = tr("Date: %1\n").arg(date) +
1358 tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(unit, amount, true));
1359 if (m_node.walletLoader().getWallets().size() > 1 && !walletName.isEmpty()) {
1360 msg += tr("Wallet: %1\n").arg(walletName);
1361 }
1362 msg += tr("Type: %1\n").arg(type);
1363 if (!label.isEmpty())
1364 msg += tr("Label: %1\n").arg(label);
1365 else if (!address.isEmpty())
1366 msg += tr("Address: %1\n").arg(address);
1367 message((amount)<0 ? tr("Sent transaction") : tr("Incoming transaction"),
1369}
1370#endif // ENABLE_WALLET
1371
1372void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
1373{
1374 // Accept only URIs
1375 if(event->mimeData()->hasUrls())
1376 event->acceptProposedAction();
1377}
1378
1379void BitcoinGUI::dropEvent(QDropEvent *event)
1380{
1381 if(event->mimeData()->hasUrls())
1382 {
1383 for (const QUrl &uri : event->mimeData()->urls())
1384 {
1385 Q_EMIT receivedURI(uri.toString());
1386 }
1387 }
1388 event->acceptProposedAction();
1389}
1390
1391bool BitcoinGUI::eventFilter(QObject *object, QEvent *event)
1392{
1393 // Catch status tip events
1394 if (event->type() == QEvent::StatusTip)
1395 {
1396 // Prevent adding text from setStatusTip(), if we currently use the status bar for displaying other stuff
1397 if (progressBarLabel->isVisible() || progressBar->isVisible())
1398 return true;
1399 }
1400 return QMainWindow::eventFilter(object, event);
1401}
1402
1403#ifdef ENABLE_WALLET
1404bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient)
1405{
1406 // URI has to be valid
1407 if (walletFrame && walletFrame->handlePaymentRequest(recipient))
1408 {
1410 gotoSendCoinsPage();
1411 return true;
1412 }
1413 return false;
1414}
1415
1416void BitcoinGUI::setHDStatus(bool privkeyDisabled, int hdEnabled)
1417{
1418 labelWalletHDStatusIcon->setThemedPixmap(privkeyDisabled ? QStringLiteral(":/icons/eye") : hdEnabled ? QStringLiteral(":/icons/hd_enabled") : QStringLiteral(":/icons/hd_disabled"), STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE);
1419 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>"));
1421}
1422
1423void BitcoinGUI::setEncryptionStatus(int status)
1424{
1425 switch(status)
1426 {
1429 encryptWalletAction->setChecked(false);
1430 changePassphraseAction->setEnabled(false);
1431 encryptWalletAction->setEnabled(false);
1432 break;
1435 encryptWalletAction->setChecked(false);
1436 changePassphraseAction->setEnabled(false);
1437 encryptWalletAction->setEnabled(true);
1438 break;
1442 labelWalletEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>unlocked</b>"));
1443 encryptWalletAction->setChecked(true);
1444 changePassphraseAction->setEnabled(true);
1445 encryptWalletAction->setEnabled(false);
1446 break;
1449 labelWalletEncryptionIcon->setThemedPixmap(QStringLiteral(":/icons/lock_closed"), STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE);
1450 labelWalletEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>locked</b>"));
1451 encryptWalletAction->setChecked(true);
1452 changePassphraseAction->setEnabled(true);
1453 encryptWalletAction->setEnabled(false);
1454 break;
1455 }
1456}
1457
1458void BitcoinGUI::updateWalletStatus()
1459{
1461
1462 WalletView * const walletView = walletFrame->currentWalletView();
1463 if (!walletView) {
1464 return;
1465 }
1466 WalletModel * const walletModel = walletView->getWalletModel();
1467 setEncryptionStatus(walletModel->getEncryptionStatus());
1468 setHDStatus(walletModel->wallet().privateKeysDisabled(), walletModel->wallet().hdEnabled());
1469}
1470#endif // ENABLE_WALLET
1471
1473{
1474 std::string ip_port;
1475 bool proxy_enabled = clientModel->getProxyInfo(ip_port);
1476
1477 if (proxy_enabled) {
1479 QString ip_port_q = QString::fromStdString(ip_port);
1481 labelProxyIcon->setToolTip(tr("Proxy is <b>enabled</b>: %1").arg(ip_port_q));
1482 } else {
1483 labelProxyIcon->show();
1484 }
1485 } else {
1486 labelProxyIcon->hide();
1487 }
1488}
1489
1491{
1492 QString window_title = CLIENT_NAME;
1493#ifdef ENABLE_WALLET
1494 if (walletFrame) {
1495 WalletModel* const wallet_model = walletFrame->currentWalletModel();
1496 if (wallet_model && !wallet_model->getWalletName().isEmpty()) {
1497 window_title += " - " + wallet_model->getDisplayName();
1498 }
1499 }
1500#endif
1501 if (!m_network_style->getTitleAddText().isEmpty()) {
1502 window_title += " - " + m_network_style->getTitleAddText();
1503 }
1504 setWindowTitle(window_title);
1505}
1506
1508{
1509 if(!clientModel)
1510 return;
1511
1512 if (!isHidden() && !isMinimized() && !GUIUtil::isObscured(this) && fToggleHidden) {
1513 hide();
1514 } else {
1516 }
1517}
1518
1520{
1522}
1523
1525{
1527 {
1528 if(rpcConsole)
1529 rpcConsole->hide();
1530 Q_EMIT quitRequested();
1531 }
1532}
1533
1534void BitcoinGUI::showProgress(const QString &title, int nProgress)
1535{
1536 if (nProgress == 0) {
1537 progressDialog = new QProgressDialog(title, QString(), 0, 100);
1539 progressDialog->setWindowModality(Qt::ApplicationModal);
1540 progressDialog->setAutoClose(false);
1541 progressDialog->setValue(0);
1542 } else if (nProgress == 100) {
1543 if (progressDialog) {
1544 progressDialog->close();
1545 progressDialog->deleteLater();
1546 progressDialog = nullptr;
1547 }
1548 } else if (progressDialog) {
1549 progressDialog->setValue(nProgress);
1550 }
1551}
1552
1554{
1555 if (modalOverlay && (progressBar->isVisible() || modalOverlay->isLayerVisible()))
1557}
1558
1559static bool ThreadSafeMessageBox(BitcoinGUI* gui, const bilingual_str& message, const std::string& caption, unsigned int style)
1560{
1561 bool modal = (style & CClientUIInterface::MODAL);
1562 // The SECURE flag has no effect in the Qt GUI.
1563 // bool secure = (style & CClientUIInterface::SECURE);
1564 style &= ~CClientUIInterface::SECURE;
1565 bool ret = false;
1566
1567 QString detailed_message; // This is original message, in English, for googling and referencing.
1568 if (message.original != message.translated) {
1569 detailed_message = BitcoinGUI::tr("Original message:") + "\n" + QString::fromStdString(message.original);
1570 }
1571
1572 // In case of modal message, use blocking connection to wait for user to click a button
1573 bool invoked = QMetaObject::invokeMethod(gui, "message",
1574 modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
1575 Q_ARG(QString, QString::fromStdString(caption)),
1576 Q_ARG(QString, QString::fromStdString(message.translated)),
1577 Q_ARG(unsigned int, style),
1578 Q_ARG(bool*, &ret),
1579 Q_ARG(QString, detailed_message));
1580 assert(invoked);
1581 return ret;
1582}
1583
1585{
1586 // Connect signals to client
1587 m_handler_message_box = m_node.handleMessageBox(std::bind(ThreadSafeMessageBox, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
1588 m_handler_question = m_node.handleQuestion(std::bind(ThreadSafeMessageBox, this, std::placeholders::_1, std::placeholders::_3, std::placeholders::_4));
1589}
1590
1592{
1593 // Disconnect signals from client
1594 m_handler_message_box->disconnect();
1595 m_handler_question->disconnect();
1596}
1597
1599{
1601 return m_mask_values_action->isChecked();
1602}
1603
1605 : m_platform_style{platformStyle}
1606{
1608 setToolTip(tr("Unit to show amounts in. Click to select another unit."));
1609 QList<BitcoinUnit> units = BitcoinUnits::availableUnits();
1610 int max_width = 0;
1611 const QFontMetrics fm(font());
1612 for (const BitcoinUnit unit : units) {
1613 max_width = qMax(max_width, GUIUtil::TextWidth(fm, BitcoinUnits::longName(unit)));
1614 }
1615 setMinimumSize(max_width, 0);
1616 setAlignment(Qt::AlignRight | Qt::AlignVCenter);
1617 setStyleSheet(QString("QLabel { color : %1 }").arg(m_platform_style->SingleColor().name()));
1618}
1619
1622{
1623 onDisplayUnitsClicked(event->pos());
1624}
1625
1627{
1628 if (e->type() == QEvent::PaletteChange) {
1629 QString style = QString("QLabel { color : %1 }").arg(m_platform_style->SingleColor().name());
1630 if (style != styleSheet()) {
1631 setStyleSheet(style);
1632 }
1633 }
1634
1635 QLabel::changeEvent(e);
1636}
1637
1640{
1641 menu = new QMenu(this);
1642 for (const BitcoinUnit u : BitcoinUnits::availableUnits()) {
1643 menu->addAction(BitcoinUnits::longName(u))->setData(QVariant::fromValue(u));
1644 }
1645 connect(menu, &QMenu::triggered, this, &UnitDisplayStatusBarControl::onMenuSelection);
1646}
1647
1650{
1651 if (_optionsModel)
1652 {
1653 this->optionsModel = _optionsModel;
1654
1655 // be aware of a display unit change reported by the OptionsModel object.
1657
1658 // initialize the display units label with the current value in the model.
1659 updateDisplayUnit(_optionsModel->getDisplayUnit());
1660 }
1661}
1662
1665{
1666 setText(BitcoinUnits::longName(newUnits));
1667}
1668
1671{
1672 QPoint globalPos = mapToGlobal(point);
1673 menu->exec(globalPos);
1674}
1675
1678{
1679 if (action)
1680 {
1681 optionsModel->setDisplayUnit(action->data());
1682 }
1683}
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
int ret
if(!SetupNetworking())
node::NodeContext m_node
Definition: bitcoin-gui.cpp:42
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:624
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:929
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:833
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:846
HelpMessageDialog * helpMessageDialog
Definition: bitcoingui.h:174
void aboutClicked()
Show about dialog.
Definition: bitcoingui.cpp:934
void toggleHidden()
Simply calls showNormalIfMinimized(true)
QAction * encryptWalletAction
Definition: bitcoingui.h:148
void updateNetworkState()
Update UI with latest network info from model.
void createActions()
Create the main UI actions.
Definition: bitcoingui.cpp:247
void showDebugWindow()
Show debug window.
Definition: bitcoingui.cpp:943
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
QMenu * m_migrate_wallet_menu
Definition: bitcoingui.h:165
void showDebugWindowActivateConsole()
Show debug window and set focus to the console.
Definition: bitcoingui.cpp:949
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:588
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:815
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:494
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:955
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:26
@ BTN_MASK
Mask of all available buttons in CClientUIInterface::MessageBoxFlags This needs to be updated,...
Definition: interface_ui.h:56
@ MSG_INFORMATION
Predefined combinations for certain default usage cases.
Definition: interface_ui.h:66
@ MODAL
Force blocking, modal message box dialog (not just OS notification)
Definition: interface_ui.h:60
Model for Bitcoin network client.
Definition: clientmodel.h:57
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:854
"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 QIcon & getTrayAndWindowIcon() const
Definition: networkstyle.h:23
const QString & getTitleAddText() const
Definition: networkstyle.h:24
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:101
BitcoinUnit getDisplayUnit() const
Definition: optionsmodel.h:103
bool getShowTrayIcon() const
Definition: optionsmodel.h:100
QVariant getOption(OptionID option, const std::string &suffix="") const
bool getMinimizeOnClose() const
Definition: optionsmodel.h:102
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
std::vector< TabTypes > tabs() const
Definition: rpcconsole.h:76
QString tabTitle(TabTypes tab_type) const
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:659
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)
void walletRemoved(WalletModel *wallet_model)
void closeWallet(WalletModel *wallet_model, QWidget *parent=nullptr)
std::map< std::string, std::pair< bool, std::string > > listWalletDir() const
Returns all wallet names in the wallet dir mapped to whether the wallet is loaded.
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
EncryptionStatus getEncryptionStatus() const
interfaces::Wallet & wallet() const
Definition: walletmodel.h:138
QString getDisplayName() const
static bool isWalletEnabled()
QString getWalletName() const
void outOfSyncWarningClicked()
Notify that the out of sync warning icon has been pressed.
WalletModel * getWalletModel() const noexcept
Definition: walletview.h:46
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.
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:71
virtual void setNetworkActive(bool active)=0
Set network active.
virtual std::unique_ptr< Handler > handleMessageBox(MessageBoxFn fn)=0
virtual bool getNetworkActive()=0
Get network active.
virtual std::unique_ptr< Handler > handleQuestion(QuestionFn 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:42
@ HEADER_PRESYNC
BlockSource
Definition: clientmodel.h:36
#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:397
Qt::ConnectionType blockingGUIThreadConnection()
Get connection type to call object slot in GUI thread with invokeMethod.
Definition: guiutil.cpp:378
QString WalletDisplayName(const QString &name)
Definition: guiutil.cpp:1011
void PopupMenu(QMenu *menu, const QPoint &point, QAction *at_action)
Call QMenu::popup() only on supported QT_QPA_PLATFORM.
Definition: guiutil.cpp:948
void ShowModalDialogAsynchronously(QDialog *dialog)
Shows a QDialog instance asynchronously, and deletes it on close.
Definition: guiutil.cpp:1004
void handleCloseWindowShortcut(QWidget *w)
Definition: guiutil.cpp:431
void PolishProgressDialog(QProgressDialog *dialog)
Definition: guiutil.cpp:901
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
Get open filename, convenience wrapper for QFileDialog::getOpenFileName.
Definition: guiutil.cpp:353
ClickableProgressBar ProgressBar
Definition: guiutil.h:300
void bringToFront(QWidget *w)
Definition: guiutil.cpp:406
bool HasPixmap(const QLabel *label)
Returns true if pixmap has been set.
Definition: guiutil.cpp:964
QString formatNiceTimeOffset(qint64 secs)
Definition: guiutil.cpp:787
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:915
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
const char * name
Definition: rest.cpp:49
static RPCHelpMan help()
Definition: server.cpp:127
int64_t nPowTargetSpacing
Definition: params.h:117
Bilingual messages:
Definition: translation.h:21
std::string translated
Definition: translation.h:23
std::string original
Definition: translation.h:22
Block and header tip information.
Definition: node.h:51
static int count
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
Definition: time.cpp:47
assert(!tx.IsCoinBase())
SynchronizationState
Current sync state passed to tip changed callbacks.
Definition: validation.h:85