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 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  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 "headers.h"
  9. #include "init.h"
  10. #include "qtipcserver.h"
  11. #include <QApplication>
  12. #include <QMessageBox>
  13. #include <QThread>
  14. #include <QTextCodec>
  15. #include <QLocale>
  16. #include <QTranslator>
  17. #include <QSplashScreen>
  18. #include <QLibraryInfo>
  19. #include <boost/interprocess/ipc/message_queue.hpp>
  20. // Need a global reference for the notifications to find the GUI
  21. BitcoinGUI *guiref;
  22. QSplashScreen *splashref;
  23. int MyMessageBox(const std::string& message, const std::string& caption, int style, wxWindow* parent, int x, int y)
  24. {
  25. // Message from AppInit2(), always in main thread before main window is constructed
  26. QMessageBox::critical(0, QString::fromStdString(caption),
  27. QString::fromStdString(message),
  28. QMessageBox::Ok, QMessageBox::Ok);
  29. return 4;
  30. }
  31. int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style, wxWindow* parent, int x, int y)
  32. {
  33. // Message from network thread
  34. if(guiref)
  35. {
  36. QMetaObject::invokeMethod(guiref, "error", Qt::QueuedConnection,
  37. Q_ARG(QString, QString::fromStdString(caption)),
  38. Q_ARG(QString, QString::fromStdString(message)));
  39. }
  40. else
  41. {
  42. printf("%s: %s\n", caption.c_str(), message.c_str());
  43. fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
  44. }
  45. return 4;
  46. }
  47. bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption, wxWindow* parent)
  48. {
  49. if(!guiref)
  50. return false;
  51. if(nFeeRequired < MIN_TX_FEE || nFeeRequired <= nTransactionFee || fDaemon)
  52. return true;
  53. bool payFee = false;
  54. // Call slot on GUI thread.
  55. // If called from another thread, use a blocking QueuedConnection.
  56. Qt::ConnectionType connectionType = Qt::DirectConnection;
  57. if(QThread::currentThread() != QCoreApplication::instance()->thread())
  58. {
  59. connectionType = Qt::BlockingQueuedConnection;
  60. }
  61. QMetaObject::invokeMethod(guiref, "askFee", connectionType,
  62. Q_ARG(qint64, nFeeRequired),
  63. Q_ARG(bool*, &payFee));
  64. return payFee;
  65. }
  66. void ThreadSafeHandleURL(const std::string& strURL)
  67. {
  68. if(!guiref)
  69. return;
  70. // Call slot on GUI thread.
  71. // If called from another thread, use a blocking QueuedConnection.
  72. Qt::ConnectionType connectionType = Qt::DirectConnection;
  73. if(QThread::currentThread() != QCoreApplication::instance()->thread())
  74. {
  75. connectionType = Qt::BlockingQueuedConnection;
  76. }
  77. QMetaObject::invokeMethod(guiref, "handleURL", connectionType,
  78. Q_ARG(QString, QString::fromStdString(strURL)));
  79. }
  80. void CalledSetStatusBar(const std::string& strText, int nField)
  81. {
  82. // Only used for built-in mining, which is disabled, simple ignore
  83. }
  84. void UIThreadCall(boost::function0<void> fn)
  85. {
  86. // Only used for built-in mining, which is disabled, simple ignore
  87. }
  88. void MainFrameRepaint()
  89. {
  90. if(guiref)
  91. QMetaObject::invokeMethod(guiref, "refreshStatusBar", Qt::QueuedConnection);
  92. }
  93. void InitMessage(const std::string &message)
  94. {
  95. if(splashref)
  96. {
  97. splashref->showMessage(QString::fromStdString(message), Qt::AlignBottom|Qt::AlignHCenter, QColor(255,255,200));
  98. QApplication::instance()->processEvents();
  99. }
  100. }
  101. /*
  102. Translate string to current locale using Qt.
  103. */
  104. std::string _(const char* psz)
  105. {
  106. return QCoreApplication::translate("bitcoin-core", psz).toStdString();
  107. }
  108. #ifndef BITCOIN_QT_TEST
  109. int main(int argc, char *argv[])
  110. {
  111. #if !defined(MAC_OSX) && !defined(WIN32)
  112. // TODO: implement qtipcserver.cpp for Mac and Windows
  113. // Do this early as we don't want to bother initializing if we are just calling IPC
  114. for (int i = 1; i < argc; i++)
  115. {
  116. if (strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0)
  117. {
  118. const char *strURL = argv[i];
  119. try {
  120. boost::interprocess::message_queue mq(boost::interprocess::open_only, "BitcoinURL");
  121. if(mq.try_send(strURL, strlen(strURL), 0))
  122. exit(0);
  123. else
  124. break;
  125. }
  126. catch (boost::interprocess::interprocess_exception &ex) {
  127. break;
  128. }
  129. }
  130. }
  131. #endif
  132. // Internal string conversion is all UTF-8
  133. QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
  134. QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());
  135. Q_INIT_RESOURCE(bitcoin);
  136. QApplication app(argc, argv);
  137. // Command-line options take precedence:
  138. ParseParameters(argc, argv);
  139. // ... then bitcoin.conf:
  140. if (!ReadConfigFile(mapArgs, mapMultiArgs))
  141. {
  142. fprintf(stderr, "Error: Specified directory does not exist\n");
  143. return 1;
  144. }
  145. // Application identification (must be set before OptionsModel is initialized,
  146. // as it is used to locate QSettings)
  147. app.setOrganizationName("Bitcoin");
  148. app.setOrganizationDomain("bitcoin.org");
  149. if(GetBoolArg("-testnet")) // Separate UI settings for testnet
  150. app.setApplicationName("Bitcoin-Qt-testnet");
  151. else
  152. app.setApplicationName("Bitcoin-Qt");
  153. // ... then GUI settings:
  154. OptionsModel optionsModel;
  155. // Get desired locale ("en_US") from command line or system locale
  156. QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString()));
  157. // Load language files for configured locale:
  158. // - First load the translator for the base language, without territory
  159. // - Then load the more specific locale translator
  160. QString lang = lang_territory;
  161. lang.truncate(lang_territory.lastIndexOf('_')); // "en"
  162. QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
  163. qtTranslatorBase.load(QLibraryInfo::location(QLibraryInfo::TranslationsPath) + "/qt_" + lang);
  164. if (!qtTranslatorBase.isEmpty())
  165. app.installTranslator(&qtTranslatorBase);
  166. qtTranslator.load(QLibraryInfo::location(QLibraryInfo::TranslationsPath) + "/qt_" + lang_territory);
  167. if (!qtTranslator.isEmpty())
  168. app.installTranslator(&qtTranslator);
  169. translatorBase.load(":/translations/"+lang);
  170. if (!translatorBase.isEmpty())
  171. app.installTranslator(&translatorBase);
  172. translator.load(":/translations/"+lang_territory);
  173. if (!translator.isEmpty())
  174. app.installTranslator(&translator);
  175. QSplashScreen splash(QPixmap(":/images/splash"), 0);
  176. if (GetBoolArg("-splash", true) && !GetBoolArg("-min"))
  177. {
  178. splash.show();
  179. splash.setAutoFillBackground(true);
  180. splashref = &splash;
  181. }
  182. app.processEvents();
  183. app.setQuitOnLastWindowClosed(false);
  184. try
  185. {
  186. if(AppInit2(argc, argv))
  187. {
  188. {
  189. // Put this in a block, so that BitcoinGUI is cleaned up properly before
  190. // calling Shutdown() in case of exceptions.
  191. optionsModel.Upgrade(); // Must be done after AppInit2
  192. BitcoinGUI window;
  193. if (splashref)
  194. splash.finish(&window);
  195. ClientModel clientModel(&optionsModel);
  196. WalletModel walletModel(pwalletMain, &optionsModel);
  197. guiref = &window;
  198. window.setClientModel(&clientModel);
  199. window.setWalletModel(&walletModel);
  200. // If -min option passed, start window minimized.
  201. if(GetBoolArg("-min"))
  202. {
  203. window.showMinimized();
  204. }
  205. else
  206. {
  207. window.show();
  208. }
  209. // Place this here as guiref has to be defined if we dont want to lose URLs
  210. ipcInit();
  211. #if !defined(MAC_OSX) && !defined(WIN32)
  212. // TODO: implement qtipcserver.cpp for Mac and Windows
  213. // Check for URL in argv
  214. for (int i = 1; i < argc; i++)
  215. {
  216. if (strlen(argv[i]) > 7 && strncasecmp(argv[i], "bitcoin:", 8) == 0)
  217. {
  218. const char *strURL = argv[i];
  219. try {
  220. boost::interprocess::message_queue mq(boost::interprocess::open_only, "BitcoinURL");
  221. mq.try_send(strURL, strlen(strURL), 0);
  222. }
  223. catch (boost::interprocess::interprocess_exception &ex) {
  224. }
  225. }
  226. }
  227. #endif
  228. app.exec();
  229. guiref = 0;
  230. }
  231. Shutdown(NULL);
  232. }
  233. else
  234. {
  235. return 1;
  236. }
  237. } catch (std::exception& e) {
  238. PrintException(&e, "Runaway exception");
  239. } catch (...) {
  240. PrintException(NULL, "Runaway exception");
  241. }
  242. return 0;
  243. }
  244. #endif // BITCOIN_QT_TEST