2011-05-07 17:13:39 -03:00
/*
2012-03-21 04:56:38 -03:00
* W . J . van der Laan 2011 - 2012
2011-05-07 17:13:39 -03:00
*/
2013-01-23 17:51:02 -03:00
# include <QApplication>
2011-05-12 08:49:42 -04:00
# include "bitcoingui.h"
2011-05-22 11:19:43 -04:00
# include "clientmodel.h"
2011-06-30 12:05:29 -04:00
# include "walletmodel.h"
2011-07-29 08:36:35 -04:00
# include "optionsmodel.h"
2012-03-24 13:07:29 -03:00
# include "guiutil.h"
2012-04-13 12:10:50 -03:00
# include "guiconstants.h"
2011-05-22 11:19:43 -04:00
# include "init.h"
2013-03-07 00:16:05 -03:00
# include "util.h"
2012-04-16 09:56:45 -03:00
# include "ui_interface.h"
2013-02-11 20:52:30 -03:00
# include "paymentserver.h"
2013-04-14 06:35:37 -03:00
# include "splashscreen.h"
2011-05-07 17:13:39 -03:00
2011-06-05 10:03:29 -04:00
# include <QMessageBox>
2013-05-31 08:02:24 -04:00
# if QT_VERSION < 0x050000
2011-08-28 09:12:26 -03:00
# include <QTextCodec>
2013-05-31 08:02:24 -04:00
# endif
2011-06-23 16:35:30 -04:00
# include <QLocale>
2013-02-11 20:52:30 -03:00
# include <QTimer>
2011-06-23 16:35:30 -04:00
# include <QTranslator>
2011-10-07 08:21:45 -03:00
# include <QLibraryInfo>
2011-06-05 10:03:29 -04:00
2012-03-24 12:52:43 -03:00
# if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
# define _BITCOIN_QT_PLUGINS_INCLUDED
# define __INSURE__
# include <QtPlugin>
Q_IMPORT_PLUGIN ( qcncodecs )
Q_IMPORT_PLUGIN ( qjpcodecs )
Q_IMPORT_PLUGIN ( qtwcodecs )
Q_IMPORT_PLUGIN ( qkrcodecs )
Q_IMPORT_PLUGIN ( qtaccessiblewidgets )
# endif
2013-04-14 13:50:40 -03:00
// Declare meta types used for QMetaObject::invokeMethod
Q_DECLARE_METATYPE ( bool * )
2011-06-05 10:24:23 -04:00
// Need a global reference for the notifications to find the GUI
2012-03-24 14:48:18 -03:00
static BitcoinGUI * guiref ;
2013-04-14 06:35:37 -03:00
static SplashScreen * splashref ;
2011-06-05 10:03:29 -04:00
2013-02-16 13:58:45 -03:00
static bool ThreadSafeMessageBox ( const std : : string & message , const std : : string & caption , unsigned int style )
2011-06-05 10:03:29 -04:00
{
// Message from network thread
if ( guiref )
{
2012-05-19 03:35:26 -04:00
bool modal = ( style & CClientUIInterface : : MODAL ) ;
2013-02-16 13:58:45 -03:00
bool ret = false ;
2012-11-05 04:04:21 -03:00
// In case of modal message, use blocking connection to wait for user to click a button
QMetaObject : : invokeMethod ( guiref , " message " ,
2012-03-25 15:47:33 -03:00
modal ? GUIUtil : : blockingGUIThreadConnection ( ) : Qt : : QueuedConnection ,
2011-06-05 10:03:29 -04:00
Q_ARG ( QString , QString : : fromStdString ( caption ) ) ,
2012-03-25 15:47:33 -03:00
Q_ARG ( QString , QString : : fromStdString ( message ) ) ,
2013-02-16 13:58:45 -03:00
Q_ARG ( unsigned int , style ) ,
Q_ARG ( bool * , & ret ) ) ;
return ret ;
2011-06-05 10:03:29 -04:00
}
else
{
printf ( " %s: %s \n " , caption . c_str ( ) , message . c_str ( ) ) ;
fprintf ( stderr , " %s: %s \n " , caption . c_str ( ) , message . c_str ( ) ) ;
2013-02-16 13:58:45 -03:00
return false ;
2011-06-05 10:03:29 -04:00
}
}
2012-12-03 09:51:58 -03:00
static bool ThreadSafeAskFee ( int64 nFeeRequired )
2011-06-05 10:03:29 -04:00
{
2011-06-05 11:36:52 -04:00
if ( ! guiref )
return false ;
2013-04-25 21:11:27 -03:00
if ( nFeeRequired < CTransaction : : nMinTxFee | | nFeeRequired < = nTransactionFee | | fDaemon )
2011-06-05 11:36:52 -04:00
return true ;
2012-12-03 09:51:58 -03:00
2011-06-05 11:36:52 -04:00
bool payFee = false ;
2012-03-24 13:07:29 -03:00
QMetaObject : : invokeMethod ( guiref , " askFee " , GUIUtil : : blockingGUIThreadConnection ( ) ,
2011-06-05 11:36:52 -04:00
Q_ARG ( qint64 , nFeeRequired ) ,
Q_ARG ( bool * , & payFee ) ) ;
return payFee ;
2011-06-05 10:03:29 -04:00
}
2012-05-06 13:40:58 -04:00
static void InitMessage ( const std : : string & message )
2011-08-02 15:48:59 -04:00
{
if ( splashref )
{
2013-04-14 06:35:37 -03:00
splashref - > showMessage ( QString : : fromStdString ( message ) , Qt : : AlignBottom | Qt : : AlignHCenter , QColor ( 55 , 55 , 55 ) ) ;
2013-04-02 12:30:14 -03:00
qApp - > processEvents ( ) ;
2011-08-02 15:48:59 -04:00
}
2013-01-11 18:57:22 -03:00
printf ( " init message: %s \n " , message . c_str ( ) ) ;
2011-08-02 15:48:59 -04:00
}
2011-06-13 10:56:37 -04:00
/*
Translate string to current locale using Qt .
*/
2012-05-06 13:40:58 -04:00
static std : : string Translate ( const char * psz )
2011-06-13 10:56:37 -04:00
{
return QCoreApplication : : translate ( " bitcoin-core " , psz ) . toStdString ( ) ;
}
2012-04-14 04:41:05 -03:00
/* Handle runaway exceptions. Shows a message box with the problem and quits the program.
*/
static void handleRunawayException ( std : : exception * e )
{
PrintExceptionContinue ( e , " Runaway exception " ) ;
2012-07-22 23:59:02 -04:00
QMessageBox : : critical ( 0 , " Runaway exception " , BitcoinGUI : : tr ( " A fatal error occurred. Bitcoin can no longer continue safely and will quit. " ) + QString ( " \n \n " ) + QString : : fromStdString ( strMiscWarning ) ) ;
2012-04-14 04:41:05 -03:00
exit ( 1 ) ;
}
2012-02-10 19:25:36 -03:00
# ifndef BITCOIN_QT_TEST
2011-05-07 17:13:39 -03:00
int main ( int argc , char * argv [ ] )
{
2013-05-26 14:00:16 -04:00
fHaveGUI = true ;
2013-01-03 18:06:18 -03:00
// Command-line options take precedence:
ParseParameters ( argc , argv ) ;
2013-05-31 08:02:24 -04:00
# if QT_VERSION < 0x050000
2011-11-12 08:20:34 -03:00
// Internal string conversion is all UTF-8
2011-08-28 09:12:26 -03:00
QTextCodec : : setCodecForTr ( QTextCodec : : codecForName ( " UTF-8 " ) ) ;
QTextCodec : : setCodecForCStrings ( QTextCodec : : codecForTr ( ) ) ;
2013-05-31 08:02:24 -04:00
# endif
2011-08-28 09:12:26 -03:00
2011-06-18 08:25:24 -04:00
Q_INIT_RESOURCE ( bitcoin ) ;
2011-05-07 17:13:39 -03:00
QApplication app ( argc , argv ) ;
2011-06-23 16:35:30 -04:00
2013-04-14 13:50:40 -03:00
// Register meta types used for QMetaObject::invokeMethod
qRegisterMetaType < bool * > ( ) ;
2013-02-11 20:52:30 -03:00
// Do this early as we don't want to bother initializing if we are just calling IPC
// ... but do it after creating app, so QCoreApplication::arguments is initialized:
if ( PaymentServer : : ipcSendCommandLine ( ) )
exit ( 0 ) ;
PaymentServer * paymentServer = new PaymentServer ( & app ) ;
2012-04-13 12:10:50 -03:00
// Install global event filter that makes sure that long tooltips can be word-wrapped
app . installEventFilter ( new GUIUtil : : ToolTipToRichTextFilter ( TOOLTIP_WRAP_THRESHOLD , & app ) ) ;
2012-02-16 23:09:41 -03:00
// ... then bitcoin.conf:
2012-04-22 09:35:22 -03:00
if ( ! boost : : filesystem : : is_directory ( GetDataDir ( false ) ) )
2012-02-16 23:09:41 -03:00
{
2012-10-04 02:47:10 -03:00
// This message can not be translated, as translation is not initialized yet
// (which not yet possible because lang=XX can be overridden in bitcoin.conf in the data directory)
QMessageBox : : critical ( 0 , " Bitcoin " ,
QString ( " Error: Specified data directory \" %1 \" does not exist. " ) . arg ( QString : : fromStdString ( mapArgs [ " -datadir " ] ) ) ) ;
2012-02-16 23:09:41 -03:00
return 1 ;
}
2012-04-22 09:35:22 -03:00
ReadConfigFile ( mapArgs , mapMultiArgs ) ;
2012-02-16 23:09:41 -03:00
// Application identification (must be set before OptionsModel is initialized,
// as it is used to locate QSettings)
2013-04-14 14:45:27 -03:00
QApplication : : setOrganizationName ( " Bitcoin " ) ;
QApplication : : setOrganizationDomain ( " bitcoin.org " ) ;
2013-04-28 11:37:50 -04:00
if ( GetBoolArg ( " -testnet " , false ) ) // Separate UI settings for testnet
2013-04-14 14:45:27 -03:00
QApplication : : setApplicationName ( " Bitcoin-Qt-testnet " ) ;
2012-02-16 23:09:41 -03:00
else
2013-04-14 14:45:27 -03:00
QApplication : : setApplicationName ( " Bitcoin-Qt " ) ;
2012-02-16 23:09:41 -03:00
// ... then GUI settings:
OptionsModel optionsModel ;
2012-05-01 11:54:07 -04:00
// Get desired locale (e.g. "de_DE") from command line or use system locale
2012-02-17 14:44:39 -03:00
QString lang_territory = QString : : fromStdString ( GetArg ( " -lang " , QLocale : : system ( ) . name ( ) . toStdString ( ) ) ) ;
2011-10-23 08:37:39 -03:00
QString lang = lang_territory ;
2012-05-01 11:54:07 -04:00
// Convert to "de" only by truncating "_DE"
lang . truncate ( lang_territory . lastIndexOf ( ' _ ' ) ) ;
2012-02-17 14:44:39 -03:00
2011-10-23 08:37:39 -03:00
QTranslator qtTranslatorBase , qtTranslator , translatorBase , translator ;
2012-05-01 11:54:07 -04:00
// Load language files for configured locale:
// - First load the translator for the base language, without territory
// - Then load the more specific locale translator
2011-10-23 08:37:39 -03:00
2012-05-01 11:54:07 -04:00
// Load e.g. qt_de.qm
if ( qtTranslatorBase . load ( " qt_ " + lang , QLibraryInfo : : location ( QLibraryInfo : : TranslationsPath ) ) )
2011-10-23 08:37:39 -03:00
app . installTranslator ( & qtTranslatorBase ) ;
2012-05-01 11:54:07 -04:00
// Load e.g. qt_de_DE.qm
if ( qtTranslator . load ( " qt_ " + lang_territory , QLibraryInfo : : location ( QLibraryInfo : : TranslationsPath ) ) )
2011-10-07 08:21:45 -03:00
app . installTranslator ( & qtTranslator ) ;
2011-10-23 08:37:39 -03:00
2012-05-01 11:54:07 -04:00
// Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
if ( translatorBase . load ( lang , " :/translations/ " ) )
2011-10-23 08:37:39 -03:00
app . installTranslator ( & translatorBase ) ;
2012-05-01 11:54:07 -04:00
// Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
if ( translator . load ( lang_territory , " :/translations/ " ) )
2011-10-01 08:23:00 -03:00
app . installTranslator ( & translator ) ;
2011-06-23 16:35:30 -04:00
2012-05-06 13:40:58 -04:00
// Subscribe to global signals from core
uiInterface . ThreadSafeMessageBox . connect ( ThreadSafeMessageBox ) ;
uiInterface . ThreadSafeAskFee . connect ( ThreadSafeAskFee ) ;
uiInterface . InitMessage . connect ( InitMessage ) ;
uiInterface . Translate . connect ( Translate ) ;
2012-05-13 05:36:10 -04:00
// 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 " ) )
{
2012-05-20 09:49:17 -04:00
GUIUtil : : HelpMessageBox help ;
2012-06-14 09:06:23 -04:00
help . showOrPrint ( ) ;
2012-05-13 05:36:10 -04:00
return 1 ;
}
2013-04-14 06:35:37 -03:00
SplashScreen splash ( QPixmap ( ) , 0 ) ;
2013-04-28 11:37:50 -04:00
if ( GetBoolArg ( " -splash " , true ) & & ! GetBoolArg ( " -min " , false ) )
2012-02-24 23:54:18 -03:00
{
splash . show ( ) ;
splash . setAutoFillBackground ( true ) ;
splashref = & splash ;
}
2011-08-02 15:48:59 -04:00
app . processEvents ( ) ;
2011-06-05 08:19:57 -04:00
app . setQuitOnLastWindowClosed ( false ) ;
2011-05-07 17:13:39 -03:00
2011-06-07 12:59:01 -04:00
try
{
2013-05-03 09:18:28 -04:00
# ifndef Q_OS_MAC
2012-05-01 12:44:11 -04:00
// Regenerate startup link, to fix links to old versions
2013-05-03 09:18:28 -04:00
// OSX: makes no sense on mac and might also scan/mount external (and sleeping) volumes (can take up some secs)
2012-05-01 12:44:11 -04:00
if ( GUIUtil : : GetStartOnSystemStartup ( ) )
GUIUtil : : SetStartOnSystemStartup ( true ) ;
2013-05-03 09:18:28 -04:00
# endif
2012-05-01 12:44:11 -04:00
2013-03-07 00:16:05 -03:00
boost : : thread_group threadGroup ;
2013-03-23 19:14:12 -03:00
2013-05-19 14:20:06 -04:00
BitcoinGUI window ( GetBoolArg ( " -testnet " , false ) , 0 ) ;
2012-03-25 15:47:33 -03:00
guiref = & window ;
2013-03-23 19:14:12 -03:00
QTimer * pollShutdownTimer = new QTimer ( guiref ) ;
QObject : : connect ( pollShutdownTimer , SIGNAL ( timeout ( ) ) , guiref , SLOT ( detectShutdown ( ) ) ) ;
pollShutdownTimer - > start ( 200 ) ;
2013-03-07 00:16:05 -03:00
if ( AppInit2 ( threadGroup ) )
2011-05-22 11:19:43 -04:00
{
2011-07-03 14:53:56 -04:00
{
2012-03-25 15:47:33 -03:00
// Put this in a block, so that the Model objects are cleaned up before
// calling Shutdown().
2012-02-16 23:09:41 -03:00
optionsModel . Upgrade ( ) ; // Must be done after AppInit2
2012-02-24 23:54:18 -03:00
if ( splashref )
splash . finish ( & window ) ;
2012-02-16 23:09:41 -03:00
2011-07-29 08:36:35 -04:00
ClientModel clientModel ( & optionsModel ) ;
WalletModel walletModel ( pwalletMain , & optionsModel ) ;
2011-07-09 09:26:57 -04:00
2011-07-03 14:53:56 -04:00
window . setClientModel ( & clientModel ) ;
2013-03-22 14:32:49 -03:00
window . addWallet ( " ~Default " , & walletModel ) ;
window . setCurrentWallet ( " ~Default " ) ;
2011-07-03 14:53:56 -04:00
2011-12-03 13:57:30 -03:00
// If -min option passed, start window minimized.
2013-04-28 11:37:50 -04:00
if ( GetBoolArg ( " -min " , false ) )
2011-12-03 13:57:30 -03:00
{
window . showMinimized ( ) ;
}
else
{
window . show ( ) ;
}
2011-07-03 14:53:56 -04:00
2013-02-11 20:52:30 -03:00
// Now that initialization/startup is done, process any command-line
// bitcoin: URIs
QObject : : connect ( paymentServer , SIGNAL ( receivedURI ( QString ) ) , & window , SLOT ( handleURI ( QString ) ) ) ;
QTimer : : singleShot ( 100 , paymentServer , SLOT ( uiReady ( ) ) ) ;
2012-03-26 13:18:24 -03:00
2011-07-03 14:53:56 -04:00
app . exec ( ) ;
2012-05-06 02:14:19 -04:00
window . hide ( ) ;
2012-03-25 15:47:33 -03:00
window . setClientModel ( 0 ) ;
2013-03-22 14:32:49 -03:00
window . removeAllWallets ( ) ;
2011-07-03 14:53:56 -04:00
guiref = 0 ;
}
2012-07-25 23:25:26 -04:00
// Shutdown the core and its threads, but don't exit Bitcoin-Qt here
2013-03-07 00:16:05 -03:00
threadGroup . interrupt_all ( ) ;
threadGroup . join_all ( ) ;
2013-03-09 14:02:57 -03:00
Shutdown ( ) ;
2011-05-22 11:19:43 -04:00
}
else
{
2013-05-02 12:26:33 -04:00
threadGroup . interrupt_all ( ) ;
threadGroup . join_all ( ) ;
Shutdown ( ) ;
2011-05-22 11:19:43 -04:00
return 1 ;
}
} catch ( std : : exception & e ) {
2012-04-14 04:41:05 -03:00
handleRunawayException ( & e ) ;
2011-05-22 11:19:43 -04:00
} catch ( . . . ) {
2012-04-14 04:41:05 -03:00
handleRunawayException ( NULL ) ;
2011-05-22 11:19:43 -04:00
}
2011-07-03 14:53:56 -04:00
return 0 ;
2011-05-07 17:13:39 -03:00
}
2012-02-10 19:25:36 -03:00
# endif // BITCOIN_QT_TEST