diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index f8ad205fe..0e30d27a7 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -1,271 +1,266 @@ // Copyright (c) 2011-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include SplashScreen::SplashScreen(const NetworkStyle *networkStyle) : QWidget(nullptr), curAlignment(0) { // set reference point, paddings int paddingRight = 50; int paddingTop = 50; int titleVersionVSpace = 17; int titleCopyrightVSpace = 40; float fontFactor = 1.0; float devicePixelRatio = 1.0; devicePixelRatio = static_cast(QCoreApplication::instance()) ->devicePixelRatio(); // define text to place QString titleText = PACKAGE_NAME; QString versionText = QString("Version %1").arg(QString::fromStdString(FormatFullVersion())); QString copyrightText = QString::fromUtf8( CopyrightHolders(strprintf("\xc2\xA9 %u-%u ", 2009, COPYRIGHT_YEAR)) .c_str()); QString titleAddText = networkStyle->getTitleAddText(); QString font = QApplication::font().toString(); // create a bitmap according to device pixelratio QSize splashSize(634 * devicePixelRatio, 320 * devicePixelRatio); pixmap = QPixmap(splashSize); // change to HiDPI if it makes sense pixmap.setDevicePixelRatio(devicePixelRatio); QPainter pixPaint(&pixmap); pixPaint.setPen(QColor(100, 100, 100)); // draw a slightly radial gradient QRadialGradient gradient(QPoint(0, 0), splashSize.width() / devicePixelRatio); gradient.setColorAt(0, Qt::white); gradient.setColorAt(1, QColor(247, 247, 247)); QRect rGradient(QPoint(0, 0), splashSize); pixPaint.fillRect(rGradient, gradient); // draw the bitcoin icon, expected size of PNG: 1024x1024 QRect rectIcon(QPoint(-10, -100), QSize(430, 430)); const QSize requiredSize(1024, 1024); QPixmap icon(networkStyle->getAppIcon().pixmap(requiredSize)); pixPaint.drawPixmap(rectIcon, icon); // check font size and drawing with pixPaint.setFont(QFont(font, 33 * fontFactor)); QFontMetrics fm = pixPaint.fontMetrics(); int titleTextWidth = GUIUtil::TextWidth(fm, titleText); if (titleTextWidth > 176) { fontFactor = fontFactor * 176 / titleTextWidth; } pixPaint.setFont(QFont(font, 33 * fontFactor)); fm = pixPaint.fontMetrics(); titleTextWidth = GUIUtil::TextWidth(fm, titleText); pixPaint.drawText(pixmap.width() / devicePixelRatio - titleTextWidth - paddingRight, paddingTop, titleText); pixPaint.setFont(QFont(font, 15 * fontFactor)); // if the version string is too long, reduce size fm = pixPaint.fontMetrics(); int versionTextWidth = GUIUtil::TextWidth(fm, titleText); if (versionTextWidth > titleTextWidth + paddingRight - 10) { pixPaint.setFont(QFont(font, 10 * fontFactor)); titleVersionVSpace -= 5; } pixPaint.drawText(pixmap.width() / devicePixelRatio - titleTextWidth - paddingRight + 2, paddingTop + titleVersionVSpace, versionText); // draw copyright stuff { pixPaint.setFont(QFont(font, 10 * fontFactor)); const int x = pixmap.width() / devicePixelRatio - titleTextWidth - paddingRight; const int y = paddingTop + titleCopyrightVSpace; QRect copyrightRect(x, y, pixmap.width() - x - paddingRight, pixmap.height() - y); pixPaint.drawText(copyrightRect, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, copyrightText); } // draw additional text if special network if (!titleAddText.isEmpty()) { QFont boldFont = QFont(font, 10 * fontFactor); boldFont.setWeight(QFont::Bold); pixPaint.setFont(boldFont); fm = pixPaint.fontMetrics(); int titleAddTextWidth = GUIUtil::TextWidth(fm, titleAddText); pixPaint.drawText(pixmap.width() / devicePixelRatio - titleAddTextWidth - 10, 15, titleAddText); } pixPaint.end(); // Set window title setWindowTitle(titleText + " " + titleAddText); // Resize window and move to center of desktop, disallow resizing QRect r(QPoint(), QSize(pixmap.size().width() / devicePixelRatio, pixmap.size().height() / devicePixelRatio)); resize(r.size()); setFixedSize(r.size()); move(QGuiApplication::primaryScreen()->geometry().center() - r.center()); installEventFilter(this); GUIUtil::handleCloseWindowShortcut(this); } SplashScreen::~SplashScreen() { if (m_node) { unsubscribeFromCoreSignals(); } } void SplashScreen::setNode(interfaces::Node &node) { assert(!m_node); m_node = &node; subscribeToCoreSignals(); if (m_shutdown) { m_node->startShutdown(); } } void SplashScreen::shutdown() { m_shutdown = true; if (m_node) { m_node->startShutdown(); } } bool SplashScreen::eventFilter(QObject *obj, QEvent *ev) { if (ev->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(ev); if (keyEvent->key() == Qt::Key_Q) { shutdown(); } } return QObject::eventFilter(obj, ev); } void SplashScreen::finish() { /* If the window is minimized, hide() will be ignored. */ /* Make sure we de-minimize the splashscreen window before hiding */ if (isMinimized()) { showNormal(); } hide(); // No more need for this deleteLater(); } static void InitMessage(SplashScreen *splash, const std::string &message) { bool invoked = QMetaObject::invokeMethod( splash, "showMessage", Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(message)), Q_ARG(int, Qt::AlignBottom | Qt::AlignHCenter), Q_ARG(QColor, QColor(55, 55, 55))); assert(invoked); } static void ShowProgress(SplashScreen *splash, const std::string &title, int nProgress, bool resume_possible) { InitMessage( splash, title + std::string("\n") + (resume_possible ? _("(press q to shutdown and continue later)").translated : _("press q to shutdown").translated) + strprintf("\n%d", nProgress) + "%"); } -#ifdef ENABLE_WALLET -void SplashScreen::ConnectWallet(std::unique_ptr wallet) { - m_connected_wallet_handlers.emplace_back(wallet->handleShowProgress( - std::bind(ShowProgress, this, std::placeholders::_1, - std::placeholders::_2, false))); - m_connected_wallets.emplace_back(std::move(wallet)); -} -#endif void SplashScreen::subscribeToCoreSignals() { // Connect signals to client m_handler_init_message = m_node->handleInitMessage( std::bind(InitMessage, this, std::placeholders::_1)); m_handler_show_progress = m_node->handleShowProgress( std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); } void SplashScreen::handleLoadWallet() { #ifdef ENABLE_WALLET if (!WalletModel::isWalletEnabled()) { return; } m_handler_load_wallet = m_node->walletClient().handleLoadWallet( [this](std::unique_ptr wallet) { - ConnectWallet(std::move(wallet)); + m_connected_wallet_handlers.emplace_back(wallet->handleShowProgress( + std::bind(ShowProgress, this, std::placeholders::_1, + std::placeholders::_2, false))); + m_connected_wallets.emplace_back(std::move(wallet)); }); #endif } void SplashScreen::unsubscribeFromCoreSignals() { // Disconnect signals from client m_handler_init_message->disconnect(); m_handler_show_progress->disconnect(); for (const auto &handler : m_connected_wallet_handlers) { handler->disconnect(); } m_connected_wallet_handlers.clear(); m_connected_wallets.clear(); } void SplashScreen::showMessage(const QString &message, int alignment, const QColor &color) { curMessage = message; curAlignment = alignment; curColor = color; update(); } void SplashScreen::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.drawPixmap(0, 0, pixmap); QRect r = rect().adjusted(5, 5, -5, -5); painter.setPen(curColor); painter.drawText(r, curAlignment, curMessage); } void SplashScreen::closeEvent(QCloseEvent *event) { // allows an "emergency" shutdown during startup shutdown(); event->ignore(); } diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h index 4f75a01c7..11023e5b5 100644 --- a/src/qt/splashscreen.h +++ b/src/qt/splashscreen.h @@ -1,77 +1,75 @@ // Copyright (c) 2011-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_QT_SPLASHSCREEN_H #define BITCOIN_QT_SPLASHSCREEN_H #include #include class NetworkStyle; namespace interfaces { class Handler; class Node; class Wallet; }; // namespace interfaces /** Class for the splashscreen with information of the running client. * * @note this is intentionally not a QSplashScreen. Bitcoin Core initialization * can take a long time, and in that case a progress window that cannot be moved * around and minimized has turned out to be frustrating to the user. */ class SplashScreen : public QWidget { Q_OBJECT public: explicit SplashScreen(const NetworkStyle *networkStyle); ~SplashScreen(); void setNode(interfaces::Node &node); protected: void paintEvent(QPaintEvent *event) override; void closeEvent(QCloseEvent *event) override; public Q_SLOTS: /** Hide the splash screen window and schedule the splash screen object for * deletion */ void finish(); /** Show message and progress */ void showMessage(const QString &message, int alignment, const QColor &color); /** Handle wallet load notifications. */ void handleLoadWallet(); protected: bool eventFilter(QObject *obj, QEvent *ev) override; private: /** Connect core signals to splash screen */ void subscribeToCoreSignals(); /** Disconnect core signals to splash screen */ void unsubscribeFromCoreSignals(); /** Initiate shutdown */ void shutdown(); - /** Connect wallet signals to splash screen */ - void ConnectWallet(std::unique_ptr wallet); QPixmap pixmap; QString curMessage; QColor curColor; int curAlignment; interfaces::Node *m_node = nullptr; bool m_shutdown = false; std::unique_ptr m_handler_init_message; std::unique_ptr m_handler_show_progress; std::unique_ptr m_handler_load_wallet; std::list> m_connected_wallets; std::list> m_connected_wallet_handlers; }; #endif // BITCOIN_QT_SPLASHSCREEN_H