merged with master
This commit is contained in:
+33
-3
@@ -57,13 +57,14 @@ Config::Config()
|
||||
hover_focus(false),
|
||||
project_view_type(olive::PROJECT_VIEW_TREE),
|
||||
set_name_with_marker(true),
|
||||
show_project_toolbar(false),
|
||||
show_project_toolbar(true),
|
||||
previous_queue_size(3),
|
||||
previous_queue_type(olive::FRAME_QUEUE_TYPE_FRAMES),
|
||||
upcoming_queue_size(0.5),
|
||||
upcoming_queue_type(olive::FRAME_QUEUE_TYPE_SECONDS),
|
||||
loop(false),
|
||||
seek_also_selects(false),
|
||||
auto_seek_to_beginning(true),
|
||||
effect_textbox_lines(3),
|
||||
use_software_fallback(false),
|
||||
center_timeline_timecodes(true),
|
||||
@@ -73,7 +74,12 @@ Config::Config()
|
||||
invert_timeline_scroll_axes(true),
|
||||
enable_color_management(false),
|
||||
style(olive::styling::kOliveDefaultDark),
|
||||
use_native_menu_styling(true)
|
||||
use_native_menu_styling(true),
|
||||
default_sequence_width(1920),
|
||||
default_sequence_height(1080),
|
||||
default_sequence_framerate(29.97),
|
||||
default_sequence_audio_frequency(48000),
|
||||
default_sequence_audio_channel_layout(3)
|
||||
{}
|
||||
|
||||
void Config::load(QString path) {
|
||||
@@ -180,6 +186,9 @@ void Config::load(QString path) {
|
||||
} else if (stream.name() == "SeekAlsoSelects") {
|
||||
stream.readNext();
|
||||
seek_also_selects = (stream.text() == "1");
|
||||
} else if (stream.name() == "AutoSeekToBeginning") {
|
||||
stream.readNext();
|
||||
auto_seek_to_beginning = (stream.text() == "1");
|
||||
} else if (stream.name() == "CSSPath") {
|
||||
stream.readNext();
|
||||
css_path = stream.text().toString();
|
||||
@@ -222,6 +231,21 @@ void Config::load(QString path) {
|
||||
} else if (stream.name() == "NativeMenuStyling") {
|
||||
stream.readNext();
|
||||
use_native_menu_styling = (stream.text() == "1");
|
||||
} else if (stream.name() == "DefaultSequenceWidth") {
|
||||
stream.readNext();
|
||||
default_sequence_width = stream.text().toInt();
|
||||
} else if (stream.name() == "DefaultSequenceHeight") {
|
||||
stream.readNext();
|
||||
default_sequence_height = stream.text().toInt();
|
||||
} else if (stream.name() == "DefaultSequenceFrameRate") {
|
||||
stream.readNext();
|
||||
default_sequence_framerate = stream.text().toDouble();
|
||||
} else if (stream.name() == "DefaultSequenceAudioFrequency") {
|
||||
stream.readNext();
|
||||
default_sequence_audio_frequency = stream.text().toInt();
|
||||
} else if (stream.name() == "DefaultSequenceAudioLayout") {
|
||||
stream.readNext();
|
||||
default_sequence_audio_channel_layout = stream.text().toInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -271,13 +295,14 @@ void Config::save(QString path) {
|
||||
stream.writeTextElement("HoverFocus", QString::number(hover_focus));
|
||||
stream.writeTextElement("ProjectViewType", QString::number(project_view_type));
|
||||
stream.writeTextElement("SetNameWithMarker", QString::number(set_name_with_marker));
|
||||
stream.writeTextElement("ShowProjectToolbar", QString::number(panel_project->toolbar_widget->isVisible()));
|
||||
stream.writeTextElement("ShowProjectToolbar", QString::number(panel_project->IsToolbarVisible()));
|
||||
stream.writeTextElement("PreviousFrameQueueSize", QString::number(previous_queue_size));
|
||||
stream.writeTextElement("PreviousFrameQueueType", QString::number(previous_queue_type));
|
||||
stream.writeTextElement("UpcomingFrameQueueSize", QString::number(upcoming_queue_size));
|
||||
stream.writeTextElement("UpcomingFrameQueueType", QString::number(upcoming_queue_type));
|
||||
stream.writeTextElement("Loop", QString::number(loop));
|
||||
stream.writeTextElement("SeekAlsoSelects", QString::number(seek_also_selects));
|
||||
stream.writeTextElement("AutoSeekToBeginning", QString::number(auto_seek_to_beginning));
|
||||
stream.writeTextElement("CSSPath", css_path);
|
||||
stream.writeTextElement("EffectTextboxLines", QString::number(effect_textbox_lines));
|
||||
stream.writeTextElement("UseSoftwareFallback", QString::number(use_software_fallback));
|
||||
@@ -292,6 +317,11 @@ void Config::save(QString path) {
|
||||
stream.writeTextElement("OCIOConfigPath", ocio_config_path);
|
||||
stream.writeTextElement("Style", QString::number(style));
|
||||
stream.writeTextElement("NativeMenuStyling", QString::number(use_native_menu_styling));
|
||||
stream.writeTextElement("DefaultSequenceWidth", QString::number(default_sequence_width));
|
||||
stream.writeTextElement("DefaultSequenceHeight", QString::number(default_sequence_height));
|
||||
stream.writeTextElement("DefaultSequenceFrameRate", QString::number(default_sequence_framerate));
|
||||
stream.writeTextElement("DefaultSequenceAudioFrequency", QString::number(default_sequence_audio_frequency));
|
||||
stream.writeTextElement("DefaultSequenceAudioLayout", QString::number(default_sequence_audio_channel_layout));
|
||||
|
||||
stream.writeEndElement(); // configuration
|
||||
stream.writeEndDocument(); // doc
|
||||
|
||||
+36
-1
@@ -120,7 +120,10 @@ namespace olive {
|
||||
PROJECT_VIEW_TREE,
|
||||
|
||||
/** Display project media in icon browser */
|
||||
PROJECT_VIEW_ICON
|
||||
PROJECT_VIEW_ICON,
|
||||
|
||||
/** Display project media in list browser */
|
||||
PROJECT_VIEW_LIST
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -413,6 +416,13 @@ struct Config {
|
||||
*/
|
||||
bool seek_also_selects;
|
||||
|
||||
/**
|
||||
* @brief Automatically seek to the beginning of a sequence if the user plays beyond the end of it
|
||||
*
|
||||
* TRUE if this behavior should be enabled.
|
||||
*/
|
||||
bool auto_seek_to_beginning;
|
||||
|
||||
/**
|
||||
* @brief CSS Path
|
||||
*
|
||||
@@ -558,6 +568,31 @@ struct Config {
|
||||
*/
|
||||
bool use_native_menu_styling;
|
||||
|
||||
/**
|
||||
* @brief Default Sequence video width
|
||||
*/
|
||||
int default_sequence_width;
|
||||
|
||||
/**
|
||||
* @brief Default Sequence video height
|
||||
*/
|
||||
int default_sequence_height;
|
||||
|
||||
/**
|
||||
* @brief Default Sequence video frame rate
|
||||
*/
|
||||
double default_sequence_framerate;
|
||||
|
||||
/**
|
||||
* @brief Default Sequence audio frequency
|
||||
*/
|
||||
int default_sequence_audio_frequency;
|
||||
|
||||
/**
|
||||
* @brief Default Sequence audio channel layout
|
||||
*/
|
||||
int default_sequence_audio_channel_layout;
|
||||
|
||||
/**
|
||||
* @brief Load config from file
|
||||
*
|
||||
|
||||
+85
-42
@@ -39,6 +39,7 @@
|
||||
#include "dialogs/speeddialog.h"
|
||||
#include "dialogs/actionsearch.h"
|
||||
#include "dialogs/loaddialog.h"
|
||||
#include "dialogs/autocutsilencedialog.h"
|
||||
#include "project/loadthread.h"
|
||||
#include "timeline/sequence.h"
|
||||
#include "ui/mediaiconservice.h"
|
||||
@@ -91,7 +92,12 @@ void OliveGlobal::check_for_autorecovery_file() {
|
||||
// detect auto-recovery file
|
||||
autorecovery_filename = data_dir + "/autorecovery.ove";
|
||||
if (QFile::exists(autorecovery_filename)) {
|
||||
if (QMessageBox::question(nullptr, tr("Auto-recovery"), tr("Olive didn't close properly and an autorecovery file was detected. Would you like to open it?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
|
||||
if (QMessageBox::question(nullptr,
|
||||
tr("Auto-recovery"),
|
||||
tr("Olive didn't close properly and an autorecovery file "
|
||||
"was detected. Would you like to open it?"),
|
||||
QMessageBox::Yes,
|
||||
QMessageBox::No) == QMessageBox::Yes) {
|
||||
enable_load_project_on_init = false;
|
||||
OpenProjectWorker(autorecovery_filename, true);
|
||||
}
|
||||
@@ -166,18 +172,19 @@ void OliveGlobal::SetNativeStyling(QWidget *w)
|
||||
#endif
|
||||
}
|
||||
|
||||
void OliveGlobal::LoadProject(const QString &fn, bool autorecovery, bool clear)
|
||||
void OliveGlobal::LoadProject(const QString &fn, bool autorecovery)
|
||||
{
|
||||
// Normally, the user will be closing the previous project to load a new one, but just in case the user
|
||||
// is importing a new project
|
||||
// QSortFilterProxyModels are not thread-safe, and as we'll be loading in another thread, leaving it connected
|
||||
// can cause glitches in its presentation. Therefore for the duration of the loading process, we disconnect it,
|
||||
// and reconnect it later once the loading is complete.
|
||||
|
||||
if (clear) {
|
||||
new_project();
|
||||
}
|
||||
panel_project->DisconnectFilterToModel();
|
||||
|
||||
LoadDialog ld(olive::MainWindow);
|
||||
|
||||
LoadThread* lt = new LoadThread(fn, autorecovery, clear);
|
||||
ld.open();
|
||||
|
||||
LoadThread* lt = new LoadThread(fn, autorecovery);
|
||||
connect(&ld, SIGNAL(cancel()), lt, SLOT(cancel()));
|
||||
connect(lt, SIGNAL(success()), &ld, SLOT(accept()));
|
||||
connect(lt, SIGNAL(error()), &ld, SLOT(reject()));
|
||||
@@ -185,40 +192,46 @@ void OliveGlobal::LoadProject(const QString &fn, bool autorecovery, bool clear)
|
||||
connect(lt, SIGNAL(report_progress(int)), &ld, SLOT(setValue(int)));
|
||||
lt->start();
|
||||
|
||||
ld.exec();
|
||||
panel_project->ConnectFilterToModel();
|
||||
}
|
||||
|
||||
void OliveGlobal::ClearProject()
|
||||
{
|
||||
// clear graph editor
|
||||
panel_graph_editor->set_row(nullptr);
|
||||
|
||||
// clear effects panel
|
||||
panel_effect_controls->Clear(true);
|
||||
|
||||
// clear existing project
|
||||
olive::Global->set_sequence(nullptr);
|
||||
panel_footage_viewer->set_media(nullptr);
|
||||
|
||||
// clear project contents (footage, sequences, etc.)
|
||||
panel_project->clear();
|
||||
|
||||
// clear undo stack
|
||||
olive::UndoStack.clear();
|
||||
|
||||
// empty current project filename
|
||||
update_project_filename("");
|
||||
|
||||
// full update of all panels
|
||||
update_ui(false);
|
||||
|
||||
// set to unmodified
|
||||
olive::Global->set_modified(false);
|
||||
}
|
||||
|
||||
void OliveGlobal::ImportProject(const QString &fn)
|
||||
{
|
||||
LoadProject(fn, false, false);
|
||||
LoadProject(fn, false);
|
||||
set_modified(true);
|
||||
}
|
||||
|
||||
void OliveGlobal::new_project() {
|
||||
if (can_close_project()) {
|
||||
// clear graph editor
|
||||
panel_graph_editor->set_row(nullptr);
|
||||
|
||||
// clear effects panel
|
||||
panel_effect_controls->Clear(true);
|
||||
|
||||
// clear existing project
|
||||
olive::Global->set_sequence(nullptr);
|
||||
panel_footage_viewer->set_media(nullptr);
|
||||
|
||||
// clear project contents (footage, sequences, etc.)
|
||||
panel_project->clear();
|
||||
|
||||
// clear undo stack
|
||||
olive::UndoStack.clear();
|
||||
|
||||
// empty current project filename
|
||||
update_project_filename("");
|
||||
|
||||
// full update of all panels
|
||||
update_ui(false);
|
||||
|
||||
// set to unmodified
|
||||
olive::Global->set_modified(false);
|
||||
ClearProject();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,12 +302,7 @@ bool OliveGlobal::can_close_project() {
|
||||
}
|
||||
|
||||
void OliveGlobal::open_export_dialog() {
|
||||
if (olive::ActiveSequence == nullptr) {
|
||||
QMessageBox::information(olive::MainWindow,
|
||||
tr("No active sequence"),
|
||||
tr("Please open the sequence you wish to export."),
|
||||
QMessageBox::Ok);
|
||||
} else {
|
||||
if (CheckForActiveSequence()) {
|
||||
ExportDialog e(olive::MainWindow);
|
||||
e.exec();
|
||||
}
|
||||
@@ -358,12 +366,29 @@ void OliveGlobal::set_sequence(SequencePtr s)
|
||||
panel_timeline->setFocus();
|
||||
}
|
||||
|
||||
void OliveGlobal::OpenProjectWorker(const QString& fn, bool autorecovery) {
|
||||
void OliveGlobal::OpenProjectWorker(QString fn, bool autorecovery) {
|
||||
ClearProject();
|
||||
update_project_filename(fn);
|
||||
LoadProject(fn, autorecovery, true);
|
||||
LoadProject(fn, autorecovery);
|
||||
olive::UndoStack.clear();
|
||||
}
|
||||
|
||||
bool OliveGlobal::CheckForActiveSequence(bool show_msg)
|
||||
{
|
||||
if (olive::ActiveSequence == nullptr) {
|
||||
|
||||
if (show_msg) {
|
||||
QMessageBox::information(olive::MainWindow,
|
||||
tr("No active sequence"),
|
||||
tr("Please open the sequence to perform this action."),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void OliveGlobal::undo() {
|
||||
// workaround to prevent crash (and also users should never need to do this)
|
||||
if (!panel_timeline->importing) {
|
||||
@@ -413,6 +438,24 @@ void OliveGlobal::open_speed_dialog() {
|
||||
}
|
||||
}
|
||||
|
||||
void OliveGlobal::open_autocut_silence_dialog() {
|
||||
if (CheckForActiveSequence()) {
|
||||
|
||||
QVector<Clip*> selected_clips = olive::ActiveSequence->SelectedClips();
|
||||
|
||||
if (selected_clips.isEmpty()) {
|
||||
QMessageBox::critical(olive::MainWindow,
|
||||
tr("No clips selected"),
|
||||
tr("Select the clips you wish to auto-cut"),
|
||||
QMessageBox::Ok);
|
||||
} else {
|
||||
AutoCutSilenceDialog s(olive::MainWindow, selected_clips);
|
||||
s.exec();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void OliveGlobal::clear_undo_stack() {
|
||||
olive::UndoStack.clear();
|
||||
}
|
||||
|
||||
+27
-2
@@ -275,6 +275,11 @@ public slots:
|
||||
*/
|
||||
void open_speed_dialog();
|
||||
|
||||
/**
|
||||
* @brief Open the auto-cut silence dialog.
|
||||
*/
|
||||
void open_autocut_silence_dialog();
|
||||
|
||||
/**
|
||||
* @brief Open the Action Search overlay.
|
||||
*/
|
||||
@@ -338,7 +343,19 @@ private:
|
||||
* beside the original project file so that it does not overwrite the original and so that the user is not working
|
||||
* on the autorecovery project in Olive's application data directory.
|
||||
*/
|
||||
void OpenProjectWorker(const QString& fn, bool autorecovery);
|
||||
void OpenProjectWorker(QString fn, bool autorecovery);
|
||||
|
||||
/**
|
||||
* @brief Returns whether a Sequence is currently active or not, and optionally displays a messagebox if not
|
||||
*
|
||||
* Checks whether a Sequence is active and can display a messagebox if not to inform users to make one active in
|
||||
* order to perform said action.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* TRUE if there is an active Sequence, FALSE if not.
|
||||
*/
|
||||
bool CheckForActiveSequence(bool show_msg = true);
|
||||
|
||||
/**
|
||||
* @brief Create a LoadDialog and start a LoadThread to load data from a project
|
||||
@@ -366,7 +383,15 @@ private:
|
||||
* TRUE if the current project should be closed before opening, FALSE if the project should be imported into the
|
||||
* currently open one.
|
||||
*/
|
||||
void LoadProject(const QString& fn, bool autorecovery, bool clear);
|
||||
void LoadProject(const QString& fn, bool autorecovery);
|
||||
|
||||
/**
|
||||
* @brief Indiscriminately clear the project without prompting the user
|
||||
*
|
||||
* Will clear the entire project without prompting to save. This is dangerous, use new_project() instead for
|
||||
* anything initiated by the user.
|
||||
*/
|
||||
void ClearProject();
|
||||
|
||||
/**
|
||||
* @brief File filter used for any file dialogs relating to Olive project files.
|
||||
|
||||
+21
-2
@@ -74,9 +74,28 @@ double cubic_t_from_x(double x_target, double a, double b, double c, double d) {
|
||||
}
|
||||
|
||||
double amplitude_to_db(double amplitude) {
|
||||
return (20.0*(qLn(amplitude)/qLn(10.0)));
|
||||
return (20.0*(qLn(amplitude)/qLn(10.0)));
|
||||
}
|
||||
|
||||
double db_to_amplitude(double db) {
|
||||
return qPow(M_E, (db*qLn(10.0))/20.0);
|
||||
return qPow(M_E, (db*qLn(10.0))/20.0);
|
||||
}
|
||||
|
||||
QRect fit_size_into_rect(const QRect &r, int width, int height)
|
||||
{
|
||||
// Get aspect ratio of object we're fitting
|
||||
double inner_ar = double(width) / double(height);
|
||||
|
||||
// Get aspect ratio of rectangle
|
||||
double rect_ar = double(r.width()) / double(r.height());
|
||||
|
||||
if (rect_ar > inner_ar) {
|
||||
// The rect is wider than the object, so we'll be limiting by height and scaling by width
|
||||
int new_width = qRound(r.height() * inner_ar);
|
||||
return QRect(r.x() + (r.width() / 2 - new_width / 2), r.y(), new_width, r.height());
|
||||
} else {
|
||||
// The rect is taller than the object, so we'll be limiting by width and scaling by height
|
||||
int new_height = qRound(r.width() / inner_ar);
|
||||
return QRect(r.x(), r.y() + (r.height() / 2 - new_height / 2), r.width(), new_height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#ifndef MATH_H
|
||||
#define MATH_H
|
||||
|
||||
#include <QRect>
|
||||
|
||||
int lerp(int a, int b, double t);
|
||||
float float_lerp(float a, float b, float t);
|
||||
double double_lerp(double a, double b, double t);
|
||||
@@ -30,6 +32,8 @@ double cubic_from_t(double a, double b, double c, double d, double t);
|
||||
double cubic_t_from_x(double x_target, double a, double b, double c, double d);
|
||||
double solveCubicBezier(double p0, double p1, double p2, double p3, double x);
|
||||
|
||||
QRect fit_size_into_rect(const QRect& r, int width, int height);
|
||||
|
||||
// decibel conversion functions
|
||||
double amplitude_to_db(double amplitude);
|
||||
double db_to_amplitude(double db);
|
||||
|
||||
Reference in New Issue
Block a user