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