You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bitcoin.cpp 9.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. * W.J. van der Laan 2011-2012
  3. */
  4. #include "bitcoingui.h"
  5. #include "clientmodel.h"
  6. #include "walletmodel.h"
  7. #include "optionsmodel.h"
  8. #include "guiutil.h"
  9. #include "guiconstants.h"
  10. #include "init.h"
  11. #include "ui_interface.h"
  12. #include "qtipcserver.h"
  13. #include <QApplication>
  14. #include <QMessageBox>
  15. #include <QTextCodec>
  16. #include <QLocale>
  17. #include <QTranslator>
  18. #include <QSplashScreen>
  19. #include <QLibraryInfo>
  20. #include <boost/interprocess/ipc/message_queue.hpp>
  21. #include <boost/algorithm/string/predicate.hpp>
  22. #if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
  23. #define _BITCOIN_QT_PLUGINS_INCLUDED
  24. #define __INSURE__
  25. #include <QtPlugin>
  26. Q_IMPORT_PLUGIN(qcncodecs)
  27. Q_IMPORT_PLUGIN(qjpcodecs)
  28. Q_IMPORT_PLUGIN(qtwcodecs)
  29. Q_IMPORT_PLUGIN(qkrcodecs)
  30. Q_IMPORT_PLUGIN(qtaccessiblewidgets)
  31. #endif
  32. // Need a global reference for the notifications to find the GUI
  33. static BitcoinGUI *guiref;
  34. static QSplashScreen *splashref;
  35. static void ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
  36. {
  37. // Message from network thread
  38. if(guiref)
  39. {
  40. bool modal = (style & CClientUIInterface::MODAL);
  41. // in case of modal message, use blocking connection to wait for user to click OK
  42. QMetaObject::invokeMethod(guiref, "error",
  43. modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
  44. Q_ARG(QString, QString::fromStdString(caption)),
  45. Q_ARG(QString, QString::fromStdString(message)),
  46. Q_ARG(bool, modal));
  47. }
  48. else
  49. {
  50. printf("%s: %s\n", caption.c_str(), message.c_str());
  51. fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
  52. }
  53. }
  54. static bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
  55. {
  56. if(!guiref)
  57. return false;
  58. if(nFeeRequired < MIN_TX_FEE || nFeeRequired <= nTransactionFee || fDaemon)
  59. return true;
  60. bool payFee = false;
  61. QMetaObject::invokeMethod(guiref, "askFee", GUIUtil::blockingGUIThreadConnection(),
  62. Q_ARG(qint64, nFeeRequired),
  63. Q_ARG(bool*, &payFee));
  64. return payFee;
  65. }
  66. static void ThreadSafeHandleURI(const std::string& strURI)
  67. {
  68. if(!guiref)
  69. return;
  70. QMetaObject::invokeMethod(guiref, "handleURI", GUIUtil::blockingGUIThreadConnection(),
  71. Q_ARG(QString, QString::fromStdString(strURI)));
  72. }
  73. static void InitMessage(const std::string &message)
  74. {
  75. if(splashref)
  76. {
  77. splashref->showMessage(QString::fromStdString(message), Qt::AlignBottom|Qt::AlignHCenter, QColor(255,255,200));
  78. QApplication::instance()->processEvents();
  79. }
  80. }
  81. static void QueueShutdown()
  82. {
  83. QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
  84. }
  85. /*
  86. Translate string to current locale using Qt.
  87. */
  88. static std::string Translate(const char* psz)
  89. {
  90. return QCoreApplication::translate("bitcoin-core", psz).toStdString();
  91. }
  92. /* Handle runaway exceptions. Shows a message box with the problem and quits the program.
  93. */
  94. static void handleRunawayException(std::exception *e)
  95. {
  96. PrintExceptionContinue(e, "Runaway exception");
  97. 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));
  98. exit(1);
  99. }
  100. #ifndef BITCOIN_QT_TEST
  101. int main(int argc, char *argv[])
  102. {
  103. // Do this early as we don't want to bother initializing if we are just calling IPC
  104. for (int i = 1; i < argc; i++)
  105. {
  106. if (boost::algorithm::istarts_with(argv[i], "bitcoin:"))
  107. {
  108. const char *strURI = argv[i];
  109. try {
  110. boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME);
  111. if(mq.try_send(strURI, strlen(strURI), 0))
  112. exit(0);
  113. else
  114. break;
  115. }
  116. catch (boost::interprocess::interprocess_exception &ex) {
  117. break;
  118. }
  119. }
  120. }
  121. // Internal string conversion is all UTF-8
  122. QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
  123. QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());
  124. Q_INIT_RESOURCE(bitcoin);
  125. QApplication app(argc, argv);
  126. // Install global event filter that makes sure that long tooltips can be word-wrapped
  127. app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
  128. // Command-line options take precedence:
  129. ParseParameters(argc, argv);
  130. // ... then bitcoin.conf:
  131. if (!boost::filesystem::is_directory(GetDataDir(false)))
  132. {
  133. fprintf(stderr, "Error: Specified directory does not exist\n");
  134. return 1;
  135. }
  136. ReadConfigFile(mapArgs, mapMultiArgs);
  137. // Application identification (must be set before OptionsModel is initialized,
  138. // as it is used to locate QSettings)
  139. app.setOrganizationName("Bitcoin");
  140. app.setOrganizationDomain("bitcoin.org");
  141. if(GetBoolArg("-testnet")) // Separate UI settings for testnet
  142. app.setApplicationName("Bitcoin-Qt-testnet");
  143. else
  144. app.setApplicationName("Bitcoin-Qt");
  145. // ... then GUI settings:
  146. OptionsModel optionsModel;
  147. // Get desired locale (e.g. "de_DE") from command line or use system locale
  148. QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString()));
  149. QString lang = lang_territory;
  150. // Convert to "de" only by truncating "_DE"
  151. lang.truncate(lang_territory.lastIndexOf('_'));
  152. QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
  153. // Load language files for configured locale:
  154. // - First load the translator for the base language, without territory
  155. // - Then load the more specific locale translator
  156. // Load e.g. qt_de.qm
  157. if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
  158. app.installTranslator(&qtTranslatorBase);
  159. // Load e.g. qt_de_DE.qm
  160. if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
  161. app.installTranslator(&qtTranslator);
  162. // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
  163. if (translatorBase.load(lang, ":/translations/"))
  164. app.installTranslator(&translatorBase);
  165. // Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
  166. if (translator.load(lang_territory, ":/translations/"))
  167. app.installTranslator(&translator);
  168. // Subscribe to global signals from core
  169. uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox);
  170. uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee);
  171. uiInterface.ThreadSafeHandleURI.connect(ThreadSafeHandleURI);
  172. uiInterface.InitMessage.connect(InitMessage);
  173. uiInterface.QueueShutdown.connect(QueueShutdown);
  174. uiInterface.Translate.connect(Translate);
  175. // Show help message immediately after parsing command-line options (for "-lang") and setting locale,
  176. // but before showing splash screen.
  177. if (mapArgs.count("-?") || mapArgs.count("--help"))
  178. {
  179. GUIUtil::HelpMessageBox help;
  180. help.showOrPrint();
  181. return 1;
  182. }
  183. QSplashScreen splash(QPixmap(":/images/splash"), 0);
  184. if (GetBoolArg("-splash", true) && !GetBoolArg("-min"))
  185. {
  186. splash.show();
  187. splash.setAutoFillBackground(true);
  188. splashref = &splash;
  189. }
  190. app.processEvents();
  191. app.setQuitOnLastWindowClosed(false);
  192. try
  193. {
  194. // Regenerate startup link, to fix links to old versions
  195. if (GUIUtil::GetStartOnSystemStartup())
  196. GUIUtil::SetStartOnSystemStartup(true);
  197. BitcoinGUI window;
  198. guiref = &window;
  199. if(AppInit2())
  200. {
  201. {
  202. // Put this in a block, so that the Model objects are cleaned up before
  203. // calling Shutdown().
  204. optionsModel.Upgrade(); // Must be done after AppInit2
  205. if (splashref)
  206. splash.finish(&window);
  207. ClientModel clientModel(&optionsModel);
  208. WalletModel walletModel(pwalletMain, &optionsModel);
  209. window.setClientModel(&clientModel);
  210. window.setWalletModel(&walletModel);
  211. // If -min option passed, start window minimized.
  212. if(GetBoolArg("-min"))
  213. {
  214. window.showMinimized();
  215. }
  216. else
  217. {
  218. window.show();
  219. }
  220. // Place this here as guiref has to be defined if we dont want to lose URIs
  221. ipcInit();
  222. // Check for URI in argv
  223. for (int i = 1; i < argc; i++)
  224. {
  225. if (boost::algorithm::istarts_with(argv[i], "bitcoin:"))
  226. {
  227. const char *strURI = argv[i];
  228. try {
  229. boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME);
  230. mq.try_send(strURI, strlen(strURI), 0);
  231. }
  232. catch (boost::interprocess::interprocess_exception &ex) {
  233. }
  234. }
  235. }
  236. app.exec();
  237. window.hide();
  238. window.setClientModel(0);
  239. window.setWalletModel(0);
  240. guiref = 0;
  241. }
  242. // Shutdown the core and it's threads, but don't exit Bitcoin-Qt here
  243. Shutdown(NULL);
  244. }
  245. else
  246. {
  247. return 1;
  248. }
  249. } catch (std::exception& e) {
  250. handleRunawayException(&e);
  251. } catch (...) {
  252. handleRunawayException(NULL);
  253. }
  254. return 0;
  255. }
  256. #endif // BITCOIN_QT_TEST