<commit_before>// 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 <config/bitcoin-config.h>
#endif

#include <qt/splashscreen.h>

#include <clientversion.h>
#include <interfaces/handler.h>
#include <interfaces/node.h>
#include <interfaces/wallet.h>
#include <qt/guiutil.h>
#include <qt/networkstyle.h>
#include <util/system.h>
#include <util/translation.h>

#include <QApplication>
#include <QCloseEvent>
#include <QPainter>
#include <QRadialGradient>
#include <QScreen>

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<QGuiApplication *>(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);
}

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<QKeyEvent *>(ev);
        if (keyEvent->text()[0] == '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,<commit_msg>qt: Fix deprecated QCharRef usage<commit_after>// 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 <config/bitcoin-config.h>
#endif

#include <qt/splashscreen.h>

#include <clientversion.h>
#include <interfaces/handler.h>
#include <interfaces/node.h>
#include <interfaces/wallet.h>
#include <qt/guiutil.h>
#include <qt/networkstyle.h>
#include <util/system.h>
#include <util/translation.h>

#include <QApplication>
#include <QCloseEvent>
#include <QPainter>
#include <QRadialGradient>
#include <QScreen>

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<QGuiApplication *>(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);
}

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<QKeyEvent *>(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,
{'fraction_non_alphanumeric': 0.12073637233025183, 'fraction_numerical': 0.017931144405482945, 'mean_word_length': 2.895995032598572, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3272534', 'n_tokens_mistral': 4050, 'n_tokens_neox': 3710, 'n_words': 847}