Merge #79: Embed monospaced font

67f26319a0 gui: Add monospaced font settings (Hennadii Stepanov)
22e0114d05 qt: Choose monospaced font in C++ code rather in `*.ui` file (Hennadii Stepanov)
623de12d04 qt: Make GUIUtil::fixedPitchFont aware of embedded font (Hennadii Stepanov)
89e421918e gui: Add Roboto Mono font (Hennadii Stepanov)

Pull request description:

  Qt does not guarantee that the actual applied font matches to the requested one.
  It was noted (https://github.com/bitcoin/bitcoin/pull/16432#issuecomment-514486077):
  > the monospace font looks a bit weird no macOS

  ... because it is _not_ monospaced.
  Also some discrepancies I've noted on Windows while testing Qt 5.15 ([#19716](https://github.com/bitcoin/bitcoin/pull/19716)).

  Of course, we could check the actual font with `QFontInfo`, and try to choose another font.
  But this PR suggests to just embed a monospaced font, and get the GUI look (partially) independent from a platform.

  [Roboto Mono](https://fonts.google.com/specimen/Roboto+Mono) was chosen after discussion with Bitcoin Design community, and due to its [Apache License, Version 2.0](https://fonts.google.com/specimen/Roboto+Mono#license).

  Changes are scoped to the Overview page only.

  ---

  Screenshots on macOS 10.15.6 (images are simulated by code patching):

  - master (ca30d34cf9)
  ![Screenshot from 2020-09-03 14-10-03](https://user-images.githubusercontent.com/32963518/92107902-30357d80-edef-11ea-8a4f-b4c758eebf66.png)

  - this PR (3fdd5b6bd17a679d6e3876682266092159c52d59)
  ![Screenshot from 2020-09-03 15-41-36](https://user-images.githubusercontent.com/32963518/92116277-4b5aba00-edfc-11ea-8cb9-22fc44460bfb.png)

  ---

  More screenshots added after https://github.com/bitcoin-core/gui/pull/79#issuecomment-782909149:

  - Linux Mint 20.1 + Cinnamon DE

  ![DeepinScreenshot_select-area_20210221205410](https://user-images.githubusercontent.com/32963518/108635739-b327be80-7489-11eb-8851-ac89f61199ee.png)

  - Windows 10 (with depends)

  ![DeepinScreenshot_select-area_20210221205056](https://user-images.githubusercontent.com/32963518/108635741-b6bb4580-7489-11eb-8b6b-66be5551eb8c.png)

  - macOS Big Sur (with depends)

  ![DeepinScreenshot_select-area_20210221202917](https://user-images.githubusercontent.com/32963518/108635746-bd49bd00-7489-11eb-8cd2-cf4bb2273a6d.png)

ACKs for top commit:
  laanwj:
    Tested ACK 67f26319a0

Tree-SHA512: a59775570b8ce314669ede50a0b69f53e8a47a41e7eea428835013240f0ce9afcff6e4c258895455b56806417ed877e5b7a9522f1904e95a5f435db8ccf6078c
This commit is contained in:
Wladimir J. van der Laan 2021-02-22 12:36:25 +01:00
commit 7fca189a2a
No known key found for this signature in database
GPG key ID: 1E4AED62986CD25D
14 changed files with 180 additions and 60 deletions

View file

@ -87,6 +87,10 @@ Files: src/qt/res/icons/proxy.png
Copyright: Cristian Mircea Messel Copyright: Cristian Mircea Messel
License: public-domain License: public-domain
Files: src/qt/fonts/RobotoMono-Bold.ttf
License: Apache-2.0
Comment: Site: https://fonts.google.com/specimen/Roboto+Mono
License: Expat License: Expat
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
@ -144,3 +148,14 @@ Comment:
License: public-domain License: public-domain
This work is in the public domain. This work is in the public domain.
License: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -164,6 +164,9 @@ BITCOIN_QT_H = \
qt/walletview.h \ qt/walletview.h \
qt/winshutdownmonitor.h qt/winshutdownmonitor.h
RES_FONTS = \
qt/res/fonts/RobotoMono-Bold.ttf
RES_ICONS = \ RES_ICONS = \
qt/res/icons/add.png \ qt/res/icons/add.png \
qt/res/icons/address-book.png \ qt/res/icons/address-book.png \
@ -290,7 +293,7 @@ qt_libbitcoinqt_a_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
qt_libbitcoinqt_a_OBJCXXFLAGS = $(AM_OBJCXXFLAGS) $(QT_PIE_FLAGS) qt_libbitcoinqt_a_OBJCXXFLAGS = $(AM_OBJCXXFLAGS) $(QT_PIE_FLAGS)
qt_libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \ qt_libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \
$(QT_QRC) $(QT_QRC_LOCALE) $(QT_TS) $(RES_ICONS) $(RES_ANIMATION) $(QT_QRC) $(QT_QRC_LOCALE) $(QT_TS) $(RES_FONTS) $(RES_ICONS) $(RES_ANIMATION)
if TARGET_DARWIN if TARGET_DARWIN
qt_libbitcoinqt_a_SOURCES += $(BITCOIN_MM) qt_libbitcoinqt_a_SOURCES += $(BITCOIN_MM)
endif endif
@ -361,7 +364,7 @@ $(QT_QRC_LOCALE_CPP): $(QT_QRC_LOCALE) $(QT_QM)
$(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@ $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@
@rm $(@D)/temp_$(<F) @rm $(@D)/temp_$(<F)
$(QT_QRC_CPP): $(QT_QRC) $(QT_FORMS_H) $(RES_ICONS) $(RES_ANIMATION) $(QT_QRC_CPP): $(QT_QRC) $(QT_FORMS_H) $(RES_FONTS) $(RES_ICONS) $(RES_ANIMATION)
@test -f $(RCC) @test -f $(RCC)
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin $< | \ $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin $< | \
$(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@ $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@

View file

@ -44,6 +44,7 @@
#include <QApplication> #include <QApplication>
#include <QDebug> #include <QDebug>
#include <QFontDatabase>
#include <QLibraryInfo> #include <QLibraryInfo>
#include <QLocale> #include <QLocale>
#include <QMessageBox> #include <QMessageBox>
@ -475,6 +476,7 @@ int GuiMain(int argc, char* argv[])
#endif #endif
BitcoinApplication app; BitcoinApplication app;
QFontDatabase::addApplicationFont(":/fonts/monospace");
/// 2. Parse command-line options. We do this after qt in order to show an error if there are problems parsing these /// 2. Parse command-line options. We do this after qt in order to show an error if there are problems parsing these
// Command-line options take precedence: // Command-line options take precedence:

View file

@ -83,4 +83,7 @@
<file alias="spinner-034">res/animation/spinner-034.png</file> <file alias="spinner-034">res/animation/spinner-034.png</file>
<file alias="spinner-035">res/animation/spinner-035.png</file> <file alias="spinner-035">res/animation/spinner-035.png</file>
</qresource> </qresource>
<qresource prefix="/fonts">
<file alias="monospace">res/fonts/RobotoMono-Bold.ttf</file>
</qresource>
</RCC> </RCC>

View file

@ -705,6 +705,106 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QGroupBox" name="font_groupBox">
<property name="title">
<string>Monospaced font in the Overview tab:</string>
</property>
<layout class="QVBoxLayout" name="font_verticalLayout">
<item>
<layout class="QHBoxLayout" name="embeddedFont_horizontalLayout">
<item>
<widget class="QRadioButton" name="embeddedFont_radioButton">
<property name="text">
<string>embedded &quot;%1&quot;</string>
</property>
</widget>
</item>
<item>
<spacer name="embeddedFont_horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="embeddedFont_verticalLayout">
<item>
<widget class="QLabel" name="embeddedFont_label_1">
<property name="text">
<string>111.11111111 BTC</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="embeddedFont_label_9">
<property name="text">
<string>909.09090909 BTC</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="Line" name="font_line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="systemFont_horizontalLayout">
<item>
<widget class="QRadioButton" name="systemFont_radioButton">
<property name="text">
<string>closest matching &quot;%1&quot;</string>
</property>
</widget>
</item>
<item>
<spacer name="systemFont_horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="systemFont_verticalLayout">
<item>
<widget class="QLabel" name="systemFont_label_1">
<property name="text">
<string>111.11111111 BTC</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="systemFont_label_9">
<property name="text">
<string>909.09090909 BTC</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item> <item>
<spacer name="verticalSpacer_Display"> <spacer name="verticalSpacer_Display">
<property name="orientation"> <property name="orientation">

View file

@ -116,13 +116,6 @@
</property> </property>
<item row="2" column="2"> <item row="2" column="2">
<widget class="QLabel" name="labelWatchPending"> <widget class="QLabel" name="labelWatchPending">
<property name="font">
<font>
<family>Monospace</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="cursor"> <property name="cursor">
<cursorShape>IBeamCursor</cursorShape> <cursorShape>IBeamCursor</cursorShape>
</property> </property>
@ -142,13 +135,6 @@
</item> </item>
<item row="2" column="1"> <item row="2" column="1">
<widget class="QLabel" name="labelUnconfirmed"> <widget class="QLabel" name="labelUnconfirmed">
<property name="font">
<font>
<family>Monospace</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="cursor"> <property name="cursor">
<cursorShape>IBeamCursor</cursorShape> <cursorShape>IBeamCursor</cursorShape>
</property> </property>
@ -168,13 +154,6 @@
</item> </item>
<item row="3" column="2"> <item row="3" column="2">
<widget class="QLabel" name="labelWatchImmature"> <widget class="QLabel" name="labelWatchImmature">
<property name="font">
<font>
<family>Monospace</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="cursor"> <property name="cursor">
<cursorShape>IBeamCursor</cursorShape> <cursorShape>IBeamCursor</cursorShape>
</property> </property>
@ -227,13 +206,6 @@
</item> </item>
<item row="3" column="1"> <item row="3" column="1">
<widget class="QLabel" name="labelImmature"> <widget class="QLabel" name="labelImmature">
<property name="font">
<font>
<family>Monospace</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="cursor"> <property name="cursor">
<cursorShape>IBeamCursor</cursorShape> <cursorShape>IBeamCursor</cursorShape>
</property> </property>
@ -273,13 +245,6 @@
</item> </item>
<item row="5" column="1"> <item row="5" column="1">
<widget class="QLabel" name="labelTotal"> <widget class="QLabel" name="labelTotal">
<property name="font">
<font>
<family>Monospace</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="cursor"> <property name="cursor">
<cursorShape>IBeamCursor</cursorShape> <cursorShape>IBeamCursor</cursorShape>
</property> </property>
@ -299,13 +264,6 @@
</item> </item>
<item row="5" column="2"> <item row="5" column="2">
<widget class="QLabel" name="labelWatchTotal"> <widget class="QLabel" name="labelWatchTotal">
<property name="font">
<font>
<family>Monospace</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="cursor"> <property name="cursor">
<cursorShape>IBeamCursor</cursorShape> <cursorShape>IBeamCursor</cursorShape>
</property> </property>
@ -342,13 +300,6 @@
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QLabel" name="labelBalance"> <widget class="QLabel" name="labelBalance">
<property name="font">
<font>
<family>Monospace</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="cursor"> <property name="cursor">
<cursorShape>IBeamCursor</cursorShape> <cursorShape>IBeamCursor</cursorShape>
</property> </property>
@ -368,13 +319,6 @@
</item> </item>
<item row="1" column="2"> <item row="1" column="2">
<widget class="QLabel" name="labelWatchAvailable"> <widget class="QLabel" name="labelWatchAvailable">
<property name="font">
<font>
<family>Monospace</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="cursor"> <property name="cursor">
<cursorShape>IBeamCursor</cursorShape> <cursorShape>IBeamCursor</cursorShape>
</property> </property>

View file

@ -78,8 +78,11 @@ QString dateTimeStr(qint64 nTime)
return dateTimeStr(QDateTime::fromTime_t((qint32)nTime)); return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
} }
QFont fixedPitchFont() QFont fixedPitchFont(bool use_embedded_font)
{ {
if (use_embedded_font) {
return {"Roboto Mono"};
}
return QFontDatabase::systemFont(QFontDatabase::FixedFont); return QFontDatabase::systemFont(QFontDatabase::FixedFont);
} }

View file

@ -53,7 +53,7 @@ namespace GUIUtil
QString dateTimeStr(qint64 nTime); QString dateTimeStr(qint64 nTime);
// Return a monospace font // Return a monospace font
QFont fixedPitchFont(); QFont fixedPitchFont(bool use_embedded_font = false);
// Set up widget for address // Set up widget for address
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent); void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent);

View file

@ -144,6 +144,20 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
ui->minimizeToTray->setEnabled(false); ui->minimizeToTray->setEnabled(false);
} }
QFont embedded_font{GUIUtil::fixedPitchFont(true)};
ui->embeddedFont_radioButton->setText(ui->embeddedFont_radioButton->text().arg(QFontInfo(embedded_font).family()));
embedded_font.setWeight(QFont::Bold);
ui->embeddedFont_label_1->setFont(embedded_font);
ui->embeddedFont_label_9->setFont(embedded_font);
QFont system_font{GUIUtil::fixedPitchFont(false)};
ui->systemFont_radioButton->setText(ui->systemFont_radioButton->text().arg(QFontInfo(system_font).family()));
system_font.setWeight(QFont::Bold);
ui->systemFont_label_1->setFont(system_font);
ui->systemFont_label_9->setFont(system_font);
// Checking the embeddedFont_radioButton automatically unchecks the systemFont_radioButton.
ui->systemFont_radioButton->setChecked(true);
GUIUtil::handleCloseWindowShortcut(this); GUIUtil::handleCloseWindowShortcut(this);
} }
@ -246,6 +260,7 @@ void OptionsDialog::setMapper()
mapper->addMapping(ui->lang, OptionsModel::Language); mapper->addMapping(ui->lang, OptionsModel::Language);
mapper->addMapping(ui->unit, OptionsModel::DisplayUnit); mapper->addMapping(ui->unit, OptionsModel::DisplayUnit);
mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls); mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls);
mapper->addMapping(ui->embeddedFont_radioButton, OptionsModel::UseEmbeddedMonospacedFont);
} }
void OptionsDialog::setOkButtonState(bool fState) void OptionsDialog::setOkButtonState(bool fState)

View file

@ -163,6 +163,12 @@ void OptionsModel::Init(bool resetSettings)
addOverriddenOption("-lang"); addOverriddenOption("-lang");
language = settings.value("language").toString(); language = settings.value("language").toString();
if (!settings.contains("UseEmbeddedMonospacedFont")) {
settings.setValue("UseEmbeddedMonospacedFont", "true");
}
m_use_embedded_monospaced_font = settings.value("UseEmbeddedMonospacedFont").toBool();
Q_EMIT useEmbeddedMonospacedFontChanged(m_use_embedded_monospaced_font);
} }
/** Helper function to copy contents from one QSettings to another. /** Helper function to copy contents from one QSettings to another.
@ -326,6 +332,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
return strThirdPartyTxUrls; return strThirdPartyTxUrls;
case Language: case Language:
return settings.value("language"); return settings.value("language");
case UseEmbeddedMonospacedFont:
return m_use_embedded_monospaced_font;
case CoinControlFeatures: case CoinControlFeatures:
return fCoinControlFeatures; return fCoinControlFeatures;
case Prune: case Prune:
@ -453,6 +461,11 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
setRestartRequired(true); setRestartRequired(true);
} }
break; break;
case UseEmbeddedMonospacedFont:
m_use_embedded_monospaced_font = value.toBool();
settings.setValue("UseEmbeddedMonospacedFont", m_use_embedded_monospaced_font);
Q_EMIT useEmbeddedMonospacedFontChanged(m_use_embedded_monospaced_font);
break;
case CoinControlFeatures: case CoinControlFeatures:
fCoinControlFeatures = value.toBool(); fCoinControlFeatures = value.toBool();
settings.setValue("fCoinControlFeatures", fCoinControlFeatures); settings.setValue("fCoinControlFeatures", fCoinControlFeatures);

View file

@ -59,6 +59,7 @@ public:
DisplayUnit, // BitcoinUnits::Unit DisplayUnit, // BitcoinUnits::Unit
ThirdPartyTxUrls, // QString ThirdPartyTxUrls, // QString
Language, // QString Language, // QString
UseEmbeddedMonospacedFont, // bool
CoinControlFeatures, // bool CoinControlFeatures, // bool
ThreadsScriptVerif, // int ThreadsScriptVerif, // int
Prune, // bool Prune, // bool
@ -84,6 +85,7 @@ public:
bool getMinimizeOnClose() const { return fMinimizeOnClose; } bool getMinimizeOnClose() const { return fMinimizeOnClose; }
int getDisplayUnit() const { return nDisplayUnit; } int getDisplayUnit() const { return nDisplayUnit; }
QString getThirdPartyTxUrls() const { return strThirdPartyTxUrls; } QString getThirdPartyTxUrls() const { return strThirdPartyTxUrls; }
bool getUseEmbeddedMonospacedFont() const { return m_use_embedded_monospaced_font; }
bool getCoinControlFeatures() const { return fCoinControlFeatures; } bool getCoinControlFeatures() const { return fCoinControlFeatures; }
const QString& getOverriddenByCommandLine() { return strOverriddenByCommandLine; } const QString& getOverriddenByCommandLine() { return strOverriddenByCommandLine; }
@ -107,6 +109,7 @@ private:
QString language; QString language;
int nDisplayUnit; int nDisplayUnit;
QString strThirdPartyTxUrls; QString strThirdPartyTxUrls;
bool m_use_embedded_monospaced_font;
bool fCoinControlFeatures; bool fCoinControlFeatures;
/* settings that were overridden by command-line */ /* settings that were overridden by command-line */
QString strOverriddenByCommandLine; QString strOverriddenByCommandLine;
@ -120,6 +123,7 @@ Q_SIGNALS:
void displayUnitChanged(int unit); void displayUnitChanged(int unit);
void coinControlFeaturesChanged(bool); void coinControlFeaturesChanged(bool);
void showTrayIconChanged(bool); void showTrayIconChanged(bool);
void useEmbeddedMonospacedFontChanged(bool);
}; };
#endif // BITCOIN_QT_OPTIONSMODEL_H #endif // BITCOIN_QT_OPTIONSMODEL_H

View file

@ -257,6 +257,9 @@ void OverviewPage::setClientModel(ClientModel *model)
// Show warning, for example if this is a prerelease version // Show warning, for example if this is a prerelease version
connect(model, &ClientModel::alertsChanged, this, &OverviewPage::updateAlerts); connect(model, &ClientModel::alertsChanged, this, &OverviewPage::updateAlerts);
updateAlerts(model->getStatusBarWarnings()); updateAlerts(model->getStatusBarWarnings());
connect(model->getOptionsModel(), &OptionsModel::useEmbeddedMonospacedFontChanged, this, &OverviewPage::setMonospacedFont);
setMonospacedFont(model->getOptionsModel()->getUseEmbeddedMonospacedFont());
} }
} }
@ -321,3 +324,17 @@ void OverviewPage::showOutOfSyncWarning(bool fShow)
ui->labelWalletStatus->setVisible(fShow); ui->labelWalletStatus->setVisible(fShow);
ui->labelTransactionsStatus->setVisible(fShow); ui->labelTransactionsStatus->setVisible(fShow);
} }
void OverviewPage::setMonospacedFont(bool use_embedded_font)
{
QFont f = GUIUtil::fixedPitchFont(use_embedded_font);
f.setWeight(QFont::Bold);
ui->labelBalance->setFont(f);
ui->labelUnconfirmed->setFont(f);
ui->labelImmature->setFont(f);
ui->labelTotal->setFont(f);
ui->labelWatchAvailable->setFont(f);
ui->labelWatchPending->setFont(f);
ui->labelWatchImmature->setFont(f);
ui->labelWatchTotal->setFont(f);
}

View file

@ -61,6 +61,7 @@ private Q_SLOTS:
void updateAlerts(const QString &warnings); void updateAlerts(const QString &warnings);
void updateWatchOnlyLabels(bool showWatchOnly); void updateWatchOnlyLabels(bool showWatchOnly);
void handleOutOfSyncWarningClicks(); void handleOutOfSyncWarningClicks();
void setMonospacedFont(bool use_embedded_font);
}; };
#endif // BITCOIN_QT_OVERVIEWPAGE_H #endif // BITCOIN_QT_OVERVIEWPAGE_H

Binary file not shown.