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 *.wallet);;") + tr("All Files") + QLatin1String(" (*)"), 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,
533 tr("Save Watch-only Wallet Export"), QString(),
534 //: Name of the wallet data file format.
535 tr("Wallet Data") + QLatin1String(" (*.dat)"), nullptr);
536
537 if (destination.isEmpty()) return;
538 WalletModel* model = walletFrame->currentWalletModel();
539 if (!Assume(model)) return;
541 if (export_res) {
542 QMessageBox::information(nullptr, tr("Export Successful"), tr("The wallet has been exported to ") + QString::fromStdString(*export_res));
543 } else {
544 QMessageBox::critical(nullptr, tr("Export Error"), QString::fromStdString(util::ErrorString(export_res).translated));
545 }
546 });
547 }
548#endif // ENABLE_WALLET
549
550 connect(new QShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_C), this), &QShortcut::activated, this, &BitcoinGUI::showDebugWindowActivateConsole);
551 connect(new QShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_D), this), &QShortcut::activated, this, &BitcoinGUI::showDebugWindow);
552}
553
555{
556 appMenuBar = menuBar();
557
558 // Configure the menus
559 QMenu *file = appMenuBar->addMenu(tr("&File"));
560 if(walletFrame)
561 {
562 file->addAction(m_create_wallet_action);
563 file->addAction(m_open_wallet_action);
564 file->addAction(m_close_wallet_action);
565 file->addAction(m_close_all_wallets_action);
566 file->addAction(m_migrate_wallet_action);
567 file->addSeparator();
568 file->addAction(backupWalletAction);
569 file->addAction(m_restore_wallet_action);
570 file->addAction(m_export_watchonly_action);
571 file->addSeparator();
572 file->addAction(openAction);
573 file->addAction(signMessageAction);
574 file->addAction(verifyMessageAction);
575 file->addAction(m_load_psbt_action);
576 file->addAction(m_load_psbt_clipboard_action);
577 file->addSeparator();
578 }
579 file->addAction(quitAction);
580
581 QMenu *settings = appMenuBar->addMenu(tr("&Settings"));
582 if(walletFrame)
583 {
584 settings->addAction(encryptWalletAction);
585 settings->addAction(changePassphraseAction);
586 settings->addSeparator();
587 settings->addAction(m_mask_values_action);
588 settings->addSeparator();
589 }
590 settings->addAction(optionsAction);
591
592 QMenu* window_menu = appMenuBar->addMenu(tr("&Window"));
593
594 QAction* minimize_action = window_menu->addAction(tr("&Minimize"));
595 minimize_action->setShortcut(QKeySequence(tr("Ctrl+M")));
596 connect(minimize_action, &QAction::triggered, [] {
597 QApplication::activeWindow()->showMinimized();
598 });
599 connect(qApp, &QApplication::focusWindowChanged, this, [minimize_action] (QWindow* window) {
600 minimize_action->setEnabled(window != nullptr && (window->flags() & Qt::Dialog) != Qt::Dialog && window->windowState() != Qt::WindowMinimized);
601 });
602
603#ifdef Q_OS_MACOS
604 QAction* zoom_action = window_menu->addAction(tr("Zoom"));
605 connect(zoom_action, &QAction::triggered, [] {
606 QWindow* window = qApp->focusWindow();
607 if (window->windowState() != Qt::WindowMaximized) {
608 window->showMaximized();
609 } else {
610 window->showNormal();
611 }
612 });
613
614 connect(qApp, &QApplication::focusWindowChanged, this, [zoom_action] (QWindow* window) {
615 zoom_action->setEnabled(window != nullptr);
616 });
617#endif
618
619 if (walletFrame) {
620#ifdef Q_OS_MACOS
621 window_menu->addSeparator();
622 QAction* main_window_action = window_menu->addAction(tr("Main Window"));
623 connect(main_window_action, &QAction::triggered, [this] {
625 });
626#endif
627 window_menu->addSeparator();
628 window_menu->addAction(usedSendingAddressesAction);
629 window_menu->addAction(usedReceivingAddressesAction);
630 }
631
632 window_menu->addSeparator();
633 for (RPCConsole::TabTypes tab_type : rpcConsole->tabs()) {
634 QAction* tab_action = window_menu->addAction(rpcConsole->tabTitle(tab_type));
635 tab_action->setShortcut(rpcConsole->tabShortcut(tab_type));
636 connect(tab_action, &QAction::triggered, [this, tab_type] {
637 rpcConsole->setTabFocus(tab_type);
639 });
640 }
641
642 QMenu *help = appMenuBar->addMenu(tr("&Help"));
643 help->addAction(showHelpMessageAction);
644 help->addSeparator();
645 help->addAction(aboutAction);
646 help->addAction(aboutQtAction);
647}
648
650{
651 if(walletFrame)
652 {
653 QToolBar *toolbar = addToolBar(tr("Tabs toolbar"));
654 appToolBar = toolbar;
655 toolbar->setMovable(false);
656 toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
657 toolbar->addAction(overviewAction);
658 toolbar->addAction(sendCoinsAction);
659 toolbar->addAction(receiveCoinsAction);
660 toolbar->addAction(historyAction);
661 overviewAction->setChecked(true);
662
663#ifdef ENABLE_WALLET
664 QWidget *spacer = new QWidget();
665 spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
666 toolbar->addWidget(spacer);
667
668 m_wallet_selector = new QComboBox();
669 m_wallet_selector->setSizeAdjustPolicy(QComboBox::AdjustToContents);
670 connect(m_wallet_selector, qOverload<int>(&QComboBox::currentIndexChanged), this, &BitcoinGUI::setCurrentWalletBySelectorIndex);
671
672 m_wallet_selector_label = new QLabel();
673 m_wallet_selector_label->setText(tr("Wallet:") + " ");
674 m_wallet_selector_label->setBuddy(m_wallet_selector);
675
676 m_wallet_selector_label_action = appToolBar->addWidget(m_wallet_selector_label);
677 m_wallet_selector_action = appToolBar->addWidget(m_wallet_selector);
678
679 m_wallet_selector_label_action->setVisible(false);
680 m_wallet_selector_action->setVisible(false);
681#endif
682 }
683}
684
686{
687 this->clientModel = _clientModel;
688 if(_clientModel)
689 {
690 // Create system tray menu (or setup the dock menu) that late to prevent users from calling actions,
691 // while the client has not yet fully loaded
693
694 // Keep up to date with client
698 });
701
702 modalOverlay->setKnownBestHeight(tip_info->header_height, QDateTime::fromSecsSinceEpoch(tip_info->header_time), /*presync=*/false);
703 setNumBlocks(tip_info->block_height, QDateTime::fromSecsSinceEpoch(tip_info->block_time), tip_info->verification_progress, SyncType::BLOCK_SYNC, SynchronizationState::INIT_DOWNLOAD);
704 connect(_clientModel, &ClientModel::numBlocksChanged, this, &BitcoinGUI::setNumBlocks);
705
706 // Receive and report messages from client model
707 connect(_clientModel, &ClientModel::message, [this](const QString &title, const QString &message, unsigned int style){
708 this->message(title, message, style);
709 });
710
711 // Show progress dialog
712 connect(_clientModel, &ClientModel::showProgress, this, &BitcoinGUI::showProgress);
713
714 rpcConsole->setClientModel(_clientModel, tip_info->block_height, tip_info->block_time, tip_info->verification_progress);
715
717
718#ifdef ENABLE_WALLET
719 if(walletFrame)
720 {
721 walletFrame->setClientModel(_clientModel);
722 }
723#endif // ENABLE_WALLET
725
726 OptionsModel* optionsModel = _clientModel->getOptionsModel();
727 if (optionsModel && trayIcon) {
728 // be aware of the tray icon disable state change reported by the OptionsModel object.
729 connect(optionsModel, &OptionsModel::showTrayIconChanged, trayIcon, &QSystemTrayIcon::setVisible);
730
731 // initialize the disable state of the tray icon with the current value in the model.
732 trayIcon->setVisible(optionsModel->getShowTrayIcon());
733 }
734
735 m_mask_values_action->setChecked(_clientModel->getOptionsModel()->getOption(OptionsModel::OptionID::MaskValues).toBool());
736 } else {
737 // Shutdown requested, disable menus
738 if (trayIconMenu)
739 {
740 // Disable context menu on tray icon
741 trayIconMenu->clear();
742 }
743 // Propagate cleared model to child objects
744 rpcConsole->setClientModel(nullptr);
745#ifdef ENABLE_WALLET
746 if (walletFrame)
747 {
748 walletFrame->setClientModel(nullptr);
749 }
750#endif // ENABLE_WALLET
752 // Disable top bar menu actions
753 appMenuBar->clear();
754 }
755}
756
757#ifdef ENABLE_WALLET
758void BitcoinGUI::enableHistoryAction(bool privacy)
759{
761 historyAction->setEnabled(!privacy);
762 if (historyAction->isChecked()) gotoOverviewPage();
763 }
764}
765
766void BitcoinGUI::setWalletController(WalletController* wallet_controller, bool show_loading_minimized)
767{
768 assert(!m_wallet_controller);
769 assert(wallet_controller);
770
771 m_wallet_controller = wallet_controller;
772
773 m_create_wallet_action->setEnabled(true);
774 m_open_wallet_action->setEnabled(true);
776 m_restore_wallet_action->setEnabled(true);
777 m_migrate_wallet_action->setEnabled(true);
779
780 GUIUtil::ExceptionSafeConnect(wallet_controller, &WalletController::walletAdded, this, &BitcoinGUI::addWallet);
781 connect(wallet_controller, &WalletController::walletRemoved, this, &BitcoinGUI::removeWallet);
782 connect(wallet_controller, &WalletController::destroyed, this, [this] {
783 // wallet_controller gets destroyed manually, but it leaves our member copy dangling
784 m_wallet_controller = nullptr;
785 });
786
787 auto activity = new LoadWalletsActivity(m_wallet_controller, this);
788 activity->load(show_loading_minimized);
789}
790
791WalletController* BitcoinGUI::getWalletController()
792{
793 return m_wallet_controller;
794}
795
796void BitcoinGUI::addWallet(WalletModel* walletModel)
797{
798 if (!walletFrame || !m_wallet_controller) return;
799
800 WalletView* wallet_view = new WalletView(walletModel, platformStyle, walletFrame);
801 if (!walletFrame->addView(wallet_view)) return;
802
803 rpcConsole->addWallet(walletModel);
804 if (m_wallet_selector->count() == 0) {
806 } else if (m_wallet_selector->count() == 1) {
807 m_wallet_selector_label_action->setVisible(true);
808 m_wallet_selector_action->setVisible(true);
809 }
810
812 connect(wallet_view, &WalletView::transactionClicked, this, &BitcoinGUI::gotoHistoryPage);
813 connect(wallet_view, &WalletView::coinsSent, this, &BitcoinGUI::gotoHistoryPage);
814 connect(wallet_view, &WalletView::message, [this](const QString& title, const QString& message, unsigned int style) {
815 this->message(title, message, style);
816 });
817 connect(wallet_view, &WalletView::encryptionStatusChanged, this, &BitcoinGUI::updateWalletStatus);
818 connect(wallet_view, &WalletView::incomingTransaction, this, &BitcoinGUI::incomingTransaction);
819 connect(this, &BitcoinGUI::setPrivacy, wallet_view, &WalletView::setPrivacy);
820 wallet_view->setPrivacy(isPrivacyModeActivated());
821 const QString display_name = walletModel->getDisplayName();
822 m_wallet_selector->addItem(display_name, QVariant::fromValue(walletModel));
823}
824
825void BitcoinGUI::removeWallet(WalletModel* walletModel)
826{
827 if (!walletFrame) return;
828
831
832 int index = m_wallet_selector->findData(QVariant::fromValue(walletModel));
833 m_wallet_selector->removeItem(index);
834 if (m_wallet_selector->count() == 0) {
836 overviewAction->setChecked(true);
837 } else if (m_wallet_selector->count() == 1) {
838 m_wallet_selector_label_action->setVisible(false);
839 m_wallet_selector_action->setVisible(false);
840 }
841 rpcConsole->removeWallet(walletModel);
842 walletFrame->removeWallet(walletModel);
844}
845
846void BitcoinGUI::setCurrentWallet(WalletModel* wallet_model)
847{
848 if (!walletFrame || !m_wallet_controller) return;
849 walletFrame->setCurrentWallet(wallet_model);
850 for (int index = 0; index < m_wallet_selector->count(); ++index) {
851 if (m_wallet_selector->itemData(index).value<WalletModel*>() == wallet_model) {
852 m_wallet_selector->setCurrentIndex(index);
853 break;
854 }
855 }
856 m_export_watchonly_action->setEnabled(!wallet_model->wallet().privateKeysDisabled());
858}
859
860void BitcoinGUI::setCurrentWalletBySelectorIndex(int index)
861{
862 WalletModel* wallet_model = m_wallet_selector->itemData(index).value<WalletModel*>();
863 if (wallet_model) setCurrentWallet(wallet_model);
864}
865
866void BitcoinGUI::removeAllWallets()
867{
868 if(!walletFrame)
869 return;
872}
873#endif // ENABLE_WALLET
874
876{
877 overviewAction->setEnabled(enabled);
878 sendCoinsAction->setEnabled(enabled);
879 receiveCoinsAction->setEnabled(enabled);
880 historyAction->setEnabled(enabled && !isPrivacyModeActivated());
881 encryptWalletAction->setEnabled(enabled);
882 backupWalletAction->setEnabled(enabled);
883 changePassphraseAction->setEnabled(enabled);
884 signMessageAction->setEnabled(enabled);
885 verifyMessageAction->setEnabled(enabled);
886 usedSendingAddressesAction->setEnabled(enabled);
887 usedReceivingAddressesAction->setEnabled(enabled);
888 openAction->setEnabled(enabled);
889 m_close_wallet_action->setEnabled(enabled);
890 m_close_all_wallets_action->setEnabled(enabled);
891 m_export_watchonly_action->setEnabled(enabled);
892}
893
895{
896 assert(QSystemTrayIcon::isSystemTrayAvailable());
897
898#ifndef Q_OS_MACOS
899 if (QSystemTrayIcon::isSystemTrayAvailable()) {
900 trayIcon = new QSystemTrayIcon(m_network_style->getTrayAndWindowIcon(), this);
901 QString toolTip = tr("%1 client").arg(CLIENT_NAME) + " " + m_network_style->getTitleAddText();
902 trayIcon->setToolTip(toolTip);
903 }
904#endif
905}
906
908{
909#ifndef Q_OS_MACOS
910 if (!trayIcon) return;
911#endif // Q_OS_MACOS
912
913 // Configuration of the tray icon (or Dock icon) menu.
914 QAction* show_hide_action{nullptr};
915#ifndef Q_OS_MACOS
916 // Note: On macOS, the Dock icon's menu already has Show / Hide action.
917 show_hide_action = trayIconMenu->addAction(QString(), this, &BitcoinGUI::toggleHidden);
918 trayIconMenu->addSeparator();
919#endif // Q_OS_MACOS
920
921 QAction* send_action{nullptr};
922 QAction* receive_action{nullptr};
923 QAction* sign_action{nullptr};
924 QAction* verify_action{nullptr};
925 if (enableWallet) {
926 send_action = trayIconMenu->addAction(sendCoinsAction->text(), sendCoinsAction, &QAction::trigger);
927 receive_action = trayIconMenu->addAction(receiveCoinsAction->text(), receiveCoinsAction, &QAction::trigger);
928 trayIconMenu->addSeparator();
929 sign_action = trayIconMenu->addAction(signMessageAction->text(), signMessageAction, &QAction::trigger);
930 verify_action = trayIconMenu->addAction(verifyMessageAction->text(), verifyMessageAction, &QAction::trigger);
931 trayIconMenu->addSeparator();
932 }
933 QAction* options_action = trayIconMenu->addAction(optionsAction->text(), optionsAction, &QAction::trigger);
934 options_action->setMenuRole(QAction::PreferencesRole);
935 QAction* node_window_action = trayIconMenu->addAction(openRPCConsoleAction->text(), openRPCConsoleAction, &QAction::trigger);
936 QAction* quit_action{nullptr};
937#ifndef Q_OS_MACOS
938 // Note: On macOS, the Dock icon's menu already has Quit action.
939 trayIconMenu->addSeparator();
940 quit_action = trayIconMenu->addAction(quitAction->text(), quitAction, &QAction::trigger);
941
942 trayIcon->setContextMenu(trayIconMenu.get());
943 connect(trayIcon, &QSystemTrayIcon::activated, [this](QSystemTrayIcon::ActivationReason reason) {
944 if (reason == QSystemTrayIcon::Trigger) {
945 // Click on system tray icon triggers show/hide of the main window
946 toggleHidden();
947 }
948 });
949#else
950 // Note: On macOS, the Dock icon is used to provide the tray's functionality.
952 connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, [this] {
953 if (m_node.shutdownRequested()) return; // nothing to show, node is shutting down.
954 show();
955 activateWindow();
956 });
957 trayIconMenu->setAsDockMenu();
958#endif // Q_OS_MACOS
959
960 connect(
961 // Using QSystemTrayIcon::Context is not reliable.
962 // See https://bugreports.qt.io/browse/QTBUG-91697
963 trayIconMenu.get(), &QMenu::aboutToShow,
964 [this, show_hide_action, send_action, receive_action, sign_action, verify_action, options_action, node_window_action, quit_action] {
965 if (m_node.shutdownRequested()) return; // nothing to do, node is shutting down.
966
967 if (show_hide_action) show_hide_action->setText(
968 (!isHidden() && !isMinimized() && !GUIUtil::isObscured(this)) ?
969 tr("&Hide") :
970 tr("S&how"));
971 if (QApplication::activeModalWidget()) {
972 for (QAction* a : trayIconMenu.get()->actions()) {
973 a->setEnabled(false);
974 }
975 } else {
976 if (show_hide_action) show_hide_action->setEnabled(true);
977 if (enableWallet) {
978 send_action->setEnabled(sendCoinsAction->isEnabled());
979 receive_action->setEnabled(receiveCoinsAction->isEnabled());
980 sign_action->setEnabled(signMessageAction->isEnabled());
981 verify_action->setEnabled(verifyMessageAction->isEnabled());
982 }
983 options_action->setEnabled(optionsAction->isEnabled());
984 node_window_action->setEnabled(openRPCConsoleAction->isEnabled());
985 if (quit_action) quit_action->setEnabled(true);
986 }
987 });
988}
989
991{
993}
994
996{
997 if(!clientModel)
998 return;
999
1000 auto dlg = new HelpMessageDialog(this, /*about=*/true);
1002}
1003
1005{
1007 Q_EMIT consoleShown(rpcConsole);
1008}
1009
1011{
1014}
1015
1017{
1019}
1020
1021#ifdef ENABLE_WALLET
1022void BitcoinGUI::openClicked()
1023{
1024 OpenURIDialog dlg(platformStyle, this);
1025 if(dlg.exec())
1026 {
1027 Q_EMIT receivedURI(dlg.getURI());
1028 }
1029}
1030
1031void BitcoinGUI::gotoOverviewPage()
1032{
1033 overviewAction->setChecked(true);
1035}
1036
1037void BitcoinGUI::gotoHistoryPage()
1038{
1039 historyAction->setChecked(true);
1041}
1042
1043void BitcoinGUI::gotoReceiveCoinsPage()
1044{
1045 receiveCoinsAction->setChecked(true);
1047}
1048
1049void BitcoinGUI::gotoSendCoinsPage(QString addr)
1050{
1051 sendCoinsAction->setChecked(true);
1053}
1054
1055void BitcoinGUI::gotoSignMessageTab(QString addr)
1056{
1058}
1059
1060void BitcoinGUI::gotoVerifyMessageTab(QString addr)
1061{
1063}
1064void BitcoinGUI::gotoLoadPSBT(bool from_clipboard)
1065{
1066 if (walletFrame) walletFrame->gotoLoadPSBT(from_clipboard);
1067}
1068#endif // ENABLE_WALLET
1069
1071{
1072 if (!clientModel) return;
1074 QString icon;
1075 switch(count)
1076 {
1077 case 0: icon = ":/icons/connect_0"; break;
1078 case 1: case 2: case 3: icon = ":/icons/connect_1"; break;
1079 case 4: case 5: case 6: icon = ":/icons/connect_2"; break;
1080 case 7: case 8: case 9: icon = ":/icons/connect_3"; break;
1081 default: icon = ":/icons/connect_4"; break;
1082 }
1083
1084 QString tooltip;
1085
1086 if (m_node.getNetworkActive()) {
1087 //: A substring of the tooltip.
1088 tooltip = tr("%n active connection(s) to Bitcoin network.", "", count);
1089 } else {
1090 //: A substring of the tooltip.
1091 tooltip = tr("Network activity disabled.");
1092 icon = ":/icons/network_disabled";
1093 }
1094
1095 // Don't word-wrap this (fixed-width) tooltip
1096 tooltip = QLatin1String("<nobr>") + tooltip + QLatin1String("<br>") +
1097 //: A substring of the tooltip. "More actions" are available via the context menu.
1098 tr("Click for more actions.") + QLatin1String("</nobr>");
1099 connectionsControl->setToolTip(tooltip);
1100
1102}
1103
1105{
1107}
1108
1109void BitcoinGUI::setNetworkActive(bool network_active)
1110{
1112 m_network_context_menu->clear();
1113 m_network_context_menu->addAction(
1114 //: A context menu item. The "Peers tab" is an element of the "Node window".
1115 tr("Show Peers tab"),
1116 [this] {
1119 });
1120 m_network_context_menu->addAction(
1121 network_active ?
1122 //: A context menu item.
1123 tr("Disable network activity") :
1124 //: A context menu item. The network activity was disabled previously.
1125 tr("Enable network activity"),
1126 [this, new_state = !network_active] { m_node.setNetworkActive(new_state); });
1127}
1128
1130{
1131 int64_t headersTipTime = clientModel->getHeaderTipTime();
1132 int headersTipHeight = clientModel->getHeaderTipHeight();
1133 int estHeadersLeft = (GetTime() - headersTipTime) / Params().GetConsensus().nPowTargetSpacing;
1134 if (estHeadersLeft > HEADER_HEIGHT_DELTA_SYNC)
1135 progressBarLabel->setText(tr("Syncing Headers (%1%)…").arg(QString::number(100.0 / (headersTipHeight+estHeadersLeft)*headersTipHeight, 'f', 1)));
1136}
1137
1138void BitcoinGUI::updateHeadersPresyncProgressLabel(int64_t height, const QDateTime& blockDate)
1139{
1140 int estHeadersLeft = blockDate.secsTo(QDateTime::currentDateTime()) / Params().GetConsensus().nPowTargetSpacing;
1141 if (estHeadersLeft > HEADER_HEIGHT_DELTA_SYNC)
1142 progressBarLabel->setText(tr("Pre-syncing Headers (%1%)…").arg(QString::number(100.0 / (height+estHeadersLeft)*height, 'f', 1)));
1143}
1144
1146{
1148 return;
1149
1150 auto dlg = new OptionsDialog(this, enableWallet);
1152 dlg->setCurrentTab(tab);
1153 dlg->setClientModel(clientModel);
1154 dlg->setModel(clientModel->getOptionsModel());
1156}
1157
1158void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state)
1159{
1160// Disabling macOS App Nap on initial sync, disk and reindex operations.
1161#ifdef Q_OS_MACOS
1162 if (sync_state == SynchronizationState::POST_INIT) {
1163 m_app_nap_inhibitor->enableAppNap();
1164 } else {
1165 m_app_nap_inhibitor->disableAppNap();
1166 }
1167#endif
1168
1169 if (modalOverlay)
1170 {
1171 if (synctype != SyncType::BLOCK_SYNC)
1173 else
1174 modalOverlay->tipUpdate(count, blockDate, nVerificationProgress);
1175 }
1176 if (!clientModel)
1177 return;
1178
1179 // Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbled text)
1180 statusBar()->clearMessage();
1181
1182 // Acquire current block source
1183 BlockSource blockSource{clientModel->getBlockSource()};
1184 switch (blockSource) {
1186 if (synctype == SyncType::HEADER_PRESYNC) {
1188 return;
1189 } else if (synctype == SyncType::HEADER_SYNC) {
1191 return;
1192 }
1193 progressBarLabel->setText(tr("Synchronizing with network…"));
1195 break;
1196 case BlockSource::DISK:
1197 if (synctype != SyncType::BLOCK_SYNC) {
1198 progressBarLabel->setText(tr("Indexing blocks on disk…"));
1199 } else {
1200 progressBarLabel->setText(tr("Processing blocks on disk…"));
1201 }
1202 break;
1203 case BlockSource::NONE:
1204 if (synctype != SyncType::BLOCK_SYNC) {
1205 return;
1206 }
1207 progressBarLabel->setText(tr("Connecting to peers…"));
1208 break;
1209 }
1210
1211 QString tooltip;
1212
1213 QDateTime currentDate = QDateTime::currentDateTime();
1214 qint64 secs = blockDate.secsTo(currentDate);
1215
1216 tooltip = tr("Processed %n block(s) of transaction history.", "", count);
1217
1218 // Set icon state: spinning if catching up, tick otherwise
1219 if (secs < MAX_BLOCK_TIME_GAP) {
1220 tooltip = tr("Up to date") + QString(".<br>") + tooltip;
1221 labelBlocksIcon->setThemedPixmap(QStringLiteral(":/icons/synced"), STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE);
1222
1223#ifdef ENABLE_WALLET
1224 if(walletFrame)
1225 {
1227 modalOverlay->showHide(true, true);
1228 }
1229#endif // ENABLE_WALLET
1230
1231 progressBarLabel->setVisible(false);
1232 progressBar->setVisible(false);
1233 }
1234 else
1235 {
1236 QString timeBehindText = GUIUtil::formatNiceTimeOffset(secs);
1237
1238 progressBarLabel->setVisible(true);
1239 progressBar->setFormat(tr("%1 behind").arg(timeBehindText));
1240 progressBar->setMaximum(1000000000);
1241 progressBar->setValue(nVerificationProgress * 1000000000.0 + 0.5);
1242 progressBar->setVisible(true);
1243
1244 tooltip = tr("Catching up…") + QString("<br>") + tooltip;
1245 if(count != prevBlocks)
1246 {
1248 QString(":/animation/spinner-%1").arg(spinnerFrame, 3, 10, QChar('0')),
1251 }
1252 prevBlocks = count;
1253
1254#ifdef ENABLE_WALLET
1255 if(walletFrame)
1256 {
1259 }
1260#endif // ENABLE_WALLET
1261
1262 tooltip += QString("<br>");
1263 tooltip += tr("Last received block was generated %1 ago.").arg(timeBehindText);
1264 tooltip += QString("<br>");
1265 tooltip += tr("Transactions after this will not yet be visible.");
1266 }
1267
1268 // Don't word-wrap this (fixed-width) tooltip
1269 tooltip = QString("<nobr>") + tooltip + QString("</nobr>");
1270
1271 labelBlocksIcon->setToolTip(tooltip);
1272 progressBarLabel->setToolTip(tooltip);
1273 progressBar->setToolTip(tooltip);
1274}
1275
1277{
1278#ifdef ENABLE_WALLET
1279 auto activity = new CreateWalletActivity(getWalletController(), this);
1280 connect(activity, &CreateWalletActivity::created, this, &BitcoinGUI::setCurrentWallet);
1281 connect(activity, &CreateWalletActivity::created, rpcConsole, &RPCConsole::setCurrentWallet);
1282 activity->create();
1283#endif // ENABLE_WALLET
1284}
1285
1286void BitcoinGUI::message(const QString& title, QString message, unsigned int style, bool* ret, const QString& detailed_message)
1287{
1288 // Default title. On macOS, the window title is ignored (as required by the macOS Guidelines).
1289 QString strTitle{CLIENT_NAME};
1290 // Default to information icon
1291 int nMBoxIcon = QMessageBox::Information;
1292 int nNotifyIcon = Notificator::Information;
1293
1294 QString msgType;
1295 if (!title.isEmpty()) {
1296 msgType = title;
1297 } else {
1298 switch (style) {
1300 msgType = tr("Error");
1301 message = tr("Error: %1").arg(message);
1302 break;
1304 msgType = tr("Warning");
1305 message = tr("Warning: %1").arg(message);
1306 break;
1308 msgType = tr("Information");
1309 // No need to prepend the prefix here.
1310 break;
1311 default:
1312 break;
1313 }
1314 }
1315
1316 if (!msgType.isEmpty()) {
1317 strTitle += " - " + msgType;
1318 }
1319
1320 if (style & CClientUIInterface::ICON_ERROR) {
1321 nMBoxIcon = QMessageBox::Critical;
1322 nNotifyIcon = Notificator::Critical;
1323 } else if (style & CClientUIInterface::ICON_WARNING) {
1324 nMBoxIcon = QMessageBox::Warning;
1325 nNotifyIcon = Notificator::Warning;
1326 }
1327
1328 if (style & CClientUIInterface::MODAL) {
1329 // Check for buttons, use OK as default, if none was supplied
1330 QMessageBox::StandardButton buttons;
1331 if (!(buttons = (QMessageBox::StandardButton)(style & CClientUIInterface::BTN_MASK)))
1332 buttons = QMessageBox::Ok;
1333
1335 QMessageBox mBox(static_cast<QMessageBox::Icon>(nMBoxIcon), strTitle, message, buttons, this);
1336 mBox.setTextFormat(Qt::PlainText);
1337 mBox.setDetailedText(detailed_message);
1338 int r = mBox.exec();
1339 if (ret != nullptr)
1340 *ret = r == QMessageBox::Ok;
1341 } else {
1342 notificator->notify(static_cast<Notificator::Class>(nNotifyIcon), strTitle, message);
1343 }
1344}
1345
1347{
1348 if (e->type() == QEvent::PaletteChange) {
1349 overviewAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/overview")));
1350 sendCoinsAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/send")));
1351 receiveCoinsAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/receiving_addresses")));
1352 historyAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/history")));
1353 }
1354
1355 QMainWindow::changeEvent(e);
1356
1357#ifndef Q_OS_MACOS // Ignored on Mac
1358 if(e->type() == QEvent::WindowStateChange)
1359 {
1361 {
1362 QWindowStateChangeEvent *wsevt = static_cast<QWindowStateChangeEvent*>(e);
1363 if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized())
1364 {
1365 QTimer::singleShot(0, this, &BitcoinGUI::hide);
1366 e->ignore();
1367 }
1368 else if((wsevt->oldState() & Qt::WindowMinimized) && !isMinimized())
1369 {
1370 QTimer::singleShot(0, this, &BitcoinGUI::show);
1371 e->ignore();
1372 }
1373 }
1374 }
1375#endif
1376}
1377
1378void BitcoinGUI::closeEvent(QCloseEvent *event)
1379{
1380#ifndef Q_OS_MACOS // Ignored on Mac
1382 {
1384 {
1385 // close rpcConsole in case it was open to make some space for the shutdown window
1386 rpcConsole->close();
1387
1388 Q_EMIT quitRequested();
1389 }
1390 else
1391 {
1392 QMainWindow::showMinimized();
1393 event->ignore();
1394 }
1395 }
1396#else
1397 QMainWindow::closeEvent(event);
1398#endif
1399}
1400
1401void BitcoinGUI::showEvent(QShowEvent *event)
1402{
1403 // enable the debug window when the main window shows up
1404 openRPCConsoleAction->setEnabled(true);
1405 aboutAction->setEnabled(true);
1406 optionsAction->setEnabled(true);
1407}
1408
1409#ifdef ENABLE_WALLET
1410void BitcoinGUI::incomingTransaction(const QString& date, BitcoinUnit unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName)
1411{
1412 // On new transaction, make an info balloon
1413 QString msg = tr("Date: %1\n").arg(date) +
1414 tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(unit, amount, true));
1415 if (m_node.walletLoader().getWallets().size() > 1 && !walletName.isEmpty()) {
1416 msg += tr("Wallet: %1\n").arg(walletName);
1417 }
1418 msg += tr("Type: %1\n").arg(type);
1419 if (!label.isEmpty())
1420 msg += tr("Label: %1\n").arg(label);
1421 else if (!address.isEmpty())
1422 msg += tr("Address: %1\n").arg(address);
1423 message((amount)<0 ? tr("Sent transaction") : tr("Incoming transaction"),
1425}
1426#endif // ENABLE_WALLET
1427
1428void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
1429{
1430 // Accept only URIs
1431 if(event->mimeData()->hasUrls())
1432 event->acceptProposedAction();
1433}
1434
1435void BitcoinGUI::dropEvent(QDropEvent *event)
1436{
1437 if(event->mimeData()->hasUrls())
1438 {
1439 for (const QUrl &uri : event->mimeData()->urls())
1440 {
1441 Q_EMIT receivedURI(uri.toString());
1442 }
1443 }
1444 event->acceptProposedAction();
1445}
1446
1447bool BitcoinGUI::eventFilter(QObject *object, QEvent *event)
1448{
1449 // Catch status tip events
1450 if (event->type() == QEvent::StatusTip)
1451 {
1452 // Prevent adding text from setStatusTip(), if we currently use the status bar for displaying other stuff
1453 if (progressBarLabel->isVisible() || progressBar->isVisible())
1454 return true;
1455 }
1456 return QMainWindow::eventFilter(object, event);
1457}
1458
1459#ifdef ENABLE_WALLET
1460bool BitcoinGUI::handlePaymentRequest(const SendCoinsRecipient& recipient)
1461{
1462 // URI has to be valid
1463 if (walletFrame && walletFrame->handlePaymentRequest(recipient))
1464 {
1466 gotoSendCoinsPage();
1467 return true;
1468 }
1469 return false;
1470}
1471
1472void BitcoinGUI::setHDStatus(bool privkeyDisabled, int hdEnabled)
1473{
1474 labelWalletHDStatusIcon->setThemedPixmap(privkeyDisabled ? QStringLiteral(":/icons/eye") : hdEnabled ? QStringLiteral(":/icons/hd_enabled") : QStringLiteral(":/icons/hd_disabled"), STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE);
1475 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>"));
1477}
1478
1479void BitcoinGUI::setEncryptionStatus(int status)
1480{
1481 switch(status)
1482 {
1485 encryptWalletAction->setChecked(false);
1486 changePassphraseAction->setEnabled(false);
1487 encryptWalletAction->setEnabled(false);
1488 break;
1491 encryptWalletAction->setChecked(false);
1492 changePassphraseAction->setEnabled(false);
1493 encryptWalletAction->setEnabled(true);
1494 break;
1498 labelWalletEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>unlocked</b>"));
1499 encryptWalletAction->setChecked(true);
1500 changePassphraseAction->setEnabled(true);
1501 encryptWalletAction->setEnabled(false);
1502 break;
1505 labelWalletEncryptionIcon->setThemedPixmap(QStringLiteral(":/icons/lock_closed"), STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE);
1506 labelWalletEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>locked</b>"));
1507 encryptWalletAction->setChecked(true);
1508 changePassphraseAction->setEnabled(true);
1509 encryptWalletAction->setEnabled(false);
1510 break;
1511 }
1512}
1513
1514void BitcoinGUI::updateWalletStatus()
1515{
1517
1518 WalletView * const walletView = walletFrame->currentWalletView();
1519 if (!walletView) {
1520 return;
1521 }
1522 WalletModel * const walletModel = walletView->getWalletModel();
1523 setEncryptionStatus(walletModel->getEncryptionStatus());
1524 setHDStatus(walletModel->wallet().privateKeysDisabled(), walletModel->wallet().hdEnabled());
1525}
1526#endif // ENABLE_WALLET
1527
1529{
1530 std::string ip_port;
1531 bool proxy_enabled = clientModel->getProxyInfo(ip_port);
1532
1533 if (proxy_enabled) {
1535 QString ip_port_q = QString::fromStdString(ip_port);
1537 labelProxyIcon->setToolTip(tr("Proxy is <b>enabled</b>: %1").arg(ip_port_q));
1538 } else {
1539 labelProxyIcon->show();
1540 }
1541 } else {
1542 labelProxyIcon->hide();
1543 }
1544}
1545
1547{
1548 QString window_title = CLIENT_NAME;
1549#ifdef ENABLE_WALLET
1550 if (walletFrame) {
1551 WalletModel* const wallet_model = walletFrame->currentWalletModel();
1552 if (wallet_model && !wallet_model->getWalletName().isEmpty()) {
1553 window_title += " - " + wallet_model->getDisplayName();
1554 }
1555 }
1556#endif
1557 if (!m_network_style->getTitleAddText().isEmpty()) {
1558 window_title += " - " + m_network_style->getTitleAddText();
1559 }
1560 setWindowTitle(window_title);
1561}
1562
1564{
1565 if(!clientModel)
1566 return;
1567
1568 if (!isHidden() && !isMinimized() && !GUIUtil::isObscured(this) && fToggleHidden) {
1569 hide();
1570 } else {
1572 }
1573}
1574
1576{
1578}
1579
1581{
1583 {
1584 if(rpcConsole)
1585 rpcConsole->hide();
1586 Q_EMIT quitRequested();
1587 }
1588}
1589
1590void BitcoinGUI::showProgress(const QString &title, int nProgress)
1591{
1592 if (nProgress == 0) {
1593 progressDialog = new QProgressDialog(title, QString(), 0, 100);
1595 progressDialog->setWindowModality(Qt::ApplicationModal);
1596 progressDialog->setAutoClose(false);
1597 progressDialog->setValue(0);
1598 } else if (nProgress == 100) {
1599 if (progressDialog) {
1600 progressDialog->close();
1601 progressDialog->deleteLater();
1602 progressDialog = nullptr;
1603 }
1604 } else if (progressDialog) {
1605 progressDialog->setValue(nProgress);
1606 }
1607}
1608
1610{
1611 if (modalOverlay && (progressBar->isVisible() || modalOverlay->isLayerVisible()))
1613}
1614
1615[[nodiscard]] static bool ThreadSafeMessageBox(BitcoinGUI* gui, const bilingual_str& message, unsigned int style)
1616{
1617 bool modal = (style & CClientUIInterface::MODAL);
1618 // The SECURE flag has no effect in the Qt GUI.
1619 // bool secure = (style & CClientUIInterface::SECURE);
1620 style &= ~CClientUIInterface::SECURE;
1621 bool ret = false;
1622
1623 QString detailed_message; // This is original message, in English, for googling and referencing.
1624 if (message.original != message.translated) {
1625 detailed_message = BitcoinGUI::tr("Original message:") + "\n" + QString::fromStdString(message.original);
1626 }
1627 // The title is empty for node messages. The fallback title is usually set
1628 // by `style`.
1629 const QString title{};
1630
1631 // In case of modal message, use blocking connection to wait for user to click a button
1632 bool invoked = QMetaObject::invokeMethod(gui, "message",
1633 modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
1634 Q_ARG(QString, title),
1635 Q_ARG(QString, QString::fromStdString(message.translated)),
1636 Q_ARG(unsigned int, style),
1637 Q_ARG(bool*, &ret),
1638 Q_ARG(QString, detailed_message));
1639 assert(invoked);
1640 return ret;
1641}
1642
1644{
1645 // Connect signals to client
1646 m_handler_message_box = m_node.handleMessageBox([this](const bilingual_str& message, unsigned int style) {
1647 (void)ThreadSafeMessageBox(this, message, style);
1648 });
1649 m_handler_question = m_node.handleQuestion([this](const bilingual_str& message, const std::string& /*non_interactive_message*/, unsigned int style) {
1650 return ThreadSafeMessageBox(this, message, style);
1651 });
1652}
1653
1655{
1656 // Disconnect signals from client
1657 m_handler_message_box->disconnect();
1658 m_handler_question->disconnect();
1659}
1660
1662{
1664 return m_mask_values_action->isChecked();
1665}
1666
1668 : m_platform_style{platformStyle}
1669{
1671 setToolTip(tr("Unit to show amounts in. Click to select another unit."));
1672 QList<BitcoinUnit> units = BitcoinUnits::availableUnits();
1673 int max_width = 0;
1674 const QFontMetrics fm(font());
1675 for (const BitcoinUnit unit : units) {
1676 max_width = qMax(max_width, GUIUtil::TextWidth(fm, BitcoinUnits::longName(unit)));
1677 }
1678 setMinimumSize(max_width, 0);
1679 setAlignment(Qt::AlignRight | Qt::AlignVCenter);
1680 setStyleSheet(QString("QLabel { color : %1 }").arg(m_platform_style->SingleColor().name()));
1681}
1682
1685{
1686 onDisplayUnitsClicked(event->pos());
1687}
1688
1690{
1691 if (e->type() == QEvent::PaletteChange) {
1692 QString style = QString("QLabel { color : %1 }").arg(m_platform_style->SingleColor().name());
1693 if (style != styleSheet()) {
1694 setStyleSheet(style);
1695 }
1696 }
1697
1698 QLabel::changeEvent(e);
1699}
1700
1703{
1704 menu = new QMenu(this);
1705 for (const BitcoinUnit u : BitcoinUnits::availableUnits()) {
1706 menu->addAction(BitcoinUnits::longName(u))->setData(QVariant::fromValue(u));
1707 }
1708 connect(menu, &QMenu::triggered, this, &UnitDisplayStatusBarControl::onMenuSelection);
1709}
1710
1713{
1714 if (_optionsModel)
1715 {
1716 this->optionsModel = _optionsModel;
1717
1718 // be aware of a display unit change reported by the OptionsModel object.
1720
1721 // initialize the display units label with the current value in the model.
1722 updateDisplayUnit(_optionsModel->getDisplayUnit());
1723 }
1724}
1725
1728{
1729 setText(BitcoinUnits::longName(newUnits));
1730}
1731
1734{
1735 QPoint globalPos = mapToGlobal(point);
1736 menu->exec(globalPos);
1737}
1738
1741{
1742 if (action)
1743 {
1744 optionsModel->setDisplayUnit(action->data());
1745 }
1746}
1747
1748#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:685
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:990
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:894
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:907
HelpMessageDialog * helpMessageDialog
Definition: bitcoingui.h:179
void aboutClicked()
Show about dialog.
Definition: bitcoingui.cpp:995
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:649
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:875
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:554
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:627
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
constexpr int STATUSBAR_ICONSIZE
Definition: guiconstants.h:23
#define SPINNER_FRAMES
Definition: guiconstants.h:47
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:56
static RPCMethod help()
Definition: server.cpp:123
int64_t nPowTargetSpacing
Definition: params.h:124
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