merged master and fixed superimpose effect
This commit is contained in:
@@ -33,7 +33,7 @@ extern "C" {
|
||||
}
|
||||
|
||||
AdvancedVideoDialog::AdvancedVideoDialog(QWidget *parent,
|
||||
int encoding_codec,
|
||||
AVCodecID encoding_codec,
|
||||
VideoCodecParams &iparams) :
|
||||
QDialog(parent),
|
||||
params_(iparams)
|
||||
|
||||
@@ -36,11 +36,29 @@
|
||||
class AdvancedVideoDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief AdvancedVideoDialog Constructor
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* QWidget parent. Usually ExportDialog.
|
||||
*
|
||||
* @param encoding_codec
|
||||
*
|
||||
* The AVCodecID of the selected export codec.
|
||||
*
|
||||
* @param iparams
|
||||
*
|
||||
* A VideoCodecParams struct containing the extra codec data.
|
||||
*/
|
||||
AdvancedVideoDialog(QWidget* parent,
|
||||
int encoding_codec,
|
||||
AVCodecID encoding_codec,
|
||||
VideoCodecParams& iparams);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief Overrided accept for saving the UI data into the provided VideoCodecParams struct.
|
||||
*/
|
||||
virtual void accept() override;
|
||||
private:
|
||||
/**
|
||||
|
||||
+11
-11
@@ -330,16 +330,16 @@ void ExportDialog::format_changed(int index) {
|
||||
audioGroupbox->setEnabled(audio_enabled);
|
||||
}
|
||||
|
||||
void ExportDialog::render_thread_finished() {
|
||||
void ExportDialog::export_thread_finished() {
|
||||
// Determine if the export succeeded
|
||||
bool succeeded = (progressBar->value() == 100);
|
||||
|
||||
// If it failed and we didn't cancel it, it must have errored out. Show an error message.
|
||||
if (!succeeded && !et->WasInterrupted()) {
|
||||
if (!succeeded && !export_thread_->WasInterrupted()) {
|
||||
QMessageBox::critical(
|
||||
this,
|
||||
tr("Export Failed"),
|
||||
tr("Export failed - %1").arg(et->GetError()),
|
||||
tr("Export failed - %1").arg(export_thread_->GetError()),
|
||||
QMessageBox::Ok
|
||||
);
|
||||
}
|
||||
@@ -358,10 +358,10 @@ void ExportDialog::render_thread_finished() {
|
||||
update_ui(false);
|
||||
|
||||
// Disconnect cancel button from export thread
|
||||
disconnect(renderCancel, SIGNAL(clicked(bool)), et, SLOT(Interrupt()));
|
||||
disconnect(renderCancel, SIGNAL(clicked(bool)), export_thread_, SLOT(Interrupt()));
|
||||
|
||||
// Free the export thread
|
||||
et->deleteLater();
|
||||
export_thread_->deleteLater();
|
||||
|
||||
// If the export succeeded, close the dialog
|
||||
if (succeeded) {
|
||||
@@ -562,12 +562,12 @@ void ExportDialog::StartExport() {
|
||||
}
|
||||
|
||||
// Create export thread
|
||||
et = new ExportThread(params, vcodec_params, this);
|
||||
export_thread_ = new ExportThread(params, vcodec_params, this);
|
||||
|
||||
// Connect export thread signals/slots
|
||||
connect(et, SIGNAL(finished()), this, SLOT(render_thread_finished()));
|
||||
connect(et, SIGNAL(ProgressChanged(int, qint64)), this, SLOT(update_progress_bar(int, qint64)));
|
||||
connect(renderCancel, SIGNAL(clicked(bool)), et, SLOT(Interrupt()));
|
||||
connect(export_thread_, SIGNAL(finished()), this, SLOT(export_thread_finished()));
|
||||
connect(export_thread_, SIGNAL(ProgressChanged(int, qint64)), this, SLOT(update_progress_bar(int, qint64)));
|
||||
connect(renderCancel, SIGNAL(clicked(bool)), export_thread_, SLOT(Interrupt()));
|
||||
|
||||
// Close all currently open clips
|
||||
close_active_clips(olive::ActiveSequence.get());
|
||||
@@ -580,7 +580,7 @@ void ExportDialog::StartExport() {
|
||||
|
||||
total_export_time_start = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
et->start();
|
||||
export_thread_->start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -667,7 +667,7 @@ void ExportDialog::comp_type_changed(int) {
|
||||
}
|
||||
|
||||
void ExportDialog::open_advanced_video_dialog() {
|
||||
AdvancedVideoDialog avd(this, vcodecCombobox->currentData().toInt(), vcodec_params);
|
||||
AdvancedVideoDialog avd(this, static_cast<AVCodecID>(vcodecCombobox->currentData().toInt()), vcodec_params);
|
||||
avd.exec();
|
||||
}
|
||||
|
||||
|
||||
+167
-4
@@ -68,42 +68,205 @@ private slots:
|
||||
* Asks the user for the file to save to.
|
||||
*/
|
||||
void StartExport();
|
||||
|
||||
/**
|
||||
* @brief Slot for the export thread to update the progress bar's value
|
||||
*
|
||||
* @param value
|
||||
*
|
||||
* An value between 0 - 100. A percentage of the Sequence that has been exported so far.
|
||||
*
|
||||
* @param remaining_ms
|
||||
*
|
||||
* The estimated time in milliseconds that it will take to complete the rest of the Sequence.
|
||||
*/
|
||||
void update_progress_bar(int value, qint64 remaining_ms);
|
||||
void render_thread_finished();
|
||||
|
||||
/**
|
||||
* @brief Slot for the export thread completing (both succeeding and failing)
|
||||
*
|
||||
* Runs whenever the thread has finished. Determines whether the thread succeeded or not (and shows an error message
|
||||
* if not), cleans up the ExportThread object, sets the UI state back to normal.
|
||||
*
|
||||
* Connect to ExportThread::finished().
|
||||
*/
|
||||
void export_thread_finished();
|
||||
|
||||
/**
|
||||
* @brief Slot for when the video codec changes
|
||||
*
|
||||
* Some video codecs require different settings. In the case of that, this function sorts through those.
|
||||
*
|
||||
* @param index
|
||||
*
|
||||
* Current vcodecCombobox index - its item data contains the AVCodecID.
|
||||
*/
|
||||
void vcodec_changed(int index);
|
||||
|
||||
/**
|
||||
* @brief Slot for when the compression type changes
|
||||
*
|
||||
* Different UI objects should be displayed for different compression types.
|
||||
*
|
||||
* @param index
|
||||
*
|
||||
* Unused.
|
||||
*/
|
||||
void comp_type_changed(int index);
|
||||
|
||||
/**
|
||||
* @brief Slot to open the Advanced Video Dialog
|
||||
*
|
||||
* Opens a dialog for setting more advanced video settings and passes a reference to vcodec_params to it.
|
||||
*/
|
||||
void open_advanced_video_dialog();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Function to create UI objects.
|
||||
*/
|
||||
void setup_ui();
|
||||
|
||||
/**
|
||||
* @brief Enables/disables certain UI objects based on the exporting state.
|
||||
*
|
||||
* Some UI controls don't need to be set while exporting. This function enables/disables them appropriately.
|
||||
*
|
||||
* @param r
|
||||
*
|
||||
* TRUE if we're exporting, FALSE if we finished.
|
||||
*/
|
||||
void prep_ui_for_render(bool r);
|
||||
|
||||
QVector<QString> format_strings;
|
||||
ExportThread* et;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the human-readable name of an AVCodecID and adds it to a QComboBox
|
||||
*
|
||||
* Also sets that item's data to the AVCodecID so it can be retrieved directly from the QComboBox.
|
||||
*
|
||||
* @param box
|
||||
*
|
||||
* The QComboBox to add the item to.
|
||||
*
|
||||
* @param codec
|
||||
*
|
||||
* The codec to add to the QComboBox.
|
||||
*/
|
||||
void add_codec_to_combobox(QComboBox* box, enum AVCodecID codec);
|
||||
|
||||
/**
|
||||
* @brief Internal array of human-readable names corresponding to enum ExportFormats
|
||||
*/
|
||||
QVector<QString> format_strings;
|
||||
|
||||
/**
|
||||
* @brief Pointer to an ExportThread
|
||||
*
|
||||
* Set when exporting starts, and deleted by export_thread_finished() when the thread is complete.
|
||||
*/
|
||||
ExportThread* export_thread_;
|
||||
|
||||
/**
|
||||
* @brief Struct for advanced video codec parameters.
|
||||
*
|
||||
* More advanced video encoding parameters to be sent to the ExportThread. These variables are not directly editable
|
||||
* in this dialog, instead calling open_advanced_video_dialog() will open an AdvancedVideoDialog for setting these
|
||||
* values directly. vcodec_changed() should also set these to the defaults for that codec where appropriate.
|
||||
*/
|
||||
VideoCodecParams vcodec_params;
|
||||
|
||||
/**
|
||||
* @brief ComboBox for selecting the time range of the Sequence to export
|
||||
*/
|
||||
QComboBox* rangeCombobox;
|
||||
|
||||
/**
|
||||
* @brief SpinBox for the exported video's width
|
||||
*/
|
||||
QSpinBox* widthSpinbox;
|
||||
|
||||
/**
|
||||
* @brief SpinBox for the exported video's bitrate
|
||||
*/
|
||||
QDoubleSpinBox* videobitrateSpinbox;
|
||||
|
||||
/**
|
||||
* @brief Label for the exported video's bitrate - changes depending on the compression type
|
||||
*/
|
||||
QLabel* videoBitrateLabel;
|
||||
|
||||
/**
|
||||
* @brief SpinBox for the exported video's frame rate
|
||||
*/
|
||||
QDoubleSpinBox* framerateSpinbox;
|
||||
|
||||
/**
|
||||
* @brief ComboBox for the exported video codec
|
||||
*/
|
||||
QComboBox* vcodecCombobox;
|
||||
|
||||
/**
|
||||
* @brief ComboBox for the exported audio's codec
|
||||
*/
|
||||
QComboBox* acodecCombobox;
|
||||
|
||||
/**
|
||||
* @brief SpinBox for the exported audio's sample rate
|
||||
*/
|
||||
QSpinBox* samplingRateSpinbox;
|
||||
|
||||
/**
|
||||
* @brief SpinBox for the exported audio's bitrate
|
||||
*/
|
||||
QSpinBox* audiobitrateSpinbox;
|
||||
|
||||
/**
|
||||
* @brief Progress bar for visually showing the export progress
|
||||
*/
|
||||
QProgressBar* progressBar;
|
||||
|
||||
/**
|
||||
* @brief ComboBox for the exported video's format
|
||||
*/
|
||||
QComboBox* formatCombobox;
|
||||
|
||||
/**
|
||||
* @brief SpinBox for the exported video's height
|
||||
*/
|
||||
QSpinBox* heightSpinbox;
|
||||
|
||||
/**
|
||||
* @brief Export button to trigger the start of an export
|
||||
*/
|
||||
QPushButton* export_button;
|
||||
|
||||
/**
|
||||
* @brief Dialog cancel button to close this dialog
|
||||
*/
|
||||
QPushButton* cancel_button;
|
||||
|
||||
/**
|
||||
* @brief Cancel button to abort the export before completion
|
||||
*/
|
||||
QPushButton* renderCancel;
|
||||
|
||||
/**
|
||||
* @brief GroupBox containing all video-related UI objects
|
||||
*/
|
||||
QGroupBox* videoGroupbox;
|
||||
|
||||
/**
|
||||
* @brief GroupBox containing all audio-related UI objects
|
||||
*/
|
||||
QGroupBox* audioGroupbox;
|
||||
|
||||
/**
|
||||
* @brief ComboBox for the exported video compression type
|
||||
*/
|
||||
QComboBox* compressionTypeCombobox;
|
||||
|
||||
/**
|
||||
* @brief Time value set when exporting begins to determine the total duration of the export
|
||||
*/
|
||||
qint64 total_export_time_start;
|
||||
};
|
||||
|
||||
|
||||
+8
-25
@@ -31,7 +31,7 @@
|
||||
#include "ui/sourcetable.h"
|
||||
#include "ui/mainwindow.h"
|
||||
|
||||
LoadDialog::LoadDialog(QWidget *parent, const QString& fn, bool autorecovery, bool clear) :
|
||||
LoadDialog::LoadDialog(QWidget *parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("Loading..."));
|
||||
@@ -45,36 +45,19 @@ LoadDialog::LoadDialog(QWidget *parent, const QString& fn, bool autorecovery, bo
|
||||
bar->setValue(0);
|
||||
layout->addWidget(bar);
|
||||
|
||||
cancel_button = new QPushButton(tr("Cancel"), this);
|
||||
connect(cancel_button, SIGNAL(clicked(bool)), this, SLOT(cancel()));
|
||||
QPushButton* cancel_button = new QPushButton(tr("Cancel"), this);
|
||||
connect(cancel_button, SIGNAL(clicked(bool)), this, SIGNAL(cancel()));
|
||||
|
||||
hboxLayout = new QHBoxLayout();
|
||||
// Wrap cancel button in a horizontal layout so it can be centered
|
||||
QHBoxLayout* hboxLayout = new QHBoxLayout();
|
||||
hboxLayout->addStretch();
|
||||
hboxLayout->addWidget(cancel_button);
|
||||
hboxLayout->addStretch();
|
||||
|
||||
layout->addLayout(hboxLayout);
|
||||
|
||||
update();
|
||||
|
||||
lt = new LoadThread(fn, autorecovery, clear);
|
||||
QObject::connect(lt, SIGNAL(success()), this, SLOT(thread_done()));
|
||||
QObject::connect(lt, SIGNAL(error()), this, SLOT(die()));
|
||||
QObject::connect(lt, SIGNAL(report_progress(int)), bar, SLOT(setValue(int)));
|
||||
lt->start();
|
||||
}
|
||||
|
||||
void LoadDialog::cancel() {
|
||||
lt->cancel();
|
||||
lt->wait();
|
||||
die();
|
||||
}
|
||||
|
||||
void LoadDialog::die() {
|
||||
olive::Global->new_project();
|
||||
reject();
|
||||
}
|
||||
|
||||
void LoadDialog::thread_done() {
|
||||
accept();
|
||||
void LoadDialog::setValue(int i)
|
||||
{
|
||||
bar->setValue(i);
|
||||
}
|
||||
|
||||
+34
-7
@@ -28,20 +28,47 @@
|
||||
#include "project/projectelements.h"
|
||||
#include "project/loadthread.h"
|
||||
|
||||
/**
|
||||
* @brief The LoadDialog class
|
||||
*
|
||||
* Shows a modal dialog for loading a project. Designed to be connected to a LoadThread object.
|
||||
*/
|
||||
class LoadDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LoadDialog(QWidget* parent, const QString& filename, bool autorecovery, bool clear);
|
||||
private slots:
|
||||
/**
|
||||
* @brief LoadDialog Constructor
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* QWidget parent. Usually MainWindow.
|
||||
*/
|
||||
LoadDialog(QWidget* parent);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief Set the progress bar value
|
||||
*
|
||||
* Ideally, connect this to LoadThread::report_progress().
|
||||
*
|
||||
* @param i
|
||||
*
|
||||
* Should be a value between 0-100.
|
||||
*/
|
||||
void setValue(int i);
|
||||
signals:
|
||||
/**
|
||||
* @brief Signal emitted when the cancel button is clicked.
|
||||
*
|
||||
* Ideally, connect this to LoadThread::cancel();
|
||||
*/
|
||||
void cancel();
|
||||
void die();
|
||||
void thread_done();
|
||||
private:
|
||||
/**
|
||||
* @brief Progress bar widget
|
||||
*/
|
||||
QProgressBar* bar;
|
||||
QPushButton* cancel_button;
|
||||
QHBoxLayout* hboxLayout;
|
||||
LoadThread* lt;
|
||||
};
|
||||
|
||||
#endif // LOADDIALOG_H
|
||||
|
||||
@@ -31,19 +31,62 @@
|
||||
#include "project/footage.h"
|
||||
#include "project/media.h"
|
||||
|
||||
/**
|
||||
* @brief The MediaPropertiesDialog class
|
||||
*
|
||||
* A dialog for setting properties on Media.
|
||||
*/
|
||||
class MediaPropertiesDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief MediaPropertiesDialog Constructor
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* QWidget parent. Usually MainWindow or Project panel.
|
||||
*
|
||||
* @param i
|
||||
*
|
||||
* Media object to set properties for.
|
||||
*/
|
||||
MediaPropertiesDialog(QWidget *parent, Media* i);
|
||||
private:
|
||||
/**
|
||||
* @brief ComboBox for interlacing setting
|
||||
*/
|
||||
QComboBox* interlacing_box;
|
||||
|
||||
/**
|
||||
* @brief Media name text field
|
||||
*/
|
||||
QLineEdit* name_box;
|
||||
|
||||
/**
|
||||
* @brief Internal pointer to Media object (set in constructor)
|
||||
*/
|
||||
Media* item;
|
||||
|
||||
/**
|
||||
* @brief A list widget for listing the tracks in Media
|
||||
*/
|
||||
QListWidget* track_list;
|
||||
|
||||
/**
|
||||
* @brief Frame rate to conform to
|
||||
*/
|
||||
QDoubleSpinBox* conform_fr;
|
||||
|
||||
/**
|
||||
* @brief Setting for associated/premultiplied alpha
|
||||
*/
|
||||
QCheckBox* premultiply_alpha_setting;
|
||||
|
||||
QComboBox* color_management;
|
||||
private slots:
|
||||
/**
|
||||
* @brief Overrided accept function for saving the properties back to the Media class
|
||||
*/
|
||||
void accept();
|
||||
};
|
||||
|
||||
|
||||
@@ -76,15 +76,15 @@ NewSequenceDialog::NewSequenceDialog(QWidget *parent, Media *existing) :
|
||||
}
|
||||
}
|
||||
|
||||
NewSequenceDialog::~NewSequenceDialog()
|
||||
{}
|
||||
|
||||
void NewSequenceDialog::set_sequence_name(const QString& s) {
|
||||
sequence_name_edit->setText(s);
|
||||
}
|
||||
|
||||
void NewSequenceDialog::create() {
|
||||
void NewSequenceDialog::accept() {
|
||||
if (existing_sequence == nullptr) {
|
||||
|
||||
// The dialog wasn't given an existing Sequence object, so we'll make a new one
|
||||
|
||||
SequencePtr s = std::make_shared<Sequence>();
|
||||
|
||||
s->name = sequence_name_edit->text();
|
||||
@@ -97,7 +97,11 @@ void NewSequenceDialog::create() {
|
||||
ComboAction* ca = new ComboAction();
|
||||
panel_project->create_sequence_internal(ca, s, true, nullptr);
|
||||
olive::UndoStack.push(ca);
|
||||
|
||||
} else {
|
||||
|
||||
// The dialog was given an existing Sequence object, so we'll apply the changes to it
|
||||
|
||||
ComboAction* ca = new ComboAction();
|
||||
|
||||
double multiplier = frame_rate_combobox->currentData().toDouble() / existing_sequence->frame_rate;
|
||||
@@ -121,7 +125,7 @@ void NewSequenceDialog::create() {
|
||||
olive::UndoStack.push(ca);
|
||||
}
|
||||
|
||||
accept();
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void NewSequenceDialog::preset_changed(int index) {
|
||||
@@ -280,6 +284,6 @@ void NewSequenceDialog::setup_ui() {
|
||||
verticalLayout->addWidget(buttonBox);
|
||||
|
||||
connect(preset_combobox, SIGNAL(currentIndexChanged(int)), this, SLOT(preset_changed(int)));
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(create()));
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
}
|
||||
|
||||
@@ -30,33 +30,115 @@
|
||||
#include "project/media.h"
|
||||
#include "timeline/sequence.h"
|
||||
|
||||
/**
|
||||
* @brief The NewSequenceDialog class
|
||||
*
|
||||
* A dialog that creates a new (or edits an existing) Sequence object.
|
||||
*/
|
||||
class NewSequenceDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief NewSequenceDialog constructor
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* QWidget parent. Usually MainWindow.
|
||||
*
|
||||
* @param existing
|
||||
*
|
||||
* Set this to a Sequence object (wrapped in a Media object) to edit an existing Sequence,
|
||||
* or leave as nullptr to create a new one.
|
||||
*/
|
||||
explicit NewSequenceDialog(QWidget *parent = nullptr, Media* existing = nullptr);
|
||||
~NewSequenceDialog();
|
||||
|
||||
/**
|
||||
* @brief Set the name for the new Sequence
|
||||
*
|
||||
* If creating a new Sequence, use this function before calling exec() to set what the new Sequence's
|
||||
* name will be.
|
||||
*
|
||||
* The primary use of this is to set a unique default name (i.e. one that doesn't exist
|
||||
* in the Sequence already) which is done by Project panel. This is usually "Sequence" followed by a number.
|
||||
*
|
||||
* @param s
|
||||
*
|
||||
* The name to set the new Sequence.
|
||||
*/
|
||||
void set_sequence_name(const QString& s);
|
||||
|
||||
private slots:
|
||||
void create();
|
||||
/**
|
||||
* @brief Override accept function to create/edit a Sequence
|
||||
*/
|
||||
virtual void accept() override;
|
||||
|
||||
/**
|
||||
* @brief Slot when the user changes the preset
|
||||
*
|
||||
* Sets all values according to the preset chosen.
|
||||
*
|
||||
* @param index
|
||||
*
|
||||
* Currently selected index of preset_combobox;
|
||||
*/
|
||||
void preset_changed(int index);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Internal reference to an existing Sequence (if one was provided to the constructor)
|
||||
*/
|
||||
SequencePtr existing_sequence;
|
||||
|
||||
/**
|
||||
* @brief Internal reference to an existing Media wrapper (if one was provided to the constructor)
|
||||
*/
|
||||
Media* existing_item;
|
||||
|
||||
/**
|
||||
* @brief Internal function to create the dialog's UI
|
||||
*/
|
||||
void setup_ui();
|
||||
|
||||
/**
|
||||
* @brief ComboBox to set the preset
|
||||
*/
|
||||
QComboBox* preset_combobox;
|
||||
|
||||
/**
|
||||
* @brief SpinBox to set the Sequence height
|
||||
*/
|
||||
QSpinBox* height_numeric;
|
||||
|
||||
/**
|
||||
* @brief SpinBox to set the Sequence width
|
||||
*/
|
||||
QSpinBox* width_numeric;
|
||||
|
||||
/**
|
||||
* @brief ComboBox to set the pixel aspect ratio
|
||||
*/
|
||||
QComboBox* par_combobox;
|
||||
|
||||
/**
|
||||
* @brief ComboBox to set the interlacing mode
|
||||
*/
|
||||
QComboBox* interlacing_combobox;
|
||||
|
||||
/**
|
||||
* @brief ComboBox to set the frame rate
|
||||
*/
|
||||
QComboBox* frame_rate_combobox;
|
||||
|
||||
/**
|
||||
* @brief ComboBox to set the audio frequence
|
||||
*/
|
||||
QComboBox* audio_frequency_combobox;
|
||||
|
||||
/**
|
||||
* @brief Line edit to set the Sequence's name
|
||||
*/
|
||||
QLineEdit* sequence_name_edit;
|
||||
};
|
||||
|
||||
|
||||
@@ -83,9 +83,12 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) :
|
||||
{
|
||||
setWindowTitle(tr("Preferences"));
|
||||
setup_ui();
|
||||
}
|
||||
|
||||
PreferencesDialog::~PreferencesDialog() {}
|
||||
recordingComboBox->setCurrentIndex(olive::CurrentConfig.recording_mode - 1);
|
||||
imgSeqFormatEdit->setText(olive::CurrentConfig.img_seq_formats);
|
||||
|
||||
setup_kbd_shortcuts(olive::MainWindow->menuBar());
|
||||
}
|
||||
|
||||
void PreferencesDialog::setup_kbd_shortcut_worker(QMenu* menu, QTreeWidgetItem* parent) {
|
||||
QList<QAction*> actions = menu->actions();
|
||||
@@ -255,7 +258,7 @@ void PreferencesDialog::setup_kbd_shortcuts(QMenuBar* menubar) {
|
||||
}
|
||||
}
|
||||
|
||||
void PreferencesDialog::save() {
|
||||
void PreferencesDialog::accept() {
|
||||
bool restart_after_saving = false;
|
||||
bool reinit_audio = false;
|
||||
bool reload_language = false;
|
||||
@@ -448,7 +451,7 @@ void PreferencesDialog::save() {
|
||||
olive::Global->load_translation_from_config();
|
||||
}
|
||||
|
||||
accept();
|
||||
QDialog::accept();
|
||||
|
||||
if (restart_after_saving) {
|
||||
// since we already ran can_close_project(), bypass checking again by running set_modified(false)
|
||||
@@ -1025,6 +1028,6 @@ void PreferencesDialog::setup_ui() {
|
||||
|
||||
verticalLayout->addWidget(buttonBox);
|
||||
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(save()));
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
}
|
||||
|
||||
+106
-16
@@ -40,38 +40,86 @@ namespace OCIO = OCIO_NAMESPACE::v1;
|
||||
|
||||
#include "timeline/sequence.h"
|
||||
|
||||
class KeySequenceEditor : public QKeySequenceEdit {
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeySequenceEditor(QWidget *parent, QAction* a);
|
||||
void set_action_shortcut();
|
||||
void reset_to_default();
|
||||
QString action_name();
|
||||
QString export_shortcut();
|
||||
private:
|
||||
QAction* action;
|
||||
};
|
||||
class KeySequenceEditor;
|
||||
|
||||
/**
|
||||
* @brief The PreferencesDialog class
|
||||
*
|
||||
* A dialog for the global application settings. Mostly an interface for Config.
|
||||
*/
|
||||
class PreferencesDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief PreferencesDialog Constructor
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* QWidget parent. Usually MainWindow.
|
||||
*/
|
||||
explicit PreferencesDialog(QWidget *parent = nullptr);
|
||||
~PreferencesDialog();
|
||||
|
||||
void setup_kbd_shortcuts(QMenuBar* menu);
|
||||
|
||||
private slots:
|
||||
void save();
|
||||
/**
|
||||
* @brief Override of accept to save preferences to Config.
|
||||
*/
|
||||
virtual void accept() override;
|
||||
|
||||
/**
|
||||
* @brief Reset all selected shortcuts in keyboard_tree to their defaults
|
||||
*/
|
||||
void reset_default_shortcut();
|
||||
|
||||
/**
|
||||
* @brief Reset all shortcuts indiscriminately to their defaults
|
||||
*
|
||||
* This is safe to call directly as it'll ask the user if they wish to do so before it resets.
|
||||
*/
|
||||
void reset_all_shortcuts();
|
||||
bool refine_shortcut_list(const QString &, QTreeWidgetItem* parent = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Shows/hides shortcut entries according to a shortcut query.
|
||||
*
|
||||
* This function can be directly connected to QLineEdit::textChanged() for simplicity.
|
||||
*
|
||||
* @param s
|
||||
*
|
||||
* The search query to compare shortcut names to.
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* This is used as the function calls itself recursively to traverse the menu item hierarchy. This should be left as
|
||||
* nullptr when called externally.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* Value used as function calls itself recursively to determine if a menu parent has any children that are not hidden.
|
||||
* If so, TRUE is returned so the parent is shown too (even if it doesn't match the search query). If not, FALSE is
|
||||
* returned so the parent is hidden.
|
||||
*/
|
||||
bool refine_shortcut_list(const QString &s, QTreeWidgetItem* parent = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Show a file dialog to load an external shortcut preset from file
|
||||
*/
|
||||
void load_shortcut_file();
|
||||
|
||||
/**
|
||||
* @brief Show a file dialog to save an external shortcut preset from file
|
||||
*/
|
||||
void save_shortcut_file();
|
||||
|
||||
/**
|
||||
* @brief Delete all previews (waveform and thumbnail cache)
|
||||
*/
|
||||
void delete_all_previews();
|
||||
|
||||
// Browse for file functionns
|
||||
/**
|
||||
* @brief Show a file dialog to browse for an external CSS file to load for styling the application.
|
||||
*/
|
||||
void browse_css_file();
|
||||
void browse_ocio_config();
|
||||
|
||||
@@ -83,7 +131,37 @@ private slots:
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Create and arrange all UI widgets
|
||||
*/
|
||||
void setup_ui();
|
||||
|
||||
/**
|
||||
* @brief Populate keyboard shortcut panel with keyboard shortcuts from the menu bar
|
||||
*
|
||||
* @param menu
|
||||
*
|
||||
* A reference to the main application's menu bar. Usually MainWindow::menuBar().
|
||||
*/
|
||||
void setup_kbd_shortcuts(QMenuBar* menu);
|
||||
|
||||
/**
|
||||
* @brief Internal function called by setup_kbd_shortcuts() to traverse down the menu bar's hierarchy and populate the
|
||||
* shortcut panel.
|
||||
*
|
||||
* This function will call itself recursively as it finds submenus belong to the menu provided. It will also create
|
||||
* QTreeWidgetItems as children of the parent item provided, either using them as parents themselves for submenus
|
||||
* or attaching a KeySequenceEditor to them for shortcut editing.
|
||||
*
|
||||
* @param menu
|
||||
*
|
||||
* The current menu to traverse down.
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* The parent item to add QTreeWidgetItems to.
|
||||
*/
|
||||
void setup_kbd_shortcut_worker(QMenu* menu, QTreeWidgetItem* parent);
|
||||
|
||||
enum PreviewDeleteTypes {
|
||||
@@ -143,4 +221,16 @@ private:
|
||||
QVector<KeySequenceEditor*> key_shortcut_fields;
|
||||
};
|
||||
|
||||
class KeySequenceEditor : public QKeySequenceEdit {
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeySequenceEditor(QWidget *parent, QAction* a);
|
||||
void set_action_shortcut();
|
||||
void reset_to_default();
|
||||
QString action_name();
|
||||
QString export_shortcut();
|
||||
private:
|
||||
QAction* action;
|
||||
};
|
||||
|
||||
#endif // PREFERENCESDIALOG_H
|
||||
|
||||
+27
-1
@@ -122,7 +122,8 @@ Effect::Effect(Clip* c, const EffectMeta *em) :
|
||||
isOpen(false),
|
||||
bound(false),
|
||||
iterations(1),
|
||||
enabled_(true)
|
||||
enabled_(true),
|
||||
expanded_(true)
|
||||
{
|
||||
if (em != nullptr) {
|
||||
// set up UI from effect file
|
||||
@@ -507,6 +508,16 @@ bool Effect::IsEnabled() {
|
||||
return enabled_;
|
||||
}
|
||||
|
||||
bool Effect::IsExpanded()
|
||||
{
|
||||
return expanded_;
|
||||
}
|
||||
|
||||
void Effect::SetExpanded(bool e)
|
||||
{
|
||||
expanded_ = e;
|
||||
}
|
||||
|
||||
void Effect::SetEnabled(bool b) {
|
||||
enabled_ = b;
|
||||
emit EnabledChanged(b);
|
||||
@@ -895,15 +906,30 @@ GLuint Effect::process_superimpose(double timecode) {
|
||||
tex_width_ = img.width();
|
||||
tex_height_ = img.height();
|
||||
|
||||
// create texture object
|
||||
f->glGenTextures(1, &texture);
|
||||
|
||||
f->glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
// set texture filtering to bilinear
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
f->glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_RGBA8, tex_width_, tex_height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.constBits()
|
||||
);
|
||||
|
||||
f->glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
redrew_image = false;
|
||||
}
|
||||
|
||||
if (redrew_image) {
|
||||
f->glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
f->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tex_width_, tex_height_, GL_RGBA, GL_UNSIGNED_BYTE, img.constBits());
|
||||
|
||||
f->glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
return texture;
|
||||
|
||||
@@ -153,6 +153,7 @@ public:
|
||||
int gizmo_count();
|
||||
|
||||
bool IsEnabled();
|
||||
bool IsExpanded();
|
||||
|
||||
virtual void refresh();
|
||||
|
||||
@@ -212,6 +213,7 @@ public:
|
||||
public slots:
|
||||
void FieldChanged();
|
||||
void SetEnabled(bool b);
|
||||
void SetExpanded(bool e);
|
||||
signals:
|
||||
void EnabledChanged(bool);
|
||||
private slots:
|
||||
@@ -243,6 +245,7 @@ private:
|
||||
int iterations;
|
||||
|
||||
bool enabled_;
|
||||
bool expanded_;
|
||||
|
||||
int flags_;
|
||||
|
||||
|
||||
+44
-9
@@ -38,6 +38,8 @@
|
||||
#include "dialogs/aboutdialog.h"
|
||||
#include "dialogs/speeddialog.h"
|
||||
#include "dialogs/actionsearch.h"
|
||||
#include "dialogs/loaddialog.h"
|
||||
#include "project/loadthread.h"
|
||||
#include "timeline/sequence.h"
|
||||
#include "ui/mediaiconservice.h"
|
||||
#include "ui/mainwindow.h"
|
||||
@@ -91,7 +93,7 @@ void OliveGlobal::check_for_autorecovery_file() {
|
||||
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) {
|
||||
enable_load_project_on_init = false;
|
||||
open_project_worker(autorecovery_filename, true);
|
||||
OpenProjectWorker(autorecovery_filename, true);
|
||||
}
|
||||
}
|
||||
autorecovery_timer.setInterval(60000);
|
||||
@@ -164,6 +166,33 @@ void OliveGlobal::SetNativeStyling(QWidget *w)
|
||||
#endif
|
||||
}
|
||||
|
||||
void OliveGlobal::LoadProject(const QString &fn, bool autorecovery, bool clear)
|
||||
{
|
||||
// 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
|
||||
|
||||
if (clear) {
|
||||
new_project();
|
||||
}
|
||||
|
||||
LoadDialog ld(olive::MainWindow);
|
||||
|
||||
LoadThread* lt = new LoadThread(fn, autorecovery, clear);
|
||||
connect(&ld, SIGNAL(cancel()), lt, SLOT(cancel()));
|
||||
connect(lt, SIGNAL(success()), &ld, SLOT(accept()));
|
||||
connect(lt, SIGNAL(error()), &ld, SLOT(reject()));
|
||||
connect(lt, SIGNAL(error()), this, SLOT(new_project()));
|
||||
connect(lt, SIGNAL(report_progress(int)), &ld, SLOT(setValue(int)));
|
||||
lt->start();
|
||||
|
||||
ld.exec();
|
||||
}
|
||||
|
||||
void OliveGlobal::ImportProject(const QString &fn)
|
||||
{
|
||||
LoadProject(fn, false, false);
|
||||
}
|
||||
|
||||
void OliveGlobal::new_project() {
|
||||
if (can_close_project()) {
|
||||
// clear graph editor
|
||||
@@ -172,8 +201,12 @@ void OliveGlobal::new_project() {
|
||||
// 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->new_project();
|
||||
panel_project->clear();
|
||||
|
||||
// clear undo stack
|
||||
olive::UndoStack.clear();
|
||||
@@ -183,13 +216,16 @@ void OliveGlobal::new_project() {
|
||||
|
||||
// full update of all panels
|
||||
update_ui(false);
|
||||
|
||||
// set to unmodified
|
||||
olive::Global->set_modified(false);
|
||||
}
|
||||
}
|
||||
|
||||
void OliveGlobal::open_project() {
|
||||
void OliveGlobal::OpenProject() {
|
||||
QString fn = QFileDialog::getOpenFileName(olive::MainWindow, tr("Open Project..."), "", project_file_filter);
|
||||
if (!fn.isEmpty() && can_close_project()) {
|
||||
open_project_worker(fn, false);
|
||||
OpenProjectWorker(fn, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +241,7 @@ void OliveGlobal::open_recent(int index) {
|
||||
panel_project->save_recent_projects();
|
||||
}
|
||||
} else if (can_close_project()) {
|
||||
open_project_worker(recent_url, false);
|
||||
OpenProjectWorker(recent_url, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,7 +305,7 @@ void OliveGlobal::finished_initialize() {
|
||||
|
||||
// if a project was set as a command line argument, we load it here
|
||||
if (QFileInfo::exists(olive::ActiveProjectFilename)) {
|
||||
open_project_worker(olive::ActiveProjectFilename, false);
|
||||
OpenProjectWorker(olive::ActiveProjectFilename, false);
|
||||
} else {
|
||||
QMessageBox::critical(olive::MainWindow,
|
||||
tr("Missing Project File"),
|
||||
@@ -308,7 +344,6 @@ void OliveGlobal::open_preferences() {
|
||||
panel_footage_viewer->pause();
|
||||
|
||||
PreferencesDialog pd(olive::MainWindow);
|
||||
pd.setup_kbd_shortcuts(olive::MainWindow->menuBar());
|
||||
pd.exec();
|
||||
}
|
||||
|
||||
@@ -323,9 +358,9 @@ void OliveGlobal::set_sequence(SequencePtr s)
|
||||
panel_timeline->setFocus();
|
||||
}
|
||||
|
||||
void OliveGlobal::open_project_worker(const QString& fn, bool autorecovery) {
|
||||
void OliveGlobal::OpenProjectWorker(const QString& fn, bool autorecovery) {
|
||||
update_project_filename(fn);
|
||||
panel_project->load_project(fn, autorecovery, true);
|
||||
LoadProject(fn, autorecovery, true);
|
||||
olive::UndoStack.clear();
|
||||
}
|
||||
|
||||
|
||||
+41
-2
@@ -193,7 +193,18 @@ public slots:
|
||||
* Confirms whether the current project can be closed, and if so, shows an open file dialog to allow the user to
|
||||
* select a project file and then triggers a project load with it.
|
||||
*/
|
||||
void open_project();
|
||||
void OpenProject();
|
||||
|
||||
/**
|
||||
* @brief Import project from file
|
||||
*
|
||||
* Imports an Olive project into the current project, effectively merging them.
|
||||
*
|
||||
* @param fn
|
||||
*
|
||||
* The filename of the project to import.
|
||||
*/
|
||||
void ImportProject(const QString& fn);
|
||||
|
||||
/**
|
||||
* @brief Open recent project from list
|
||||
@@ -327,7 +338,35 @@ 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 open_project_worker(const QString& fn, bool autorecovery);
|
||||
void OpenProjectWorker(const QString& fn, bool autorecovery);
|
||||
|
||||
/**
|
||||
* @brief Create a LoadDialog and start a LoadThread to load data from a project
|
||||
*
|
||||
* Loads data from an Olive project file creating a LoadDialog to show visual information and a LoadThread to load
|
||||
* outside of the main/GUI thread.
|
||||
*
|
||||
* All project loading functions eventually lead to this one and there's no reason to use it directly. Instead use
|
||||
* one of the following functions:
|
||||
*
|
||||
* * OpenProject() - to check if the current project can be closed and prompt the user for the new project file
|
||||
* * OpenProjectWorker() - if you already have the filename and wish to close the current project and open it
|
||||
* * ImportProject() - to import a project file into this one, effectively merging them both
|
||||
*
|
||||
* @param fn
|
||||
*
|
||||
* The URL of the project file to open
|
||||
*
|
||||
* @param autorecovery
|
||||
*
|
||||
* TRUE if this file is an autorecovery file, in which case it's loaded slightly differently
|
||||
*
|
||||
* @param clear
|
||||
*
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* @brief File filter used for any file dialogs relating to Olive project files.
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "panels/grapheditor.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
#include "ui/menuhelper.h"
|
||||
#include "ui/icons.h"
|
||||
#include "project/clipboard.h"
|
||||
#include "global/config.h"
|
||||
#include "ui/timelineheader.h"
|
||||
@@ -374,8 +375,8 @@ void EffectControls::setup_ui() {
|
||||
veHeaderLayout->setSpacing(0);
|
||||
veHeaderLayout->setMargin(0);
|
||||
|
||||
QIcon add_effect_icon(":/icons/add-effect.svg");
|
||||
QIcon add_transition_icon(":/icons/add-transition.svg");
|
||||
QIcon add_effect_icon = olive::icon::CreateIconFromSVG(":/icons/add-effect.svg", false);
|
||||
QIcon add_transition_icon = olive::icon::CreateIconFromSVG(":/icons/add-transition.svg", false);
|
||||
|
||||
btnAddVideoEffect = new QPushButton();
|
||||
btnAddVideoEffect->setIcon(add_effect_icon);
|
||||
|
||||
+13
-31
@@ -111,7 +111,7 @@ Project::Project(QWidget *parent) :
|
||||
QPushButton* toolbar_open = new QPushButton();
|
||||
toolbar_open->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/open.svg")));
|
||||
toolbar_open->setToolTip("Open Project");
|
||||
connect(toolbar_open, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(open_project()));
|
||||
connect(toolbar_open, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(OpenProject()));
|
||||
toolbar->addWidget(toolbar_open);
|
||||
|
||||
QPushButton* toolbar_save = new QPushButton();
|
||||
@@ -433,27 +433,30 @@ void Project::new_sequence() {
|
||||
}
|
||||
|
||||
MediaPtr Project::create_sequence_internal(ComboAction *ca, SequencePtr s, bool open, Media* parent) {
|
||||
if (parent == nullptr) {
|
||||
parent = olive::project_model.get_root();
|
||||
}
|
||||
|
||||
MediaPtr item = std::make_shared<Media>(parent);
|
||||
MediaPtr item = std::make_shared<Media>();
|
||||
item->set_sequence(s);
|
||||
|
||||
if (ca != nullptr) {
|
||||
|
||||
ca->append(new AddMediaCommand(item, parent));
|
||||
|
||||
if (open) {
|
||||
ca->append(new ChangeSequenceAction(s));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
olive::project_model.appendChild(parent, item);
|
||||
|
||||
if (open) {
|
||||
olive::Global->set_sequence(s);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return item;
|
||||
|
||||
}
|
||||
|
||||
QString Project::get_file_name_from_path(const QString& path) {
|
||||
@@ -700,14 +703,14 @@ void Project::process_file_list(QStringList& files, bool recursive, MediaPtr rep
|
||||
subdir_filenames.append(subdir_files.at(j).filePath());
|
||||
}
|
||||
|
||||
process_file_list(subdir_filenames, true, nullptr, folder.get());
|
||||
|
||||
if (create_undo_action) {
|
||||
ca->append(new AddMediaCommand(folder, parent));
|
||||
} else {
|
||||
olive::project_model.appendChild(parent, folder);
|
||||
}
|
||||
|
||||
process_file_list(subdir_filenames, true, nullptr, folder.get());
|
||||
|
||||
imported = true;
|
||||
|
||||
} else if (!files.at(i).isEmpty()) {
|
||||
@@ -724,7 +727,7 @@ void Project::process_file_list(QStringList& files, bool recursive, MediaPtr rep
|
||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
||||
|
||||
// load the project without clearing the current one
|
||||
load_project(file, false, false);
|
||||
olive::Global->ImportProject(file);
|
||||
|
||||
}
|
||||
|
||||
@@ -868,7 +871,7 @@ void Project::process_file_list(QStringList& files, bool recursive, MediaPtr rep
|
||||
if (replace != nullptr) {
|
||||
item = replace;
|
||||
} else {
|
||||
item = std::make_shared<Media>(parent);
|
||||
item = std::make_shared<Media>();
|
||||
}
|
||||
|
||||
m = std::make_shared<Footage>();
|
||||
@@ -891,7 +894,7 @@ void Project::process_file_list(QStringList& files, bool recursive, MediaPtr rep
|
||||
if (create_undo_action) {
|
||||
ca->append(new AddMediaCommand(item, parent));
|
||||
} else {
|
||||
parent->appendChild(item);
|
||||
olive::project_model.appendChild(parent, item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1046,27 +1049,6 @@ void Project::clear() {
|
||||
tree_view->update();
|
||||
}
|
||||
|
||||
void Project::new_project() {
|
||||
// clear existing project
|
||||
olive::Global->set_sequence(nullptr);
|
||||
panel_footage_viewer->set_media(nullptr);
|
||||
clear();
|
||||
olive::Global->set_modified(false);
|
||||
}
|
||||
|
||||
void Project::load_project(const QString& filename, bool autorecovery, bool clear) {
|
||||
|
||||
// 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
|
||||
|
||||
if (clear) {
|
||||
new_project();
|
||||
}
|
||||
|
||||
LoadDialog ld(this, filename, autorecovery, clear);
|
||||
ld.exec();
|
||||
}
|
||||
|
||||
void save_marker(QXmlStreamWriter& stream, const Marker& m) {
|
||||
stream.writeStartElement("marker");
|
||||
stream.writeAttribute("frame", QString::number(m.frame));
|
||||
|
||||
@@ -66,8 +66,6 @@ public:
|
||||
bool reveal_media(Media *media, QModelIndex parent = QModelIndex());
|
||||
void add_recent_project(QString url);
|
||||
|
||||
void new_project();
|
||||
void load_project(const QString &filename, bool autorecovery, bool clear);
|
||||
void save_project(bool autorecovery);
|
||||
|
||||
MediaPtr create_folder_internal(QString name);
|
||||
|
||||
+18
-6
@@ -605,6 +605,22 @@ Media* LoadThread::find_loaded_folder_by_id(int id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void LoadThread::OrganizeFolders(int folder) {
|
||||
qDebug() << "starting with" << folder;
|
||||
|
||||
for (int i=0;i<loaded_folders.size();i++) {
|
||||
MediaPtr item = loaded_folders.at(i);
|
||||
int parent_id = item->temp_id2;
|
||||
|
||||
if (parent_id == folder) {
|
||||
olive::project_model.appendChild(find_loaded_folder_by_id(parent_id), item);
|
||||
|
||||
OrganizeFolders(parent_id);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void LoadThread::run() {
|
||||
mutex.lock();
|
||||
|
||||
@@ -657,15 +673,11 @@ void LoadThread::run() {
|
||||
cont = load_worker(file, stream, MEDIA_TYPE_FOLDER);
|
||||
}
|
||||
|
||||
// load media
|
||||
if (cont) {
|
||||
// since folders loaded correctly, organize them appropriately
|
||||
for (int i=0;i<loaded_folders.size();i++) {
|
||||
MediaPtr folder = loaded_folders.at(i);
|
||||
int parent = folder->temp_id2;
|
||||
olive::project_model.appendChild(find_loaded_folder_by_id(parent), folder);
|
||||
}
|
||||
OrganizeFolders();
|
||||
|
||||
// load media
|
||||
cont = load_worker(file, stream, MEDIA_TYPE_FOOTAGE);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ class LoadThread : public QThread
|
||||
public:
|
||||
LoadThread(const QString& filename, bool autorecovery, bool clear);
|
||||
void run();
|
||||
public slots:
|
||||
void cancel();
|
||||
signals:
|
||||
void start_question(const QString &title, const QString &text, int buttons);
|
||||
@@ -75,6 +76,7 @@ private:
|
||||
QVector<ClipPtr> loaded_clips;
|
||||
QVector<Media*> loaded_sequences;
|
||||
Media* find_loaded_folder_by_id(int id);
|
||||
void OrganizeFolders(int folder = 0);
|
||||
|
||||
int current_element_count;
|
||||
int total_element_count;
|
||||
|
||||
+5
-5
@@ -61,10 +61,10 @@ QString get_channel_layout_name(int channels, uint64_t layout) {
|
||||
}
|
||||
}
|
||||
|
||||
Media::Media(Media* iparent) {
|
||||
parent = iparent;
|
||||
root = false;
|
||||
type = -1;
|
||||
Media::Media() :
|
||||
root(false),
|
||||
type(-1)
|
||||
{
|
||||
}
|
||||
|
||||
Footage* Media::to_footage() {
|
||||
@@ -341,7 +341,7 @@ QVariant Media::data(int column, int role) {
|
||||
}
|
||||
|
||||
int Media::row() const {
|
||||
if (parent) {
|
||||
if (parent != nullptr) {
|
||||
for (int i=0;i<parent->children.size();i++) {
|
||||
if (parent->children.at(i).get() == this) {
|
||||
return i;
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ using MediaPtr = std::shared_ptr<Media>;
|
||||
class Media
|
||||
{
|
||||
public:
|
||||
Media(Media* iparent = nullptr);
|
||||
Media();
|
||||
|
||||
Footage *to_footage();
|
||||
SequencePtr to_sequence();
|
||||
|
||||
@@ -28,29 +28,29 @@ class ProjectFilter : public QSortFilterProxyModel {
|
||||
public:
|
||||
ProjectFilter(QObject *parent = nullptr);
|
||||
|
||||
// are sequences visible
|
||||
// are sequences visible
|
||||
bool get_show_sequences();
|
||||
|
||||
public slots:
|
||||
|
||||
// set whether sequences are visible
|
||||
// set whether sequences are visible
|
||||
void set_show_sequences(bool b);
|
||||
|
||||
// update search filter
|
||||
void update_search_filter(const QString& s);
|
||||
// update search filter
|
||||
void update_search_filter(const QString& s);
|
||||
|
||||
protected:
|
||||
|
||||
// function that filters whether rows are displayed or not
|
||||
virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
|
||||
// function that filters whether rows are displayed or not
|
||||
virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
|
||||
|
||||
private:
|
||||
|
||||
// internal variable for whether to show sequences
|
||||
// internal variable for whether to show sequences
|
||||
bool show_sequences;
|
||||
|
||||
// search filter variable
|
||||
QString search_filter;
|
||||
// search filter variable
|
||||
QString search_filter;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -43,8 +43,12 @@ void ProjectModel::make_root() {
|
||||
}
|
||||
|
||||
void ProjectModel::destroy_root() {
|
||||
if (panel_sequence_viewer != nullptr) panel_sequence_viewer->viewer_widget->delete_function();
|
||||
if (panel_footage_viewer != nullptr) panel_footage_viewer->viewer_widget->delete_function();
|
||||
if (panel_sequence_viewer != nullptr) {
|
||||
panel_sequence_viewer->viewer_widget->delete_function();
|
||||
}
|
||||
if (panel_footage_viewer != nullptr) {
|
||||
panel_footage_viewer->viewer_widget->delete_function();
|
||||
}
|
||||
|
||||
root_item_ = std::make_shared<Media>();
|
||||
}
|
||||
@@ -64,7 +68,9 @@ QVariant ProjectModel::data(const QModelIndex &index, int role) const {
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
return static_cast<Media*>(index.internalPointer())->data(index.column(), role);
|
||||
Media* media = static_cast<Media*>(index.internalPointer());
|
||||
|
||||
return media->data(index.column(), role);
|
||||
}
|
||||
|
||||
Qt::ItemFlags ProjectModel::flags(const QModelIndex &index) const {
|
||||
@@ -191,11 +197,20 @@ void ProjectModel::set_icon(Media* m, const QIcon &ico) {
|
||||
}
|
||||
|
||||
void ProjectModel::appendChild(Media* parent, MediaPtr child) {
|
||||
QModelIndex row_start;
|
||||
|
||||
if (parent == nullptr) {
|
||||
|
||||
parent = get_root();
|
||||
row_start = QModelIndex();
|
||||
|
||||
} else {
|
||||
|
||||
row_start = createIndex(parent->row(), 0, parent);
|
||||
|
||||
}
|
||||
beginInsertRows(parent == get_root() ?
|
||||
QModelIndex() : createIndex(parent->row(), 0, parent), parent->childCount(), parent->childCount());
|
||||
|
||||
beginInsertRows(row_start, parent->childCount(), parent->childCount());
|
||||
parent->appendChild(child);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
@@ -271,9 +271,6 @@ void SourcesCommon::dropEvent(QWidget* parent,
|
||||
const QModelIndexList& items) {
|
||||
const QMimeData* mimeData = event->mimeData();
|
||||
MediaPtr m = project_parent->item_to_media_ptr(drop_item);
|
||||
if (m == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (mimeData->hasUrls()) {
|
||||
// drag files in from outside
|
||||
QList<QUrl> urls = mimeData->urls();
|
||||
@@ -285,7 +282,7 @@ void SourcesCommon::dropEvent(QWidget* parent,
|
||||
bool replace = false;
|
||||
if (urls.size() == 1
|
||||
&& drop_item.isValid()
|
||||
&& m->get_type() == MEDIA_TYPE_FOOTAGE
|
||||
&& (m != nullptr && m->get_type() == MEDIA_TYPE_FOOTAGE)
|
||||
&& !QFileInfo(paths.at(0)).isDir()
|
||||
&& olive::CurrentConfig.drop_on_media_to_replace
|
||||
&& QMessageBox::question(
|
||||
|
||||
@@ -87,6 +87,13 @@ bool CollapsibleWidget::IsExpanded() {
|
||||
return contents->isVisible();
|
||||
}
|
||||
|
||||
void CollapsibleWidget::SetExpanded(bool s)
|
||||
{
|
||||
contents->setVisible(s);
|
||||
set_button_icon(s);
|
||||
emit visibleChanged(s);
|
||||
}
|
||||
|
||||
bool CollapsibleWidget::IsSelected()
|
||||
{
|
||||
return selected;
|
||||
@@ -116,9 +123,7 @@ void CollapsibleWidget::SetTitle(const QString &s) {
|
||||
}
|
||||
|
||||
void CollapsibleWidget::on_visible_change() {
|
||||
contents->setVisible(!contents->isVisible());
|
||||
set_button_icon(contents->isVisible());
|
||||
emit visibleChanged();
|
||||
SetExpanded(!IsExpanded());
|
||||
}
|
||||
|
||||
CollapsibleWidgetHeader::CollapsibleWidgetHeader(QWidget* parent) : QWidget(parent), selected(false) {
|
||||
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
void SetTitle(const QString &);
|
||||
bool IsFocused();
|
||||
bool IsExpanded();
|
||||
void SetExpanded(bool s);
|
||||
bool IsSelected();
|
||||
protected:
|
||||
QCheckBox* enabled_check;
|
||||
@@ -68,7 +69,7 @@ private:
|
||||
|
||||
signals:
|
||||
void deselect_others(QWidget*);
|
||||
void visibleChanged();
|
||||
void visibleChanged(bool);
|
||||
|
||||
private slots:
|
||||
void on_visible_change();
|
||||
|
||||
@@ -88,6 +88,9 @@ EffectUI::EffectUI(Effect* e) :
|
||||
QWidget* ui = new QWidget(this);
|
||||
SetContents(ui);
|
||||
|
||||
SetExpanded(e->IsExpanded());
|
||||
connect(this, SIGNAL(visibleChanged(bool)), e, SLOT(SetExpanded(bool)));
|
||||
|
||||
layout_ = new QGridLayout(ui);
|
||||
layout_->setSpacing(4);
|
||||
|
||||
|
||||
+60
-21
@@ -61,8 +61,6 @@
|
||||
|
||||
MainWindow* olive::MainWindow;
|
||||
|
||||
#define DEFAULT_CSS "QPushButton::checked { background: rgb(25, 25, 25); }"
|
||||
|
||||
void MainWindow::setup_layout(bool reset) {
|
||||
// load panels from file
|
||||
if (!reset) {
|
||||
@@ -424,25 +422,66 @@ void MainWindow::Restyle()
|
||||
} else {
|
||||
|
||||
// set default palette
|
||||
QPalette darkPalette;
|
||||
darkPalette.setColor(QPalette::Window, QColor(53,53,53));
|
||||
darkPalette.setColor(QPalette::WindowText, Qt::white);
|
||||
darkPalette.setColor(QPalette::Base, QColor(25,25,25));
|
||||
darkPalette.setColor(QPalette::AlternateBase, QColor(53,53,53));
|
||||
darkPalette.setColor(QPalette::ToolTipBase, QColor(25,25,25));
|
||||
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
|
||||
darkPalette.setColor(QPalette::Text, Qt::white);
|
||||
darkPalette.setColor(QPalette::Button, QColor(53,53,53));
|
||||
darkPalette.setColor(QPalette::ButtonText, Qt::white);
|
||||
darkPalette.setColor(QPalette::BrightText, Qt::red);
|
||||
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(128, 128, 128));
|
||||
darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
|
||||
darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
|
||||
darkPalette.setColor(QPalette::HighlightedText, Qt::black);
|
||||
qApp->setPalette(darkPalette);
|
||||
QPalette palette;
|
||||
|
||||
if (olive::CurrentConfig.style == olive::styling::kOliveDefaultLight) {
|
||||
|
||||
palette.setColor(QPalette::Window, QColor(208, 208, 208));
|
||||
palette.setColor(QPalette::WindowText, Qt::black);
|
||||
palette.setColor(QPalette::Base, QColor(240, 240, 240));
|
||||
palette.setColor(QPalette::AlternateBase, QColor(208, 208, 208));
|
||||
palette.setColor(QPalette::ToolTipBase, QColor(255, 255, 255));
|
||||
palette.setColor(QPalette::ToolTipText, Qt::black);
|
||||
palette.setColor(QPalette::Text, Qt::black);
|
||||
palette.setColor(QPalette::Button, QColor(208, 208, 208));
|
||||
palette.setColor(QPalette::ButtonText, Qt::black);
|
||||
palette.setColor(QPalette::BrightText, Qt::red);
|
||||
palette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(208, 208, 208));
|
||||
palette.setColor(QPalette::Link, QColor(42, 130, 218));
|
||||
palette.setColor(QPalette::Highlight, QColor(42, 130, 218));
|
||||
palette.setColor(QPalette::HighlightedText, Qt::white);
|
||||
|
||||
/* Olive Mid
|
||||
palette.setColor(QPalette::Window, QColor(128, 128, 128));
|
||||
palette.setColor(QPalette::WindowText, Qt::black);
|
||||
palette.setColor(QPalette::Base, QColor(192, 192, 192));
|
||||
palette.setColor(QPalette::AlternateBase, QColor(128, 128, 128));
|
||||
palette.setColor(QPalette::ToolTipBase, QColor(192, 192, 192));
|
||||
palette.setColor(QPalette::ToolTipText, Qt::black);
|
||||
palette.setColor(QPalette::Text, Qt::black);
|
||||
palette.setColor(QPalette::Button, QColor(128, 128, 128));
|
||||
palette.setColor(QPalette::ButtonText, Qt::black);
|
||||
palette.setColor(QPalette::BrightText, Qt::red);
|
||||
palette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(128, 128, 128));
|
||||
palette.setColor(QPalette::Link, QColor(42, 130, 218));
|
||||
palette.setColor(QPalette::Highlight, QColor(42, 130, 218));
|
||||
palette.setColor(QPalette::HighlightedText, Qt::black);
|
||||
*/
|
||||
|
||||
} else {
|
||||
|
||||
palette.setColor(QPalette::Window, QColor(53,53,53));
|
||||
palette.setColor(QPalette::WindowText, Qt::white);
|
||||
palette.setColor(QPalette::Base, QColor(25,25,25));
|
||||
palette.setColor(QPalette::AlternateBase, QColor(53,53,53));
|
||||
palette.setColor(QPalette::ToolTipBase, QColor(25,25,25));
|
||||
palette.setColor(QPalette::ToolTipText, Qt::white);
|
||||
palette.setColor(QPalette::Text, Qt::white);
|
||||
palette.setColor(QPalette::Button, QColor(53,53,53));
|
||||
palette.setColor(QPalette::ButtonText, Qt::white);
|
||||
palette.setColor(QPalette::BrightText, Qt::red);
|
||||
palette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(128, 128, 128));
|
||||
palette.setColor(QPalette::Link, QColor(42, 130, 218));
|
||||
palette.setColor(QPalette::Highlight, QColor(42, 130, 218));
|
||||
palette.setColor(QPalette::HighlightedText, Qt::white);
|
||||
|
||||
// set default CSS
|
||||
setStyleSheet("QPushButton::checked { background: rgb(25, 25, 25); }");
|
||||
|
||||
}
|
||||
|
||||
qApp->setPalette(palette);
|
||||
|
||||
// set default CSS
|
||||
setStyleSheet(DEFAULT_CSS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -470,7 +509,7 @@ void MainWindow::setup_menus() {
|
||||
new_menu = MenuHelper::create_submenu(file_menu);
|
||||
olive::MenuHelper.make_new_menu(new_menu);
|
||||
|
||||
open_project = MenuHelper::create_menu_action(file_menu, "openproj", olive::Global.get(), SLOT(open_project()), QKeySequence("Ctrl+O"));
|
||||
open_project = MenuHelper::create_menu_action(file_menu, "openproj", olive::Global.get(), SLOT(OpenProject()), QKeySequence("Ctrl+O"));
|
||||
|
||||
open_recent = MenuHelper::create_submenu(file_menu);
|
||||
|
||||
|
||||
+8
-2
@@ -316,16 +316,22 @@ void DeleteTransitionCommand::doRedo() {
|
||||
|
||||
AddMediaCommand::AddMediaCommand(MediaPtr iitem, Media *iparent) :
|
||||
item(iitem),
|
||||
parent(iparent)
|
||||
parent(iparent),
|
||||
done_(false)
|
||||
{
|
||||
doRedo();
|
||||
}
|
||||
|
||||
void AddMediaCommand::doUndo() {
|
||||
olive::project_model.removeChild(parent, item.get());
|
||||
done_ = false;
|
||||
}
|
||||
|
||||
void AddMediaCommand::doRedo() {
|
||||
olive::project_model.appendChild(parent, item);
|
||||
if (!done_) {
|
||||
olive::project_model.appendChild(parent, item);
|
||||
done_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
DeleteMediaCommand::DeleteMediaCommand(MediaPtr i) :
|
||||
|
||||
@@ -213,6 +213,7 @@ public:
|
||||
private:
|
||||
MediaPtr item;
|
||||
Media* parent;
|
||||
bool done_;
|
||||
};
|
||||
|
||||
class DeleteMediaCommand : public OliveAction {
|
||||
|
||||
Reference in New Issue
Block a user