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