aboutsummaryrefslogtreecommitdiff
path: root/src/qt/bitcoin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qt/bitcoin.cpp')
-rw-r--r--src/qt/bitcoin.cpp294
1 files changed, 294 insertions, 0 deletions
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
new file mode 100644
index 000000000..1083f9bfe
--- /dev/null
+++ b/src/qt/bitcoin.cpp
@@ -0,0 +1,294 @@
+/*
+ * W.J. van der Laan 2011-2012
+ */
+
+#include <QApplication>
+
+#include "bitcoingui.h"
+#include "clientmodel.h"
+#include "walletmodel.h"
+#include "optionsmodel.h"
+#include "guiutil.h"
+#include "guiconstants.h"
+#include "init.h"
+#include "util.h"
+#include "ui_interface.h"
+#include "paymentserver.h"
+#include "splashscreen.h"
+
+#include <QMessageBox>
+#include <QTextCodec>
+#include <QLocale>
+#include <QTimer>
+#include <QTranslator>
+#include <QLibraryInfo>
+
+#ifdef Q_OS_MAC
+#include "macdockiconhandler.h"
+#endif
+
+#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
+
+// Declare meta types used for QMetaObject::invokeMethod
+Q_DECLARE_METATYPE(bool*)
+
+// Need a global reference for the notifications to find the GUI
+static BitcoinGUI *guiref;
+static SplashScreen *splashref;
+
+static bool ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style)
+{
+ // Message from network thread
+ if(guiref)
+ {
+ bool modal = (style & CClientUIInterface::MODAL);
+ bool ret = false;
+ // In case of modal message, use blocking connection to wait for user to click a button
+ QMetaObject::invokeMethod(guiref, "message",
+ modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
+ Q_ARG(QString, QString::fromStdString(caption)),
+ Q_ARG(QString, QString::fromStdString(message)),
+ Q_ARG(unsigned int, style),
+ Q_ARG(bool*, &ret));
+ return ret;
+ }
+ else
+ {
+ printf("%s: %s\n", caption.c_str(), message.c_str());
+ fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
+ return false;
+ }
+}
+
+static bool ThreadSafeAskFee(int64 nFeeRequired)
+{
+ if(!guiref)
+ return false;
+ if(nFeeRequired < MIN_TX_FEE || nFeeRequired <= nTransactionFee || fDaemon)
+ return true;
+
+ bool payFee = false;
+
+ QMetaObject::invokeMethod(guiref, "askFee", GUIUtil::blockingGUIThreadConnection(),
+ Q_ARG(qint64, nFeeRequired),
+ Q_ARG(bool*, &payFee));
+
+ return payFee;
+}
+
+static void InitMessage(const std::string &message)
+{
+ if(splashref)
+ {
+ splashref->showMessage(QString::fromStdString(message), Qt::AlignBottom|Qt::AlignHCenter, QColor(55,55,55));
+ qApp->processEvents();
+ }
+ printf("init message: %s\n", message.c_str());
+}
+
+/*
+ Translate string to current locale using Qt.
+ */
+static std::string Translate(const char* psz)
+{
+ return QCoreApplication::translate("bitcoin-core", psz).toStdString();
+}
+
+/* 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 occurred. Bitcoin can no longer continue safely and will quit.") + QString("\n\n") + QString::fromStdString(strMiscWarning));
+ exit(1);
+}
+
+#ifndef BITCOIN_QT_TEST
+int main(int argc, char *argv[])
+{
+ // Command-line options take precedence:
+ ParseParameters(argc, argv);
+
+ // Internal string conversion is all UTF-8
+ QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
+ QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());
+
+ Q_INIT_RESOURCE(bitcoin);
+ QApplication app(argc, argv);
+
+ // Register meta types used for QMetaObject::invokeMethod
+ qRegisterMetaType< bool* >();
+
+ // 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);
+
+ // Install global event filter that makes sure that long tooltips can be word-wrapped
+ app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
+
+ // ... then bitcoin.conf:
+ if (!boost::filesystem::is_directory(GetDataDir(false)))
+ {
+ // 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"])));
+ return 1;
+ }
+ ReadConfigFile(mapArgs, mapMultiArgs);
+
+ // Application identification (must be set before OptionsModel is initialized,
+ // as it is used to locate QSettings)
+ QApplication::setOrganizationName("Bitcoin");
+ QApplication::setOrganizationDomain("bitcoin.org");
+ if(GetBoolArg("-testnet")) // Separate UI settings for testnet
+ QApplication::setApplicationName("Bitcoin-Qt-testnet");
+ else
+ QApplication::setApplicationName("Bitcoin-Qt");
+
+ // ... then GUI settings:
+ OptionsModel optionsModel;
+
+ // Get desired locale (e.g. "de_DE") from command line or use system locale
+ QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString()));
+ QString lang = lang_territory;
+ // Convert to "de" only by truncating "_DE"
+ lang.truncate(lang_territory.lastIndexOf('_'));
+
+ QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
+ // 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)))
+ app.installTranslator(&qtTranslatorBase);
+
+ // Load e.g. qt_de_DE.qm
+ if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
+ app.installTranslator(&qtTranslator);
+
+ // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
+ if (translatorBase.load(lang, ":/translations/"))
+ app.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/"))
+ app.installTranslator(&translator);
+
+ // Subscribe to global signals from core
+ uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox);
+ uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee);
+ uiInterface.InitMessage.connect(InitMessage);
+ uiInterface.Translate.connect(Translate);
+
+ // 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"))
+ {
+ GUIUtil::HelpMessageBox help;
+ help.showOrPrint();
+ return 1;
+ }
+
+#ifdef Q_OS_MAC
+ // on mac, also change the icon now because it would look strange to have a testnet splash (green) and a std app icon (orange)
+ if(GetBoolArg("-testnet")) {
+ MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
+ }
+#endif
+
+ SplashScreen splash(QPixmap(), 0);
+ if (GetBoolArg("-splash", true) && !GetBoolArg("-min"))
+ {
+ splash.show();
+ splash.setAutoFillBackground(true);
+ splashref = &splash;
+ }
+
+ app.processEvents();
+ app.setQuitOnLastWindowClosed(false);
+
+ try
+ {
+ // Regenerate startup link, to fix links to old versions
+ if (GUIUtil::GetStartOnSystemStartup())
+ GUIUtil::SetStartOnSystemStartup(true);
+
+ boost::thread_group threadGroup;
+
+ BitcoinGUI window;
+ guiref = &window;
+
+ QTimer* pollShutdownTimer = new QTimer(guiref);
+ QObject::connect(pollShutdownTimer, SIGNAL(timeout()), guiref, SLOT(detectShutdown()));
+ pollShutdownTimer->start(200);
+
+ if(AppInit2(threadGroup))
+ {
+ {
+ // Put this in a block, so that the Model objects are cleaned up before
+ // calling Shutdown().
+
+ optionsModel.Upgrade(); // Must be done after AppInit2
+
+ if (splashref)
+ splash.finish(&window);
+
+ ClientModel clientModel(&optionsModel);
+ WalletModel walletModel(pwalletMain, &optionsModel);
+
+ window.setClientModel(&clientModel);
+ window.addWallet("~Default", &walletModel);
+ window.setCurrentWallet("~Default");
+
+ // If -min option passed, start window minimized.
+ if(GetBoolArg("-min"))
+ {
+ window.showMinimized();
+ }
+ else
+ {
+ window.show();
+ }
+
+ // 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()));
+
+ app.exec();
+
+ window.hide();
+ window.setClientModel(0);
+ window.removeAllWallets();
+ guiref = 0;
+ }
+ // Shutdown the core and its threads, but don't exit Bitcoin-Qt here
+ threadGroup.interrupt_all();
+ threadGroup.join_all();
+ Shutdown();
+ }
+ else
+ {
+ return 1;
+ }
+ } catch (std::exception& e) {
+ handleRunawayException(&e);
+ } catch (...) {
+ handleRunawayException(NULL);
+ }
+ return 0;
+}
+#endif // BITCOIN_QT_TEST