2011-05-07 22:13:39 +02:00
/*
2012-03-21 08:56:38 +01:00
* W . J . van der Laan 2011 - 2012
2011-05-07 22:13:39 +02:00
*/
2011-05-12 14:49:42 +02:00
# include "bitcoingui.h"
2011-05-22 17:19:43 +02:00
# include "clientmodel.h"
2011-06-30 18:05:29 +02:00
# include "walletmodel.h"
2011-07-29 14:36:35 +02:00
# include "optionsmodel.h"
2012-03-24 17:07:29 +01:00
# include "guiutil.h"
2012-04-13 17:10:50 +02:00
# include "guiconstants.h"
2011-06-26 19:23:24 +02:00
2011-05-22 17:19:43 +02:00
# include "init.h"
2012-04-16 14:56:45 +02:00
# include "ui_interface.h"
2011-12-24 05:27:12 +01:00
# include "qtipcserver.h"
2011-05-07 22:13:39 +02:00
# include <QApplication>
2011-06-05 16:03:29 +02:00
# include <QMessageBox>
2011-08-28 14:12:26 +02:00
# include <QTextCodec>
2011-06-23 22:35:30 +02:00
# include <QLocale>
# include <QTranslator>
2011-08-02 21:48:59 +02:00
# include <QSplashScreen>
2011-10-07 13:21:45 +02:00
# include <QLibraryInfo>
2011-06-05 16:03:29 +02:00
2011-12-24 05:27:12 +01:00
# include <boost/interprocess/ipc/message_queue.hpp>
2012-05-20 00:46:23 +02:00
# include <boost/algorithm/string/predicate.hpp>
2011-12-24 05:27:12 +01:00
2012-03-24 16:52:43 +01: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
2011-06-05 16:24:23 +02:00
// Need a global reference for the notifications to find the GUI
2012-03-24 18:48:18 +01:00
static BitcoinGUI * guiref ;
static QSplashScreen * splashref ;
2011-06-05 16:03:29 +02:00
2012-05-06 19:40:58 +02:00
static void ThreadSafeMessageBox ( const std : : string & message , const std : : string & caption , int style )
2011-06-05 16:03:29 +02:00
{
// Message from network thread
if ( guiref )
{
2012-05-19 09:35:26 +02:00
bool modal = ( style & CClientUIInterface : : MODAL ) ;
2012-03-25 20:47:33 +02:00
// in case of modal message, use blocking connection to wait for user to click OK
QMetaObject : : invokeMethod ( guiref , " error " ,
modal ? GUIUtil : : blockingGUIThreadConnection ( ) : Qt : : QueuedConnection ,
2011-06-05 16:03:29 +02:00
Q_ARG ( QString , QString : : fromStdString ( caption ) ) ,
2012-03-25 20:47:33 +02:00
Q_ARG ( QString , QString : : fromStdString ( message ) ) ,
Q_ARG ( bool , modal ) ) ;
2011-06-05 16:03:29 +02:00
}
else
{
printf ( " %s: %s \n " , caption . c_str ( ) , message . c_str ( ) ) ;
fprintf ( stderr , " %s: %s \n " , caption . c_str ( ) , message . c_str ( ) ) ;
}
}
2012-05-06 19:40:58 +02:00
static bool ThreadSafeAskFee ( int64 nFeeRequired , const std : : string & strCaption )
2011-06-05 16:03:29 +02:00
{
2011-06-05 17:36:52 +02:00
if ( ! guiref )
return false ;
if ( nFeeRequired < MIN_TX_FEE | | nFeeRequired < = nTransactionFee | | fDaemon )
return true ;
bool payFee = false ;
2012-03-24 17:07:29 +01:00
QMetaObject : : invokeMethod ( guiref , " askFee " , GUIUtil : : blockingGUIThreadConnection ( ) ,
2011-06-05 17:36:52 +02:00
Q_ARG ( qint64 , nFeeRequired ) ,
Q_ARG ( bool * , & payFee ) ) ;
return payFee ;
2011-06-05 16:03:29 +02:00
}
2012-05-06 19:40:58 +02:00
static void ThreadSafeHandleURI ( const std : : string & strURI )
2011-12-24 05:27:12 +01:00
{
if ( ! guiref )
return ;
2012-03-25 23:25:10 +02:00
QMetaObject : : invokeMethod ( guiref , " handleURI " , GUIUtil : : blockingGUIThreadConnection ( ) ,
Q_ARG ( QString , QString : : fromStdString ( strURI ) ) ) ;
2011-12-24 05:27:12 +01:00
}
2012-05-06 19:40:58 +02:00
static void InitMessage ( const std : : string & message )
2011-08-02 21:48:59 +02:00
{
if ( splashref )
{
2011-08-02 22:03:41 +02:00
splashref - > showMessage ( QString : : fromStdString ( message ) , Qt : : AlignBottom | Qt : : AlignHCenter , QColor ( 255 , 255 , 200 ) ) ;
2011-08-02 21:48:59 +02:00
QApplication : : instance ( ) - > processEvents ( ) ;
}
}
2012-05-06 19:40:58 +02:00
static void QueueShutdown ( )
2012-03-25 20:17:59 +02:00
{
QMetaObject : : invokeMethod ( QCoreApplication : : instance ( ) , " quit " , Qt : : QueuedConnection ) ;
}
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 ( ) ;
}
2012-04-14 09:41:05 +02: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 " ) ;
QMessageBox : : critical ( 0 , " Runaway exception " , BitcoinGUI : : tr ( " A fatal error occured. Bitcoin can no longer continue safely and will quit. " ) + QString ( " \n \n " ) + QString : : fromStdString ( strMiscWarning ) ) ;
exit ( 1 ) ;
}
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 [ ] )
{
Fix Qt build on OSX
Compiling boost::interprocess::message_queue against
boost 1.50 macports with -arch i386 (how releases are built,
for minimum download size and maximum compatibility) is failing:
src/qt/qtipcserver.cpp:37: error: no matching function for call to ‘boost::interprocess::message_queue_t<boost::interprocess::offset_ptr<void, int, long unsigned int, 0u> >::timed_receive(char (*)[257], long unsigned int, size_t&, unsigned int&, boost::posix_time::ptime&)’
This is probably a boost or macports bug, but since interprocess::message_queue
is only used for URI support, which isn't implemented on OSX anyway, I fixed
the build by #ifdef'ing out that code.
2012-07-09 17:03:38 +02:00
// TODO: implement URI support on the Mac.
# if !defined(MAC_OSX)
2011-12-24 05:27:12 +01:00
// Do this early as we don't want to bother initializing if we are just calling IPC
for ( int i = 1 ; i < argc ; i + + )
{
2012-05-20 00:46:23 +02:00
if ( boost : : algorithm : : istarts_with ( argv [ i ] , " bitcoin: " ) )
2011-12-24 05:27:12 +01:00
{
2012-03-25 23:25:10 +02:00
const char * strURI = argv [ i ] ;
2011-12-24 05:27:12 +01:00
try {
2012-03-25 23:25:10 +02:00
boost : : interprocess : : message_queue mq ( boost : : interprocess : : open_only , BITCOINURI_QUEUE_NAME ) ;
2012-07-06 13:45:38 +02:00
if ( mq . try_send ( strURI , strlen ( strURI ) , 0 ) )
// if URI could be sent to the message queue exit here
2011-12-24 05:27:12 +01:00
exit ( 0 ) ;
else
2012-07-06 13:45:38 +02:00
// if URI could not be sent to the message queue do a normal Bitcoin-Qt startup
2011-12-24 05:27:12 +01:00
break ;
}
catch ( boost : : interprocess : : interprocess_exception & ex ) {
2012-07-06 13:45:38 +02:00
// don't log the "file not found" exception, because that's normal for
// the first start of the first instance
if ( ex . get_error_code ( ) ! = boost : : interprocess : : not_found_error )
{
printf ( " main() - boost interprocess exception #%d: %s \n " , ex . get_error_code ( ) , ex . what ( ) ) ;
break ;
}
2011-12-24 05:27:12 +01:00
}
}
}
Fix Qt build on OSX
Compiling boost::interprocess::message_queue against
boost 1.50 macports with -arch i386 (how releases are built,
for minimum download size and maximum compatibility) is failing:
src/qt/qtipcserver.cpp:37: error: no matching function for call to ‘boost::interprocess::message_queue_t<boost::interprocess::offset_ptr<void, int, long unsigned int, 0u> >::timed_receive(char (*)[257], long unsigned int, size_t&, unsigned int&, boost::posix_time::ptime&)’
This is probably a boost or macports bug, but since interprocess::message_queue
is only used for URI support, which isn't implemented on OSX anyway, I fixed
the build by #ifdef'ing out that code.
2012-07-09 17:03:38 +02:00
# endif
2011-12-24 05:27:12 +01:00
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 ( ) ) ;
2011-06-18 14:25:24 +02:00
Q_INIT_RESOURCE ( bitcoin ) ;
2011-05-07 22:13:39 +02:00
QApplication app ( argc , argv ) ;
2011-06-23 22:35:30 +02:00
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 ) ) ;
2012-02-17 03:09:41 +01:00
// Command-line options take precedence:
2011-12-09 19:19:27 +01:00
ParseParameters ( argc , argv ) ;
2012-02-17 03:09:41 +01:00
// ... then bitcoin.conf:
2012-04-22 14:35:22 +02:00
if ( ! boost : : filesystem : : is_directory ( GetDataDir ( false ) ) )
2012-02-17 03:09:41 +01:00
{
fprintf ( stderr , " Error: Specified directory does not exist \n " ) ;
return 1 ;
}
2012-04-22 14:35:22 +02:00
ReadConfigFile ( mapArgs , mapMultiArgs ) ;
2012-02-17 03:09:41 +01:00
// Application identification (must be set before OptionsModel is initialized,
// as it is used to locate QSettings)
app . setOrganizationName ( " Bitcoin " ) ;
app . setOrganizationDomain ( " bitcoin.org " ) ;
if ( GetBoolArg ( " -testnet " ) ) // Separate UI settings for testnet
app . setApplicationName ( " Bitcoin-Qt-testnet " ) ;
else
app . setApplicationName ( " Bitcoin-Qt " ) ;
// ... then GUI settings:
OptionsModel optionsModel ;
2012-05-01 17:54:07 +02:00
// Get desired locale (e.g. "de_DE") from command line or use system locale
2012-02-17 18:44:39 +01:00
QString lang_territory = QString : : fromStdString ( GetArg ( " -lang " , QLocale : : system ( ) . name ( ) . toStdString ( ) ) ) ;
2011-10-23 13:37:39 +02:00
QString lang = lang_territory ;
2012-05-01 17:54:07 +02:00
// Convert to "de" only by truncating "_DE"
lang . truncate ( lang_territory . lastIndexOf ( ' _ ' ) ) ;
2012-02-17 18:44:39 +01:00
2011-10-23 13:37:39 +02:00
QTranslator qtTranslatorBase , qtTranslator , translatorBase , translator ;
2012-05-01 17:54:07 +02: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 13:37:39 +02:00
2012-05-01 17:54:07 +02:00
// Load e.g. qt_de.qm
if ( qtTranslatorBase . load ( " qt_ " + lang , QLibraryInfo : : location ( QLibraryInfo : : TranslationsPath ) ) )
2011-10-23 13:37:39 +02:00
app . installTranslator ( & qtTranslatorBase ) ;
2012-05-01 17:54:07 +02:00
// Load e.g. qt_de_DE.qm
if ( qtTranslator . load ( " qt_ " + lang_territory , QLibraryInfo : : location ( QLibraryInfo : : TranslationsPath ) ) )
2011-10-07 13:21:45 +02:00
app . installTranslator ( & qtTranslator ) ;
2011-10-23 13:37:39 +02:00
2012-05-01 17:54:07 +02:00
// Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
if ( translatorBase . load ( lang , " :/translations/ " ) )
2011-10-23 13:37:39 +02:00
app . installTranslator ( & translatorBase ) ;
2012-05-01 17:54:07 +02: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 13:23:00 +02:00
app . installTranslator ( & translator ) ;
2011-06-23 22:35:30 +02:00
2012-05-06 19:40:58 +02:00
// Subscribe to global signals from core
uiInterface . ThreadSafeMessageBox . connect ( ThreadSafeMessageBox ) ;
uiInterface . ThreadSafeAskFee . connect ( ThreadSafeAskFee ) ;
uiInterface . ThreadSafeHandleURI . connect ( ThreadSafeHandleURI ) ;
uiInterface . InitMessage . connect ( InitMessage ) ;
uiInterface . QueueShutdown . connect ( QueueShutdown ) ;
uiInterface . Translate . connect ( Translate ) ;
2012-05-13 11:36:10 +02: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 15:49:17 +02:00
GUIUtil : : HelpMessageBox help ;
2012-06-14 15:06:23 +02:00
help . showOrPrint ( ) ;
2012-05-13 11:36:10 +02:00
return 1 ;
}
2011-08-16 11:18:27 +02:00
QSplashScreen splash ( QPixmap ( " :/images/splash " ) , 0 ) ;
2012-02-25 03:54:18 +01:00
if ( GetBoolArg ( " -splash " , true ) & & ! GetBoolArg ( " -min " ) )
{
splash . show ( ) ;
splash . setAutoFillBackground ( true ) ;
splashref = & splash ;
}
2011-08-02 21:48:59 +02:00
app . processEvents ( ) ;
2011-06-05 14:19:57 +02:00
app . setQuitOnLastWindowClosed ( false ) ;
2011-05-07 22:13:39 +02:00
2011-06-07 18:59:01 +02:00
try
{
2012-05-01 18:44:11 +02:00
// Regenerate startup link, to fix links to old versions
if ( GUIUtil : : GetStartOnSystemStartup ( ) )
GUIUtil : : SetStartOnSystemStartup ( true ) ;
2012-03-25 20:47:33 +02:00
BitcoinGUI window ;
guiref = & window ;
2012-05-13 11:36:10 +02:00
if ( AppInit2 ( ) )
2011-05-22 17:19:43 +02:00
{
2011-07-03 20:53:56 +02:00
{
2012-03-25 20:47:33 +02:00
// Put this in a block, so that the Model objects are cleaned up before
// calling Shutdown().
2012-02-17 03:09:41 +01:00
optionsModel . Upgrade ( ) ; // Must be done after AppInit2
2012-02-25 03:54:18 +01:00
if ( splashref )
splash . finish ( & window ) ;
2012-02-17 03:09:41 +01:00
2011-07-29 14:36:35 +02:00
ClientModel clientModel ( & optionsModel ) ;
WalletModel walletModel ( pwalletMain , & optionsModel ) ;
2011-07-09 15:26:57 +02:00
2011-07-03 20:53:56 +02:00
window . setClientModel ( & clientModel ) ;
window . setWalletModel ( & walletModel ) ;
2011-12-03 17:57:30 +01:00
// If -min option passed, start window minimized.
if ( GetBoolArg ( " -min " ) )
{
window . showMinimized ( ) ;
}
else
{
window . show ( ) ;
}
Fix Qt build on OSX
Compiling boost::interprocess::message_queue against
boost 1.50 macports with -arch i386 (how releases are built,
for minimum download size and maximum compatibility) is failing:
src/qt/qtipcserver.cpp:37: error: no matching function for call to ‘boost::interprocess::message_queue_t<boost::interprocess::offset_ptr<void, int, long unsigned int, 0u> >::timed_receive(char (*)[257], long unsigned int, size_t&, unsigned int&, boost::posix_time::ptime&)’
This is probably a boost or macports bug, but since interprocess::message_queue
is only used for URI support, which isn't implemented on OSX anyway, I fixed
the build by #ifdef'ing out that code.
2012-07-09 17:03:38 +02:00
// TODO: implement URI support on the Mac.
# if !defined(MAC_OSX)
2011-07-03 20:53:56 +02:00
2012-03-25 23:25:10 +02:00
// Place this here as guiref has to be defined if we dont want to lose URIs
2011-12-24 05:27:12 +01:00
ipcInit ( ) ;
2012-03-26 18:18:24 +02:00
2012-03-25 23:25:10 +02:00
// Check for URI in argv
2011-12-24 05:27:12 +01:00
for ( int i = 1 ; i < argc ; i + + )
{
2012-05-20 00:46:23 +02:00
if ( boost : : algorithm : : istarts_with ( argv [ i ] , " bitcoin: " ) )
2011-12-24 05:27:12 +01:00
{
2012-03-25 23:25:10 +02:00
const char * strURI = argv [ i ] ;
2011-12-24 05:27:12 +01:00
try {
2012-03-25 23:25:10 +02:00
boost : : interprocess : : message_queue mq ( boost : : interprocess : : open_only , BITCOINURI_QUEUE_NAME ) ;
mq . try_send ( strURI , strlen ( strURI ) , 0 ) ;
2011-12-24 05:27:12 +01:00
}
catch ( boost : : interprocess : : interprocess_exception & ex ) {
2012-07-06 13:45:38 +02:00
printf ( " main() - boost interprocess exception #%d: %s \n " , ex . get_error_code ( ) , ex . what ( ) ) ;
break ;
2011-12-24 05:27:12 +01:00
}
}
}
Fix Qt build on OSX
Compiling boost::interprocess::message_queue against
boost 1.50 macports with -arch i386 (how releases are built,
for minimum download size and maximum compatibility) is failing:
src/qt/qtipcserver.cpp:37: error: no matching function for call to ‘boost::interprocess::message_queue_t<boost::interprocess::offset_ptr<void, int, long unsigned int, 0u> >::timed_receive(char (*)[257], long unsigned int, size_t&, unsigned int&, boost::posix_time::ptime&)’
This is probably a boost or macports bug, but since interprocess::message_queue
is only used for URI support, which isn't implemented on OSX anyway, I fixed
the build by #ifdef'ing out that code.
2012-07-09 17:03:38 +02:00
# endif
2011-07-03 20:53:56 +02:00
app . exec ( ) ;
2012-05-06 08:14:19 +02:00
window . hide ( ) ;
2012-03-25 20:47:33 +02:00
window . setClientModel ( 0 ) ;
window . setWalletModel ( 0 ) ;
2011-07-03 20:53:56 +02:00
guiref = 0 ;
}
2012-06-11 07:40:14 +02:00
// Shutdown the core and it's threads, but don't exit Bitcoin-Qt here
2011-05-22 17:19:43 +02:00
Shutdown ( NULL ) ;
}
else
{
return 1 ;
}
} catch ( std : : exception & e ) {
2012-04-14 09:41:05 +02:00
handleRunawayException ( & e ) ;
2011-05-22 17:19:43 +02:00
} catch ( . . . ) {
2012-04-14 09:41:05 +02:00
handleRunawayException ( NULL ) ;
2011-05-22 17:19:43 +02:00
}
2011-07-03 20:53:56 +02:00
return 0 ;
2011-05-07 22:13:39 +02:00
}
2012-02-10 23:25:36 +01:00
# endif // BITCOIN_QT_TEST