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