Bitcoin Core 22.99.0
P2P Digital Currency
splashscreen.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2020 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#if defined(HAVE_CONFIG_H)
7#endif
8
9#include <qt/splashscreen.h>
10
11#include <clientversion.h>
12#include <interfaces/handler.h>
13#include <interfaces/node.h>
14#include <interfaces/wallet.h>
15#include <qt/guiutil.h>
16#include <qt/networkstyle.h>
17#include <qt/walletmodel.h>
18#include <util/system.h>
19#include <util/translation.h>
20
21#include <functional>
22
23#include <QApplication>
24#include <QCloseEvent>
25#include <QPainter>
26#include <QRadialGradient>
27#include <QScreen>
28
29
31 : QWidget(), curAlignment(0)
32{
33 // set reference point, paddings
34 int paddingRight = 50;
35 int paddingTop = 50;
36 int titleVersionVSpace = 17;
37 int titleCopyrightVSpace = 40;
38
39 float fontFactor = 1.0;
40 float devicePixelRatio = 1.0;
41 devicePixelRatio = static_cast<QGuiApplication*>(QCoreApplication::instance())->devicePixelRatio();
42
43 // define text to place
44 QString titleText = PACKAGE_NAME;
45 QString versionText = QString("Version %1").arg(QString::fromStdString(FormatFullVersion()));
46 QString copyrightText = QString::fromUtf8(CopyrightHolders(strprintf("\xc2\xA9 %u-%u ", 2009, COPYRIGHT_YEAR)).c_str());
47 QString titleAddText = networkStyle->getTitleAddText();
48
49 QString font = QApplication::font().toString();
50
51 // create a bitmap according to device pixelratio
52 QSize splashSize(480*devicePixelRatio,320*devicePixelRatio);
53 pixmap = QPixmap(splashSize);
54
55 // change to HiDPI if it makes sense
56 pixmap.setDevicePixelRatio(devicePixelRatio);
57
58 QPainter pixPaint(&pixmap);
59 pixPaint.setPen(QColor(100,100,100));
60
61 // draw a slightly radial gradient
62 QRadialGradient gradient(QPoint(0,0), splashSize.width()/devicePixelRatio);
63 gradient.setColorAt(0, Qt::white);
64 gradient.setColorAt(1, QColor(247,247,247));
65 QRect rGradient(QPoint(0,0), splashSize);
66 pixPaint.fillRect(rGradient, gradient);
67
68 // draw the bitcoin icon, expected size of PNG: 1024x1024
69 QRect rectIcon(QPoint(-150,-122), QSize(430,430));
70
71 const QSize requiredSize(1024,1024);
72 QPixmap icon(networkStyle->getAppIcon().pixmap(requiredSize));
73
74 pixPaint.drawPixmap(rectIcon, icon);
75
76 // check font size and drawing with
77 pixPaint.setFont(QFont(font, 33*fontFactor));
78 QFontMetrics fm = pixPaint.fontMetrics();
79 int titleTextWidth = GUIUtil::TextWidth(fm, titleText);
80 if (titleTextWidth > 176) {
81 fontFactor = fontFactor * 176 / titleTextWidth;
82 }
83
84 pixPaint.setFont(QFont(font, 33*fontFactor));
85 fm = pixPaint.fontMetrics();
86 titleTextWidth = GUIUtil::TextWidth(fm, titleText);
87 pixPaint.drawText(pixmap.width()/devicePixelRatio-titleTextWidth-paddingRight,paddingTop,titleText);
88
89 pixPaint.setFont(QFont(font, 15*fontFactor));
90
91 // if the version string is too long, reduce size
92 fm = pixPaint.fontMetrics();
93 int versionTextWidth = GUIUtil::TextWidth(fm, versionText);
94 if(versionTextWidth > titleTextWidth+paddingRight-10) {
95 pixPaint.setFont(QFont(font, 10*fontFactor));
96 titleVersionVSpace -= 5;
97 }
98 pixPaint.drawText(pixmap.width()/devicePixelRatio-titleTextWidth-paddingRight+2,paddingTop+titleVersionVSpace,versionText);
99
100 // draw copyright stuff
101 {
102 pixPaint.setFont(QFont(font, 10*fontFactor));
103 const int x = pixmap.width()/devicePixelRatio-titleTextWidth-paddingRight;
104 const int y = paddingTop+titleCopyrightVSpace;
105 QRect copyrightRect(x, y, pixmap.width() - x - paddingRight, pixmap.height() - y);
106 pixPaint.drawText(copyrightRect, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, copyrightText);
107 }
108
109 // draw additional text if special network
110 if(!titleAddText.isEmpty()) {
111 QFont boldFont = QFont(font, 10*fontFactor);
112 boldFont.setWeight(QFont::Bold);
113 pixPaint.setFont(boldFont);
114 fm = pixPaint.fontMetrics();
115 int titleAddTextWidth = GUIUtil::TextWidth(fm, titleAddText);
116 pixPaint.drawText(pixmap.width()/devicePixelRatio-titleAddTextWidth-10,15,titleAddText);
117 }
118
119 pixPaint.end();
120
121 // Set window title
122 setWindowTitle(titleText + " " + titleAddText);
123
124 // Resize window and move to center of desktop, disallow resizing
125 QRect r(QPoint(), QSize(pixmap.size().width()/devicePixelRatio,pixmap.size().height()/devicePixelRatio));
126 resize(r.size());
127 setFixedSize(r.size());
128 move(QGuiApplication::primaryScreen()->geometry().center() - r.center());
129
130 installEventFilter(this);
131
133}
134
136{
138}
139
141{
142 assert(!m_node);
143 m_node = &node;
146}
147
149{
150 m_shutdown = true;
152}
153
154bool SplashScreen::eventFilter(QObject * obj, QEvent * ev) {
155 if (ev->type() == QEvent::KeyPress) {
156 QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
157 if (keyEvent->key() == Qt::Key_Q) {
158 shutdown();
159 }
160 }
161 return QObject::eventFilter(obj, ev);
162}
163
165{
166 /* If the window is minimized, hide() will be ignored. */
167 /* Make sure we de-minimize the splashscreen window before hiding */
168 if (isMinimized())
169 showNormal();
170 hide();
171 deleteLater(); // No more need for this
172}
173
174static void InitMessage(SplashScreen *splash, const std::string &message)
175{
176 bool invoked = QMetaObject::invokeMethod(splash, "showMessage",
177 Qt::QueuedConnection,
178 Q_ARG(QString, QString::fromStdString(message)),
179 Q_ARG(int, Qt::AlignBottom|Qt::AlignHCenter),
180 Q_ARG(QColor, QColor(55,55,55)));
181 assert(invoked);
182}
183
184static void ShowProgress(SplashScreen *splash, const std::string &title, int nProgress, bool resume_possible)
185{
186 InitMessage(splash, title + std::string("\n") +
187 (resume_possible ? SplashScreen::tr("(press q to shutdown and continue later)").toStdString()
188 : SplashScreen::tr("press q to shutdown").toStdString()) +
189 strprintf("\n%d", nProgress) + "%");
190}
191
193{
194 // Connect signals to client
195 m_handler_init_message = m_node->handleInitMessage(std::bind(InitMessage, this, std::placeholders::_1));
196 m_handler_show_progress = m_node->handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
197}
198
200{
201#ifdef ENABLE_WALLET
202 if (!WalletModel::isWalletEnabled()) return;
203 m_handler_load_wallet = m_node->walletClient().handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) {
204 m_connected_wallet_handlers.emplace_back(wallet->handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2, false)));
205 m_connected_wallets.emplace_back(std::move(wallet));
206 });
207#endif
208}
209
211{
212 // Disconnect signals from client
213 m_handler_init_message->disconnect();
214 m_handler_show_progress->disconnect();
215 for (const auto& handler : m_connected_wallet_handlers) {
216 handler->disconnect();
217 }
219 m_connected_wallets.clear();
220}
221
222void SplashScreen::showMessage(const QString &message, int alignment, const QColor &color)
223{
224 curMessage = message;
225 curAlignment = alignment;
226 curColor = color;
227 update();
228}
229
230void SplashScreen::paintEvent(QPaintEvent *event)
231{
232 QPainter painter(this);
233 painter.drawPixmap(0, 0, pixmap);
234 QRect r = rect().adjusted(5, 5, -5, -5);
235 painter.setPen(curColor);
236 painter.drawText(r, curAlignment, curMessage);
237}
238
239void SplashScreen::closeEvent(QCloseEvent *event)
240{
241 shutdown(); // allows an "emergency" shutdown during startup
242 event->ignore();
243}
#define PACKAGE_NAME
#define COPYRIGHT_YEAR
const QIcon & getAppIcon() const
Definition: networkstyle.h:20
const QString & getTitleAddText() const
Definition: networkstyle.h:22
Class for the splashscreen with information of the running client.
Definition: splashscreen.h:27
void shutdown()
Initiate shutdown.
std::unique_ptr< interfaces::Handler > m_handler_show_progress
Definition: splashscreen.h:68
void showMessage(const QString &message, int alignment, const QColor &color)
Show message and progress.
void unsubscribeFromCoreSignals()
Disconnect core signals to splash screen.
std::list< std::unique_ptr< interfaces::Wallet > > m_connected_wallets
Definition: splashscreen.h:70
void subscribeToCoreSignals()
Connect core signals to splash screen.
void finish()
Hide the splash screen window and schedule the splash screen object for deletion.
QColor curColor
Definition: splashscreen.h:62
std::list< std::unique_ptr< interfaces::Handler > > m_connected_wallet_handlers
Definition: splashscreen.h:71
std::unique_ptr< interfaces::Handler > m_handler_init_message
Definition: splashscreen.h:67
void paintEvent(QPaintEvent *event) override
void closeEvent(QCloseEvent *event) override
void handleLoadWallet()
Handle wallet load notifications.
QString curMessage
Definition: splashscreen.h:61
void setNode(interfaces::Node &node)
QPixmap pixmap
Definition: splashscreen.h:60
bool eventFilter(QObject *obj, QEvent *ev) override
SplashScreen(const NetworkStyle *networkStyle)
std::unique_ptr< interfaces::Handler > m_handler_load_wallet
Definition: splashscreen.h:69
interfaces::Node * m_node
Definition: splashscreen.h:65
static bool isWalletEnabled()
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:55
virtual std::unique_ptr< Handler > handleInitMessage(InitMessageFn fn)=0
virtual std::unique_ptr< Handler > handleShowProgress(ShowProgressFn fn)=0
virtual void startShutdown()=0
Start shutdown.
virtual WalletClient & walletClient()=0
Get wallet client.
virtual std::unique_ptr< Handler > handleLoadWallet(LoadWalletFn fn)=0
std::string FormatFullVersion()
void handleCloseWindowShortcut(QWidget *w)
Definition: guiutil.cpp:409
int TextWidth(const QFontMetrics &fm, const QString &text)
Returns the distance in pixels appropriate for drawing a subsequent character after text.
Definition: guiutil.cpp:882
bool(* handler)(const std::any &context, HTTPRequest *req, const std::string &strReq)
Definition: rest.cpp:715
static void ShowProgress(SplashScreen *splash, const std::string &title, int nProgress, bool resume_possible)
static void InitMessage(SplashScreen *splash, const std::string &message)
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
std::string CopyrightHolders(const std::string &strPrefix)
Definition: system.cpp:1350
assert(!tx.IsCoinBase())