improvements and moved many behavioral tools menu items to preferences
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "autocutsilencedialog.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QDialogButtonBox>
|
||||
|
||||
#include "timeline/sequence.h"
|
||||
#include "rendering/renderfunctions.h"
|
||||
#include "panels/panels.h"
|
||||
#include "panels/timeline.h"
|
||||
|
||||
AutoCutSilenceDialog::AutoCutSilenceDialog(QWidget *parent, QVector<Clip*> clips) :
|
||||
QDialog(parent),
|
||||
clips_(clips)
|
||||
{
|
||||
setWindowTitle(tr("Cut Silence"));
|
||||
|
||||
QVBoxLayout* main_layout = new QVBoxLayout(this);
|
||||
QGridLayout* grid = new QGridLayout();
|
||||
grid->setSpacing(6);
|
||||
|
||||
grid->addWidget(new QLabel(tr("Attack Threshold:"), this), 0, 0);
|
||||
attack_threshold = new LabelSlider(this);
|
||||
attack_threshold->SetDecimalPlaces(0);
|
||||
grid->addWidget(attack_threshold, 0, 1);
|
||||
|
||||
grid->addWidget(new QLabel(tr("Attack Time:"), this), 1, 0);
|
||||
attack_time = new LabelSlider(this);
|
||||
attack_time->SetDecimalPlaces(0);
|
||||
grid->addWidget(attack_time, 1, 1);
|
||||
|
||||
grid->addWidget(new QLabel(tr("Release Threshold:"), this), 2, 0);
|
||||
release_threshold = new LabelSlider(this);
|
||||
release_threshold->SetDecimalPlaces(0);
|
||||
grid->addWidget(release_threshold, 2, 1);
|
||||
|
||||
grid->addWidget(new QLabel(tr("Release Time:"), this), 3, 0);
|
||||
release_time = new LabelSlider(this);
|
||||
release_time->SetDecimalPlaces(0);
|
||||
grid->addWidget(release_time, 3, 1);
|
||||
|
||||
main_layout->addLayout(grid);
|
||||
|
||||
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
|
||||
buttonBox->setCenterButtons(true);
|
||||
main_layout->addWidget(buttonBox);
|
||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
|
||||
}
|
||||
|
||||
int AutoCutSilenceDialog::exec()
|
||||
{
|
||||
default_attack_threshold = 5;
|
||||
current_attack_threshold = 5;
|
||||
default_attack_time = 2;
|
||||
current_attack_time = 2;
|
||||
default_release_threshold = 2;
|
||||
current_release_threshold = 2;
|
||||
default_release_time = 5;
|
||||
current_release_time = 5;
|
||||
|
||||
attack_threshold->SetMinimum(1);
|
||||
attack_threshold->setEnabled(true);
|
||||
attack_threshold->SetDefault(default_attack_threshold);
|
||||
attack_threshold->SetValue(current_attack_threshold);
|
||||
|
||||
attack_time->SetMinimum(1);
|
||||
attack_time->setEnabled(true);
|
||||
attack_time->SetDefault(default_attack_time);
|
||||
attack_time->SetValue(current_attack_time);
|
||||
|
||||
release_threshold->SetMinimum(1);
|
||||
release_threshold->setEnabled(true);
|
||||
release_threshold->SetDefault(default_release_threshold);
|
||||
release_threshold->SetValue(current_release_threshold);
|
||||
|
||||
release_time->SetMinimum(1);
|
||||
release_time->setEnabled(true);
|
||||
release_time->SetDefault(default_release_time);
|
||||
release_time->SetValue(current_release_time);
|
||||
|
||||
return QDialog::exec();
|
||||
}
|
||||
|
||||
void AutoCutSilenceDialog::accept() {
|
||||
|
||||
current_attack_threshold = attack_threshold->value();
|
||||
current_attack_time = attack_time->value();
|
||||
current_release_threshold = release_threshold->value();
|
||||
current_release_time = release_time->value();
|
||||
|
||||
cut_silence();
|
||||
|
||||
update_ui(true);
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void AutoCutSilenceDialog::cut_silence() {
|
||||
// Loop over clips provided to this dialog
|
||||
for (int j=0;j<clips_.size();j++) {
|
||||
|
||||
Clip* clip = clips_.at(j);
|
||||
|
||||
// Check if this clip is an audio footage clip
|
||||
if (clip->track() >= 0
|
||||
&& clip->media() != nullptr
|
||||
&& clip->media_stream()->preview_done) { // TODO provide warning for preview not being done
|
||||
|
||||
QVector<long> split_positions;
|
||||
|
||||
int clip_start = clip->timeline_in();
|
||||
const FootageStream* ms = clip->media_stream();
|
||||
|
||||
long media_length = clip->media_length();
|
||||
int preview_size = ms->audio_preview.length();
|
||||
float chunk_size = (float)preview_size/media_length; // how many audio samples to read for each fotogram
|
||||
|
||||
int sample_size = qMax(current_attack_time, current_release_time)+1;
|
||||
|
||||
bool attack = false; // status flags
|
||||
bool release = false;
|
||||
|
||||
QVector<qint8> vols;
|
||||
vols.resize(sample_size);
|
||||
vols.fill(0);
|
||||
|
||||
// loop through the entire sequence
|
||||
for (long i=clip_start;i<media_length+clip_start;i++) {
|
||||
long start = ((i-clip_start)*chunk_size); //audio samples are read relative to the clip, not absolute to the timeline
|
||||
int circular_index = i%sample_size;
|
||||
|
||||
// read the current sample into the circular array
|
||||
qint8 tmp = 0;
|
||||
for (int k=start; k<start+chunk_size; k++){
|
||||
tmp = qMax(tmp, qint8(qRound(double(ms->audio_preview.at(k)))));
|
||||
}
|
||||
vols[circular_index] = tmp;
|
||||
|
||||
//for debug:
|
||||
//qInfo() << "i:" << i <<" - "<< i/30 <<":"<< i%30 << " - volume:" << vols[circular_index] <<"\n";
|
||||
|
||||
int overthreshold = 0;
|
||||
int cut_idx = 0; //how much to cut (backwards)
|
||||
|
||||
// if current volume value is above threshold
|
||||
if (vols[circular_index] >= current_attack_threshold && !attack){ // if we get one sample over the threshold
|
||||
for(int k=0; k<sample_size; k++){ // count how many times this happened before within sample_size range (avoid false activations)
|
||||
int back_idx = (((circular_index-k)%sample_size)+sample_size)%sample_size; // positive modulus
|
||||
if(vols[back_idx] > current_attack_threshold){
|
||||
overthreshold++;
|
||||
cut_idx = k+1;
|
||||
}
|
||||
}
|
||||
// if we reached threshold over the set tolerance
|
||||
if(overthreshold >= current_attack_time){
|
||||
split_positions.append(i-cut_idx);
|
||||
attack = true;
|
||||
release = false;
|
||||
//qInfo() << "\n\n Current vol: "<<vols[circular_index]<<" attack at " << i-cut_idx << "\n\n";
|
||||
}
|
||||
overthreshold = 0;
|
||||
cut_idx = 0;
|
||||
}else if (vols[circular_index] < current_release_threshold && !release){ // if we get one sample under the threshold
|
||||
for(int k=0; k<sample_size; k++){ // count how many times this happened before within sample_size range
|
||||
int back_idx = (((circular_index-k)%sample_size)+sample_size)%sample_size; // positive modulus
|
||||
if(vols[back_idx] < current_release_threshold)
|
||||
overthreshold++;
|
||||
}
|
||||
// if we reached threshold over the set tolerance
|
||||
if(overthreshold >= current_release_time){ // must be <= sample_size
|
||||
attack = false;
|
||||
release = true;
|
||||
split_positions.append(i);
|
||||
//qInfo() << "\n\n Current vol: "<<vols[circular_index]<<" release at " << i << "\n\n";
|
||||
}
|
||||
overthreshold = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ComboAction* ca = new ComboAction();
|
||||
|
||||
// NO GOOD VERY BAD TEST CODE
|
||||
int clip_index = -1;
|
||||
for (int i=0;i<olive::ActiveSequence->clips.size();i++) {
|
||||
if (olive::ActiveSequence->clips.at(i).get() == clip) {
|
||||
clip_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Q_ASSERT(clip_index > -1);
|
||||
|
||||
panel_timeline->split_clip_at_positions(ca, clip_index, split_positions);
|
||||
olive::UndoStack.push(ca);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef SILENCEDIALOG_H
|
||||
#define SILENCEDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QCheckBox>
|
||||
|
||||
#include "timeline/clip.h"
|
||||
#include "ui/labelslider.h"
|
||||
|
||||
class AutoCutSilenceDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AutoCutSilenceDialog(QWidget* parent, QVector<Clip*> clips);
|
||||
public slots:
|
||||
virtual int exec() override;
|
||||
private slots:
|
||||
virtual void accept() override;
|
||||
private:
|
||||
void cut_silence();
|
||||
|
||||
QVector<Clip*> clips_;
|
||||
|
||||
LabelSlider* attack_threshold;
|
||||
LabelSlider* release_threshold;
|
||||
LabelSlider* attack_time;
|
||||
LabelSlider* release_time;
|
||||
|
||||
int default_attack_threshold;
|
||||
int current_attack_threshold;
|
||||
int default_release_threshold;
|
||||
int current_release_threshold;
|
||||
int default_attack_time;
|
||||
int current_attack_time;
|
||||
int default_release_time;
|
||||
int current_release_time;
|
||||
};
|
||||
|
||||
#endif // SILENCEDIALOG_H
|
||||
@@ -20,13 +20,6 @@
|
||||
|
||||
#include "preferencesdialog.h"
|
||||
|
||||
#include "global/global.h"
|
||||
#include "global/config.h"
|
||||
#include "global/path.h"
|
||||
#include "rendering/audio.h"
|
||||
#include "panels/panels.h"
|
||||
#include "ui/mainwindow.h"
|
||||
|
||||
#include <QMenuBar>
|
||||
#include <QAction>
|
||||
#include <QVBoxLayout>
|
||||
@@ -51,6 +44,14 @@
|
||||
#include <QProcess>
|
||||
#include <QDebug>
|
||||
|
||||
#include "global/global.h"
|
||||
#include "global/config.h"
|
||||
#include "global/path.h"
|
||||
#include "rendering/audio.h"
|
||||
#include "panels/panels.h"
|
||||
#include "ui/columnedgridlayout.h"
|
||||
#include "ui/mainwindow.h"
|
||||
|
||||
KeySequenceEditor::KeySequenceEditor(QWidget* parent, QAction* a)
|
||||
: QKeySequenceEdit(parent), action(a) {
|
||||
setKeySequence(action->shortcut());
|
||||
@@ -142,6 +143,15 @@ void PreferencesDialog::delete_previews(char type) {
|
||||
}
|
||||
}
|
||||
|
||||
void PreferencesDialog::AddBoolPair(QCheckBox *ui, bool *value, bool restart_required)
|
||||
{
|
||||
bool_ui.append(ui);
|
||||
bool_value.append(value);
|
||||
bool_restart_required.append(restart_required);
|
||||
|
||||
ui->setChecked(*value);
|
||||
}
|
||||
|
||||
void PreferencesDialog::setup_kbd_shortcuts(QMenuBar* menubar) {
|
||||
QList<QAction*> menus = menubar->actions();
|
||||
|
||||
@@ -186,14 +196,20 @@ void PreferencesDialog::accept() {
|
||||
reload_effects = true;
|
||||
}
|
||||
|
||||
bool bool_requires_restart = false;
|
||||
for (int i=0;i<bool_restart_required.size();i++) {
|
||||
if (bool_restart_required.at(i)
|
||||
&& bool_ui.at(i)->isChecked() != *bool_value.at(i)) {
|
||||
bool_requires_restart = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if any settings will require a restart of Olive
|
||||
if (olive::CurrentConfig.use_software_fallback != use_software_fallbacks_checkbox->isChecked()
|
||||
if (bool_requires_restart
|
||||
|| olive::CurrentConfig.thumbnail_resolution != thumbnail_res_spinbox->value()
|
||||
|| olive::CurrentConfig.waveform_resolution != waveform_res_spinbox->value()
|
||||
|| olive::CurrentConfig.css_path != custom_css_fn->text()
|
||||
#ifdef Q_OS_WIN32
|
||||
|| olive::CurrentConfig.use_native_menu_styling != native_menus->isChecked()
|
||||
#endif
|
||||
|| olive::CurrentConfig.style != static_cast<olive::styling::Style>(ui_style->currentData().toInt())) {
|
||||
|
||||
// any changes to these settings will require a restart - ask the user if we should do one now or later
|
||||
@@ -241,22 +257,19 @@ void PreferencesDialog::accept() {
|
||||
olive::CurrentConfig.upcoming_queue_type = upcoming_queue_type->currentIndex();
|
||||
olive::CurrentConfig.previous_queue_size = previous_queue_spinbox->value();
|
||||
olive::CurrentConfig.previous_queue_type = previous_queue_type->currentIndex();
|
||||
olive::CurrentConfig.add_default_effects_to_clips = add_default_effects_to_clips->isChecked();
|
||||
|
||||
olive::CurrentConfig.preferred_audio_output = audio_output_devices->currentData().toString();
|
||||
olive::CurrentConfig.preferred_audio_input = audio_input_devices->currentData().toString();
|
||||
olive::CurrentConfig.audio_rate = audio_sample_rate->currentData().toInt();
|
||||
|
||||
olive::CurrentConfig.effect_textbox_lines = effect_textbox_lines_field->value();
|
||||
olive::CurrentConfig.use_software_fallback = use_software_fallbacks_checkbox->isChecked();
|
||||
olive::CurrentConfig.language_file = language_combobox->currentData().toString();
|
||||
|
||||
olive::CurrentConfig.style = static_cast<olive::styling::Style>(ui_style->currentData().toInt());
|
||||
#ifdef Q_OS_WIN
|
||||
olive::CurrentConfig.use_native_menu_styling = native_menus->isChecked();
|
||||
#endif
|
||||
for (int i=0;i<bool_ui.size();i++) {
|
||||
*bool_value[i] = bool_ui.at(i)->isChecked();
|
||||
}
|
||||
|
||||
olive::CurrentConfig.auto_seek_to_beginning = auto_seek_to_beginning->isChecked();
|
||||
olive::CurrentConfig.style = static_cast<olive::styling::Style>(ui_style->currentData().toInt());
|
||||
|
||||
// Check if the thumbnail or waveform icon
|
||||
if (olive::CurrentConfig.thumbnail_resolution != thumbnail_res_spinbox->value()
|
||||
@@ -539,9 +552,8 @@ void PreferencesDialog::setup_ui() {
|
||||
row++;
|
||||
|
||||
// General -> Use Software Fallbacks When Possible
|
||||
use_software_fallbacks_checkbox = new QCheckBox(general_tab);
|
||||
use_software_fallbacks_checkbox->setText(tr("Use Software Fallbacks When Possible"));
|
||||
use_software_fallbacks_checkbox->setChecked(olive::CurrentConfig.use_software_fallback);
|
||||
QCheckBox* use_software_fallbacks_checkbox = new QCheckBox(tr("Use Software Fallbacks When Possible"));
|
||||
AddBoolPair(use_software_fallbacks_checkbox, &olive::CurrentConfig.use_software_fallback, true);
|
||||
general_layout->addWidget(use_software_fallbacks_checkbox, row, 0, 1, 4);
|
||||
|
||||
row++;
|
||||
@@ -556,15 +568,72 @@ void PreferencesDialog::setup_ui() {
|
||||
QWidget* behavior_tab = new QWidget(this);
|
||||
tabWidget->addTab(behavior_tab, tr("Behavior"));
|
||||
|
||||
QVBoxLayout* behavior_tab_layout = new QVBoxLayout(behavior_tab);
|
||||
ColumnedGridLayout* behavior_tab_layout = new ColumnedGridLayout(behavior_tab, 2);
|
||||
|
||||
add_default_effects_to_clips = new QCheckBox(tr("Add Default Effects to New Clips"));
|
||||
add_default_effects_to_clips->setChecked(olive::CurrentConfig.add_default_effects_to_clips);
|
||||
behavior_tab_layout->addWidget(add_default_effects_to_clips);
|
||||
QCheckBox* add_default_effects_to_clips = new QCheckBox(tr("Add Default Effects to New Clips"));
|
||||
AddBoolPair(add_default_effects_to_clips, &olive::CurrentConfig.add_default_effects_to_clips);
|
||||
behavior_tab_layout->Add(add_default_effects_to_clips);
|
||||
|
||||
auto_seek_to_beginning = new QCheckBox(tr("Automatically Seek to the Beginning When Playing at the End of a Sequence"));
|
||||
auto_seek_to_beginning->setChecked(olive::CurrentConfig.auto_seek_to_beginning);
|
||||
behavior_tab_layout->addWidget(auto_seek_to_beginning);
|
||||
QCheckBox* auto_seek_to_beginning = new QCheckBox(tr("Automatically Seek to the Beginning When Playing at the End of a Sequence"));
|
||||
AddBoolPair(auto_seek_to_beginning, &olive::CurrentConfig.auto_seek_to_beginning);
|
||||
behavior_tab_layout->Add(auto_seek_to_beginning);
|
||||
|
||||
QCheckBox* selecting_also_seeks = new QCheckBox(tr("Selecting Also Seeks"));
|
||||
AddBoolPair(selecting_also_seeks, &olive::CurrentConfig.select_also_seeks);
|
||||
behavior_tab_layout->Add(selecting_also_seeks);
|
||||
|
||||
QCheckBox* edit_tool_also_seeks = new QCheckBox(tr("Edit Tool Also Seeks"));
|
||||
AddBoolPair(edit_tool_also_seeks, &olive::CurrentConfig.edit_tool_also_seeks);
|
||||
behavior_tab_layout->Add(edit_tool_also_seeks);
|
||||
|
||||
QCheckBox* edit_tool_selects_links = new QCheckBox(tr("Edit Tool Selects Links"));
|
||||
AddBoolPair(edit_tool_selects_links, &olive::CurrentConfig.edit_tool_selects_links);
|
||||
behavior_tab_layout->Add(edit_tool_selects_links);
|
||||
|
||||
QCheckBox* seek_also_selects = new QCheckBox(tr("Seek Also Selects"));
|
||||
AddBoolPair(seek_also_selects, &olive::CurrentConfig.seek_also_selects);
|
||||
behavior_tab_layout->Add(seek_also_selects);
|
||||
|
||||
QCheckBox* seek_to_end_of_pastes = new QCheckBox(tr("Seek to the End of Pastes"));
|
||||
AddBoolPair(seek_to_end_of_pastes, &olive::CurrentConfig.paste_seeks);
|
||||
behavior_tab_layout->Add(seek_to_end_of_pastes);
|
||||
|
||||
QCheckBox* scroll_wheel_zooms = new QCheckBox(tr("Scroll Wheel Zooms"));
|
||||
scroll_wheel_zooms->setToolTip(tr("Hold CTRL to toggle this setting"));
|
||||
AddBoolPair(scroll_wheel_zooms, &olive::CurrentConfig.scroll_zooms);
|
||||
behavior_tab_layout->Add(scroll_wheel_zooms);
|
||||
|
||||
QCheckBox* invert_timeline_scroll_axes = new QCheckBox(tr("Invert Timeline Scroll Axes"));
|
||||
AddBoolPair(invert_timeline_scroll_axes, &olive::CurrentConfig.invert_timeline_scroll_axes);
|
||||
behavior_tab_layout->Add(invert_timeline_scroll_axes);
|
||||
|
||||
QCheckBox* enable_drag_files_to_timeline = new QCheckBox(tr("Enable Drag Files to Timeline"));
|
||||
AddBoolPair(enable_drag_files_to_timeline, &olive::CurrentConfig.enable_drag_files_to_timeline);
|
||||
behavior_tab_layout->Add(enable_drag_files_to_timeline);
|
||||
|
||||
QCheckBox* autoscale_by_default = new QCheckBox(tr("Auto-Scale By Default"));
|
||||
AddBoolPair(autoscale_by_default, &olive::CurrentConfig.autoscale_by_default);
|
||||
behavior_tab_layout->Add(autoscale_by_default);
|
||||
|
||||
QCheckBox* enable_seek_to_import = new QCheckBox(tr("Auto-Seek to Imported Clips"));
|
||||
AddBoolPair(enable_seek_to_import, &olive::CurrentConfig.enable_seek_to_import);
|
||||
behavior_tab_layout->Add(enable_seek_to_import);
|
||||
|
||||
QCheckBox* enable_audio_scrubbing = new QCheckBox(tr("Audio Scrubbing"));
|
||||
AddBoolPair(enable_audio_scrubbing, &olive::CurrentConfig.enable_audio_scrubbing);
|
||||
behavior_tab_layout->Add(enable_audio_scrubbing);
|
||||
|
||||
QCheckBox* enable_drop_on_media_to_replace = new QCheckBox(tr("Drop Files on Media to Replace"));
|
||||
AddBoolPair(enable_drop_on_media_to_replace, &olive::CurrentConfig.drop_on_media_to_replace);
|
||||
behavior_tab_layout->Add(enable_drop_on_media_to_replace);
|
||||
|
||||
QCheckBox* enable_hover_focus = new QCheckBox(tr("Enable Hover Focus"));
|
||||
AddBoolPair(enable_hover_focus, &olive::CurrentConfig.hover_focus);
|
||||
behavior_tab_layout->Add(enable_hover_focus);
|
||||
|
||||
QCheckBox* set_name_and_marker = new QCheckBox(tr("Ask For Name When Setting Marker"));
|
||||
AddBoolPair(set_name_and_marker, &olive::CurrentConfig.set_name_with_marker);
|
||||
behavior_tab_layout->Add(set_name_and_marker);
|
||||
|
||||
// Appearance
|
||||
QWidget* appearance_tab = new QWidget(this);
|
||||
@@ -590,8 +659,8 @@ void PreferencesDialog::setup_ui() {
|
||||
#ifdef Q_OS_WIN
|
||||
// Native menu styling is only available on Windows. Environments like Ubuntu and Mac use the native menu system by
|
||||
// default
|
||||
native_menus = new QCheckBox(tr("Use Native Menu Styling"));
|
||||
native_menus->setChecked(olive::CurrentConfig.use_native_menu_styling);
|
||||
QCheckBox* native_menus = new QCheckBox(tr("Use Native Menu Styling"));
|
||||
AddBoolPair(native_menus, &olive::CurrentConfig.use_native_menu_styling);
|
||||
appearance_layout->addWidget(native_menus, row, 0, 1, 3);
|
||||
|
||||
row++;
|
||||
|
||||
+39
-21
@@ -208,11 +208,6 @@ private:
|
||||
*/
|
||||
QSpinBox* effect_textbox_lines_field;
|
||||
|
||||
/**
|
||||
* @brief UI widget for enabling/disabling software fallbacks
|
||||
*/
|
||||
QCheckBox* use_software_fallbacks_checkbox;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the output audio device
|
||||
*/
|
||||
@@ -243,26 +238,10 @@ private:
|
||||
*/
|
||||
QSpinBox* waveform_res_spinbox;
|
||||
|
||||
/**
|
||||
* @brief UI widget for enabling/disabling default effects
|
||||
*/
|
||||
QCheckBox* add_default_effects_to_clips;
|
||||
|
||||
/**
|
||||
* @brief UI widget for enabling/disabling Config::auto_seek_to_beginning
|
||||
*/
|
||||
QCheckBox* auto_seek_to_beginning;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the current UI style
|
||||
*/
|
||||
QComboBox* ui_style;
|
||||
#ifdef Q_OS_WIN
|
||||
/**
|
||||
* @brief UI widget for forcing native menu styling on Windows
|
||||
*/
|
||||
QCheckBox* native_menus;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief List of keyboard shortcut actions that can be triggered (links with key_shortcut_items and
|
||||
@@ -281,6 +260,45 @@ private:
|
||||
* key_shortcut_actions and key_shortcut_fields)
|
||||
*/
|
||||
QVector<KeySequenceEditor*> key_shortcut_fields;
|
||||
|
||||
/**
|
||||
* @brief Add an automated QCheckBox+boolean value pair
|
||||
*
|
||||
* Many preferences are simple true/false (or on/off) options. Rather than adding a QCheckBox for each one and
|
||||
* manually setting its checked value to the configuration setting (and vice versa when saving), this convenience
|
||||
* function will add it to an automated set of checkboxes, automatically setting the checked state to the current
|
||||
* setting, and then saving the new checked state back to the setting when the user accepts the changes (clicks OK).
|
||||
*
|
||||
* @param ui
|
||||
*
|
||||
* A valid QCheckBox item. This function does not take ownership of the QWidget or place it in a layout anywhere.
|
||||
*
|
||||
* @param value
|
||||
*
|
||||
* A pointer to the Boolean value this QCheckBox should be shared with. The QCheckBox widget's checked state will be
|
||||
* set to the value of this pointer.
|
||||
*
|
||||
* @param restart_required
|
||||
*
|
||||
* Defaults to FALSE, set this to TRUE if changing this setting should prompt the user for a restart of Olive before
|
||||
* the setting change takes effect.
|
||||
*/
|
||||
void AddBoolPair(QCheckBox* ui, bool* value, bool restart_required = false);
|
||||
|
||||
/**
|
||||
* @brief Internal array managed by AddBoolPair(). Do not access this directly.
|
||||
*/
|
||||
QVector<QCheckBox*> bool_ui;
|
||||
|
||||
/**
|
||||
* @brief Internal array managed by AddBoolPair(). Do not access this directly.
|
||||
*/
|
||||
QVector<bool*> bool_value;
|
||||
|
||||
/**
|
||||
* @brief Internal array managed by AddBoolPair(). Do not access this directly.
|
||||
*/
|
||||
QVector<bool> bool_restart_required;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ 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),
|
||||
|
||||
+36
-6
@@ -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"
|
||||
@@ -301,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();
|
||||
}
|
||||
@@ -377,6 +373,22 @@ void OliveGlobal::OpenProjectWorker(const QString& fn, bool 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) {
|
||||
@@ -426,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();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -340,6 +345,18 @@ private:
|
||||
*/
|
||||
void OpenProjectWorker(const 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
|
||||
*
|
||||
|
||||
@@ -174,7 +174,9 @@ SOURCES += \
|
||||
effects/internal/richtexteffect.cpp \
|
||||
ui/blur.cpp \
|
||||
ui/menu.cpp \
|
||||
timeline/mediaimportdata.cpp
|
||||
timeline/mediaimportdata.cpp \
|
||||
dialogs/autocutsilencedialog.cpp \
|
||||
ui/columnedgridlayout.cpp
|
||||
|
||||
HEADERS += \
|
||||
ui/mainwindow.h \
|
||||
@@ -302,7 +304,9 @@ HEADERS += \
|
||||
effects/internal/richtexteffect.h \
|
||||
ui/blur.h \
|
||||
ui/menu.h \
|
||||
timeline/mediaimportdata.h
|
||||
timeline/mediaimportdata.h \
|
||||
dialogs/autocutsilencedialog.h \
|
||||
ui/columnedgridlayout.h
|
||||
|
||||
FORMS +=
|
||||
|
||||
|
||||
@@ -138,6 +138,53 @@ void Timeline::Retranslate() {
|
||||
UpdateTitle();
|
||||
}
|
||||
|
||||
void Timeline::split_clip_at_positions(ComboAction* ca, int clip_index, QVector<long> positions) {
|
||||
|
||||
QVector<int> pre_splits;
|
||||
|
||||
// Add the clip and each of its links to the pre_splits array
|
||||
Clip* clip = olive::ActiveSequence->clips.at(clip_index).get();
|
||||
pre_splits.append(clip_index);
|
||||
for (int i=0;i<clip->linked.size();i++) {
|
||||
pre_splits.append(clip->linked.at(i));
|
||||
}
|
||||
|
||||
std::sort(positions.begin(), positions.end());
|
||||
|
||||
// Remove any duplicate positions
|
||||
for (int i=1;i<positions.size();i++) {
|
||||
if (positions.at(i-1) == positions.at(i)) {
|
||||
positions.removeAt(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=1;i<positions.size();i++) {
|
||||
Q_ASSERT(positions.at(i-1) < positions.at(i));
|
||||
}
|
||||
|
||||
QVector< QVector<ClipPtr> > post_splits(positions.size());
|
||||
|
||||
for (int i=positions.size()-1;i>=0;i--) {
|
||||
|
||||
post_splits[i].resize(pre_splits.size());
|
||||
|
||||
for (int j=0;j<pre_splits.size();j++) {
|
||||
post_splits[i][j] = split_clip(ca, true, pre_splits.at(j), positions.at(i));
|
||||
|
||||
if (post_splits[i][j] != nullptr && i + 1 < positions.size()) {
|
||||
post_splits[i][j]->set_timeline_out(positions.at(i+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0;i<post_splits.size();i++) {
|
||||
relink_clips_using_ids(pre_splits, post_splits[i]);
|
||||
ca->append(new AddClipCommand(olive::ActiveSequence.get(), post_splits[i]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Timeline::previous_cut() {
|
||||
if (olive::ActiveSequence != nullptr
|
||||
&& olive::ActiveSequence->playhead > 0) {
|
||||
|
||||
@@ -117,6 +117,7 @@ public:
|
||||
bool split_selection(ComboAction* ca);
|
||||
bool split_all_clips_at_point(ComboAction *ca, long point);
|
||||
bool split_clip_and_relink(ComboAction* ca, int clip, long frame, bool relink);
|
||||
void split_clip_at_positions(ComboAction* ca, int clip_index, QVector<long> positions);
|
||||
void clean_up_selections(QVector<Selection>& areas);
|
||||
void deselect_area(long in, long out, int track);
|
||||
void delete_areas_and_relink(ComboAction *ca, QVector<Selection>& areas, bool deselect_areas);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "columnedgridlayout.h"
|
||||
|
||||
ColumnedGridLayout::ColumnedGridLayout(QWidget* parent,
|
||||
int maximum_columns) :
|
||||
QGridLayout (parent),
|
||||
maximum_columns_(maximum_columns)
|
||||
{
|
||||
}
|
||||
|
||||
void ColumnedGridLayout::Add(QWidget *widget)
|
||||
{
|
||||
if (maximum_columns_ > 0) {
|
||||
|
||||
int row = count() / maximum_columns_;
|
||||
int column = count() % maximum_columns_;
|
||||
|
||||
addWidget(widget, row, column);
|
||||
|
||||
} else {
|
||||
|
||||
addWidget(widget);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int ColumnedGridLayout::MaximumColumns() const
|
||||
{
|
||||
return maximum_columns_;
|
||||
}
|
||||
|
||||
void ColumnedGridLayout::SetMaximumColumns(int maximum_columns)
|
||||
{
|
||||
maximum_columns_ = maximum_columns;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef COLUMNEDGRIDLAYOUT_H
|
||||
#define COLUMNEDGRIDLAYOUT_H
|
||||
|
||||
#include <QGridLayout>
|
||||
|
||||
/**
|
||||
* @brief The ColumnedGridLayout class
|
||||
*
|
||||
* A simple derivative of QGridLayout that provides a automatic row/column layout based on a specified maximum
|
||||
* column count.
|
||||
*/
|
||||
class ColumnedGridLayout : public QGridLayout
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColumnedGridLayout(QWidget* parent = nullptr,
|
||||
int maximum_columns = 0);
|
||||
|
||||
void Add(QWidget* widget);
|
||||
int MaximumColumns() const;
|
||||
void SetMaximumColumns(int maximum_columns);
|
||||
|
||||
private:
|
||||
int maximum_columns_;
|
||||
};
|
||||
|
||||
#endif // COLUMNEDGRIDLAYOUT_H
|
||||
+4
-86
@@ -760,61 +760,7 @@ void MainWindow::setup_menus() {
|
||||
|
||||
tools_menu->addSeparator();
|
||||
|
||||
selecting_also_seeks = MenuHelper::create_menu_action(tools_menu, "selectingalsoseeks", &olive::MenuHelper, SLOT(toggle_bool_action()));
|
||||
selecting_also_seeks->setCheckable(true);
|
||||
selecting_also_seeks->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.select_also_seeks));
|
||||
|
||||
edit_tool_also_seeks = MenuHelper::create_menu_action(tools_menu, "editalsoseeks", &olive::MenuHelper, SLOT(toggle_bool_action()));
|
||||
edit_tool_also_seeks->setCheckable(true);
|
||||
edit_tool_also_seeks->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.edit_tool_also_seeks));
|
||||
|
||||
edit_tool_selects_links = MenuHelper::create_menu_action(tools_menu, "editselectslinks", &olive::MenuHelper, SLOT(toggle_bool_action()));
|
||||
edit_tool_selects_links->setCheckable(true);
|
||||
edit_tool_selects_links->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.edit_tool_selects_links));
|
||||
|
||||
seek_also_selects = MenuHelper::create_menu_action(tools_menu, "seekalsoselects", &olive::MenuHelper, SLOT(toggle_bool_action()));
|
||||
seek_also_selects->setCheckable(true);
|
||||
seek_also_selects->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.seek_also_selects));
|
||||
|
||||
seek_to_end_of_pastes = MenuHelper::create_menu_action(tools_menu, "seektoendofpastes", &olive::MenuHelper, SLOT(toggle_bool_action()));
|
||||
seek_to_end_of_pastes->setCheckable(true);
|
||||
seek_to_end_of_pastes->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.paste_seeks));
|
||||
|
||||
scroll_wheel_zooms = MenuHelper::create_menu_action(tools_menu, "scrollwheelzooms", &olive::MenuHelper, SLOT(toggle_bool_action()));
|
||||
scroll_wheel_zooms->setCheckable(true);
|
||||
scroll_wheel_zooms->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.scroll_zooms));
|
||||
|
||||
invert_timeline_scroll_axes = MenuHelper::create_menu_action(tools_menu, "inverttimelinescrollaxes", &olive::MenuHelper, SLOT(toggle_bool_action()));
|
||||
invert_timeline_scroll_axes->setCheckable(true);
|
||||
invert_timeline_scroll_axes->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.invert_timeline_scroll_axes));
|
||||
|
||||
enable_drag_files_to_timeline = MenuHelper::create_menu_action(tools_menu, "enabledragfilestotimeline", &olive::MenuHelper, SLOT(toggle_bool_action()));
|
||||
enable_drag_files_to_timeline->setCheckable(true);
|
||||
enable_drag_files_to_timeline->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.enable_drag_files_to_timeline));
|
||||
|
||||
autoscale_by_default = MenuHelper::create_menu_action(tools_menu, "autoscalebydefault", &olive::MenuHelper, SLOT(toggle_bool_action()));
|
||||
autoscale_by_default->setCheckable(true);
|
||||
autoscale_by_default->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.autoscale_by_default));
|
||||
|
||||
enable_seek_to_import = MenuHelper::create_menu_action(tools_menu, "enableseektoimport", &olive::MenuHelper, SLOT(toggle_bool_action()));
|
||||
enable_seek_to_import->setCheckable(true);
|
||||
enable_seek_to_import->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.enable_seek_to_import));
|
||||
|
||||
enable_audio_scrubbing = MenuHelper::create_menu_action(tools_menu, "audioscrubbing", &olive::MenuHelper, SLOT(toggle_bool_action()));
|
||||
enable_audio_scrubbing->setCheckable(true);
|
||||
enable_audio_scrubbing->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.enable_audio_scrubbing));
|
||||
|
||||
enable_drop_on_media_to_replace = MenuHelper::create_menu_action(tools_menu, "enabledropmediareplace", &olive::MenuHelper, SLOT(toggle_bool_action()));
|
||||
enable_drop_on_media_to_replace->setCheckable(true);
|
||||
enable_drop_on_media_to_replace->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.drop_on_media_to_replace));
|
||||
|
||||
enable_hover_focus = MenuHelper::create_menu_action(tools_menu, "hoverfocus", &olive::MenuHelper, SLOT(toggle_bool_action()));
|
||||
enable_hover_focus->setCheckable(true);
|
||||
enable_hover_focus->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.hover_focus));
|
||||
|
||||
set_name_and_marker = MenuHelper::create_menu_action(tools_menu, "asknamemarkerset", &olive::MenuHelper, SLOT(toggle_bool_action()));
|
||||
set_name_and_marker->setCheckable(true);
|
||||
set_name_and_marker->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.set_name_with_marker));
|
||||
autocut_silence_ = MenuHelper::create_menu_action(tools_menu, "autocutsilence", olive::Global.get(), SLOT(open_autocut_silence_dialog()));
|
||||
|
||||
tools_menu->addSeparator();
|
||||
|
||||
@@ -952,21 +898,7 @@ void MainWindow::Retranslate()
|
||||
hand_tool_action->setText(tr("Hand Tool"));
|
||||
transition_tool_action->setText(tr("Transition Tool"));
|
||||
snap_toggle->setText(tr("Enable Snapping"));
|
||||
selecting_also_seeks->setText(tr("Selecting Also Seeks"));
|
||||
edit_tool_also_seeks->setText(tr("Edit Tool Also Seeks"));
|
||||
edit_tool_selects_links->setText(tr("Edit Tool Selects Links"));
|
||||
seek_also_selects->setText(tr("Seek Also Selects"));
|
||||
seek_to_end_of_pastes->setText(tr("Seek to the End of Pastes"));
|
||||
scroll_wheel_zooms->setText(tr("Scroll Wheel Zooms"));
|
||||
scroll_wheel_zooms->setToolTip(tr("Hold CTRL to toggle this setting"));
|
||||
invert_timeline_scroll_axes->setText(tr("Invert Timeline Scroll Axes"));
|
||||
enable_drag_files_to_timeline->setText(tr("Enable Drag Files to Timeline"));
|
||||
autoscale_by_default->setText(tr("Auto-Scale By Default"));
|
||||
enable_seek_to_import->setText(tr("Enable Seek to Import"));
|
||||
enable_audio_scrubbing->setText(tr("Audio Scrubbing"));
|
||||
enable_drop_on_media_to_replace->setText(tr("Enable Drop on Media to Replace"));
|
||||
enable_hover_focus->setText(tr("Enable Hover Focus"));
|
||||
set_name_and_marker->setText(tr("Ask For Name When Setting Marker"));
|
||||
autocut_silence_->setText(tr("Auto-Cut Silence"));
|
||||
|
||||
no_autoscroll->setText(tr("No Auto-Scroll"));
|
||||
page_autoscroll->setText(tr("Page Auto-Scroll"));
|
||||
@@ -1173,6 +1105,8 @@ void MainWindow::playbackMenu_About_To_Be_Shown() {
|
||||
void MainWindow::viewMenu_About_To_Be_Shown() {
|
||||
olive::MenuHelper.set_bool_action_checked(track_lines);
|
||||
|
||||
olive::MenuHelper.set_bool_action_checked(rectified_waveforms);
|
||||
|
||||
olive::MenuHelper.set_int_action_checked(frames_action, olive::CurrentConfig.timecode_view);
|
||||
olive::MenuHelper.set_int_action_checked(drop_frame_action, olive::CurrentConfig.timecode_view);
|
||||
olive::MenuHelper.set_int_action_checked(nondrop_frame_action, olive::CurrentConfig.timecode_view);
|
||||
@@ -1208,22 +1142,6 @@ void MainWindow::toolMenu_About_To_Be_Shown() {
|
||||
olive::MenuHelper.set_button_action_checked(transition_tool_action);
|
||||
olive::MenuHelper.set_button_action_checked(snap_toggle);
|
||||
|
||||
olive::MenuHelper.set_bool_action_checked(selecting_also_seeks);
|
||||
olive::MenuHelper.set_bool_action_checked(edit_tool_also_seeks);
|
||||
olive::MenuHelper.set_bool_action_checked(edit_tool_selects_links);
|
||||
olive::MenuHelper.set_bool_action_checked(seek_to_end_of_pastes);
|
||||
olive::MenuHelper.set_bool_action_checked(scroll_wheel_zooms);
|
||||
olive::MenuHelper.set_bool_action_checked(invert_timeline_scroll_axes);
|
||||
olive::MenuHelper.set_bool_action_checked(rectified_waveforms);
|
||||
olive::MenuHelper.set_bool_action_checked(enable_drag_files_to_timeline);
|
||||
olive::MenuHelper.set_bool_action_checked(autoscale_by_default);
|
||||
olive::MenuHelper.set_bool_action_checked(enable_seek_to_import);
|
||||
olive::MenuHelper.set_bool_action_checked(enable_audio_scrubbing);
|
||||
olive::MenuHelper.set_bool_action_checked(enable_drop_on_media_to_replace);
|
||||
olive::MenuHelper.set_bool_action_checked(enable_hover_focus);
|
||||
olive::MenuHelper.set_bool_action_checked(set_name_and_marker);
|
||||
olive::MenuHelper.set_bool_action_checked(seek_also_selects);
|
||||
|
||||
olive::MenuHelper.set_int_action_checked(no_autoscroll, olive::CurrentConfig.autoscroll);
|
||||
olive::MenuHelper.set_int_action_checked(page_autoscroll, olive::CurrentConfig.autoscroll);
|
||||
olive::MenuHelper.set_int_action_checked(smooth_autoscroll, olive::CurrentConfig.autoscroll);
|
||||
|
||||
+1
-14
@@ -328,21 +328,8 @@ private:
|
||||
QAction* hand_tool_action;
|
||||
QAction* transition_tool_action;
|
||||
QAction* snap_toggle;
|
||||
QAction* selecting_also_seeks;
|
||||
QAction* edit_tool_also_seeks;
|
||||
QAction* edit_tool_selects_links;
|
||||
QAction* seek_to_end_of_pastes;
|
||||
QAction* scroll_wheel_zooms;
|
||||
QAction* invert_timeline_scroll_axes;
|
||||
QAction* rectified_waveforms;
|
||||
QAction* enable_drag_files_to_timeline;
|
||||
QAction* autoscale_by_default;
|
||||
QAction* enable_seek_to_import;
|
||||
QAction* enable_audio_scrubbing;
|
||||
QAction* enable_drop_on_media_to_replace;
|
||||
QAction* enable_hover_focus;
|
||||
QAction* set_name_and_marker;
|
||||
QAction* seek_also_selects;
|
||||
QAction* autocut_silence_;
|
||||
QAction* preferences_action_;
|
||||
QAction* clear_undo_action_;
|
||||
|
||||
|
||||
+16
-1
@@ -118,11 +118,26 @@ void TimelineWidget::show_context_menu(const QPoint& pos) {
|
||||
|
||||
if (!selected_clips.isEmpty()) {
|
||||
|
||||
bool video_clips_are_selected = false;
|
||||
bool audio_clips_are_selected = false;
|
||||
|
||||
for (int i=0;i<selected_clips.size();i++) {
|
||||
if (selected_clips.at(i)->track() < 0) {
|
||||
video_clips_are_selected = true;
|
||||
} else {
|
||||
audio_clips_are_selected = true;
|
||||
}
|
||||
}
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
menu.addAction(tr("&Speed/Duration"), olive::Global.get(), SLOT(open_speed_dialog()));
|
||||
|
||||
QAction* autoscaleAction = menu.addAction(tr("Auto-s&cale"), this, SLOT(toggle_autoscale()));
|
||||
if (audio_clips_are_selected) {
|
||||
menu.addAction(tr("Auto-Cut Silence"), olive::Global.get(), SLOT(open_autocut_silence_dialog()));
|
||||
}
|
||||
|
||||
QAction* autoscaleAction = menu.addAction(tr("Auto-S&cale"), this, SLOT(toggle_autoscale()));
|
||||
autoscaleAction->setCheckable(true);
|
||||
// set autoscale to the first selected clip
|
||||
autoscaleAction->setChecked(selected_clips.at(0)->autoscaled());
|
||||
|
||||
Reference in New Issue
Block a user