mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 12:32:48 +01:00
qt: Introduce runtime theme changes (#3559)
* qt: Set the default theme properly * qt: Keep track of disabled rects for macOS This allows enabling them again on theme changes * qt: Introduce runtime theme changes Runtime theme changes means no more client restart required if the theme gets changed in the options dialog. In the RPCConsole's StyleChange event make sure following things are still correct after a runtime theme change: - Hide prompt icon for dash themes in rpc console if dash theme gets activated. - Clear rpc console on theme changes to make sure fonts/sizes/colors are correct.
This commit is contained in:
parent
b3738648d6
commit
7db9909a17
@ -131,8 +131,6 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *
|
||||
spinnerFrame(0),
|
||||
platformStyle(_platformStyle)
|
||||
{
|
||||
GUIUtil::loadStyleSheet(this);
|
||||
|
||||
QSettings settings;
|
||||
if (!restoreGeometry(settings.value("MainWindowGeometry").toByteArray())) {
|
||||
// Restore failed (perhaps missing setting), center the window
|
||||
@ -856,6 +854,7 @@ void BitcoinGUI::optionsClicked()
|
||||
|
||||
OptionsDialog dlg(this, enableWallet);
|
||||
dlg.setModel(clientModel->getOptionsModel());
|
||||
connect(&dlg, &OptionsDialog::themeChanged, [=]() { GUIUtil::loadTheme(); });
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
|
@ -419,6 +419,8 @@ void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
|
||||
{
|
||||
window = new BitcoinGUI(platformStyle, networkStyle, 0);
|
||||
|
||||
GUIUtil::loadTheme(window);
|
||||
|
||||
pollShutdownTimer = new QTimer(window);
|
||||
connect(pollShutdownTimer, SIGNAL(timeout()), window, SLOT(detectShutdown()));
|
||||
}
|
||||
|
@ -139,6 +139,11 @@ static std::set<QWidget*> setFixedPitchFontUpdates;
|
||||
// Contains all widgets where a non-default fontsize has been seet with GUIUtil::setFont
|
||||
static std::map<QWidget*, int> mapFontSizeUpdates;
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
// Contains all widgets where the macOS focus rect has been disabled.
|
||||
static std::set<QWidget*> setRectsDisabled;
|
||||
#endif
|
||||
|
||||
static const std::map<ThemedColor, QColor> themedColors = {
|
||||
{ ThemedColor::DEFAULT, QColor(85, 85, 85) },
|
||||
{ ThemedColor::UNCONFIRMED, QColor(128, 128, 128) },
|
||||
@ -1064,7 +1069,12 @@ const std::vector<QString> listThemes()
|
||||
return vecThemes;
|
||||
}
|
||||
|
||||
void loadStyleSheet(QWidget* widget, bool fDebugWidget)
|
||||
const QString getDefaultTheme()
|
||||
{
|
||||
return defaultTheme;
|
||||
}
|
||||
|
||||
void loadStyleSheet(QWidget* widget, bool fForceUpdate)
|
||||
{
|
||||
AssertLockNotHeld(cs_css);
|
||||
LOCK(cs_css);
|
||||
@ -1075,7 +1085,7 @@ void loadStyleSheet(QWidget* widget, bool fDebugWidget)
|
||||
bool fDebugCustomStyleSheets = gArgs.GetBoolArg("-debug-ui", false) && isStyleSheetDirectoryCustom();
|
||||
bool fStyleSheetChanged = false;
|
||||
|
||||
if (stylesheet == nullptr || fDebugCustomStyleSheets) {
|
||||
if (stylesheet == nullptr || fForceUpdate || fDebugCustomStyleSheets) {
|
||||
auto hasModified = [](const std::vector<QString>& vecFiles) -> bool {
|
||||
static std::map<const QString, QDateTime> mapLastModified;
|
||||
|
||||
@ -1092,7 +1102,7 @@ void loadStyleSheet(QWidget* widget, bool fDebugWidget)
|
||||
};
|
||||
|
||||
auto loadFiles = [&](const std::vector<QString>& vecFiles) -> bool {
|
||||
if (fDebugCustomStyleSheets && !hasModified(vecFiles)) {
|
||||
if (!fForceUpdate && fDebugCustomStyleSheets && !hasModified(vecFiles)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1125,29 +1135,27 @@ void loadStyleSheet(QWidget* widget, bool fDebugWidget)
|
||||
fStyleSheetChanged = loadFiles(vecFiles);
|
||||
}
|
||||
|
||||
bool fUpdateStyleSheet = fDebugCustomStyleSheets && fStyleSheetChanged;
|
||||
|
||||
if (fDebugWidget) {
|
||||
setWidgets.insert(widget);
|
||||
QWidgetList allWidgets = QApplication::allWidgets();
|
||||
auto it = setWidgets.begin();
|
||||
while (it != setWidgets.end()) {
|
||||
if (!allWidgets.contains(*it)) {
|
||||
it = setWidgets.erase(it);
|
||||
continue;
|
||||
}
|
||||
if (fUpdateStyleSheet && *it != widget) {
|
||||
(*it)->setStyleSheet(*stylesheet);
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
bool fUpdateStyleSheet = fForceUpdate || (fDebugCustomStyleSheets && fStyleSheetChanged);
|
||||
|
||||
if (widget) {
|
||||
setWidgets.insert(widget);
|
||||
widget->setStyleSheet(*stylesheet);
|
||||
}
|
||||
|
||||
if (!ShutdownRequested() && fDebugCustomStyleSheets) {
|
||||
QWidgetList allWidgets = QApplication::allWidgets();
|
||||
auto it = setWidgets.begin();
|
||||
while (it != setWidgets.end()) {
|
||||
if (!allWidgets.contains(*it)) {
|
||||
it = setWidgets.erase(it);
|
||||
continue;
|
||||
}
|
||||
if (fUpdateStyleSheet && *it != widget) {
|
||||
(*it)->setStyleSheet(*stylesheet);
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
if (!ShutdownRequested() && fDebugCustomStyleSheets && !fForceUpdate) {
|
||||
QTimer::singleShot(200, [] { loadStyleSheet(); });
|
||||
}
|
||||
}
|
||||
@ -1556,12 +1564,36 @@ bool dashThemeActive()
|
||||
return theme != traditionalTheme;
|
||||
}
|
||||
|
||||
void loadTheme(QWidget* widget, bool fForce)
|
||||
{
|
||||
loadStyleSheet(widget, fForce);
|
||||
updateFonts();
|
||||
updateMacFocusRects();
|
||||
}
|
||||
|
||||
void disableMacFocusRect(const QWidget* w)
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
for (const auto& c : w->findChildren<QWidget*>()) {
|
||||
if (c->testAttribute(Qt::WA_MacShowFocusRect)) {
|
||||
c->setAttribute(Qt::WA_MacShowFocusRect, !dashThemeActive());
|
||||
setRectsDisabled.emplace(c);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void updateMacFocusRects()
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
QWidgetList allWidgets = QApplication::allWidgets();
|
||||
auto it = setRectsDisabled.begin();
|
||||
while (it != setRectsDisabled.end()) {
|
||||
if (allWidgets.contains(*it)) {
|
||||
(*it)->setAttribute(Qt::WA_MacShowFocusRect, !dashThemeActive());
|
||||
++it;
|
||||
} else {
|
||||
it = setRectsDisabled.erase(it);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -253,10 +253,13 @@ namespace GUIUtil
|
||||
/** Return a list of all theme css files */
|
||||
const std::vector<QString> listThemes();
|
||||
|
||||
/** Updates the widgets stylesheet and adds it to the list of ui debug elements
|
||||
if fDebugWidget is true. Beeing on that list means the stylesheet of the
|
||||
widget gets updated if the related css files has been changed if -debug-ui mode is active. */
|
||||
void loadStyleSheet(QWidget* widget = nullptr, bool fDebugWidget = true);
|
||||
/** Return the name of the default theme `*/
|
||||
const QString getDefaultTheme();
|
||||
|
||||
/** Updates the widgets stylesheet and adds it to the list of ui debug elements.
|
||||
Beeing on that list means the stylesheet of the widget gets updated if the
|
||||
related css files has been changed if -debug-ui mode is active. */
|
||||
void loadStyleSheet(QWidget* widget = nullptr, bool fForceUpdate = false);
|
||||
|
||||
enum class FontFamily {
|
||||
SystemDefault,
|
||||
@ -335,10 +338,16 @@ namespace GUIUtil
|
||||
/** Check if a dash specific theme is activated (light/dark).*/
|
||||
bool dashThemeActive();
|
||||
|
||||
/** Load the theme and update all UI elements according to the appearance settings. */
|
||||
void loadTheme(QWidget* widget = nullptr, bool fForce = true);
|
||||
|
||||
/** Disable the OS default focus rect for macOS because we have custom focus rects
|
||||
* set in the css files */
|
||||
void disableMacFocusRect(const QWidget* w);
|
||||
|
||||
/** Enable/Disable the macOS focus rects depending on the current theme. */
|
||||
void updateMacFocusRects();
|
||||
|
||||
/* Convert QString to OS specific boost path through UTF-8 */
|
||||
fs::path qstringToBoostPath(const QString &path);
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <QIntValidator>
|
||||
#include <QLocale>
|
||||
#include <QMessageBox>
|
||||
#include <QSettings>
|
||||
#include <QTimer>
|
||||
|
||||
OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
|
||||
@ -36,6 +37,8 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
previousTheme = GUIUtil::getActiveTheme();
|
||||
|
||||
GUIUtil::setFont({ui->statusLabel}, GUIUtil::FontWeight::Bold, 16);
|
||||
|
||||
GUIUtil::updateFonts();
|
||||
@ -104,6 +107,7 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
|
||||
for (const QString& entry : GUIUtil::listThemes()) {
|
||||
ui->theme->addItem(entry, QVariant(entry));
|
||||
}
|
||||
connect(ui->theme, SIGNAL(valueChanged()), this, SLOT(updateTheme()));
|
||||
|
||||
/* Language selector */
|
||||
QDir translations(":translations");
|
||||
@ -200,7 +204,6 @@ void OptionsDialog::setModel(OptionsModel *_model)
|
||||
connect(ui->connectSocksTor, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning()));
|
||||
/* Display */
|
||||
connect(ui->digits, SIGNAL(valueChanged()), this, SLOT(showRestartWarning()));
|
||||
connect(ui->theme, SIGNAL(valueChanged()), this, SLOT(showRestartWarning()));
|
||||
connect(ui->lang, SIGNAL(valueChanged()), this, SLOT(showRestartWarning()));
|
||||
connect(ui->thirdPartyTxUrls, SIGNAL(textChanged(const QString &)), this, SLOT(showRestartWarning()));
|
||||
}
|
||||
@ -306,6 +309,9 @@ void OptionsDialog::on_okButton_clicked()
|
||||
|
||||
void OptionsDialog::on_cancelButton_clicked()
|
||||
{
|
||||
if (previousTheme != GUIUtil::getActiveTheme()) {
|
||||
updateTheme(previousTheme);
|
||||
}
|
||||
reject();
|
||||
}
|
||||
|
||||
@ -386,6 +392,16 @@ void OptionsDialog::updateDefaultProxyNets()
|
||||
(strProxy == strDefaultProxyGUI.toStdString()) ? ui->proxyReachTor->setChecked(true) : ui->proxyReachTor->setChecked(false);
|
||||
}
|
||||
|
||||
void OptionsDialog::updateTheme(const QString& theme)
|
||||
{
|
||||
QString newValue = theme.isEmpty() ? ui->theme->value().toString() : theme;
|
||||
if (GUIUtil::getActiveTheme() != newValue) {
|
||||
QSettings().setValue("theme", newValue);
|
||||
QSettings().sync();
|
||||
Q_EMIT themeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
ProxyAddressValidator::ProxyAddressValidator(QObject *parent) :
|
||||
QValidator(parent)
|
||||
{
|
||||
|
@ -60,15 +60,18 @@ private Q_SLOTS:
|
||||
void updateProxyValidationState();
|
||||
/* query the networks, for which the default proxy is used */
|
||||
void updateDefaultProxyNets();
|
||||
void updateTheme(const QString& toTheme = QString());
|
||||
|
||||
Q_SIGNALS:
|
||||
void proxyIpChecks(QValidatedLineEdit *pUiProxyIp, int nProxyPort);
|
||||
void themeChanged();
|
||||
|
||||
private:
|
||||
Ui::OptionsDialog *ui;
|
||||
OptionsModel *model;
|
||||
QDataWidgetMapper *mapper;
|
||||
QButtonGroup pageButtons;
|
||||
QString previousTheme;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_QT_OPTIONSDIALOG_H
|
||||
|
@ -83,7 +83,7 @@ void OptionsModel::Init(bool resetSettings)
|
||||
strThirdPartyTxUrls = settings.value("strThirdPartyTxUrls", "").toString();
|
||||
|
||||
if (!settings.contains("theme"))
|
||||
settings.setValue("theme", "");
|
||||
settings.setValue("theme", GUIUtil::getDefaultTheme());
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
if (!settings.contains("fCoinControlFeatures"))
|
||||
@ -502,10 +502,8 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
|
||||
break;
|
||||
#endif // ENABLE_WALLET
|
||||
case Theme:
|
||||
if (settings.value("theme") != value) {
|
||||
settings.setValue("theme", value);
|
||||
setRestartRequired(true);
|
||||
}
|
||||
// Set in OptionsDialog::updateTheme slot now
|
||||
// to allow instant theme changes.
|
||||
break;
|
||||
case Language:
|
||||
if (settings.value("language") != value) {
|
||||
|
@ -1267,6 +1267,16 @@ void RPCConsole::hideEvent(QHideEvent *event)
|
||||
clientModel->getPeerTableModel()->stopAutoRefresh();
|
||||
}
|
||||
|
||||
void RPCConsole::changeEvent(QEvent* e)
|
||||
{
|
||||
if (e->type() == QEvent::StyleChange) {
|
||||
clear();
|
||||
ui->promptIcon->setHidden(GUIUtil::dashThemeActive());
|
||||
}
|
||||
|
||||
QWidget::changeEvent(e);
|
||||
}
|
||||
|
||||
void RPCConsole::showPeersTableContextMenu(const QPoint& point)
|
||||
{
|
||||
QModelIndex index = ui->peerWidget->indexAt(point);
|
||||
|
@ -79,6 +79,7 @@ private Q_SLOTS:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
void showEvent(QShowEvent *event);
|
||||
void hideEvent(QHideEvent *event);
|
||||
void changeEvent(QEvent* e);
|
||||
/** Show custom context menu on Peers tab */
|
||||
void showPeersTableContextMenu(const QPoint& point);
|
||||
/** Show custom context menu on Bans tab */
|
||||
|
@ -210,7 +210,7 @@ ShutdownWindow::ShutdownWindow(QWidget *parent, Qt::WindowFlags f):
|
||||
{
|
||||
setObjectName("ShutdownWindow");
|
||||
|
||||
GUIUtil::loadStyleSheet(this, false);
|
||||
GUIUtil::loadStyleSheet(this);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout();
|
||||
layout->addWidget(new QLabel(
|
||||
|
Loading…
Reference in New Issue
Block a user