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