2018-07-27 00:36:45 +02:00
// Copyright (c) 2011-2018 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)
2017-11-10 01:57:53 +01:00
# include <config/bitcoin-config.h>
2014-01-11 18:56:24 +01:00
# endif
2017-11-10 01:57:53 +01:00
# include <qt/bitcoingui.h>
# include <chainparams.h>
# include <qt/clientmodel.h>
# include <fs.h>
# include <qt/guiconstants.h>
# include <qt/guiutil.h>
# include <qt/intro.h>
# include <qt/networkstyle.h>
# include <qt/optionsmodel.h>
# include <qt/platformstyle.h>
# include <qt/splashscreen.h>
# include <qt/utilitydialog.h>
# include <qt/winshutdownmonitor.h>
2014-09-05 13:18:35 +02:00
2013-12-11 15:00:56 +01:00
# ifdef ENABLE_WALLET
2017-11-10 01:57:53 +01:00
# include <qt/paymentserver.h>
# include <qt/walletmodel.h>
2013-12-11 15:00:56 +01:00
# endif
2013-04-13 07:13:08 +02:00
2018-04-07 09:42:02 +02:00
# include <interfaces/handler.h>
# include <interfaces/node.h>
2018-09-06 21:21:00 +02:00
# include <noui.h>
2017-11-10 01:57:53 +01:00
# include <rpc/server.h>
# include <ui_interface.h>
2018-03-01 10:40:36 +01:00
# include <uint256.h>
2017-11-10 01:57:53 +01:00
# include <util.h>
# include <warnings.h>
2014-09-05 13:18:35 +02:00
2018-03-27 21:35:54 +02:00
# include <walletinitinterface.h>
2011-05-07 22:13:39 +02:00
2018-04-02 20:31:40 +02:00
# include <memory>
2013-04-13 07:13:08 +02:00
# include <stdint.h>
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>
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
2012-03-24 16:52:43 +01:00
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 )
2018-03-01 10:40:36 +01:00
Q_DECLARE_METATYPE ( uint256 )
2013-04-14 18:50:40 +02:00
2018-09-06 21:21:00 +02:00
static void InitMessage ( const std : : string & message )
2011-08-02 21:48:59 +02:00
{
2018-09-06 21:21:00 +02:00
noui_InitMessage ( message ) ;
2011-08-02 21:48:59 +02:00
}
2018-08-13 22:13:29 +02:00
/** Translate string to current locale using Qt. */
const std : : function < std : : string ( const char * ) > G_TRANSLATION_FUN = [ ] ( const char * psz ) {
2011-06-13 16:56:37 +02:00
return QCoreApplication : : translate ( " bitcoin-core " , psz ) . toStdString ( ) ;
2018-08-13 22:13:29 +02:00
} ;
2011-06-13 16:56:37 +02:00
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
2017-08-01 21:17:40 +02:00
lang_territory = QString : : fromStdString ( gArgs . GetArg ( " -lang " , lang_territory . toStdString ( ) ) ) ;
2015-01-16 22:03:48 +01:00
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 */
void DebugMessageHandler ( QtMsgType type , const QMessageLogContext & context , const QString & msg )
{
2013-09-28 19:29:44 +02:00
Q_UNUSED ( context ) ;
2016-12-25 21:19:40 +01:00
if ( type = = QtDebugMsg ) {
LogPrint ( BCLog : : QT , " GUI: %s \n " , msg . toStdString ( ) ) ;
} else {
LogPrintf ( " GUI: %s \n " , msg . toStdString ( ) ) ;
}
2013-07-23 09:01:08 +02:00
}
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 :
2018-04-07 09:42:02 +02:00
explicit BitcoinCore ( interfaces : : Node & node ) ;
2014-01-07 11:30:17 +01:00
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 :
2017-02-23 09:12:36 +01:00
void initializeResult ( bool success ) ;
void shutdownResult ( ) ;
2014-01-07 11:30:17 +01:00
void runawayException ( const QString & message ) ;
private :
/// Pass fatal exception message to UI thread
2014-12-07 13:29:06 +01:00
void handleRunawayException ( const std : : exception * e ) ;
2017-04-17 19:55:43 +02:00
2018-04-07 09:42:02 +02:00
interfaces : : Node & m_node ;
2014-01-07 11:30:17 +01:00
} ;
/** Main Bitcoin application object */
class BitcoinApplication : public QApplication
{
Q_OBJECT
public :
2018-04-07 09:42:02 +02:00
explicit BitcoinApplication ( interfaces : : Node & node , int & argc , char * * argv ) ;
2014-01-07 11:30:17 +01:00
~ 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
2017-03-09 13:34:54 +01:00
int getReturnValue ( ) const { return returnValue ; }
2014-01-07 11:30:17 +01:00
2014-04-10 08:19:58 +02:00
/// Get window identifier of QMainWindow (BitcoinGUI)
WId getMainWinId ( ) const ;
2018-04-29 01:40:51 +02:00
/// Setup platform style
void setupPlatformStyle ( ) ;
2015-07-14 13:59:05 +02:00
public Q_SLOTS :
2017-02-23 09:12:36 +01:00
void initializeResult ( bool success ) ;
void shutdownResult ( ) ;
2014-01-07 11:30:17 +01:00
/// Handle runaway exceptions. Shows a message box with the problem and quits the program.
void handleRunawayException ( const QString & message ) ;
2018-04-26 19:28:41 +02:00
void addWallet ( WalletModel * walletModel ) ;
2018-06-05 12:17:28 +02:00
void removeWallet ( ) ;
2014-01-07 11:30:17 +01:00
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 ;
2018-04-07 09:42:02 +02:00
interfaces : : Node & m_node ;
2014-01-07 11:30:17 +01:00
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 ;
2016-09-09 11:25:13 +02:00
std : : vector < WalletModel * > m_wallet_models ;
2018-04-26 19:28:41 +02:00
std : : unique_ptr < interfaces : : Handler > m_handler_load_wallet ;
2013-12-11 15:00:56 +01:00
# endif
2014-01-07 11:30:17 +01:00
int returnValue ;
2015-07-28 15:20:14 +02:00
const PlatformStyle * platformStyle ;
2016-11-19 14:28:55 +01:00
std : : unique_ptr < QWidget > shutdownWindow ;
2014-01-07 11:30:17 +01:00
void startThread ( ) ;
} ;
2017-08-15 17:31:26 +02:00
# include <qt/bitcoin.moc>
2014-01-07 11:30:17 +01:00
2018-04-07 09:42:02 +02:00
BitcoinCore : : BitcoinCore ( interfaces : : Node & node ) :
2017-04-17 19:55:43 +02:00
QObject ( ) , m_node ( node )
2014-01-07 11:30:17 +01:00
{
}
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 " ) ;
2017-04-17 19:55:43 +02:00
Q_EMIT runawayException ( QString : : fromStdString ( m_node . getWarnings ( " gui " ) ) ) ;
2017-07-15 10:46:06 +02:00
}
2014-01-07 11:30:17 +01:00
void BitcoinCore : : initialize ( )
{
try
{
2017-02-23 08:38:41 +01:00
qDebug ( ) < < __func__ < < " : Running initialization in thread " ;
2017-04-17 19:55:43 +02:00
bool rv = m_node . appInitMain ( ) ;
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 ( . . . ) {
2017-08-07 07:36:37 +02:00
handleRunawayException ( nullptr ) ;
2014-01-07 11:30:17 +01:00
}
}
void BitcoinCore : : shutdown ( )
{
try
{
2014-07-15 10:23:28 +02:00
qDebug ( ) < < __func__ < < " : Running Shutdown in thread " ;
2017-04-17 19:55:43 +02:00
m_node . appShutdown ( ) ;
2014-07-15 10:23:28 +02:00
qDebug ( ) < < __func__ < < " : Shutdown finished " ;
2017-02-23 09:12:36 +01:00
Q_EMIT shutdownResult ( ) ;
2014-12-07 13:29:06 +01:00
} catch ( const std : : exception & e ) {
2014-01-07 11:30:17 +01:00
handleRunawayException ( & e ) ;
} catch ( . . . ) {
2017-08-07 07:36:37 +02:00
handleRunawayException ( nullptr ) ;
2014-01-07 11:30:17 +01:00
}
}
2018-04-07 09:42:02 +02:00
BitcoinApplication : : BitcoinApplication ( interfaces : : Node & node , int & argc , char * * argv ) :
2014-01-07 11:30:17 +01:00
QApplication ( argc , argv ) ,
coreThread ( 0 ) ,
2017-04-17 19:55:43 +02:00
m_node ( node ) ,
2014-01-07 11:30:17 +01:00
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 ) ,
2016-09-09 11:25:13 +02:00
m_wallet_models ( ) ,
2013-12-11 15:00:56 +01:00
# endif
2018-04-29 01:40:51 +02:00
returnValue ( 0 ) ,
platformStyle ( 0 )
2014-01-07 11:30:17 +01:00
{
setQuitOnLastWindowClosed ( false ) ;
2018-04-29 01:40:51 +02:00
}
2015-07-28 15:20:14 +02:00
2018-04-29 01:40:51 +02:00
void BitcoinApplication : : setupPlatformStyle ( )
{
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 ;
2017-08-01 21:17:40 +02:00
platformName = gArgs . 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
{
2017-04-17 20:23:14 +02:00
optionsModel = new OptionsModel ( m_node , nullptr , 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
{
2017-04-17 20:33:47 +02:00
window = new BitcoinGUI ( m_node , platformStyle , networkStyle , 0 ) ;
2014-01-07 11:30:17 +01:00
2014-01-08 10:45:00 +01:00
pollShutdownTimer = new QTimer ( window ) ;
2018-06-24 17:18:22 +02:00
connect ( pollShutdownTimer , & QTimer : : timeout , window , & BitcoinGUI : : detectShutdown ) ;
2014-01-07 11:30:17 +01:00
}
2014-10-09 11:04:49 +02:00
void BitcoinApplication : : createSplashScreen ( const NetworkStyle * networkStyle )
2014-01-08 08:59:24 +01:00
{
2017-04-17 21:10:47 +02:00
SplashScreen * splash = new SplashScreen ( m_node , 0 , networkStyle ) ;
2016-11-19 11:08:19 +01:00
// We don't hold a direct pointer to the splash screen after creation, but the splash
// screen will take care of deleting itself when slotFinish happens.
2014-01-08 08:59:24 +01:00
splash - > show ( ) ;
2018-06-24 17:18:22 +02:00
connect ( this , & BitcoinApplication : : splashFinished , splash , & SplashScreen : : slotFinish ) ;
connect ( this , & BitcoinApplication : : requestedShutdown , splash , & QWidget : : close ) ;
2014-01-08 08:59:24 +01:00
}
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 ) ;
2017-04-17 19:55:43 +02:00
BitcoinCore * executor = new BitcoinCore ( m_node ) ;
2014-01-07 11:30:17 +01:00
executor - > moveToThread ( coreThread ) ;
/* communication to and from thread */
2018-06-24 17:18:22 +02:00
connect ( executor , & BitcoinCore : : initializeResult , this , & BitcoinApplication : : initializeResult ) ;
connect ( executor , & BitcoinCore : : shutdownResult , this , & BitcoinApplication : : shutdownResult ) ;
connect ( executor , & BitcoinCore : : runawayException , this , & BitcoinApplication : : handleRunawayException ) ;
connect ( this , & BitcoinApplication : : requestedInitialize , executor , & BitcoinCore : : initialize ) ;
connect ( this , & BitcoinApplication : : requestedShutdown , executor , & BitcoinCore : : shutdown ) ;
2014-01-07 11:30:17 +01:00
/* make sure executor object is deleted in its own thread */
2018-06-24 17:18:22 +02:00
connect ( this , & BitcoinApplication : : stopThread , executor , & QObject : : deleteLater ) ;
connect ( this , & BitcoinApplication : : stopThread , coreThread , & QThread : : quit ) ;
2014-01-07 11:30:17 +01:00
coreThread - > start ( ) ;
}
2015-10-08 10:01:29 +02:00
void BitcoinApplication : : parameterSetup ( )
{
2018-04-23 09:25:34 +02:00
// Default printtoconsole to false for the GUI. GUI programs should not
// print to the console unnecessarily.
gArgs . SoftSetBoolArg ( " -printtoconsole " , false ) ;
2017-04-17 19:55:43 +02:00
m_node . initLogging ( ) ;
m_node . initParameterInteraction ( ) ;
2015-10-08 10:01:29 +02:00
}
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 ( )
{
2016-11-18 16:35:14 +01:00
// Show a simple window indicating shutdown status
// Do this first as some of the steps may take some time below,
// for example the RPC console may still be executing a command.
2016-11-19 14:28:55 +01:00
shutdownWindow . reset ( ShutdownWindow : : showShutdownWindow ( window ) ) ;
2016-11-18 16:35:14 +01:00
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 ( ) ;
2018-06-18 07:58:28 +02:00
for ( const WalletModel * walletModel : m_wallet_models ) {
2016-09-09 11:25:13 +02:00
delete walletModel ;
}
m_wallet_models . clear ( ) ;
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
2017-04-17 19:55:43 +02:00
m_node . startShutdown ( ) ;
2017-01-05 12:40:10 +01:00
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
}
2018-04-26 19:28:41 +02:00
void BitcoinApplication : : addWallet ( WalletModel * walletModel )
{
# ifdef ENABLE_WALLET
window - > addWallet ( walletModel ) ;
if ( m_wallet_models . empty ( ) ) {
window - > setCurrentWallet ( walletModel - > getWalletName ( ) ) ;
}
2018-06-24 17:18:22 +02:00
connect ( walletModel , & WalletModel : : coinsSent ,
paymentServer , & PaymentServer : : fetchPaymentACK ) ;
connect ( walletModel , & WalletModel : : unload , this , & BitcoinApplication : : removeWallet ) ;
2018-04-26 19:28:41 +02:00
m_wallet_models . push_back ( walletModel ) ;
# endif
}
2018-06-05 12:17:28 +02:00
void BitcoinApplication : : removeWallet ( )
{
# ifdef ENABLE_WALLET
WalletModel * walletModel = static_cast < WalletModel * > ( sender ( ) ) ;
m_wallet_models . erase ( std : : find ( m_wallet_models . begin ( ) , m_wallet_models . end ( ) , walletModel ) ) ;
window - > removeWallet ( walletModel ) ;
walletModel - > deleteLater ( ) ;
# endif
}
2017-02-23 09:12:36 +01:00
void BitcoinApplication : : initializeResult ( bool success )
2014-01-07 11:30:17 +01:00
{
2017-02-23 09:12:36 +01:00
qDebug ( ) < < __func__ < < " : Initialization result: " < < success ;
// Set exit result.
returnValue = success ? EXIT_SUCCESS : EXIT_FAILURE ;
if ( success )
2014-01-07 11:30:17 +01:00
{
2017-02-23 08:38:41 +01:00
// Log this only after AppInitMain finishes, as then logging setup is guaranteed complete
2015-07-28 15:20:14 +02:00
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
2017-04-17 21:37:36 +02:00
clientModel = new ClientModel ( m_node , optionsModel ) ;
2014-01-07 11:30:17 +01:00
window - > setClientModel ( clientModel ) ;
2013-12-11 15:00:56 +01:00
# ifdef ENABLE_WALLET
2018-04-26 19:28:41 +02:00
m_handler_load_wallet = m_node . handleLoadWallet ( [ this ] ( std : : unique_ptr < interfaces : : Wallet > wallet ) {
2018-06-05 12:17:28 +02:00
WalletModel * wallet_model = new WalletModel ( std : : move ( wallet ) , m_node , platformStyle , optionsModel , nullptr ) ;
// Fix wallet model thread affinity.
wallet_model - > moveToThread ( thread ( ) ) ;
QMetaObject : : invokeMethod ( this , " addWallet " , Qt : : QueuedConnection , Q_ARG ( WalletModel * , wallet_model ) ) ;
2018-04-26 19:28:41 +02:00
} ) ;
2014-01-07 11:30:17 +01:00
2018-04-26 19:28:41 +02:00
for ( auto & wallet : m_node . getWallets ( ) ) {
addWallet ( new WalletModel ( std : : move ( wallet ) , m_node , platformStyle , optionsModel ) ) ;
2014-01-07 11:30:17 +01:00
}
2013-12-11 15:00:56 +01:00
# endif
2014-01-07 11:30:17 +01:00
// If -min option passed, start window minimized.
2017-08-01 21:17:40 +02:00
if ( gArgs . GetBoolArg ( " -min " , false ) )
2014-01-07 11:30:17 +01:00
{
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:
2018-06-24 17:18:22 +02:00
connect ( paymentServer , & PaymentServer : : receivedPaymentRequest , window , & BitcoinGUI : : handlePaymentRequest ) ;
connect ( window , & BitcoinGUI : : receivedURI , paymentServer , & PaymentServer : : handleURIOrFile ) ;
connect ( paymentServer , & PaymentServer : : message , [ this ] ( const QString & title , const QString & message , unsigned int style ) {
window - > message ( title , message , style ) ;
} ) ;
QTimer : : singleShot ( 100 , paymentServer , & PaymentServer : : uiReady ) ;
2013-12-11 15:00:56 +01:00
# endif
2018-02-07 21:18:54 +01:00
pollShutdownTimer - > start ( 200 ) ;
2014-01-07 11:30:17 +01:00
} else {
2018-02-07 10:37:19 +01:00
Q_EMIT splashFinished ( window ) ; // Make sure splash screen doesn't stick around during shutdown
quit ( ) ; // Exit first main loop invocation
2014-01-07 11:30:17 +01:00
}
}
2017-02-23 09:12:36 +01:00
void BitcoinApplication : : shutdownResult ( )
2014-01-07 11:30:17 +01:00
{
2018-02-07 10:37:19 +01:00
quit ( ) ; // Exit second main loop invocation after shutdown finished
2014-01-07 11:30:17 +01:00
}
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 ) ;
2016-11-07 19:31:38 +01:00
: : exit ( EXIT_FAILURE ) ;
2014-01-07 11:30:17 +01:00
}
2014-04-10 08:19:58 +02:00
WId BitcoinApplication : : getMainWinId ( ) const
{
if ( ! window )
return 0 ;
return window - > winId ( ) ;
}
2018-04-28 22:54:58 +02:00
static void SetupUIArgs ( )
{
# ifdef ENABLE_WALLET
gArgs . AddArg ( " -allowselfsignedrootcertificates " , strprintf ( " Allow self signed root certificates (default: %u) " , DEFAULT_SELFSIGNED_ROOTCERTS ) , true , OptionsCategory : : GUI ) ;
# endif
2018-05-29 18:49:44 +02:00
gArgs . AddArg ( " -choosedatadir " , strprintf ( " Choose data directory on startup (default: %u) " , DEFAULT_CHOOSE_DATADIR ) , false , OptionsCategory : : GUI ) ;
gArgs . AddArg ( " -lang=<lang> " , " Set language, for example \" de_DE \" (default: system locale) " , false , OptionsCategory : : GUI ) ;
gArgs . AddArg ( " -min " , " Start minimized " , false , OptionsCategory : : GUI ) ;
gArgs . AddArg ( " -resetguisettings " , " Reset all settings changed in the GUI " , false , OptionsCategory : : GUI ) ;
gArgs . AddArg ( " -rootcertificates=<file> " , " Set SSL root certificates for payment request (default: -system-) " , false , OptionsCategory : : GUI ) ;
gArgs . AddArg ( " -splash " , strprintf ( " Show splash screen on startup (default: %u) " , DEFAULT_SPLASHSCREEN ) , false , OptionsCategory : : GUI ) ;
2018-04-28 22:54:58 +02:00
gArgs . AddArg ( " -uiplatform " , strprintf ( " Select platform to customize UI for (one of windows, macosx, other; default: %s) " , BitcoinGUI : : DEFAULT_UIPLATFORM ) , true , OptionsCategory : : GUI ) ;
}
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 [ ] )
{
2018-08-05 18:38:25 +02:00
# ifdef WIN32
util : : WinCmdLineArgs winArgs ;
std : : tie ( argc , argv ) = winArgs . get ( ) ;
# endif
2014-05-13 12:15:00 +02:00
SetupEnvironment ( ) ;
2018-04-07 09:42:02 +02:00
std : : unique_ptr < interfaces : : Node > node = interfaces : : MakeNode ( ) ;
2017-04-17 19:55:43 +02:00
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
2018-04-29 01:40:51 +02:00
/// 1. Basic Qt initialization (not dependent on parameters or configuration)
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
2017-04-17 19:55:43 +02:00
BitcoinApplication app ( * node , argc , argv ) ;
2013-11-21 17:59:31 +01:00
# if QT_VERSION > 0x050100
// Generate high-dpi pixmaps
QApplication : : setAttribute ( Qt : : AA_UseHighDpiPixmaps ) ;
# endif
2016-06-20 10:17:01 +02:00
# if QT_VERSION >= 0x050600
QGuiApplication : : setAttribute ( Qt : : AA_EnableHighDpiScaling ) ;
# endif
2013-11-21 17:59:31 +01:00
# 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 " ) ;
2018-09-13 19:36:41 +02:00
qRegisterMetaType < std : : function < void ( ) > > ( " std::function<void()> " ) ;
2018-04-26 19:28:41 +02:00
# ifdef ENABLE_WALLET
qRegisterMetaType < WalletModel * > ( " WalletModel* " ) ;
# endif
2013-04-14 18:50:40 +02:00
2018-04-29 01:40:51 +02:00
/// 2. Parse command-line options. We do this after qt in order to show an error if there are problems parsing these
// Command-line options take precedence:
node - > setupServerArgs ( ) ;
SetupUIArgs ( ) ;
std : : string error ;
if ( ! node - > parseParameters ( argc , argv , error ) ) {
QMessageBox : : critical ( 0 , QObject : : tr ( PACKAGE_NAME ) ,
QObject : : tr ( " Error parsing command line arguments: %1. " ) . arg ( QString : : fromStdString ( error ) ) ) ;
return EXIT_FAILURE ;
}
// Now that the QApplication is setup and we have parsed our parameters, we can set the platform style
app . setupPlatformStyle ( ) ;
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 ) ;
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 ) ;
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.
2018-03-30 22:47:36 +02:00
if ( HelpRequested ( gArgs ) | | gArgs . IsArgSet ( " -version " ) ) {
2017-04-17 20:40:41 +02:00
HelpMessageDialog help ( * node , nullptr , gArgs . IsArgSet ( " -version " ) ) ;
2014-01-05 12:37:51 +01:00
help . showOrPrint ( ) ;
2016-11-07 19:31:38 +01:00
return EXIT_SUCCESS ;
2013-06-23 18:04:44 +02:00
}
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
2017-04-17 21:44:10 +02:00
if ( ! Intro : : pickDataDirectory ( * node ) )
2016-11-07 19:31:38 +01:00
return EXIT_SUCCESS ;
2014-01-05 12:37:51 +01:00
2018-03-09 05:12:43 +01:00
/// 6. Determine availability of data and blocks directory and parse bitcoin.conf
2014-03-11 08:32:07 +01:00
/// - Do not call GetDataDir(true) before this step finishes
2017-03-01 17:05:50 +01:00
if ( ! fs : : is_directory ( GetDataDir ( false ) ) )
2014-01-05 12:37:51 +01:00
{
2015-12-09 11:53:12 +01:00
QMessageBox : : critical ( 0 , QObject : : tr ( PACKAGE_NAME ) ,
2017-08-01 21:17:40 +02:00
QObject : : tr ( " Error: Specified data directory \" %1 \" does not exist. " ) . arg ( QString : : fromStdString ( gArgs . GetArg ( " -datadir " , " " ) ) ) ) ;
2016-11-07 19:31:38 +01:00
return EXIT_FAILURE ;
2014-01-05 12:37:51 +01:00
}
2018-04-29 01:40:51 +02:00
if ( ! node - > readConfigFiles ( error ) ) {
2015-12-09 11:53:12 +01:00
QMessageBox : : critical ( 0 , QObject : : tr ( PACKAGE_NAME ) ,
2018-04-29 01:40:51 +02:00
QObject : : tr ( " Error: Cannot parse configuration file: %1. " ) . arg ( QString : : fromStdString ( error ) ) ) ;
2016-11-07 19:31:38 +01:00
return EXIT_FAILURE ;
2014-04-07 10:10:01 +02:00
}
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 {
2018-03-29 07:00:00 +02:00
node - > selectParams ( gArgs . GetChainName ( ) ) ;
2015-05-25 09:00:17 +02:00
} 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 ( ) ) ) ;
2016-11-07 19:31:38 +01:00
return EXIT_FAILURE ;
2014-03-11 08:32:07 +01:00
}
# ifdef ENABLE_WALLET
// Parse URIs on command line -- this can affect Params()
2018-03-23 22:14:39 +01:00
PaymentServer : : ipcParseCommandLine ( * node , 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 ( ) )
2016-11-07 19:31:38 +01:00
exit ( EXIT_SUCCESS ) ;
2014-01-05 12:37:51 +01:00
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 ) ) ;
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 ) ;
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
2018-03-26 21:13:33 +02:00
app . createOptionsModel ( gArgs . GetBoolArg ( " -resetguisettings " , false ) ) ;
2012-02-17 03:09:41 +01:00
2012-05-06 19:40:58 +02:00
// Subscribe to global signals from core
2018-04-07 09:42:02 +02:00
std : : unique_ptr < interfaces : : Handler > handler = node - > handleInitMessage ( InitMessage ) ;
2012-05-06 19:40:58 +02:00
2017-08-01 21:17:40 +02:00
if ( gArgs . GetBoolArg ( " -splash " , DEFAULT_SPLASHSCREEN ) & & ! gArgs . GetBoolArg ( " -min " , false ) )
2014-10-09 11:04:49 +02:00
app . createSplashScreen ( networkStyle . data ( ) ) ;
2011-05-07 22:13:39 +02:00
2017-07-15 10:46:06 +02:00
int rv = EXIT_SUCCESS ;
2011-06-07 18:59:01 +02:00
try
{
2014-10-09 11:04:49 +02:00
app . createWindow ( networkStyle . data ( ) ) ;
2017-07-15 10:46:06 +02:00
// Perform base initialization before spinning up initialization/shutdown thread
// This is acceptable because this function only contains steps that are quick to execute,
// so the GUI thread won't be held up.
2017-04-17 19:55:43 +02:00
if ( node - > baseInitialize ( ) ) {
2017-07-15 10:46:06 +02:00
app . requestInitialize ( ) ;
2018-06-13 16:02:39 +02:00
# if defined(Q_OS_WIN)
2018-02-12 15:48:37 +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
2017-07-15 10:46:06 +02:00
app . exec ( ) ;
app . requestShutdown ( ) ;
app . exec ( ) ;
rv = app . getReturnValue ( ) ;
} else {
// A dialog with detailed error will have been shown by InitError()
rv = EXIT_FAILURE ;
}
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 " ) ;
2017-04-17 19:55:43 +02:00
app . handleRunawayException ( QString : : fromStdString ( node - > getWarnings ( " gui " ) ) ) ;
2011-05-22 17:19:43 +02:00
} catch ( . . . ) {
2017-08-07 07:36:37 +02:00
PrintExceptionContinue ( nullptr , " Runaway exception " ) ;
2017-04-17 19:55:43 +02:00
app . handleRunawayException ( QString : : fromStdString ( node - > getWarnings ( " gui " ) ) ) ;
2011-05-22 17:19:43 +02:00
}
2017-07-15 10:46:06 +02:00
return rv ;
2011-05-07 22:13:39 +02:00
}
2012-02-10 23:25:36 +01:00
# endif // BITCOIN_QT_TEST