/*
* Olive Community Edition - Non-Linear Video Editor
* Copyright (C) 2025 Olive CE Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "sequence.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include "config/config.h"
#include "core.h"
#include "common/qtutils.h"
#include "undo/undostack.h"
namespace olive
{
SequenceDialog::SequenceDialog(Sequence *s, Type t, QWidget *parent)
: QDialog(parent)
, sequence_(s)
, make_undoable_(true)
{
QVBoxLayout *layout = new QVBoxLayout(this);
QSplitter *splitter = new QSplitter();
layout->addWidget(splitter);
preset_tab_ = new SequenceDialogPresetTab();
splitter->addWidget(preset_tab_);
parameter_tab_ = new SequenceDialogParameterTab(sequence_);
splitter->addWidget(parameter_tab_);
connect(preset_tab_, &SequenceDialogPresetTab::PresetChanged,
parameter_tab_, &SequenceDialogParameterTab::PresetChanged);
connect(preset_tab_, &SequenceDialogPresetTab::PresetAccepted, this,
&SequenceDialog::accept);
connect(parameter_tab_, &SequenceDialogParameterTab::SaveParametersAsPreset,
preset_tab_, &SequenceDialogPresetTab::SaveParametersAsPreset);
// Set up name section
QHBoxLayout *name_layout = new QHBoxLayout();
name_layout->addWidget(new QLabel(tr("Name:")));
name_field_ = new QLineEdit();
name_layout->addWidget(name_field_);
layout->addLayout(name_layout);
// Set up dialog buttons
QDialogButtonBox *buttons =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
QPushButton *default_btn =
buttons->addButton(tr("Set As Default"), QDialogButtonBox::ActionRole);
connect(buttons, &QDialogButtonBox::accepted, this,
&SequenceDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, this,
&SequenceDialog::reject);
connect(default_btn, &QPushButton::clicked, this,
&SequenceDialog::SetAsDefaultClicked);
layout->addWidget(buttons);
// Set window title based on type
switch (t) {
case kNew:
setWindowTitle(tr("New Sequence"));
break;
case kExisting:
setWindowTitle(tr("Editing \"%1\"").arg(sequence_->GetLabel()));
break;
}
name_field_->setText(sequence_->GetLabel());
}
void SequenceDialog::SetUndoable(bool u)
{
make_undoable_ = u;
}
void SequenceDialog::SetNameIsEditable(bool e)
{
name_field_->setEnabled(e);
}
void SequenceDialog::accept()
{
if (name_field_->isEnabled() && name_field_->text().isEmpty()) {
QtUtils::MsgBox(this, QMessageBox::Critical,
tr("Error editing Sequence"),
tr("Please enter a name for this Sequence."));
return;
}
if (!VideoParams::FormatIsFloat(
parameter_tab_->GetSelectedPreviewFormat()) &&
!OLIVE_CONFIG("PreviewNonFloatDontAskAgain").toBool()) {
QMessageBox b(this);
QCheckBox *dont_show_again_ = new QCheckBox(tr("Don't ask me again"));
b.setIcon(QMessageBox::Warning);
b.setWindowTitle(tr("Low Quality Preview"));
b.setText(tr(
"The preview resolution has been set to a non-float format. This may cause banding and clipping artifacts in the preview.\n\n"
"Do you wish to continue?"));
b.setCheckBox(dont_show_again_);
b.addButton(QMessageBox::Yes);
b.addButton(QMessageBox::No);
if (b.exec() == QMessageBox::No) {
return;
}
if (dont_show_again_->isChecked()) {
OLIVE_CONFIG("PreviewNonFloatDontAskAgain") = true;
}
}
// Generate video and audio parameter structs from data
VideoParams video_params =
VideoParams(parameter_tab_->GetSelectedVideoWidth(),
parameter_tab_->GetSelectedVideoHeight(),
parameter_tab_->GetSelectedVideoFrameRate().flipped(),
parameter_tab_->GetSelectedPreviewFormat(),
VideoParams::kInternalChannelCount,
parameter_tab_->GetSelectedVideoPixelAspect(),
parameter_tab_->GetSelectedVideoInterlacingMode(),
parameter_tab_->GetSelectedPreviewResolution());
AudioParams audio_params =
AudioParams(parameter_tab_->GetSelectedAudioSampleRate(),
parameter_tab_->GetSelectedAudioChannelLayout(),
Sequence::kDefaultSampleFormat);
if (make_undoable_) {
// Make undoable command to change the parameters
SequenceParamCommand *param_command = new SequenceParamCommand(
sequence_, video_params, audio_params, name_field_->text(),
parameter_tab_->GetSelectedPreviewAutoCache());
Core::instance()->undo_stack()->push(
param_command,
tr("Set Sequence Parameters For \"%1\"").arg(sequence_->GetLabel()));
} else {
// Set sequence values directly with no undo command
sequence_->SetVideoParams(video_params);
sequence_->SetAudioParams(audio_params);
sequence_->SetLabel(name_field_->text());
sequence_->SetVideoAutoCacheEnabled(
parameter_tab_->GetSelectedPreviewAutoCache());
}
QDialog::accept();
}
void SequenceDialog::SetAsDefaultClicked()
{
if (QtUtils::MsgBox(
this, QMessageBox::Question, tr("Confirm Set As Default"),
tr("Are you sure you want to set the current parameters as defaults?"),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
// Maybe replace with Preset system
OLIVE_CONFIG("DefaultSequenceWidth") =
parameter_tab_->GetSelectedVideoWidth();
OLIVE_CONFIG("DefaultSequenceHeight") =
parameter_tab_->GetSelectedVideoHeight();
OLIVE_CONFIG("DefaultSequencePixelAspect") =
QVariant::fromValue(parameter_tab_->GetSelectedVideoPixelAspect());
OLIVE_CONFIG("DefaultSequenceFrameRate") = QVariant::fromValue(
parameter_tab_->GetSelectedVideoFrameRate().flipped());
OLIVE_CONFIG("DefaultSequenceInterlacing") =
parameter_tab_->GetSelectedVideoInterlacingMode();
OLIVE_CONFIG("DefaultSequenceAudioFrequency") =
parameter_tab_->GetSelectedAudioSampleRate();
OLIVE_CONFIG("DefaultSequenceAudioLayout") = QVariant::fromValue(
parameter_tab_->GetSelectedAudioChannelLayout());
}
}
SequenceDialog::SequenceParamCommand::SequenceParamCommand(
Sequence *s, const VideoParams &video_params,
const AudioParams &audio_params, const QString &name, bool autocache)
: sequence_(s)
, new_video_params_(video_params)
, new_audio_params_(audio_params)
, new_name_(name)
, new_autocache_(autocache)
, old_video_params_(s->GetVideoParams())
, old_audio_params_(s->GetAudioParams())
, old_name_(s->GetLabel())
, old_autocache_(s->IsVideoAutoCacheEnabled())
{
}
Project *SequenceDialog::SequenceParamCommand::GetRelevantProject() const
{
return sequence_->project();
}
void SequenceDialog::SequenceParamCommand::redo()
{
if (sequence_->GetVideoParams() != new_video_params_) {
sequence_->SetVideoParams(new_video_params_);
}
if (sequence_->GetAudioParams() != new_audio_params_) {
sequence_->SetAudioParams(new_audio_params_);
}
sequence_->SetLabel(new_name_);
sequence_->SetVideoAutoCacheEnabled(new_autocache_);
}
void SequenceDialog::SequenceParamCommand::undo()
{
if (sequence_->GetVideoParams() != old_video_params_) {
sequence_->SetVideoParams(old_video_params_);
}
if (sequence_->GetAudioParams() != old_audio_params_) {
sequence_->SetAudioParams(old_audio_params_);
}
sequence_->SetLabel(old_name_);
sequence_->SetVideoAutoCacheEnabled(old_autocache_);
}
}