LCOV - code coverage report
Current view: top level - src/qt - splashscreen.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 0 139 0.0 %
Date: 2020-09-26 01:30:44 Functions: 0 18 0.0 %

          Line data    Source code
       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)
       6             : #include <config/bitcoin-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           0 : SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) :
      28           0 :     QWidget(nullptr, f), curAlignment(0)
      29           0 : {
      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           0 :     devicePixelRatio = static_cast<QGuiApplication*>(QCoreApplication::instance())->devicePixelRatio();
      39             : 
      40             :     // define text to place
      41           0 :     QString titleText       = PACKAGE_NAME;
      42           0 :     QString versionText     = QString("Version %1").arg(QString::fromStdString(FormatFullVersion()));
      43           0 :     QString copyrightText   = QString::fromUtf8(CopyrightHolders(strprintf("\xc2\xA9 %u-%u ", 2009, COPYRIGHT_YEAR)).c_str());
      44           0 :     QString titleAddText    = networkStyle->getTitleAddText();
      45             : 
      46           0 :     QString font            = QApplication::font().toString();
      47             : 
      48             :     // create a bitmap according to device pixelratio
      49           0 :     QSize splashSize(480*devicePixelRatio,320*devicePixelRatio);
      50           0 :     pixmap = QPixmap(splashSize);
      51             : 
      52             :     // change to HiDPI if it makes sense
      53           0 :     pixmap.setDevicePixelRatio(devicePixelRatio);
      54             : 
      55           0 :     QPainter pixPaint(&pixmap);
      56           0 :     pixPaint.setPen(QColor(100,100,100));
      57             : 
      58             :     // draw a slightly radial gradient
      59           0 :     QRadialGradient gradient(QPoint(0,0), splashSize.width()/devicePixelRatio);
      60           0 :     gradient.setColorAt(0, Qt::white);
      61           0 :     gradient.setColorAt(1, QColor(247,247,247));
      62           0 :     QRect rGradient(QPoint(0,0), splashSize);
      63           0 :     pixPaint.fillRect(rGradient, gradient);
      64             : 
      65           0 :     // draw the bitcoin icon, expected size of PNG: 1024x1024
      66           0 :     QRect rectIcon(QPoint(-150,-122), QSize(430,430));
      67             : 
      68           0 :     const QSize requiredSize(1024,1024);
      69           0 :     QPixmap icon(networkStyle->getAppIcon().pixmap(requiredSize));
      70             : 
      71           0 :     pixPaint.drawPixmap(rectIcon, icon);
      72             : 
      73             :     // check font size and drawing with
      74           0 :     pixPaint.setFont(QFont(font, 33*fontFactor));
      75           0 :     QFontMetrics fm = pixPaint.fontMetrics();
      76           0 :     int titleTextWidth = GUIUtil::TextWidth(fm, titleText);
      77           0 :     if (titleTextWidth > 176) {
      78           0 :         fontFactor = fontFactor * 176 / titleTextWidth;
      79           0 :     }
      80             : 
      81           0 :     pixPaint.setFont(QFont(font, 33*fontFactor));
      82           0 :     fm = pixPaint.fontMetrics();
      83           0 :     titleTextWidth  = GUIUtil::TextWidth(fm, titleText);
      84           0 :     pixPaint.drawText(pixmap.width()/devicePixelRatio-titleTextWidth-paddingRight,paddingTop,titleText);
      85             : 
      86           0 :     pixPaint.setFont(QFont(font, 15*fontFactor));
      87             : 
      88             :     // if the version string is too long, reduce size
      89           0 :     fm = pixPaint.fontMetrics();
      90           0 :     int versionTextWidth  = GUIUtil::TextWidth(fm, versionText);
      91           0 :     if(versionTextWidth > titleTextWidth+paddingRight-10) {
      92           0 :         pixPaint.setFont(QFont(font, 10*fontFactor));
      93             :         titleVersionVSpace -= 5;
      94           0 :     }
      95           0 :     pixPaint.drawText(pixmap.width()/devicePixelRatio-titleTextWidth-paddingRight+2,paddingTop+titleVersionVSpace,versionText);
      96             : 
      97             :     // draw copyright stuff
      98             :     {
      99           0 :         pixPaint.setFont(QFont(font, 10*fontFactor));
     100           0 :         const int x = pixmap.width()/devicePixelRatio-titleTextWidth-paddingRight;
     101             :         const int y = paddingTop+titleCopyrightVSpace;
     102           0 :         QRect copyrightRect(x, y, pixmap.width() - x - paddingRight, pixmap.height() - y);
     103           0 :         pixPaint.drawText(copyrightRect, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, copyrightText);
     104           0 :     }
     105             : 
     106             :     // draw additional text if special network
     107           0 :     if(!titleAddText.isEmpty()) {
     108           0 :         QFont boldFont = QFont(font, 10*fontFactor);
     109           0 :         boldFont.setWeight(QFont::Bold);
     110           0 :         pixPaint.setFont(boldFont);
     111           0 :         fm = pixPaint.fontMetrics();
     112           0 :         int titleAddTextWidth  = GUIUtil::TextWidth(fm, titleAddText);
     113           0 :         pixPaint.drawText(pixmap.width()/devicePixelRatio-titleAddTextWidth-10,15,titleAddText);
     114           0 :     }
     115             : 
     116           0 :     pixPaint.end();
     117             : 
     118             :     // Set window title
     119           0 :     setWindowTitle(titleText + " " + titleAddText);
     120             : 
     121             :     // Resize window and move to center of desktop, disallow resizing
     122           0 :     QRect r(QPoint(), QSize(pixmap.size().width()/devicePixelRatio,pixmap.size().height()/devicePixelRatio));
     123           0 :     resize(r.size());
     124           0 :     setFixedSize(r.size());
     125           0 :     move(QGuiApplication::primaryScreen()->geometry().center() - r.center());
     126             : 
     127           0 :     installEventFilter(this);
     128             : 
     129           0 :     GUIUtil::handleCloseWindowShortcut(this);
     130           0 : }
     131             : 
     132           0 : SplashScreen::~SplashScreen()
     133           0 : {
     134           0 :     if (m_node) unsubscribeFromCoreSignals();
     135           0 : }
     136             : 
     137           0 : void SplashScreen::setNode(interfaces::Node& node)
     138             : {
     139           0 :     assert(!m_node);
     140           0 :     m_node = &node;
     141           0 :     subscribeToCoreSignals();
     142           0 :     if (m_shutdown) m_node->startShutdown();
     143           0 : }
     144             : 
     145           0 : void SplashScreen::shutdown()
     146             : {
     147           0 :     m_shutdown = true;
     148           0 :     if (m_node) m_node->startShutdown();
     149           0 : }
     150             : 
     151           0 : bool SplashScreen::eventFilter(QObject * obj, QEvent * ev) {
     152           0 :     if (ev->type() == QEvent::KeyPress) {
     153           0 :         QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
     154           0 :         if (keyEvent->key() == Qt::Key_Q) {
     155           0 :             shutdown();
     156           0 :         }
     157           0 :     }
     158           0 :     return QObject::eventFilter(obj, ev);
     159             : }
     160             : 
     161           0 : void SplashScreen::finish()
     162             : {
     163             :     /* If the window is minimized, hide() will be ignored. */
     164             :     /* Make sure we de-minimize the splashscreen window before hiding */
     165           0 :     if (isMinimized())
     166           0 :         showNormal();
     167           0 :     hide();
     168           0 :     deleteLater(); // No more need for this
     169           0 : }
     170             : 
     171           0 : static void InitMessage(SplashScreen *splash, const std::string &message)
     172             : {
     173           0 :     bool invoked = QMetaObject::invokeMethod(splash, "showMessage",
     174             :         Qt::QueuedConnection,
     175           0 :         Q_ARG(QString, QString::fromStdString(message)),
     176           0 :         Q_ARG(int, Qt::AlignBottom|Qt::AlignHCenter),
     177           0 :         Q_ARG(QColor, QColor(55,55,55)));
     178           0 :     assert(invoked);
     179           0 : }
     180             : 
     181           0 : static void ShowProgress(SplashScreen *splash, const std::string &title, int nProgress, bool resume_possible)
     182             : {
     183           0 :     InitMessage(splash, title + std::string("\n") +
     184           0 :             (resume_possible ? _("(press q to shutdown and continue later)").translated
     185           0 :                                 : _("press q to shutdown").translated) +
     186           0 :             strprintf("\n%d", nProgress) + "%");
     187           0 : }
     188             : 
     189           0 : void SplashScreen::subscribeToCoreSignals()
     190             : {
     191             :     // Connect signals to client
     192           0 :     m_handler_init_message = m_node->handleInitMessage(std::bind(InitMessage, this, std::placeholders::_1));
     193           0 :     m_handler_show_progress = m_node->handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
     194           0 : }
     195             : 
     196           0 : void SplashScreen::handleLoadWallet()
     197             : {
     198             : #ifdef ENABLE_WALLET
     199           0 :     m_handler_load_wallet = m_node->walletClient().handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) {
     200           0 :         m_connected_wallet_handlers.emplace_back(wallet->handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2, false)));
     201           0 :         m_connected_wallets.emplace_back(std::move(wallet));
     202           0 :     });
     203             : #endif
     204           0 : }
     205             : 
     206           0 : void SplashScreen::unsubscribeFromCoreSignals()
     207             : {
     208             :     // Disconnect signals from client
     209           0 :     m_handler_init_message->disconnect();
     210           0 :     m_handler_show_progress->disconnect();
     211           0 :     for (const auto& handler : m_connected_wallet_handlers) {
     212           0 :         handler->disconnect();
     213             :     }
     214           0 :     m_connected_wallet_handlers.clear();
     215           0 :     m_connected_wallets.clear();
     216           0 : }
     217             : 
     218           0 : void SplashScreen::showMessage(const QString &message, int alignment, const QColor &color)
     219             : {
     220           0 :     curMessage = message;
     221           0 :     curAlignment = alignment;
     222           0 :     curColor = color;
     223           0 :     update();
     224           0 : }
     225             : 
     226           0 : void SplashScreen::paintEvent(QPaintEvent *event)
     227             : {
     228           0 :     QPainter painter(this);
     229           0 :     painter.drawPixmap(0, 0, pixmap);
     230           0 :     QRect r = rect().adjusted(5, 5, -5, -5);
     231           0 :     painter.setPen(curColor);
     232           0 :     painter.drawText(r, curAlignment, curMessage);
     233           0 : }
     234             : 
     235           0 : void SplashScreen::closeEvent(QCloseEvent *event)
     236             : {
     237           0 :     shutdown(); // allows an "emergency" shutdown during startup
     238           0 :     event->ignore();
     239           0 : }

Generated by: LCOV version 1.15