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