qt: Fix some font weight related issues (#4131)

* qt: Add missing -font-family overridden check

* qt: Add missing `QFont::ExtraBold`

* qt: Remove settings depencency from GUIUtil::loadFonts and load earlier

* qt: Modify supportedWeightToIndex

Return -1 in case of failure

* qt: Add GUIUtil::isSupportedWeight

* qt: Make sure there are always supported weights in the settings

* qt: Add "supported defaults" + store weights based on font family

* qt: Use supported defaults in update weight sliders

* qt: Use supported defaults when updating weight sliders

* qt: Fix tests
This commit is contained in:
dustinface 2021-05-06 19:15:47 +02:00 committed by GitHub
parent d03eed72a7
commit 3a1d168a33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 156 additions and 66 deletions

View File

@ -47,7 +47,7 @@ AppearanceWidget::AppearanceWidget(QWidget* parent) :
mapper->setOrientation(Qt::Vertical); mapper->setOrientation(Qt::Vertical);
connect(ui->theme, SIGNAL(currentTextChanged(const QString&)), this, SLOT(updateTheme(const QString&))); connect(ui->theme, SIGNAL(currentTextChanged(const QString&)), this, SLOT(updateTheme(const QString&)));
connect(ui->fontFamily, SIGNAL(activated(int)), this, SLOT(updateFontFamily(int))); connect(ui->fontFamily, SIGNAL(currentIndexChanged(int)), this, SLOT(updateFontFamily(int)));
connect(ui->fontScaleSlider, SIGNAL(valueChanged(int)), this, SLOT(updateFontScale(int))); connect(ui->fontScaleSlider, SIGNAL(valueChanged(int)), this, SLOT(updateFontScale(int)));
connect(ui->fontWeightNormalSlider, SIGNAL(valueChanged(int)), this, SLOT(updateFontWeightNormal(int))); connect(ui->fontWeightNormalSlider, SIGNAL(valueChanged(int)), this, SLOT(updateFontWeightNormal(int)));
connect(ui->fontWeightBoldSlider, SIGNAL(valueChanged(int)), this, SLOT(updateFontWeightBold(int))); connect(ui->fontWeightBoldSlider, SIGNAL(valueChanged(int)), this, SLOT(updateFontWeightBold(int)));
@ -118,7 +118,7 @@ void AppearanceWidget::updateTheme(const QString& theme)
void AppearanceWidget::updateFontFamily(int index) void AppearanceWidget::updateFontFamily(int index)
{ {
GUIUtil::setFontFamily(static_cast<GUIUtil::FontFamily>(ui->fontFamily->itemData(index).toInt())); GUIUtil::setFontFamily(static_cast<GUIUtil::FontFamily>(ui->fontFamily->itemData(index).toInt()));
updateWeightSlider(); updateWeightSlider(true);
} }
void AppearanceWidget::updateFontScale(int nScale) void AppearanceWidget::updateFontScale(int nScale)
@ -148,7 +148,7 @@ void AppearanceWidget::updateFontWeightBold(int nValue, bool fForce)
GUIUtil::setFontWeightBold(GUIUtil::supportedWeightFromIndex(ui->fontWeightBoldSlider->value())); GUIUtil::setFontWeightBold(GUIUtil::supportedWeightFromIndex(ui->fontWeightBoldSlider->value()));
} }
void AppearanceWidget::updateWeightSlider() void AppearanceWidget::updateWeightSlider(const bool fForce)
{ {
int nMaximum = GUIUtil::getSupportedWeights().size() - 1; int nMaximum = GUIUtil::getSupportedWeights().size() - 1;
@ -158,11 +158,11 @@ void AppearanceWidget::updateWeightSlider()
ui->fontWeightBoldSlider->setMinimum(0); ui->fontWeightBoldSlider->setMinimum(0);
ui->fontWeightBoldSlider->setMaximum(nMaximum); ui->fontWeightBoldSlider->setMaximum(nMaximum);
if (nMaximum < 4) { if (fForce || !GUIUtil::isSupportedWeight(prevWeightNormal) || !GUIUtil::isSupportedWeight(prevWeightBold)) {
updateFontWeightNormal(0, true); int nIndexNormal = GUIUtil::supportedWeightToIndex(GUIUtil::getSupportedFontWeightNormalDefault());
updateFontWeightBold(nMaximum, true); int nIndexBold = GUIUtil::supportedWeightToIndex(GUIUtil::getSupportedFontWeightBoldDefault());
} else { assert(nIndexNormal != -1 && nIndexBold != -1);
updateFontWeightNormal(1, true); updateFontWeightNormal(nIndexNormal, true);
updateFontWeightBold(4, true); updateFontWeightBold(nIndexBold, true);
} }
} }

View File

@ -53,7 +53,7 @@ private:
QFont::Weight prevWeightNormal; QFont::Weight prevWeightNormal;
QFont::Weight prevWeightBold; QFont::Weight prevWeightBold;
void updateWeightSlider(); void updateWeightSlider(bool fForce = false);
}; };
#endif // BITCOIN_QT_APPEARANCEWIDGET_H #endif // BITCOIN_QT_APPEARANCEWIDGET_H

View File

@ -714,14 +714,14 @@ int main(int argc, char *argv[])
qInstallMessageHandler(DebugMessageHandler); qInstallMessageHandler(DebugMessageHandler);
// Allow parameter interaction before we create the options model // Allow parameter interaction before we create the options model
app.parameterSetup(); app.parameterSetup();
// Load GUI settings from QSettings
app.createOptionsModel(gArgs.GetBoolArg("-resetguisettings", false));
// Load custom application fonts and setup font management // Load custom application fonts and setup font management
if (!GUIUtil::loadFonts()) { if (!GUIUtil::loadFonts()) {
QMessageBox::critical(0, QObject::tr(PACKAGE_NAME), QMessageBox::critical(0, QObject::tr(PACKAGE_NAME),
QObject::tr("Error: Failed to load application fonts.")); QObject::tr("Error: Failed to load application fonts."));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Load GUI settings from QSettings
app.createOptionsModel(gArgs.GetBoolArg("-resetguisettings", false));
// Validate/set font family // Validate/set font family
if (gArgs.IsArgSet("-font-family")) { if (gArgs.IsArgSet("-font-family")) {
GUIUtil::FontFamily family; GUIUtil::FontFamily family;

View File

@ -126,11 +126,9 @@ static const int defaultFontScale = 0;
static FontFamily fontFamily = defaultFontFamily; static FontFamily fontFamily = defaultFontFamily;
// Application font scale value. May be overwritten by -font-scale. // Application font scale value. May be overwritten by -font-scale.
static int fontScale = defaultFontScale; static int fontScale = defaultFontScale;
// Application font weight for normal text. May be overwritten by -font-weight-normal. // Contains the weight settings separated for all available fonts
static QFont::Weight fontWeightNormal = defaultFontWeightNormal; static std::map<FontFamily, std::pair<QFont::Weight, QFont::Weight>> mapDefaultWeights;
// Application font weight for bold text. May be overwritten by -font-weight-bold. static std::map<FontFamily, std::pair<QFont::Weight, QFont::Weight>> mapWeights;
static QFont::Weight fontWeightBold = defaultFontWeightBold;
// Contains all widgets and its font attributes (weight, italic, size) with font changes due to GUIUtil::setFont // Contains all widgets and its font attributes (weight, italic, size) with font changes due to GUIUtil::setFont
static std::map<QPointer<QWidget>, std::tuple<FontWeight, bool, int>> mapFontUpdates; static std::map<QPointer<QWidget>, std::tuple<FontWeight, bool, int>> mapFontUpdates;
// Contains a list of supported font weights for all members of GUIUtil::FontFamily // Contains a list of supported font weights for all members of GUIUtil::FontFamily
@ -290,23 +288,6 @@ void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent, bool fAllow
void setupAppearance(QWidget* parent, OptionsModel* model) void setupAppearance(QWidget* parent, OptionsModel* model)
{ {
if (!QSettings().value("fAppearanceSetupDone", false).toBool()) { if (!QSettings().value("fAppearanceSetupDone", false).toBool()) {
std::vector<QFont::Weight> vecWeights = getSupportedWeights();
// See if the default value for normal weight is available
if (std::find(vecWeights.begin(), vecWeights.end(), defaultFontWeightNormal) == vecWeights.end()) {
// If not, use the lightest available weight as normal weight
fontWeightNormal = vecWeights.front();
}
// See if the default value for bold weight is available
if (std::find(vecWeights.begin(), vecWeights.end(), defaultFontWeightBold) == vecWeights.end()) {
// If not, use the second lightest available weight as bold weight default or also the lightest if there is only one
int nBoldOffset = vecWeights.size() > 1 ? 1 : 0;
fontWeightBold = vecWeights[nBoldOffset];
}
QSettings().setValue("fontWeightNormal", weightToArg(fontWeightNormal));
QSettings().setValue("fontWeightBold", weightToArg(fontWeightBold));
// Create the dialog // Create the dialog
QDialog dlg(parent); QDialog dlg(parent);
dlg.setObjectName("AppearanceSetup"); dlg.setObjectName("AppearanceSetup");
@ -1260,12 +1241,18 @@ QFont::Weight toQFontWeight(FontWeight weight)
QFont::Weight getFontWeightNormal() QFont::Weight getFontWeightNormal()
{ {
return fontWeightNormal; if (!mapWeights.count(fontFamily)) {
return defaultFontWeightNormal;
}
return mapWeights[fontFamily].first;
} }
void setFontWeightNormal(QFont::Weight weight) void setFontWeightNormal(QFont::Weight weight)
{ {
fontWeightNormal = weight; if (!mapWeights.count(fontFamily)) {
throw std::runtime_error(strprintf("%s: Font family not loaded: %s", __func__, fontFamilyToString(fontFamily).toStdString()));
}
mapWeights[fontFamily].first = weight;
updateFonts(); updateFonts();
} }
@ -1276,12 +1263,18 @@ QFont::Weight getFontWeightBoldDefault()
QFont::Weight getFontWeightBold() QFont::Weight getFontWeightBold()
{ {
return fontWeightBold; if (!mapWeights.count(fontFamily)) {
return defaultFontWeightBold;
}
return mapWeights[fontFamily].second;
} }
void setFontWeightBold(QFont::Weight weight) void setFontWeightBold(QFont::Weight weight)
{ {
fontWeightBold = weight; if (!mapWeights.count(fontFamily)) {
throw std::runtime_error(strprintf("%s: Font family not loaded: %s", __func__, fontFamilyToString(fontFamily).toStdString()));
}
mapWeights[fontFamily].second = weight;
updateFonts(); updateFonts();
} }
@ -1367,26 +1360,6 @@ bool loadFonts()
} }
} }
// Load font related settings
QSettings settings;
QFont::Weight weight;
if (!gArgs.IsArgSet("-font-family")) {
fontFamily = fontFamilyFromString(settings.value("fontFamily").toString());
}
if (!gArgs.IsArgSet("-font-scale")) {
fontScale = settings.value("fontScale").toInt();
}
if (!gArgs.IsArgSet("-font-weight-normal") && weightFromArg(settings.value("fontWeightNormal").toInt(), weight)) {
fontWeightNormal = weight;
}
if (!gArgs.IsArgSet("-font-weight-bold") && weightFromArg(settings.value("fontWeightBold").toInt(), weight)) {
fontWeightBold = weight;
}
setApplicationFont(); setApplicationFont();
// Initialize supported font weights for all available fonts // Initialize supported font weights for all available fonts
@ -1398,7 +1371,7 @@ bool loadFonts()
}; };
std::vector<QFont::Weight> vecWeights{QFont::Thin, QFont::ExtraLight, QFont::Light, std::vector<QFont::Weight> vecWeights{QFont::Thin, QFont::ExtraLight, QFont::Light,
QFont::Normal, QFont::Medium, QFont::DemiBold, QFont::Normal, QFont::Medium, QFont::DemiBold,
QFont::Bold, QFont::Black}; QFont::Bold, QFont::ExtraBold, QFont::Black};
std::vector<QFont::Weight> vecSupported; std::vector<QFont::Weight> vecSupported;
QFont::Weight prevWeight = vecWeights.front(); QFont::Weight prevWeight = vecWeights.front();
for (auto weight = vecWeights.begin() + 1; weight != vecWeights.end(); ++weight) { for (auto weight = vecWeights.begin() + 1; weight != vecWeights.end(); ++weight) {
@ -1416,11 +1389,55 @@ bool loadFonts()
mapSupportedWeights.insert(std::make_pair(FontFamily::SystemDefault, supportedWeights(FontFamily::SystemDefault))); mapSupportedWeights.insert(std::make_pair(FontFamily::SystemDefault, supportedWeights(FontFamily::SystemDefault)));
mapSupportedWeights.insert(std::make_pair(FontFamily::Montserrat, supportedWeights(FontFamily::Montserrat))); mapSupportedWeights.insert(std::make_pair(FontFamily::Montserrat, supportedWeights(FontFamily::Montserrat)));
auto getBestMatch = [&](FontFamily fontFamily, QFont::Weight targetWeight) {
auto& vecSupported = mapSupportedWeights[fontFamily];
auto it = vecSupported.begin();
QFont::Weight bestWeight = *it;
int nBestDiff = abs(*it - targetWeight);
while (++it != vecSupported.end()) {
int nDiff = abs(*it - targetWeight);
if (nDiff < nBestDiff) {
bestWeight = *it;
nBestDiff = nDiff;
}
}
return bestWeight;
};
auto addBestDefaults = [&](FontFamily family) -> auto {
QFont::Weight normalWeight = getBestMatch(family, defaultFontWeightNormal);
QFont::Weight boldWeight = getBestMatch(family, defaultFontWeightBold);
if (normalWeight == boldWeight) {
// If the results are the same use the next possible weight for bold font
auto& vecSupported = mapSupportedWeights[fontFamily];
auto it = std::find(vecSupported.begin(), vecSupported.end(),normalWeight);
if (++it != vecSupported.end()) {
boldWeight = *it;
}
}
mapDefaultWeights.emplace(family, std::make_pair(normalWeight, boldWeight));
};
addBestDefaults(FontFamily::SystemDefault);
addBestDefaults(FontFamily::Montserrat);
// Load supported defaults. May become overwritten later.
mapWeights = mapDefaultWeights;
return true; return true;
} }
bool fontsLoaded()
{
return osDefaultFont != nullptr;
}
void setApplicationFont() void setApplicationFont()
{ {
if (!fontsLoaded()) {
return;
}
std::unique_ptr<QFont> font; std::unique_ptr<QFont> font;
if (fontFamily == FontFamily::Montserrat) { if (fontFamily == FontFamily::Montserrat) {
@ -1569,6 +1586,9 @@ void updateFonts()
QFont getFont(FontFamily family, QFont::Weight qWeight, bool fItalic, int nPointSize) QFont getFont(FontFamily family, QFont::Weight qWeight, bool fItalic, int nPointSize)
{ {
QFont font; QFont font;
if (!fontsLoaded()) {
return font;
}
if (family == FontFamily::Montserrat) { if (family == FontFamily::Montserrat) {
static std::map<QFont::Weight, QString> mapMontserratMapping{ static std::map<QFont::Weight, QString> mapMontserratMapping{
@ -1645,6 +1665,22 @@ QFont getFontBold()
return getFont(FontWeight::Bold); return getFont(FontWeight::Bold);
} }
QFont::Weight getSupportedFontWeightNormalDefault()
{
if (!mapDefaultWeights.count(fontFamily)) {
throw std::runtime_error(strprintf("%s: Font family not loaded: %s", __func__, fontFamilyToString(fontFamily).toStdString()));
}
return mapDefaultWeights[fontFamily].first;
}
QFont::Weight getSupportedFontWeightBoldDefault()
{
if (!mapDefaultWeights.count(fontFamily)) {
throw std::runtime_error(strprintf("%s: Font family not loaded: %s", __func__, fontFamilyToString(fontFamily).toStdString()));
}
return mapDefaultWeights[fontFamily].second;
}
std::vector<QFont::Weight> getSupportedWeights() std::vector<QFont::Weight> getSupportedWeights()
{ {
assert(mapSupportedWeights.count(fontFamily)); assert(mapSupportedWeights.count(fontFamily));
@ -1666,7 +1702,12 @@ int supportedWeightToIndex(QFont::Weight weight)
return index; return index;
} }
} }
assert(false); return -1;
}
bool isSupportedWeight(const QFont::Weight weight)
{
return supportedWeightToIndex(weight) != -1;
} }
QString getActiveTheme() QString getActiveTheme()

View File

@ -321,6 +321,8 @@ namespace GUIUtil
/** Load dash specific appliciation fonts */ /** Load dash specific appliciation fonts */
bool loadFonts(); bool loadFonts();
/** Check if the fonts have been loaded successfully */
bool fontsLoaded();
/** Set an application wide default font, depends on the selected theme */ /** Set an application wide default font, depends on the selected theme */
void setApplicationFont(); void setApplicationFont();
@ -345,12 +347,18 @@ namespace GUIUtil
/** Get the default bold QFont */ /** Get the default bold QFont */
QFont getFontBold(); QFont getFontBold();
/** Return supported normal default for the current font family */
QFont::Weight getSupportedFontWeightNormalDefault();
/** Return supported bold default for the current font family */
QFont::Weight getSupportedFontWeightBoldDefault();
/** Return supported weights for the current font family */ /** Return supported weights for the current font family */
std::vector<QFont::Weight> getSupportedWeights(); std::vector<QFont::Weight> getSupportedWeights();
/** Convert an index to a weight in the supported weights vector */ /** Convert an index to a weight in the supported weights vector */
QFont::Weight supportedWeightFromIndex(int nIndex); QFont::Weight supportedWeightFromIndex(int nIndex);
/** Convert a weight to an index in the supported weights vector */ /** Convert a weight to an index in the supported weights vector */
int supportedWeightToIndex(QFont::Weight weight); int supportedWeightToIndex(QFont::Weight weight);
/** Check if a weight is supported by the current font family */
bool isSupportedWeight(QFont::Weight weight);
/** Return the name of the currently active theme.*/ /** Return the name of the currently active theme.*/
QString getActiveTheme(); QString getActiveTheme();

View File

@ -85,21 +85,59 @@ void OptionsModel::Init(bool resetSettings)
if (!settings.contains("fontFamily")) if (!settings.contains("fontFamily"))
settings.setValue("fontFamily", GUIUtil::fontFamilyToString(GUIUtil::getFontFamilyDefault())); settings.setValue("fontFamily", GUIUtil::fontFamilyToString(GUIUtil::getFontFamilyDefault()));
if (m_node.softSetArg("-font-family", settings.value("fontFamily").toString().toStdString())) {
if (GUIUtil::fontsLoaded()) {
GUIUtil::setFontFamily(GUIUtil::fontFamilyFromString(settings.value("fontFamily").toString()));
}
} else {
addOverriddenOption("-font-family");
}
if (!settings.contains("fontScale")) if (!settings.contains("fontScale"))
settings.setValue("fontScale", GUIUtil::getFontScaleDefault()); settings.setValue("fontScale", GUIUtil::getFontScaleDefault());
if (!m_node.softSetArg("-font-scale", settings.value("fontScale").toString().toStdString())) if (m_node.softSetArg("-font-scale", settings.value("fontScale").toString().toStdString())) {
if (GUIUtil::fontsLoaded()) {
GUIUtil::setFontScale(settings.value("fontScale").toInt());
}
} else {
addOverriddenOption("-font-scale"); addOverriddenOption("-font-scale");
}
if (!settings.contains("fontWeightNormal")) if (!settings.contains("fontWeightNormal"))
settings.setValue("fontWeightNormal", GUIUtil::weightToArg(GUIUtil::getFontWeightNormalDefault())); settings.setValue("fontWeightNormal", GUIUtil::weightToArg(GUIUtil::getFontWeightNormalDefault()));
if (!m_node.softSetArg("-font-weight-normal", settings.value("fontWeightNormal").toString().toStdString())) if (m_node.softSetArg("-font-weight-normal", settings.value("fontWeightNormal").toString().toStdString())) {
if (GUIUtil::fontsLoaded()) {
QFont::Weight weight;
GUIUtil::weightFromArg(settings.value("fontWeightNormal").toInt(), weight);
if (!GUIUtil::isSupportedWeight(weight)) {
// If the currently selected weight is not supported fallback to the lightest weight for normal font.
weight = GUIUtil::getSupportedWeights().front();
settings.setValue("fontWeightNormal", GUIUtil::weightToArg(weight));
}
GUIUtil::setFontWeightNormal(weight);
}
} else {
addOverriddenOption("-font-weight-normal"); addOverriddenOption("-font-weight-normal");
}
if (!settings.contains("fontWeightBold")) if (!settings.contains("fontWeightBold"))
settings.setValue("fontWeightBold", GUIUtil::weightToArg(GUIUtil::getFontWeightBoldDefault())); settings.setValue("fontWeightBold", GUIUtil::weightToArg(GUIUtil::getFontWeightBoldDefault()));
if (!m_node.softSetArg("-font-weight-bold", settings.value("fontWeightBold").toString().toStdString())) if (m_node.softSetArg("-font-weight-bold", settings.value("fontWeightBold").toString().toStdString())) {
if (GUIUtil::fontsLoaded()) {
QFont::Weight weight;
GUIUtil::weightFromArg(settings.value("fontWeightBold").toInt(), weight);
if (!GUIUtil::isSupportedWeight(weight)) {
// If the currently selected weight is not supported fallback to the second lightest weight for bold font
// or the lightest if there is only one.
auto vecSupported = GUIUtil::getSupportedWeights();
weight = vecSupported[vecSupported.size() > 1 ? 1 : 0];
settings.setValue("fontWeightBold", GUIUtil::weightToArg(weight));
}
GUIUtil::setFontWeightBold(weight);
}
} else {
addOverriddenOption("-font-weight-bold"); addOverriddenOption("-font-weight-bold");
}
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
if (!settings.contains("fCoinControlFeatures")) if (!settings.contains("fCoinControlFeatures"))
@ -388,12 +426,16 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
case FontWeightNormal: { case FontWeightNormal: {
QFont::Weight weight; QFont::Weight weight;
GUIUtil::weightFromArg(settings.value("fontWeightNormal").toInt(), weight); GUIUtil::weightFromArg(settings.value("fontWeightNormal").toInt(), weight);
return GUIUtil::supportedWeightToIndex(weight); int nIndex = GUIUtil::supportedWeightToIndex(weight);
assert(nIndex != -1);
return nIndex;
} }
case FontWeightBold: { case FontWeightBold: {
QFont::Weight weight; QFont::Weight weight;
GUIUtil::weightFromArg(settings.value("fontWeightBold").toInt(), weight); GUIUtil::weightFromArg(settings.value("fontWeightBold").toInt(), weight);
return GUIUtil::supportedWeightToIndex(weight); int nIndex = GUIUtil::supportedWeightToIndex(weight);
assert(nIndex != -1);
return nIndex;
} }
case Language: case Language:
return settings.value("language"); return settings.value("language");

View File

@ -113,7 +113,6 @@ QModelIndex FindTx(const QAbstractItemModel& model, const uint256& txid)
// src/qt/test/test_dash-qt -platform cocoa # macOS // src/qt/test/test_dash-qt -platform cocoa # macOS
void TestGUI() void TestGUI()
{ {
GUIUtil::loadFonts();
// Set up wallet and chain with 105 blocks (5 mature blocks for spending). // Set up wallet and chain with 105 blocks (5 mature blocks for spending).
TestChain100Setup test; TestChain100Setup test;
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) {