File indexing completed on 2025-02-02 04:11:29
0001 /* 0002 * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best> 0003 * 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 0007 #include "google_fonts_widget.hpp" 0008 #include "ui_google_fonts_widget.h" 0009 0010 #include <QEvent> 0011 #include <QSortFilterProxyModel> 0012 0013 #include "io/svg/font_weight.hpp" 0014 0015 namespace { 0016 0017 class SortFilterGoogleFont : public QSortFilterProxyModel 0018 { 0019 public: 0020 0021 void set_search(const QString& query) 0022 { 0023 search = query.toLower(); 0024 invalidateFilter(); 0025 } 0026 0027 void set_subset(const QString& subset) 0028 { 0029 this->subset = subset; 0030 invalidateFilter(); 0031 } 0032 0033 void set_category(glaxnimate::gui::font::GoogleFontsModel::GoogleFont::Category category) 0034 { 0035 this->category = category; 0036 invalidateFilter(); 0037 } 0038 0039 0040 bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override 0041 { 0042 if ( source_row < 0 || source_row >= sourceModel()->rowCount(source_parent) ) 0043 return false; 0044 0045 auto source = static_cast<glaxnimate::gui::font::GoogleFontsModel*>(sourceModel()); 0046 0047 QModelIndex index = source->index(source_row, 0, source_parent); 0048 0049 if ( !search.isEmpty() ) 0050 { 0051 if ( !source->data(index, Qt::DisplayRole).toString().toLower().contains(search) ) 0052 return false; 0053 } 0054 0055 if ( !subset.isEmpty() ) 0056 { 0057 if ( !source->has_subset(index, subset) ) 0058 return false; 0059 } 0060 0061 if ( category != glaxnimate::gui::font::GoogleFontsModel::GoogleFont::Any ) 0062 { 0063 if ( !source->has_category(index, category) ) 0064 return false; 0065 } 0066 0067 return true; 0068 0069 } 0070 private: 0071 QString search; 0072 QString subset; 0073 glaxnimate::gui::font::GoogleFontsModel::GoogleFont::Category category = glaxnimate::gui::font::GoogleFontsModel::GoogleFont::Any; 0074 }; 0075 0076 } // namespace 0077 0078 class glaxnimate::gui::font::GoogleFontsWidget::Private 0079 { 0080 public: 0081 GoogleFontsWidget* parent; 0082 Ui::GoogleFontsWidget ui; 0083 GoogleFontsModel model; 0084 SortFilterGoogleFont proxy_model; 0085 QFont current_font; 0086 int current_weight = 400; 0087 bool current_italic = false; 0088 0089 void set_active_font(const GoogleFontsModel::GoogleFont* font) 0090 { 0091 ui.view_style->clear(); 0092 0093 QListWidgetItem* best_item = nullptr; 0094 int best_score = 0; 0095 const GoogleFontsModel::GoogleFont::Style* best_style = nullptr; 0096 0097 for ( const auto& style : font->styles ) 0098 { 0099 auto item = new QListWidgetItem(style.font.style_name()); 0100 // item->setData(Qt::UserRole, style.weight); 0101 // item->setData(Qt::UserRole+1, style.italic); 0102 ui.view_style->addItem(item); 0103 int score = style.score(current_weight, current_italic); 0104 0105 if ( score > best_score ) 0106 { 0107 best_item = item; 0108 best_score = score; 0109 best_style = &style; 0110 } 0111 } 0112 0113 current_weight = best_style->weight; 0114 current_italic = best_style->italic; 0115 ui.view_style->setCurrentItem(best_item); 0116 0117 current_font.setFamily(font->family); 0118 using io::svg::WeightConverter; 0119 current_font.setWeight(QFont::Weight(WeightConverter::convert(current_weight, WeightConverter::css, WeightConverter::qt))); 0120 current_font.setItalic(current_italic); 0121 0122 Q_EMIT parent->font_changed(current_font); 0123 } 0124 0125 void update_writing_systems() 0126 { 0127 auto current = ui.combo_system->currentText(); 0128 ui.combo_system->clear(); 0129 ui.combo_system->addItem(""); 0130 for ( const auto& subset : model.subsets() ) 0131 ui.combo_system->addItem(subset); 0132 ui.combo_system->setCurrentText(current); 0133 } 0134 0135 void add_category(GoogleFontsModel::GoogleFont::Category cat) 0136 { 0137 ui.combo_category->addItem(model.category_name(cat), int(cat)); 0138 } 0139 0140 void add_categories() 0141 { 0142 add_category(GoogleFontsModel::GoogleFont::Any); 0143 add_category(GoogleFontsModel::GoogleFont::Serif); 0144 add_category(GoogleFontsModel::GoogleFont::SansSerif); 0145 add_category(GoogleFontsModel::GoogleFont::Monospace); 0146 add_category(GoogleFontsModel::GoogleFont::Display); 0147 add_category(GoogleFontsModel::GoogleFont::Handwriting); 0148 } 0149 }; 0150 0151 glaxnimate::gui::font::GoogleFontsWidget::GoogleFontsWidget(QWidget* parent) 0152 : QWidget(parent), d(std::make_unique<Private>()) 0153 { 0154 d->parent = this; 0155 d->ui.setupUi(this); 0156 0157 d->proxy_model.setSourceModel(&d->model); 0158 d->ui.view_google_fonts->setModel(&d->proxy_model); 0159 d->ui.view_google_fonts->verticalHeader()->setVisible(false); 0160 d->ui.view_google_fonts->horizontalHeader()->setSectionResizeMode(GoogleFontsModel::Column::Family, QHeaderView::ResizeToContents); 0161 d->ui.view_google_fonts->horizontalHeader()->setSectionResizeMode(GoogleFontsModel::Column::Popularity, QHeaderView::ResizeToContents); 0162 d->ui.view_google_fonts->horizontalHeader()->setSectionResizeMode(GoogleFontsModel::Column::Category, QHeaderView::ResizeToContents); 0163 d->ui.view_google_fonts->horizontalHeader()->setSectionResizeMode(GoogleFontsModel::Column::Status, QHeaderView::Stretch); 0164 0165 d->proxy_model.setSortRole(GoogleFontsModel::SortRole); 0166 d->ui.view_google_fonts->setSortingEnabled(true); 0167 d->ui.view_google_fonts->sortByColumn(GoogleFontsModel::Column::Popularity, Qt::AscendingOrder); 0168 0169 connect(&d->model, &GoogleFontsModel::max_progress_changed, this, [this](int max){ 0170 d->ui.google_fonts_progress->setMaximum(max); 0171 d->ui.google_fonts_progress->setVisible(max); 0172 d->ui.button_google_refresh->setEnabled(max == 0); 0173 if ( max == 0 ) 0174 d->ui.label_google_error->setText(""); 0175 }); 0176 connect(&d->model, &GoogleFontsModel::progress_changed, d->ui.google_fonts_progress, &QProgressBar::setValue); 0177 connect(d->ui.button_google_refresh, &QAbstractButton::clicked, this, [this]{ 0178 d->model.refresh(); 0179 d->ui.label_google_error->setText(""); 0180 }); 0181 connect(&d->model, &GoogleFontsModel::error, d->ui.label_google_error, &QLabel::setText); 0182 connect(&d->model, &GoogleFontsModel::download_finished, this, [this](int row){ 0183 if ( auto font = d->model.font(row) ) 0184 d->set_active_font(font); 0185 }); 0186 0187 connect(d->ui.view_google_fonts, &QTableView::clicked, this, [this](const QModelIndex& index){ 0188 int row = d->proxy_model.mapToSource(index).row(); 0189 auto font = d->model.font(row); 0190 0191 d->ui.view_style->clear(); 0192 0193 if ( !font ) 0194 return; 0195 0196 if ( font->status == GoogleFontsModel::GoogleFont::Available || font->status == GoogleFontsModel::GoogleFont::Broken ) 0197 d->model.download_font(row); 0198 else 0199 d->set_active_font(font); 0200 }); 0201 0202 connect(d->ui.view_style->selectionModel(), &QItemSelectionModel::currentChanged, this, &GoogleFontsWidget::change_style); 0203 0204 connect(&d->model, &GoogleFontsModel::refresh_finished, this, [this](){ 0205 d->update_writing_systems(); 0206 }); 0207 connect(d->ui.combo_system, &QComboBox::currentTextChanged, &d->proxy_model, &SortFilterGoogleFont::set_subset); 0208 connect(d->ui.edit_family, &QLineEdit::textChanged, &d->proxy_model, &SortFilterGoogleFont::set_search); 0209 0210 d->add_categories(); 0211 connect(d->ui.combo_category, qOverload<int>(&QComboBox::currentIndexChanged), this, [this](){ 0212 d->proxy_model.set_category(GoogleFontsModel::GoogleFont::Category(d->ui.combo_category->currentData().toInt())); 0213 }); 0214 0215 connect(d->ui.size_widget, &FontSizeWidget::font_size_changed, this, [this](double size){ 0216 d->current_font.setPointSizeF(size); 0217 Q_EMIT font_changed(d->current_font); 0218 }); 0219 0220 } 0221 0222 glaxnimate::gui::font::GoogleFontsWidget::~GoogleFontsWidget() = default; 0223 0224 void glaxnimate::gui::font::GoogleFontsWidget::changeEvent ( QEvent* e ) 0225 { 0226 QWidget::changeEvent(e); 0227 0228 if ( e->type() == QEvent::LanguageChange) 0229 { 0230 d->ui.retranslateUi(this); 0231 } 0232 } 0233 0234 void glaxnimate::gui::font::GoogleFontsWidget::showEvent(QShowEvent* e) 0235 { 0236 QWidget::showEvent(e); 0237 if ( d->model.has_token() && d->model.rowCount() == 0 ) 0238 d->model.refresh(); 0239 } 0240 0241 const glaxnimate::gui::font::GoogleFontsModel & glaxnimate::gui::font::GoogleFontsWidget::model() const 0242 { 0243 return d->model; 0244 } 0245 0246 void glaxnimate::gui::font::GoogleFontsWidget::change_style(const QModelIndex& index) 0247 { 0248 if ( index.isValid() ) 0249 { 0250 d->current_font.setStyleName(index.data(Qt::DisplayRole).toString()); 0251 Q_EMIT font_changed(d->current_font); 0252 } 0253 } 0254 0255 void glaxnimate::gui::font::GoogleFontsWidget::set_font_size(double size) 0256 { 0257 d->ui.size_widget->set_font_size(size); 0258 } 0259 0260 glaxnimate::model::CustomFont glaxnimate::gui::font::GoogleFontsWidget::custom_font() const 0261 { 0262 int font_row = d->proxy_model.mapToSource(d->ui.view_google_fonts->currentIndex()).row(); 0263 auto font = d->model.font(font_row); 0264 if ( !font ) 0265 return {}; 0266 0267 auto style_row = d->ui.view_style->currentRow(); 0268 if ( style_row < 0 || style_row >= int(font->styles.size()) ) 0269 return {}; 0270 0271 return font->styles[style_row].font; 0272 } 0273 0274 const QFont & glaxnimate::gui::font::GoogleFontsWidget::selected_font() const 0275 { 0276 return d->current_font; 0277 }