diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 657b42d16..cd74fb4ce 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -161,22 +161,23 @@ void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons #ifndef BITCOIN_QT_TEST int main(int argc, char *argv[]) { - bool fMissingDatadir = false; bool fSelParFromCLFailed = false; - + /// 1. Parse command-line options. These take precedence over anything else. // Command-line options take precedence: ParseParameters(argc, argv); - // ... then bitcoin.conf: - if (!boost::filesystem::is_directory(GetDataDir(false))) { - fMissingDatadir = true; - } else { - ReadConfigFile(mapArgs, mapMultiArgs); - } // Check for -testnet or -regtest parameter (TestNet() calls are only valid after this clause) if (!SelectParamsFromCommandLine()) { fSelParFromCLFailed = true; } + // Parse URIs on command line -- this can affect TestNet() / RegTest() mode + if (!PaymentServer::ipcParseCommandLine(argc, argv)) + exit(0); + + bool isaTestNet = TestNet() || RegTest(); + + // Do not refer to data directory yet, this can be overridden by Intro::pickDataDirectory + /// 2. Basic Qt initialization (not dependent on parameters or configuration) #if QT_VERSION < 0x050000 // Internal string conversion is all UTF-8 QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); @@ -196,9 +197,9 @@ int main(int argc, char *argv[]) // Register meta types used for QMetaObject::invokeMethod qRegisterMetaType< bool* >(); - // Application identification (must be set before OptionsModel is initialized, - // as it is used to locate QSettings) - bool isaTestNet = TestNet() || RegTest(); + /// 3. Application identification + // must be set before OptionsModel is initialized or translations are loaded, + // as it is used to locate QSettings QApplication::setOrganizationName("Bitcoin"); QApplication::setOrganizationDomain("bitcoin.org"); if (isaTestNet) // Separate UI settings for testnets @@ -206,34 +207,52 @@ int main(int argc, char *argv[]) else QApplication::setApplicationName("Bitcoin-Qt"); + /// 4. Initialization of translations, so that intro dialog is in user's language // Now that QSettings are accessible, initialize translations QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator; initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator); - // Do this early as we don't want to bother initializing if we are just calling IPC - // ... but do it after creating app and setting up translations, so errors are - // translated properly. - if (PaymentServer::ipcSendCommandLine(argc, argv)) - exit(0); - - // Now that translations are initialized check for errors and allow a translatable error message - if (fMissingDatadir) { - QMessageBox::critical(0, QObject::tr("Bitcoin"), - QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"]))); + // Show help message immediately after parsing command-line options (for "-lang") and setting locale, + // but before showing splash screen. + if (mapArgs.count("-?") || mapArgs.count("--help")) + { + GUIUtil::HelpMessageBox help; + help.showOrPrint(); return 1; } - else if (fSelParFromCLFailed) { + // Now that translations are initialized, check for earlier errors and show a translatable error message + if (fSelParFromCLFailed) { QMessageBox::critical(0, QObject::tr("Bitcoin"), QObject::tr("Error: Invalid combination of -regtest and -testnet.")); return 1; } + /// 5. Now that settings and translations are available, ask user for data directory + // User language is set up: pick a data directory + Intro::pickDataDirectory(isaTestNet); + + /// 6. Determine availability of data directory and parse bitcoin.conf + if (!boost::filesystem::is_directory(GetDataDir(false))) + { + QMessageBox::critical(0, QObject::tr("Bitcoin"), + QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"]))); + return 1; + } + ReadConfigFile(mapArgs, mapMultiArgs); + + /// 7. URI IPC sending + // - Do this early as we don't want to bother initializing if we are just calling IPC + // - Do this *after* setting up the data directory, as the data directory hash is used in the name + // of the server. + // - Do this after creating app and setting up translations, so errors are + // translated properly. + if (PaymentServer::ipcSendCommandLine()) + exit(0); + // Start up the payment server early, too, so impatient users that click on // bitcoin: links repeatedly have their payment requests routed to this process: PaymentServer* paymentServer = new PaymentServer(&app); - // User language is set up: pick a data directory - Intro::pickDataDirectory(isaTestNet); - + /// 8. Main GUI initialization // Install global event filter that makes sure that long tooltips can be word-wrapped app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app)); // Install qDebug() message handler to route to debug.log @@ -242,8 +261,7 @@ int main(int argc, char *argv[]) #else qInstallMessageHandler(DebugMessageHandler); #endif - - // ... now GUI settings: + // Load GUI settings from QSettings OptionsModel optionsModel; // Subscribe to global signals from core @@ -251,15 +269,7 @@ int main(int argc, char *argv[]) uiInterface.InitMessage.connect(InitMessage); uiInterface.Translate.connect(Translate); - // Show help message immediately after parsing command-line options (for "-lang") and setting locale, - // but before showing splash screen. - if (mapArgs.count("-?") || mapArgs.count("--help")) - { - GUIUtil::HelpMessageBox help; - help.showOrPrint(); - return 1; - } - + // Show splash screen if appropriate SplashScreen splash(QPixmap(), 0, isaTestNet); if (GetBoolArg("-splash", true) && !GetBoolArg("-min", false)) { diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 3ecd96cc4..5f7ccf709 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -148,7 +148,7 @@ QString Intro::getDefaultDataDirectory() void Intro::pickDataDirectory(bool fIsTestnet) { - namespace fs = boost::filesystem;; + namespace fs = boost::filesystem; QSettings settings; /* If data directory provided on command line, no need to look at settings or show a picking dialog */ diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index ba5c06064..3d6f5de75 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -180,10 +180,8 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store) // and the items in savedPaymentRequest will be handled // when uiReady() is called. // -bool PaymentServer::ipcSendCommandLine(int argc, char* argv[]) +bool PaymentServer::ipcParseCommandLine(int argc, char* argv[]) { - bool fResult = false; - for (int i = 1; i < argc; i++) { QString arg(argv[i]); @@ -226,7 +224,18 @@ bool PaymentServer::ipcSendCommandLine(int argc, char* argv[]) qDebug() << "PaymentServer::ipcSendCommandLine : Payment request file does not exist: " << arg; } } + return true; +} +// +// Sending to the server is done synchronously, at startup. +// If the server isn't already running, startup continues, +// and the items in savedPaymentRequest will be handled +// when uiReady() is called. +// +bool PaymentServer::ipcSendCommandLine() +{ + bool fResult = false; foreach (const QString& r, savedPaymentRequests) { QLocalSocket* socket = new QLocalSocket(); diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h index ab59388ac..5ee85f7db 100644 --- a/src/qt/paymentserver.h +++ b/src/qt/paymentserver.h @@ -56,12 +56,16 @@ class PaymentServer : public QObject Q_OBJECT public: + // Parse URIs on command line + // Returns false on error + static bool ipcParseCommandLine(int argc, char *argv[]); + // Returns true if there were URIs on the command line // which were successfully sent to an already-running // process. // Note: if a payment request is given, SelectParams(MAIN/TESTNET) // will be called so we startup in the right mode. - static bool ipcSendCommandLine(int argc, char *argv[]); + static bool ipcSendCommandLine(); // parent should be QApplication object PaymentServer(QObject* parent, bool startLocalServer = true);