Bitcoin Core 31.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 m_export_watchonly_action = new QAction(tr("Export watch-only wallet"), this);
381 m_export_watchonly_action->setEnabled(false);
382 m_export_watchonly_action->setStatusTip(tr("Export a watch-only version of the current wallet that can be restored onto another node."));
383
384 connect(quitAction, &QAction::triggered, this, &BitcoinGUI::quitRequested);
385 connect(aboutAction, &QAction::triggered, this, &BitcoinGUI::aboutClicked);
386 connect(aboutQtAction, &QAction::triggered, qApp, QApplication::aboutQt);
387 connect(optionsAction, &QAction::triggered, this, &BitcoinGUI::optionsClicked);
388 connect(showHelpMessageAction, &QAction::triggered, this, &BitcoinGUI::showHelpMessageClicked);
389 connect(openRPCConsoleAction, &QAction::triggered, this, &BitcoinGUI::showDebugWindow);
390 // prevents an open debug window from becoming stuck/unusable on client shutdown
391 connect(quitAction, &QAction::triggered, rpcConsole, &QWidget::hide);
392
393#ifdef ENABLE_WALLET
394 if(walletFrame)
395 {
396 connect(encryptWalletAction, &QAction::triggered, walletFrame, &WalletFrame::encryptWallet);
397 connect(backupWalletAction, &QAction::triggered, walletFrame, &WalletFrame::backupWallet);
399 connect(signMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
400 connect(signMessageAction, &QAction::triggered, [this]{ gotoSignMessageTab(); });
401 connect(m_load_psbt_action, &QAction::triggered, [this]{ gotoLoadPSBT(); });
402 connect(m_load_psbt_clipboard_action, &QAction::triggered, [this]{ gotoLoadPSBT(true); });
403 connect(verifyMessageAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
404 connect(verifyMessageAction, &QAction::triggered, [this]{ gotoVerifyMessageTab(); });
407 connect(openAction, &QAction::triggered, this, &BitcoinGUI::openClicked);
408 connect(m_open_wallet_menu, &QMenu::aboutToShow, [this] {
409 m_open_wallet_menu->clear();
410 for (const auto& [path, info] : m_wallet_controller->listWalletDir()) {
411 const auto& [loaded, format] = info;
412 QString name = GUIUtil::WalletDisplayName(path);
413 // An single ampersand in the menu item's text sets a shortcut for this item.
414 // Single & are shown when && is in the string. So replace & with &&.
415 name.replace(QChar('&'), QString("&&"));
416 bool is_legacy = format == "bdb";
417 if (is_legacy) {
418 name += " (needs migration)";
419 }
420 QAction* action = m_open_wallet_menu->addAction(name);
421
422 if (loaded || is_legacy) {
423 // This wallet is already loaded or it is a legacy wallet
424 action->setEnabled(false);
425 continue;
426 }
427
428 connect(action, &QAction::triggered, [this, path] {
429 auto activity = new OpenWalletActivity(m_wallet_controller, this);
430 connect(activity, &OpenWalletActivity::opened, this, &BitcoinGUI::setCurrentWallet, Qt::QueuedConnection);
431 connect(activity, &OpenWalletActivity::opened, rpcConsole, &RPCConsole::setCurrentWallet, Qt::QueuedConnection);
432 activity->open(path);
433 });
434 }
435 if (m_open_wallet_menu->isEmpty()) {
436 QAction* action = m_open_wallet_menu->addAction(tr("No wallets available"));
437 action->setEnabled(false);
438 }
439 });
440 connect(m_restore_wallet_action, &QAction::triggered, [this] {
441 //: Name of the wallet data file format.
442 QString name_data_file = tr("Wallet Data");
443
444 //: The title for Restore Wallet File Windows
445 QString title_windows = tr("Load Wallet Backup");
446
447 QString backup_file = GUIUtil::getOpenFileName(this, title_windows, QString(), name_data_file + QLatin1String(" (*.dat)"), nullptr);
448 if (backup_file.isEmpty()) return;
449
450 bool wallet_name_ok;
451 /*: Title of pop-up window shown when the user is attempting to
452 restore a wallet. */
453 QString title = tr("Restore Wallet");
454 //: Label of the input field where the name of the wallet is entered.
455 QString label = tr("Wallet Name");
456 QString wallet_name = QInputDialog::getText(this, title, label, QLineEdit::Normal, "", &wallet_name_ok);
457 if (!wallet_name_ok) return;
458 if (wallet_name.isEmpty()) {
459 QMessageBox::critical(nullptr, tr("Invalid Wallet Name"), tr("Wallet name cannot be empty"));
460 return;
461 }
462
463 auto activity = new RestoreWalletActivity(m_wallet_controller, this);
464 connect(activity, &RestoreWalletActivity::restored, this, &BitcoinGUI::setCurrentWallet, Qt::QueuedConnection);
465 connect(activity, &RestoreWalletActivity::restored, rpcConsole, &RPCConsole::setCurrentWallet, Qt::QueuedConnection);
466
467 auto backup_file_path = fs::PathFromString(backup_file.toStdString());
468 activity->restore(backup_file_path, wallet_name.toStdString());
469 });
470 connect(m_close_wallet_action, &QAction::triggered, [this] {
471 m_wallet_controller->closeWallet(walletFrame->currentWalletModel(), this);
472 });
473 connect(m_create_wallet_action, &QAction::triggered, this, &BitcoinGUI::createWallet);
474 connect(m_close_all_wallets_action, &QAction::triggered, [this] {
475 m_wallet_controller->closeAllWallets(this);
476 });
477 connect(m_migrate_wallet_menu, &QMenu::aboutToShow, [this] {
478 m_migrate_wallet_menu->clear();
479 for (const auto& [wallet_name, info] : m_wallet_controller->listWalletDir()) {
480 const auto& [loaded, format] = info;
481
482 if (format != "bdb") { // Skip already migrated wallets
483 continue;
484 }
485
486 QString name = GUIUtil::WalletDisplayName(wallet_name);
487 // An single ampersand in the menu item's text sets a shortcut for this item.
488 // Single & are shown when && is in the string. So replace & with &&.
489 name.replace(QChar('&'), QString("&&"));
490 QAction* action = m_migrate_wallet_menu->addAction(name);
491
492 connect(action, &QAction::triggered, [this, wallet_name] {
493 auto activity = new MigrateWalletActivity(m_wallet_controller, this);
494 connect(activity, &MigrateWalletActivity::migrated, this, &BitcoinGUI::setCurrentWallet);
495 activity->migrate(wallet_name);
496 });
497 }
498 if (m_migrate_wallet_menu->isEmpty()) {
499 QAction* action = m_migrate_wallet_menu->addAction(tr("No wallets available"));
500 action->setEnabled(false);
501 }
502 m_migrate_wallet_menu->addSeparator();
503 QAction* restore_migrate_file_action = m_migrate_wallet_menu->addAction(tr("Restore and Migrate Wallet File…"));
504 restore_migrate_file_action->setEnabled(true);
505
506 connect(restore_migrate_file_action, &QAction::triggered, [this] {
507 QString name_data_file = tr("Wallet Data");
508 QString title_windows = tr("Restore and Migrate Wallet Backup");
509
510 QString backup_file = GUIUtil::getOpenFileName(this, title_windows, QString(), name_data_file + QLatin1String(" (*.dat)"), nullptr);
511 if (backup_file.isEmpty()) return;
512
513 bool wallet_name_ok;
514 /*: Title of pop-up window shown when the user is attempting to
515 restore a wallet. */
516 QString title = tr("Restore and Migrate Wallet");
517 //: Label of the input field where the name of the wallet is entered.
518 QString label = tr("Wallet Name");
519 QString wallet_name = QInputDialog::getText(this, title, label, QLineEdit::Normal, "", &wallet_name_ok);
520 if (!wallet_name_ok || wallet_name.isEmpty()) return;
521
522 auto activity = new MigrateWalletActivity(m_wallet_controller, this);
523 connect(activity, &MigrateWalletActivity::migrated, this, &BitcoinGUI::setCurrentWallet);
524 connect(activity, &MigrateWalletActivity::migrated, rpcConsole, &RPCConsole::setCurrentWallet);
525 auto backup_file_path = fs::PathFromString(backup_file.toStdString());
526 activity->restore_and_migrate(backup_file_path, wallet_name.toStdString());
527 });
528 });
529 connect(m_mask_values_action, &QAction::toggled, this, &BitcoinGUI::setPrivacy);
530 connect(m_mask_values_action, &QAction::toggled, this, &BitcoinGUI::enableHistoryAction);
531 GUIUtil::ExceptionSafeConnect(m_export_watchonly_action, &QAction::triggered, [this](bool) {
532 QString destination = GUIUtil::getSaveFileName(this, tr("Save Watch-only Wallet Export"), QString(), QString(), nullptr);
533 if (destination.isEmpty()) return;
534 WalletModel* model = walletFrame->currentWalletModel();
535 if (!Assume(model)) return;
537 if (export_res) {
538 QMessageBox::information(nullptr, tr("Export Successful"), tr("The wallet has been exported to ") + QString::fromStdString(*export_res));
539 } else {
540 QMessageBox::critical(nullptr, tr("Export Error"), QString::fromStdString(util::ErrorString(export_res).translated));
541 }
542 });
543 }
544#endif // ENABLE_WALLET
545
546 connect(new QShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_C), this), &QShortcut::activated, this, &BitcoinGUI::showDebugWindowActivateConsole);
547 connect(new QShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_D), this), &QShortcut::activated, this, &BitcoinGUI::showDebugWindow);
548}
549
551{
552 appMenuBar = menuBar();
553
554 // Configure the menus
555 QMenu *file = appMenuBar->addMenu(tr("&File"));
556 if(walletFrame)
557 {
558 file->addAction(m_create_wallet_action);
559 file->addAction(m_open_wallet_action);
560 file->addAction(m_close_wallet_action);
561 file->addAction(m_close_all_wallets_action);
562 file->addAction(m_migrate_wallet_action);
563 file->addSeparator();
564 file->addAction(backupWalletAction);
565 file->addAction(m_restore_wallet_action);
566 file->addAction(m_export_watchonly_action);
567 file->addSeparator();
568 file->addAction(openAction);
569 file->addAction(signMessageAction);
570 file->addAction(verifyMessageAction);
571 file->addAction(m_load_psbt_action);
572 file->addAction(m_load_psbt_clipboard_action);
573 file->addSeparator();
574 }
575 file->addAction(quitAction);
576
577 QMenu *settings = appMenuBar->addMenu(tr("&Settings"));
578 if(walletFrame)
579 {
580 settings->addAction(encryptWalletAction);
581 settings->addAction(changePassphraseAction);
582 settings->addSeparator();
583 settings->addAction(m_mask_values_action);
584 settings->addSeparator();
585 }
586 settings->addAction(optionsAction);
587
588 QMenu* window_menu = appMenuBar->addMenu(tr("&Window"));
589
590 QAction* minimize_action = window_menu->addAction(tr("&Minimize"));
591 minimize_action->setShortcut(QKeySequence(tr("Ctrl+M")));
592 connect(minimize_action, &QAction::triggered, [] {
593 QApplication::activeWindow()->showMinimized();
594 });
595 connect(qApp, &QApplication::focusWindowChanged, this, [minimize_action] (QWindow* window) {
596 minimize_action->setEnabled(window != nullptr && (window->flags() & Qt::Dialog) != Qt::Dialog && window->windowState() != Qt::WindowMinimized);
597 });
598
599#ifdef Q_OS_MACOS
600 QAction* zoom_action = window_menu->addAction(tr("Zoom"));
601 connect(zoom_action, &QAction::triggered, [] {
602 QWindow* window = qApp->focusWindow();
603 if (window->windowState() != Qt::WindowMaximized) {
604 window->showMaximized();
605 } else {
606 window->showNormal();
607 }
608 });
609
610 connect(qApp, &QApplication::focusWindowChanged, this, [zoom_action] (QWindow* window) {
611 zoom_action->setEnabled(window != nullptr);
612 });
613#endif
614
615 if (walletFrame) {
616#ifdef Q_OS_MACOS
617 window_menu->addSeparator();
618 QAction* main_window_action = window_menu->addAction(tr("Main Window"));
619 connect(main_window_action, &QAction::triggered, [this] {
621 });
622#endif
623 window_menu->addSeparator();
624 window_menu->addAction(usedSendingAddressesAction);
625 window_menu->addAction(usedReceivingAddressesAction);
626 }
627
628 window_menu->addSeparator();
629 for (RPCConsole::TabTypes tab_type : rpcConsole->tabs()) {
630 QAction* tab_action = window_menu->addAction(rpcConsole->tabTitle(tab_type));
631 tab_action->setShortcut(rpcConsole->tabShortcut(tab_type));
632 connect(tab_action, &QAction::triggered, [this, tab_type] {
633 rpcConsole->setTabFocus(tab_type);
635 });
636 }
637
638 QMenu *help = appMenuBar->addMenu(tr("&Help"));
639 help->addAction(showHelpMessageAction);
640 help->addSeparator();
641 help->addAction(aboutAction);
642 help->addAction(aboutQtAction);
643}
644
646{
647 if(walletFrame)
648 {
649 QToolBar *toolbar = addToolBar(tr("Tabs toolbar"));
650 appToolBar = toolbar;
651 toolbar->setMovable(false);
652 toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
653 toolbar->addAction(overviewAction);
654 toolbar->addAction(sendCoinsAction);
655 toolbar->addAction(receiveCoinsAction);
656 toolbar->addAction(historyAction);
657 overviewAction->setChecked(true);
658
659#ifdef ENABLE_WALLET
660 QWidget *spacer = new QWidget();
661 spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
662 toolbar->addWidget(spacer);
663
664 m_wallet_selector = new QComboBox();
665 m_wallet_selector->setSizeAdjustPolicy(QComboBox::AdjustToContents);
666 connect(m_wallet_selector, qOverload<int>(&QComboBox::currentIndexChanged), this, &BitcoinGUI::setCurrentWalletBySelectorIndex);
667
668 m_wallet_selector_label = new QLabel();
669 m_wallet_selector_label->setText(tr("Wallet:") + " ");
670 m_wallet_selector_label->setBuddy(m_wallet_selector);
671
672 m_wallet_selector_label_action = appToolBar->addWidget(m_wallet_selector_label);
673 m_wallet_selector_action = appToolBar->addWidget(m_wallet_selector);
674
675 m_wallet_selector_label_action->setVisible(false);
676 m_wallet_selector_action->setVisible(false);
677#endif
678 }
679}
680
682{
683 this->clientModel = _clientModel;
684 if(_clientModel)
685 {
686 // Create system tray menu (or setup the dock menu) that late to prevent users from calling actions,
687 // while the client has not yet fully loaded
689
690 // Keep up to date with client
694 });
697
698 modalOverlay->setKnownBestHeight(tip_info->header_height, QDateTime::fromSecsSinceEpoch(tip_info->header_time), /*presync=*/false);
699 setNumBlocks(tip_info->block_height, QDateTime::fromSecsSinceEpoch(tip_info->block_time), tip_info->verification_progress, SyncType::BLOCK_SYNC, SynchronizationState::INIT_DOWNLOAD);
700 connect(_clientModel, &ClientModel::numBlocksChanged, this, &BitcoinGUI::setNumBlocks);
701
702 // Receive and report messages from client model
703 connect(_clientModel, &ClientModel::message, [this](const QString &title, const QString &message, unsigned int style){
704 this->message(title, message, style);
705 });
706
707 // Show progress dialog
708 connect(_clientModel, &ClientModel::showProgress, this, &BitcoinGUI::showProgress);
709
710 rpcConsole->setClientModel(_clientModel, tip_info->block_height, tip_info->block_time, tip_info->verification_progress);
711
713
714#ifdef ENABLE_WALLET
715 if(walletFrame)
716 {
717 walletFrame->setClientModel(_clientModel);
718 }
719#endif // ENABLE_WALLET
721
722 OptionsModel* optionsModel = _clientModel->getOptionsModel();
723 if (optionsModel && trayIcon) {
724 // be aware of the tray icon disable state change reported by the OptionsModel object.
725 connect(optionsModel, &OptionsModel::showTrayIconChanged, trayIcon, &QSystemTrayIcon::setVisible);
726
727 // initialize the disable state of the tray icon with the current value in the model.
728 trayIcon->setVisible(optionsModel->getShowTrayIcon());
729 }
730
731 m_mask_values_action->setChecked(_clientModel->getOptionsModel()->getOption(OptionsModel::OptionID::MaskValues).toBool());
732 } else {
733 // Shutdown requested, disable menus
734 if (trayIconMenu)
735 {
736 // Disable context menu on tray icon
737 trayIconMenu->clear();
738 }
739 // Propagate cleared model to child objects
740 rpcConsole->setClientModel(nullptr);
741#ifdef ENABLE_WALLET
742 if (walletFrame)
743 {
744 walletFrame->setClientModel(nullptr);
745 }
746#endif // ENABLE_WALLET
748 // Disable top bar menu actions
749 appMenuBar->clear();
750 }
751}
752
753#ifdef ENABLE_WALLET
754void BitcoinGUI::enableHistoryAction(bool privacy)
755{
757 historyAction->setEnabled(!privacy);
758 if (historyAction->isChecked()) gotoOverviewPage();
759 }
760}
761
762void BitcoinGUI::setWalletController(WalletController* wallet_controller, bool show_loading_minimized)
763{
764 assert(!m_wallet_controller);
765 assert(wallet_controller);
766
767 m_wallet_controller = wallet_controller;
768
769 m_create_wallet_action->setEnabled(true);
770 m_open_wallet_action->setEnabled(true);
772 m_restore_wallet_action->setEnabled(true);
773 m_migrate_wallet_action->setEnabled(true);
775
776 GUIUtil::ExceptionSafeConnect(wallet_controller, &WalletController::walletAdded, this, &BitcoinGUI::addWallet);
777 connect(wallet_controller, &WalletController::walletRemoved, this, &BitcoinGUI::removeWallet);
778 connect(wallet_controller, &WalletController::destroyed, this, [this] {
779 // wallet_controller gets destroyed manually, but it leaves our member copy dangling
780 m_wallet_controller = nullptr;
781 });
782
783 auto activity = new LoadWalletsActivity(m_wallet_controller, this);
784 activity->load(show_loading_minimized);
785}
786
787WalletController* BitcoinGUI::getWalletController()
788{
789 return m_wallet_controller;
790}
791
792void BitcoinGUI::addWallet(WalletModel* walletModel)
793{
794 if (!walletFrame || !m_wallet_controller) return;
795
796 WalletView* wallet_view = new WalletView(walletModel, platformStyle, walletFrame);
797 if (!walletFrame->addView(wallet_view)) return;
798
799 rpcConsole->addWallet(walletModel);
800 if (m_wallet_selector->count() == 0) {
802 } else if (m_wallet_selector->count() == 1) {
803 m_wallet_selector_label_action->setVisible(true);
804 m_wallet_selector_action->setVisible(true);
805 }
806
808 connect(wallet_view, &WalletView::transactionClicked, this, &BitcoinGUI::gotoHistoryPage);
809 connect(wallet_view, &WalletView::coinsSent, this, &BitcoinGUI::gotoHistoryPage);
810 connect(wallet_view, &WalletView::message, [this](const QString& title, const QString& message, unsigned int style) {
811 this->message(title, message, style);
812 });
813 connect(wallet_view, &WalletView::encryptionStatusChanged, this, &BitcoinGUI::updateWalletStatus);
814 connect(wallet_view, &WalletView::incomingTransaction, this, &BitcoinGUI::incomingTransaction);
815 connect(this, &BitcoinGUI::setPrivacy, wallet_view, &WalletView::setPrivacy);
816 wallet_view->setPrivacy(isPrivacyModeActivated());
817 const QString display_name = walletModel->getDisplayName();
818 m_wallet_selector->addItem(display_name, QVariant::fromValue(walletModel));
819}
820
821void BitcoinGUI::removeWallet(WalletModel* walletModel)
822{
823 if (!walletFrame) return;
824
827
828 int index = m_wallet_selector->findData(QVariant::fromValue(walletModel));
829 m_wallet_selector->removeItem(index);
830 if (m_wallet_selector->count() == 0) {
832 overviewAction->setChecked(true);
833 } else if (m_wallet_selector->count() == 1) {
834 m_wallet_selector_label_action->setVisible(false);
835 m_wallet_selector_action->setVisible(false);
836 }
837 rpcConsole->removeWallet(walletModel);
838 walletFrame->removeWallet(walletModel);
840}
841
842void BitcoinGUI::setCurrentWallet(WalletModel* wallet_model)
843{
844 if (!walletFrame || !m_wallet_controller) return;
845 walletFrame->setCurrentWallet(wallet_model);
846 for (int index = 0; index < m_wallet_selector->count(); ++index) {
847 if (m_wallet_selector->itemData(index).value<WalletModel*>() == wallet_model) {
848 m_wallet_selector->setCurrentIndex(index);
849 break;
850 }
851 }
852 m_export_watchonly_action->setEnabled(!wallet_model->wallet().privateKeysDisabled());
854}
855
856void BitcoinGUI::setCurrentWalletBySelectorIndex(int index)
857{
858 WalletModel* wallet_model = m_wallet_selector->itemData(index).value<WalletModel*>();
859 if (wallet_model) setCurrentWallet(wallet_model);
860}
861
862void BitcoinGUI::removeAllWallets()
863{
864 if(!walletFrame)
865 return;
868}
869#endif // ENABLE_WALLET
870
872{
873 overviewAction->setEnabled(enabled);
874 sendCoinsAction->setEnabled(enabled);
875 receiveCoinsAction->setEnabled(enabled);
876 historyAction->setEnabled(enabled && !isPrivacyModeActivated());
877 encryptWalletAction->setEnabled(enabled);
878 backupWalletAction->setEnabled(enabled);
879 changePassphraseAction->setEnabled(enabled);
880 signMessageAction->setEnabled(enabled);
881 verifyMessageAction->setEnabled(enabled);
882 usedSendingAddressesAction->setEnabled(enabled);
883 usedReceivingAddressesAction->setEnabled(enabled);
884 openAction->setEnabled(enabled);
885 m_close_wallet_action->setEnabled(enabled);
886 m_close_all_wallets_action->setEnabled(enabled);
887 m_export_watchonly_action->setEnabled(enabled);
888}
889
891{
892 assert(QSystemTrayIcon::isSystemTrayAvailable());
893
894#ifndef Q_OS_MACOS
895 if (QSystemTrayIcon::isSystemTrayAvailable()) {
896 trayIcon = new QSystemTrayIcon(m_network_style->getTrayAndWindowIcon(), this);
897 QString toolTip = tr("%1 client").arg(CLIENT_NAME) + " " + m_network_style->getTitleAddText();
898 trayIcon->setToolTip(toolTip);
899 }
900#endif
901}
902
904{
905#ifndef Q_OS_MACOS
906 if (!trayIcon) return;
907#endif // Q_OS_MACOS
908
909 // Configuration of the tray icon (or Dock icon) menu.
910 QAction* show_hide_action{nullptr};
911#ifndef Q_OS_MACOS
912 // Note: On macOS, the Dock icon's menu already has Show / Hide action.
913 show_hide_action = trayIconMenu->addAction(QString(), this, &BitcoinGUI::toggleHidden);
914 trayIconMenu->addSeparator();
915#endif // Q_OS_MACOS
916
917 QAction* send_action{nullptr};
918 QAction* receive_action{nullptr};
919 QAction* sign_action{nullptr};
920 QAction* verify_action{nullptr};
921 if (enableWallet) {
922 send_action = trayIconMenu->addAction(sendCoinsAction->text(), sendCoinsAction, &QAction::trigger);
923 receive_action = trayIconMenu->addAction(receiveCoinsAction->text(), receiveCoinsAction, &QAction::trigger);
924 trayIconMenu->addSeparator();
925 sign_action = trayIconMenu->addAction(signMessageAction->text(), signMessageAction, &QAction::trigger);
926 verify_action = trayIconMenu->addAction(verifyMessageAction->text(), verifyMessageAction, &QAction::trigger);
927 trayIconMenu->addSeparator();
928 }
929 QAction* options_action = trayIconMenu->addAction(optionsAction->text(), optionsAction, &QAction::trigger);
930 options_action->setMenuRole(QAction::PreferencesRole);
931 QAction* node_window_action = trayIconMenu->addAction(openRPCConsoleAction->text(), openRPCConsoleAction, &QAction::trigger);
932 QAction* quit_action{nullptr};
933#ifndef Q_OS_MACOS
934 // Note: On macOS, the Dock icon's menu already has Quit action.
935 trayIconMenu->addSeparator();
936 quit_action = trayIconMenu->addAction(quitAction->text(), quitAction, &QAction::trigger);
937
938 trayIcon->setContextMenu(trayIconMenu.get());
939 connect(trayIcon, &QSystemTrayIcon::activated, [this](QSystemTrayIcon::ActivationReason reason) {
940 if (reason == QSystemTrayIcon::Trigger) {
941 // Click on system tray icon triggers show/hide of the main window
942 toggleHidden();
943 }
944 });
945#else
946 // Note: On macOS, the Dock icon is used to provide the tray's functionality.
948 connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, [this] {
949 if (m_node.shutdownRequested()) return; // nothing to show, node is shutting down.
950 show();
951 activateWindow();
952 });
953 trayIconMenu->setAsDockMenu();
954#endif // Q_OS_MACOS
955
956 connect(
957 // Using QSystemTrayIcon::Context is not reliable.
958 // See https://bugreports.qt.io/browse/QTBUG-91697
959 trayIconMenu.get(), &QMenu::aboutToShow,
960 [this, show_hide_action, send_action, receive_action, sign_action, verify_action, options_action, node_window_action, quit_action] {
961 if (m_node.shutdownRequested()) return; // nothing to do, node is shutting down.
962
963 if (show_hide_action) show_hide_action->setText(
964 (!isHidden() && !isMinimized() && !GUIUtil::isObscured(this)) ?
965 tr("&Hide") :
966 tr("S&how"));
967 if (QApplication::activeModalWidget()) {
968 for (QAction* a : trayIconMenu.get()->actions()) {
969 a->setEnabled(false);
970 }
971 } else {
972 if (show_hide_action) show_hide_action->setEnabled(true);
973 if (enableWallet) {
974 send_action->setEnabled(sendCoinsAction->isEnabled());
975 receive_action->setEnabled(receiveCoinsAction->isEnabled());
976 sign_action->setEnabled(signMessageAction->isEnabled());
977 verify_action->setEnabled(verifyMessageAction->isEnabled());
978 }
979 options_action->setEnabled(optionsAction->isEnabled());
980 node_window_action->setEnabled(openRPCConsoleAction->isEnabled());
981 if (quit_action) quit_action->setEnabled(true);
982 }
983 });
984}
985
987{
989}
990
992{
993 if(!clientModel)
994 return;
995
996 auto dlg = new HelpMessageDialog(this, /*about=*/true);
998}
999
1001{
1003 Q_EMIT consoleShown(rpcConsole);
1004}
1005
1007{
1010}
1011
1013{
1015}
1016
1017#ifdef ENABLE_WALLET
1018void BitcoinGUI::openClicked()
1019{
1020 OpenURIDialog dlg(platformStyle, this);
1021 if(dlg.exec())
1022 {
1023 Q_EMIT receivedURI(dlg.getURI());
1024 }
1025}
1026
1027void BitcoinGUI::gotoOverviewPage()
1028{
1029 overviewAction->setChecked(true);
1031}
1032
1033void BitcoinGUI::gotoHistoryPage()
1034{
1035 historyAction->setChecked(true);
1037}
1038
1039void BitcoinGUI::gotoReceiveCoinsPage()
1040{
1041 receiveCoinsAction->setChecked(true);
1043}
1044
1045void BitcoinGUI::gotoSendCoinsPage(QString addr)
1046{
1047 sendCoinsAction->setChecked(true);
1049}
1050
1051void BitcoinGUI::gotoSignMessageTab(QString addr)
1052{
1054}
1055
1056void BitcoinGUI::gotoVerifyMessageTab(QString addr)
1057{
1059}
1060void BitcoinGUI::gotoLoadPSBT(bool from_clipboard)
1061{
1062 if (walletFrame) walletFrame->gotoLoadPSBT(from_clipboard);
1063}
1064#endif // ENABLE_WALLET
1065
1067{
1068 if (!clientModel) return;
1070 QString icon;
1071 switch(count)
1072 {
1073 case 0: icon = ":/icons/connect_0"; break;
1074 case 1: case 2: case 3: icon = ":/icons/connect_1"; break;
1075 case 4: case 5: case 6: icon = ":/icons/connect_2"; break;
1076 case 7: case 8: case 9: icon = ":/icons/connect_3"; break;
1077 default: icon = ":/icons/connect_4"; break;
1078 }
1079
1080 QString tooltip;
1081
1082 if (m_node.getNetworkActive()) {
1083 //: A substring of the tooltip.
1084 tooltip = tr("%n active connection(s) to Bitcoin network.", "", count);
1085 } else {
1086 //: A substring of the tooltip.
1087 tooltip = tr("Network activity disabled.");
1088 icon = ":/icons/network_disabled";
1089 }
1090
1091 // Don't word-wrap this (fixed-width) tooltip
1092 tooltip = QLatin1String("<nobr>") + tooltip + QLatin1String("<br>") +
1093 //: A substring of the tooltip. "More actions" are available via the context menu.
1094 tr("Click for more actions.") + QLatin1String("</nobr>");
1095 connectionsControl->setToolTip(tooltip);
1096
1098}
1099
1101{
1103}
1104
1105void BitcoinGUI::setNetworkActive(bool network_active)
1106{
1108 m_network_context_menu->clear();
1109 m_network_context_menu->addAction(
1110 //: A context menu item. The "Peers tab" is an element of the "Node window".
1111 tr("Show Peers tab"),
1112 [this] {
1115 });
1116 m_network_context_menu->addAction(
1117 network_active ?
1118 //: A context menu item.
1119 tr("Disable network activity") :
1120 //: A context menu item. The network activity was disabled previously.
1121 tr("Enable network activity"),
1122 [this, new_state = !network_active] { m_node.setNetworkActive(new_state); });
1123}
1124
1126{
1127 int64_t headersTipTime = clientModel->getHeaderTipTime();
1128 int headersTipHeight = clientModel->getHeaderTipHeight();
1129 int estHeadersLeft = (GetTime() - headersTipTime) / Params().GetConsensus().nPowTargetSpacing;
1130 if (estHeadersLeft > HEADER_HEIGHT_DELTA_SYNC)
1131 progressBarLabel->setText(tr("Syncing Headers (%1%)…").arg(QString::number(100.0 / (headersTipHeight+estHeadersLeft)*headersTipHeight, 'f', 1)));
1132}
1133
1134void BitcoinGUI::updateHeadersPresyncProgressLabel(int64_t height, const QDateTime& blockDate)
1135{
1136 int estHeadersLeft = blockDate.secsTo(QDateTime::currentDateTime()) / Params().GetConsensus().nPowTargetSpacing;
1137 if (estHeadersLeft > HEADER_HEIGHT_DELTA_SYNC)
1138 progressBarLabel->setText(tr("Pre-syncing Headers (%1%)…").arg(QString::number(100.0 / (height+estHeadersLeft)*height, 'f', 1)));
1139}
1140
1142{
1144 return;
1145
1146 auto dlg = new OptionsDialog(this, enableWallet);
1148 dlg->setCurrentTab(tab);
1149 dlg->setClientModel(clientModel);
1150 dlg->setModel(clientModel->getOptionsModel());
1152}
1153
1154void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state)
1155{
1156// Disabling macOS App Nap on initial sync, disk and reindex operations.
1157#ifdef Q_OS_MACOS
1158 if (sync_state == SynchronizationState::POST_INIT) {
1159 m_app_nap_inhibitor->enableAppNap();
1160 } else {
1161 m_app_nap_inhibitor->disableAppNap();
1162 }
1163#endif
1164
1165 if (modalOverlay)
1166 {
1167 if (synctype != SyncType::BLOCK_SYNC)
1169 else
1170 modalOverlay->tipUpdate(count, blockDate, nVerificationProgress);
1171 }
1172 if (!clientModel)
1173 return;
1174
1175 // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbled text)
1176 statusBar()->clearMessage();
1177
1178 // Acquire current block source
1179 BlockSource blockSource{clientModel->getBlockSource()};
1180 switch (blockSource) {
1182 if (synctype == SyncType::HEADER_PRESYNC) {
1184 return;
1185 } else if (synctype == SyncType::HEADER_SYNC) {
1187 return;
1188 }
1189 progressBarLabel->setText(tr("Synchronizing with network…"));
1191 break;
1192 case BlockSource::DISK:
1193 if (synctype != SyncType::BLOCK_SYNC) {
1194 progressBarLabel->setText(tr("Indexing blocks on disk…"));
1195 } else {
1196 progressBarLabel->setText(tr("Processing blocks on disk…"));
1197 }
1198 break;
1199 case BlockSource::NONE:
1200 if (synctype != SyncType::BLOCK_SYNC) {
1201 return;
1202 }
1203 progressBarLabel->setText(tr("Connecting to peers…"));
1204 break;
1205 }
1206
1207 QString tooltip;
1208
1209 QDateTime currentDate = QDateTime::currentDateTime();
1210 qint64 secs = blockDate.secsTo(currentDate);
1211
1212 tooltip = tr("Processed %n block(s) of transaction history.", "", count);
1213
1214 // Set icon state: spinning if catching up, tick otherwise
1215 if (secs < MAX_BLOCK_TIME_GAP) {
1216 tooltip = tr("Up to date") + QString(".<br>") + tooltip;
1217 labelBlocksIcon->setThemedPixmap(QStringLiteral(":/icons/synced"), STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE);
1218
1219#ifdef ENABLE_WALLET
1220 if(walletFrame)
1221 {
1223 modalOverlay->showHide(true, true);
1224 }
1225#endif // ENABLE_WALLET
1226
1227 progressBarLabel->setVisible(false);
1228 progressBar->setVisible(false);
1229 }
1230 else
1231 {
1232 QString timeBehindText = GUIUtil::formatNiceTimeOffset(secs);
1233
1234 progressBarLabel->setVisible(true);
1235 progressBar->setFormat(tr("%1 behind").arg(timeBehindText));
1236 progressBar->setMaximum(1000000000);
1237 progressBar->setValue(nVerificationProgress * 1000000000.0 + 0.5);
1238 progressBar->setVisible(true);
1239
1240 tooltip = tr("Catching up…") + QString("<br>") + tooltip;
1241 if(count != prevBlocks)
1242 {
1244 QString(":/animation/spinner-%1").arg(spinnerFrame, 3, 10, QChar('0')),
1247 }
1248 prevBlocks = count;
1249
1250#ifdef ENABLE_WALLET
1251 if(walletFrame)
1252 {
1255 }
1256#endif // ENABLE_WALLET
1257
1258 tooltip += QString("<br>");
1259 tooltip += tr("Last received block was generated %1 ago.").arg(timeBehindText);
1260 tooltip += QString("<br>");
1261 tooltip += tr("Transactions after this will not yet be visible.");
1262 }
1263
1264 // Don't word-wrap this (fixed-width) tooltip
1265 tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
1266
1267 labelBlocksIcon->setToolTip(tooltip);
1268 progressBarLabel->setToolTip(tooltip);
1269 progressBar->setToolTip(tooltip);
1270}
1271
1273{
1274#ifdef ENABLE_WALLET
1275 auto activity = new CreateWalletActivity(getWalletController(), this);
1276 connect(activity, &CreateWalletActivity::created, this, &BitcoinGUI::setCurrentWallet);
1277 connect(activity, &CreateWalletActivity::created, rpcConsole, &RPCConsole::setCurrentWallet);
1278 activity->create();
1279#endif // ENABLE_WALLET
1280}
1281
1282void BitcoinGUI::message(const QString& title, QString message, unsigned int style, bool* ret, const QString& detailed_message)
1283{
1284 // Default title. On macOS, the window title is ignored (as required by the macOS Guidelines).
1285 QString strTitle{CLIENT_NAME};
1286 // Default to information icon
1287 int nMBoxIcon = QMessageBox::Information;
1288 int nNotifyIcon = Notificator::Information;
1289
1290 QString msgType;
1291 if (!title.isEmpty()) {
1292 msgType = title;
1293 } else {
1294 switch (style) {
1296 msgType = tr("Error");
1297 message = tr("Error: %1").arg(message);
1298 break;
1300 msgType = tr("Warning");
1301 message = tr("Warning: %1").arg(message);
1302 break;
1304 msgType = tr("Information");
1305 // No need to prepend the prefix here.
1306 break;
1307 default:
1308 break;
1309 }
1310 }
1311
1312 if (!msgType.isEmpty()) {
1313 strTitle += " - " + msgType;
1314 }
1315
1316 if (style & CClientUIInterface::ICON_ERROR) {
1317 nMBoxIcon = QMessageBox::Critical;
1318 nNotifyIcon = Notificator::Critical;
1319 } else if (style & CClientUIInterface::ICON_WARNING) {
1320 nMBoxIcon = QMessageBox::Warning;
1321 nNotifyIcon = Notificator::Warning;
1322 }
1323
1324 if (style & CClientUIInterface::MODAL) {
1325 // Check for buttons, use OK as default, if none was supplied
1326 QMessageBox::StandardButton buttons;
1327 if (!(buttons = (QMessageBox::StandardButton)(style & CClientUIInterface::BTN_MASK)))
1328 buttons = QMessageBox::Ok;
1329
1331 QMessageBox mBox(static_cast<QMessageBox::Icon>(nMBoxIcon), strTitle, message, buttons, this);
1332 mBox.setTextFormat(Qt::PlainText);
1333 mBox.setDetailedText(detailed_message);
1334 int r = mBox.exec();
1335 if (ret != nullptr)
1336 *ret = r == QMessageBox::Ok;
1337 } else {
1338 notificator->notify(static_cast<Notificator::Class>(nNotifyIcon), strTitle, message);
1339 }
1340}
1341
1343{
1344 if (e->type() == QEvent::PaletteChange) {
1345 overviewAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/overview")));
1346 sendCoinsAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/send")));
1347 receiveCoinsAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/receiving_addresses")));
1348 historyAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/history")));
1349 }
1350
1351 QMainWindow::changeEvent(e);
1352
1353#ifndef Q_OS_MACOS // Ignored on Mac
1354 if(e->type() == QEvent::WindowStateChange)
1355 {
1357 {
1358 QWindowStateChangeEvent *wsevt = static_cast<QWindowStateChangeEvent*>(e);
1359 if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized())
1360 {
1361 QTimer::singleShot(0, this, &BitcoinGUI::hide);
1362 e->ignore();
1363 }
1364 else if((wsevt->oldState() & Qt::WindowMinimized) && !isMinimized())
1365 {
1366 QTimer::singleShot(0, this, &BitcoinGUI::show);
1367 e->ignore();
1368 }
1369 }
1370 }
1371#endif
1372}
1373
1374void BitcoinGUI::closeEvent(QCloseEvent *event)
1375{
1376#ifndef Q_OS_MACOS // Ignored on Mac
1378 {
1380 {
1381 // close rpcConsole in case it was open to make some space for the shutdown window
1382 rpcConsole->close();
1383
1384 Q_EMIT quitRequested();
1385 }
1386 else
1387 {
1388 QMainWindow::showMinimized();
1389 event->ignore();
1390 }
1391 }
1392#else
1393 QMainWindow::closeEvent(event);
1394#endif
1395}
1396
1397void BitcoinGUI::showEvent(QShowEvent *event)
1398{
1399 // enable the debug window when the main window shows up
1400 openRPCConsoleAction->setEnabled(true);
1401 aboutAction->setEnabled(true);
1402 optionsAction->setEnabled(true);
1403}
1404
1405#ifdef ENABLE_WALLET
1406void BitcoinGUI::incomingTransaction(const QString& date, BitcoinUnit unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName)
1407{
1408 // On new transaction, make an info balloon
1409 QString msg = tr("Date: %1\n").arg(date) +
1410 tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(unit, amount, true));
1411 if (m_node.walletLoader().getWallets().size() > 1 && !walletName.isEmpty()) {
1412 msg += tr("Wallet: %1\n").arg(walletName);
1413 }
1414 msg += tr("Type: %1\n").arg(type);
1415 if (!label.isEmpty())
1416 msg += tr("Label: %1\n").arg(label);
1417 else if (!address.isEmpty())
1418 msg += tr("Address: %1\n").arg(address);
1419 message((amount)<0 ? tr("Sent transaction") : tr("Incoming transaction"),
1421}
1422#endif // ENABLE_WALLET
1423
1424void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
1425{
1426 // Accept only URIs
1427 if(event->mimeData()->hasUrls())
1428 event->acceptProposedAction();
1429}
1430
1431void BitcoinGUI::dropEvent(QDropEvent *event)
1432{
1433 if(event->mimeData()->hasUrls())
1434 {
1435 for (const QUrl &uri : event->mimeData()->urls())
1436 {
1437 Q_EMIT receivedURI(uri.toString());
1438 }
1439 }
1440 event->acceptProposedAction();
1441}
1442
1443bool BitcoinGUI::eventFilter(QObject *object, QEvent *event)
1444{
1445 // Catch status tip events
1446 if (event->type() == QEvent::StatusTip)
1447 {
1448 // Prevent adding text from setStatusTip(), if we currently use the status bar for displaying other stuff
1449 if (progressBarLabel->isVisible() || progressBar->isVisible())
1450 return true;
1451 }
1452 return QMainWindow::eventFilter(object, event);
1453}
1454
1455#ifdef ENABLE_WALLET
1456bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient)
1457{
1458 // URI has to be valid
1459 if (walletFrame && walletFrame->handlePaymentRequest(recipient))
1460 {
1462 gotoSendCoinsPage();
1463 return true;
1464 }
1465 return false;
1466}
1467
1468void BitcoinGUI::setHDStatus(bool privkeyDisabled, int hdEnabled)
1469{
1470 labelWalletHDStatusIcon->setThemedPixmap(privkeyDisabled ? QStringLiteral(":/icons/eye") : hdEnabled ? QStringLiteral(":/icons/hd_enabled") : QStringLiteral(":/icons/hd_disabled"), STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE);
1471 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>"));
1473}
1474
1475void BitcoinGUI::setEncryptionStatus(int status)
1476{
1477 switch(status)
1478 {
1481 encryptWalletAction->setChecked(false);
1482 changePassphraseAction->setEnabled(false);
1483 encryptWalletAction->setEnabled(false);
1484 break;
1487 encryptWalletAction->setChecked(false);
1488 changePassphraseAction->setEnabled(false);
1489 encryptWalletAction->setEnabled(true);
1490 break;
1494 labelWalletEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>unlocked</b>"));
1495 encryptWalletAction->setChecked(true);
1496 changePassphraseAction->setEnabled(true);
1497 encryptWalletAction->setEnabled(false);
1498 break;
1501 labelWalletEncryptionIcon->setThemedPixmap(QStringLiteral(":/icons/lock_closed"), STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE);
1502 labelWalletEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>locked</b>"));
1503 encryptWalletAction->setChecked(true);
1504 changePassphraseAction->setEnabled(true);
1505 encryptWalletAction->setEnabled(false);
1506 break;
1507 }
1508}
1509
1510void BitcoinGUI::updateWalletStatus()
1511{
1513
1514 WalletView * const walletView = walletFrame->currentWalletView();
1515 if (!walletView) {
1516 return;
1517 }
1518 WalletModel * const walletModel = walletView->getWalletModel();
1519 setEncryptionStatus(walletModel->getEncryptionStatus());
1520 setHDStatus(walletModel->wallet().privateKeysDisabled(), walletModel->wallet().hdEnabled());
1521}
1522#endif // ENABLE_WALLET
1523
1525{
1526 std::string ip_port;
1527 bool proxy_enabled = clientModel->getProxyInfo(ip_port);
1528
1529 if (proxy_enabled) {
1531 QString ip_port_q = QString::fromStdString(ip_port);
1533 labelProxyIcon->setToolTip(tr("Proxy is <b>enabled</b>: %1").arg(ip_port_q));
1534 } else {
1535 labelProxyIcon->show();
1536 }
1537 } else {
1538 labelProxyIcon->hide();
1539 }
1540}
1541
1543{
1544 QString window_title = CLIENT_NAME;
1545#ifdef ENABLE_WALLET
1546 if (walletFrame) {
1547 WalletModel* const wallet_model = walletFrame->currentWalletModel();
1548 if (wallet_model && !wallet_model->getWalletName().isEmpty()) {
1549 window_title += " - " + wallet_model->getDisplayName();
1550 }
1551 }
1552#endif
1553 if (!m_network_style->getTitleAddText().isEmpty()) {
1554 window_title += " - " + m_network_style->getTitleAddText();
1555 }
1556 setWindowTitle(window_title);
1557}
1558
1560{
1561 if(!clientModel)
1562 return;
1563
1564 if (!isHidden() && !isMinimized() && !GUIUtil::isObscured(this) && fToggleHidden) {
1565 hide();
1566 } else {
1568 }
1569}
1570
1572{
1574}
1575
1577{
1579 {
1580 if(rpcConsole)
1581 rpcConsole->hide();
1582 Q_EMIT quitRequested();
1583 }
1584}
1585
1586void BitcoinGUI::showProgress(const QString &title, int nProgress)
1587{
1588 if (nProgress == 0) {
1589 progressDialog = new QProgressDialog(title, QString(), 0, 100);
1591 progressDialog->setWindowModality(Qt::ApplicationModal);
1592 progressDialog->setAutoClose(false);
1593 progressDialog->setValue(0);
1594 } else if (nProgress == 100) {
1595 if (progressDialog) {
1596 progressDialog->close();
1597 progressDialog->deleteLater();
1598 progressDialog = nullptr;
1599 }
1600 } else if (progressDialog) {
1601 progressDialog->setValue(nProgress);
1602 }
1603}
1604
1606{
1607 if (modalOverlay && (progressBar->isVisible() || modalOverlay->isLayerVisible()))
1609}
1610
1611[[nodiscard]] static bool ThreadSafeMessageBox(BitcoinGUI* gui, const bilingual_str& message, unsigned int style)
1612{
1613 bool modal = (style & CClientUIInterface::MODAL);
1614 // The SECURE flag has no effect in the Qt GUI.
1615 // bool secure = (style & CClientUIInterface::SECURE);
1616 style &= ~CClientUIInterface::SECURE;
1617 bool ret = false;
1618
1619 QString detailed_message; // This is original message, in English, for googling and referencing.
1620 if (message.original != message.translated) {
1621 detailed_message = BitcoinGUI::tr("Original message:") + "\n" + QString::fromStdString(message.original);
1622 }
1623 // The title is empty for node messages. The fallback title is usually set
1624 // by `style`.
1625 const QString title{};
1626
1627 // In case of modal message, use blocking connection to wait for user to click a button
1628 bool invoked = QMetaObject::invokeMethod(gui, "message",
1629 modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
1630 Q_ARG(QString, title),
1631 Q_ARG(QString, QString::fromStdString(message.translated)),
1632 Q_ARG(unsigned int, style),
1633 Q_ARG(bool*, &ret),
1634 Q_ARG(QString, detailed_message));
1635 assert(invoked);
1636 return ret;
1637}
1638
1640{
1641 // Connect signals to client
1642 m_handler_message_box = m_node.handleMessageBox([this](const bilingual_str& message, unsigned int style) {
1643 (void)ThreadSafeMessageBox(this, message, style);
1644 });
1645 m_handler_question = m_node.handleQuestion([this](const bilingual_str& message, const std::string& /*non_interactive_message*/, unsigned int style) {
1646 return ThreadSafeMessageBox(this, message, style);
1647 });
1648}
1649
1651{
1652 // Disconnect signals from client
1653 m_handler_message_box->disconnect();
1654 m_handler_question->disconnect();
1655}
1656
1658{
1660 return m_mask_values_action->isChecked();
1661}
1662
1664 : m_platform_style{platformStyle}
1665{
1667 setToolTip(tr("Unit to show amounts in. Click to select another unit."));
1668 QList<BitcoinUnit> units = BitcoinUnits::availableUnits();
1669 int max_width = 0;
1670 const QFontMetrics fm(font());
1671 for (const BitcoinUnit unit : units) {
1672 max_width = qMax(max_width, GUIUtil::TextWidth(fm, BitcoinUnits::longName(unit)));
1673 }
1674 setMinimumSize(max_width, 0);
1675 setAlignment(Qt::AlignRight | Qt::AlignVCenter);
1676 setStyleSheet(QString("QLabel { color : %1 }").arg(m_platform_style->SingleColor().name()));
1677}
1678
1681{
1682 onDisplayUnitsClicked(event->pos());
1683}
1684
1686{
1687 if (e->type() == QEvent::PaletteChange) {
1688 QString style = QString("QLabel { color : %1 }").arg(m_platform_style->SingleColor().name());
1689 if (style != styleSheet()) {
1690 setStyleSheet(style);
1691 }
1692 }
1693
1694 QLabel::changeEvent(e);
1695}
1696
1699{
1700 menu = new QMenu(this);
1701 for (const BitcoinUnit u : BitcoinUnits::availableUnits()) {
1702 menu->addAction(BitcoinUnits::longName(u))->setData(QVariant::fromValue(u));
1703 }
1704 connect(menu, &QMenu::triggered, this, &UnitDisplayStatusBarControl::onMenuSelection);
1705}
1706
1709{
1710 if (_optionsModel)
1711 {
1712 this->optionsModel = _optionsModel;
1713
1714 // be aware of a display unit change reported by the OptionsModel object.
1716
1717 // initialize the display units label with the current value in the model.
1718 updateDisplayUnit(_optionsModel->getDisplayUnit());
1719 }
1720}
1721
1724{
1725 setText(BitcoinUnits::longName(newUnits));
1726}
1727
1730{
1731 QPoint globalPos = mapToGlobal(point);
1732 menu->exec(globalPos);
1733}
1734
1737{
1738 if (action)
1739 {
1740 optionsModel->setDisplayUnit(action->data());
1741 }
1742}
1743
1744#include <moc_bitcoingui.cpp>
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:47
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.
#define Assume(val)
Assume is the identity function.
Definition: check.h:128
Bitcoin GUI main class.
Definition: bitcoingui.h:68
void updateHeadersPresyncProgressLabel(int64_t height, const QDateTime &blockDate)
GUIUtil::ClickableProgressBar * progressBar
Definition: bitcoingui.h:132
QAction * m_close_all_wallets_action
Definition: bitcoingui.h:162
void showEvent(QShowEvent *event) override
QLabel * progressBarLabel
Definition: bitcoingui.h:131
QAction * m_open_wallet_action
Definition: bitcoingui.h:158
static const std::string DEFAULT_UIPLATFORM
Definition: bitcoingui.h:72
QAction * m_export_watchonly_action
Definition: bitcoingui.h:170
QAction * openAction
Definition: bitcoingui.h:155
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:681
GUIUtil::ClickableLabel * connectionsControl
Definition: bitcoingui.h:129
void receivedURI(const QString &uri)
Signal raised when a URI was entered or dragged to the GUI.
ModalOverlay * modalOverlay
Definition: bitcoingui.h:180
GUIUtil::ThemedLabel * labelWalletEncryptionIcon
Definition: bitcoingui.h:126
QAction * changePassphraseAction
Definition: bitcoingui.h:152
void openOptionsDialogWithTab(OptionsDialog::Tab tab)
Open the OptionsDialog on the specified tab index.
int prevBlocks
Keep track of previous number of blocks, to detect progress.
Definition: bitcoingui.h:189
QAction * openRPCConsoleAction
Definition: bitcoingui.h:154
const NetworkStyle *const m_network_style
Definition: bitcoingui.h:193
void changeEvent(QEvent *e) override
GUIUtil::ClickableLabel * labelProxyIcon
Definition: bitcoingui.h:128
void optionsClicked()
Show configuration dialog.
Definition: bitcoingui.cpp:986
QAction * historyAction
Definition: bitcoingui.h:138
bool eventFilter(QObject *object, QEvent *event) override
QMenu * m_open_wallet_menu
Definition: bitcoingui.h:159
void createTrayIcon()
Create system tray icon and notification.
Definition: bitcoingui.cpp:890
QAction * m_load_psbt_clipboard_action
Definition: bitcoingui.h:146
QAction * quitAction
Definition: bitcoingui.h:139
void setNetworkActive(bool network_active)
Set network state shown in the UI.
void setPrivacy(bool privacy)
QProgressDialog * progressDialog
Definition: bitcoingui.h:133
BitcoinGUI(interfaces::Node &node, const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent=nullptr)
Definition: bitcoingui.cpp:91
std::unique_ptr< interfaces::Handler > m_handler_message_box
Definition: bitcoingui.h:120
WalletFrame * walletFrame
Definition: bitcoingui.h:123
void updateProxyIcon()
Set the proxy-enabled icon as shown in the UI.
QAction * m_restore_wallet_action
Definition: bitcoingui.h:160
QAction * receiveCoinsAction
Definition: bitcoingui.h:148
const std::unique_ptr< QMenu > trayIconMenu
Definition: bitcoingui.h:176
QAction * usedSendingAddressesAction
Definition: bitcoingui.h:141
void unsubscribeFromCoreSignals()
Disconnect core signals from GUI client.
void closeEvent(QCloseEvent *event) override
QAction * verifyMessageAction
Definition: bitcoingui.h:144
QAction * m_migrate_wallet_action
Definition: bitcoingui.h:168
void createTrayIconMenu()
Create system tray menu (or setup the dock menu)
Definition: bitcoingui.cpp:903
HelpMessageDialog * helpMessageDialog
Definition: bitcoingui.h:179
void aboutClicked()
Show about dialog.
Definition: bitcoingui.cpp:991
void toggleHidden()
Simply calls showNormalIfMinimized(true)
QAction * encryptWalletAction
Definition: bitcoingui.h:150
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.
QAction * m_mask_values_action
Definition: bitcoingui.h:167
int spinnerFrame
Definition: bitcoingui.h:190
QAction * aboutAction
Definition: bitcoingui.h:147
void consoleShown(RPCConsole *console)
Signal raised when RPC console shown.
bool isPrivacyModeActivated() const
QMenu * m_migrate_wallet_menu
Definition: bitcoingui.h:169
void showDebugWindowActivateConsole()
Show debug window and set focus to the console.
void dropEvent(QDropEvent *event) override
void showProgress(const QString &title, int nProgress)
Show progress dialog e.g.
QAction * usedReceivingAddressesAction
Definition: bitcoingui.h:142
void subscribeToCoreSignals()
Connect core signals to GUI client.
void createToolBars()
Create the toolbars.
Definition: bitcoingui.cpp:645
UnitDisplayStatusBarControl * unitDisplayControl
Definition: bitcoingui.h:125
QAction * optionsAction
Definition: bitcoingui.h:149
void updateWindowTitle()
void setWalletActionsEnabled(bool enabled)
Enable or disable all wallet-related actions.
Definition: bitcoingui.cpp:871
const PlatformStyle * platformStyle
Definition: bitcoingui.h:192
void dragEnterEvent(QDragEnterEvent *event) override
QAction * m_close_wallet_action
Definition: bitcoingui.h:161
QAction * overviewAction
Definition: bitcoingui.h:137
GUIUtil::ClickableLabel * labelBlocksIcon
Definition: bitcoingui.h:130
interfaces::Node & m_node
Definition: bitcoingui.h:116
QAction * m_create_wallet_action
Definition: bitcoingui.h:157
QAction * m_load_psbt_action
Definition: bitcoingui.h:145
void detectShutdown()
called by a timer to check if shutdown has been requested
bool enableWallet
Definition: bitcoingui.h:95
RPCConsole * rpcConsole
Definition: bitcoingui.h:178
QMenu * m_network_context_menu
Definition: bitcoingui.h:182
QAction * backupWalletAction
Definition: bitcoingui.h:151
QAction * showHelpMessageAction
Definition: bitcoingui.h:156
QAction * aboutQtAction
Definition: bitcoingui.h:153
void showNormalIfMinimized()
Show window if hidden, unminimize when minimized, rise when obscured or show if hidden and fToggleHid...
Definition: bitcoingui.h:316
ClientModel * clientModel
Definition: bitcoingui.h:122
void updateHeadersSyncProgressLabel()
void createMenuBar()
Create the menu bar and sub-menus.
Definition: bitcoingui.cpp:550
QSystemTrayIcon * trayIcon
Definition: bitcoingui.h:175
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.
QAction * sendCoinsAction
Definition: bitcoingui.h:140
void quitRequested()
QToolBar * appToolBar
Definition: bitcoingui.h:136
void setNumConnections(int count)
Set number of connections shown in the UI.
QAction * signMessageAction
Definition: bitcoingui.h:143
GUIUtil::ThemedLabel * labelWalletHDStatusIcon
Definition: bitcoingui.h:127
void showModalOverlay()
Notificator * notificator
Definition: bitcoingui.h:177
std::unique_ptr< interfaces::Handler > m_handler_question
Definition: bitcoingui.h:121
QMenuBar * appMenuBar
Definition: bitcoingui.h:135
static QList< Unit > availableUnits()
Get list of units, for drop-down box.
static QString longName(Unit unit)
Long name.
static QString formatWithUnit(Unit unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD)
Format as string (with unit)
Unit
Bitcoin units.
Definition: bitcoinunits.h:42
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:89
Signals for UI communication.
Definition: interface_ui.h:22
@ BTN_MASK
Mask of all available buttons in CClientUIInterface::MessageBoxFlags This needs to be updated,...
Definition: interface_ui.h:52
@ MSG_INFORMATION
Predefined combinations for certain default usage cases.
Definition: interface_ui.h:62
@ MODAL
Force blocking, modal message box dialog (not just OS notification)
Definition: interface_ui.h:56
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:850
"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:44
void displayUnitChanged(BitcoinUnit unit)
void showTrayIconChanged(bool)
bool getMinimizeToTray() const
Definition: optionsmodel.h:102
BitcoinUnit getDisplayUnit() const
Definition: optionsmodel.h:104
bool getShowTrayIcon() const
Definition: optionsmodel.h:101
QVariant getOption(OptionID option, const std::string &suffix="") const
bool getMinimizeOnClose() const
Definition: optionsmodel.h:103
void setDisplayUnit(const QVariant &new_unit)
Updates current unit in memory, settings and emits displayUnitChanged(new_unit) signal.
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
QColor SingleColor() const
Local Bitcoin RPC console.
Definition: rpcconsole.h: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:622
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:345
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:347
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 walletRemoved(WalletModel *wallet_model)
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:138
QString getDisplayName() const
static bool isWalletEnabled()
QString getWalletName() const
void outOfSyncWarningClicked()
Notify that the out of sync warning icon has been pressed.
WalletModel * getWalletModel() const noexcept
Definition: walletview.h:46
void message(const QString &title, const QString &message, unsigned int style)
Fired when a message should be reported to the user.
void incomingTransaction(const QString &date, BitcoinUnit unit, const CAmount &amount, const QString &type, const QString &address, const QString &label, const QString &walletName)
Notify that a new transaction appeared.
void transactionClicked()
void coinsSent()
void setPrivacy(bool privacy)
void encryptionStatusChanged()
Encryption status of wallet changed.
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:71
virtual void setNetworkActive(bool active)=0
Set network active.
virtual std::unique_ptr< Handler > handleMessageBox(MessageBoxFn fn)=0
virtual bool getNetworkActive()=0
Get network active.
virtual std::unique_ptr< Handler > handleQuestion(QuestionFn fn)=0
virtual WalletLoader & walletLoader()=0
Get wallet loader.
virtual bool shutdownRequested()=0
Return whether shutdown was requested.
virtual util::Result< std::string > exportWatchOnlyWallet(const fs::path &destination)=0
Export a watchonly wallet file. See CWallet::ExportWatchOnlyWallet.
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:185
#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:399
Qt::ConnectionType blockingGUIThreadConnection()
Get connection type to call object slot in GUI thread with invokeMethod.
Definition: guiutil.cpp:380
QString WalletDisplayName(const QString &name)
Definition: guiutil.cpp:990
void PopupMenu(QMenu *menu, const QPoint &point, QAction *at_action)
Call QMenu::popup() only on supported QT_QPA_PLATFORM.
Definition: guiutil.cpp:944
void ShowModalDialogAsynchronously(QDialog *dialog)
Shows a QDialog instance asynchronously, and deletes it on close.
Definition: guiutil.cpp:983
void handleCloseWindowShortcut(QWidget *w)
Definition: guiutil.cpp:426
void PolishProgressDialog(QProgressDialog *dialog)
Definition: guiutil.cpp:897
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:355
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix when ...
Definition: guiutil.cpp:315
ClickableProgressBar ProgressBar
Definition: guiutil.h:300
void bringToFront(QWidget *w)
Definition: guiutil.cpp:408
bool HasPixmap(const QLabel *label)
Returns true if pixmap has been set.
Definition: guiutil.cpp:956
QString formatNiceTimeOffset(qint64 secs)
Definition: guiutil.cpp:783
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:911
fs::path QStringToPath(const QString &path)
Convert QString to OS specific boost path through UTF-8.
Definition: guiutil.cpp:672
Definition: messages.h:21
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:93
const char * name
Definition: rest.cpp:50
static RPCMethod help()
Definition: server.cpp:122
int64_t nPowTargetSpacing
Definition: params.h:123
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:51
static int count
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
Definition: time.cpp:89
assert(!tx.IsCoinBase())
SynchronizationState
Current sync state passed to tip changed callbacks.
Definition: validation.h:96