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