7#include <chainparams.h>
35#include <validation.h>
44#include <QLibraryInfo>
53#include <boost/signals2/connection.hpp>
57#if defined(QT_STATICPLUGIN)
59#if defined(QT_QPA_PLATFORM_XCB)
60Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
61#elif defined(QT_QPA_PLATFORM_WINDOWS)
62Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
63#elif defined(QT_QPA_PLATFORM_COCOA)
64Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
65Q_IMPORT_PLUGIN(QMacStylePlugin);
70Q_DECLARE_METATYPE(
bool *)
79Q_DECLARE_METATYPE(
Config *)
88 qRegisterMetaType<bool *>();
89 qRegisterMetaType<SynchronizationState>();
90 qRegisterMetaType<SyncType>();
92 qRegisterMetaType<WalletModel *>();
94 qRegisterMetaType<Amount>();
97 qRegisterMetaType<size_t>(
"size_t");
99 qRegisterMetaType<std::function<void()>>(
"std::function<void()>");
100 qRegisterMetaType<QMessageBox::Icon>(
"QMessageBox::Icon");
101 qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>(
102 "interfaces::BlockAndHeaderTipInfo");
110 qRegisterMetaType<Config *>();
111 qRegisterMetaType<RPCServer *>();
112 qRegisterMetaType<HTTPRPCRequestProcessor *>();
121 QString lang_territory = QLocale::system().name();
123 QString lang_territory_qsettings =
124 settings.value(
"language",
"").toString();
125 if (!lang_territory_qsettings.isEmpty()) {
126 lang_territory = lang_territory_qsettings;
129 lang_territory = QString::fromStdString(
130 gArgs.
GetArg(
"-lang", lang_territory.toStdString()));
131 return lang_territory;
136 QTranslator &qtTranslator,
137 QTranslator &translatorBase,
138 QTranslator &translator) {
140 QApplication::removeTranslator(&qtTranslatorBase);
141 QApplication::removeTranslator(&qtTranslator);
142 QApplication::removeTranslator(&translatorBase);
143 QApplication::removeTranslator(&translator);
150 QString lang = lang_territory;
151 lang.truncate(lang_territory.lastIndexOf(
'_'));
157#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
158 const QString translation_path{
159 QLibraryInfo::location(QLibraryInfo::TranslationsPath)};
161 const QString translation_path{
162 QLibraryInfo::path(QLibraryInfo::TranslationsPath)};
165 if (qtTranslatorBase.load(
"qt_" + lang, translation_path)) {
166 QApplication::installTranslator(&qtTranslatorBase);
170 if (qtTranslator.load(
"qt_" + lang_territory, translation_path)) {
171 QApplication::installTranslator(&qtTranslator);
176 if (translatorBase.load(lang,
":/translations/")) {
177 QApplication::installTranslator(&translatorBase);
182 if (translator.load(lang_territory,
":/translations/")) {
183 QApplication::installTranslator(&translator);
188 const std::vector<std::string> &details) {
189 QMessageBox messagebox(
190 QMessageBox::Critical, PACKAGE_NAME,
192 QMessageBox::Reset | QMessageBox::Abort);
195 messagebox.setInformativeText(
196 QObject::tr(
"Do you want to reset settings to default values, or to "
197 "abort without making changes?"));
198 messagebox.setDetailedText(
200 messagebox.setTextFormat(Qt::PlainText);
201 messagebox.setDefaultButton(QMessageBox::Reset);
202 switch (messagebox.exec()) {
203 case QMessageBox::Reset:
205 case QMessageBox::Abort:
213 const std::vector<std::string> &details) {
214 QMessageBox messagebox(
215 QMessageBox::Critical, PACKAGE_NAME,
222 messagebox.setInformativeText(
223 QObject::tr(
"A fatal error occurred. Check that settings file is "
224 "writable, or try running with -nosettings."));
225 messagebox.setDetailedText(
227 messagebox.setTextFormat(Qt::PlainText);
228 messagebox.setDefaultButton(QMessageBox::Ok);
234 const QString &msg) {
236 if (type == QtDebugMsg) {
239 LogPrintf(
"GUI: %s\n", msg.toStdString());
255 qDebug() << __func__ <<
": Running initialization in thread";
258 *httpRPCRequestProcessor, &tip_info);
260 }
catch (
const std::exception &e) {
269 qDebug() << __func__ <<
": Running Shutdown in thread";
271 qDebug() << __func__ <<
": Shutdown finished";
273 }
catch (
const std::exception &e) {
284 : QApplication(
qt_argc, const_cast<char **>(&
qt_argv)), coreThread(nullptr),
285 optionsModel(nullptr), clientModel(nullptr), window(nullptr),
286 pollShutdownTimer(nullptr), platformStyle(nullptr) {
289 setQuitOnLastWindowClosed(
false);
296 std::string platformName;
309 qDebug() << __func__ <<
": Stopping thread";
312 qDebug() << __func__ <<
": Stopped thread";
322void BitcoinApplication::createPaymentServer() {
340 if (!QApplication::activeModalWidget()) {
388 [] { QCoreApplication::exit(0); });
411 connect(
coreThread, &QThread::finished, executor, &QObject::deleteLater);
434 qDebug() << __func__ <<
": Requesting initialize";
443 for (
const auto w : QGuiApplication::topLevelWindows()) {
452 qDebug() << __func__ <<
": Requesting shutdown";
478 delete m_wallet_controller;
479 m_wallet_controller =
nullptr;
491 qDebug() << __func__ <<
": Initialization result: " << success;
505 m_wallet_controller =
507 window->setWalletController(m_wallet_controller);
511 PaymentServer::LoadRootCAs();
513 paymentServer, &PaymentServer::fetchPaymentACK);
537 &BitcoinGUI::handlePaymentRequest);
541 [
this](
const QString &title,
const QString &message,
542 unsigned int style) {
553 QMessageBox::critical(
554 nullptr,
"Runaway exception",
555 BitcoinGUI::tr(
"A fatal error occurred. %1 can no longer continue "
556 "safely and will quit.")
558 QString(
"<br><br>") + message);
559 ::exit(EXIT_FAILURE);
571 if (e->type() == QEvent::Quit) {
576 return QApplication::event(e);
580#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
582 "-allowselfsignedrootcertificates",
583 strprintf(
"Allow self signed root certificates (default: %d)",
587 argsman.
AddArg(
"-choosedatadir",
588 strprintf(
"Choose data directory on startup (default: %d)",
593 "Set language, for example \"de_DE\" (default: system locale)",
598 "-rootcertificates=<file>",
599 "Set SSL root certificates for payment request (default: -system-)",
602 strprintf(
"Show splash screen on startup (default: %d)",
605 argsman.
AddArg(
"-resetguisettings",
"Reset all settings changed in the GUI",
607 argsman.
AddArg(
"-uiplatform",
608 strprintf(
"Select platform to customize UI for (one of "
609 "windows, macosx, other; default: %s)",
617 common::WinCmdLineArgs winArgs;
618 std::tie(argc, argv) = winArgs.get();
624 std::unique_ptr<interfaces::Node>
node =
628 boost::signals2::scoped_connection handler_message_box =
630 boost::signals2::scoped_connection handler_question =
632 boost::signals2::scoped_connection handler_init_message =
640 Q_INIT_RESOURCE(bitcoin);
641 Q_INIT_RESOURCE(bitcoin_locale);
643#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
645 QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
646 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
659 Untranslated(
"Error parsing command line arguments: %s"), error));
662 QMessageBox::critical(
663 nullptr, PACKAGE_NAME,
666 QString::fromStdString(
"Error parsing command line arguments: %1.")
667 .arg(QString::fromStdString(error)));
684 QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
698 app.installEventFilter(
703 bool did_show_intro =
false;
727 QMessageBox::critical(
728 nullptr, PACKAGE_NAME,
729 QObject::tr(
"Error: %1")
730 .arg(QString::fromStdString(err->message.translated)));
739 QScopedPointer<const NetworkStyle> networkStyle(
741 assert(!networkStyle.isNull());
743 QApplication::setApplicationName(networkStyle->getAppName());
766 app.createPaymentServer();
777 qApp->installNativeEventFilter(
new WinShutdownMonitor());
787 if (did_show_intro) {
803 std::any context{&node_context};
818 WinShutdownMonitor::registerShutdownBlockReason(
819 QObject::tr(
"%1 didn't yet exit safely...").arg(PACKAGE_NAME),
823 }
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 LogPrint(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.