7#include <chainparams.h>
36#include <validation.h>
45#include <QLibraryInfo>
54#include <boost/signals2/connection.hpp>
58#if defined(QT_STATICPLUGIN)
60#if defined(QT_QPA_PLATFORM_XCB)
61Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
62#elif defined(QT_QPA_PLATFORM_WINDOWS)
63Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
64#elif defined(QT_QPA_PLATFORM_COCOA)
65Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
66Q_IMPORT_PLUGIN(QMacStylePlugin);
71Q_DECLARE_METATYPE(
bool *)
80Q_DECLARE_METATYPE(
Config *)
89 qRegisterMetaType<bool *>();
90 qRegisterMetaType<SynchronizationState>();
91 qRegisterMetaType<SyncType>();
93 qRegisterMetaType<WalletModel *>();
95 qRegisterMetaType<Amount>();
98 qRegisterMetaType<size_t>(
"size_t");
100 qRegisterMetaType<std::function<void()>>(
"std::function<void()>");
101 qRegisterMetaType<QMessageBox::Icon>(
"QMessageBox::Icon");
102 qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>(
103 "interfaces::BlockAndHeaderTipInfo");
111 qRegisterMetaType<Config *>();
112 qRegisterMetaType<RPCServer *>();
113 qRegisterMetaType<HTTPRPCRequestProcessor *>();
122 QString lang_territory = QLocale::system().name();
124 QString lang_territory_qsettings =
125 settings.value(
"language",
"").toString();
126 if (!lang_territory_qsettings.isEmpty()) {
127 lang_territory = lang_territory_qsettings;
130 lang_territory = QString::fromStdString(
131 gArgs.
GetArg(
"-lang", lang_territory.toStdString()));
132 return lang_territory;
137 QTranslator &qtTranslator,
138 QTranslator &translatorBase,
139 QTranslator &translator) {
141 QApplication::removeTranslator(&qtTranslatorBase);
142 QApplication::removeTranslator(&qtTranslator);
143 QApplication::removeTranslator(&translatorBase);
144 QApplication::removeTranslator(&translator);
151 QString lang = lang_territory;
152 lang.truncate(lang_territory.lastIndexOf(
'_'));
158#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
159 const QString translation_path{
160 QLibraryInfo::location(QLibraryInfo::TranslationsPath)};
162 const QString translation_path{
163 QLibraryInfo::path(QLibraryInfo::TranslationsPath)};
166 if (qtTranslatorBase.load(
"qt_" + lang, translation_path)) {
167 QApplication::installTranslator(&qtTranslatorBase);
171 if (qtTranslator.load(
"qt_" + lang_territory, translation_path)) {
172 QApplication::installTranslator(&qtTranslator);
177 if (translatorBase.load(lang,
":/translations/")) {
178 QApplication::installTranslator(&translatorBase);
183 if (translator.load(lang_territory,
":/translations/")) {
184 QApplication::installTranslator(&translator);
189 const std::vector<std::string> &details) {
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 to "
198 "abort without making changes?"));
199 messagebox.setDetailedText(
201 messagebox.setTextFormat(Qt::PlainText);
202 messagebox.setDefaultButton(QMessageBox::Reset);
203 switch (messagebox.exec()) {
204 case QMessageBox::Reset:
206 case QMessageBox::Abort:
214 const std::vector<std::string> &details) {
215 QMessageBox messagebox(
216 QMessageBox::Critical, PACKAGE_NAME,
223 messagebox.setInformativeText(
224 QObject::tr(
"A fatal error occurred. Check that settings file is "
225 "writable, or try running with -nosettings."));
226 messagebox.setDetailedText(
228 messagebox.setTextFormat(Qt::PlainText);
229 messagebox.setDefaultButton(QMessageBox::Ok);
235 const QString &
msg) {
237 if (type == QtDebugMsg) {
256 qDebug() << __func__ <<
": Running initialization in thread";
259 *httpRPCRequestProcessor, &tip_info);
261 }
catch (
const std::exception &e) {
270 qDebug() << __func__ <<
": Running Shutdown in thread";
272 qDebug() << __func__ <<
": Shutdown finished";
274 }
catch (
const std::exception &e) {
285 : QApplication(
qt_argc, const_cast<char **>(&
qt_argv)), coreThread(nullptr),
286 optionsModel(nullptr), clientModel(nullptr), window(nullptr),
287 pollShutdownTimer(nullptr), platformStyle(nullptr) {
290 setQuitOnLastWindowClosed(
false);
297 std::string platformName;
310 qDebug() << __func__ <<
": Stopping thread";
313 qDebug() << __func__ <<
": Stopped thread";
323void BitcoinApplication::createPaymentServer() {
341 if (!QApplication::activeModalWidget()) {
389 [] { QCoreApplication::exit(0); });
412 connect(
coreThread, &QThread::finished, executor, &QObject::deleteLater);
435 qDebug() << __func__ <<
": Requesting initialize";
444 for (
const auto w : QGuiApplication::topLevelWindows()) {
453 qDebug() << __func__ <<
": Requesting shutdown";
479 delete m_wallet_controller;
480 m_wallet_controller =
nullptr;
492 qDebug() << __func__ <<
": Initialization result: " << success;
506 m_wallet_controller =
508 window->setWalletController(m_wallet_controller);
512 PaymentServer::LoadRootCAs();
514 paymentServer, &PaymentServer::fetchPaymentACK);
538 &BitcoinGUI::handlePaymentRequest);
542 [
this](
const QString &title,
const QString &message,
543 unsigned int style) {
554 QMessageBox::critical(
555 nullptr,
"Runaway exception",
556 BitcoinGUI::tr(
"A fatal error occurred. %1 can no longer continue "
557 "safely and will quit.")
559 QString(
"<br><br>") + message);
560 ::exit(EXIT_FAILURE);
572 if (e->type() == QEvent::Quit) {
577 return QApplication::event(e);
581#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
583 "-allowselfsignedrootcertificates",
584 strprintf(
"Allow self signed root certificates (default: %d)",
588 argsman.
AddArg(
"-choosedatadir",
589 strprintf(
"Choose data directory on startup (default: %d)",
594 "Set language, for example \"de_DE\" (default: system locale)",
599 "-rootcertificates=<file>",
600 "Set SSL root certificates for payment request (default: -system-)",
603 strprintf(
"Show splash screen on startup (default: %d)",
606 argsman.
AddArg(
"-resetguisettings",
"Reset all settings changed in the GUI",
608 argsman.
AddArg(
"-uiplatform",
609 strprintf(
"Select platform to customize UI for (one of "
610 "windows, macosx, other; default: %s)",
618 common::WinCmdLineArgs winArgs;
619 std::tie(argc, argv) = winArgs.get();
625 std::unique_ptr<interfaces::Node>
node =
629 boost::signals2::scoped_connection handler_message_box =
631 boost::signals2::scoped_connection handler_question =
633 boost::signals2::scoped_connection handler_init_message =
641 Q_INIT_RESOURCE(bitcoin);
642 Q_INIT_RESOURCE(bitcoin_locale);
644#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
646 QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
647 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
660 Untranslated(
"Error parsing command line arguments: %s"), error));
663 QMessageBox::critical(
664 nullptr, PACKAGE_NAME,
667 QString::fromStdString(
"Error parsing command line arguments: %1.")
668 .arg(QString::fromStdString(error)));
685 QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
699 app.installEventFilter(
704 bool did_show_intro =
false;
728 QMessageBox::critical(
729 nullptr, PACKAGE_NAME,
730 QObject::tr(
"Error: %1")
731 .arg(QString::fromStdString(err->message.translated)));
740 QScopedPointer<const NetworkStyle> networkStyle(
742 assert(!networkStyle.isNull());
744 QApplication::setApplicationName(networkStyle->getAppName());
767 app.createPaymentServer();
778 qApp->installNativeEventFilter(
new WinShutdownMonitor());
788 if (did_show_intro) {
804 std::any context{&node_context};
819 WinShutdownMonitor::registerShutdownBlockReason(
820 QObject::tr(
"%1 didn't yet exit safely...").arg(PACKAGE_NAME),
824 }
catch (
const std::exception &e) {
bool HelpRequested(const ArgsManager &args)
const CChainParams & Params()
Return the currently selected parameters.
@ ALLOW_ANY
disable validation
bool ParseParameters(int argc, const char *const argv[], std::string &error)
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
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 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.
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.
void createWindow(const Config &, const NetworkStyle *networkStyle)
Create main window.
ClientModel * clientModel
bool baseInitialize(Config &config)
Basic initialization, before starting initialization/shutdown thread.
void createSplashScreen(const NetworkStyle *networkStyle)
Create splash screen.
void requestShutdown()
Request core shutdown.
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
void parameterSetup()
parameter interaction/setup based on rules
void handleRunawayException(const QString &message)
Handle runaway exceptions.
OptionsModel * optionsModel
bool event(QEvent *e) override
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
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 ChainType 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 int getExitStatus()=0
Get exit status.
virtual bool baseInitialize(Config &config)=0
Initialize app dependencies.
const Config & GetConfig()
void PrintExceptionContinue(const std::exception *pex, std::string_view thread_name)
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
#define LogDebug(category,...)
void LogQtInfo()
Writes to debug.log short info about the used Qt and the host system.
std::optional< ConfigError > InitConfig(ArgsManager &args, SettingsAbortFn settings_abort_fn)
Read config files, and create datadir and settings.json if they don't exist.
@ ABORTED
Aborted by user.
@ FAILED_WRITE
Failed to write settings.json.
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.
std::string MakeUnorderedList(const std::vector< std::string > &items)
Create an unordered multi-line list of items.
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 bool ErrorSettingsRead(const bilingual_str &error, const std::vector< std::string > &details)
static void RegisterMetaTypes()
static QString GetLangTerritory()
int GuiMain(int argc, char *argv[])
static void ErrorSettingsWrite(const bilingual_str &error, const std::vector< std::string > &details)
static void SetupUIArgs(ArgsManager &argsman)
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)
Block and header tip information.
NodeContext struct containing references to chain state and connection state.
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.