Qt: HiDPI (retina) support for splash screen
- remove splash screen images (reduce binary size) - dynamicly draw splash screen with available icon. - remove testnet icon - dynamicly colorize testnet icon
This commit is contained in:
parent
f3af0c898f
commit
54f2571a00
12 changed files with 122 additions and 36 deletions
|
@ -49,8 +49,7 @@ Jonas Schnelli
|
||||||
src/qt/res/icons/tx_output.png, src/qt/res/icons/bitcoin.icns,
|
src/qt/res/icons/tx_output.png, src/qt/res/icons/bitcoin.icns,
|
||||||
src/qt/res/src/bitcoin.svg, src/qt/res/src/bitcoin.ico,
|
src/qt/res/src/bitcoin.svg, src/qt/res/src/bitcoin.ico,
|
||||||
src/qt/res/src/bitcoin.png, src/qt/res/src/bitcoin_testnet.png,
|
src/qt/res/src/bitcoin.png, src/qt/res/src/bitcoin_testnet.png,
|
||||||
docs/bitcoin_logo_doxygen.png, src/qt/res/images/splash.png,
|
docs/bitcoin_logo_doxygen.png, src/qt/res/src/tx*.svg,
|
||||||
src/qt/res/images/splash_testnet.png, src/qt/res/src/tx*.svg,
|
|
||||||
src/qt/res/src/connect*.svg, src/qt/res/src/clock*.svg,
|
src/qt/res/src/connect*.svg, src/qt/res/src/clock*.svg,
|
||||||
src/qt/res/src/mine.svg, src/qt/res/src/qt.svg,
|
src/qt/res/src/mine.svg, src/qt/res/src/qt.svg,
|
||||||
src/qt/res/src/verify.svg,
|
src/qt/res/src/verify.svg,
|
||||||
|
|
|
@ -216,8 +216,6 @@ RES_ICONS = \
|
||||||
qt/res/icons/about_qt.png \
|
qt/res/icons/about_qt.png \
|
||||||
qt/res/icons/bitcoin.ico \
|
qt/res/icons/bitcoin.ico \
|
||||||
qt/res/icons/bitcoin.png \
|
qt/res/icons/bitcoin.png \
|
||||||
qt/res/icons/bitcoin_testnet.ico \
|
|
||||||
qt/res/icons/bitcoin_testnet.png \
|
|
||||||
qt/res/icons/clock1.png \
|
qt/res/icons/clock1.png \
|
||||||
qt/res/icons/clock2.png \
|
qt/res/icons/clock2.png \
|
||||||
qt/res/icons/clock3.png \
|
qt/res/icons/clock3.png \
|
||||||
|
@ -315,9 +313,7 @@ BITCOIN_QT_CPP += \
|
||||||
endif
|
endif
|
||||||
|
|
||||||
RES_IMAGES = \
|
RES_IMAGES = \
|
||||||
qt/res/images/about.png \
|
qt/res/images/about.png
|
||||||
qt/res/images/splash.png \
|
|
||||||
qt/res/images/splash_testnet.png
|
|
||||||
|
|
||||||
RES_MOVIES = $(wildcard qt/res/movies/spinner-*.png)
|
RES_MOVIES = $(wildcard qt/res/movies/spinner-*.png)
|
||||||
|
|
||||||
|
@ -371,7 +367,7 @@ qt_bitcoin_qt_LIBTOOLFLAGS = --tag CXX
|
||||||
#locale/foo.ts -> locale/foo.qm
|
#locale/foo.ts -> locale/foo.qm
|
||||||
QT_QM=$(QT_TS:.ts=.qm)
|
QT_QM=$(QT_TS:.ts=.qm)
|
||||||
|
|
||||||
.SECONDARY: $(QT_QM)
|
SECONDARY: $(QT_QM)
|
||||||
|
|
||||||
qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES)
|
qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES)
|
||||||
@test -n $(XGETTEXT) || echo "xgettext is required for updating translations"
|
@test -n $(XGETTEXT) || echo "xgettext is required for updating translations"
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
<file alias="editpaste">res/icons/editpaste.png</file>
|
<file alias="editpaste">res/icons/editpaste.png</file>
|
||||||
<file alias="editcopy">res/icons/editcopy.png</file>
|
<file alias="editcopy">res/icons/editcopy.png</file>
|
||||||
<file alias="add">res/icons/add.png</file>
|
<file alias="add">res/icons/add.png</file>
|
||||||
<file alias="bitcoin_testnet">res/icons/bitcoin_testnet.png</file>
|
|
||||||
<file alias="edit">res/icons/edit.png</file>
|
<file alias="edit">res/icons/edit.png</file>
|
||||||
<file alias="history">res/icons/history.png</file>
|
<file alias="history">res/icons/history.png</file>
|
||||||
<file alias="overview">res/icons/overview.png</file>
|
<file alias="overview">res/icons/overview.png</file>
|
||||||
|
@ -52,8 +51,6 @@
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/images">
|
<qresource prefix="/images">
|
||||||
<file alias="about">res/images/about.png</file>
|
<file alias="about">res/images/about.png</file>
|
||||||
<file alias="splash">res/images/splash.png</file>
|
|
||||||
<file alias="splash_testnet">res/images/splash_testnet.png</file>
|
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/movies">
|
<qresource prefix="/movies">
|
||||||
<file alias="spinner-000">res/movies/spinner-000.png</file>
|
<file alias="spinner-000">res/movies/spinner-000.png</file>
|
||||||
|
|
|
@ -11,22 +11,22 @@
|
||||||
static const struct {
|
static const struct {
|
||||||
const char *networkId;
|
const char *networkId;
|
||||||
const char *appName;
|
const char *appName;
|
||||||
const char *appIcon;
|
const int iconColorHueShift;
|
||||||
|
const int iconColorSaturationReduction;
|
||||||
const char *titleAddText;
|
const char *titleAddText;
|
||||||
const char *splashImage;
|
|
||||||
} network_styles[] = {
|
} network_styles[] = {
|
||||||
{"main", QAPP_APP_NAME_DEFAULT, ":/icons/bitcoin", "", ":/images/splash"},
|
{"main", QAPP_APP_NAME_DEFAULT, 0, 0, ""},
|
||||||
{"test", QAPP_APP_NAME_TESTNET, ":/icons/bitcoin_testnet", QT_TRANSLATE_NOOP("SplashScreen", "[testnet]"), ":/images/splash_testnet"},
|
{"test", QAPP_APP_NAME_TESTNET, 70, 30, QT_TRANSLATE_NOOP("SplashScreen", "[testnet]")},
|
||||||
{"regtest", QAPP_APP_NAME_TESTNET, ":/icons/bitcoin_testnet", "[regtest]", ":/images/splash_testnet"}
|
{"regtest", QAPP_APP_NAME_TESTNET, 70, 30, "[regtest]"}
|
||||||
};
|
};
|
||||||
static const unsigned network_styles_count = sizeof(network_styles)/sizeof(*network_styles);
|
static const unsigned network_styles_count = sizeof(network_styles)/sizeof(*network_styles);
|
||||||
|
|
||||||
// titleAddText needs to be const char* for tr()
|
// titleAddText needs to be const char* for tr()
|
||||||
NetworkStyle::NetworkStyle(const QString &appName, const QString &appIcon, const char *titleAddText, const QString &splashImage):
|
NetworkStyle::NetworkStyle(const QString &appName, const int iconColorHueShift, const int iconColorSaturationReduction, const char *titleAddText):
|
||||||
appName(appName),
|
appName(appName),
|
||||||
appIcon(appIcon),
|
iconColorHueShift(iconColorHueShift),
|
||||||
titleAddText(qApp->translate("SplashScreen", titleAddText)),
|
iconColorSaturationReduction(iconColorSaturationReduction),
|
||||||
splashImage(splashImage)
|
titleAddText(qApp->translate("SplashScreen", titleAddText))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,10 +38,78 @@ const NetworkStyle *NetworkStyle::instantiate(const QString &networkId)
|
||||||
{
|
{
|
||||||
return new NetworkStyle(
|
return new NetworkStyle(
|
||||||
network_styles[x].appName,
|
network_styles[x].appName,
|
||||||
network_styles[x].appIcon,
|
network_styles[x].iconColorHueShift,
|
||||||
network_styles[x].titleAddText,
|
network_styles[x].iconColorSaturationReduction,
|
||||||
network_styles[x].splashImage);
|
network_styles[x].titleAddText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QIcon NetworkStyle::getAppIcon() const
|
||||||
|
{
|
||||||
|
return getAppIcon(QSize(256,256));
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon NetworkStyle::getAppIcon(const QSize size) const
|
||||||
|
{
|
||||||
|
// load pixmap
|
||||||
|
QPixmap pixmap(":/icons/bitcoin");
|
||||||
|
|
||||||
|
if(pixmap.size().width() != size.width() && pixmap.size().height() != size.height())
|
||||||
|
{
|
||||||
|
QPixmap scaledPixmap = pixmap.scaled(size, Qt::KeepAspectRatio);
|
||||||
|
if(!scaledPixmap.isNull())
|
||||||
|
{
|
||||||
|
pixmap = scaledPixmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(iconColorHueShift != 0 && iconColorSaturationReduction != 0)
|
||||||
|
{
|
||||||
|
// copy the pixmap because on linux the original pixmap will be affected
|
||||||
|
pixmap = pixmap.copy();
|
||||||
|
|
||||||
|
// generate QImage from QPixmap
|
||||||
|
QImage img = pixmap.toImage();
|
||||||
|
|
||||||
|
int h,s,l,a;
|
||||||
|
|
||||||
|
// traverse though lines
|
||||||
|
for(int y=0;y<img.height();y++)
|
||||||
|
{
|
||||||
|
QRgb *scL = reinterpret_cast< QRgb *>( img.scanLine( y ) );
|
||||||
|
|
||||||
|
// loop through pixels
|
||||||
|
for(int x=0;x<img.width();x++)
|
||||||
|
{
|
||||||
|
// preserve alpha because QColor::getHsl doesen't return the alpha value
|
||||||
|
a = qAlpha(scL[x]);
|
||||||
|
QColor col(scL[x]);
|
||||||
|
|
||||||
|
// get hue value
|
||||||
|
col.getHsl(&h,&s,&l);
|
||||||
|
|
||||||
|
// rotate color on RGB color circle
|
||||||
|
// 70° should end up with the typical "testnet" green
|
||||||
|
h+=iconColorHueShift;
|
||||||
|
|
||||||
|
// change saturation value
|
||||||
|
if(s>iconColorSaturationReduction)
|
||||||
|
{
|
||||||
|
s -= iconColorSaturationReduction;
|
||||||
|
}
|
||||||
|
col.setHsl(h,s,l,a);
|
||||||
|
|
||||||
|
// set the pixel
|
||||||
|
scL[x] = col.rgba();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//convert back to QPixmap
|
||||||
|
pixmap.convertFromImage(img);
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon icon(pixmap);
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
|
@ -17,17 +17,17 @@ public:
|
||||||
static const NetworkStyle *instantiate(const QString &networkId);
|
static const NetworkStyle *instantiate(const QString &networkId);
|
||||||
|
|
||||||
const QString &getAppName() const { return appName; }
|
const QString &getAppName() const { return appName; }
|
||||||
const QIcon &getAppIcon() const { return appIcon; }
|
|
||||||
const QString &getTitleAddText() const { return titleAddText; }
|
const QString &getTitleAddText() const { return titleAddText; }
|
||||||
const QPixmap &getSplashImage() const { return splashImage; }
|
|
||||||
|
|
||||||
|
QIcon getAppIcon() const;
|
||||||
|
QIcon getAppIcon(const QSize size) const;
|
||||||
private:
|
private:
|
||||||
NetworkStyle(const QString &appName, const QString &appIcon, const char *titleAddText, const QString &splashImage);
|
NetworkStyle(const QString &appName, const int iconColorHueShift, const int iconColorSaturationReduction, const char *titleAddText);
|
||||||
|
|
||||||
QString appName;
|
QString appName;
|
||||||
QIcon appIcon;
|
int iconColorHueShift;
|
||||||
|
int iconColorSaturationReduction;
|
||||||
QString titleAddText;
|
QString titleAddText;
|
||||||
QPixmap splashImage;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BITCOIN_QT_NETWORKSTYLE_H
|
#endif // BITCOIN_QT_NETWORKSTYLE_H
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
IDI_ICON1 ICON DISCARDABLE "icons/bitcoin.ico"
|
IDI_ICON1 ICON DISCARDABLE "icons/bitcoin.ico"
|
||||||
IDI_ICON2 ICON DISCARDABLE "icons/bitcoin_testnet.ico"
|
|
||||||
|
|
||||||
#include <windows.h> // needed for VERSIONINFO
|
#include <windows.h> // needed for VERSIONINFO
|
||||||
#include "../../clientversion.h" // holds the needed client version information
|
#include "../../clientversion.h" // holds the needed client version information
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 342 KiB |
Binary file not shown.
Before Width: | Height: | Size: 45 KiB |
Binary file not shown.
Before Width: | Height: | Size: 28 KiB |
Binary file not shown.
Before Width: | Height: | Size: 42 KiB |
Binary file not shown.
Before Width: | Height: | Size: 33 KiB |
|
@ -19,6 +19,7 @@
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QRadialGradient>
|
||||||
|
|
||||||
SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) :
|
SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) :
|
||||||
QWidget(0, f), curAlignment(0)
|
QWidget(0, f), curAlignment(0)
|
||||||
|
@ -30,6 +31,10 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle)
|
||||||
int titleCopyrightVSpace = 40;
|
int titleCopyrightVSpace = 40;
|
||||||
|
|
||||||
float fontFactor = 1.0;
|
float fontFactor = 1.0;
|
||||||
|
float devicePixelRatio = 1.0;
|
||||||
|
#if QT_VERSION > 0x050100
|
||||||
|
devicePixelRatio = ((QGuiApplication*)QCoreApplication::instance())->devicePixelRatio();
|
||||||
|
#endif
|
||||||
|
|
||||||
// define text to place
|
// define text to place
|
||||||
QString titleText = tr("Bitcoin Core");
|
QString titleText = tr("Bitcoin Core");
|
||||||
|
@ -39,12 +44,34 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle)
|
||||||
|
|
||||||
QString font = "Arial";
|
QString font = "Arial";
|
||||||
|
|
||||||
// load the bitmap for writing some text over it
|
// create a bitmap according to device pixelratio
|
||||||
pixmap = networkStyle->getSplashImage();
|
QSize splashSize(480*devicePixelRatio,320*devicePixelRatio);
|
||||||
|
pixmap = QPixmap(splashSize);
|
||||||
|
|
||||||
|
#if QT_VERSION > 0x050100
|
||||||
|
// change to HiDPI if it makes sense
|
||||||
|
pixmap.setDevicePixelRatio(devicePixelRatio);
|
||||||
|
#endif
|
||||||
|
|
||||||
QPainter pixPaint(&pixmap);
|
QPainter pixPaint(&pixmap);
|
||||||
pixPaint.setPen(QColor(100,100,100));
|
pixPaint.setPen(QColor(100,100,100));
|
||||||
|
|
||||||
|
// draw a slighly 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(-150,-122), QSize(430,430));
|
||||||
|
|
||||||
|
const QSize requiredSize(1024,1024);
|
||||||
|
QIcon appIcon = networkStyle->getAppIcon(requiredSize);
|
||||||
|
QPixmap icon(appIcon.pixmap(requiredSize));
|
||||||
|
|
||||||
|
pixPaint.drawPixmap(rectIcon, icon);
|
||||||
|
|
||||||
// check font size and drawing with
|
// check font size and drawing with
|
||||||
pixPaint.setFont(QFont(font, 33*fontFactor));
|
pixPaint.setFont(QFont(font, 33*fontFactor));
|
||||||
QFontMetrics fm = pixPaint.fontMetrics();
|
QFontMetrics fm = pixPaint.fontMetrics();
|
||||||
|
@ -57,7 +84,7 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle)
|
||||||
pixPaint.setFont(QFont(font, 33*fontFactor));
|
pixPaint.setFont(QFont(font, 33*fontFactor));
|
||||||
fm = pixPaint.fontMetrics();
|
fm = pixPaint.fontMetrics();
|
||||||
titleTextWidth = fm.width(titleText);
|
titleTextWidth = fm.width(titleText);
|
||||||
pixPaint.drawText(pixmap.width()-titleTextWidth-paddingRight,paddingTop,titleText);
|
pixPaint.drawText(pixmap.width()/devicePixelRatio-titleTextWidth-paddingRight,paddingTop,titleText);
|
||||||
|
|
||||||
pixPaint.setFont(QFont(font, 15*fontFactor));
|
pixPaint.setFont(QFont(font, 15*fontFactor));
|
||||||
|
|
||||||
|
@ -68,11 +95,11 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle)
|
||||||
pixPaint.setFont(QFont(font, 10*fontFactor));
|
pixPaint.setFont(QFont(font, 10*fontFactor));
|
||||||
titleVersionVSpace -= 5;
|
titleVersionVSpace -= 5;
|
||||||
}
|
}
|
||||||
pixPaint.drawText(pixmap.width()-titleTextWidth-paddingRight+2,paddingTop+titleVersionVSpace,versionText);
|
pixPaint.drawText(pixmap.width()/devicePixelRatio-titleTextWidth-paddingRight+2,paddingTop+titleVersionVSpace,versionText);
|
||||||
|
|
||||||
// draw copyright stuff
|
// draw copyright stuff
|
||||||
pixPaint.setFont(QFont(font, 10*fontFactor));
|
pixPaint.setFont(QFont(font, 10*fontFactor));
|
||||||
pixPaint.drawText(pixmap.width()-titleTextWidth-paddingRight,paddingTop+titleCopyrightVSpace,copyrightText);
|
pixPaint.drawText(pixmap.width()/devicePixelRatio-titleTextWidth-paddingRight,paddingTop+titleCopyrightVSpace,copyrightText);
|
||||||
|
|
||||||
// draw additional text if special network
|
// draw additional text if special network
|
||||||
if(!titleAddText.isEmpty()) {
|
if(!titleAddText.isEmpty()) {
|
||||||
|
@ -81,7 +108,7 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle)
|
||||||
pixPaint.setFont(boldFont);
|
pixPaint.setFont(boldFont);
|
||||||
fm = pixPaint.fontMetrics();
|
fm = pixPaint.fontMetrics();
|
||||||
int titleAddTextWidth = fm.width(titleAddText);
|
int titleAddTextWidth = fm.width(titleAddText);
|
||||||
pixPaint.drawText(pixmap.width()-titleAddTextWidth-10,15,titleAddText);
|
pixPaint.drawText(pixmap.width()/devicePixelRatio-titleAddTextWidth-10,15,titleAddText);
|
||||||
}
|
}
|
||||||
|
|
||||||
pixPaint.end();
|
pixPaint.end();
|
||||||
|
@ -90,7 +117,7 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle)
|
||||||
setWindowTitle(titleText + " " + titleAddText);
|
setWindowTitle(titleText + " " + titleAddText);
|
||||||
|
|
||||||
// Resize window and move to center of desktop, disallow resizing
|
// Resize window and move to center of desktop, disallow resizing
|
||||||
QRect r(QPoint(), pixmap.size());
|
QRect r(QPoint(), QSize(pixmap.size().width()/devicePixelRatio,pixmap.size().height()/devicePixelRatio));
|
||||||
resize(r.size());
|
resize(r.size());
|
||||||
setFixedSize(r.size());
|
setFixedSize(r.size());
|
||||||
move(QApplication::desktop()->screenGeometry().center() - r.center());
|
move(QApplication::desktop()->screenGeometry().center() - r.center());
|
||||||
|
|
Loading…
Reference in a new issue