Bitcoin Core 29.99.0
P2P Digital Currency
bitcoin.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2022 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <bitcoin-build-config.h> // IWYU pragma: keep
6
7#include <qt/bitcoin.h>
8
9#include <chainparams.h>
10#include <common/args.h>
11#include <common/init.h>
12#include <common/system.h>
13#include <init.h>
14#include <interfaces/handler.h>
15#include <interfaces/init.h>
16#include <interfaces/node.h>
17#include <logging.h>
18#include <node/context.h>
19#include <node/interface_ui.h>
20#include <noui.h>
21#include <qt/bitcoingui.h>
22#include <qt/clientmodel.h>
23#include <qt/guiconstants.h>
24#include <qt/guiutil.h>
25#include <qt/initexecutor.h>
26#include <qt/intro.h>
27#include <qt/networkstyle.h>
28#include <qt/optionsmodel.h>
29#include <qt/platformstyle.h>
30#include <qt/splashscreen.h>
31#include <qt/utilitydialog.h>
33#include <uint256.h>
34#include <util/exception.h>
35#include <util/string.h>
36#include <util/threadnames.h>
37#include <util/translation.h>
38#include <validation.h>
39
40#ifdef ENABLE_WALLET
41#include <qt/paymentserver.h>
42#include <qt/walletcontroller.h>
43#include <qt/walletmodel.h>
44#include <wallet/types.h>
45#endif // ENABLE_WALLET
46
47#include <boost/signals2/connection.hpp>
48#include <chrono>
49#include <memory>
50
51#include <QApplication>
52#include <QDebug>
53#include <QLatin1String>
54#include <QLibraryInfo>
55#include <QLocale>
56#include <QMessageBox>
57#include <QSettings>
58#include <QThread>
59#include <QTimer>
60#include <QTranslator>
61#include <QWindow>
62
63// Declare meta types used for QMetaObject::invokeMethod
64Q_DECLARE_METATYPE(bool*)
65Q_DECLARE_METATYPE(CAmount)
66Q_DECLARE_METATYPE(SynchronizationState)
67Q_DECLARE_METATYPE(SyncType)
68Q_DECLARE_METATYPE(uint256)
69#ifdef ENABLE_WALLET
70Q_DECLARE_METATYPE(wallet::AddressPurpose)
71#endif // ENABLE_WALLET
72
74
75static void RegisterMetaTypes()
76{
77 // Register meta types used for QMetaObject::invokeMethod and Qt::QueuedConnection
78 qRegisterMetaType<bool*>();
79 qRegisterMetaType<SynchronizationState>();
80 qRegisterMetaType<SyncType>();
81 #ifdef ENABLE_WALLET
82 qRegisterMetaType<WalletModel*>();
83 qRegisterMetaType<wallet::AddressPurpose>();
84 #endif // ENABLE_WALLET
85 // Register typedefs (see https://doc.qt.io/qt-5/qmetatype.html#qRegisterMetaType)
86 // IMPORTANT: if CAmount is no longer a typedef use the normal variant above (see https://doc.qt.io/qt-5/qmetatype.html#qRegisterMetaType-1)
87 qRegisterMetaType<CAmount>("CAmount");
88 qRegisterMetaType<size_t>("size_t");
89
90 qRegisterMetaType<std::function<void()>>("std::function<void()>");
91 qRegisterMetaType<QMessageBox::Icon>("QMessageBox::Icon");
92 qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>("interfaces::BlockAndHeaderTipInfo");
93 qRegisterMetaType<BitcoinUnit>("BitcoinUnit");
94}
95
96static QString GetLangTerritory()
97{
98 QSettings settings;
99 // Get desired locale (e.g. "de_DE")
100 // 1) System default language
101 QString lang_territory = QLocale::system().name();
102 // 2) Language from QSettings
103 QString lang_territory_qsettings = settings.value("language", "").toString();
104 if(!lang_territory_qsettings.isEmpty())
105 lang_territory = lang_territory_qsettings;
106 // 3) -lang command line argument
107 lang_territory = QString::fromStdString(gArgs.GetArg("-lang", lang_territory.toStdString()));
108 return lang_territory;
109}
110
112static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTranslator, QTranslator &translatorBase, QTranslator &translator)
113{
114 // Remove old translators
115 QApplication::removeTranslator(&qtTranslatorBase);
116 QApplication::removeTranslator(&qtTranslator);
117 QApplication::removeTranslator(&translatorBase);
118 QApplication::removeTranslator(&translator);
119
120 // Get desired locale (e.g. "de_DE")
121 // 1) System default language
122 QString lang_territory = GetLangTerritory();
123
124 // Convert to "de" only by truncating "_DE"
125 QString lang = lang_territory;
126 lang.truncate(lang_territory.lastIndexOf('_'));
127
128 // Load language files for configured locale:
129 // - First load the translator for the base language, without territory
130 // - Then load the more specific locale translator
131
132 const QString translation_path{QLibraryInfo::path(QLibraryInfo::TranslationsPath)};
133 // Load e.g. qt_de.qm
134 if (qtTranslatorBase.load("qt_" + lang, translation_path)) {
135 QApplication::installTranslator(&qtTranslatorBase);
136 }
137
138 // Load e.g. qt_de_DE.qm
139 if (qtTranslator.load("qt_" + lang_territory, translation_path)) {
140 QApplication::installTranslator(&qtTranslator);
141 }
142
143 // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
144 if (translatorBase.load(lang, ":/translations/")) {
145 QApplication::installTranslator(&translatorBase);
146 }
147
148 // Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
149 if (translator.load(lang_territory, ":/translations/")) {
150 QApplication::installTranslator(&translator);
151 }
152}
153
154static bool ErrorSettingsRead(const bilingual_str& error, const std::vector<std::string>& details)
155{
156 QMessageBox messagebox(QMessageBox::Critical, CLIENT_NAME, QString::fromStdString(strprintf("%s.", error.translated)), QMessageBox::Reset | QMessageBox::Abort);
157 /*: Explanatory text shown on startup when the settings file cannot be read.
158 Prompts user to make a choice between resetting or aborting. */
159 messagebox.setInformativeText(QObject::tr("Do you want to reset settings to default values, or to abort without making changes?"));
160 messagebox.setDetailedText(QString::fromStdString(MakeUnorderedList(details)));
161 messagebox.setTextFormat(Qt::PlainText);
162 messagebox.setDefaultButton(QMessageBox::Reset);
163 switch (messagebox.exec()) {
164 case QMessageBox::Reset:
165 return false;
166 case QMessageBox::Abort:
167 return true;
168 default:
169 assert(false);
170 }
171}
172
173static void ErrorSettingsWrite(const bilingual_str& error, const std::vector<std::string>& details)
174{
175 QMessageBox messagebox(QMessageBox::Critical, CLIENT_NAME, QString::fromStdString(strprintf("%s.", error.translated)), QMessageBox::Ok);
176 /*: Explanatory text shown on startup when the settings file could not be written.
177 Prompts user to check that we have the ability to write to the file.
178 Explains that the user has the option of running without a settings file.*/
179 messagebox.setInformativeText(QObject::tr("A fatal error occurred. Check that settings file is writable, or try running with -nosettings."));
180 messagebox.setDetailedText(QString::fromStdString(MakeUnorderedList(details)));
181 messagebox.setTextFormat(Qt::PlainText);
182 messagebox.setDefaultButton(QMessageBox::Ok);
183 messagebox.exec();
184}
185
186/* qDebug() message handler --> debug.log */
187void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg)
188{
189 Q_UNUSED(context);
190 if (type == QtDebugMsg) {
191 LogDebug(BCLog::QT, "GUI: %s\n", msg.toStdString());
192 } else {
193 LogPrintf("GUI: %s\n", msg.toStdString());
194 }
195}
196
197static int qt_argc = 1;
198static const char* qt_argv = "bitcoin-qt";
199
201 : QApplication(qt_argc, const_cast<char**>(&qt_argv))
202{
203 // Qt runs setlocale(LC_ALL, "") on initialization.
205 setQuitOnLastWindowClosed(false);
206}
207
209{
210 // UI per-platform customization
211 // This must be done inside the BitcoinApplication constructor, or after it, because
212 // PlatformStyle::instantiate requires a QApplication
213 std::string platformName;
214 platformName = gArgs.GetArg("-uiplatform", BitcoinGUI::DEFAULT_UIPLATFORM);
215 platformStyle = PlatformStyle::instantiate(QString::fromStdString(platformName));
216 if (!platformStyle) // Fall back to "other" if specified name not found
219}
220
222{
223 m_executor.reset();
224
225 delete window;
226 window = nullptr;
227 delete platformStyle;
228 platformStyle = nullptr;
229}
230
231#ifdef ENABLE_WALLET
232void BitcoinApplication::createPaymentServer()
233{
234 paymentServer = new PaymentServer(this);
235}
236#endif
237
239{
240 optionsModel = new OptionsModel(node(), this);
241 if (resetSettings) {
243 }
244 bilingual_str error;
245 if (!optionsModel->Init(error)) {
246 fs::path settings_path;
247 if (gArgs.GetSettingsPath(&settings_path)) {
248 error += Untranslated("\n");
249 std::string quoted_path = strprintf("%s", fs::quoted(fs::PathToString(settings_path)));
250 error.original += strprintf("Settings file %s might be corrupt or invalid.", quoted_path);
251 error.translated += tr("Settings file %1 might be corrupt or invalid.").arg(QString::fromStdString(quoted_path)).toStdString();
252 }
253 InitError(error);
254 QMessageBox::critical(nullptr, CLIENT_NAME, QString::fromStdString(error.translated));
255 return false;
256 }
257 return true;
258}
259
261{
262 window = new BitcoinGUI(node(), platformStyle, networkStyle, nullptr);
264
265 pollShutdownTimer = new QTimer(window);
266 connect(pollShutdownTimer, &QTimer::timeout, [this]{
267 if (!QApplication::activeModalWidget()) {
269 }
270 });
271}
272
274{
276 m_splash = new SplashScreen(networkStyle);
277 m_splash->show();
278}
279
281{
282 assert(!m_node);
283 m_node = init.makeNode();
285}
286
288{
289 return node().baseInitialize();
290}
291
293{
295 m_executor.emplace(node());
296
297 /* communication to and from thread */
299 connect(&m_executor.value(), &InitExecutor::shutdownResult, this, [] {
300 QCoreApplication::exit(0);
301 });
305}
306
308{
309 // Default printtoconsole to false for the GUI. GUI programs should not
310 // print to the console unnecessarily.
311 gArgs.SoftSetBoolArg("-printtoconsole", false);
312
315}
316
318{
320}
321
323{
324 qDebug() << __func__ << ": Requesting initialize";
325 startThread();
326 Q_EMIT requestedInitialize();
327}
328
330{
331 for (const auto w : QGuiApplication::topLevelWindows()) {
332 w->hide();
333 }
334
335 delete m_splash;
336 m_splash = nullptr;
337
338 // Show a simple window indicating shutdown status
339 // Do this first as some of the steps may take some time below,
340 // for example the RPC console may still be executing a command.
342
343 qDebug() << __func__ << ": Requesting shutdown";
344
345 // Must disconnect node signals otherwise current thread can deadlock since
346 // no event loop is running.
348 // Request node shutdown, which can interrupt long operations, like
349 // rescanning a wallet.
351 // Prior to unsetting the client model, stop listening backend signals
352 if (clientModel) {
353 clientModel->stop();
354 }
355
356 // Unsetting the client model can cause the current thread to wait for node
357 // to complete an operation, like wait for a RPC execution to complete.
358 window->setClientModel(nullptr);
359 pollShutdownTimer->stop();
360
361#ifdef ENABLE_WALLET
362 // Delete wallet controller here manually, instead of relying on Qt object
363 // tracking (https://doc.qt.io/qt-5/objecttrees.html). This makes sure
364 // walletmodel m_handle_* notification handlers are deleted before wallets
365 // are unloaded, which can simplify wallet implementations. It also avoids
366 // these notifications having to be handled while GUI objects are being
367 // destroyed, making GUI code less fragile as well.
368 delete m_wallet_controller;
369 m_wallet_controller = nullptr;
370#endif // ENABLE_WALLET
371
372 delete clientModel;
373 clientModel = nullptr;
374
375 // Request shutdown from core thread
376 Q_EMIT requestedShutdown();
377}
378
380{
381 qDebug() << __func__ << ": Initialization result: " << success;
382
383 if (success) {
384 delete m_splash;
385 m_splash = nullptr;
386
387 // Log this only after AppInitMain finishes, as then logging setup is guaranteed complete
388 qInfo() << "Platform customization:" << platformStyle->getName();
390 window->setClientModel(clientModel, &tip_info);
391
392 // If '-min' option passed, start window minimized (iconified) or minimized to tray
393 bool start_minimized = gArgs.GetBoolArg("-min", false);
394#ifdef ENABLE_WALLET
396 m_wallet_controller = new WalletController(*clientModel, platformStyle, this);
397 window->setWalletController(m_wallet_controller, /*show_loading_minimized=*/start_minimized);
398 if (paymentServer) {
399 paymentServer->setOptionsModel(optionsModel);
400 }
401 }
402#endif // ENABLE_WALLET
403
404 // Show or minimize window
405 if (!start_minimized) {
406 window->show();
408 // do nothing as the window is managed by the tray icon
409 } else {
410 window->showMinimized();
411 }
412 Q_EMIT windowShown(window);
413
414#ifdef ENABLE_WALLET
415 // Now that initialization/startup is done, process any command-line
416 // bitcoin: URIs or payment requests:
417 if (paymentServer) {
418 connect(paymentServer, &PaymentServer::receivedPaymentRequest, window, &BitcoinGUI::handlePaymentRequest);
420 connect(paymentServer, &PaymentServer::message, [this](const QString& title, const QString& message, unsigned int style) {
421 window->message(title, message, style);
422 });
423 QTimer::singleShot(100ms, paymentServer, &PaymentServer::uiReady);
424 }
425#endif
427 } else {
429 }
430}
431
433{
434 QMessageBox::critical(
435 nullptr, tr("Runaway exception"),
436 tr("A fatal error occurred. %1 can no longer continue safely and will quit.").arg(CLIENT_NAME) +
437 QLatin1String("<br><br>") + GUIUtil::MakeHtmlLink(message, CLIENT_BUGREPORT));
438 ::exit(EXIT_FAILURE);
439}
440
442{
443 assert(QThread::currentThread() == thread());
444 QMessageBox::warning(
445 nullptr, tr("Internal error"),
446 tr("An internal error occurred. %1 will attempt to continue safely. This is "
447 "an unexpected bug which can be reported as described below.").arg(CLIENT_NAME) +
448 QLatin1String("<br><br>") + GUIUtil::MakeHtmlLink(message, CLIENT_BUGREPORT));
449}
450
452{
453 if (!window)
454 return 0;
455
456 return window->winId();
457}
458
460{
461 if (e->type() == QEvent::Quit) {
463 return true;
464 }
465
466 return QApplication::event(e);
467}
468
469static void SetupUIArgs(ArgsManager& argsman)
470{
471 argsman.AddArg("-choosedatadir", strprintf("Choose data directory on startup (default: %u)", DEFAULT_CHOOSE_DATADIR), ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
472 argsman.AddArg("-lang=<lang>", "Set language, for example \"de_DE\" (default: system locale)", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
473 argsman.AddArg("-min", "Start minimized", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
474 argsman.AddArg("-resetguisettings", "Reset all settings changed in the GUI", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
475 argsman.AddArg("-splash", strprintf("Show splash screen on startup (default: %u)", DEFAULT_SPLASHSCREEN), ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
476 argsman.AddArg("-uiplatform", strprintf("Select platform to customize UI for (one of windows, macosx, other; default: %s)", BitcoinGUI::DEFAULT_UIPLATFORM), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::GUI);
477}
478
479int GuiMain(int argc, char* argv[])
480{
481#ifdef WIN32
482 common::WinCmdLineArgs winArgs;
483 std::tie(argc, argv) = winArgs.get();
484#endif
485
486 std::unique_ptr<interfaces::Init> init = interfaces::MakeGuiInit(argc, argv);
487
490
491 // Subscribe to global signals from core
492 boost::signals2::scoped_connection handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(noui_ThreadSafeMessageBox);
493 boost::signals2::scoped_connection handler_question = ::uiInterface.ThreadSafeQuestion_connect(noui_ThreadSafeQuestion);
494 boost::signals2::scoped_connection handler_init_message = ::uiInterface.InitMessage_connect(noui_InitMessage);
495
496 // Do not refer to data directory yet, this can be overridden by Intro::pickDataDirectory
497
499 Q_INIT_RESOURCE(bitcoin);
500 Q_INIT_RESOURCE(bitcoin_locale);
501
502#if defined(QT_QPA_PLATFORM_ANDROID)
503 QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
504 QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
505 QApplication::setAttribute(Qt::AA_DontUseNativeDialogs);
506#endif
507
509 GUIUtil::LoadFont(QStringLiteral(":/fonts/monospace"));
510
512 // Command-line options take precedence:
513 SetupServerArgs(gArgs, init->canListenIpc());
515 std::string error;
516 if (!gArgs.ParseParameters(argc, argv, error)) {
517 InitError(Untranslated(strprintf("Error parsing command line arguments: %s", error)));
518 // Create a message box, because the gui has neither been created nor has subscribed to core signals
519 QMessageBox::critical(nullptr, CLIENT_NAME,
520 // message cannot be translated because translations have not been initialized
521 QString::fromStdString("Error parsing command line arguments: %1.").arg(QString::fromStdString(error)));
522 return EXIT_FAILURE;
523 }
524
525 // Error out when loose non-argument tokens are encountered on command line
526 // However, allow BIP-21 URIs only if no options follow
527 bool payment_server_token_seen = false;
528 for (int i = 1; i < argc; i++) {
529 QString arg(argv[i]);
530 bool invalid_token = !arg.startsWith("-");
531#ifdef ENABLE_WALLET
532 if (arg.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) {
533 invalid_token &= false;
534 payment_server_token_seen = true;
535 }
536#endif
537 if (payment_server_token_seen && arg.startsWith("-")) {
538 InitError(Untranslated(strprintf("Options ('%s') cannot follow a BIP-21 payment URI", argv[i])));
539 QMessageBox::critical(nullptr, CLIENT_NAME,
540 // message cannot be translated because translations have not been initialized
541 QString::fromStdString("Options ('%1') cannot follow a BIP-21 payment URI").arg(QString::fromStdString(argv[i])));
542 return EXIT_FAILURE;
543 }
544 if (invalid_token) {
545 InitError(Untranslated(strprintf("Command line contains unexpected token '%s', see bitcoin-qt -h for a list of options.", argv[i])));
546 QMessageBox::critical(nullptr, CLIENT_NAME,
547 // message cannot be translated because translations have not been initialized
548 QString::fromStdString("Command line contains unexpected token '%1', see bitcoin-qt -h for a list of options.").arg(QString::fromStdString(argv[i])));
549 return EXIT_FAILURE;
550 }
551 }
552
553 // Now that the QApplication is setup and we have parsed our parameters, we can set the platform style
554 app.setupPlatformStyle();
555
557 // must be set before OptionsModel is initialized or translations are loaded,
558 // as it is used to locate QSettings
559 QApplication::setOrganizationName(QAPP_ORG_NAME);
560 QApplication::setOrganizationDomain(QAPP_ORG_DOMAIN);
561 QApplication::setApplicationName(QAPP_APP_NAME_DEFAULT);
562
564 // Now that QSettings are accessible, initialize translations
565 QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
566 initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);
567
568 // Show help message immediately after parsing command-line options (for "-lang") and setting locale,
569 // but before showing splash screen.
570 if (HelpRequested(gArgs) || gArgs.GetBoolArg("-version", false)) {
571 HelpMessageDialog help(nullptr, gArgs.GetBoolArg("-version", false));
572 help.showOrPrint();
573 return EXIT_SUCCESS;
574 }
575
576 // Install global event filter that makes sure that long tooltips can be word-wrapped
577 app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
578
580 // User language is set up: pick a data directory
581 bool did_show_intro = false;
582 int64_t prune_MiB = 0; // Intro dialog prune configuration
583 // Gracefully exit if the user cancels
584 if (!Intro::showIfNeeded(did_show_intro, prune_MiB)) return EXIT_SUCCESS;
585
588 // - Do not call gArgs.GetDataDirNet() before this step finishes
589 // - Do not call Params() before this step
590 // - QSettings() will use the new application name after this, resulting in network-specific settings
591 // - Needs to be done before createOptionsModel
592 if (auto error = common::InitConfig(gArgs, ErrorSettingsRead)) {
593 InitError(error->message, error->details);
594 if (error->status == common::ConfigStatus::FAILED_WRITE) {
595 // Show a custom error message to provide more information in the
596 // case of a datadir write error.
597 ErrorSettingsWrite(error->message, error->details);
598 } else if (error->status != common::ConfigStatus::ABORTED) {
599 // Show a generic message in other cases, and no additional error
600 // message in the case of a read error if the user decided to abort.
601 QMessageBox::critical(nullptr, CLIENT_NAME, QObject::tr("Error: %1").arg(QString::fromStdString(error->message.translated)));
602 }
603 return EXIT_FAILURE;
604 }
605#ifdef ENABLE_WALLET
606 // Parse URIs on command line
608#endif
609
610 QScopedPointer<const NetworkStyle> networkStyle(NetworkStyle::instantiate(Params().GetChainType()));
611 assert(!networkStyle.isNull());
612 // Allow for separate UI settings for testnets
613 QApplication::setApplicationName(networkStyle->getAppName());
614 // Re-initialize translations after changing application name (language in network-specific settings can be different)
615 initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);
616
617#ifdef ENABLE_WALLET
619 // - Do this early as we don't want to bother initializing if we are just calling IPC
620 // - Do this *after* setting up the data directory, as the data directory hash is used in the name
621 // of the server.
622 // - Do this after creating app and setting up translations, so errors are
623 // translated properly.
625 exit(EXIT_SUCCESS);
626
627 // Start up the payment server early, too, so impatient users that click on
628 // bitcoin: links repeatedly have their payment requests routed to this process:
630 app.createPaymentServer();
631 }
632#endif // ENABLE_WALLET
633
635 // Install global event filter that makes sure that out-of-focus labels do not contain text cursor.
636 app.installEventFilter(new GUIUtil::LabelOutOfFocusEventFilter(&app));
637#if defined(Q_OS_WIN)
638 // Install global event filter for processing Windows session related Windows messages (WM_QUERYENDSESSION and WM_ENDSESSION)
639 // Note: it is safe to call app.node() in the lambda below despite the fact
640 // that app.createNode() hasn't been called yet, because native events will
641 // not be processed until the Qt event loop is executed.
642 qApp->installNativeEventFilter(new WinShutdownMonitor([&app] { app.node().startShutdown(); }));
643#endif
644 // Install qDebug() message handler to route to debug.log
645 qInstallMessageHandler(DebugMessageHandler);
646 // Allow parameter interaction before we create the options model
647 app.parameterSetup();
649
650 if (gArgs.GetBoolArg("-splash", DEFAULT_SPLASHSCREEN) && !gArgs.GetBoolArg("-min", false))
651 app.createSplashScreen(networkStyle.data());
652
653 app.createNode(*init);
654
655 // Load GUI settings from QSettings
656 if (!app.createOptionsModel(gArgs.GetBoolArg("-resetguisettings", false))) {
657 return EXIT_FAILURE;
658 }
659
660 if (did_show_intro) {
661 // Store intro dialog settings other than datadir (network specific)
662 app.InitPruneSetting(prune_MiB);
663 }
664
665 try
666 {
667 app.createWindow(networkStyle.data());
668 // Perform base initialization before spinning up initialization/shutdown thread
669 // This is acceptable because this function only contains steps that are quick to execute,
670 // so the GUI thread won't be held up.
671 if (app.baseInitialize()) {
672 app.requestInitialize();
673#if defined(Q_OS_WIN)
674 WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely…").arg(CLIENT_NAME), (HWND)app.getMainWinId());
675#endif
676 app.exec();
677 } else {
678 // A dialog with detailed error will have been shown by InitError()
679 return EXIT_FAILURE;
680 }
681 } catch (const std::exception& e) {
682 PrintExceptionContinue(&e, "Runaway exception");
683 app.handleRunawayException(QString::fromStdString(app.node().getWarnings().translated));
684 } catch (...) {
685 PrintExceptionContinue(nullptr, "Runaway exception");
686 app.handleRunawayException(QString::fromStdString(app.node().getWarnings().translated));
687 }
688 return app.node().getExitStatus();
689}
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
bool HelpRequested(const ArgsManager &args)
Definition: args.cpp:684
ArgsManager gArgs
Definition: args.cpp:42
SetupEnvironment()
Definition: system.cpp:59
return EXIT_SUCCESS
static bool ErrorSettingsRead(const bilingual_str &error, const std::vector< std::string > &details)
Definition: bitcoin.cpp:154
static void RegisterMetaTypes()
Definition: bitcoin.cpp:75
static int qt_argc
Definition: bitcoin.cpp:197
static QString GetLangTerritory()
Definition: bitcoin.cpp:96
int GuiMain(int argc, char *argv[])
Definition: bitcoin.cpp:479
static void ErrorSettingsWrite(const bilingual_str &error, const std::vector< std::string > &details)
Definition: bitcoin.cpp:173
static void SetupUIArgs(ArgsManager &argsman)
Definition: bitcoin.cpp:469
static const char * qt_argv
Definition: bitcoin.cpp:198
static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTranslator, QTranslator &translatorBase, QTranslator &translator)
Set up translations.
Definition: bitcoin.cpp:112
void DebugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
Definition: bitcoin.cpp:187
const CChainParams & Params()
Return the currently selected parameters.
@ ALLOW_ANY
disable validation
Definition: args.h:106
@ DEBUG_ONLY
Definition: args.h:114
bool ParseParameters(int argc, const char *const argv[], std::string &error)
Definition: args.cpp:179
bool GetSettingsPath(fs::path *filepath=nullptr, bool temp=false, bool backup=false) const
Get settings file path, or return false if read-write settings were disabled with -nosettings.
Definition: args.cpp:376
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: args.cpp:457
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
Definition: args.cpp:538
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: args.cpp:507
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
Definition: args.cpp:564
Main Bitcoin application object.
Definition: bitcoin.h:35
bool createOptionsModel(bool resetSettings)
Create options model.
Definition: bitcoin.cpp:238
std::optional< InitExecutor > m_executor
Definition: bitcoin.h:93
void requestedInitialize()
ClientModel * clientModel
Definition: bitcoin.h:95
void InitPruneSetting(int64_t prune_MiB)
Initialize prune setting.
Definition: bitcoin.cpp:317
void createSplashScreen(const NetworkStyle *networkStyle)
Create splash screen.
Definition: bitcoin.cpp:273
void requestShutdown()
Request core shutdown.
Definition: bitcoin.cpp:329
SplashScreen * m_splash
Definition: bitcoin.h:104
void windowShown(BitcoinGUI *window)
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info)
Definition: bitcoin.cpp:379
interfaces::Node & node() const
Definition: bitcoin.h:69
void createNode(interfaces::Init &init)
Create or spawn node.
Definition: bitcoin.cpp:280
QTimer * pollShutdownTimer
Definition: bitcoin.h:97
BitcoinGUI * window
Definition: bitcoin.h:96
const PlatformStyle * platformStyle
Definition: bitcoin.h:102
bool baseInitialize()
Basic initialization, before starting initialization/shutdown thread. Return true on success.
Definition: bitcoin.cpp:287
void createWindow(const NetworkStyle *networkStyle)
Create main window.
Definition: bitcoin.cpp:260
void parameterSetup()
parameter interaction/setup based on rules
Definition: bitcoin.cpp:307
void handleRunawayException(const QString &message)
Handle runaway exceptions. Shows a message box with the problem and quits the program.
Definition: bitcoin.cpp:432
OptionsModel * optionsModel
Definition: bitcoin.h:94
bool event(QEvent *e) override
Definition: bitcoin.cpp:459
void setupPlatformStyle()
Setup platform style.
Definition: bitcoin.cpp:208
std::unique_ptr< interfaces::Node > m_node
Definition: bitcoin.h:105
std::unique_ptr< QWidget > shutdownWindow
Definition: bitcoin.h:103
void requestInitialize()
Request core initialization.
Definition: bitcoin.cpp:322
WId getMainWinId() const
Get window identifier of QMainWindow (BitcoinGUI)
Definition: bitcoin.cpp:451
void handleNonFatalException(const QString &message)
A helper function that shows a message box with details about a non-fatal exception.
Definition: bitcoin.cpp:441
Bitcoin GUI main class.
Definition: bitcoingui.h:68
static const std::string DEFAULT_UIPLATFORM
Definition: bitcoingui.h:72
void setClientModel(ClientModel *clientModel=nullptr, interfaces::BlockAndHeaderTipInfo *tip_info=nullptr)
Set the client model.
Definition: bitcoingui.cpp:624
void receivedURI(const QString &uri)
Signal raised when a URI was entered or dragged to the GUI.
void unsubscribeFromCoreSignals()
Disconnect core signals from GUI client.
bool hasTrayIcon() const
Get the tray icon status.
Definition: bitcoingui.h:100
void detectShutdown()
called by a timer to check if shutdown has been requested
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 quitRequested()
Model for Bitcoin network client.
Definition: clientmodel.h:57
OptionsModel * getOptionsModel()
Qt event filter that intercepts QEvent::FocusOut events for QLabel objects, and resets their ‘textInt...
Definition: guiutil.h:208
Qt event filter that intercepts ToolTipChange events, and replaces the tooltip with a rich text repre...
Definition: guiutil.h:188
"Help message" dialog box
Definition: utilitydialog.h:21
void initialize()
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info)
void runawayException(const QString &message)
void shutdownResult()
static bool showIfNeeded(bool &did_show_intro, int64_t &prune_MiB)
Determine data directory.
Definition: intro.cpp:205
static const NetworkStyle * instantiate(const ChainType networkId)
Get style associated with provided network id, or 0 if not known.
Interface from Qt to configuration data structure for Bitcoin client.
Definition: optionsmodel.h:43
void SetPruneTargetGB(int prune_target_gb)
bool Init(bilingual_str &error)
bool getMinimizeToTray() const
Definition: optionsmodel.h:101
static bool ipcSendCommandLine()
void message(const QString &title, const QString &message, unsigned int style)
static void ipcParseCommandLine(int argc, char *argv[])
void receivedPaymentRequest(SendCoinsRecipient)
void handleURIOrFile(const QString &s)
const QString & getName() const
Definition: platformstyle.h:19
static const PlatformStyle * instantiate(const QString &platformId)
Get style associated with provided platform name, or 0 if not known.
static QWidget * showShutdownWindow(QMainWindow *window)
Class for the splashscreen with information of the running client.
Definition: splashscreen.h:27
void setNode(interfaces::Node &node)
Controller between interfaces::Node, WalletModel instances and the GUI.
static bool isWalletEnabled()
Initial interface created when a process is first started, and used to give and get access to other i...
Definition: init.h:31
virtual bool baseInitialize()=0
Initialize app dependencies.
virtual bilingual_str getWarnings()=0
Get warnings.
virtual void startShutdown()=0
Start shutdown.
virtual int getExitStatus()=0
Get exit status.
256-bit opaque blob.
Definition: uint256.h:196
SyncType
Definition: clientmodel.h:42
void PrintExceptionContinue(const std::exception *pex, std::string_view thread_name)
Definition: exception.cpp:36
static auto quoted(const std::string &s)
Definition: fs.h:95
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:151
static constexpr auto SHUTDOWN_POLLING_DELAY
Definition: guiconstants.h:17
static const int TOOLTIP_WRAP_THRESHOLD
Definition: guiconstants.h:44
#define QAPP_ORG_NAME
Definition: guiconstants.h:49
static const bool DEFAULT_SPLASHSCREEN
Definition: guiconstants.h:25
#define QAPP_APP_NAME_DEFAULT
Definition: guiconstants.h:51
#define QAPP_ORG_DOMAIN
Definition: guiconstants.h:50
void InitLogging(const ArgsManager &args)
Initialize global loggers.
Definition: init.cpp:831
void InitParameterInteraction(ArgsManager &args)
Parameter interaction: change current parameters depending on various rules.
Definition: init.cpp:716
void SetupServerArgs(ArgsManager &argsman, bool can_listen_ipc)
Register all arguments with the ArgsManager.
Definition: init.cpp:444
CClientUIInterface uiInterface
bool InitError(const bilingual_str &str)
Show error message.
static const bool DEFAULT_CHOOSE_DATADIR
Definition: intro.h:12
#define LogDebug(category,...)
Definition: logging.h:280
#define LogPrintf(...)
Definition: logging.h:266
@ QT
Definition: logging.h:62
QString MakeHtmlLink(const QString &source, const QString &link)
Replaces a plain text link with an HTML tagged one.
Definition: guiutil.cpp:965
void LogQtInfo()
Writes to debug.log short info about the used Qt and the host system.
Definition: guiutil.cpp:920
void LoadFont(const QString &file_name)
Loads the font from the file specified by file_name, aborts if it fails.
Definition: guiutil.cpp:291
@ ABORTED
Aborted by user.
@ FAILED_WRITE
Failed to write settings.json.
std::optional< ConfigError > InitConfig(ArgsManager &args, SettingsAbortFn settings_abort_fn)
Definition: init.cpp:18
std::unique_ptr< Init > MakeGuiInit(int argc, char *argv[])
Return implementation of Init interface for the gui process.
Definition: bitcoin-gui.cpp:49
std::string MakeUnorderedList(const std::vector< std::string > &items)
Create an unordered multi-line list of items.
Definition: string.h:213
void ThreadSetInternalName(const std::string &)
Set the internal (in-memory) name of the current thread only.
Definition: threadnames.cpp:63
AddressPurpose
Address purpose field that has been been stored with wallet sending and receiving addresses since BIP...
Definition: types.h:61
bool noui_ThreadSafeQuestion(const bilingual_str &, const std::string &message, const std::string &caption, unsigned int style)
Non-GUI handler, which logs and prints questions.
Definition: noui.cpp:50
void noui_InitMessage(const std::string &message)
Non-GUI handler, which only logs a message.
Definition: noui.cpp:55
bool noui_ThreadSafeMessageBox(const bilingual_str &message, const std::string &caption, unsigned int style)
Non-GUI handler, which logs and prints messages.
Definition: noui.cpp:22
static int PruneMiBtoGB(int64_t mib)
Convert configured prune target MiB to displayed GB.
Definition: optionsmodel.h:29
QT_END_NAMESPACE const QString BITCOIN_IPC_PREFIX
static RPCHelpMan help()
Definition: server.cpp:127
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
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:82
assert(!tx.IsCoinBase())
SynchronizationState
Current sync state passed to tip changed callbacks.
Definition: validation.h:85
is a home for public enum and struct type definitions that are used by internally by wallet code,...