2015-12-13 17:58:29 +01:00
// Copyright (c) 2011-2015 The Bitcoin Core developers
2014-12-13 05:09:33 +01:00
// Distributed under the MIT software license, see the accompanying
2013-11-04 16:20:43 +01:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2013-01-23 21:51:02 +01:00
2014-01-11 18:56:24 +01:00
# if defined(HAVE_CONFIG_H)
2014-06-23 20:04:24 +02:00
# include "config/bitcoin-config.h"
2014-01-11 18:56:24 +01:00
# endif
2011-05-12 14:49:42 +02:00
# include "bitcoingui.h"
2013-04-13 07:13:08 +02:00
2015-07-05 14:17:46 +02:00
# include "chainparams.h"
2011-05-22 17:19:43 +02:00
# include "clientmodel.h"
2012-04-13 17:10:50 +02:00
# include "guiconstants.h"
2013-04-13 07:13:08 +02:00
# include "guiutil.h"
# include "intro.h"
2014-10-09 11:04:49 +02:00
# include "networkstyle.h"
2013-04-13 07:13:08 +02:00
# include "optionsmodel.h"
2015-07-28 15:20:14 +02:00
# include "platformstyle.h"
2013-04-14 11:35:37 +02:00
# include "splashscreen.h"
2014-01-16 16:05:44 +01:00
# include "utilitydialog.h"
2014-04-10 08:19:58 +02:00
# include "winshutdownmonitor.h"
2014-09-05 13:18:35 +02:00
2013-12-11 15:00:56 +01:00
# ifdef ENABLE_WALLET
# include "paymentserver.h"
2013-04-13 07:13:08 +02:00
# include "walletmodel.h"
2013-12-11 15:00:56 +01:00
# endif
2013-04-13 07:13:08 +02:00
# include "init.h"
2016-01-15 01:55:17 +01:00
# include "rpc/server.h"
2015-04-03 17:50:06 +02:00
# include "scheduler.h"
2013-04-13 07:13:08 +02:00
# include "ui_interface.h"
# include "util.h"
2014-09-05 13:18:35 +02:00
2014-03-31 06:13:40 +02:00
# ifdef ENABLE_WALLET
2015-02-03 21:09:47 +01:00
# include "wallet/wallet.h"
2014-03-31 06:13:40 +02:00
# endif
2011-05-07 22:13:39 +02:00
2013-04-13 07:13:08 +02:00
# include <stdint.h>
# include <boost/filesystem/operations.hpp>
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
# include <boost/thread.hpp>
2014-09-05 13:18:35 +02:00
2013-07-23 08:52:24 +02:00
# include <QApplication>
2014-07-15 10:23:28 +02:00
# include <QDebug>
2013-04-13 07:13:08 +02:00
# include <QLibraryInfo>
# include <QLocale>
2011-06-05 16:03:29 +02:00
# include <QMessageBox>
2013-04-13 07:13:08 +02:00
# include <QSettings>
2014-09-05 13:18:35 +02:00
# include <QThread>
2013-04-13 07:13:08 +02:00
# include <QTimer>
# include <QTranslator>
2015-07-06 20:06:16 +02:00
# include <QSslConfiguration>
2013-04-13 07:13:08 +02:00
2013-12-02 22:54:19 +01:00
# if defined(QT_STATICPLUGIN)
2012-03-24 16:52:43 +01:00
# include <QtPlugin>
2013-12-02 22:54:19 +01:00
# if QT_VERSION < 0x050000
2012-03-24 16:52:43 +01:00
Q_IMPORT_PLUGIN ( qcncodecs )
Q_IMPORT_PLUGIN ( qjpcodecs )
Q_IMPORT_PLUGIN ( qtwcodecs )
Q_IMPORT_PLUGIN ( qkrcodecs )
Q_IMPORT_PLUGIN ( qtaccessiblewidgets )
2013-12-02 22:54:19 +01:00
# else
2015-07-23 23:10:15 +02:00
# if QT_VERSION < 0x050400
2013-12-02 22:54:19 +01:00
Q_IMPORT_PLUGIN ( AccessibleFactory )
2015-07-23 23:10:15 +02:00
# endif
2014-06-04 05:42:53 +02:00
# if defined(QT_QPA_PLATFORM_XCB)
Q_IMPORT_PLUGIN ( QXcbIntegrationPlugin ) ;
# elif defined(QT_QPA_PLATFORM_WINDOWS)
2013-12-02 22:54:19 +01:00
Q_IMPORT_PLUGIN ( QWindowsIntegrationPlugin ) ;
2014-06-04 05:42:53 +02:00
# elif defined(QT_QPA_PLATFORM_COCOA)
Q_IMPORT_PLUGIN ( QCocoaIntegrationPlugin ) ;
# endif
2013-12-02 22:54:19 +01:00
# endif
# endif
# if QT_VERSION < 0x050000
# include <QTextCodec>
2012-03-24 16:52:43 +01:00
# endif
2013-04-14 18:50:40 +02:00
// Declare meta types used for QMetaObject::invokeMethod
Q_DECLARE_METATYPE ( bool * )
2014-10-01 10:09:08 +02:00
Q_DECLARE_METATYPE ( CAmount )
2013-04-14 18:50:40 +02:00
2012-05-06 19:40:58 +02:00
static void InitMessage ( const std : : string & message )
2011-08-02 21:48:59 +02:00
{
2014-01-16 16:15:27 +01:00
LogPrintf ( " init message: %s \n " , message ) ;
2011-08-02 21:48:59 +02:00
}
2011-06-13 16:56:37 +02:00
/*
Translate string to current locale using Qt .
*/
2012-05-06 19:40:58 +02:00
static std : : string Translate ( const char * psz )
2011-06-13 16:56:37 +02:00
{
return QCoreApplication : : translate ( " bitcoin-core " , psz ) . toStdString ( ) ;
}
2015-01-16 22:03:48 +01:00
static QString GetLangTerritory ( )
{
QSettings settings ;
// Get desired locale (e.g. "de_DE")
// 1) System default language
QString lang_territory = QLocale : : system ( ) . name ( ) ;
// 2) Language from QSettings
QString lang_territory_qsettings = settings . value ( " language " , " " ) . toString ( ) ;
if ( ! lang_territory_qsettings . isEmpty ( ) )
lang_territory = lang_territory_qsettings ;
// 3) -lang command line argument
lang_territory = QString : : fromStdString ( GetArg ( " -lang " , lang_territory . toStdString ( ) ) ) ;
return lang_territory ;
}
2013-05-19 17:36:01 +02:00
/** Set up translations */
static void initTranslations ( QTranslator & qtTranslatorBase , QTranslator & qtTranslator , QTranslator & translatorBase , QTranslator & translator )
{
2014-03-11 08:32:07 +01:00
// Remove old translators
QApplication : : removeTranslator ( & qtTranslatorBase ) ;
QApplication : : removeTranslator ( & qtTranslator ) ;
QApplication : : removeTranslator ( & translatorBase ) ;
QApplication : : removeTranslator ( & translator ) ;
2013-05-19 17:36:01 +02:00
// Get desired locale (e.g. "de_DE")
// 1) System default language
2015-01-16 22:03:48 +01:00
QString lang_territory = GetLangTerritory ( ) ;
2013-05-19 17:36:01 +02:00
// Convert to "de" only by truncating "_DE"
QString lang = lang_territory ;
lang . truncate ( lang_territory . lastIndexOf ( ' _ ' ) ) ;
// Load language files for configured locale:
// - First load the translator for the base language, without territory
// - Then load the more specific locale translator
// Load e.g. qt_de.qm
if ( qtTranslatorBase . load ( " qt_ " + lang , QLibraryInfo : : location ( QLibraryInfo : : TranslationsPath ) ) )
QApplication : : installTranslator ( & qtTranslatorBase ) ;
// Load e.g. qt_de_DE.qm
if ( qtTranslator . load ( " qt_ " + lang_territory , QLibraryInfo : : location ( QLibraryInfo : : TranslationsPath ) ) )
QApplication : : installTranslator ( & qtTranslator ) ;
// Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
if ( translatorBase . load ( lang , " :/translations/ " ) )
QApplication : : installTranslator ( & translatorBase ) ;
// Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
if ( translator . load ( lang_territory , " :/translations/ " ) )
QApplication : : installTranslator ( & translator ) ;
}
2013-07-23 09:01:08 +02:00
/* qDebug() message handler --> debug.log */
# if QT_VERSION < 0x050000
2013-12-03 09:25:24 +01:00
void DebugMessageHandler ( QtMsgType type , const char * msg )
2013-07-23 09:01:08 +02:00
{
2014-07-01 14:57:45 +02:00
const char * category = ( type = = QtDebugMsg ) ? " qt " : NULL ;
LogPrint ( category , " GUI: %s \n " , msg ) ;
2013-07-23 09:01:08 +02:00
}
# else
void DebugMessageHandler ( QtMsgType type , const QMessageLogContext & context , const QString & msg )
{
2013-09-28 19:29:44 +02:00
Q_UNUSED ( context ) ;
2014-07-01 14:57:45 +02:00
const char * category = ( type = = QtDebugMsg ) ? " qt " : NULL ;
2014-07-02 08:14:50 +02:00
LogPrint ( category , " GUI: %s \n " , msg . toStdString ( ) ) ;
2013-07-23 09:01:08 +02:00
}
# endif
2014-01-07 11:30:17 +01:00
/** Class encapsulating Bitcoin Core startup and shutdown.
* Allows running startup and shutdown in a different thread from the UI thread .
*/
class BitcoinCore : public QObject
{
Q_OBJECT
public :
explicit BitcoinCore ( ) ;
2015-07-14 13:59:05 +02:00
public Q_SLOTS :
2014-01-07 11:30:17 +01:00
void initialize ( ) ;
void shutdown ( ) ;
2015-07-14 13:59:05 +02:00
Q_SIGNALS :
2014-01-07 11:30:17 +01:00
void initializeResult ( int retval ) ;
void shutdownResult ( int retval ) ;
void runawayException ( const QString & message ) ;
private :
boost : : thread_group threadGroup ;
2015-04-03 17:50:06 +02:00
CScheduler scheduler ;
2014-01-07 11:30:17 +01:00
/// Pass fatal exception message to UI thread
2014-12-07 13:29:06 +01:00
void handleRunawayException ( const std : : exception * e ) ;
2014-01-07 11:30:17 +01:00
} ;
/** Main Bitcoin application object */
class BitcoinApplication : public QApplication
{
Q_OBJECT
public :
explicit BitcoinApplication ( int & argc , char * * argv ) ;
~ BitcoinApplication ( ) ;
2013-12-11 15:00:56 +01:00
# ifdef ENABLE_WALLET
2014-01-07 11:30:17 +01:00
/// Create payment server
void createPaymentServer ( ) ;
2013-12-11 15:00:56 +01:00
# endif
2015-10-08 10:01:29 +02:00
/// parameter interaction/setup based on rules
void parameterSetup ( ) ;
2014-01-07 11:30:17 +01:00
/// Create options model
2015-11-13 16:27:42 +01:00
void createOptionsModel ( bool resetSettings ) ;
2014-01-07 11:30:17 +01:00
/// Create main window
2014-10-09 11:04:49 +02:00
void createWindow ( const NetworkStyle * networkStyle ) ;
2014-01-08 08:59:24 +01:00
/// Create splash screen
2014-10-09 11:04:49 +02:00
void createSplashScreen ( const NetworkStyle * networkStyle ) ;
2014-01-07 11:30:17 +01:00
/// Request core initialization
void requestInitialize ( ) ;
/// Request core shutdown
void requestShutdown ( ) ;
/// Get process return value
int getReturnValue ( ) { return returnValue ; }
2014-04-10 08:19:58 +02:00
/// Get window identifier of QMainWindow (BitcoinGUI)
WId getMainWinId ( ) const ;
2015-07-14 13:59:05 +02:00
public Q_SLOTS :
2014-01-07 11:30:17 +01:00
void initializeResult ( int retval ) ;
void shutdownResult ( int retval ) ;
/// Handle runaway exceptions. Shows a message box with the problem and quits the program.
void handleRunawayException ( const QString & message ) ;
2015-07-14 13:59:05 +02:00
Q_SIGNALS :
2014-01-07 11:30:17 +01:00
void requestedInitialize ( ) ;
void requestedShutdown ( ) ;
void stopThread ( ) ;
2014-01-08 08:59:24 +01:00
void splashFinished ( QWidget * window ) ;
2014-01-07 11:30:17 +01:00
private :
QThread * coreThread ;
OptionsModel * optionsModel ;
ClientModel * clientModel ;
BitcoinGUI * window ;
2014-01-08 10:45:00 +01:00
QTimer * pollShutdownTimer ;
2013-12-11 15:00:56 +01:00
# ifdef ENABLE_WALLET
PaymentServer * paymentServer ;
WalletModel * walletModel ;
# endif
2014-01-07 11:30:17 +01:00
int returnValue ;
2015-07-28 15:20:14 +02:00
const PlatformStyle * platformStyle ;
2014-01-07 11:30:17 +01:00
void startThread ( ) ;
} ;
# include "bitcoin.moc"
BitcoinCore : : BitcoinCore ( ) :
QObject ( )
{
}
2014-12-07 13:29:06 +01:00
void BitcoinCore : : handleRunawayException ( const std : : exception * e )
2014-01-07 11:30:17 +01:00
{
PrintExceptionContinue ( e , " Runaway exception " ) ;
2015-07-14 13:59:05 +02:00
Q_EMIT runawayException ( QString : : fromStdString ( strMiscWarning ) ) ;
2014-01-07 11:30:17 +01:00
}
void BitcoinCore : : initialize ( )
{
try
{
2014-07-15 10:23:28 +02:00
qDebug ( ) < < __func__ < < " : Running AppInit2 in thread " ;
2015-04-03 17:50:06 +02:00
int rv = AppInit2 ( threadGroup , scheduler ) ;
2015-07-14 13:59:05 +02:00
Q_EMIT initializeResult ( rv ) ;
2014-12-07 13:29:06 +01:00
} catch ( const std : : exception & e ) {
2014-01-07 11:30:17 +01:00
handleRunawayException ( & e ) ;
} catch ( . . . ) {
handleRunawayException ( NULL ) ;
}
}
void BitcoinCore : : shutdown ( )
{
try
{
2014-07-15 10:23:28 +02:00
qDebug ( ) < < __func__ < < " : Running Shutdown in thread " ;
evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*.
boost::asio is not part of C++11, so unlike other boost there is no
forwards-compatibility reason to stick with it. Together with #4738 (convert
json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with
regard to compile-time slowness.
- *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling
is handled by libevent, a work queue (with configurable depth and parallelism)
is used to handle application requests.
- *Wrap HTTP request in C++ class*; this makes the application code mostly
HTTP-server-neutral
- *Refactor RPC to move all http-specific code to a separate file*.
Theoreticaly this can allow building without HTTP server but with another RPC
backend, e.g. Qt's debug console (currently not implemented) or future RPC
mechanisms people may want to use.
- *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL
paths they want to handle.
By using a proven, high-performance asynchronous networking library (also used
by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided.
What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests
pass. The aim for now is everything but SSL support.
Configuration options:
- `-rpcthreads`: repurposed as "number of work handler threads". Still
defaults to 4.
- `-rpcworkqueue`: maximum depth of work queue. When this is reached, new
requests will return a 500 Internal Error.
- `-rpctimeout`: inactivity time, in seconds, after which to disconnect a
client.
- `-debug=http`: low-level http activity logging
2015-01-23 07:53:17 +01:00
Interrupt ( threadGroup ) ;
2014-01-07 11:30:17 +01:00
threadGroup . join_all ( ) ;
Shutdown ( ) ;
2014-07-15 10:23:28 +02:00
qDebug ( ) < < __func__ < < " : Shutdown finished " ;
2015-07-14 13:59:05 +02:00
Q_EMIT shutdownResult ( 1 ) ;
2014-12-07 13:29:06 +01:00
} catch ( const std : : exception & e ) {
2014-01-07 11:30:17 +01:00
handleRunawayException ( & e ) ;
} catch ( . . . ) {
handleRunawayException ( NULL ) ;
}
}
BitcoinApplication : : BitcoinApplication ( int & argc , char * * argv ) :
QApplication ( argc , argv ) ,
coreThread ( 0 ) ,
optionsModel ( 0 ) ,
clientModel ( 0 ) ,
window ( 0 ) ,
2014-01-08 10:45:00 +01:00
pollShutdownTimer ( 0 ) ,
2013-12-11 15:00:56 +01:00
# ifdef ENABLE_WALLET
paymentServer ( 0 ) ,
walletModel ( 0 ) ,
# endif
2014-01-07 11:30:17 +01:00
returnValue ( 0 )
{
setQuitOnLastWindowClosed ( false ) ;
2015-07-28 15:20:14 +02:00
// UI per-platform customization
// This must be done inside the BitcoinApplication constructor, or after it, because
// PlatformStyle::instantiate requires a QApplication
2015-11-28 22:44:55 +01:00
std : : string platformName ;
platformName = GetArg ( " -uiplatform " , BitcoinGUI : : DEFAULT_UIPLATFORM ) ;
2015-07-28 15:20:14 +02:00
platformStyle = PlatformStyle : : instantiate ( QString : : fromStdString ( platformName ) ) ;
if ( ! platformStyle ) // Fall back to "other" if specified name not found
platformStyle = PlatformStyle : : instantiate ( " other " ) ;
assert ( platformStyle ) ;
2014-01-07 11:30:17 +01:00
}
BitcoinApplication : : ~ BitcoinApplication ( )
{
2014-07-15 16:26:16 +02:00
if ( coreThread )
{
qDebug ( ) < < __func__ < < " : Stopping thread " ;
2015-07-14 13:59:05 +02:00
Q_EMIT stopThread ( ) ;
2014-07-15 16:26:16 +02:00
coreThread - > wait ( ) ;
qDebug ( ) < < __func__ < < " : Stopped thread " ;
}
2014-01-08 08:59:24 +01:00
delete window ;
2013-12-11 15:00:56 +01:00
window = 0 ;
# ifdef ENABLE_WALLET
2014-01-08 08:59:24 +01:00
delete paymentServer ;
2013-12-11 15:00:56 +01:00
paymentServer = 0 ;
# endif
2014-01-08 08:59:24 +01:00
delete optionsModel ;
2013-12-11 15:00:56 +01:00
optionsModel = 0 ;
2015-07-28 15:20:14 +02:00
delete platformStyle ;
platformStyle = 0 ;
2014-01-07 11:30:17 +01:00
}
2013-12-11 15:00:56 +01:00
# ifdef ENABLE_WALLET
2014-01-07 11:30:17 +01:00
void BitcoinApplication : : createPaymentServer ( )
{
paymentServer = new PaymentServer ( this ) ;
}
2013-12-11 15:00:56 +01:00
# endif
2014-01-07 11:30:17 +01:00
2015-11-13 16:27:42 +01:00
void BitcoinApplication : : createOptionsModel ( bool resetSettings )
2014-01-07 11:30:17 +01:00
{
2015-11-13 16:27:42 +01:00
optionsModel = new OptionsModel ( NULL , resetSettings ) ;
2014-01-07 11:30:17 +01:00
}
2014-10-09 11:04:49 +02:00
void BitcoinApplication : : createWindow ( const NetworkStyle * networkStyle )
2014-01-07 11:30:17 +01:00
{
2015-07-28 15:20:14 +02:00
window = new BitcoinGUI ( platformStyle , networkStyle , 0 ) ;
2014-01-07 11:30:17 +01:00
2014-01-08 10:45:00 +01:00
pollShutdownTimer = new QTimer ( window ) ;
2014-01-07 11:30:17 +01:00
connect ( pollShutdownTimer , SIGNAL ( timeout ( ) ) , window , SLOT ( detectShutdown ( ) ) ) ;
pollShutdownTimer - > start ( 200 ) ;
}
2014-10-09 11:04:49 +02:00
void BitcoinApplication : : createSplashScreen ( const NetworkStyle * networkStyle )
2014-01-08 08:59:24 +01:00
{
2014-10-09 11:04:49 +02:00
SplashScreen * splash = new SplashScreen ( 0 , networkStyle ) ;
2014-09-22 10:08:47 +02:00
// We don't hold a direct pointer to the splash screen after creation, so use
// Qt::WA_DeleteOnClose to make sure that the window will be deleted eventually.
splash - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
2014-01-08 08:59:24 +01:00
splash - > show ( ) ;
connect ( this , SIGNAL ( splashFinished ( QWidget * ) ) , splash , SLOT ( slotFinish ( QWidget * ) ) ) ;
}
2014-01-07 11:30:17 +01:00
void BitcoinApplication : : startThread ( )
{
2014-07-15 16:26:16 +02:00
if ( coreThread )
return ;
2014-01-07 11:30:17 +01:00
coreThread = new QThread ( this ) ;
BitcoinCore * executor = new BitcoinCore ( ) ;
executor - > moveToThread ( coreThread ) ;
/* communication to and from thread */
connect ( executor , SIGNAL ( initializeResult ( int ) ) , this , SLOT ( initializeResult ( int ) ) ) ;
connect ( executor , SIGNAL ( shutdownResult ( int ) ) , this , SLOT ( shutdownResult ( int ) ) ) ;
connect ( executor , SIGNAL ( runawayException ( QString ) ) , this , SLOT ( handleRunawayException ( QString ) ) ) ;
connect ( this , SIGNAL ( requestedInitialize ( ) ) , executor , SLOT ( initialize ( ) ) ) ;
connect ( this , SIGNAL ( requestedShutdown ( ) ) , executor , SLOT ( shutdown ( ) ) ) ;
/* make sure executor object is deleted in its own thread */
connect ( this , SIGNAL ( stopThread ( ) ) , executor , SLOT ( deleteLater ( ) ) ) ;
connect ( this , SIGNAL ( stopThread ( ) ) , coreThread , SLOT ( quit ( ) ) ) ;
coreThread - > start ( ) ;
}
2015-10-08 10:01:29 +02:00
void BitcoinApplication : : parameterSetup ( )
{
2015-11-26 14:03:27 +01:00
InitLogging ( ) ;
2015-10-08 10:01:29 +02:00
InitParameterInteraction ( ) ;
}
2014-01-07 11:30:17 +01:00
void BitcoinApplication : : requestInitialize ( )
{
2014-07-15 10:23:28 +02:00
qDebug ( ) < < __func__ < < " : Requesting initialize " ;
2014-07-15 16:26:16 +02:00
startThread ( ) ;
2015-07-14 13:59:05 +02:00
Q_EMIT requestedInitialize ( ) ;
2014-01-07 11:30:17 +01:00
}
void BitcoinApplication : : requestShutdown ( )
{
2014-07-15 10:23:28 +02:00
qDebug ( ) < < __func__ < < " : Requesting shutdown " ;
2014-07-15 16:26:16 +02:00
startThread ( ) ;
2014-01-07 11:30:17 +01:00
window - > hide ( ) ;
window - > setClientModel ( 0 ) ;
2014-01-08 10:45:00 +01:00
pollShutdownTimer - > stop ( ) ;
2014-01-07 16:04:47 +01:00
2013-12-11 15:00:56 +01:00
# ifdef ENABLE_WALLET
window - > removeAllWallets ( ) ;
2014-01-07 11:30:17 +01:00
delete walletModel ;
2014-01-08 08:59:24 +01:00
walletModel = 0 ;
2013-12-11 15:00:56 +01:00
# endif
2014-01-08 08:59:24 +01:00
delete clientModel ;
clientModel = 0 ;
2014-01-07 16:04:47 +01:00
// Show a simple window indicating shutdown status
2014-01-16 16:05:44 +01:00
ShutdownWindow : : showShutdownWindow ( window ) ;
2014-01-07 16:04:47 +01:00
// Request shutdown from core thread
2015-07-14 13:59:05 +02:00
Q_EMIT requestedShutdown ( ) ;
2014-01-07 11:30:17 +01:00
}
void BitcoinApplication : : initializeResult ( int retval )
{
2014-07-15 10:23:28 +02:00
qDebug ( ) < < __func__ < < " : Initialization result: " < < retval ;
2014-01-07 16:04:47 +01:00
// Set exit result: 0 if successful, 1 if failure
2014-01-07 11:30:17 +01:00
returnValue = retval ? 0 : 1 ;
if ( retval )
{
2015-07-28 15:20:14 +02:00
// Log this only after AppInit2 finishes, as then logging setup is guaranteed complete
qWarning ( ) < < " Platform customization: " < < platformStyle - > getName ( ) ;
2013-12-11 15:00:56 +01:00
# ifdef ENABLE_WALLET
2014-01-07 11:30:17 +01:00
PaymentServer : : LoadRootCAs ( ) ;
paymentServer - > setOptionsModel ( optionsModel ) ;
2013-12-11 15:00:56 +01:00
# endif
2014-01-07 11:30:17 +01:00
clientModel = new ClientModel ( optionsModel ) ;
window - > setClientModel ( clientModel ) ;
2013-12-11 15:00:56 +01:00
# ifdef ENABLE_WALLET
2014-01-07 11:30:17 +01:00
if ( pwalletMain )
{
2015-07-28 15:20:14 +02:00
walletModel = new WalletModel ( platformStyle , pwalletMain , optionsModel ) ;
2014-01-07 11:30:17 +01:00
2014-08-07 09:36:02 +02:00
window - > addWallet ( BitcoinGUI : : DEFAULT_WALLET , walletModel ) ;
window - > setCurrentWallet ( BitcoinGUI : : DEFAULT_WALLET ) ;
2014-01-07 11:30:17 +01:00
connect ( walletModel , SIGNAL ( coinsSent ( CWallet * , SendCoinsRecipient , QByteArray ) ) ,
paymentServer , SLOT ( fetchPaymentACK ( CWallet * , const SendCoinsRecipient & , QByteArray ) ) ) ;
}
2013-12-11 15:00:56 +01:00
# endif
2014-01-07 11:30:17 +01:00
// If -min option passed, start window minimized.
if ( GetBoolArg ( " -min " , false ) )
{
window - > showMinimized ( ) ;
}
else
{
window - > show ( ) ;
}
2015-07-14 13:59:05 +02:00
Q_EMIT splashFinished ( window ) ;
2014-09-18 13:14:38 +02:00
2013-12-11 15:00:56 +01:00
# ifdef ENABLE_WALLET
2014-01-07 11:30:17 +01:00
// Now that initialization/startup is done, process any command-line
// bitcoin: URIs or payment requests:
connect ( paymentServer , SIGNAL ( receivedPaymentRequest ( SendCoinsRecipient ) ) ,
window , SLOT ( handlePaymentRequest ( SendCoinsRecipient ) ) ) ;
connect ( window , SIGNAL ( receivedURI ( QString ) ) ,
paymentServer , SLOT ( handleURIOrFile ( QString ) ) ) ;
connect ( paymentServer , SIGNAL ( message ( QString , QString , unsigned int ) ) ,
window , SLOT ( message ( QString , QString , unsigned int ) ) ) ;
QTimer : : singleShot ( 100 , paymentServer , SLOT ( uiReady ( ) ) ) ;
2013-12-11 15:00:56 +01:00
# endif
2014-01-07 11:30:17 +01:00
} else {
quit ( ) ; // Exit main loop
}
}
void BitcoinApplication : : shutdownResult ( int retval )
{
2014-07-15 10:23:28 +02:00
qDebug ( ) < < __func__ < < " : Shutdown result: " < < retval ;
2014-01-07 11:30:17 +01:00
quit ( ) ; // Exit main loop after shutdown finished
}
void BitcoinApplication : : handleRunawayException ( const QString & message )
{
QMessageBox : : critical ( 0 , " Runaway exception " , BitcoinGUI : : tr ( " A fatal error occurred. Bitcoin can no longer continue safely and will quit. " ) + QString ( " \n \n " ) + message ) ;
: : exit ( 1 ) ;
}
2014-04-10 08:19:58 +02:00
WId BitcoinApplication : : getMainWinId ( ) const
{
if ( ! window )
return 0 ;
return window - > winId ( ) ;
}
2012-02-10 23:25:36 +01:00
# ifndef BITCOIN_QT_TEST
2011-05-07 22:13:39 +02:00
int main ( int argc , char * argv [ ] )
{
2014-05-13 12:15:00 +02:00
SetupEnvironment ( ) ;
2014-01-05 12:37:51 +01:00
/// 1. Parse command-line options. These take precedence over anything else.
2013-01-03 22:06:18 +01:00
// Command-line options take precedence:
ParseParameters ( argc , argv ) ;
2014-01-05 12:37:51 +01:00
// Do not refer to data directory yet, this can be overridden by Intro::pickDataDirectory
2013-01-03 22:06:18 +01:00
2014-01-05 12:37:51 +01:00
/// 2. Basic Qt initialization (not dependent on parameters or configuration)
2013-05-31 14:02:24 +02:00
# if QT_VERSION < 0x050000
2011-11-12 12:20:34 +01:00
// Internal string conversion is all UTF-8
2011-08-28 14:12:26 +02:00
QTextCodec : : setCodecForTr ( QTextCodec : : codecForName ( " UTF-8 " ) ) ;
QTextCodec : : setCodecForCStrings ( QTextCodec : : codecForTr ( ) ) ;
2013-05-31 14:02:24 +02:00
# endif
2011-08-28 14:12:26 +02:00
2011-06-18 14:25:24 +02:00
Q_INIT_RESOURCE ( bitcoin ) ;
2014-06-10 21:43:02 +02:00
Q_INIT_RESOURCE ( bitcoin_locale ) ;
2014-08-06 21:06:40 +02:00
2014-01-07 11:30:17 +01:00
BitcoinApplication app ( argc , argv ) ;
2013-11-21 17:59:31 +01:00
# if QT_VERSION > 0x050100
// Generate high-dpi pixmaps
QApplication : : setAttribute ( Qt : : AA_UseHighDpiPixmaps ) ;
# endif
# ifdef Q_OS_MAC
QApplication : : setAttribute ( Qt : : AA_DontShowIconsInMenus ) ;
# endif
2015-07-06 20:06:16 +02:00
# if QT_VERSION >= 0x050500
// Because of the POODLE attack it is recommended to disable SSLv3 (https://disablessl3.com/),
// so set SSL protocols to TLS1.0+.
QSslConfiguration sslconf = QSslConfiguration : : defaultConfiguration ( ) ;
sslconf . setProtocol ( QSsl : : TlsV1_0OrLater ) ;
QSslConfiguration : : setDefaultConfiguration ( sslconf ) ;
# endif
2011-06-23 22:35:30 +02:00
2013-04-14 18:50:40 +02:00
// Register meta types used for QMetaObject::invokeMethod
qRegisterMetaType < bool * > ( ) ;
2014-10-01 10:09:08 +02:00
// Need to pass name here as CAmount is a typedef (see http://qt-project.org/doc/qt-5/qmetatype.html#qRegisterMetaType)
// IMPORTANT if it is no longer a typedef use the normal variant above
qRegisterMetaType < CAmount > ( " CAmount " ) ;
2013-04-14 18:50:40 +02:00
2014-01-05 12:37:51 +01:00
/// 3. Application identification
// must be set before OptionsModel is initialized or translations are loaded,
// as it is used to locate QSettings
2014-03-11 08:32:07 +01:00
QApplication : : setOrganizationName ( QAPP_ORG_NAME ) ;
QApplication : : setOrganizationDomain ( QAPP_ORG_DOMAIN ) ;
QApplication : : setApplicationName ( QAPP_APP_NAME_DEFAULT ) ;
2015-01-16 22:03:48 +01:00
GUIUtil : : SubstituteFonts ( GetLangTerritory ( ) ) ;
2013-05-19 17:36:01 +02:00
2014-01-05 12:37:51 +01:00
/// 4. Initialization of translations, so that intro dialog is in user's language
2013-05-19 17:36:01 +02:00
// Now that QSettings are accessible, initialize translations
QTranslator qtTranslatorBase , qtTranslator , translatorBase , translator ;
initTranslations ( qtTranslatorBase , qtTranslator , translatorBase , translator ) ;
2015-04-16 16:20:01 +02:00
translationInterface . Translate . connect ( Translate ) ;
2013-05-19 17:36:01 +02:00
2014-01-05 12:37:51 +01:00
// Show help message immediately after parsing command-line options (for "-lang") and setting locale,
// but before showing splash screen.
2015-10-18 12:02:36 +02:00
if ( mapArgs . count ( " -? " ) | | mapArgs . count ( " -h " ) | | mapArgs . count ( " -help " ) | | mapArgs . count ( " -version " ) )
2014-01-05 12:37:51 +01:00
{
2014-06-03 16:12:19 +02:00
HelpMessageDialog help ( NULL , mapArgs . count ( " -version " ) ) ;
2014-01-05 12:37:51 +01:00
help . showOrPrint ( ) ;
2013-06-23 18:04:44 +02:00
return 1 ;
}
2014-01-05 12:37:51 +01:00
/// 5. Now that settings and translations are available, ask user for data directory
// User language is set up: pick a data directory
2014-03-11 08:32:07 +01:00
Intro : : pickDataDirectory ( ) ;
2014-01-05 12:37:51 +01:00
/// 6. Determine availability of data directory and parse bitcoin.conf
2014-03-11 08:32:07 +01:00
/// - Do not call GetDataDir(true) before this step finishes
2014-01-05 12:37:51 +01:00
if ( ! boost : : filesystem : : is_directory ( GetDataDir ( false ) ) )
{
2015-12-09 11:53:12 +01:00
QMessageBox : : critical ( 0 , QObject : : tr ( PACKAGE_NAME ) ,
2014-01-05 12:37:51 +01:00
QObject : : tr ( " Error: Specified data directory \" %1 \" does not exist. " ) . arg ( QString : : fromStdString ( mapArgs [ " -datadir " ] ) ) ) ;
return 1 ;
}
2014-04-07 10:10:01 +02:00
try {
ReadConfigFile ( mapArgs , mapMultiArgs ) ;
2014-12-07 13:29:06 +01:00
} catch ( const std : : exception & e ) {
2015-12-09 11:53:12 +01:00
QMessageBox : : critical ( 0 , QObject : : tr ( PACKAGE_NAME ) ,
2014-04-07 10:10:01 +02:00
QObject : : tr ( " Error: Cannot parse configuration file: %1. Only use key=value syntax. " ) . arg ( e . what ( ) ) ) ;
return false ;
}
2014-01-05 12:37:51 +01:00
2014-03-11 08:32:07 +01:00
/// 7. Determine network (and switch to network specific options)
// - Do not call Params() before this step
// - Do this after parsing the configuration file, as the network can be switched there
// - QSettings() will use the new application name after this, resulting in network-specific settings
// - Needs to be done before createOptionsModel
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
2015-05-25 09:00:17 +02:00
try {
SelectParams ( ChainNameFromCommandLine ( ) ) ;
} catch ( std : : exception & e ) {
2015-12-09 11:53:12 +01:00
QMessageBox : : critical ( 0 , QObject : : tr ( PACKAGE_NAME ) , QObject : : tr ( " Error: %1 " ) . arg ( e . what ( ) ) ) ;
2014-03-11 08:32:07 +01:00
return 1 ;
}
# ifdef ENABLE_WALLET
// Parse URIs on command line -- this can affect Params()
2014-11-05 11:42:51 +01:00
PaymentServer : : ipcParseCommandLine ( argc , argv ) ;
2014-03-11 08:32:07 +01:00
# endif
2014-11-05 11:42:51 +01:00
2014-10-09 11:04:49 +02:00
QScopedPointer < const NetworkStyle > networkStyle ( NetworkStyle : : instantiate ( QString : : fromStdString ( Params ( ) . NetworkIDString ( ) ) ) ) ;
assert ( ! networkStyle . isNull ( ) ) ;
2014-03-11 08:32:07 +01:00
// Allow for separate UI settings for testnets
2014-10-09 11:04:49 +02:00
QApplication : : setApplicationName ( networkStyle - > getAppName ( ) ) ;
2014-03-11 08:32:07 +01:00
// Re-initialize translations after changing application name (language in network-specific settings can be different)
initTranslations ( qtTranslatorBase , qtTranslator , translatorBase , translator ) ;
2013-12-11 15:00:56 +01:00
# ifdef ENABLE_WALLET
2014-03-11 08:32:07 +01:00
/// 8. URI IPC sending
2014-01-05 12:37:51 +01:00
// - 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 ) ;
2013-07-18 08:50:17 +02:00
// Start up the payment server early, too, so impatient users that click on
// bitcoin: links repeatedly have their payment requests routed to this process:
2014-01-07 11:30:17 +01:00
app . createPaymentServer ( ) ;
2013-12-11 15:00:56 +01:00
# endif
2013-07-18 08:50:17 +02:00
2014-03-11 08:32:07 +01:00
/// 9. Main GUI initialization
2012-04-13 17:10:50 +02:00
// Install global event filter that makes sure that long tooltips can be word-wrapped
app . installEventFilter ( new GUIUtil : : ToolTipToRichTextFilter ( TOOLTIP_WRAP_THRESHOLD , & app ) ) ;
2013-08-31 15:32:35 +02:00
# if QT_VERSION < 0x050000
2014-04-10 08:19:58 +02:00
// Install qDebug() message handler to route to debug.log
2013-08-31 15:32:35 +02:00
qInstallMsgHandler ( DebugMessageHandler ) ;
# else
2014-04-10 08:19:58 +02:00
# if defined(Q_OS_WIN)
// Install global event filter for processing Windows session related Windows messages (WM_QUERYENDSESSION and WM_ENDSESSION)
qApp - > installNativeEventFilter ( new WinShutdownMonitor ( ) ) ;
# endif
// Install qDebug() message handler to route to debug.log
2013-08-31 15:32:35 +02:00
qInstallMessageHandler ( DebugMessageHandler ) ;
# endif
2015-10-08 10:01:29 +02:00
// Allow parameter interaction before we create the options model
app . parameterSetup ( ) ;
2014-01-05 12:37:51 +01:00
// Load GUI settings from QSettings
2015-11-13 16:27:42 +01:00
app . createOptionsModel ( mapArgs . count ( " -resetguisettings " ) ! = 0 ) ;
2012-02-17 03:09:41 +01:00
2012-05-06 19:40:58 +02:00
// Subscribe to global signals from core
uiInterface . InitMessage . connect ( InitMessage ) ;
2015-06-27 21:21:41 +02:00
if ( GetBoolArg ( " -splash " , DEFAULT_SPLASHSCREEN ) & & ! GetBoolArg ( " -min " , false ) )
2014-10-09 11:04:49 +02:00
app . createSplashScreen ( networkStyle . data ( ) ) ;
2011-05-07 22:13:39 +02:00
2011-06-07 18:59:01 +02:00
try
{
2014-10-09 11:04:49 +02:00
app . createWindow ( networkStyle . data ( ) ) ;
2014-01-07 11:30:17 +01:00
app . requestInitialize ( ) ;
2014-04-10 08:19:58 +02:00
# if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
2015-12-09 11:53:12 +01:00
WinShutdownMonitor : : registerShutdownBlockReason ( QObject : : tr ( " %1 didn't yet exit safely... " ) . arg ( QObject : : tr ( PACKAGE_NAME ) ) , ( HWND ) app . getMainWinId ( ) ) ;
2014-04-10 08:19:58 +02:00
# endif
2014-01-07 11:30:17 +01:00
app . exec ( ) ;
app . requestShutdown ( ) ;
app . exec ( ) ;
2014-12-07 13:29:06 +01:00
} catch ( const std : : exception & e ) {
2014-01-07 11:30:17 +01:00
PrintExceptionContinue ( & e , " Runaway exception " ) ;
app . handleRunawayException ( QString : : fromStdString ( strMiscWarning ) ) ;
2011-05-22 17:19:43 +02:00
} catch ( . . . ) {
2014-01-07 11:30:17 +01:00
PrintExceptionContinue ( NULL , " Runaway exception " ) ;
app . handleRunawayException ( QString : : fromStdString ( strMiscWarning ) ) ;
2011-05-22 17:19:43 +02:00
}
2014-01-07 11:30:17 +01:00
return app . getReturnValue ( ) ;
2011-05-07 22:13:39 +02:00
}
2012-02-10 23:25:36 +01:00
# endif // BITCOIN_QT_TEST