7#include <chainparams.h>
32#include <validation.h>
41#include <QLibraryInfo>
49#include <boost/signals2/connection.hpp>
53#if defined(QT_STATICPLUGIN)
55#if defined(QT_QPA_PLATFORM_XCB)
56Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
57#elif defined(QT_QPA_PLATFORM_WINDOWS)
58Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
59#elif defined(QT_QPA_PLATFORM_COCOA)
60Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
61Q_IMPORT_PLUGIN(QMacStylePlugin);
66Q_DECLARE_METATYPE(
bool *)
73Q_DECLARE_METATYPE(
Config *)
80 qRegisterMetaType<bool *>();
81 qRegisterMetaType<SynchronizationState>();
82 qRegisterMetaType<SyncType>();
84 qRegisterMetaType<WalletModel *>();
86 qRegisterMetaType<Amount>();
89 qRegisterMetaType<size_t>(
"size_t");
91 qRegisterMetaType<std::function<void()>>(
"std::function<void()>");
92 qRegisterMetaType<QMessageBox::Icon>(
"QMessageBox::Icon");
93 qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>(
94 "interfaces::BlockAndHeaderTipInfo");
102 qRegisterMetaType<Config *>();
109 QString lang_territory = QLocale::system().name();
111 QString lang_territory_qsettings =
112 settings.value(
"language",
"").toString();
113 if (!lang_territory_qsettings.isEmpty()) {
114 lang_territory = lang_territory_qsettings;
117 lang_territory = QString::fromStdString(
118 gArgs.
GetArg(
"-lang", lang_territory.toStdString()));
119 return lang_territory;
124 QTranslator &qtTranslator,
125 QTranslator &translatorBase,
126 QTranslator &translator) {
128 QApplication::removeTranslator(&qtTranslatorBase);
129 QApplication::removeTranslator(&qtTranslator);
130 QApplication::removeTranslator(&translatorBase);
131 QApplication::removeTranslator(&translator);
138 QString lang = lang_territory;
139 lang.truncate(lang_territory.lastIndexOf(
'_'));
146 if (qtTranslatorBase.load(
148 QLibraryInfo::location(QLibraryInfo::TranslationsPath))) {
149 QApplication::installTranslator(&qtTranslatorBase);
153 if (qtTranslator.load(
154 "qt_" + lang_territory,
155 QLibraryInfo::location(QLibraryInfo::TranslationsPath))) {
156 QApplication::installTranslator(&qtTranslator);
161 if (translatorBase.load(lang,
":/translations/")) {
162 QApplication::installTranslator(&translatorBase);
167 if (translator.load(lang_territory,
":/translations/")) {
168 QApplication::installTranslator(&translator);
172static std::string
JoinErrors(
const std::vector<std::string> &errors) {
173 return Join(errors,
"\n",
174 [](
const std::string &
error) {
return "- " +
error; });
184 std::vector<std::string> errors;
190 QMessageBox messagebox(
191 QMessageBox::Critical, PACKAGE_NAME,
193 QMessageBox::Reset | QMessageBox::Abort);
196 messagebox.setInformativeText(
197 QObject::tr(
"Do you want to reset settings to default values, or "
198 "to abort without making changes?"));
199 messagebox.setDetailedText(QString::fromStdString(
JoinErrors(errors)));
200 messagebox.setTextFormat(Qt::PlainText);
201 messagebox.setDefaultButton(QMessageBox::Reset);
202 switch (messagebox.exec()) {
203 case QMessageBox::Reset:
205 case QMessageBox::Abort:
218 QMessageBox messagebox(
219 QMessageBox::Critical, PACKAGE_NAME,
226 messagebox.setInformativeText(
227 QObject::tr(
"A fatal error occurred. Check that settings file is "
228 "writable, or try running with -nosettings."));
229 messagebox.setDetailedText(QString::fromStdString(
JoinErrors(errors)));
230 messagebox.setTextFormat(Qt::PlainText);
231 messagebox.setDefaultButton(QMessageBox::Ok);
240 const QString &msg) {
242 if (type == QtDebugMsg) {
245 LogPrintf(
"GUI: %s\n", msg.toStdString());
261 qDebug() << __func__ <<
": Running initialization in thread";
264 *httpRPCRequestProcessor, &tip_info);
266 }
catch (
const std::exception &e) {
275 qDebug() << __func__ <<
": Running Shutdown in thread";
277 qDebug() << __func__ <<
": Shutdown finished";
279 }
catch (
const std::exception &e) {
290 : QApplication(
qt_argc, const_cast<char **>(&
qt_argv)), coreThread(nullptr),
291 optionsModel(nullptr), clientModel(nullptr), window(nullptr),
292 pollShutdownTimer(nullptr), returnValue(0), platformStyle(nullptr) {
295 setQuitOnLastWindowClosed(
false);
302 std::string platformName;
315 qDebug() << __func__ <<
": Stopping thread";
318 qDebug() << __func__ <<
": Stopped thread";
328void BitcoinApplication::createPaymentServer() {
412 connect(
coreThread, &QThread::finished, executor, &QObject::deleteLater);
435 qDebug() << __func__ <<
": Requesting initialize";
449 qDebug() << __func__ <<
": Requesting shutdown";
472 qDebug() << __func__ <<
": Initialization result: " << success;
473 returnValue = success ? EXIT_SUCCESS : EXIT_FAILURE;
488 m_wallet_controller =
490 window->setWalletController(m_wallet_controller);
494 PaymentServer::LoadRootCAs();
496 paymentServer, &PaymentServer::fetchPaymentACK);
520 &BitcoinGUI::handlePaymentRequest);
524 [
this](
const QString &title,
const QString &message,
525 unsigned int style) {
541 QMessageBox::critical(
542 nullptr,
"Runaway exception",
543 BitcoinGUI::tr(
"A fatal error occurred. %1 can no longer continue "
544 "safely and will quit.")
546 QString(
"<br><br>") + message);
547 ::exit(EXIT_FAILURE);
559#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
561 "-allowselfsignedrootcertificates",
562 strprintf(
"Allow self signed root certificates (default: %d)",
566 argsman.
AddArg(
"-choosedatadir",
567 strprintf(
"Choose data directory on startup (default: %d)",
572 "Set language, for example \"de_DE\" (default: system locale)",
577 "-rootcertificates=<file>",
578 "Set SSL root certificates for payment request (default: -system-)",
581 strprintf(
"Show splash screen on startup (default: %d)",
584 argsman.
AddArg(
"-resetguisettings",
"Reset all settings changed in the GUI",
586 argsman.
AddArg(
"-uiplatform",
587 strprintf(
"Select platform to customize UI for (one of "
588 "windows, macosx, other; default: %s)",
596 common::WinCmdLineArgs winArgs;
597 std::tie(argc, argv) = winArgs.get();
603 std::unique_ptr<interfaces::Node>
node =
607 boost::signals2::scoped_connection handler_message_box =
609 boost::signals2::scoped_connection handler_question =
611 boost::signals2::scoped_connection handler_init_message =
619 Q_INIT_RESOURCE(bitcoin);
620 Q_INIT_RESOURCE(bitcoin_locale);
623 QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
624 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
639 QMessageBox::critical(
640 nullptr, PACKAGE_NAME,
643 QString::fromStdString(
"Error parsing command line arguments: %1.")
644 .arg(QString::fromStdString(
error)));
661 QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
675 app.installEventFilter(
680 bool did_show_intro =
false;
693 Untranslated(
"Specified data directory \"%s\" does not exist.\n"),
695 QMessageBox::critical(
696 nullptr, PACKAGE_NAME,
698 "Error: Specified data directory \"%1\" does not exist.")
699 .arg(QString::fromStdString(
gArgs.
GetArg(
"-datadir",
""))));
705 QMessageBox::critical(
706 nullptr, PACKAGE_NAME,
707 QObject::tr(
"Error: Cannot parse configuration file: %1.")
708 .arg(QString::fromStdString(
error)));
724 }
catch (std::exception &e) {
726 QMessageBox::critical(
nullptr, PACKAGE_NAME,
727 QObject::tr(
"Error: %1").arg(e.what()));
738 QScopedPointer<const NetworkStyle> networkStyle(
740 assert(!networkStyle.isNull());
742 QApplication::setApplicationName(networkStyle->getAppName());
765 app.createPaymentServer();
776 qApp->installNativeEventFilter(
new WinShutdownMonitor());
786 if (did_show_intro) {
802 std::any context{&node_context};
817 WinShutdownMonitor::registerShutdownBlockReason(
818 QObject::tr(
"%1 didn't yet exit safely...").arg(PACKAGE_NAME),
825 }
catch (
const std::exception &e) {
bool HelpRequested(const ArgsManager &args)
bool CheckDataDirOption(const ArgsManager &args)
void SelectParams(const std::string &network)
Sets the params returned by Params() to those for the given BIP70 chain name.
const CChainParams & Params()
Return the currently selected parameters.
bool ReadSettingsFile(std::vector< std::string > *errors=nullptr)
Read settings file.
bool ParseParameters(int argc, const char *const argv[], std::string &error)
void EnsureDataDir() const
If datadir does not exist, create it along with wallets/ subdirectory(s).
bool GetSettingsPath(fs::path *filepath=nullptr, bool temp=false, bool backup=false) const
Get settings file path, or return false if read-write settings were disabled with -nosettings.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
bool WriteSettingsFile(std::vector< std::string > *errors=nullptr, bool backup=false) const
Write settings file or backup settings file.
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
bool ReadConfigFiles(std::string &error, bool ignore_invalid_keys=false)
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
Class encapsulating Bitcoin ABC startup and shutdown.
interfaces::Node & m_node
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info)
void handleRunawayException(const std::exception *e)
Pass fatal exception message to UI thread.
void runawayException(const QString &message)
BitcoinABC(interfaces::Node &node)
void initialize(Config *config, RPCServer *rpcServer, HTTPRPCRequestProcessor *httpRPCRequestProcessor)
Main Bitcoin application object.
ClientModel * clientModel
bool baseInitialize(Config &config)
Basic initialization, before starting initialization/shutdown thread.
void createSplashScreen(const NetworkStyle *networkStyle)
Create splash screen.
void windowShown(BitcoinGUI *window)
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info)
void setNode(interfaces::Node &node)
interfaces::Node & node() const
QTimer * pollShutdownTimer
void InitializePruneSetting(bool prune)
Initialize prune setting.
interfaces::Node * m_node
const PlatformStyle * platformStyle
int getReturnValue() const
Get process return value.
void parameterSetup()
parameter interaction/setup based on rules
void handleRunawayException(const QString &message)
Handle runaway exceptions.
void createWindow(const Config *, const NetworkStyle *networkStyle)
Create main window.
OptionsModel * optionsModel
void createOptionsModel(bool resetSettings)
Create options model.
void requestInitialize(Config &config, RPCServer &rpcServer, HTTPRPCRequestProcessor &httpRPCRequestProcessor)
Request core initialization.
void setupPlatformStyle()
Setup platform style.
void requestedInitialize(Config *config, RPCServer *rpcServer, HTTPRPCRequestProcessor *httpRPCRequestProcessor)
std::unique_ptr< QWidget > shutdownWindow
void requestShutdown(Config &config)
Request core shutdown.
WId getMainWinId() const
Get window identifier of QMainWindow (BitcoinGUI)
static const std::string DEFAULT_UIPLATFORM
void setClientModel(ClientModel *clientModel=nullptr, interfaces::BlockAndHeaderTipInfo *tip_info=nullptr)
Set the client model.
void receivedURI(const QString &uri)
Signal raised when a URI was entered or dragged to the GUI.
void unsubscribeFromCoreSignals()
Disconnect core signals from GUI client.
bool hasTrayIcon() const
Get the tray icon status.
void detectShutdown()
called by a timer to check if ShutdownRequested() has been set
void message(const QString &title, QString message, unsigned int style, bool *ret=nullptr, const QString &detailed_message=QString())
Notify the user of an event from the core network or transaction handling code.
Model for Bitcoin network client.
OptionsModel * getOptionsModel()
Qt event filter that intercepts QEvent::FocusOut events for QLabel objects, and resets their ‘textInt...
Qt event filter that intercepts ToolTipChange events, and replaces the tooltip with a rich text repre...
"Help message" dialog box
static bool showIfNeeded(bool &did_show_intro, bool &prune)
Determine data directory.
static const NetworkStyle * instantiate(const std::string &networkId)
Get style associated with provided BIP70 network id, or 0 if not known.
Interface from Qt to configuration data structure for Bitcoin client.
void SetPruneTargetGB(int prune_target_gb, bool force=false)
bool getMinimizeToTray() const
void setNode(interfaces::Node &node)
static bool ipcSendCommandLine()
void message(const QString &title, const QString &message, unsigned int style)
static void ipcParseCommandLine(int argc, char *argv[])
void receivedPaymentRequest(SendCoinsRecipient)
void handleURIOrFile(const QString &s)
Class for registering and managing all RPC calls.
static QWidget * showShutdownWindow(QMainWindow *window)
Class for the splashscreen with information of the running client.
void finish()
Hide the splash screen window and schedule the splash screen object for deletion.
void handleLoadWallet()
Handle wallet load notifications.
void setNode(interfaces::Node &node)
Controller between interfaces::Node, WalletModel instances and the GUI.
void coinsSent(interfaces::Wallet &wallet, SendCoinsRecipient recipient, QByteArray transaction)
static bool isWalletEnabled()
Top-level interface for a bitcoin node (bitcoind process).
virtual bilingual_str getWarnings()=0
Get warnings.
virtual void appShutdown()=0
Stop node.
virtual bool appInitMain(Config &config, RPCServer &rpcServer, HTTPRPCRequestProcessor &httpRPCRequestProcessor, interfaces::BlockAndHeaderTipInfo *tip_info=nullptr)=0
Start node.
virtual void startShutdown()=0
Start shutdown.
virtual bool baseInitialize(Config &config)=0
Initialize app dependencies.
const Config & GetConfig()
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
static constexpr int DEFAULT_PRUNE_TARGET_GB
static const int TOOLTIP_WRAP_THRESHOLD
static const bool DEFAULT_SPLASHSCREEN
#define QAPP_APP_NAME_DEFAULT
void InitLogging(const ArgsManager &args)
Initialize global loggers.
void SetupServerArgs(NodeContext &node)
Register all arguments with the ArgsManager.
void InitParameterInteraction(ArgsManager &args)
Parameter interaction: change current parameters depending on various rules.
static const bool DEFAULT_CHOOSE_DATADIR
bool error(const char *fmt, const Args &...args)
#define LogPrint(category,...)
void LogQtInfo()
Writes to debug.log short info about the used Qt and the host system.
std::unique_ptr< Node > MakeNode(node::NodeContext *context)
Return implementation of Node interface.
void ThreadSetInternalName(std::string &&)
Set the internal (in-memory) name of the current thread only.
void ThreadRename(std::string &&)
Rename a thread both in terms of an internal (in-memory) name as well as its system thread name.
bool noui_ThreadSafeQuestion(const bilingual_str &, const std::string &message, const std::string &caption, unsigned int style)
Non-GUI handler, which logs and prints questions.
void noui_InitMessage(const std::string &message)
Non-GUI handler, which only logs a message.
bool noui_ThreadSafeMessageBox(const bilingual_str &message, const std::string &caption, unsigned int style)
Non-GUI handler, which logs and prints messages.
static const bool DEFAULT_SELFSIGNED_ROOTCERTS
static void RegisterMetaTypes()
static QString GetLangTerritory()
int GuiMain(int argc, char *argv[])
static void SetupUIArgs(ArgsManager &argsman)
static bool InitSettings()
static const char * qt_argv
static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTranslator, QTranslator &translatorBase, QTranslator &translator)
Set up translations.
void DebugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
static std::string JoinErrors(const std::vector< std::string > &errors)
auto Join(const std::vector< T > &list, const BaseType &separator, UnaryOp unary_op) -> decltype(unary_op(list.at(0)))
Join a list of items.
Block and header tip information.
NodeContext struct containing references to chain state and connection state.
bilingual_str _(const char *psz)
Translation function.
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
CClientUIInterface uiInterface
bool InitError(const bilingual_str &str)
Show error message.
SynchronizationState
Current sync state passed to tip changed callbacks.