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

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 "frame_controls_widget.hpp"
0008 #include "ui_frame_controls_widget.h"
0009 
0010 #include <cmath>
0011 
0012 #include "glaxnimate_app.hpp"
0013 
0014 using namespace glaxnimate::gui;
0015 using namespace glaxnimate;
0016 
0017 FrameControlsWidget::FrameControlsWidget(QWidget* parent)
0018     : QWidget(parent), d(std::make_unique<Ui::FrameControlsWidget>())
0019 {
0020     d->setupUi(this);
0021 
0022 #ifdef Q_OS_ANDROID
0023     d->layout->setMargin(0);
0024     d->layout->setSpacing(0);
0025 #endif
0026 
0027     d->button_record->setIcon(QIcon::fromTheme("keyframe-record"));
0028 
0029     d->button_next_kf->setVisible(false);
0030     d->button_prev_kf->setVisible(false);
0031     connect(d->button_record, &QAbstractButton::clicked, this, &FrameControlsWidget::record_toggled);
0032     connect(d->button_loop, &QAbstractButton::clicked, this, &FrameControlsWidget::loop_changed);
0033 }
0034 
0035 FrameControlsWidget::~FrameControlsWidget() = default;
0036 
0037 void FrameControlsWidget::changeEvent ( QEvent* e )
0038 {
0039     QWidget::changeEvent(e);
0040     if ( e->type() == QEvent::LanguageChange)
0041     {
0042         d->retranslateUi(this);
0043     }
0044 }
0045 
0046 void FrameControlsWidget::play_toggled(bool checked)
0047 {
0048     if ( checked )
0049         play();
0050     else
0051         pause();
0052 }
0053 
0054 void FrameControlsWidget::set_min(int min)
0055 {
0056     d->spin_frame->setMinimum(min);
0057     Q_EMIT min_changed(min);
0058 }
0059 
0060 void FrameControlsWidget::set_max(int max)
0061 {
0062     d->spin_frame->setMaximum(max-1);
0063     Q_EMIT max_changed(max-1);
0064 }
0065 
0066 void FrameControlsWidget::set_range(int min, int max)
0067 {
0068     d->spin_frame->setRange(min, max-1);
0069     d->spin_frame->setValue(min);
0070     Q_EMIT min_changed(min);
0071     Q_EMIT max_changed(max-1);
0072 }
0073 
0074 void FrameControlsWidget::set_fps(qreal fps)
0075 {
0076     this->fps = fps;
0077     Q_EMIT fps_changed(fps);
0078 }
0079 
0080 void FrameControlsWidget::timerEvent(QTimerEvent*)
0081 {
0082     if ( d->spin_frame->maximum() <= d->spin_frame->minimum() || fps <= 0 )
0083         return;
0084 
0085     auto range_frames = d->spin_frame->maximum() - d->spin_frame->minimum();
0086 
0087     std::chrono::duration<double> offset = std::chrono::high_resolution_clock::now() - playback_start;
0088     auto seconds_off = offset.count();
0089     qreal frame_off = seconds_off * fps + frame_start;
0090 
0091     if ( frame_off >= range_frames && !d->button_loop->isChecked() )
0092     {
0093         pause();
0094         d->spin_frame->setValue(d->spin_frame->minimum());
0095         return;
0096     }
0097 
0098     d->spin_frame->setValue(d->spin_frame->minimum() + qRound(std::fmod(frame_off, range_frames)));
0099 }
0100 
0101 void FrameControlsWidget::play()
0102 {
0103     if ( !timer )
0104     {
0105         timer = startTimer(playback_tick, Qt::PreciseTimer);
0106         playback_start = std::chrono::high_resolution_clock::now();
0107         frame_start = d->spin_frame->value();
0108         d->button_play->setChecked(true);
0109         d->button_play->setIcon(QIcon::fromTheme("media-playback-pause"));
0110         Q_EMIT play_started();
0111     }
0112 }
0113 
0114 void FrameControlsWidget::pause()
0115 {
0116     if ( timer )
0117     {
0118         killTimer(timer);
0119         timer = 0;
0120         d->button_play->setChecked(false);
0121         d->button_play->setIcon(QIcon::fromTheme("media-playback-start"));
0122         Q_EMIT play_stopped();
0123     }
0124 }
0125 
0126 void FrameControlsWidget::commit_time()
0127 {
0128     Q_EMIT frame_selected(d->spin_frame->value());
0129 }
0130 
0131 void FrameControlsWidget::go_first()
0132 {
0133     d->spin_frame->setValue(d->spin_frame->minimum());
0134 }
0135 
0136 void FrameControlsWidget::go_last()
0137 {
0138     d->spin_frame->setValue(d->spin_frame->maximum());
0139 }
0140 
0141 void FrameControlsWidget::go_next()
0142 {
0143     int i = d->spin_frame->value();
0144     if ( i >= d->spin_frame->maximum() && d->button_loop->isChecked() )
0145         d->spin_frame->setValue(d->spin_frame->minimum());
0146     else
0147         d->spin_frame->setValue(i+1);
0148 }
0149 
0150 void FrameControlsWidget::go_prev()
0151 {
0152     int i = d->spin_frame->value();
0153     if ( i <= d->spin_frame->minimum() && d->button_loop->isChecked() )
0154         d->spin_frame->setValue(d->spin_frame->maximum());
0155     else
0156         d->spin_frame->setValue(i-1);
0157 }
0158 
0159 void FrameControlsWidget::set_frame(int frame)
0160 {
0161     d->spin_frame->setValue(frame);
0162 }
0163 
0164 void FrameControlsWidget::set_record_enabled(bool enabled)
0165 {
0166     d->button_record->setChecked(enabled);
0167 }
0168 
0169 void FrameControlsWidget::toggle_play()
0170 {
0171     if ( timer )
0172         pause();
0173     else
0174         play();
0175 }
0176 
0177 void FrameControlsWidget::set_loop(bool loop)
0178 {
0179     d->button_loop->setChecked(loop);
0180 }