File indexing completed on 2025-02-02 04:11:27

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 "external_font_widget.hpp"
0008 #include "ui_external_font_widget.h"
0009 
0010 #include <QEvent>
0011 #include <QStandardItemModel>
0012 #include <QFileDialog>
0013 
0014 #include "widgets/font/font_loader.hpp"
0015 #include "font_delegate.hpp"
0016 
0017 class glaxnimate::gui::font::ExternalFontWidget::Private
0018 {
0019 public:
0020     Ui::ExternalFontWidget ui;
0021     FontLoader loader;
0022     std::map<QString, std::vector<model::CustomFont>> fonts;
0023     QStandardItemModel font_model;
0024     QUrl url;
0025     ExternalFontWidget* parent;
0026     QFont current_font;
0027     FontDelegate delegate;
0028 
0029     static bool style_lte(const model::CustomFont& a, const model::CustomFont& b)
0030     {
0031         return a.raw_font().weight() < b.raw_font().weight() || (
0032             a.raw_font().weight() == b.raw_font().weight() &&
0033             a.raw_font().style() < b.raw_font().style()
0034         );
0035     }
0036 
0037     void set_active_font(const QString& family)
0038     {
0039         ui.view_style->clear();
0040 
0041         for ( const auto& style : fonts.at(family) )
0042         {
0043             auto item = new QListWidgetItem(style.raw_font().styleName());
0044             ui.view_style->addItem(item);
0045         }
0046 
0047         current_font.setFamily(family);
0048         ui.view_style->setCurrentRow(0);
0049     }
0050 
0051     void loader_finished()
0052     {
0053         for ( const auto& font : loader.fonts() )
0054             fonts[font.family()].push_back(font);
0055 
0056         loader.clear();
0057         ui.progress_bar->setVisible(false);
0058 
0059         if ( !fonts.empty() )
0060         {
0061             ui.widget_data->setEnabled(true);
0062 
0063             for ( auto& p : fonts )
0064             {
0065                 font_model.appendRow(new QStandardItem(p.first));
0066                 std::sort(p.second.begin(), p.second.end(), &style_lte);
0067             }
0068 
0069             ui.view_fonts->setCurrentIndex(font_model.index(0, 0));
0070         }
0071     }
0072 
0073     void style_selected(const QString& style)
0074     {
0075         current_font.setStyleName(style);
0076         Q_EMIT parent->font_changed(current_font);
0077     }
0078 };
0079 
0080 glaxnimate::gui::font::ExternalFontWidget::ExternalFontWidget(QWidget* parent)
0081     : QWidget(parent), d(std::make_unique<Private>())
0082 {
0083     d->parent = this;
0084     d->ui.setupUi(this);
0085     d->ui.view_fonts->setModel(&d->font_model);
0086     d->ui.view_fonts->setItemDelegateForColumn(0, &d->delegate);
0087     connect(&d->loader, &FontLoader::finished, this, [this]{d->loader_finished();});
0088     connect(&d->loader, &FontLoader::fonts_queued, d->ui.progress_bar, &QProgressBar::setMaximum);
0089     connect(&d->loader, &FontLoader::fonts_loaded, d->ui.progress_bar, &QProgressBar::setValue);
0090     /// \todo handle FontLoader::error
0091     connect(d->ui.view_style->selectionModel(), &QItemSelectionModel::currentChanged, this, [this](const QModelIndex& index){
0092         d->style_selected(index.data().toString());
0093     });
0094     connect(d->ui.size_widget, &FontSizeWidget::font_size_changed, this, [this](double size){
0095         d->current_font.setPointSizeF(size);
0096         Q_EMIT font_changed(d->current_font);
0097     });
0098     connect(d->ui.view_fonts->selectionModel(), &QItemSelectionModel::currentChanged, this, [this](const QModelIndex& index){
0099         d->set_active_font(index.data().toString());
0100     });
0101 }
0102 
0103 glaxnimate::gui::font::ExternalFontWidget::~ExternalFontWidget() = default;
0104 
0105 void glaxnimate::gui::font::ExternalFontWidget::changeEvent ( QEvent* e )
0106 {
0107     QWidget::changeEvent(e);
0108 
0109     if ( e->type() == QEvent::LanguageChange)
0110     {
0111         d->ui.retranslateUi(this);
0112     }
0113 }
0114 
0115 void glaxnimate::gui::font::ExternalFontWidget::load_url()
0116 {
0117     if ( d->url.scheme() == "" )
0118     {
0119         d->url = QUrl::fromLocalFile(d->ui.edit_url->text());
0120         d->ui.edit_url->setText(d->url.toString());
0121     }
0122 
0123     d->loader.cancel();
0124 
0125     d->loader.queue("", d->url);
0126     d->ui.progress_bar->setVisible(true);
0127     d->font_model.clear();
0128     d->ui.widget_data->setEnabled(false);
0129     d->ui.view_style->clear();
0130 
0131     d->loader.load_queue();
0132 }
0133 
0134 void glaxnimate::gui::font::ExternalFontWidget::url_from_file()
0135 {
0136     QString path = QFileDialog::getOpenFileName(this, i18n("Open File"), {},
0137         i18n("All supported files (*.ttf, *.otf, *.css); CSS files (*.css); Font files (*.ttf, *.otf); All files (*)")
0138     );
0139 
0140     if ( !path.isEmpty() )
0141     {
0142         d->url = QUrl::fromLocalFile(path);
0143         d->ui.edit_url->setText(d->url.toString());
0144         load_url();
0145     }
0146 }
0147 
0148 void glaxnimate::gui::font::ExternalFontWidget::url_changed(const QString& url)
0149 {
0150     d->url = QUrl(url);
0151     d->ui.button_load->setEnabled(d->url.isValid());
0152 }
0153 
0154 glaxnimate::model::CustomFont glaxnimate::gui::font::ExternalFontWidget::custom_font() const
0155 {
0156     if ( !d->ui.widget_data->isEnabled() )
0157         return {};
0158 
0159     auto font_iter = d->fonts.find(d->ui.view_fonts->currentIndex().data().toString());
0160     if ( font_iter == d->fonts.end() )
0161         return {};
0162 
0163     int style_index = d->ui.view_style->currentRow();
0164     if ( style_index < 0 || style_index >= int(font_iter->second.size()) )
0165         return {};
0166 
0167     return font_iter->second[style_index];
0168 }
0169 
0170 void glaxnimate::gui::font::ExternalFontWidget::set_font_size(double size)
0171 {
0172     d->ui.size_widget->set_font_size(size);
0173 }
0174 
0175 const QFont & glaxnimate::gui::font::ExternalFontWidget::selected_font() const
0176 {
0177     return d->current_font;
0178 }
0179 
0180 
0181 void glaxnimate::gui::font::ExternalFontWidget::showEvent(QShowEvent* event)
0182 {
0183     QWidget::showEvent(event);
0184     d->ui.progress_bar->setVisible(d->loader.loading());
0185 }