Merge pull request #3488

2102ab9 ui: Fix GUI initialization order (Wladimir J. van der Laan)
This commit is contained in:
Wladimir J. van der Laan 2014-01-10 11:39:34 +01:00
commit 5b45bf400e
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
4 changed files with 80 additions and 57 deletions

View File

@ -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,51 +207,11 @@ 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"])));
return 1;
}
else if (fSelParFromCLFailed) {
QMessageBox::critical(0, QObject::tr("Bitcoin"), QObject::tr("Error: Invalid combination of -regtest and -testnet."));
return 1;
}
// 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);
// 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
#if QT_VERSION < 0x050000
qInstallMsgHandler(DebugMessageHandler);
#else
qInstallMessageHandler(DebugMessageHandler);
#endif
// ... now GUI settings:
OptionsModel optionsModel;
// Subscribe to global signals from core
uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox);
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"))
@ -259,7 +220,56 @@ int main(int argc, char *argv[])
help.showOrPrint();
return 1;
}
// 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);
/// 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
#if QT_VERSION < 0x050000
qInstallMsgHandler(DebugMessageHandler);
#else
qInstallMessageHandler(DebugMessageHandler);
#endif
// Load GUI settings from QSettings
OptionsModel optionsModel;
// Subscribe to global signals from core
uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox);
uiInterface.InitMessage.connect(InitMessage);
uiInterface.Translate.connect(Translate);
// Show splash screen if appropriate
SplashScreen splash(QPixmap(), 0, isaTestNet);
if (GetBoolArg("-splash", true) && !GetBoolArg("-min", false))
{

View File

@ -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 */

View File

@ -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();

View File

@ -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);