Changeset View
Changeset View
Standalone View
Standalone View
src/qt/bitcoin.cpp
Show First 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | |||||
static QString GetLangTerritory() { | static QString GetLangTerritory() { | ||||
QSettings settings; | QSettings settings; | ||||
// Get desired locale (e.g. "de_DE") | // Get desired locale (e.g. "de_DE") | ||||
// 1) System default language | // 1) System default language | ||||
QString lang_territory = QLocale::system().name(); | QString lang_territory = QLocale::system().name(); | ||||
// 2) Language from QSettings | // 2) Language from QSettings | ||||
QString lang_territory_qsettings = | QString lang_territory_qsettings = | ||||
settings.value("language", "").toString(); | settings.value("language", "").toString(); | ||||
if (!lang_territory_qsettings.isEmpty()) | if (!lang_territory_qsettings.isEmpty()) { | ||||
lang_territory = lang_territory_qsettings; | lang_territory = lang_territory_qsettings; | ||||
} | |||||
// 3) -lang command line argument | // 3) -lang command line argument | ||||
lang_territory = QString::fromStdString( | lang_territory = QString::fromStdString( | ||||
gArgs.GetArg("-lang", lang_territory.toStdString())); | gArgs.GetArg("-lang", lang_territory.toStdString())); | ||||
return lang_territory; | return lang_territory; | ||||
} | } | ||||
/** Set up translations */ | /** Set up translations */ | ||||
static void initTranslations(QTranslator &qtTranslatorBase, | static void initTranslations(QTranslator &qtTranslatorBase, | ||||
Show All 16 Lines | static void initTranslations(QTranslator &qtTranslatorBase, | ||||
// Load language files for configured locale: | // Load language files for configured locale: | ||||
// - First load the translator for the base language, without territory | // - First load the translator for the base language, without territory | ||||
// - Then load the more specific locale translator | // - Then load the more specific locale translator | ||||
// Load e.g. qt_de.qm | // Load e.g. qt_de.qm | ||||
if (qtTranslatorBase.load( | if (qtTranslatorBase.load( | ||||
"qt_" + lang, | "qt_" + lang, | ||||
QLibraryInfo::location(QLibraryInfo::TranslationsPath))) | QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { | ||||
QApplication::installTranslator(&qtTranslatorBase); | QApplication::installTranslator(&qtTranslatorBase); | ||||
} | |||||
// Load e.g. qt_de_DE.qm | // Load e.g. qt_de_DE.qm | ||||
if (qtTranslator.load( | if (qtTranslator.load( | ||||
"qt_" + lang_territory, | "qt_" + lang_territory, | ||||
QLibraryInfo::location(QLibraryInfo::TranslationsPath))) | QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { | ||||
QApplication::installTranslator(&qtTranslator); | QApplication::installTranslator(&qtTranslator); | ||||
} | |||||
// Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in | // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in | ||||
// bitcoin.qrc) | // bitcoin.qrc) | ||||
if (translatorBase.load(lang, ":/translations/")) | if (translatorBase.load(lang, ":/translations/")) { | ||||
QApplication::installTranslator(&translatorBase); | QApplication::installTranslator(&translatorBase); | ||||
} | |||||
// Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in | // Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in | ||||
// bitcoin.qrc) | // bitcoin.qrc) | ||||
if (translator.load(lang_territory, ":/translations/")) | if (translator.load(lang_territory, ":/translations/")) { | ||||
QApplication::installTranslator(&translator); | QApplication::installTranslator(&translator); | ||||
} | } | ||||
} | |||||
/* qDebug() message handler --> debug.log */ | /* qDebug() message handler --> debug.log */ | ||||
void DebugMessageHandler(QtMsgType type, const QMessageLogContext &context, | void DebugMessageHandler(QtMsgType type, const QMessageLogContext &context, | ||||
const QString &msg) { | const QString &msg) { | ||||
Q_UNUSED(context); | Q_UNUSED(context); | ||||
if (type == QtDebugMsg) { | if (type == QtDebugMsg) { | ||||
LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString()); | LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString()); | ||||
} else { | } else { | ||||
▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Lines | #endif | ||||
// UI per-platform customization. | // UI per-platform customization. | ||||
// This must be done inside the BitcoinApplication constructor, or after it, | // This must be done inside the BitcoinApplication constructor, or after it, | ||||
// because PlatformStyle::instantiate requires a QApplication. | // because PlatformStyle::instantiate requires a QApplication. | ||||
std::string platformName; | std::string platformName; | ||||
platformName = gArgs.GetArg("-uiplatform", BitcoinGUI::DEFAULT_UIPLATFORM); | platformName = gArgs.GetArg("-uiplatform", BitcoinGUI::DEFAULT_UIPLATFORM); | ||||
platformStyle = | platformStyle = | ||||
PlatformStyle::instantiate(QString::fromStdString(platformName)); | PlatformStyle::instantiate(QString::fromStdString(platformName)); | ||||
// Fall back to "other" if specified name not found. | // Fall back to "other" if specified name not found. | ||||
if (!platformStyle) platformStyle = PlatformStyle::instantiate("other"); | if (!platformStyle) { | ||||
platformStyle = PlatformStyle::instantiate("other"); | |||||
} | |||||
assert(platformStyle); | assert(platformStyle); | ||||
} | } | ||||
BitcoinApplication::~BitcoinApplication() { | BitcoinApplication::~BitcoinApplication() { | ||||
if (coreThread) { | if (coreThread) { | ||||
qDebug() << __func__ << ": Stopping thread"; | qDebug() << __func__ << ": Stopping thread"; | ||||
Q_EMIT stopThread(); | Q_EMIT stopThread(); | ||||
coreThread->wait(); | coreThread->wait(); | ||||
Show All 39 Lines | void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle) { | ||||
// happens. | // happens. | ||||
splash->show(); | splash->show(); | ||||
connect(this, SIGNAL(splashFinished(QWidget *)), splash, | connect(this, SIGNAL(splashFinished(QWidget *)), splash, | ||||
SLOT(slotFinish(QWidget *))); | SLOT(slotFinish(QWidget *))); | ||||
connect(this, SIGNAL(requestedShutdown()), splash, SLOT(close())); | connect(this, SIGNAL(requestedShutdown()), splash, SLOT(close())); | ||||
} | } | ||||
void BitcoinApplication::startThread() { | void BitcoinApplication::startThread() { | ||||
if (coreThread) return; | if (coreThread) { | ||||
return; | |||||
} | |||||
coreThread = new QThread(this); | coreThread = new QThread(this); | ||||
BitcoinABC *executor = new BitcoinABC(); | BitcoinABC *executor = new BitcoinABC(); | ||||
executor->moveToThread(coreThread); | executor->moveToThread(coreThread); | ||||
/* communication to and from thread */ | /* communication to and from thread */ | ||||
connect(executor, SIGNAL(initializeResult(bool)), this, | connect(executor, SIGNAL(initializeResult(bool)), this, | ||||
SLOT(initializeResult(bool))); | SLOT(initializeResult(bool))); | ||||
connect(executor, SIGNAL(shutdownResult()), this, SLOT(shutdownResult())); | connect(executor, SIGNAL(shutdownResult()), this, SLOT(shutdownResult())); | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | #endif | ||||
// Request shutdown from core thread | // Request shutdown from core thread | ||||
Q_EMIT requestedShutdown(); | Q_EMIT requestedShutdown(); | ||||
} | } | ||||
void BitcoinApplication::initializeResult(bool success) { | void BitcoinApplication::initializeResult(bool success) { | ||||
qDebug() << __func__ << ": Initialization result: " << success; | qDebug() << __func__ << ": Initialization result: " << success; | ||||
returnValue = success ? EXIT_SUCCESS : EXIT_FAILURE; | returnValue = success ? EXIT_SUCCESS : EXIT_FAILURE; | ||||
if (success) { | if (!success) { | ||||
// Exit main loop. | |||||
quit(); | |||||
return; | |||||
} | |||||
// Log this only after AppInit2 finishes, as then logging setup is | // Log this only after AppInit2 finishes, as then logging setup is | ||||
// guaranteed complete. | // guaranteed complete. | ||||
qWarning() << "Platform customization:" << platformStyle->getName(); | qWarning() << "Platform customization:" << platformStyle->getName(); | ||||
#ifdef ENABLE_WALLET | #ifdef ENABLE_WALLET | ||||
PaymentServer::LoadRootCAs(); | PaymentServer::LoadRootCAs(); | ||||
paymentServer->setOptionsModel(optionsModel); | paymentServer->setOptionsModel(optionsModel); | ||||
#endif | #endif | ||||
clientModel = new ClientModel(optionsModel); | clientModel = new ClientModel(optionsModel); | ||||
window->setClientModel(clientModel); | window->setClientModel(clientModel); | ||||
#ifdef ENABLE_WALLET | #ifdef ENABLE_WALLET | ||||
// TODO: Expose secondary wallets | // TODO: Expose secondary wallets | ||||
if (!vpwallets.empty()) { | if (!vpwallets.empty()) { | ||||
walletModel = | walletModel = | ||||
new WalletModel(platformStyle, vpwallets[0], optionsModel); | new WalletModel(platformStyle, vpwallets[0], optionsModel); | ||||
window->addWallet(BitcoinGUI::DEFAULT_WALLET, walletModel); | window->addWallet(BitcoinGUI::DEFAULT_WALLET, walletModel); | ||||
window->setCurrentWallet(BitcoinGUI::DEFAULT_WALLET); | window->setCurrentWallet(BitcoinGUI::DEFAULT_WALLET); | ||||
connect(walletModel, SIGNAL(coinsSent(CWallet *, SendCoinsRecipient, | connect(walletModel, | ||||
QByteArray)), | SIGNAL(coinsSent(CWallet *, SendCoinsRecipient, QByteArray)), | ||||
paymentServer, | paymentServer, | ||||
SLOT(fetchPaymentACK(CWallet *, const SendCoinsRecipient &, | SLOT(fetchPaymentACK(CWallet *, const SendCoinsRecipient &, | ||||
QByteArray))); | QByteArray))); | ||||
} | } | ||||
#endif | #endif | ||||
// If -min option passed, start window minimized. | // If -min option passed, start window minimized. | ||||
if (gArgs.GetBoolArg("-min", false)) { | if (gArgs.GetBoolArg("-min", false)) { | ||||
window->showMinimized(); | window->showMinimized(); | ||||
} else { | } else { | ||||
window->show(); | window->show(); | ||||
} | } | ||||
Q_EMIT splashFinished(window); | Q_EMIT splashFinished(window); | ||||
#ifdef ENABLE_WALLET | #ifdef ENABLE_WALLET | ||||
// Now that initialization/startup is done, process any command-line | // Now that initialization/startup is done, process any command-line | ||||
// bitcoincash: URIs or payment requests: | // bitcoincash: URIs or payment requests: | ||||
connect(paymentServer, | connect(paymentServer, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)), | ||||
SIGNAL(receivedPaymentRequest(SendCoinsRecipient)), window, | window, SLOT(handlePaymentRequest(SendCoinsRecipient))); | ||||
SLOT(handlePaymentRequest(SendCoinsRecipient))); | |||||
connect(window, SIGNAL(receivedURI(QString)), paymentServer, | connect(window, SIGNAL(receivedURI(QString)), paymentServer, | ||||
SLOT(handleURIOrFile(QString))); | SLOT(handleURIOrFile(QString))); | ||||
connect(paymentServer, SIGNAL(message(QString, QString, unsigned int)), | connect(paymentServer, SIGNAL(message(QString, QString, unsigned int)), | ||||
window, SLOT(message(QString, QString, unsigned int))); | window, SLOT(message(QString, QString, unsigned int))); | ||||
QTimer::singleShot(100, paymentServer, SLOT(uiReady())); | QTimer::singleShot(100, paymentServer, SLOT(uiReady())); | ||||
#endif | #endif | ||||
} else { | |||||
// Exit main loop. | |||||
quit(); | |||||
} | |||||
} | } | ||||
void BitcoinApplication::shutdownResult() { | void BitcoinApplication::shutdownResult() { | ||||
// Exit main loop after shutdown finished. | // Exit main loop after shutdown finished. | ||||
quit(); | quit(); | ||||
} | } | ||||
void BitcoinApplication::handleRunawayException(const QString &message) { | void BitcoinApplication::handleRunawayException(const QString &message) { | ||||
QMessageBox::critical( | QMessageBox::critical( | ||||
0, "Runaway exception", | 0, "Runaway exception", | ||||
BitcoinGUI::tr("A fatal error occurred. Bitcoin can no longer continue " | BitcoinGUI::tr("A fatal error occurred. Bitcoin can no longer continue " | ||||
"safely and will quit.") + | "safely and will quit.") + | ||||
QString("\n\n") + message); | QString("\n\n") + message); | ||||
::exit(EXIT_FAILURE); | ::exit(EXIT_FAILURE); | ||||
} | } | ||||
WId BitcoinApplication::getMainWinId() const { | WId BitcoinApplication::getMainWinId() const { | ||||
if (!window) return 0; | if (!window) { | ||||
return 0; | |||||
} | |||||
return window->winId(); | return window->winId(); | ||||
} | } | ||||
#ifndef BITCOIN_QT_TEST | #ifndef BITCOIN_QT_TEST | ||||
static void MigrateSettings() { | static void MigrateSettings() { | ||||
assert(!QApplication::applicationName().isEmpty()); | assert(!QApplication::applicationName().isEmpty()); | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | if (gArgs.IsArgSet("-?") || gArgs.IsArgSet("-h") || | ||||
gArgs.IsArgSet("-help") || gArgs.IsArgSet("-version")) { | gArgs.IsArgSet("-help") || gArgs.IsArgSet("-version")) { | ||||
HelpMessageDialog help(nullptr, gArgs.IsArgSet("-version")); | HelpMessageDialog help(nullptr, gArgs.IsArgSet("-version")); | ||||
help.showOrPrint(); | help.showOrPrint(); | ||||
return EXIT_SUCCESS; | return EXIT_SUCCESS; | ||||
} | } | ||||
/// 5. Now that settings and translations are available, ask user for data | /// 5. Now that settings and translations are available, ask user for data | ||||
/// directory. User language is set up: pick a data directory. | /// directory. User language is set up: pick a data directory. | ||||
if (!Intro::pickDataDirectory()) return EXIT_SUCCESS; | if (!Intro::pickDataDirectory()) { | ||||
return EXIT_SUCCESS; | |||||
} | |||||
/// 6. Determine availability of data directory and parse bitcoin.conf | /// 6. Determine availability of data directory and parse bitcoin.conf | ||||
/// - Do not call GetDataDir(true) before this step finishes. | /// - Do not call GetDataDir(true) before this step finishes. | ||||
if (!fs::is_directory(GetDataDir(false))) { | if (!fs::is_directory(GetDataDir(false))) { | ||||
QMessageBox::critical( | QMessageBox::critical( | ||||
0, QObject::tr(PACKAGE_NAME), | 0, QObject::tr(PACKAGE_NAME), | ||||
QObject::tr( | QObject::tr( | ||||
"Error: Specified data directory \"%1\" does not exist.") | "Error: Specified data directory \"%1\" does not exist.") | ||||
.arg(QString::fromStdString(gArgs.GetArg("-datadir", "")))); | .arg(QString::fromStdString(gArgs.GetArg("-datadir", "")))); | ||||
return EXIT_FAILURE; | return EXIT_FAILURE; | ||||
} | } | ||||
try { | try { | ||||
gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)); | gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)); | ||||
} catch (const std::exception &e) { | } catch (const std::exception &e) { | ||||
QMessageBox::critical( | QMessageBox::critical( | ||||
0, QObject::tr(PACKAGE_NAME), | 0, QObject::tr(PACKAGE_NAME), | ||||
QObject::tr("Error: Cannot parse configuration file: %1. Only use " | QObject::tr("Error: Cannot parse configuration file: %1. Only use " | ||||
"key=value syntax.") | "key=value syntax.") | ||||
.arg(e.what())); | .arg(e.what())); | ||||
Show All 36 Lines | #ifdef ENABLE_WALLET | ||||
/// 8. URI IPC sending | /// 8. URI IPC sending | ||||
// - Do this early as we don't want to bother initializing if we are just | // - Do this early as we don't want to bother initializing if we are just | ||||
// calling IPC | // calling IPC | ||||
// - Do this *after* setting up the data directory, as the data directory | // - Do this *after* setting up the data directory, as the data directory | ||||
// hash is used in the name | // hash is used in the name | ||||
// of the server. | // of the server. | ||||
// - Do this after creating app and setting up translations, so errors are | // - Do this after creating app and setting up translations, so errors are | ||||
// translated properly. | // translated properly. | ||||
if (PaymentServer::ipcSendCommandLine()) exit(EXIT_SUCCESS); | if (PaymentServer::ipcSendCommandLine()) { | ||||
exit(EXIT_SUCCESS); | |||||
} | |||||
// Start up the payment server early, too, so impatient users that click on | // Start up the payment server early, too, so impatient users that click on | ||||
// bitcoincash: links repeatedly have their payment requests routed to this | // bitcoincash: links repeatedly have their payment requests routed to this | ||||
// process: | // process: | ||||
app.createPaymentServer(); | app.createPaymentServer(); | ||||
#endif | #endif | ||||
/// 9. Main GUI initialization | /// 9. Main GUI initialization | ||||
Show All 15 Lines | #endif | ||||
// Subscribe to global signals from core | // Subscribe to global signals from core | ||||
uiInterface.InitMessage.connect(InitMessage); | uiInterface.InitMessage.connect(InitMessage); | ||||
// Get global config | // Get global config | ||||
Config &config = const_cast<Config &>(GetConfig()); | Config &config = const_cast<Config &>(GetConfig()); | ||||
if (gArgs.GetBoolArg("-splash", DEFAULT_SPLASHSCREEN) && | if (gArgs.GetBoolArg("-splash", DEFAULT_SPLASHSCREEN) && | ||||
!gArgs.GetBoolArg("-min", false)) | !gArgs.GetBoolArg("-min", false)) { | ||||
app.createSplashScreen(networkStyle.data()); | app.createSplashScreen(networkStyle.data()); | ||||
} | |||||
RPCServer rpcServer; | RPCServer rpcServer; | ||||
HTTPRPCRequestProcessor httpRPCRequestProcessor(config, rpcServer); | HTTPRPCRequestProcessor httpRPCRequestProcessor(config, rpcServer); | ||||
int rv = EXIT_SUCCESS; | int rv = EXIT_SUCCESS; | ||||
try { | try { | ||||
app.createWindow(&config, networkStyle.data()); | app.createWindow(&config, networkStyle.data()); | ||||
// Perform base initialization before spinning up | // Perform base initialization before spinning up | ||||
// initialization/shutdown thread. This is acceptable because this | // initialization/shutdown thread. This is acceptable because this | ||||
// function only contains steps that are quick to execute, so the GUI | // function only contains steps that are quick to execute, so the GUI | ||||
// thread won't be held up. | // thread won't be held up. | ||||
if (AppInitBase(config, rpcServer)) { | if (!AppInitBase(config, rpcServer)) { | ||||
// A dialog with detailed error will have been shown by InitError() | |||||
rv = EXIT_FAILURE; | |||||
return rv; | |||||
} | |||||
app.requestInitialize(config, httpRPCRequestProcessor, rpcServer); | app.requestInitialize(config, httpRPCRequestProcessor, rpcServer); | ||||
#if defined(Q_OS_WIN) | #if defined(Q_OS_WIN) | ||||
WinShutdownMonitor::registerShutdownBlockReason( | WinShutdownMonitor::registerShutdownBlockReason( | ||||
QObject::tr("%1 didn't yet exit safely...") | QObject::tr("%1 didn't yet exit safely...") | ||||
.arg(QObject::tr(PACKAGE_NAME)), | .arg(QObject::tr(PACKAGE_NAME)), | ||||
(HWND)app.getMainWinId()); | (HWND)app.getMainWinId()); | ||||
#endif | #endif | ||||
app.exec(); | app.exec(); | ||||
app.requestShutdown(config); | app.requestShutdown(config); | ||||
app.exec(); | app.exec(); | ||||
rv = app.getReturnValue(); | rv = app.getReturnValue(); | ||||
} else { | |||||
// A dialog with detailed error will have been shown by InitError() | |||||
rv = EXIT_FAILURE; | |||||
} | |||||
} catch (const std::exception &e) { | } catch (const std::exception &e) { | ||||
PrintExceptionContinue(&e, "Runaway exception"); | PrintExceptionContinue(&e, "Runaway exception"); | ||||
app.handleRunawayException(QString::fromStdString(GetWarnings("gui"))); | app.handleRunawayException(QString::fromStdString(GetWarnings("gui"))); | ||||
} catch (...) { | } catch (...) { | ||||
PrintExceptionContinue(nullptr, "Runaway exception"); | PrintExceptionContinue(nullptr, "Runaway exception"); | ||||
app.handleRunawayException(QString::fromStdString(GetWarnings("gui"))); | app.handleRunawayException(QString::fromStdString(GetWarnings("gui"))); | ||||
} | } | ||||
return rv; | return rv; | ||||
} | } | ||||
#endif // BITCOIN_QT_TEST | #endif // BITCOIN_QT_TEST |