You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bitcoin.cpp 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. // Copyright (c) 2011-2014 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. #if defined(HAVE_CONFIG_H)
  5. #include "config/bitcoin-config.h"
  6. #endif
  7. #include "bitcoingui.h"
  8. #include "chainparams.h"
  9. #include "clientmodel.h"
  10. #include "guiconstants.h"
  11. #include "guiutil.h"
  12. #include "intro.h"
  13. #include "networkstyle.h"
  14. #include "optionsmodel.h"
  15. #include "platformstyle.h"
  16. #include "splashscreen.h"
  17. #include "utilitydialog.h"
  18. #include "winshutdownmonitor.h"
  19. #ifdef ENABLE_WALLET
  20. #include "paymentserver.h"
  21. #include "walletmodel.h"
  22. #endif
  23. #include "init.h"
  24. #include "rpcserver.h"
  25. #include "scheduler.h"
  26. #include "ui_interface.h"
  27. #include "util.h"
  28. #ifdef ENABLE_WALLET
  29. #include "wallet/wallet.h"
  30. #endif
  31. #include <stdint.h>
  32. #include <boost/filesystem/operations.hpp>
  33. #include <boost/thread.hpp>
  34. #include <QApplication>
  35. #include <QDebug>
  36. #include <QLibraryInfo>
  37. #include <QLocale>
  38. #include <QMessageBox>
  39. #include <QSettings>
  40. #include <QThread>
  41. #include <QTimer>
  42. #include <QTranslator>
  43. #include <QSslConfiguration>
  44. #if defined(QT_STATICPLUGIN)
  45. #include <QtPlugin>
  46. #if QT_VERSION < 0x050000
  47. Q_IMPORT_PLUGIN(qcncodecs)
  48. Q_IMPORT_PLUGIN(qjpcodecs)
  49. Q_IMPORT_PLUGIN(qtwcodecs)
  50. Q_IMPORT_PLUGIN(qkrcodecs)
  51. Q_IMPORT_PLUGIN(qtaccessiblewidgets)
  52. #else
  53. #if QT_VERSION < 0x050400
  54. Q_IMPORT_PLUGIN(AccessibleFactory)
  55. #endif
  56. #if defined(QT_QPA_PLATFORM_XCB)
  57. Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
  58. #elif defined(QT_QPA_PLATFORM_WINDOWS)
  59. Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
  60. #elif defined(QT_QPA_PLATFORM_COCOA)
  61. Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
  62. #endif
  63. #endif
  64. #endif
  65. #if QT_VERSION < 0x050000
  66. #include <QTextCodec>
  67. #endif
  68. // Declare meta types used for QMetaObject::invokeMethod
  69. Q_DECLARE_METATYPE(bool*)
  70. Q_DECLARE_METATYPE(CAmount)
  71. static void InitMessage(const std::string &message)
  72. {
  73. LogPrintf("init message: %s\n", message);
  74. }
  75. /*
  76. Translate string to current locale using Qt.
  77. */
  78. static std::string Translate(const char* psz)
  79. {
  80. return QCoreApplication::translate("bitcoin-core", psz).toStdString();
  81. }
  82. static QString GetLangTerritory()
  83. {
  84. QSettings settings;
  85. // Get desired locale (e.g. "de_DE")
  86. // 1) System default language
  87. QString lang_territory = QLocale::system().name();
  88. // 2) Language from QSettings
  89. QString lang_territory_qsettings = settings.value("language", "").toString();
  90. if(!lang_territory_qsettings.isEmpty())
  91. lang_territory = lang_territory_qsettings;
  92. // 3) -lang command line argument
  93. lang_territory = QString::fromStdString(GetArg("-lang", lang_territory.toStdString()));
  94. return lang_territory;
  95. }
  96. /** Set up translations */
  97. static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTranslator, QTranslator &translatorBase, QTranslator &translator)
  98. {
  99. // Remove old translators
  100. QApplication::removeTranslator(&qtTranslatorBase);
  101. QApplication::removeTranslator(&qtTranslator);
  102. QApplication::removeTranslator(&translatorBase);
  103. QApplication::removeTranslator(&translator);
  104. // Get desired locale (e.g. "de_DE")
  105. // 1) System default language
  106. QString lang_territory = GetLangTerritory();
  107. // Convert to "de" only by truncating "_DE"
  108. QString lang = lang_territory;
  109. lang.truncate(lang_territory.lastIndexOf('_'));
  110. // Load language files for configured locale:
  111. // - First load the translator for the base language, without territory
  112. // - Then load the more specific locale translator
  113. // Load e.g. qt_de.qm
  114. if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
  115. QApplication::installTranslator(&qtTranslatorBase);
  116. // Load e.g. qt_de_DE.qm
  117. if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
  118. QApplication::installTranslator(&qtTranslator);
  119. // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
  120. if (translatorBase.load(lang, ":/translations/"))
  121. QApplication::installTranslator(&translatorBase);
  122. // Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
  123. if (translator.load(lang_territory, ":/translations/"))
  124. QApplication::installTranslator(&translator);
  125. }
  126. /* qDebug() message handler --> debug.log */
  127. #if QT_VERSION < 0x050000
  128. void DebugMessageHandler(QtMsgType type, const char *msg)
  129. {
  130. const char *category = (type == QtDebugMsg) ? "qt" : NULL;
  131. LogPrint(category, "GUI: %s\n", msg);
  132. }
  133. #else
  134. void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg)
  135. {
  136. Q_UNUSED(context);
  137. const char *category = (type == QtDebugMsg) ? "qt" : NULL;
  138. LogPrint(category, "GUI: %s\n", msg.toStdString());
  139. }
  140. #endif
  141. /** Class encapsulating Bitcoin Core startup and shutdown.
  142. * Allows running startup and shutdown in a different thread from the UI thread.
  143. */
  144. class BitcoinCore: public QObject
  145. {
  146. Q_OBJECT
  147. public:
  148. explicit BitcoinCore();
  149. public Q_SLOTS:
  150. void initialize();
  151. void shutdown();
  152. Q_SIGNALS:
  153. void initializeResult(int retval);
  154. void shutdownResult(int retval);
  155. void runawayException(const QString &message);
  156. private:
  157. boost::thread_group threadGroup;
  158. CScheduler scheduler;
  159. /// Pass fatal exception message to UI thread
  160. void handleRunawayException(const std::exception *e);
  161. };
  162. /** Main Bitcoin application object */
  163. class BitcoinApplication: public QApplication
  164. {
  165. Q_OBJECT
  166. public:
  167. explicit BitcoinApplication(int &argc, char **argv);
  168. ~BitcoinApplication();
  169. #ifdef ENABLE_WALLET
  170. /// Create payment server
  171. void createPaymentServer();
  172. #endif
  173. /// Create options model
  174. void createOptionsModel();
  175. /// Create main window
  176. void createWindow(const NetworkStyle *networkStyle);
  177. /// Create splash screen
  178. void createSplashScreen(const NetworkStyle *networkStyle);
  179. /// Request core initialization
  180. void requestInitialize();
  181. /// Request core shutdown
  182. void requestShutdown();
  183. /// Get process return value
  184. int getReturnValue() { return returnValue; }
  185. /// Get window identifier of QMainWindow (BitcoinGUI)
  186. WId getMainWinId() const;
  187. public Q_SLOTS:
  188. void initializeResult(int retval);
  189. void shutdownResult(int retval);
  190. /// Handle runaway exceptions. Shows a message box with the problem and quits the program.
  191. void handleRunawayException(const QString &message);
  192. Q_SIGNALS:
  193. void requestedInitialize();
  194. void requestedShutdown();
  195. void stopThread();
  196. void splashFinished(QWidget *window);
  197. private:
  198. QThread *coreThread;
  199. OptionsModel *optionsModel;
  200. ClientModel *clientModel;
  201. BitcoinGUI *window;
  202. QTimer *pollShutdownTimer;
  203. #ifdef ENABLE_WALLET
  204. PaymentServer* paymentServer;
  205. WalletModel *walletModel;
  206. #endif
  207. int returnValue;
  208. const PlatformStyle *platformStyle;
  209. void startThread();
  210. };
  211. #include "bitcoin.moc"
  212. BitcoinCore::BitcoinCore():
  213. QObject()
  214. {
  215. }
  216. void BitcoinCore::handleRunawayException(const std::exception *e)
  217. {
  218. PrintExceptionContinue(e, "Runaway exception");
  219. Q_EMIT runawayException(QString::fromStdString(strMiscWarning));
  220. }
  221. void BitcoinCore::initialize()
  222. {
  223. try
  224. {
  225. qDebug() << __func__ << ": Running AppInit2 in thread";
  226. int rv = AppInit2(threadGroup, scheduler);
  227. Q_EMIT initializeResult(rv);
  228. } catch (const std::exception& e) {
  229. handleRunawayException(&e);
  230. } catch (...) {
  231. handleRunawayException(NULL);
  232. }
  233. }
  234. void BitcoinCore::shutdown()
  235. {
  236. try
  237. {
  238. qDebug() << __func__ << ": Running Shutdown in thread";
  239. Interrupt(threadGroup);
  240. threadGroup.join_all();
  241. Shutdown();
  242. qDebug() << __func__ << ": Shutdown finished";
  243. Q_EMIT shutdownResult(1);
  244. } catch (const std::exception& e) {
  245. handleRunawayException(&e);
  246. } catch (...) {
  247. handleRunawayException(NULL);
  248. }
  249. }
  250. BitcoinApplication::BitcoinApplication(int &argc, char **argv):
  251. QApplication(argc, argv),
  252. coreThread(0),
  253. optionsModel(0),
  254. clientModel(0),
  255. window(0),
  256. pollShutdownTimer(0),
  257. #ifdef ENABLE_WALLET
  258. paymentServer(0),
  259. walletModel(0),
  260. #endif
  261. returnValue(0)
  262. {
  263. setQuitOnLastWindowClosed(false);
  264. // UI per-platform customization
  265. // This must be done inside the BitcoinApplication constructor, or after it, because
  266. // PlatformStyle::instantiate requires a QApplication
  267. #if defined(Q_OS_MAC)
  268. std::string platformName = "macosx";
  269. #elif defined(Q_OS_WIN)
  270. std::string platformName = "windows";
  271. #else
  272. std::string platformName = "other";
  273. #endif
  274. platformName = GetArg("-uiplatform", platformName);
  275. platformStyle = PlatformStyle::instantiate(QString::fromStdString(platformName));
  276. if (!platformStyle) // Fall back to "other" if specified name not found
  277. platformStyle = PlatformStyle::instantiate("other");
  278. assert(platformStyle);
  279. }
  280. BitcoinApplication::~BitcoinApplication()
  281. {
  282. if(coreThread)
  283. {
  284. qDebug() << __func__ << ": Stopping thread";
  285. Q_EMIT stopThread();
  286. coreThread->wait();
  287. qDebug() << __func__ << ": Stopped thread";
  288. }
  289. delete window;
  290. window = 0;
  291. #ifdef ENABLE_WALLET
  292. delete paymentServer;
  293. paymentServer = 0;
  294. #endif
  295. delete optionsModel;
  296. optionsModel = 0;
  297. delete platformStyle;
  298. platformStyle = 0;
  299. }
  300. #ifdef ENABLE_WALLET
  301. void BitcoinApplication::createPaymentServer()
  302. {
  303. paymentServer = new PaymentServer(this);
  304. }
  305. #endif
  306. void BitcoinApplication::createOptionsModel()
  307. {
  308. optionsModel = new OptionsModel();
  309. }
  310. void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
  311. {
  312. window = new BitcoinGUI(platformStyle, networkStyle, 0);
  313. pollShutdownTimer = new QTimer(window);
  314. connect(pollShutdownTimer, SIGNAL(timeout()), window, SLOT(detectShutdown()));
  315. pollShutdownTimer->start(200);
  316. }
  317. void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
  318. {
  319. SplashScreen *splash = new SplashScreen(0, networkStyle);
  320. // We don't hold a direct pointer to the splash screen after creation, so use
  321. // Qt::WA_DeleteOnClose to make sure that the window will be deleted eventually.
  322. splash->setAttribute(Qt::WA_DeleteOnClose);
  323. splash->show();
  324. connect(this, SIGNAL(splashFinished(QWidget*)), splash, SLOT(slotFinish(QWidget*)));
  325. }
  326. void BitcoinApplication::startThread()
  327. {
  328. if(coreThread)
  329. return;
  330. coreThread = new QThread(this);
  331. BitcoinCore *executor = new BitcoinCore();
  332. executor->moveToThread(coreThread);
  333. /* communication to and from thread */
  334. connect(executor, SIGNAL(initializeResult(int)), this, SLOT(initializeResult(int)));
  335. connect(executor, SIGNAL(shutdownResult(int)), this, SLOT(shutdownResult(int)));
  336. connect(executor, SIGNAL(runawayException(QString)), this, SLOT(handleRunawayException(QString)));
  337. connect(this, SIGNAL(requestedInitialize()), executor, SLOT(initialize()));
  338. connect(this, SIGNAL(requestedShutdown()), executor, SLOT(shutdown()));
  339. /* make sure executor object is deleted in its own thread */
  340. connect(this, SIGNAL(stopThread()), executor, SLOT(deleteLater()));
  341. connect(this, SIGNAL(stopThread()), coreThread, SLOT(quit()));
  342. coreThread->start();
  343. }
  344. void BitcoinApplication::requestInitialize()
  345. {
  346. qDebug() << __func__ << ": Requesting initialize";
  347. startThread();
  348. Q_EMIT requestedInitialize();
  349. }
  350. void BitcoinApplication::requestShutdown()
  351. {
  352. qDebug() << __func__ << ": Requesting shutdown";
  353. startThread();
  354. window->hide();
  355. window->setClientModel(0);
  356. pollShutdownTimer->stop();
  357. #ifdef ENABLE_WALLET
  358. window->removeAllWallets();
  359. delete walletModel;
  360. walletModel = 0;
  361. #endif
  362. delete clientModel;
  363. clientModel = 0;
  364. // Show a simple window indicating shutdown status
  365. ShutdownWindow::showShutdownWindow(window);
  366. // Request shutdown from core thread
  367. Q_EMIT requestedShutdown();
  368. }
  369. void BitcoinApplication::initializeResult(int retval)
  370. {
  371. qDebug() << __func__ << ": Initialization result: " << retval;
  372. // Set exit result: 0 if successful, 1 if failure
  373. returnValue = retval ? 0 : 1;
  374. if(retval)
  375. {
  376. // Log this only after AppInit2 finishes, as then logging setup is guaranteed complete
  377. qWarning() << "Platform customization:" << platformStyle->getName();
  378. #ifdef ENABLE_WALLET
  379. PaymentServer::LoadRootCAs();
  380. paymentServer->setOptionsModel(optionsModel);
  381. #endif
  382. clientModel = new ClientModel(optionsModel);
  383. window->setClientModel(clientModel);
  384. #ifdef ENABLE_WALLET
  385. if(pwalletMain)
  386. {
  387. walletModel = new WalletModel(platformStyle, pwalletMain, optionsModel);
  388. window->addWallet(BitcoinGUI::DEFAULT_WALLET, walletModel);
  389. window->setCurrentWallet(BitcoinGUI::DEFAULT_WALLET);
  390. connect(walletModel, SIGNAL(coinsSent(CWallet*,SendCoinsRecipient,QByteArray)),
  391. paymentServer, SLOT(fetchPaymentACK(CWallet*,const SendCoinsRecipient&,QByteArray)));
  392. }
  393. #endif
  394. // If -min option passed, start window minimized.
  395. if(GetBoolArg("-min", false))
  396. {
  397. window->showMinimized();
  398. }
  399. else
  400. {
  401. window->show();
  402. }
  403. Q_EMIT splashFinished(window);
  404. #ifdef ENABLE_WALLET
  405. // Now that initialization/startup is done, process any command-line
  406. // bitcoin: URIs or payment requests:
  407. connect(paymentServer, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)),
  408. window, SLOT(handlePaymentRequest(SendCoinsRecipient)));
  409. connect(window, SIGNAL(receivedURI(QString)),
  410. paymentServer, SLOT(handleURIOrFile(QString)));
  411. connect(paymentServer, SIGNAL(message(QString,QString,unsigned int)),
  412. window, SLOT(message(QString,QString,unsigned int)));
  413. QTimer::singleShot(100, paymentServer, SLOT(uiReady()));
  414. #endif
  415. } else {
  416. quit(); // Exit main loop
  417. }
  418. }
  419. void BitcoinApplication::shutdownResult(int retval)
  420. {
  421. qDebug() << __func__ << ": Shutdown result: " << retval;
  422. quit(); // Exit main loop after shutdown finished
  423. }
  424. void BitcoinApplication::handleRunawayException(const QString &message)
  425. {
  426. QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. Bitcoin can no longer continue safely and will quit.") + QString("\n\n") + message);
  427. ::exit(1);
  428. }
  429. WId BitcoinApplication::getMainWinId() const
  430. {
  431. if (!window)
  432. return 0;
  433. return window->winId();
  434. }
  435. #ifndef BITCOIN_QT_TEST
  436. int main(int argc, char *argv[])
  437. {
  438. SetupEnvironment();
  439. /// 1. Parse command-line options. These take precedence over anything else.
  440. // Command-line options take precedence:
  441. ParseParameters(argc, argv);
  442. // Do not refer to data directory yet, this can be overridden by Intro::pickDataDirectory
  443. /// 2. Basic Qt initialization (not dependent on parameters or configuration)
  444. #if QT_VERSION < 0x050000
  445. // Internal string conversion is all UTF-8
  446. QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
  447. QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());
  448. #endif
  449. Q_INIT_RESOURCE(bitcoin);
  450. Q_INIT_RESOURCE(bitcoin_locale);
  451. BitcoinApplication app(argc, argv);
  452. #if QT_VERSION > 0x050100
  453. // Generate high-dpi pixmaps
  454. QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
  455. #endif
  456. #ifdef Q_OS_MAC
  457. QApplication::setAttribute(Qt::AA_DontShowIconsInMenus);
  458. #endif
  459. #if QT_VERSION >= 0x050500
  460. // Because of the POODLE attack it is recommended to disable SSLv3 (https://disablessl3.com/),
  461. // so set SSL protocols to TLS1.0+.
  462. QSslConfiguration sslconf = QSslConfiguration::defaultConfiguration();
  463. sslconf.setProtocol(QSsl::TlsV1_0OrLater);
  464. QSslConfiguration::setDefaultConfiguration(sslconf);
  465. #endif
  466. // Register meta types used for QMetaObject::invokeMethod
  467. qRegisterMetaType< bool* >();
  468. // Need to pass name here as CAmount is a typedef (see http://qt-project.org/doc/qt-5/qmetatype.html#qRegisterMetaType)
  469. // IMPORTANT if it is no longer a typedef use the normal variant above
  470. qRegisterMetaType< CAmount >("CAmount");
  471. /// 3. Application identification
  472. // must be set before OptionsModel is initialized or translations are loaded,
  473. // as it is used to locate QSettings
  474. QApplication::setOrganizationName(QAPP_ORG_NAME);
  475. QApplication::setOrganizationDomain(QAPP_ORG_DOMAIN);
  476. QApplication::setApplicationName(QAPP_APP_NAME_DEFAULT);
  477. GUIUtil::SubstituteFonts(GetLangTerritory());
  478. /// 4. Initialization of translations, so that intro dialog is in user's language
  479. // Now that QSettings are accessible, initialize translations
  480. QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
  481. initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);
  482. translationInterface.Translate.connect(Translate);
  483. // Show help message immediately after parsing command-line options (for "-lang") and setting locale,
  484. // but before showing splash screen.
  485. if (mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version"))
  486. {
  487. HelpMessageDialog help(NULL, mapArgs.count("-version"));
  488. help.showOrPrint();
  489. return 1;
  490. }
  491. /// 5. Now that settings and translations are available, ask user for data directory
  492. // User language is set up: pick a data directory
  493. Intro::pickDataDirectory();
  494. /// 6. Determine availability of data directory and parse bitcoin.conf
  495. /// - Do not call GetDataDir(true) before this step finishes
  496. if (!boost::filesystem::is_directory(GetDataDir(false)))
  497. {
  498. QMessageBox::critical(0, QObject::tr("Bitcoin Core"),
  499. QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"])));
  500. return 1;
  501. }
  502. try {
  503. ReadConfigFile(mapArgs, mapMultiArgs);
  504. } catch (const std::exception& e) {
  505. QMessageBox::critical(0, QObject::tr("Bitcoin Core"),
  506. QObject::tr("Error: Cannot parse configuration file: %1. Only use key=value syntax.").arg(e.what()));
  507. return false;
  508. }
  509. /// 7. Determine network (and switch to network specific options)
  510. // - Do not call Params() before this step
  511. // - Do this after parsing the configuration file, as the network can be switched there
  512. // - QSettings() will use the new application name after this, resulting in network-specific settings
  513. // - Needs to be done before createOptionsModel
  514. // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
  515. if (!SelectParamsFromCommandLine()) {
  516. QMessageBox::critical(0, QObject::tr("Bitcoin Core"), QObject::tr("Error: Invalid combination of -regtest and -testnet."));
  517. return 1;
  518. }
  519. #ifdef ENABLE_WALLET
  520. // Parse URIs on command line -- this can affect Params()
  521. PaymentServer::ipcParseCommandLine(argc, argv);
  522. #endif
  523. QScopedPointer<const NetworkStyle> networkStyle(NetworkStyle::instantiate(QString::fromStdString(Params().NetworkIDString())));
  524. assert(!networkStyle.isNull());
  525. // Allow for separate UI settings for testnets
  526. QApplication::setApplicationName(networkStyle->getAppName());
  527. // Re-initialize translations after changing application name (language in network-specific settings can be different)
  528. initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);
  529. #ifdef ENABLE_WALLET
  530. /// 8. URI IPC sending
  531. // - Do this early as we don't want to bother initializing if we are just calling IPC
  532. // - Do this *after* setting up the data directory, as the data directory hash is used in the name
  533. // of the server.
  534. // - Do this after creating app and setting up translations, so errors are
  535. // translated properly.
  536. if (PaymentServer::ipcSendCommandLine())
  537. exit(0);
  538. // Start up the payment server early, too, so impatient users that click on
  539. // bitcoin: links repeatedly have their payment requests routed to this process:
  540. app.createPaymentServer();
  541. #endif
  542. /// 9. Main GUI initialization
  543. // Install global event filter that makes sure that long tooltips can be word-wrapped
  544. app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
  545. #if QT_VERSION < 0x050000
  546. // Install qDebug() message handler to route to debug.log
  547. qInstallMsgHandler(DebugMessageHandler);
  548. #else
  549. #if defined(Q_OS_WIN)
  550. // Install global event filter for processing Windows session related Windows messages (WM_QUERYENDSESSION and WM_ENDSESSION)
  551. qApp->installNativeEventFilter(new WinShutdownMonitor());
  552. #endif
  553. // Install qDebug() message handler to route to debug.log
  554. qInstallMessageHandler(DebugMessageHandler);
  555. #endif
  556. // Load GUI settings from QSettings
  557. app.createOptionsModel();
  558. // Subscribe to global signals from core
  559. uiInterface.InitMessage.connect(InitMessage);
  560. if (GetBoolArg("-splash", true) && !GetBoolArg("-min", false))
  561. app.createSplashScreen(networkStyle.data());
  562. try
  563. {
  564. app.createWindow(networkStyle.data());
  565. app.requestInitialize();
  566. #if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
  567. WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("Bitcoin Core didn't yet exit safely..."), (HWND)app.getMainWinId());
  568. #endif
  569. app.exec();
  570. app.requestShutdown();
  571. app.exec();
  572. } catch (const std::exception& e) {
  573. PrintExceptionContinue(&e, "Runaway exception");
  574. app.handleRunawayException(QString::fromStdString(strMiscWarning));
  575. } catch (...) {
  576. PrintExceptionContinue(NULL, "Runaway exception");
  577. app.handleRunawayException(QString::fromStdString(strMiscWarning));
  578. }
  579. return app.getReturnValue();
  580. }
  581. #endif // BITCOIN_QT_TEST