Skip to content

Commit 60ac503

Browse files
committed
Merge #497: Enable users to configure their monospace font specifically
a17fd33 GUI: OptionsDialog: Replace verbose two-option font selector with simple combobox with Custom... choice (Luke Dashjr) 98e9ac5 GUI: Use FontChoice type in OptionsModel settings abstraction (Luke Dashjr) 3a6757e GUI: Load custom FontForMoney from QSettings (Luke Dashjr) 49eb97e GUI: Add possibility for an explicit QFont for FontForMoney in OptionsModel (Luke Dashjr) f2dfde8 GUI: Move "embedded font or not" decision into new OptionsModel::getFontForMoney method (Luke Dashjr) Pull request description: This replaces the overly-verbose radio-button font setting (which only allows embedded or autodetected from system) with a simple combobox providing both existing options as well as a custom option to allow the user to select any font of their choice/style. ACKs for top commit: pablomartin4btc: tested ACK a17fd33 hebasto: ACK a17fd33, I have reviewed the code and tested it on Ubuntu 22.04. This is a UX improvement. #497 (comment) might be addressed in a follow-up. Tree-SHA512: 2f0a8bc1242a374c4b7dc6e34014400428b6d36063fa0b01c9f62a8bd6078adfbbca93d95c87e4ccb580d982fe10173e1d9a28bcec586591dd3f966c7b90fc5d
2 parents 7b39702 + a17fd33 commit 60ac503

File tree

6 files changed

+175
-132
lines changed

6 files changed

+175
-132
lines changed

src/qt/forms/optionsdialog.ui

Lines changed: 23 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -772,104 +772,29 @@
772772
</layout>
773773
</item>
774774
<item>
775-
<widget class="QGroupBox" name="font_groupBox">
776-
<property name="title">
777-
<string>Monospaced font in the Overview tab:</string>
778-
</property>
779-
<layout class="QVBoxLayout" name="font_verticalLayout">
780-
<item>
781-
<layout class="QHBoxLayout" name="embeddedFont_horizontalLayout">
782-
<item>
783-
<widget class="QRadioButton" name="embeddedFont_radioButton">
784-
<property name="text">
785-
<string>embedded &quot;%1&quot;</string>
786-
</property>
787-
</widget>
788-
</item>
789-
<item>
790-
<spacer name="embeddedFont_horizontalSpacer">
791-
<property name="orientation">
792-
<enum>Qt::Horizontal</enum>
793-
</property>
794-
<property name="sizeHint" stdset="0">
795-
<size>
796-
<width>40</width>
797-
<height>20</height>
798-
</size>
799-
</property>
800-
</spacer>
801-
</item>
802-
<item>
803-
<layout class="QVBoxLayout" name="embeddedFont_verticalLayout">
804-
<item>
805-
<widget class="QLabel" name="embeddedFont_label_1">
806-
<property name="text">
807-
<string notr="true">111.11111111 BTC</string>
808-
</property>
809-
</widget>
810-
</item>
811-
<item>
812-
<widget class="QLabel" name="embeddedFont_label_9">
813-
<property name="text">
814-
<string notr="true">909.09090909 BTC</string>
815-
</property>
816-
</widget>
817-
</item>
818-
</layout>
819-
</item>
820-
</layout>
821-
</item>
822-
<item>
823-
<widget class="Line" name="font_line">
824-
<property name="orientation">
825-
<enum>Qt::Horizontal</enum>
826-
</property>
827-
</widget>
828-
</item>
829-
<item>
830-
<layout class="QHBoxLayout" name="systemFont_horizontalLayout">
831-
<item>
832-
<widget class="QRadioButton" name="systemFont_radioButton">
833-
<property name="text">
834-
<string>closest matching &quot;%1&quot;</string>
835-
</property>
836-
</widget>
837-
</item>
838-
<item>
839-
<spacer name="systemFont_horizontalSpacer">
840-
<property name="orientation">
841-
<enum>Qt::Horizontal</enum>
842-
</property>
843-
<property name="sizeHint" stdset="0">
844-
<size>
845-
<width>40</width>
846-
<height>20</height>
847-
</size>
848-
</property>
849-
</spacer>
850-
</item>
851-
<item>
852-
<layout class="QVBoxLayout" name="systemFont_verticalLayout">
853-
<item>
854-
<widget class="QLabel" name="systemFont_label_1">
855-
<property name="text">
856-
<string notr="true">111.11111111 BTC</string>
857-
</property>
858-
</widget>
859-
</item>
860-
<item>
861-
<widget class="QLabel" name="systemFont_label_9">
862-
<property name="text">
863-
<string notr="true">909.09090909 BTC</string>
864-
</property>
865-
</widget>
866-
</item>
867-
</layout>
868-
</item>
869-
</layout>
870-
</item>
871-
</layout>
872-
</widget>
775+
<layout class="QHBoxLayout" name="horizontalLayout_4_Display">
776+
<item>
777+
<widget class="QLabel" name="moneyFontLabel">
778+
<property name="text">
779+
<string>Font in the Overview tab: </string>
780+
</property>
781+
<property name="buddy">
782+
<cstring>moneyFont</cstring>
783+
</property>
784+
</widget>
785+
</item>
786+
<item>
787+
<widget class="QComboBox" name="moneyFont"/>
788+
</item>
789+
<item>
790+
<widget class="QLabel" name="moneyFont_preview">
791+
<property name="text">
792+
<string notr="true">111.11111111 BTC
793+
909.09090909 BTC</string>
794+
</property>
795+
</widget>
796+
</item>
797+
</layout>
873798
</item>
874799
<item>
875800
<spacer name="verticalSpacer_Display">

src/qt/optionsdialog.cpp

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,70 @@
2323

2424
#include <chrono>
2525

26+
#include <QApplication>
2627
#include <QDataWidgetMapper>
2728
#include <QDir>
29+
#include <QFontDialog>
2830
#include <QIntValidator>
2931
#include <QLocale>
3032
#include <QMessageBox>
3133
#include <QSystemTrayIcon>
3234
#include <QTimer>
3335

36+
int setFontChoice(QComboBox* cb, const OptionsModel::FontChoice& fc)
37+
{
38+
int i;
39+
for (i = cb->count(); --i >= 0; ) {
40+
QVariant item_data = cb->itemData(i);
41+
if (!item_data.canConvert<OptionsModel::FontChoice>()) continue;
42+
if (item_data.value<OptionsModel::FontChoice>() == fc) {
43+
break;
44+
}
45+
}
46+
if (i == -1) {
47+
// New item needed
48+
QFont chosen_font = OptionsModel::getFontForChoice(fc);
49+
QSignalBlocker block_currentindexchanged_signal(cb); // avoid triggering QFontDialog
50+
cb->insertItem(0, QFontInfo(chosen_font).family(), QVariant::fromValue(fc));
51+
i = 0;
52+
}
53+
54+
cb->setCurrentIndex(i);
55+
return i;
56+
}
57+
58+
void setupFontOptions(QComboBox* cb, QLabel* preview)
59+
{
60+
QFont embedded_font{GUIUtil::fixedPitchFont(true)};
61+
QFont system_font{GUIUtil::fixedPitchFont(false)};
62+
cb->addItem(QObject::tr("Embedded \"%1\"").arg(QFontInfo(embedded_font).family()), QVariant::fromValue(OptionsModel::FontChoice{OptionsModel::FontChoiceAbstract::EmbeddedFont}));
63+
cb->addItem(QObject::tr("Default system font \"%1\"").arg(QFontInfo(system_font).family()), QVariant::fromValue(OptionsModel::FontChoice{OptionsModel::FontChoiceAbstract::BestSystemFont}));
64+
cb->addItem(QObject::tr("Custom…"));
65+
66+
const auto& on_font_choice_changed = [cb, preview](int index) {
67+
static int previous_index = -1;
68+
QVariant item_data = cb->itemData(index);
69+
QFont f;
70+
if (item_data.canConvert<OptionsModel::FontChoice>()) {
71+
f = OptionsModel::getFontForChoice(item_data.value<OptionsModel::FontChoice>());
72+
} else {
73+
bool ok;
74+
f = QFontDialog::getFont(&ok, GUIUtil::fixedPitchFont(false), cb->parentWidget());
75+
if (!ok) {
76+
cb->setCurrentIndex(previous_index);
77+
return;
78+
}
79+
index = setFontChoice(cb, OptionsModel::FontChoice{f});
80+
}
81+
if (preview) {
82+
preview->setFont(f);
83+
}
84+
previous_index = index;
85+
};
86+
QObject::connect(cb, QOverload<int>::of(&QComboBox::currentIndexChanged), on_font_choice_changed);
87+
on_font_choice_changed(cb->currentIndex());
88+
}
89+
3490
OptionsDialog::OptionsDialog(QWidget* parent, bool enableWallet)
3591
: QDialog(parent, GUIUtil::dialog_flags),
3692
ui(new Ui::OptionsDialog)
@@ -148,19 +204,7 @@ OptionsDialog::OptionsDialog(QWidget* parent, bool enableWallet)
148204
ui->minimizeToTray->setEnabled(false);
149205
}
150206

151-
QFont embedded_font{GUIUtil::fixedPitchFont(true)};
152-
ui->embeddedFont_radioButton->setText(ui->embeddedFont_radioButton->text().arg(QFontInfo(embedded_font).family()));
153-
embedded_font.setWeight(QFont::Bold);
154-
ui->embeddedFont_label_1->setFont(embedded_font);
155-
ui->embeddedFont_label_9->setFont(embedded_font);
156-
157-
QFont system_font{GUIUtil::fixedPitchFont(false)};
158-
ui->systemFont_radioButton->setText(ui->systemFont_radioButton->text().arg(QFontInfo(system_font).family()));
159-
system_font.setWeight(QFont::Bold);
160-
ui->systemFont_label_1->setFont(system_font);
161-
ui->systemFont_label_9->setFont(system_font);
162-
// Checking the embeddedFont_radioButton automatically unchecks the systemFont_radioButton.
163-
ui->systemFont_radioButton->setChecked(true);
207+
setupFontOptions(ui->moneyFont, ui->moneyFont_preview);
164208

165209
GUIUtil::handleCloseWindowShortcut(this);
166210
}
@@ -198,6 +242,9 @@ void OptionsDialog::setModel(OptionsModel *_model)
198242
setMapper();
199243
mapper->toFirst();
200244

245+
const auto& font_for_money = _model->data(_model->index(OptionsModel::FontForMoney, 0), Qt::EditRole).value<OptionsModel::FontChoice>();
246+
setFontChoice(ui->moneyFont, font_for_money);
247+
201248
updateDefaultProxyNets();
202249
}
203250

@@ -275,7 +322,6 @@ void OptionsDialog::setMapper()
275322
mapper->addMapping(ui->lang, OptionsModel::Language);
276323
mapper->addMapping(ui->unit, OptionsModel::DisplayUnit);
277324
mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls);
278-
mapper->addMapping(ui->embeddedFont_radioButton, OptionsModel::UseEmbeddedMonospacedFont);
279325
}
280326

281327
void OptionsDialog::setOkButtonState(bool fState)
@@ -337,6 +383,8 @@ void OptionsDialog::on_openBitcoinConfButton_clicked()
337383

338384
void OptionsDialog::on_okButton_clicked()
339385
{
386+
model->setData(model->index(OptionsModel::FontForMoney, 0), ui->moneyFont->itemData(ui->moneyFont->currentIndex()));
387+
340388
mapper->submit();
341389
accept();
342390
updateDefaultProxyNets();

src/qt/optionsmodel.cpp

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,37 @@ struct ProxySetting {
119119
static ProxySetting ParseProxyString(const std::string& proxy);
120120
static std::string ProxyString(bool is_set, QString ip, QString port);
121121

122+
static const QLatin1String fontchoice_str_embedded{"embedded"};
123+
static const QLatin1String fontchoice_str_best_system{"best_system"};
124+
static const QString fontchoice_str_custom_prefix{QStringLiteral("custom, ")};
125+
126+
QString OptionsModel::FontChoiceToString(const OptionsModel::FontChoice& f)
127+
{
128+
if (std::holds_alternative<FontChoiceAbstract>(f)) {
129+
if (f == UseBestSystemFont) {
130+
return fontchoice_str_best_system;
131+
} else {
132+
return fontchoice_str_embedded;
133+
}
134+
}
135+
return fontchoice_str_custom_prefix + std::get<QFont>(f).toString();
136+
}
137+
138+
OptionsModel::FontChoice OptionsModel::FontChoiceFromString(const QString& s)
139+
{
140+
if (s == fontchoice_str_best_system) {
141+
return FontChoiceAbstract::BestSystemFont;
142+
} else if (s == fontchoice_str_embedded) {
143+
return FontChoiceAbstract::EmbeddedFont;
144+
} else if (s.startsWith(fontchoice_str_custom_prefix)) {
145+
QFont f;
146+
f.fromString(s.mid(fontchoice_str_custom_prefix.size()));
147+
return f;
148+
} else {
149+
return FontChoiceAbstract::EmbeddedFont; // default
150+
}
151+
}
152+
122153
OptionsModel::OptionsModel(interfaces::Node& node, QObject *parent) :
123154
QAbstractListModel(parent), m_node{node}
124155
{
@@ -216,11 +247,16 @@ bool OptionsModel::Init(bilingual_str& error)
216247
#endif
217248

218249
// Display
219-
if (!settings.contains("UseEmbeddedMonospacedFont")) {
220-
settings.setValue("UseEmbeddedMonospacedFont", "true");
250+
if (settings.contains("FontForMoney")) {
251+
m_font_money = FontChoiceFromString(settings.value("FontForMoney").toString());
252+
} else if (settings.contains("UseEmbeddedMonospacedFont")) {
253+
if (settings.value("UseEmbeddedMonospacedFont").toBool()) {
254+
m_font_money = FontChoiceAbstract::EmbeddedFont;
255+
} else {
256+
m_font_money = FontChoiceAbstract::BestSystemFont;
257+
}
221258
}
222-
m_use_embedded_monospaced_font = settings.value("UseEmbeddedMonospacedFont").toBool();
223-
Q_EMIT useEmbeddedMonospacedFontChanged(m_use_embedded_monospaced_font);
259+
Q_EMIT fontForMoneyChanged(getFontForMoney());
224260

225261
m_mask_values = settings.value("mask_values", false).toBool();
226262

@@ -428,8 +464,8 @@ QVariant OptionsModel::getOption(OptionID option, const std::string& suffix) con
428464
return strThirdPartyTxUrls;
429465
case Language:
430466
return QString::fromStdString(SettingToString(setting(), ""));
431-
case UseEmbeddedMonospacedFont:
432-
return m_use_embedded_monospaced_font;
467+
case FontForMoney:
468+
return QVariant::fromValue(m_font_money);
433469
case CoinControlFeatures:
434470
return fCoinControlFeatures;
435471
case EnablePSBTControls:
@@ -455,6 +491,23 @@ QVariant OptionsModel::getOption(OptionID option, const std::string& suffix) con
455491
}
456492
}
457493

494+
QFont OptionsModel::getFontForChoice(const FontChoice& fc)
495+
{
496+
QFont f;
497+
if (std::holds_alternative<FontChoiceAbstract>(fc)) {
498+
f = GUIUtil::fixedPitchFont(fc != UseBestSystemFont);
499+
f.setWeight(QFont::Bold);
500+
} else {
501+
f = std::get<QFont>(fc);
502+
}
503+
return f;
504+
}
505+
506+
QFont OptionsModel::getFontForMoney() const
507+
{
508+
return getFontForChoice(m_font_money);
509+
}
510+
458511
bool OptionsModel::setOption(OptionID option, const QVariant& value, const std::string& suffix)
459512
{
460513
auto changed = [&] { return value.isValid() && value != getOption(option, suffix); };
@@ -587,11 +640,15 @@ bool OptionsModel::setOption(OptionID option, const QVariant& value, const std::
587640
setRestartRequired(true);
588641
}
589642
break;
590-
case UseEmbeddedMonospacedFont:
591-
m_use_embedded_monospaced_font = value.toBool();
592-
settings.setValue("UseEmbeddedMonospacedFont", m_use_embedded_monospaced_font);
593-
Q_EMIT useEmbeddedMonospacedFontChanged(m_use_embedded_monospaced_font);
643+
case FontForMoney:
644+
{
645+
const auto& new_font = value.value<FontChoice>();
646+
if (m_font_money == new_font) break;
647+
settings.setValue("FontForMoney", FontChoiceToString(new_font));
648+
m_font_money = new_font;
649+
Q_EMIT fontForMoneyChanged(getFontForMoney());
594650
break;
651+
}
595652
case CoinControlFeatures:
596653
fCoinControlFeatures = value.toBool();
597654
settings.setValue("fCoinControlFeatures", fCoinControlFeatures);

0 commit comments

Comments
 (0)