qt: add network-specific style object

Mainly cleanups: Gets rid of isTestNet everywhere, by keeping track
of network-specific theming in a central place.

Also makes GUI no longer dependent on the network ID enumeration, which
alleviates concerns about #4802.
This commit is contained in:
Wladimir J. van der Laan 2014-10-09 11:04:49 +02:00 committed by jtimon
parent dec58922d0
commit 6de50c3c9a
8 changed files with 125 additions and 75 deletions

View file

@ -178,6 +178,7 @@ BITCOIN_QT_H = \
qt/macdockiconhandler.h \ qt/macdockiconhandler.h \
qt/macnotificationhandler.h \ qt/macnotificationhandler.h \
qt/monitoreddatamapper.h \ qt/monitoreddatamapper.h \
qt/networkstyle.h \
qt/notificator.h \ qt/notificator.h \
qt/openuridialog.h \ qt/openuridialog.h \
qt/optionsdialog.h \ qt/optionsdialog.h \
@ -269,6 +270,7 @@ BITCOIN_QT_CPP = \
qt/guiutil.cpp \ qt/guiutil.cpp \
qt/intro.cpp \ qt/intro.cpp \
qt/monitoreddatamapper.cpp \ qt/monitoreddatamapper.cpp \
qt/networkstyle.cpp \
qt/notificator.cpp \ qt/notificator.cpp \
qt/optionsdialog.cpp \ qt/optionsdialog.cpp \
qt/optionsmodel.cpp \ qt/optionsmodel.cpp \

View file

@ -12,6 +12,7 @@
#include "guiconstants.h" #include "guiconstants.h"
#include "guiutil.h" #include "guiutil.h"
#include "intro.h" #include "intro.h"
#include "networkstyle.h"
#include "optionsmodel.h" #include "optionsmodel.h"
#include "splashscreen.h" #include "splashscreen.h"
#include "utilitydialog.h" #include "utilitydialog.h"
@ -190,9 +191,9 @@ public:
/// Create options model /// Create options model
void createOptionsModel(); void createOptionsModel();
/// Create main window /// Create main window
void createWindow(bool isaTestNet); void createWindow(const NetworkStyle *networkStyle);
/// Create splash screen /// Create splash screen
void createSplashScreen(bool isaTestNet); void createSplashScreen(const NetworkStyle *networkStyle);
/// Request core initialization /// Request core initialization
void requestInitialize(); void requestInitialize();
@ -331,18 +332,18 @@ void BitcoinApplication::createOptionsModel()
optionsModel = new OptionsModel(); optionsModel = new OptionsModel();
} }
void BitcoinApplication::createWindow(bool isaTestNet) void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
{ {
window = new BitcoinGUI(isaTestNet, 0); window = new BitcoinGUI(networkStyle, 0);
pollShutdownTimer = new QTimer(window); pollShutdownTimer = new QTimer(window);
connect(pollShutdownTimer, SIGNAL(timeout()), window, SLOT(detectShutdown())); connect(pollShutdownTimer, SIGNAL(timeout()), window, SLOT(detectShutdown()));
pollShutdownTimer->start(200); pollShutdownTimer->start(200);
} }
void BitcoinApplication::createSplashScreen(bool isaTestNet) void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
{ {
SplashScreen *splash = new SplashScreen(0, isaTestNet); SplashScreen *splash = new SplashScreen(0, networkStyle);
// We don't hold a direct pointer to the splash screen after creation, so use // We don't hold a direct pointer to the splash screen after creation, so use
// Qt::WA_DeleteOnClose to make sure that the window will be deleted eventually. // Qt::WA_DeleteOnClose to make sure that the window will be deleted eventually.
splash->setAttribute(Qt::WA_DeleteOnClose); splash->setAttribute(Qt::WA_DeleteOnClose);
@ -572,12 +573,10 @@ int main(int argc, char *argv[])
if (!PaymentServer::ipcParseCommandLine(argc, argv)) if (!PaymentServer::ipcParseCommandLine(argc, argv))
exit(0); exit(0);
#endif #endif
bool isaTestNet = Params().NetworkID() != CBaseChainParams::MAIN; QScopedPointer<const NetworkStyle> networkStyle(NetworkStyle::instantiate(QString::fromStdString(Params().NetworkIDString())));
assert(!networkStyle.isNull());
// Allow for separate UI settings for testnets // Allow for separate UI settings for testnets
if (isaTestNet) QApplication::setApplicationName(networkStyle->getAppName());
QApplication::setApplicationName(QAPP_APP_NAME_TESTNET);
else
QApplication::setApplicationName(QAPP_APP_NAME_DEFAULT);
// Re-initialize translations after changing application name (language in network-specific settings can be different) // Re-initialize translations after changing application name (language in network-specific settings can be different)
initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator); initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);
@ -617,11 +616,11 @@ int main(int argc, char *argv[])
uiInterface.InitMessage.connect(InitMessage); uiInterface.InitMessage.connect(InitMessage);
if (GetBoolArg("-splash", true) && !GetBoolArg("-min", false)) if (GetBoolArg("-splash", true) && !GetBoolArg("-min", false))
app.createSplashScreen(isaTestNet); app.createSplashScreen(networkStyle.data());
try try
{ {
app.createWindow(isaTestNet); app.createWindow(networkStyle.data());
app.requestInitialize(); app.requestInitialize();
#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000 #if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("Bitcoin Core didn't yet exit safely..."), (HWND)app.getMainWinId()); WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("Bitcoin Core didn't yet exit safely..."), (HWND)app.getMainWinId());

View file

@ -8,6 +8,7 @@
#include "clientmodel.h" #include "clientmodel.h"
#include "guiconstants.h" #include "guiconstants.h"
#include "guiutil.h" #include "guiutil.h"
#include "networkstyle.h"
#include "notificator.h" #include "notificator.h"
#include "openuridialog.h" #include "openuridialog.h"
#include "optionsdialog.h" #include "optionsdialog.h"
@ -59,7 +60,7 @@
const QString BitcoinGUI::DEFAULT_WALLET = "~Default"; const QString BitcoinGUI::DEFAULT_WALLET = "~Default";
BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) : BitcoinGUI::BitcoinGUI(const NetworkStyle *networkStyle, QWidget *parent) :
QMainWindow(parent), QMainWindow(parent),
clientModel(0), clientModel(0),
walletFrame(0), walletFrame(0),
@ -112,26 +113,13 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) :
} else { } else {
windowTitle += tr("Node"); windowTitle += tr("Node");
} }
windowTitle += " " + networkStyle->getTitleAddText();
if (!fIsTestnet)
{
#ifndef Q_OS_MAC #ifndef Q_OS_MAC
QApplication::setWindowIcon(QIcon(":icons/bitcoin")); QApplication::setWindowIcon(networkStyle->getAppIcon());
setWindowIcon(QIcon(":icons/bitcoin")); setWindowIcon(networkStyle->getAppIcon());
#else #else
MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin")); MacDockIconHandler::instance()->setIcon(networkStyle->getAppIcon());
#endif #endif
}
else
{
windowTitle += " " + tr("[testnet]");
#ifndef Q_OS_MAC
QApplication::setWindowIcon(QIcon(":icons/bitcoin_testnet"));
setWindowIcon(QIcon(":icons/bitcoin_testnet"));
#else
MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
#endif
}
setWindowTitle(windowTitle); setWindowTitle(windowTitle);
#if defined(Q_OS_MAC) && QT_VERSION < 0x050000 #if defined(Q_OS_MAC) && QT_VERSION < 0x050000
@ -161,7 +149,7 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) :
// Create actions for the toolbar, menu bar and tray/dock icon // Create actions for the toolbar, menu bar and tray/dock icon
// Needs walletFrame to be initialized // Needs walletFrame to be initialized
createActions(fIsTestnet); createActions(networkStyle);
// Create application menu bar // Create application menu bar
createMenuBar(); createMenuBar();
@ -170,7 +158,7 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) :
createToolBars(); createToolBars();
// Create system tray icon and notification // Create system tray icon and notification
createTrayIcon(fIsTestnet); createTrayIcon(networkStyle);
// Create status bar // Create status bar
statusBar(); statusBar();
@ -248,7 +236,7 @@ BitcoinGUI::~BitcoinGUI()
#endif #endif
} }
void BitcoinGUI::createActions(bool fIsTestnet) void BitcoinGUI::createActions(const NetworkStyle *networkStyle)
{ {
QActionGroup *tabGroup = new QActionGroup(this); QActionGroup *tabGroup = new QActionGroup(this);
@ -295,10 +283,7 @@ void BitcoinGUI::createActions(bool fIsTestnet)
quitAction->setStatusTip(tr("Quit application")); quitAction->setStatusTip(tr("Quit application"));
quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
quitAction->setMenuRole(QAction::QuitRole); quitAction->setMenuRole(QAction::QuitRole);
if (!fIsTestnet) aboutAction = new QAction(networkStyle->getAppIcon(), tr("&About Bitcoin Core"), this);
aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Bitcoin Core"), this);
else
aboutAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&About Bitcoin Core"), this);
aboutAction->setStatusTip(tr("Show information about Bitcoin Core")); aboutAction->setStatusTip(tr("Show information about Bitcoin Core"));
aboutAction->setMenuRole(QAction::AboutRole); aboutAction->setMenuRole(QAction::AboutRole);
#if QT_VERSION < 0x050000 #if QT_VERSION < 0x050000
@ -311,10 +296,7 @@ void BitcoinGUI::createActions(bool fIsTestnet)
optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this); optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
optionsAction->setStatusTip(tr("Modify configuration options for Bitcoin")); optionsAction->setStatusTip(tr("Modify configuration options for Bitcoin"));
optionsAction->setMenuRole(QAction::PreferencesRole); optionsAction->setMenuRole(QAction::PreferencesRole);
if (!fIsTestnet) toggleHideAction = new QAction(networkStyle->getAppIcon(), tr("&Show / Hide"), this);
toggleHideAction = new QAction(QIcon(":/icons/bitcoin"), tr("&Show / Hide"), this);
else
toggleHideAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&Show / Hide"), this);
toggleHideAction->setStatusTip(tr("Show or hide the main Window")); toggleHideAction->setStatusTip(tr("Show or hide the main Window"));
encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this); encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this);
@ -505,22 +487,13 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
openAction->setEnabled(enabled); openAction->setEnabled(enabled);
} }
void BitcoinGUI::createTrayIcon(bool fIsTestnet) void BitcoinGUI::createTrayIcon(const NetworkStyle *networkStyle)
{ {
#ifndef Q_OS_MAC #ifndef Q_OS_MAC
trayIcon = new QSystemTrayIcon(this); trayIcon = new QSystemTrayIcon(this);
QString toolTip = tr("Bitcoin Core client") + " " + networkStyle->getTitleAddText();
if (!fIsTestnet) trayIcon->setToolTip(toolTip);
{ trayIcon->setIcon(networkStyle->getAppIcon());
trayIcon->setToolTip(tr("Bitcoin Core client"));
trayIcon->setIcon(QIcon(":/icons/bitcoin"));
}
else
{
trayIcon->setToolTip(tr("Bitcoin Core client") + " " + tr("[testnet]"));
trayIcon->setIcon(QIcon(":/icons/bitcoin_testnet"));
}
trayIcon->show(); trayIcon->show();
#endif #endif

View file

@ -19,6 +19,7 @@
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
class ClientModel; class ClientModel;
class NetworkStyle;
class Notificator; class Notificator;
class OptionsModel; class OptionsModel;
class RPCConsole; class RPCConsole;
@ -46,7 +47,7 @@ class BitcoinGUI : public QMainWindow
public: public:
static const QString DEFAULT_WALLET; static const QString DEFAULT_WALLET;
explicit BitcoinGUI(bool fIsTestnet = false, QWidget *parent = 0); explicit BitcoinGUI(const NetworkStyle *networkStyle, QWidget *parent = 0);
~BitcoinGUI(); ~BitcoinGUI();
/** Set the client model. /** Set the client model.
@ -114,13 +115,13 @@ private:
int spinnerFrame; int spinnerFrame;
/** Create the main UI actions. */ /** Create the main UI actions. */
void createActions(bool fIsTestnet); void createActions(const NetworkStyle *networkStyle);
/** Create the menu bar and sub-menus. */ /** Create the menu bar and sub-menus. */
void createMenuBar(); void createMenuBar();
/** Create the toolbars */ /** Create the toolbars */
void createToolBars(); void createToolBars();
/** Create system tray icon and notification */ /** Create system tray icon and notification */
void createTrayIcon(bool fIsTestnet); void createTrayIcon(const NetworkStyle *networkStyle);
/** Create system tray menu (or setup the dock menu) */ /** Create system tray menu (or setup the dock menu) */
void createTrayIconMenu(); void createTrayIconMenu();

47
src/qt/networkstyle.cpp Normal file
View file

@ -0,0 +1,47 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "networkstyle.h"
#include "guiconstants.h"
#include <QApplication>
static const struct {
const char *networkId;
const char *appName;
const char *appIcon;
const char *titleAddText;
const char *splashImage;
} network_styles[] = {
{"main", QAPP_APP_NAME_DEFAULT, ":/icons/bitcoin", "", ":/images/splash"},
{"test", QAPP_APP_NAME_TESTNET, ":/icons/bitcoin_testnet", QT_TRANSLATE_NOOP("SplashScreen", "[testnet]"), ":/images/splash_testnet"},
{"regtest", QAPP_APP_NAME_TESTNET, ":/icons/bitcoin_testnet", "[regtest]", ":/images/splash_testnet"}
};
static const unsigned network_styles_count = sizeof(network_styles)/sizeof(*network_styles);
// titleAddText needs to be const char* for tr()
NetworkStyle::NetworkStyle(const QString &appName, const QString &appIcon, const char *titleAddText, const QString &splashImage):
appName(appName),
appIcon(appIcon),
titleAddText(qApp->translate("SplashScreen", titleAddText)),
splashImage(splashImage)
{
}
const NetworkStyle *NetworkStyle::instantiate(const QString &networkId)
{
for (unsigned x=0; x<network_styles_count; ++x)
{
if (networkId == network_styles[x].networkId)
{
return new NetworkStyle(
network_styles[x].appName,
network_styles[x].appIcon,
network_styles[x].titleAddText,
network_styles[x].splashImage);
}
}
return 0;
}

33
src/qt/networkstyle.h Normal file
View file

@ -0,0 +1,33 @@
// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef H_NETWORKSTYLE
#define H_NETWORKSTYLE
#include <QIcon>
#include <QPixmap>
#include <QString>
/* Coin network-specific GUI style information */
class NetworkStyle
{
public:
/** Get style associated with provided BIP70 network id, or 0 if not known */
static const NetworkStyle *instantiate(const QString &networkId);
const QString &getAppName() const { return appName; }
const QIcon &getAppIcon() const { return appIcon; }
const QString &getTitleAddText() const { return titleAddText; }
const QPixmap &getSplashImage() const { return splashImage; }
private:
NetworkStyle(const QString &appName, const QString &appIcon, const char *titleAddText, const QString &splashImage);
QString appName;
QIcon appIcon;
QString titleAddText;
QPixmap splashImage;
};
#endif // H_NETWORKSTYLE

View file

@ -6,6 +6,7 @@
#include "clientversion.h" #include "clientversion.h"
#include "init.h" #include "init.h"
#include "networkstyle.h"
#include "ui_interface.h" #include "ui_interface.h"
#include "util.h" #include "util.h"
#include "version.h" #include "version.h"
@ -19,7 +20,7 @@
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QPainter> #include <QPainter>
SplashScreen::SplashScreen(Qt::WindowFlags f, bool isTestNet) : SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) :
QWidget(0, f), curAlignment(0) QWidget(0, f), curAlignment(0)
{ {
// set reference point, paddings // set reference point, paddings
@ -34,17 +35,12 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, bool isTestNet) :
QString titleText = tr("Bitcoin Core"); QString titleText = tr("Bitcoin Core");
QString versionText = QString("Version %1").arg(QString::fromStdString(FormatFullVersion())); QString versionText = QString("Version %1").arg(QString::fromStdString(FormatFullVersion()));
QString copyrightText = QChar(0xA9)+QString(" 2009-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Bitcoin Core developers")); QString copyrightText = QChar(0xA9)+QString(" 2009-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Bitcoin Core developers"));
QString testnetAddText = QString(tr("[testnet]")); // define text to place as single text object QString titleAddText = networkStyle->getTitleAddText();
QString font = "Arial"; QString font = "Arial";
// load the bitmap for writing some text over it // load the bitmap for writing some text over it
if(isTestNet) { pixmap = networkStyle->getSplashImage();
pixmap = QPixmap(":/images/splash_testnet");
}
else {
pixmap = QPixmap(":/images/splash");
}
QPainter pixPaint(&pixmap); QPainter pixPaint(&pixmap);
pixPaint.setPen(QColor(100,100,100)); pixPaint.setPen(QColor(100,100,100));
@ -78,23 +74,20 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, bool isTestNet) :
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()-titleTextWidth-paddingRight,paddingTop+titleCopyrightVSpace,copyrightText);
// draw testnet string if testnet is on // draw additional text if special network
if(isTestNet) { if(!titleAddText.isEmpty()) {
QFont boldFont = QFont(font, 10*fontFactor); QFont boldFont = QFont(font, 10*fontFactor);
boldFont.setWeight(QFont::Bold); boldFont.setWeight(QFont::Bold);
pixPaint.setFont(boldFont); pixPaint.setFont(boldFont);
fm = pixPaint.fontMetrics(); fm = pixPaint.fontMetrics();
int testnetAddTextWidth = fm.width(testnetAddText); int titleAddTextWidth = fm.width(titleAddText);
pixPaint.drawText(pixmap.width()-testnetAddTextWidth-10,15,testnetAddText); pixPaint.drawText(pixmap.width()-titleAddTextWidth-10,15,titleAddText);
} }
pixPaint.end(); pixPaint.end();
// Set window title // Set window title
if(isTestNet) setWindowTitle(titleText + " " + titleAddText);
setWindowTitle(titleText + " " + testnetAddText);
else
setWindowTitle(titleText);
// 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(), pixmap.size());

View file

@ -7,6 +7,8 @@
#include <QSplashScreen> #include <QSplashScreen>
class NetworkStyle;
/** Class for the splashscreen with information of the running client. /** Class for the splashscreen with information of the running client.
* *
* @note this is intentionally not a QSplashScreen. Bitcoin Core initialization * @note this is intentionally not a QSplashScreen. Bitcoin Core initialization
@ -18,7 +20,7 @@ class SplashScreen : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit SplashScreen(Qt::WindowFlags f, bool isTestNet); explicit SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle);
~SplashScreen(); ~SplashScreen();
protected: protected: