2 * W.J. van der Laan 2011-2012
4 #include "bitcoingui.h"
5 #include "clientmodel.h"
6 #include "walletmodel.h"
7 #include "optionsmodel.h"
9 #include "guiconstants.h"
12 #include "ui_interface.h"
13 #include "qtipcserver.h"
16 #include <QApplication>
17 #include <QMessageBox>
18 #if QT_VERSION < 0x050000
22 #include <QTranslator>
23 #include <QSplashScreen>
24 #include <QLibraryInfo>
27 #if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
28 #define _BITCOIN_QT_PLUGINS_INCLUDED
31 Q_IMPORT_PLUGIN(qcncodecs)
32 Q_IMPORT_PLUGIN(qjpcodecs)
33 Q_IMPORT_PLUGIN(qtwcodecs)
34 Q_IMPORT_PLUGIN(qkrcodecs)
35 Q_IMPORT_PLUGIN(qtaccessiblewidgets)
38 // Need a global reference for the notifications to find the GUI
39 static BitcoinGUI *guiref;
40 static QSplashScreen *splashref;
42 /** Set up translations */
43 static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTranslator, QTranslator &translatorBase, QTranslator &translator)
46 // Get desired locale (e.g. "de_DE")
47 // 1) System default language
48 QString lang_territory = QLocale::system().name();
49 // 2) Language from QSettings
50 QString lang_territory_qsettings = settings.value("language", "").toString();
51 if(!lang_territory_qsettings.isEmpty())
52 lang_territory = lang_territory_qsettings;
53 // 3) -lang command line argument
54 lang_territory = QString::fromStdString(GetArg("-lang", lang_territory.toStdString()));
55 // Convert to "de" only by truncating "_DE"
56 QString lang = lang_territory;
57 lang.truncate(lang_territory.lastIndexOf('_'));
58 // Load language files for configured locale:
59 // - First load the translator for the base language, without territory
60 // - Then load the more specific locale translator
62 if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
63 QApplication::installTranslator(&qtTranslatorBase);
64 // Load e.g. qt_de_DE.qm
65 if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
66 QApplication::installTranslator(&qtTranslator);
67 // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
68 if (translatorBase.load(lang, ":/translations/"))
69 QApplication::installTranslator(&translatorBase);
70 // Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
71 if (translator.load(lang_territory, ":/translations/"))
72 QApplication::installTranslator(&translator);
75 static void ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
77 // Message from network thread
80 bool modal = (style & CClientUIInterface::MODAL);
81 // in case of modal message, use blocking connection to wait for user to click OK
82 QMetaObject::invokeMethod(guiref, "error",
83 modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
84 Q_ARG(QString, QString::fromStdString(caption)),
85 Q_ARG(QString, QString::fromStdString(message)),
90 printf("%s: %s\n", caption.c_str(), message.c_str());
91 fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
95 static bool ThreadSafeAskFee(int64_t nFeeRequired, const std::string& strCaption)
99 if(nFeeRequired < MIN_TX_FEE || nFeeRequired <= nTransactionFee || fDaemon)
103 QMetaObject::invokeMethod(guiref, "askFee", GUIUtil::blockingGUIThreadConnection(),
104 Q_ARG(qint64, nFeeRequired),
105 Q_ARG(bool*, &payFee));
110 static void ThreadSafeHandleURI(const std::string& strURI)
115 QMetaObject::invokeMethod(guiref, "handleURI", GUIUtil::blockingGUIThreadConnection(),
116 Q_ARG(QString, QString::fromStdString(strURI)));
119 static void InitMessage(const std::string &message)
123 splashref->showMessage(QString::fromStdString(message), Qt::AlignBottom|Qt::AlignHCenter, QColor(255,255,200));
124 QApplication::instance()->processEvents();
128 static void QueueShutdown()
130 QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
134 Translate string to current locale using Qt.
136 static std::string Translate(const char* psz)
138 return QCoreApplication::translate("bitcoin-core", psz).toStdString();
141 /* Handle runaway exceptions. Shows a message box with the problem and quits the program.
143 static void handleRunawayException(std::exception *e)
145 PrintExceptionContinue(e, "Runaway exception");
146 QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. NovaCoin can no longer continue safely and will quit.") + QString("\n\n") + QString::fromStdString(strMiscWarning));
150 #ifndef BITCOIN_QT_TEST
151 int main(int argc, char *argv[])
153 // Do this early as we don't want to bother initializing if we are just calling IPC
154 ipcScanRelay(argc, argv);
155 #if QT_VERSION < 0x050000
156 // Internal string conversion is all UTF-8
157 QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
158 QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());
160 Q_INIT_RESOURCE(bitcoin);
161 QApplication app(argc, argv);
163 // Application identification (must be set before OptionsModel is initialized,
164 // as it is used to locate QSettings)
165 app.setOrganizationName("NovaCoin");
166 app.setOrganizationDomain("novacoin.su");
167 if(GetBoolArg("-testnet")) // Separate UI settings for testnet
168 app.setApplicationName("NovaCoin-Qt-testnet");
170 app.setApplicationName("NovaCoin-Qt");
171 // Now that QSettings are accessible, initialize translations
172 QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
173 initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);
175 // Command-line options take precedence:
176 ParseParameters(argc, argv);
178 // User language is set up: pick a data directory
179 Intro::pickDataDirectory();
181 // Install global event filter that makes sure that long tooltips can be word-wrapped
182 app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
184 // ... then bitcoin.conf:
185 if (!boost::filesystem::is_directory(GetDataDir(false)))
187 QMessageBox::critical(0, "NovaCoin",
188 QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"])));
191 ReadConfigFile(mapArgs, mapMultiArgs);
193 // ... then GUI settings:
194 OptionsModel optionsModel;
196 // Subscribe to global signals from core
197 uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox);
198 uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee);
199 uiInterface.ThreadSafeHandleURI.connect(ThreadSafeHandleURI);
200 uiInterface.InitMessage.connect(InitMessage);
201 uiInterface.QueueShutdown.connect(QueueShutdown);
202 uiInterface.Translate.connect(Translate);
204 // Show help message immediately after parsing command-line options (for "-lang") and setting locale,
205 // but before showing splash screen.
206 if (mapArgs.count("-?") || mapArgs.count("--help"))
208 GUIUtil::HelpMessageBox help;
213 QSplashScreen splash(QPixmap(":/images/splash"), 0);
214 if (GetBoolArg("-splash", true) && !GetBoolArg("-min"))
217 splash.setAutoFillBackground(true);
223 app.setQuitOnLastWindowClosed(false);
227 // Regenerate startup link, to fix links to old versions
228 if (GUIUtil::GetStartOnSystemStartup())
229 GUIUtil::SetStartOnSystemStartup(true);
236 // Put this in a block, so that the Model objects are cleaned up before
237 // calling Shutdown().
240 splash.finish(&window);
242 ClientModel clientModel(&optionsModel);
243 WalletModel walletModel(pwalletMain, &optionsModel);
245 window.setClientModel(&clientModel);
246 window.setWalletModel(&walletModel);
248 // If -min option passed, start window minimized.
249 if(GetBoolArg("-min"))
251 window.showMinimized();
258 // Place this here as guiref has to be defined if we don't want to lose URIs
264 window.setClientModel(0);
265 window.setWalletModel(0);
268 // Shutdown the core and its threads, but don't exit Bitcoin-Qt here
275 } catch (std::exception& e) {
276 handleRunawayException(&e);
278 handleRunawayException(NULL);
282 #endif // BITCOIN_QT_TEST