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 pasta
parent b4a0d0120b
commit b3c6d09b80
7 changed files with 156 additions and 66 deletions

View File

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

View File

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

View File

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

View File

@ -126,11 +126,9 @@ static const int defaultFontScale = 0;
static FontFamily fontFamily = defaultFontFamily;
// Application font scale value. May be overwritten by -font-scale.
static int fontScale = defaultFontScale;
// Application font weight for normal text. May be overwritten by -font-weight-normal.
static QFont::Weight fontWeightNormal = defaultFontWeightNormal;
// Application font weight for bold text. May be overwritten by -font-weight-bold.
static QFont::Weight fontWeightBold = defaultFontWeightBold;
// Contains the weight settings separated for all available fonts
static std::map<FontFamily, std::pair<QFont::Weight, QFont::Weight>> mapDefaultWeights;
static std::map<FontFamily, std::pair<QFont::Weight, QFont::Weight>> mapWeights;
// 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;
// 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)
{
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
QDialog dlg(parent);
dlg.setObjectName("AppearanceSetup");
@ -1272,12 +1253,18 @@ QFont::Weight toQFontWeight(FontWeight weight)
QFont::Weight getFontWeightNormal()
{
return fontWeightNormal;
if (!mapWeights.count(fontFamily)) {
return defaultFontWeightNormal;
}
return mapWeights[fontFamily].first;
}
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();
}
@ -1288,12 +1275,18 @@ QFont::Weight getFontWeightBoldDefault()
QFont::Weight getFontWeightBold()
{
return fontWeightBold;
if (!mapWeights.count(fontFamily)) {
return defaultFontWeightBold;
}
return mapWeights[fontFamily].second;
}
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();
}
@ -1379,26 +1372,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();
// Initialize supported font weights for all available fonts
@ -1410,7 +1383,7 @@ bool loadFonts()
};
std::vector<QFont::Weight> vecWeights{QFont::Thin, QFont::ExtraLight, QFont::Light,
QFont::Normal, QFont::Medium, QFont::DemiBold,
QFont::Bold, QFont::Black};
QFont::Bold, QFont::ExtraBold, QFont::Black};
std::vector<QFont::Weight> vecSupported;
QFont::Weight prevWeight = vecWeights.front();
for (auto weight = vecWeights.begin() + 1; weight != vecWeights.end(); ++weight) {
@ -1428,11 +1401,55 @@ bool loadFonts()
mapSupportedWeights.insert(std::make_pair(FontFamily::SystemDefault, supportedWeights(FontFamily::SystemDefault)));
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;
}
bool fontsLoaded()
{
return osDefaultFont != nullptr;
}
void setApplicationFont()
{
if (!fontsLoaded()) {
return;
}
std::unique_ptr<QFont> font;
if (fontFamily == FontFamily::Montserrat) {
@ -1581,6 +1598,9 @@ void updateFonts()
QFont getFont(FontFamily family, QFont::Weight qWeight, bool fItalic, int nPointSize)
{
QFont font;
if (!fontsLoaded()) {
return font;
}
if (family == FontFamily::Montserrat) {
static std::map<QFont::Weight, QString> mapMontserratMapping{
@ -1657,6 +1677,22 @@ QFont getFontBold()
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()
{
assert(mapSupportedWeights.count(fontFamily));
@ -1678,7 +1714,12 @@ int supportedWeightToIndex(QFont::Weight weight)
return index;
}
}
assert(false);
return -1;
}
bool isSupportedWeight(const QFont::Weight weight)
{
return supportedWeightToIndex(weight) != -1;
}
QString getActiveTheme()

View File

@ -324,6 +324,8 @@ namespace GUIUtil
/** Load dash specific appliciation fonts */
bool loadFonts();
/** Check if the fonts have been loaded successfully */
bool fontsLoaded();
/** Set an application wide default font, depends on the selected theme */
void setApplicationFont();
@ -348,12 +350,18 @@ namespace GUIUtil
/** Get the default bold QFont */
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 */
std::vector<QFont::Weight> getSupportedWeights();
/** Convert an index to a weight in the supported weights vector */
QFont::Weight supportedWeightFromIndex(int nIndex);
/** Convert a weight to an index in the supported weights vector */
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.*/
QString getActiveTheme();

View File

@ -85,21 +85,59 @@ void OptionsModel::Init(bool resetSettings)
if (!settings.contains("fontFamily"))
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"))
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");
}
if (!settings.contains("fontWeightNormal"))
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");
}
if (!settings.contains("fontWeightBold"))
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");
}
#ifdef ENABLE_WALLET
if (!settings.contains("fCoinControlFeatures"))
@ -366,12 +404,16 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
case FontWeightNormal: {
QFont::Weight weight;
GUIUtil::weightFromArg(settings.value("fontWeightNormal").toInt(), weight);
return GUIUtil::supportedWeightToIndex(weight);
int nIndex = GUIUtil::supportedWeightToIndex(weight);
assert(nIndex != -1);
return nIndex;
}
case FontWeightBold: {
QFont::Weight weight;
GUIUtil::weightFromArg(settings.value("fontWeightBold").toInt(), weight);
return GUIUtil::supportedWeightToIndex(weight);
int nIndex = GUIUtil::supportedWeightToIndex(weight);
assert(nIndex != -1);
return nIndex;
}
case 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
void TestGUI()
{
GUIUtil::loadFonts();
// Set up wallet and chain with 105 blocks (5 mature blocks for spending).
TestChain100Setup test;
for (int i = 0; i < 5; ++i) {