diff --git a/CHANGELOG.md b/CHANGELOG.md index 4256abdf..d743a9b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Minor: Added setting for character limit of deleted messages. (#6491) - Minor: Added link support to plugin message API. (#6386, #6527) - Minor: Added a description for the logging option under moderation tab. (#6514) +- Minor: Consolidate font picking into one dialog. (#6531) - Minor: Added a menu action to sort tabs alphabetically. (#6551) - Minor: Fixed "edit hotkey" dialog opening like a normal window. (#6540) - Bugfix: Expose the "Extra extension IDs" setting on non-Windows systems too. (#6509) diff --git a/resources/buttons/edit.svg b/resources/buttons/edit.svg new file mode 100644 index 00000000..f18c2b9e --- /dev/null +++ b/resources/buttons/edit.svg @@ -0,0 +1 @@ + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4ff72e04..a4c04de2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -646,6 +646,22 @@ set(SOURCE_FILES widgets/dialogs/EditUserNotesDialog.hpp widgets/dialogs/EmotePopup.cpp widgets/dialogs/EmotePopup.hpp + + widgets/dialogs/font/FontDialog.cpp + widgets/dialogs/font/FontDialog.hpp + widgets/dialogs/font/FontFamilyWidget.cpp + widgets/dialogs/font/FontFamilyWidget.hpp + widgets/dialogs/font/FontSettingDialog.cpp + widgets/dialogs/font/FontSettingDialog.hpp + widgets/dialogs/font/FontSizeWidget.cpp + widgets/dialogs/font/FontSizeWidget.hpp + widgets/dialogs/font/FontWeightWidget.cpp + widgets/dialogs/font/FontWeightWidget.hpp + widgets/dialogs/font/IntItem.cpp + widgets/dialogs/font/IntItem.hpp + widgets/dialogs/font/PreviewWidget.cpp + widgets/dialogs/font/PreviewWidget.hpp + widgets/dialogs/LastRunCrashDialog.cpp widgets/dialogs/LastRunCrashDialog.hpp widgets/dialogs/LoginDialog.cpp @@ -700,6 +716,8 @@ set(SOURCE_FILES widgets/helper/DebugPopup.hpp widgets/helper/EditableModelView.cpp widgets/helper/EditableModelView.hpp + widgets/helper/FontSettingWidget.cpp + widgets/helper/FontSettingWidget.hpp widgets/helper/IconDelegate.cpp widgets/helper/IconDelegate.hpp widgets/helper/InvisibleSizeGrip.cpp diff --git a/src/widgets/dialogs/font/FontDialog.cpp b/src/widgets/dialogs/font/FontDialog.cpp new file mode 100644 index 00000000..136411e6 --- /dev/null +++ b/src/widgets/dialogs/font/FontDialog.cpp @@ -0,0 +1,86 @@ +#include "widgets/dialogs/font/FontDialog.hpp" + +#include "widgets/dialogs/font/FontFamilyWidget.hpp" +#include "widgets/dialogs/font/FontSizeWidget.hpp" +#include "widgets/dialogs/font/FontWeightWidget.hpp" +#include "widgets/dialogs/font/PreviewWidget.hpp" + +#include +#include +#include + +namespace chatterino { + +FontDialog::FontDialog(const QFont &startFont, QWidget *parent) + : QDialog(parent) + , preview(new PreviewWidget(startFont)) + , familyW(new FontFamilyWidget(startFont)) + , sizeW(new FontSizeWidget(startFont)) + , weightW(new FontWeightWidget(startFont)) +{ + auto *layout = new QVBoxLayout; + auto *choiceLayout = new QHBoxLayout; + auto *choiceSideLayout = new QVBoxLayout; + auto *buttonLayout = new QHBoxLayout; + + auto *applyButton = new QPushButton("Apply"); + auto *acceptButton = new QPushButton("Ok"); + auto *rejectButton = new QPushButton("Cancel"); + + this->setWindowTitle("Pick Font"); + this->setLayout(layout); + this->resize(450, 450); + + layout->addLayout(choiceLayout, 5); + layout->addWidget(new QLabel("Preview")); + layout->addWidget(this->preview, 1); + layout->addLayout(buttonLayout); + + choiceLayout->addWidget(this->familyW, 5); + choiceLayout->addLayout(choiceSideLayout, 3); + + choiceSideLayout->addWidget(this->sizeW); + choiceSideLayout->addWidget(this->weightW); + + buttonLayout->addWidget(applyButton); + buttonLayout->addStretch(); + buttonLayout->addWidget(acceptButton); + buttonLayout->addWidget(rejectButton); + + QObject::connect(applyButton, &QPushButton::clicked, this, + &FontDialog::applied); + + QObject::connect(acceptButton, &QPushButton::clicked, this, + &FontDialog::accept); + + QObject::connect(rejectButton, &QPushButton::clicked, this, + &FontDialog::reject); + + QObject::connect(this->familyW, &FontFamilyWidget::selectedChanged, this, + [this] { + this->weightW->setFamily(this->familyW->getSelected()); + this->updatePreview(); + }); + + QObject::connect(this->weightW, &FontWeightWidget::selectedChanged, this, + &FontDialog::updatePreview); + + QObject::connect(this->sizeW, &FontSizeWidget::selectedChanged, this, + &FontDialog::updatePreview); +} + +QFont FontDialog::getSelected() const +{ + return { + this->familyW->getSelected(), + this->sizeW->getSelected(), + this->weightW->getSelected(), + }; +} + +void FontDialog::updatePreview() +{ + this->preview->setFont(this->getSelected()); +} + +} // namespace chatterino diff --git a/src/widgets/dialogs/font/FontDialog.hpp b/src/widgets/dialogs/font/FontDialog.hpp new file mode 100644 index 00000000..3a15b30e --- /dev/null +++ b/src/widgets/dialogs/font/FontDialog.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include + +namespace chatterino { + +class PreviewWidget; +class FontFamilyWidget; +class FontSizeWidget; +class FontWeightWidget; + +class FontDialog : public QDialog +{ + Q_OBJECT + +public: + FontDialog(const QFont &startFont, QWidget *parent = nullptr); + + /// Gets the currently selected font. + QFont getSelected() const; + +Q_SIGNALS: + void applied(); + +private: + void updatePreview(); + + PreviewWidget *preview; + FontFamilyWidget *familyW; + FontSizeWidget *sizeW; + FontWeightWidget *weightW; +}; + +} // namespace chatterino diff --git a/src/widgets/dialogs/font/FontFamilyWidget.cpp b/src/widgets/dialogs/font/FontFamilyWidget.cpp new file mode 100644 index 00000000..7e5a3054 --- /dev/null +++ b/src/widgets/dialogs/font/FontFamilyWidget.cpp @@ -0,0 +1,89 @@ +#include "widgets/dialogs/font/FontFamilyWidget.hpp" + +#include +#include +#include +#include + +namespace chatterino { + +namespace { + +/// Gets a list of available font families available on this system +QStringList getFontFamilies() +{ + QStringList families = QFontDatabase::families(); + families.removeIf(QFontDatabase::isPrivateFamily); + return families; +} + +} // namespace + +FontFamilyWidget::FontFamilyWidget(const QFont &startFont, QWidget *parent) + : QWidget(parent) + , list(new QListView) + , model(new QStringListModel(getFontFamilies(), this)) + , proxy(new QSortFilterProxyModel(this)) +{ + auto *layout = new QVBoxLayout; + auto *header = new QHBoxLayout; + auto *search = new QLineEdit; + + this->setLayout(layout); + + this->list->setModel(this->proxy); + this->list->setEditTriggers(QAbstractItemView::NoEditTriggers); + + this->proxy->setSourceModel(this->model); + this->proxy->setFilterCaseSensitivity(Qt::CaseInsensitive); + + this->setSelected(startFont.family()); + + layout->addLayout(header); + layout->addWidget(this->list); + layout->setContentsMargins(0, 0, 0, 0); + + header->addWidget(new QLabel("Font")); + header->addWidget(search); + + search->setPlaceholderText("Search..."); + + QObject::connect(search, &QLineEdit::textChanged, this->proxy, + &QSortFilterProxyModel::setFilterFixedString); + + QObject::connect( + this->list->selectionModel(), &QItemSelectionModel::currentChanged, + this, [this](const QModelIndex &proxyIndex, const QModelIndex &) { + if (proxyIndex.isValid()) + { + Q_EMIT this->selectedChanged(); + } + }); +} + +void FontFamilyWidget::setSelected(const QString &family) +{ + qsizetype row = this->model->stringList().indexOf(family); + if (row >= 0) + { + QModelIndex modelIndex = this->model->index(static_cast(row)); + QModelIndex proxyIndex = this->proxy->mapFromSource(modelIndex); + + this->list->selectionModel()->setCurrentIndex( + proxyIndex, QItemSelectionModel::ClearAndSelect); + } +} + +QString FontFamilyWidget::getSelected() const +{ + QModelIndex proxyIndex = this->list->currentIndex(); + if (!proxyIndex.isValid()) + { + return {}; + } + + QModelIndex modelIndex = this->proxy->mapToSource(proxyIndex); + return this->model->data(modelIndex).toString(); +} + +} // namespace chatterino diff --git a/src/widgets/dialogs/font/FontFamilyWidget.hpp b/src/widgets/dialogs/font/FontFamilyWidget.hpp new file mode 100644 index 00000000..725ca5ab --- /dev/null +++ b/src/widgets/dialogs/font/FontFamilyWidget.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace chatterino { + +class FontFamilyWidget : public QWidget +{ + Q_OBJECT + +public: + FontFamilyWidget(const QFont &startFont, QWidget *parent = nullptr); + + /// Gets the currently selected font family (e.g. "Arial"). + QString getSelected() const; + +Q_SIGNALS: + void selectedChanged(); + +private: + void setSelected(const QString &family); + + QListView *list; + QStringListModel *model; + QSortFilterProxyModel *proxy; +}; + +} // namespace chatterino diff --git a/src/widgets/dialogs/font/FontSettingDialog.cpp b/src/widgets/dialogs/font/FontSettingDialog.cpp new file mode 100644 index 00000000..1bf08e61 --- /dev/null +++ b/src/widgets/dialogs/font/FontSettingDialog.cpp @@ -0,0 +1,45 @@ +#include "widgets/dialogs/font/FontSettingDialog.hpp" + +#include "util/RapidJsonSerializeQString.hpp" // IWYU pragma: keep + +namespace chatterino { + +FontSettingDialog::FontSettingDialog(QStringSetting &family, IntSetting &size, + IntSetting &weight, QWidget *parent) + : FontDialog({family, size, weight}, parent) + , familySetting(family) + , sizeSetting(size) + , weightSetting(weight) + , oldFamily(family) + , oldSize(size) + , oldWeight(weight) +{ + this->setAttribute(Qt::WA_DeleteOnClose); + + QObject::connect(this, &FontDialog::applied, this, + &FontSettingDialog::setSettings); + + QObject::connect(this, &FontDialog::rejected, this, + &FontSettingDialog::restoreSettings); + + QObject::connect(this, &FontDialog::accepted, this, + &FontSettingDialog::setSettings); +} + +void FontSettingDialog::setSettings() +{ + const auto selected = this->getSelected(); + + this->familySetting.setValue(selected.family()); + this->sizeSetting.setValue(selected.pointSize()); + this->weightSetting.setValue(selected.weight()); +} + +void FontSettingDialog::restoreSettings() +{ + this->familySetting.setValue(this->oldFamily); + this->sizeSetting.setValue(this->oldSize); + this->weightSetting.setValue(this->oldWeight); +} + +} // namespace chatterino diff --git a/src/widgets/dialogs/font/FontSettingDialog.hpp b/src/widgets/dialogs/font/FontSettingDialog.hpp new file mode 100644 index 00000000..fecbfc0b --- /dev/null +++ b/src/widgets/dialogs/font/FontSettingDialog.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "common/ChatterinoSetting.hpp" +#include "widgets/dialogs/font/FontDialog.hpp" + +#include + +namespace chatterino { + +class FontSettingDialog : public FontDialog +{ + Q_OBJECT + +public: + FontSettingDialog(QStringSetting &family, IntSetting &size, + IntSetting &weight, QWidget *parent = nullptr); + +private: + /// Apply the current dialog's values to the font settings + void setSettings(); + + /// Restore the original setting values to the font settings + void restoreSettings(); + + QStringSetting &familySetting; + IntSetting &sizeSetting; + IntSetting &weightSetting; + + QString oldFamily; + int oldSize; + int oldWeight; +}; + +} // namespace chatterino diff --git a/src/widgets/dialogs/font/FontSizeWidget.cpp b/src/widgets/dialogs/font/FontSizeWidget.cpp new file mode 100644 index 00000000..20d6f8d5 --- /dev/null +++ b/src/widgets/dialogs/font/FontSizeWidget.cpp @@ -0,0 +1,79 @@ +#include "widgets/dialogs/font/FontSizeWidget.hpp" + +#include "widgets/dialogs/font/IntItem.hpp" + +#include +#include +#include +#include + +namespace chatterino { + +FontSizeWidget::FontSizeWidget(const QFont &startFont, QWidget *parent) + : QWidget(parent) + , customItem(new IntItem) + , list(new QListWidget) + , edit(new QSpinBox) +{ + auto *layout = new QVBoxLayout; + auto *header = new QHBoxLayout; + + this->setLayout(layout); + + this->edit->setMinimum(1); + this->list->setSortingEnabled(true); + this->list->addItem(this->customItem); + + for (int size : QFontDatabase::standardSizes()) + { + this->list->addItem(new IntItem(size)); + } + + this->edit->setValue(startFont.pointSize()); + this->setListSelected(startFont.pointSize()); + + layout->addLayout(header); + layout->addWidget(this->list); + layout->setContentsMargins(0, 0, 0, 0); + + header->addWidget(new QLabel("Size")); + header->addWidget(this->edit); + + QObject::connect(this->edit, &QSpinBox::valueChanged, this, + [this](int value) { + QSignalBlocker listSignalBlocker(this->list); + this->setListSelected(value); + Q_EMIT this->selectedChanged(); + }); + + QObject::connect(this->list, &QListWidget::currentItemChanged, this, + [this](QListWidgetItem *item) { + auto *cast = dynamic_cast(item); + assert(cast); + QSignalBlocker editSignalBlocker(this->edit); + this->edit->setValue(cast->getValue()); + Q_EMIT this->selectedChanged(); + }); +} + +int FontSizeWidget::getSelected() const +{ + auto *item = dynamic_cast(this->list->currentItem()); + return item ? item->getValue() : -1; +} + +void FontSizeWidget::setListSelected(int size) +{ + if (IntItem *item = findIntItemInList(this->list, size)) + { + this->customItem->setHidden(item != this->customItem); + this->list->setCurrentItem(item); + return; + } + + this->customItem->setValue(size); + this->customItem->setHidden(false); + this->list->setCurrentItem(this->customItem); +} + +} // namespace chatterino diff --git a/src/widgets/dialogs/font/FontSizeWidget.hpp b/src/widgets/dialogs/font/FontSizeWidget.hpp new file mode 100644 index 00000000..5e4578a9 --- /dev/null +++ b/src/widgets/dialogs/font/FontSizeWidget.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include +#include + +namespace chatterino { + +class IntItem; + +/// FontSizeWidget shows a subset of the possible font sizes in a list, +/// alongside a spinbox where the user can enter their exact font size. +class FontSizeWidget : public QWidget +{ + Q_OBJECT + +public: + FontSizeWidget(const QFont &startFont, QWidget *parent = nullptr); + + /// Gets the currently selected font size. + int getSelected() const; + +Q_SIGNALS: + void selectedChanged(); + +private: + void setListSelected(int size); + + IntItem *customItem; // displays the value from `edit` + QListWidget *list; + QSpinBox *edit; +}; + +} // namespace chatterino diff --git a/src/widgets/dialogs/font/FontWeightWidget.cpp b/src/widgets/dialogs/font/FontWeightWidget.cpp new file mode 100644 index 00000000..bd18168b --- /dev/null +++ b/src/widgets/dialogs/font/FontWeightWidget.cpp @@ -0,0 +1,110 @@ +#include "widgets/dialogs/font/FontWeightWidget.hpp" + +#include "widgets/dialogs/font/IntItem.hpp" + +#include +#include +#include +#include +#include +#include + +namespace chatterino { + +namespace { + +/// Get a list of weights available for the given font family +QList getWeights(const QString &family) +{ + QList weights; + QStringList styles = QFontDatabase::styles(family); + + for (const QString &style : styles) + { + int weight = QFontDatabase::weight(family, style); + if (!weights.contains(weight)) + { + weights.append(weight); + } + } + + return weights; +} + +} // namespace + +FontWeightWidget::FontWeightWidget(const QFont &startFont, QWidget *parent) + : QWidget(parent) + , list(new QListWidget) +{ + auto *layout = new QVBoxLayout; + + this->setLayout(layout); + + this->setFamily(startFont.family()); + if (IntItem *item = findIntItemInList(this->list, startFont.weight())) + { + this->list->setCurrentItem(item); + } + + layout->addWidget(new QLabel("Weight")); + layout->addWidget(this->list); + layout->setContentsMargins(0, 0, 0, 0); + + QObject::connect(this->list, &QListWidget::currentRowChanged, this, + [this](int row) { + if (row >= 0) + { + Q_EMIT this->selectedChanged(); + } + }); +} + +void FontWeightWidget::setFamily(const QString &family) +{ + QSignalBlocker listSignalBlocker{this->list}; + + QList weights = getWeights(family); + int currentCount = this->list->count(); + int newCount = static_cast(weights.count()); + int leastCount = std::min(currentCount, newCount); + + std::ranges::sort(weights); + + for (int i = 0; i < leastCount; ++i) + { + auto *cast = dynamic_cast(this->list->item(i)); + assert(cast); + cast->setValue(weights[i]); + cast->setHidden(false); + } + for (int i = currentCount; i < newCount; ++i) + { + this->list->addItem(new IntItem(weights[i])); + } + for (int i = newCount; i < currentCount; ++i) + { + this->list->item(i)->setHidden(true); + } + + int startRow = 0; + for (int closest = INT_MAX, i = 0; i < weights.count(); ++i) + { + int diff = std::abs(weights[i] - QFont::Normal); + if (diff < closest) + { + closest = diff; + startRow = i; + } + } + + this->list->setCurrentRow(startRow); +} + +int FontWeightWidget::getSelected() const +{ + auto *cast = dynamic_cast(this->list->currentItem()); + return cast ? cast->getValue() : -1; +} + +} // namespace chatterino diff --git a/src/widgets/dialogs/font/FontWeightWidget.hpp b/src/widgets/dialogs/font/FontWeightWidget.hpp new file mode 100644 index 00000000..ab14a48b --- /dev/null +++ b/src/widgets/dialogs/font/FontWeightWidget.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include +#include + +namespace chatterino { + +/// FontWeightWidget shows a list of available font weights for a given font family. +class FontWeightWidget : public QWidget +{ + Q_OBJECT + +public: + FontWeightWidget(const QFont &startFont, QWidget *parent = nullptr); + + /// Update the font family, resetting the selected font weight to the weight + /// that's closest to "normal". + void setFamily(const QString &family); + + /// Gets the currently selected font weight. + int getSelected() const; + +Q_SIGNALS: + void selectedChanged(); + +private: + QListWidget *list; +}; + +} // namespace chatterino diff --git a/src/widgets/dialogs/font/IntItem.cpp b/src/widgets/dialogs/font/IntItem.cpp new file mode 100644 index 00000000..39f3cee9 --- /dev/null +++ b/src/widgets/dialogs/font/IntItem.cpp @@ -0,0 +1,50 @@ +#include "widgets/dialogs/font/IntItem.hpp" + +namespace chatterino { + +IntItem::IntItem(int v, QListWidget *parent) + : QListWidgetItem(QString::number(v), parent, IntItem::TYPE_ID) + , value(v) +{ +} + +bool IntItem::operator<(const QListWidgetItem &other) const +{ + const auto *cast = dynamic_cast(&other); + if (cast == nullptr) + { + assert(cast && "IntItem may only be compared with other list items"); + return false; + } + + return this->value < cast->value; +} + +void IntItem::setValue(int v) +{ + this->value = v; + QListWidgetItem::setText(QString::number(v)); +} + +int IntItem::getValue() const +{ + return this->value; +} + +IntItem *findIntItemInList(QListWidget *list, int value) +{ + int numItems = list->count(); + + for (int i = 0; i < numItems; ++i) + { + auto *item = dynamic_cast(list->item(i)); + if (item && item->getValue() == value) + { + return item; + } + } + + return nullptr; +} + +} // namespace chatterino diff --git a/src/widgets/dialogs/font/IntItem.hpp b/src/widgets/dialogs/font/IntItem.hpp new file mode 100644 index 00000000..adc1bbec --- /dev/null +++ b/src/widgets/dialogs/font/IntItem.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include + +namespace chatterino { + +class IntItem : public QListWidgetItem +{ +public: + static constexpr int TYPE_ID = QListWidgetItem::UserType + 101; + + IntItem(int v = 0, QListWidget *parent = nullptr); + + /// setText should not be used, we only store int values in this item + /// + /// use setValue instead. + void setText(const QString &) = delete; + + bool operator<(const QListWidgetItem &other) const override; + + void setValue(int v); + int getValue() const; + +private: + int value; +}; + +/// Iterate through all items in the given list and return the item +/// matching the given value +IntItem *findIntItemInList(QListWidget *list, int value); + +} // namespace chatterino diff --git a/src/widgets/dialogs/font/PreviewWidget.cpp b/src/widgets/dialogs/font/PreviewWidget.cpp new file mode 100644 index 00000000..f0f08007 --- /dev/null +++ b/src/widgets/dialogs/font/PreviewWidget.cpp @@ -0,0 +1,32 @@ +#include "widgets/dialogs/font/PreviewWidget.hpp" + +#include + +namespace chatterino { + +PreviewWidget::PreviewWidget(const QFont &startFont, QWidget *parent) + : QWidget(parent) + , font(startFont) +{ + this->setMinimumHeight(60); +} + +void PreviewWidget::paintEvent(QPaintEvent * /* event */) +{ + QPainter painter{this}; + + painter.fillRect(this->rect(), this->palette().base()); + painter.setFont(this->font); + painter.drawText( + this->rect().adjusted(3, 3, -3, -3), + Qt::AlignCenter | Qt::TextSingleLine, + QStringLiteral("The quick brown fox jumps over the lazy dog")); +} + +void PreviewWidget::setFont(const QFont &font) +{ + this->font = font; + this->update(); +} + +} // namespace chatterino diff --git a/src/widgets/dialogs/font/PreviewWidget.hpp b/src/widgets/dialogs/font/PreviewWidget.hpp new file mode 100644 index 00000000..2e1aa864 --- /dev/null +++ b/src/widgets/dialogs/font/PreviewWidget.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include + +namespace chatterino { + +class PreviewWidget : public QWidget +{ +public: + PreviewWidget(const QFont &startFont, QWidget *parent = nullptr); + + void setFont(const QFont &font); + + void paintEvent(QPaintEvent *event) override; + +private: + QFont font; +}; + +} // namespace chatterino diff --git a/src/widgets/helper/FontSettingWidget.cpp b/src/widgets/helper/FontSettingWidget.cpp new file mode 100644 index 00000000..172c8f51 --- /dev/null +++ b/src/widgets/helper/FontSettingWidget.cpp @@ -0,0 +1,69 @@ +#include "widgets/helper/FontSettingWidget.hpp" + +#include "Application.hpp" +#include "singletons/Fonts.hpp" +#include "singletons/Settings.hpp" +#include "widgets/dialogs/font/FontSettingDialog.hpp" + +#include +#include +#include +#include + +namespace chatterino { + +FontSettingWidget::FontSettingWidget(QStringSetting &family, IntSetting &size, + IntSetting &weight, QWidget *parent) + : QWidget(parent) + , familySetting(family) + , sizeSetting(size) + , weightSetting(weight) + , currentLabel(new QLabel) + , listener([this] { + this->updateCurrentLabel(); + }) +{ + auto *layout = new QHBoxLayout; + auto *button = new QToolButton; + + this->setLayout(layout); + this->updateCurrentLabel(); + + this->listener.add(getApp()->getFonts()->fontChanged); + + layout->addWidget(new QLabel("Font:")); + layout->addStretch(1); + layout->addWidget(this->currentLabel); + layout->addWidget(button); + layout->setContentsMargins(0, 0, 0, 0); + + button->setIcon(QIcon(":/buttons/edit.svg")); + + QObject::connect(button, &QToolButton::clicked, this, + &FontSettingWidget::showDialog); +} + +void FontSettingWidget::updateCurrentLabel() +{ + QFont font = getApp()->getFonts()->getFont(FontStyle::ChatMedium, 1); + QString family = font.family(); + QString ptSize = QString::number(font.pointSize()); + this->currentLabel->setText(family + ", " + ptSize + "pt"); +} + +void FontSettingWidget::showDialog() +{ + if (!this->dialog) + { + this->dialog = new FontSettingDialog( + this->familySetting, this->sizeSetting, this->weightSetting, this); + + QObject::connect(this->dialog, &QObject::destroyed, [this] { + this->dialog = nullptr; + }); + } + + this->dialog->show(); +} + +} // namespace chatterino diff --git a/src/widgets/helper/FontSettingWidget.hpp b/src/widgets/helper/FontSettingWidget.hpp new file mode 100644 index 00000000..8277c97e --- /dev/null +++ b/src/widgets/helper/FontSettingWidget.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include "common/ChatterinoSetting.hpp" +#include "util/SignalListener.hpp" + +#include +#include + +namespace chatterino { + +class FontSettingDialog; + +/// FontSettingWidget includes a label showing the current font and its size, with a button +/// that opens a FontSettingDialog +class FontSettingWidget : public QWidget +{ +public: + FontSettingWidget(QStringSetting &family, IntSetting &size, + IntSetting &weight, QWidget *parent = nullptr); + +private: + void updateCurrentLabel(); + void showDialog(); + + FontSettingDialog *dialog = nullptr; + + QStringSetting &familySetting; + IntSetting &sizeSetting; + IntSetting &weightSetting; + + QLabel *currentLabel; + SignalListener listener; +}; + +} // namespace chatterino diff --git a/src/widgets/settingspages/GeneralPage.cpp b/src/widgets/settingspages/GeneralPage.cpp index 73fa5907..81ae2793 100644 --- a/src/widgets/settingspages/GeneralPage.cpp +++ b/src/widgets/settingspages/GeneralPage.cpp @@ -17,6 +17,7 @@ #include "util/Helpers.hpp" #include "util/IncognitoBrowser.hpp" #include "widgets/BaseWindow.hpp" +#include "widgets/helper/FontSettingWidget.hpp" #include "widgets/settingspages/GeneralPageView.hpp" #include "widgets/settingspages/SettingWidget.hpp" @@ -153,34 +154,6 @@ void GeneralPage::initLayout(GeneralPageView &layout) #endif } - layout.addDropdown( - "Font", {"Segoe UI", "Arial", "Choose..."}, s.chatFontFamily, - [](auto val) { - return val; - }, - [this](auto args) { - return this->getFont(args); - }, - true, "", true); - layout.addDropdown( - "Font size", {"9pt", "10pt", "12pt", "14pt", "16pt", "20pt"}, - s.chatFontSize, - [](auto val) { - return QString::number(val) + "pt"; - }, - [](auto args) { - return fuzzyToInt(args.value, 10); - }); - layout.addDropdown( - "Font weight", - {"100", "200", "300", "400", "500", "600", "700", "800", "900"}, - s.chatFontWeight, - [](auto val) { - return QString::number(val); - }, - [](auto args) { - return fuzzyToInt(args.value, 400); - }); layout.addDropdown( "Zoom", ZOOM_LEVELS, s.uiScale, [](auto val) { @@ -263,6 +236,10 @@ void GeneralPage::initLayout(GeneralPageView &layout) SettingWidget::dropdown("Tab style", s.tabStyle)->addTo(layout); + layout.addWidget(new FontSettingWidget(s.chatFontFamily, s.chatFontSize, + s.chatFontWeight), + {"font", "weight", "size"}); + SettingWidget::inverseCheckbox("Show message reply context", s.hideReplyContext) ->setTooltip( @@ -1541,25 +1518,4 @@ void GeneralPage::initExtra() } } -QString GeneralPage::getFont(const DropdownArgs &args) const -{ - if (args.combobox->currentIndex() == args.combobox->count() - 1) - { - args.combobox->setEditText("Choosing..."); - - auto ok = bool(); - auto previousFont = - getApp()->getFonts()->getFont(FontStyle::ChatMedium, 1.); - auto font = QFontDialog::getFont(&ok, previousFont, this->window()); - - if (ok) - { - return font.family(); - } - - return previousFont.family(); - } - return args.value; -} - } // namespace chatterino