// Copyright (c) 2011-2015 The Bitcoin Core developers // Copyright (c) 2014-2017 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "splashscreen.h" #include "guiutil.h" #include "networkstyle.h" #include "clientversion.h" #include "init.h" #include "util.h" #include "ui_interface.h" #include "version.h" #ifdef ENABLE_WALLET #include "wallet/wallet.h" #endif #include #include #include #include SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) : QWidget(0, f), curAlignment(0) { // transparent background setAttribute(Qt::WA_TranslucentBackground); setStyleSheet("background:transparent;"); // no window decorations setWindowFlags(Qt::FramelessWindowHint); // set reference point, paddings int paddingLeft = 14; int paddingTop = 470; int titleVersionVSpace = 17; int titleCopyrightVSpace = 32; float fontFactor = 1.0; // define text to place QString titleText = tr("Dash Core"); QString versionText = QString(tr("Version %1")).arg(QString::fromStdString(FormatFullVersion())); QString copyrightTextBtc = QChar(0xA9)+QString(" 2009-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Bitcoin Core developers")); QString copyrightTextDash = QChar(0xA9)+QString(" 2014-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Dash Core developers")); QString titleAddText = networkStyle->getTitleAddText(); // networkstyle.cpp can't (yet) read themes, so we do it here to get the correct Splash-screen QString splashScreenPath = ":/images/" + GUIUtil::getThemeName() + "/splash"; if(GetBoolArg("-regtest", false)) splashScreenPath = ":/images/" + GUIUtil::getThemeName() + "/splash_testnet"; if(GetBoolArg("-testnet", false)) splashScreenPath = ":/images/" + GUIUtil::getThemeName() + "/splash_testnet"; QString font = QApplication::font().toString(); // load the bitmap for writing some text over it pixmap = QPixmap(splashScreenPath); QPainter pixPaint(&pixmap); pixPaint.setPen(QColor(100,100,100)); // check font size and drawing with pixPaint.setFont(QFont(font, 28*fontFactor)); QFontMetrics fm = pixPaint.fontMetrics(); int titleTextWidth = fm.width(titleText); if(titleTextWidth > 160) { // strange font rendering, Arial probably not found fontFactor = 0.75; } pixPaint.setFont(QFont(font, 28*fontFactor)); fm = pixPaint.fontMetrics(); titleTextWidth = fm.width(titleText); pixPaint.drawText(paddingLeft,paddingTop,titleText); pixPaint.setFont(QFont(font, 15*fontFactor)); pixPaint.drawText(paddingLeft,paddingTop+titleVersionVSpace,versionText); // draw copyright stuff pixPaint.setFont(QFont(font, 10*fontFactor)); pixPaint.drawText(paddingLeft,paddingTop+titleCopyrightVSpace,copyrightTextBtc); pixPaint.drawText(paddingLeft,paddingTop+titleCopyrightVSpace+12,copyrightTextDash); // 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 = fm.width(titleAddText); pixPaint.drawText(pixmap.width()-titleAddTextWidth-10,pixmap.height()-25,titleAddText); } pixPaint.end(); // Resize window and move to center of desktop, disallow resizing QRect r(QPoint(), pixmap.size()); resize(r.size()); setFixedSize(r.size()); move(QApplication::desktop()->screenGeometry().center() - r.center()); subscribeToCoreSignals(); installEventFilter(this); } SplashScreen::~SplashScreen() { unsubscribeFromCoreSignals(); } bool SplashScreen::eventFilter(QObject * obj, QEvent * ev) { if (ev->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(ev); if(keyEvent->text()[0] == 'q' && breakAction != nullptr) { breakAction(); } } return QObject::eventFilter(obj, ev); } void SplashScreen::slotFinish(QWidget *mainWin) { Q_UNUSED(mainWin); /* If the window is minimized, hide() will be ignored. */ /* Make sure we de-minimize the splashscreen window before hiding */ if (isMinimized()) showNormal(); hide(); deleteLater(); // No more need for this } static void InitMessage(SplashScreen *splash, const std::string &message) { 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))); } static void ShowProgress(SplashScreen *splash, const std::string &title, int nProgress) { InitMessage(splash, title + strprintf("%d", nProgress) + "%"); } void SplashScreen::setBreakAction(const std::function &action) { breakAction = action; } static void SetProgressBreakAction(SplashScreen *splash, const std::function &action) { QMetaObject::invokeMethod(splash, "setBreakAction", Qt::QueuedConnection, Q_ARG(std::function, action)); } #ifdef ENABLE_WALLET static void ConnectWallet(SplashScreen *splash, CWallet* wallet) { wallet->ShowProgress.connect(boost::bind(ShowProgress, splash, _1, _2)); } #endif void SplashScreen::subscribeToCoreSignals() { // Connect signals to client uiInterface.InitMessage.connect(boost::bind(InitMessage, this, _1)); uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2)); uiInterface.SetProgressBreakAction.connect(boost::bind(SetProgressBreakAction, this, _1)); #ifdef ENABLE_WALLET uiInterface.LoadWallet.connect(boost::bind(ConnectWallet, this, _1)); #endif } void SplashScreen::unsubscribeFromCoreSignals() { // Disconnect signals from client uiInterface.InitMessage.disconnect(boost::bind(InitMessage, this, _1)); uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); #ifdef ENABLE_WALLET if(pwalletMain) pwalletMain->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); #endif } 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) { StartShutdown(); // allows an "emergency" shutdown during startup event->ignore(); }