File indexing completed on 2025-02-02 04:11:26
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 "startup_dialog.hpp" 0008 #include "ui_startup_dialog.h" 0009 0010 #include <QEvent> 0011 0012 #include "app/settings/settings.hpp" 0013 #include "settings/document_templates.hpp" 0014 #include <model/assets/assets.hpp> 0015 0016 using namespace glaxnimate::gui; 0017 using namespace glaxnimate; 0018 0019 class StartupDialog::Private 0020 { 0021 public: 0022 Ui::StartupDialog ui; 0023 0024 model::FrameTime duration_frames() 0025 { 0026 if ( ui.combo_time_units->currentIndex() == 0 ) 0027 return ui.spin_duration->value(); 0028 return ui.spin_duration->value() * ui.spin_fps->value(); 0029 } 0030 0031 float duration(model::FrameTime time, float fps) 0032 { 0033 if ( ui.combo_time_units->currentIndex() == 0 || fps <= 0 ) 0034 return time; 0035 return time / fps; 0036 } 0037 0038 QString time_suffix() 0039 { 0040 if ( ui.combo_time_units->currentIndex() == 0 ) 0041 return "f"; 0042 return "'"; 0043 } 0044 0045 QString format_duration(const settings::DocumentTemplate& templ) 0046 { 0047 return QString::number(duration(templ.duration(), templ.fps())) + time_suffix(); 0048 } 0049 0050 void adjust_duration_spin() 0051 { 0052 ui.spin_duration->setSuffix(time_suffix()); 0053 if ( ui.combo_time_units->currentIndex() == 0 ) 0054 ui.spin_duration->setDecimals(0); 0055 else 0056 ui.spin_duration->setDecimals(2); 0057 } 0058 0059 void apply_to_document(model::Document* doc) 0060 { 0061 auto last_frame = duration_frames(); 0062 for ( const auto& comp : doc->assets()->compositions->values ) 0063 { 0064 comp->width.set(ui.spin_size->x()); 0065 comp->height.set(ui.spin_size->y()); 0066 comp->fps.set(ui.spin_fps->value()); 0067 comp->animation->last_frame.set(last_frame); 0068 for ( auto lay : comp->docnode_find_by_type_name<model::Layer>("Layer") ) 0069 lay->animation->last_frame.set(last_frame); 0070 } 0071 } 0072 }; 0073 0074 StartupDialog::StartupDialog(QWidget* parent) 0075 : QDialog(parent), d(std::make_unique<Private>()) 0076 { 0077 d->ui.setupUi(this); 0078 reload_presets(); 0079 connect(&settings::DocumentTemplates::instance(), &settings::DocumentTemplates::loaded, this, &StartupDialog::reload_presets); 0080 connect(d->ui.button_open_browse, &QPushButton::clicked, this, &StartupDialog::open_browse); 0081 0082 d->ui.spin_size->enable_ratio_lock(); 0083 d->ui.spin_size->set_decimals(0); 0084 d->ui.spin_size->set_value( 0085 app::settings::get<int>("defaults", "width"), 0086 app::settings::get<int>("defaults", "height") 0087 ); 0088 float fps = app::settings::get<float>("defaults", "fps"); 0089 d->ui.spin_fps->setValue(fps); 0090 d->adjust_duration_spin(); 0091 d->ui.spin_duration->setValue(app::settings::get<float>("defaults", "duration")); 0092 0093 for ( const auto& recent : app::settings::get<QStringList>("open_save", "recent_files") ) 0094 { 0095 QFileInfo finfo(recent); 0096 if ( !finfo.exists() || !finfo.isReadable() ) 0097 continue; 0098 auto item = new QListWidgetItem(QIcon::fromTheme("document-open-recent"), finfo.fileName()); 0099 item->setData(Qt::ToolTipRole, recent); 0100 d->ui.view_recent->addItem(item); 0101 } 0102 0103 d->ui.view_presets->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); 0104 for ( int i = 1; i < d->ui.view_presets->columnCount(); i++ ) 0105 { 0106 d->ui.view_presets->horizontalHeader()->setSectionResizeMode(i, QHeaderView::ResizeToContents); 0107 } 0108 0109 d->ui.check_show_at_startup->setChecked(app::settings::get<bool>("ui", "startup_dialog")); 0110 } 0111 0112 StartupDialog::~StartupDialog() = default; 0113 0114 void StartupDialog::changeEvent ( QEvent* e ) 0115 { 0116 QDialog::changeEvent(e); 0117 0118 if ( e->type() == QEvent::LanguageChange) 0119 { 0120 d->ui.retranslateUi(this); 0121 } 0122 } 0123 0124 void StartupDialog::reload_presets() 0125 { 0126 d->ui.view_presets->clearContents(); 0127 int row = 0; 0128 for ( const auto& templ : settings::DocumentTemplates::instance().templates() ) 0129 { 0130 d->ui.view_presets->insertRow(row); 0131 int col = 0; 0132 d->ui.view_presets->setItem(row, col++, new QTableWidgetItem(QIcon::fromTheme("document-new-from-template"), templ.name())); 0133 0134 auto item = new QTableWidgetItem(QString("%1x%2").arg(templ.size().width()).arg(templ.size().height())); 0135 item->setTextAlignment(Qt::AlignCenter); 0136 d->ui.view_presets->setItem(row, col++, item); 0137 0138 item = new QTableWidgetItem(QString("%1 fps").arg(templ.fps())); 0139 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); 0140 d->ui.view_presets->setItem(row, col++, item); 0141 0142 item = new QTableWidgetItem(templ.aspect_ratio()); 0143 item->setTextAlignment(Qt::AlignCenter); 0144 d->ui.view_presets->setItem(row, col++, item); 0145 0146 item = new QTableWidgetItem(d->format_duration(templ)); 0147 item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); 0148 d->ui.view_presets->setItem(row, col++, item); 0149 row++; 0150 } 0151 } 0152 0153 void StartupDialog::select_preset(const QModelIndex& index) 0154 { 0155 const auto& templ = settings::DocumentTemplates::instance().templates()[index.row()]; 0156 d->ui.spin_size->set_value(templ.size()); 0157 d->ui.spin_fps->setValue(templ.fps()); 0158 d->ui.spin_duration->setValue(d->duration(templ.duration(), templ.fps())); 0159 } 0160 0161 void StartupDialog::click_recent(const QModelIndex& index) 0162 { 0163 Q_EMIT open_recent(index.data(Qt::ToolTipRole).toString()); 0164 reject(); 0165 } 0166 0167 std::unique_ptr<model::Document> StartupDialog::create() const 0168 { 0169 auto index = d->ui.view_presets->currentIndex(); 0170 if ( index.isValid() ) 0171 { 0172 const auto& templ = settings::DocumentTemplates::instance().templates()[index.row()]; 0173 bool ok = false; 0174 auto doc = templ.create(&ok); 0175 if ( ok ) 0176 { 0177 d->apply_to_document(doc.get()); 0178 return doc; 0179 } 0180 } 0181 0182 auto doc = std::make_unique<model::Document>(""); 0183 auto comp = doc->assets()->add_comp_no_undo(); 0184 d->apply_to_document(doc.get()); 0185 0186 auto layer = std::make_unique<model::Layer>(doc.get()); 0187 layer->animation->last_frame.set(d->duration_frames()); 0188 layer->name.set(layer->type_name_human()); 0189 QPointF pos( 0190 d->ui.spin_size->x() / 2.0, 0191 d->ui.spin_size->y() / 2.0 0192 ); 0193 layer->transform.get()->anchor_point.set(pos); 0194 layer->transform.get()->position.set(pos); 0195 comp->shapes.insert(std::move(layer), 0); 0196 0197 return doc; 0198 } 0199 0200 void StartupDialog::update_time_units() 0201 { 0202 d->adjust_duration_spin(); 0203 0204 // seconds * fps = frames 0205 float mult = d->ui.spin_fps->value(); 0206 0207 // fps -> seconds 0208 if ( d->ui.combo_time_units->currentIndex() == 1 ) 0209 mult = 1/mult; 0210 0211 d->ui.spin_duration->setValue(d->ui.spin_duration->value() * mult); 0212 0213 int row = 0; 0214 for ( const auto& templ : settings::DocumentTemplates::instance().templates() ) 0215 { 0216 d->ui.view_presets->item(row, 4)->setData(Qt::DisplayRole, d->format_duration(templ)); 0217 row++; 0218 } 0219 } 0220 0221 void StartupDialog::update_startup_enabled(bool checked) 0222 { 0223 app::settings::set("ui", "startup_dialog", checked); 0224 }