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