merged with master
This commit is contained in:
@@ -26,7 +26,8 @@
|
||||
/**
|
||||
* @brief The AboutDialog class
|
||||
*
|
||||
* The About dialog (accessible through Help > About). Contains license and version information.
|
||||
* The About dialog (accessible through Help > About). Contains license and version information. This can be run from
|
||||
* anywhere
|
||||
*/
|
||||
class AboutDialog : public QDialog
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ class ActionSearchList;
|
||||
* @brief The ActionSearch class
|
||||
*
|
||||
* A popup window (accessible through Help > Action Search) that allows users to search for a menu command by typing
|
||||
* rather than browsing through the menu bar.
|
||||
* rather than browsing through the menu bar. This can be created from anywhere provided olive::MainWindow is valid.
|
||||
*/
|
||||
class ActionSearch : public QDialog
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
* @brief The AdvancedVideoDialog class
|
||||
*
|
||||
* A dialog for interfacing with VideoCodecParams, a struct for more advanced video settings sometimes specific to
|
||||
* one codec.
|
||||
* one codec. Primarily a companion to ExportDialog which will provide the VideoCodecParams reference,
|
||||
*/
|
||||
class AdvancedVideoDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
@@ -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
|
||||
@@ -30,7 +30,8 @@
|
||||
/**
|
||||
* @brief The ClipPropertiesDialog class
|
||||
*
|
||||
* A dialog for setting Clip properties, accessible by right clicking a Clip and clicking "Properties".
|
||||
* A dialog for setting Clip properties, accessible by right clicking a Clip and clicking "Properties". This can be
|
||||
* run from anywhere provided it's given a valid array of Clip objects.
|
||||
*/
|
||||
class ClipPropertiesDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
/**
|
||||
* @brief The DebugDialog class
|
||||
*
|
||||
* A dialog to display the current debug output.
|
||||
* A dialog to display the current debug output. This dialog is omnipresent and shown and hidden when the user wants
|
||||
* to see it. For efficiency, it will not update if it's hidden.
|
||||
*/
|
||||
class DebugDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
@@ -69,6 +70,9 @@ private:
|
||||
};
|
||||
|
||||
namespace olive {
|
||||
/**
|
||||
* @brief Omnipresent instance of DebugDialog to be shown or hidden as the user wants
|
||||
*/
|
||||
extern DebugDialog* DebugDialog;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,10 @@
|
||||
/**
|
||||
* @brief The DemoNotice class
|
||||
*
|
||||
* Simple dialog shown on startup to introduce Olive as alpha software (in release builds).
|
||||
* Simple dialog shown on startup to introduce Olive as alpha software (in release builds). Can be run from anywhere,
|
||||
* but there should be no reason to create it outside of the application launch.
|
||||
*
|
||||
* To be phased out as Olive gains maturity.
|
||||
*/
|
||||
class DemoNotice : public QDialog
|
||||
{
|
||||
|
||||
@@ -569,6 +569,9 @@ void ExportDialog::StartExport() {
|
||||
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 effects in effect controls (prevents UI threading issues)
|
||||
panel_effect_controls->Clear();
|
||||
|
||||
// Close all currently open clips
|
||||
close_active_clips(olive::ActiveSequence.get());
|
||||
|
||||
|
||||
@@ -35,7 +35,9 @@
|
||||
/**
|
||||
* @brief The ExportDialog class
|
||||
*
|
||||
* The dialog to initiate an export.
|
||||
* The dialog to initiate an export. Requires a valid Sequence to be set in olive::ActiveSequence or the result is
|
||||
* defined (most likely a crash), so you should always do a `nullptr` check on olive::ActiveSequence before constructing
|
||||
* this dialog.
|
||||
*/
|
||||
class ExportDialog : public QDialog
|
||||
{
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
/**
|
||||
* @brief The LoadDialog class
|
||||
*
|
||||
* Shows a modal dialog for loading a project. Designed to be connected to a LoadThread object.
|
||||
* Shows a modal dialog for loading a project. Designed to be connected to a LoadThread object. This dialog should
|
||||
* generally not be created directly, use OliveGlobal::LoadProject (or its variants) to correctly set up a LoadDialog
|
||||
* and LoadThread and connect them to each other.
|
||||
*/
|
||||
class LoadDialog : public QDialog
|
||||
{
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
/**
|
||||
* @brief The MediaPropertiesDialog class
|
||||
*
|
||||
* A dialog for setting properties on Media.
|
||||
* A dialog for setting properties on Media. This can be loaded from any part of the application provided it's given
|
||||
* a valid Media object.
|
||||
*/
|
||||
class MediaPropertiesDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
@@ -39,19 +39,26 @@
|
||||
#include "panels/timeline.h"
|
||||
#include "project/media.h"
|
||||
#include "rendering/audio.h"
|
||||
#include "global/config.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
NewSequenceDialog::NewSequenceDialog(QWidget *parent, Media *existing) :
|
||||
NewSequenceDialog::NewSequenceDialog(QWidget *parent, Media *existing, Sequence* iexisting_sequence) :
|
||||
QDialog(parent),
|
||||
existing_item(existing)
|
||||
existing_item(existing),
|
||||
existing_sequence(iexisting_sequence)
|
||||
{
|
||||
Q_ASSERT(!(existing != nullptr && iexisting_sequence != nullptr));
|
||||
|
||||
setup_ui();
|
||||
|
||||
if (existing != nullptr) {
|
||||
existing_sequence = existing->to_sequence();
|
||||
existing_sequence = existing->to_sequence().get();
|
||||
}
|
||||
|
||||
if (existing_sequence != nullptr) {
|
||||
setWindowTitle(tr("Editing \"%1\"").arg(existing_sequence->name));
|
||||
|
||||
width_numeric->setValue(existing_sequence->width);
|
||||
@@ -80,6 +87,12 @@ void NewSequenceDialog::set_sequence_name(const QString& s) {
|
||||
sequence_name_edit->setText(s);
|
||||
}
|
||||
|
||||
void NewSequenceDialog::SetNameEditable(bool enabled)
|
||||
{
|
||||
sequence_name_edit->setVisible(enabled);
|
||||
sequence_name_label->setVisible(enabled);
|
||||
}
|
||||
|
||||
void NewSequenceDialog::accept() {
|
||||
if (existing_sequence == nullptr) {
|
||||
|
||||
@@ -98,7 +111,7 @@ void NewSequenceDialog::accept() {
|
||||
panel_project->create_sequence_internal(ca, s, true, nullptr);
|
||||
olive::UndoStack.push(ca);
|
||||
|
||||
} else {
|
||||
} else if (existing_item != nullptr) {
|
||||
|
||||
// The dialog was given an existing Sequence object, so we'll apply the changes to it
|
||||
|
||||
@@ -106,7 +119,7 @@ void NewSequenceDialog::accept() {
|
||||
|
||||
double multiplier = frame_rate_combobox->currentData().toDouble() / existing_sequence->frame_rate;
|
||||
|
||||
EditSequenceCommand* esc = new EditSequenceCommand(existing_item, existing_sequence);
|
||||
EditSequenceCommand* esc = new EditSequenceCommand(existing_item, existing_item->to_sequence());
|
||||
esc->name = sequence_name_edit->text();
|
||||
esc->width = width_numeric->value();
|
||||
esc->height = height_numeric->value();
|
||||
@@ -123,6 +136,18 @@ void NewSequenceDialog::accept() {
|
||||
}
|
||||
|
||||
olive::UndoStack.push(ca);
|
||||
|
||||
} else if (existing_sequence != nullptr) {
|
||||
|
||||
// This dialog was given an existing Sequence without a Media wrapper - therefore just directly apply the settings
|
||||
|
||||
existing_sequence->name = sequence_name_edit->text();
|
||||
existing_sequence->width = width_numeric->value();
|
||||
existing_sequence->height = height_numeric->value();
|
||||
existing_sequence->frame_rate = frame_rate_combobox->currentData().toDouble();
|
||||
existing_sequence->audio_frequency = audio_frequency_combobox->currentData().toInt();
|
||||
existing_sequence->audio_layout = AV_CH_LAYOUT_STEREO;
|
||||
|
||||
}
|
||||
|
||||
QDialog::accept();
|
||||
@@ -210,13 +235,13 @@ void NewSequenceDialog::setup_ui() {
|
||||
videoLayout->addWidget(new QLabel(tr("Width:"), this), 0, 0, 1, 1);
|
||||
width_numeric = new QSpinBox(videoGroupBox);
|
||||
width_numeric->setMaximum(9999);
|
||||
width_numeric->setValue(1920);
|
||||
width_numeric->setValue(olive::CurrentConfig.default_sequence_width);
|
||||
videoLayout->addWidget(width_numeric, 0, 2, 1, 2);
|
||||
|
||||
videoLayout->addWidget(new QLabel(tr("Height:"), this), 1, 0, 1, 2);
|
||||
height_numeric = new QSpinBox(videoGroupBox);
|
||||
height_numeric->setMaximum(9999);
|
||||
height_numeric->setValue(1080);
|
||||
height_numeric->setValue(olive::CurrentConfig.default_sequence_height);
|
||||
videoLayout->addWidget(height_numeric, 1, 2, 1, 2);
|
||||
|
||||
videoLayout->addWidget(new QLabel(tr("Frame Rate:"), this), 2, 0, 1, 1);
|
||||
@@ -232,7 +257,11 @@ void NewSequenceDialog::setup_ui() {
|
||||
frame_rate_combobox->addItem("50 FPS", 50.0);
|
||||
frame_rate_combobox->addItem("59.94 FPS", 59.94);
|
||||
frame_rate_combobox->addItem("60 FPS", 60.0);
|
||||
frame_rate_combobox->setCurrentIndex(6);
|
||||
for (int i=0;i<frame_rate_combobox->count();i++) {
|
||||
if (qFuzzyCompare(frame_rate_combobox->itemData(i).toDouble(), olive::CurrentConfig.default_sequence_framerate)) {
|
||||
frame_rate_combobox->setCurrentIndex(i);
|
||||
}
|
||||
}
|
||||
videoLayout->addWidget(frame_rate_combobox, 2, 2, 1, 2);
|
||||
|
||||
videoLayout->addWidget(new QLabel(tr("Pixel Aspect Ratio:"), this), 4, 0, 1, 1);
|
||||
@@ -258,7 +287,11 @@ void NewSequenceDialog::setup_ui() {
|
||||
|
||||
audio_frequency_combobox = new QComboBox(audioGroupBox);
|
||||
combobox_audio_sample_rates(audio_frequency_combobox);
|
||||
audio_frequency_combobox->setCurrentIndex(4);
|
||||
for (int i=0;i<audio_frequency_combobox->count();i++) {
|
||||
if (audio_frequency_combobox->itemData(i) == olive::CurrentConfig.default_sequence_audio_frequency) {
|
||||
audio_frequency_combobox->setCurrentIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
audioLayout->addWidget(audio_frequency_combobox, 0, 1, 1, 1);
|
||||
|
||||
@@ -268,7 +301,8 @@ void NewSequenceDialog::setup_ui() {
|
||||
QHBoxLayout* nameLayout = new QHBoxLayout(nameWidget);
|
||||
nameLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
nameLayout->addWidget(new QLabel(tr("Name:"), this));
|
||||
sequence_name_label = new QLabel(tr("Name:"));
|
||||
nameLayout->addWidget(sequence_name_label);
|
||||
|
||||
sequence_name_edit = new QLineEdit(nameWidget);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
/**
|
||||
* @brief The NewSequenceDialog class
|
||||
*
|
||||
* A dialog that creates a new (or edits an existing) Sequence object.
|
||||
* A dialog that creates a new (or edits an existing) Sequence object. Can be run from any part of the application.
|
||||
*/
|
||||
class NewSequenceDialog : public QDialog
|
||||
{
|
||||
@@ -50,8 +50,13 @@ public:
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @param existing_sequence
|
||||
*
|
||||
* If your Sequence object is not wrapped in a Media object, use this to reference a raw Sequence pointer. You must
|
||||
* not use both existing_sequence AND existing - one must be nullptr.
|
||||
*/
|
||||
explicit NewSequenceDialog(QWidget *parent = nullptr, Media* existing = nullptr);
|
||||
explicit NewSequenceDialog(QWidget *parent = nullptr, Media* existing = nullptr, Sequence* iexisting_sequence = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Set the name for the new Sequence
|
||||
@@ -68,6 +73,17 @@ public:
|
||||
*/
|
||||
void set_sequence_name(const QString& s);
|
||||
|
||||
/**
|
||||
* @brief Set whether the Sequence's name can be edited
|
||||
*
|
||||
* This defaults to TRUE.
|
||||
*
|
||||
* @param enabled
|
||||
*
|
||||
* TRUE to allow the user to edit the Sequence's name. FALSE if not.
|
||||
*/
|
||||
void SetNameEditable(bool enabled);
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief Override accept function to create/edit a Sequence
|
||||
@@ -86,16 +102,16 @@ private slots:
|
||||
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 reference to an existing Sequence (if one was provided to the constructor)
|
||||
*/
|
||||
Sequence* existing_sequence;
|
||||
|
||||
/**
|
||||
* @brief Internal function to create the dialog's UI
|
||||
*/
|
||||
@@ -136,6 +152,13 @@ private:
|
||||
*/
|
||||
QComboBox* audio_frequency_combobox;
|
||||
|
||||
/**
|
||||
* @brief Label marker for setting the Sequence's name
|
||||
*
|
||||
* Primarily a persistent class reference so it can be hidden with SetNameEditable() alongside sequence_name_edit.
|
||||
*/
|
||||
QLabel* sequence_name_label;
|
||||
|
||||
/**
|
||||
* @brief Line edit to set the Sequence's name
|
||||
*/
|
||||
|
||||
+121
-28
@@ -50,7 +50,9 @@
|
||||
#include "rendering/audio.h"
|
||||
#include "rendering/bitdepths.h"
|
||||
#include "panels/panels.h"
|
||||
#include "ui/columnedgridlayout.h"
|
||||
#include "ui/mainwindow.h"
|
||||
#include "dialogs/newsequencedialog.h"
|
||||
|
||||
KeySequenceEditor::KeySequenceEditor(QWidget* parent, QAction* a)
|
||||
: QKeySequenceEdit(parent), action(a) {
|
||||
@@ -59,7 +61,6 @@ KeySequenceEditor::KeySequenceEditor(QWidget* parent, QAction* a)
|
||||
|
||||
void KeySequenceEditor::set_action_shortcut() {
|
||||
action->setShortcut(keySequence());
|
||||
action->setShortcutContext(Qt::ApplicationShortcut);
|
||||
}
|
||||
|
||||
void KeySequenceEditor::reset_to_default() {
|
||||
@@ -73,7 +74,7 @@ QString KeySequenceEditor::action_name() {
|
||||
QString KeySequenceEditor::export_shortcut() {
|
||||
QString ks = keySequence().toString();
|
||||
if (ks != action->property("default")) {
|
||||
return action->property("id").toString() + "\t" + keySequence().toString();
|
||||
return action->property("id").toString() + "\t" + ks;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -82,12 +83,18 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("Preferences"));
|
||||
|
||||
setup_ui();
|
||||
|
||||
recordingComboBox->setCurrentIndex(olive::CurrentConfig.recording_mode - 1);
|
||||
imgSeqFormatEdit->setText(olive::CurrentConfig.img_seq_formats);
|
||||
|
||||
setup_kbd_shortcuts(olive::MainWindow->menuBar());
|
||||
|
||||
// set up default sequence
|
||||
default_sequence.name = tr("Default Sequence");
|
||||
default_sequence.width = olive::CurrentConfig.default_sequence_width;
|
||||
default_sequence.height = olive::CurrentConfig.default_sequence_height;
|
||||
default_sequence.frame_rate = olive::CurrentConfig.default_sequence_framerate;
|
||||
default_sequence.audio_frequency = olive::CurrentConfig.default_sequence_audio_frequency;
|
||||
default_sequence.audio_layout = olive::CurrentConfig.default_sequence_audio_channel_layout;
|
||||
}
|
||||
|
||||
void PreferencesDialog::setup_kbd_shortcut_worker(QMenu* menu, QTreeWidgetItem* parent) {
|
||||
@@ -235,6 +242,15 @@ void PreferencesDialog::update_ocio_config(const QString &s)
|
||||
}
|
||||
#endif
|
||||
|
||||
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();
|
||||
|
||||
@@ -299,13 +315,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()
|
||||
#ifdef Q_OS_WIN32
|
||||
|| olive::CurrentConfig.use_native_menu_styling != native_menus->isChecked()
|
||||
#endif
|
||||
|| olive::CurrentConfig.css_path != custom_css_fn->text()
|
||||
|| 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
|
||||
@@ -346,25 +369,19 @@ void PreferencesDialog::accept() {
|
||||
}
|
||||
|
||||
// save settings from UI to backend
|
||||
if (olive::CurrentConfig.css_path != custom_css_fn->text()) {
|
||||
olive::CurrentConfig.css_path = custom_css_fn->text();
|
||||
olive::MainWindow->Restyle();
|
||||
}
|
||||
|
||||
olive::CurrentConfig.css_path = custom_css_fn->text();
|
||||
olive::CurrentConfig.recording_mode = recordingComboBox->currentIndex() + 1;
|
||||
olive::CurrentConfig.img_seq_formats = imgSeqFormatEdit->text();
|
||||
olive::CurrentConfig.upcoming_queue_size = upcoming_queue_spinbox->value();
|
||||
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.enable_color_management = enable_color_management->isChecked();
|
||||
@@ -394,10 +411,17 @@ void PreferencesDialog::accept() {
|
||||
#endif
|
||||
|
||||
|
||||
olive::CurrentConfig.default_sequence_width = default_sequence.width;
|
||||
olive::CurrentConfig.default_sequence_height = default_sequence.height;
|
||||
olive::CurrentConfig.default_sequence_framerate = default_sequence.frame_rate;
|
||||
olive::CurrentConfig.default_sequence_audio_frequency = default_sequence.audio_frequency;
|
||||
olive::CurrentConfig.default_sequence_audio_channel_layout = default_sequence.audio_layout;
|
||||
|
||||
for (int i=0;i<bool_ui.size();i++) {
|
||||
*bool_value[i] = bool_ui.at(i)->isChecked();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// Check if the thumbnail or waveform icon
|
||||
if (olive::CurrentConfig.thumbnail_resolution != thumbnail_res_spinbox->value()
|
||||
@@ -615,6 +639,13 @@ void PreferencesDialog::delete_all_previews() {
|
||||
}
|
||||
}
|
||||
|
||||
void PreferencesDialog::edit_default_sequence_settings()
|
||||
{
|
||||
NewSequenceDialog nsd(this, nullptr, &default_sequence);
|
||||
nsd.SetNameEditable(false);
|
||||
nsd.exec();
|
||||
}
|
||||
|
||||
void PreferencesDialog::setup_ui() {
|
||||
QVBoxLayout* verticalLayout = new QVBoxLayout(this);
|
||||
QTabWidget* tabWidget = new QTabWidget(this);
|
||||
@@ -696,15 +727,15 @@ 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++;
|
||||
|
||||
// General -> Default Sequence Settings
|
||||
QPushButton* default_sequence_settings = new QPushButton(tr("Default Sequence Settings"));
|
||||
connect(default_sequence_settings, SIGNAL(clicked(bool)), this, SLOT(edit_default_sequence_settings()));
|
||||
general_layout->addWidget(default_sequence_settings);
|
||||
|
||||
tabWidget->addTab(general_tab, tr("General"));
|
||||
@@ -713,11 +744,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);
|
||||
|
||||
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);
|
||||
@@ -743,8 +835,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, true);
|
||||
appearance_layout->addWidget(native_menus, row, 0, 1, 3);
|
||||
|
||||
row++;
|
||||
@@ -879,6 +971,7 @@ void PreferencesDialog::setup_ui() {
|
||||
recordingComboBox = new QComboBox(general_tab);
|
||||
recordingComboBox->addItem(tr("Mono"));
|
||||
recordingComboBox->addItem(tr("Stereo"));
|
||||
recordingComboBox->setCurrentIndex(olive::CurrentConfig.recording_mode - 1);
|
||||
audio_tab_layout->addWidget(recordingComboBox, row, 1);
|
||||
|
||||
row++;
|
||||
|
||||
+193
-7
@@ -45,7 +45,8 @@ class KeySequenceEditor;
|
||||
/**
|
||||
* @brief The PreferencesDialog class
|
||||
*
|
||||
* A dialog for the global application settings. Mostly an interface for Config.
|
||||
* A dialog for the global application settings. Mostly an interface for Config. Can be loaded from any part of the
|
||||
* application.
|
||||
*/
|
||||
class PreferencesDialog : public QDialog
|
||||
{
|
||||
@@ -130,6 +131,11 @@ private slots:
|
||||
void update_ocio_config(const QString&);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Shows a NewSequenceDialog attached to default_sequence
|
||||
*/
|
||||
void edit_default_sequence_settings();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
@@ -186,23 +192,81 @@ private:
|
||||
void populate_ocio_menus(OCIO::ConstConfigRcPtr config);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the CSS filename
|
||||
*/
|
||||
QLineEdit* custom_css_fn;
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the list of extensions to detect image sequences from
|
||||
*/
|
||||
QLineEdit* imgSeqFormatEdit;
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the recording channels
|
||||
*/
|
||||
QComboBox* recordingComboBox;
|
||||
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing keyboard shortcuts
|
||||
*/
|
||||
QTreeWidget* keyboard_tree;
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the upcoming queue size
|
||||
*/
|
||||
QDoubleSpinBox* upcoming_queue_spinbox;
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the upcoming queue type
|
||||
*/
|
||||
QComboBox* upcoming_queue_type;
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the previous queue size
|
||||
*/
|
||||
QDoubleSpinBox* previous_queue_spinbox;
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the previous queue type
|
||||
*/
|
||||
QComboBox* previous_queue_type;
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the size of textboxes in the EffectControls panel
|
||||
*/
|
||||
QSpinBox* effect_textbox_lines_field;
|
||||
QCheckBox* use_software_fallbacks_checkbox;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the output audio device
|
||||
*/
|
||||
QComboBox* audio_output_devices;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the input audio device
|
||||
*/
|
||||
QComboBox* audio_input_devices;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the audio sampling rates
|
||||
*/
|
||||
QComboBox* audio_sample_rate;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the UI language
|
||||
*/
|
||||
QComboBox* language_combobox;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the resolution of the thumbnails to generate
|
||||
*/
|
||||
QSpinBox* thumbnail_res_spinbox;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the resolution of the waveforms to generate
|
||||
*/
|
||||
QSpinBox* waveform_res_spinbox;
|
||||
QCheckBox* add_default_effects_to_clips;
|
||||
|
||||
QCheckBox* enable_color_management;
|
||||
QLineEdit* ocio_config_file;
|
||||
@@ -210,26 +274,148 @@ private:
|
||||
QComboBox* ocio_view;
|
||||
QComboBox* ocio_look;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the current UI style
|
||||
*/
|
||||
QComboBox* ui_style;
|
||||
Sequence sequence_settings;
|
||||
#ifdef Q_OS_WIN
|
||||
QCheckBox* native_menus;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Stored default Sequence object
|
||||
*
|
||||
* Default Sequence settings are loaded into an actual Sequence object that can be loaded into NewSequenceDialog
|
||||
* for the sake of familiarity with the user.
|
||||
*/
|
||||
Sequence default_sequence;
|
||||
|
||||
/**
|
||||
* @brief List of keyboard shortcut actions that can be triggered (links with key_shortcut_items and
|
||||
* key_shortcut_fields)
|
||||
*/
|
||||
QVector<QAction*> key_shortcut_actions;
|
||||
|
||||
/**
|
||||
* @brief List of keyboard shortcut items in keyboard_tree corresponding to existing actions (links with
|
||||
* key_shortcut_actions and key_shortcut_fields)
|
||||
*/
|
||||
QVector<QTreeWidgetItem*> key_shortcut_items;
|
||||
|
||||
/**
|
||||
* @brief List of keyboard shortcut editing fields in keyboard_tree corresponding to existing actions (links with
|
||||
* 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;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The KeySequenceEditor class
|
||||
*
|
||||
* Simple derived class of QKeySequenceEdit that attaches to a QAction and provides functions for transferring
|
||||
* keyboard shortcuts to and from it.
|
||||
*/
|
||||
class KeySequenceEditor : public QKeySequenceEdit {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief KeySequenceEditor Constructor
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* QWidget parent.
|
||||
*
|
||||
* @param a
|
||||
*
|
||||
* The QAction to link to. This cannot be changed throughout the lifetime of a KeySequenceEditor.
|
||||
*/
|
||||
KeySequenceEditor(QWidget *parent, QAction* a);
|
||||
|
||||
/**
|
||||
* @brief Sets the attached QAction's shortcut to the shortcut entered in this field.
|
||||
*
|
||||
* This is not done automatically in case the user cancels out of the Preferences dialog, in which case the
|
||||
* expectation is that the changes made will not be saved. Therefore, this needs to be triggered manually when
|
||||
* PreferencesDialog saves.
|
||||
*/
|
||||
void set_action_shortcut();
|
||||
|
||||
/**
|
||||
* @brief Set this shortcut back to the QAction's default shortcut
|
||||
*
|
||||
* Each QAction contains the default shortcut in its `property("default")` and can be used to restore the default
|
||||
* "hard-coded" shortcut with this function.
|
||||
*
|
||||
* This function does not save the default shortcut back into the QAction, it simply loads the default shortcut from
|
||||
* the QAction into this edit field. To save it into the QAction, it's necessary to call set_action_shortcut() after
|
||||
* calling this function.
|
||||
*/
|
||||
void reset_to_default();
|
||||
|
||||
/**
|
||||
* @brief Return attached QAction's unique ID
|
||||
*
|
||||
* Each of Olive's menu actions has a unique string ID (that, unlike the text, is not translated) for matching with
|
||||
* an external shortcut configuration file. The ID is stored in the QAction's `property("id")`. This function returns
|
||||
* that ID.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* The QAction's unique ID.
|
||||
*/
|
||||
QString action_name();
|
||||
|
||||
/**
|
||||
* @brief Serialize this shortcut entry into a string that can be saved to a file
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* A string serialization of this shortcut. The format is "[ID]\t[SEQUENCE]" where [ID] is the attached QAction's
|
||||
* unique identifier and [SEQUENCE] is the current keyboard shortcut in the field (NOT necessarily the shortcut in
|
||||
* the QAction). If the entered shortcut is the same as the QAction's default shortcut, the return value is empty
|
||||
* because a default shortcut does not need to be saved to a file.
|
||||
*/
|
||||
QString export_shortcut();
|
||||
private:
|
||||
/**
|
||||
* @brief Internal reference to the linked QAction
|
||||
*/
|
||||
QAction* action;
|
||||
};
|
||||
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
/**
|
||||
* @brief The ProxyDialog class
|
||||
*
|
||||
* Dialog to set up proxy generation of footage
|
||||
* Dialog to set up proxy generation of footage. This dialog can be called from anywhere provided it's given a valid
|
||||
* array of Media and will start all proxy generation.
|
||||
*/
|
||||
class ProxyDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
@@ -50,16 +50,16 @@ ReplaceClipMediaDialog::ReplaceClipMediaDialog(QWidget *parent, Media* old_media
|
||||
use_same_media_in_points->setChecked(true);
|
||||
layout->addWidget(use_same_media_in_points);
|
||||
|
||||
QHBoxLayout* buttons = new QHBoxLayout();
|
||||
QHBoxLayout* buttons = new QHBoxLayout();
|
||||
|
||||
buttons->addStretch();
|
||||
|
||||
QPushButton* replace_button = new QPushButton(tr("Replace"), this);
|
||||
connect(replace_button, SIGNAL(clicked(bool)), this, SLOT(replace()));
|
||||
connect(replace_button, SIGNAL(clicked(bool)), this, SLOT(accept()));
|
||||
buttons->addWidget(replace_button);
|
||||
|
||||
QPushButton* cancel_button = new QPushButton(tr("Cancel"), this);
|
||||
connect(cancel_button, SIGNAL(clicked(bool)), this, SLOT(close()));
|
||||
connect(cancel_button, SIGNAL(clicked(bool)), this, SLOT(reject()));
|
||||
buttons->addWidget(cancel_button);
|
||||
|
||||
buttons->addStretch();
|
||||
@@ -69,7 +69,7 @@ ReplaceClipMediaDialog::ReplaceClipMediaDialog(QWidget *parent, Media* old_media
|
||||
tree->setModel(&olive::project_model);
|
||||
}
|
||||
|
||||
void ReplaceClipMediaDialog::replace() {
|
||||
void ReplaceClipMediaDialog::accept() {
|
||||
QModelIndexList selected_items = tree->selectionModel()->selectedRows();
|
||||
if (selected_items.size() != 1) {
|
||||
QMessageBox::critical(
|
||||
@@ -77,23 +77,23 @@ void ReplaceClipMediaDialog::replace() {
|
||||
tr("No media selected"),
|
||||
tr("Please select a media to replace with or click 'Cancel'."),
|
||||
QMessageBox::Ok
|
||||
);
|
||||
);
|
||||
} else {
|
||||
Media* new_item = static_cast<Media*>(selected_items.at(0).internalPointer());
|
||||
Media* new_item = static_cast<Media*>(selected_items.at(0).internalPointer());
|
||||
if (media == new_item) {
|
||||
QMessageBox::critical(
|
||||
this,
|
||||
tr("Same media selected"),
|
||||
tr("You selected the same media that you're replacing. Please select a different one or click 'Cancel'."),
|
||||
QMessageBox::Ok
|
||||
);
|
||||
);
|
||||
} else if (new_item->get_type() == MEDIA_TYPE_FOLDER) {
|
||||
QMessageBox::critical(
|
||||
this,
|
||||
tr("Folder selected"),
|
||||
tr("You cannot replace footage with a folder."),
|
||||
QMessageBox::Ok
|
||||
);
|
||||
);
|
||||
} else {
|
||||
if (new_item->get_type() == MEDIA_TYPE_SEQUENCE && olive::ActiveSequence == new_item->to_sequence()) {
|
||||
QMessageBox::critical(
|
||||
@@ -101,16 +101,16 @@ void ReplaceClipMediaDialog::replace() {
|
||||
tr("Active sequence selected"),
|
||||
tr("You cannot insert a sequence into itself."),
|
||||
QMessageBox::Ok
|
||||
);
|
||||
);
|
||||
} else {
|
||||
ReplaceClipMediaCommand* rcmc = new ReplaceClipMediaCommand(
|
||||
media,
|
||||
new_item,
|
||||
use_same_media_in_points->isChecked()
|
||||
);
|
||||
);
|
||||
|
||||
for (int i=0;i<olive::ActiveSequence->clips.size();i++) {
|
||||
ClipPtr c = olive::ActiveSequence->clips.at(i);
|
||||
ClipPtr c = olive::ActiveSequence->clips.at(i);
|
||||
if (c != nullptr && c->media() == media) {
|
||||
rcmc->clips.append(c);
|
||||
}
|
||||
@@ -118,7 +118,7 @@ void ReplaceClipMediaDialog::replace() {
|
||||
|
||||
olive::UndoStack.push(rcmc);
|
||||
|
||||
close();
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,15 +28,54 @@
|
||||
#include "ui/sourcetable.h"
|
||||
#include "project/projectelements.h"
|
||||
|
||||
/**
|
||||
* @brief The ReplaceClipMediaDialog class
|
||||
*
|
||||
* A dialog to replace all Clips using a certain Media with a different Media. This dialog can be run from anywhere
|
||||
* provided it's given a valid Media object.
|
||||
*/
|
||||
class ReplaceClipMediaDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ReplaceClipMediaDialog(QWidget* parent, Media* old_media);
|
||||
/**
|
||||
* @brief ReplaceClipMediaDialog Constructor
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* QWidget parent. Usually MainWindow or Project panel.
|
||||
*
|
||||
* @param old_media
|
||||
*
|
||||
* A valid Media object which will be used to scan the currently active Sequence for Clips using it.
|
||||
*/
|
||||
ReplaceClipMediaDialog(QWidget* parent, Media* old_media);
|
||||
private slots:
|
||||
void replace();
|
||||
/**
|
||||
* @brief Overrided accept for when the user clicks "Replace"
|
||||
*
|
||||
* Checks whether the requested replace is valid using the following criteria:
|
||||
* * Any Media is selected
|
||||
* * The selected Media is not the same Media that the user is trying to replace
|
||||
* * The Media is not a folder
|
||||
* * The Media is not the currently active Sequence
|
||||
*/
|
||||
virtual void accept() override;
|
||||
private:
|
||||
Media* media;
|
||||
/**
|
||||
* @brief Internal pointer to the Media we're replacing
|
||||
*/
|
||||
Media* media;
|
||||
|
||||
/**
|
||||
* @brief Tree widget to show Project's media
|
||||
*/
|
||||
QTreeView* tree;
|
||||
|
||||
/**
|
||||
* @brief CheckBox for using the same media in points
|
||||
*
|
||||
* When the starting point of a Clip is trimmed (i.e. the Clip no longer starts at 0),
|
||||
*/
|
||||
QCheckBox* use_same_media_in_points;
|
||||
};
|
||||
|
||||
|
||||
@@ -85,16 +85,16 @@ SpeedDialog::SpeedDialog(QWidget *parent, QVector<Clip*> clips) : QDialog(parent
|
||||
connect(duration, SIGNAL(valueChanged(double)), this, SLOT(duration_update()));
|
||||
}
|
||||
|
||||
void SpeedDialog::run() {
|
||||
int SpeedDialog::exec() {
|
||||
bool enable_frame_rate = false;
|
||||
bool multiple_audio = false;
|
||||
maintain_pitch->setEnabled(false);
|
||||
|
||||
default_frame_rate = qSNaN();
|
||||
current_frame_rate = qSNaN();
|
||||
current_percent = qSNaN();
|
||||
default_length = -1;
|
||||
current_length = -1;
|
||||
double default_frame_rate = qSNaN();
|
||||
double current_frame_rate = qSNaN();
|
||||
double current_percent = qSNaN();
|
||||
long default_length = -1;
|
||||
long current_length = -1;
|
||||
|
||||
for (int i=0;i<clips_.size();i++) {
|
||||
Clip* c = clips_.at(i);
|
||||
@@ -180,7 +180,7 @@ void SpeedDialog::run() {
|
||||
duration->SetDefault(default_length);
|
||||
duration->SetValue((current_length == -1) ? qSNaN() : current_length);
|
||||
|
||||
exec();
|
||||
return QDialog::exec();
|
||||
}
|
||||
|
||||
void SpeedDialog::percent_update() {
|
||||
|
||||
+82
-10
@@ -27,34 +27,106 @@
|
||||
#include "timeline/clip.h"
|
||||
#include "ui/labelslider.h"
|
||||
|
||||
/**
|
||||
* @brief The SpeedDialog class
|
||||
*
|
||||
* A dialog for setting the speed of one or more Clips. This can be run from anywhere provided it's given a valid
|
||||
* array of Clips.
|
||||
*
|
||||
* It's preferable ot
|
||||
*/
|
||||
class SpeedDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief SpeedDialog Constructor
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* QWidget parent. Usually MainWindow or Timeline panel.
|
||||
*
|
||||
* @param clips
|
||||
*
|
||||
* A valid array of Clips to change the speed of.
|
||||
*/
|
||||
SpeedDialog(QWidget* parent, QVector<Clip*> clips);
|
||||
|
||||
void run();
|
||||
public slots:
|
||||
/**
|
||||
* @brief Override of exec() to set up current Clip speed data just before opening
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* The result of QDialog::exec(), a DialogCode result.
|
||||
*/
|
||||
virtual int exec() override;
|
||||
private slots:
|
||||
/**
|
||||
* @brief Override of accept() to perform the selected changes on the Clips
|
||||
*/
|
||||
virtual void accept() override;
|
||||
|
||||
/**
|
||||
* @brief Slot when the speed percentage field is changed by the user
|
||||
*
|
||||
* The three fields (percent, duration, and frame rate) all work in tandem to create a speed multipler for the
|
||||
* Clip. Each has a slot for when one of the fields changes to update the others appropriately so they all have the
|
||||
* same speed multipler.
|
||||
*/
|
||||
void percent_update();
|
||||
|
||||
/**
|
||||
* @brief Slot when the duration field is changed by the user
|
||||
*
|
||||
* The three fields (percent, duration, and frame rate) all work in tandem to create a speed multipler for the
|
||||
* Clip. Each has a slot for when one of the fields changes to update the others appropriately so they all have the
|
||||
* same speed multipler.
|
||||
*/
|
||||
void duration_update();
|
||||
|
||||
/**
|
||||
* @brief Slot when the frame rate field is changed by the user
|
||||
*
|
||||
* The three fields (percent, duration, and frame rate) all work in tandem to create a speed multipler for the
|
||||
* Clip. Each has a slot for when one of the fields changes to update the others appropriately so they all have the
|
||||
* same speed multipler.
|
||||
*/
|
||||
void frame_rate_update();
|
||||
void accept();
|
||||
private:
|
||||
/**
|
||||
* @brief Internal array of Clip objects
|
||||
*/
|
||||
QVector<Clip*> clips_;
|
||||
|
||||
/**
|
||||
* @brief Speed percentage field
|
||||
*/
|
||||
LabelSlider* percent;
|
||||
|
||||
/**
|
||||
* @brief Duration field
|
||||
*/
|
||||
LabelSlider* duration;
|
||||
|
||||
/**
|
||||
* @brief Frame rate field
|
||||
*/
|
||||
LabelSlider* frame_rate;
|
||||
|
||||
/**
|
||||
* @brief UI widget for setting the Clip's reverse value
|
||||
*/
|
||||
QCheckBox* reverse;
|
||||
QCheckBox* maintain_pitch;
|
||||
QCheckBox* ripple;
|
||||
|
||||
double default_frame_rate;
|
||||
double current_frame_rate;
|
||||
double current_percent;
|
||||
long default_length;
|
||||
long current_length;
|
||||
/**
|
||||
* @brief UI widget for setting the Clip's maintain pitch value
|
||||
*/
|
||||
QCheckBox* maintain_pitch;
|
||||
|
||||
/**
|
||||
* @brief UI widget for setting whether to ripple Clips around these changes or not
|
||||
*/
|
||||
QCheckBox* ripple;
|
||||
};
|
||||
|
||||
#endif // SPEEDDIALOG_H
|
||||
|
||||
@@ -44,15 +44,6 @@ TextEditDialog::TextEditDialog(QWidget *parent, const QString &s, bool rich_text
|
||||
if (rich_text) {
|
||||
QHBoxLayout* toolbar = new QHBoxLayout();
|
||||
|
||||
// Bold Button
|
||||
/*
|
||||
bold_button = new QPushButton();
|
||||
bold_button->setIcon(olive::icon::CreateIconFromSVG(":/icons/bold.svg", false));
|
||||
bold_button->setCheckable(true);
|
||||
connect(bold_button, SIGNAL(clicked(bool)), this, SLOT(SetBold(bool)));
|
||||
toolbar->addWidget(bold_button);
|
||||
*/
|
||||
|
||||
// Italic Button
|
||||
italic_button = new QPushButton();
|
||||
italic_button->setIcon(olive::icon::CreateIconFromSVG(":/icons/italic.svg", false));
|
||||
@@ -156,10 +147,14 @@ TextEditDialog::TextEditDialog(QWidget *parent, const QString &s, bool rich_text
|
||||
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
|
||||
buttons->setCenterButtons(true);
|
||||
layout->addWidget(buttons);
|
||||
connect(buttons, SIGNAL(accepted()), this, SLOT(save()));
|
||||
connect(buttons, SIGNAL(rejected()), this, SLOT(cancel()));
|
||||
connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
|
||||
// Connect the cursor position changing to the rich text toolbar buttons updating (so for example, when italic text
|
||||
// is selected, the italic button will be pressed)
|
||||
connect(textEdit, SIGNAL(cursorPositionChanged()), this, SLOT(UpdateUIFromTextCursor()));
|
||||
|
||||
// Set the widget's text based on the rich text mode
|
||||
if (rich_text_) {
|
||||
textEdit->setHtml(s);
|
||||
} else {
|
||||
@@ -167,7 +162,7 @@ TextEditDialog::TextEditDialog(QWidget *parent, const QString &s, bool rich_text
|
||||
}
|
||||
|
||||
// Helps ensure the UI elements update correctly at the beginning - when the cursor is at the start, the UI elements
|
||||
// show up blank...
|
||||
// show up blank. Setting it to the end is probably more expected behavior anyway.
|
||||
textEdit->moveCursor(QTextCursor::End);
|
||||
}
|
||||
|
||||
@@ -175,21 +170,9 @@ const QString& TextEditDialog::get_string() {
|
||||
return result_str;
|
||||
}
|
||||
|
||||
void TextEditDialog::save() {
|
||||
void TextEditDialog::accept() {
|
||||
result_str = rich_text_ ? textEdit->toHtml() : textEdit->toPlainText();
|
||||
accept();
|
||||
}
|
||||
|
||||
void TextEditDialog::cancel() {
|
||||
reject();
|
||||
}
|
||||
|
||||
void TextEditDialog::SetBold(bool bold)
|
||||
{
|
||||
QFont f = textEdit->currentFont();
|
||||
f.setBold(bold);
|
||||
textEdit->setCurrentFont(f);
|
||||
UpdateUIFromTextCursor();
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void TextEditDialog::SetFontWeight(int i)
|
||||
@@ -197,13 +180,6 @@ void TextEditDialog::SetFontWeight(int i)
|
||||
textEdit->setFontWeight(font_weight->itemData(i).toInt());
|
||||
}
|
||||
|
||||
void TextEditDialog::SetLetterSpacing(qreal spacing)
|
||||
{
|
||||
QFont f = textEdit->currentFont();
|
||||
f.setLetterSpacing(f.letterSpacingType(), spacing);
|
||||
textEdit->setCurrentFont(f);
|
||||
}
|
||||
|
||||
void TextEditDialog::SetAlignmentFromProperty()
|
||||
{
|
||||
textEdit->setAlignment(static_cast<Qt::Alignment>(sender()->property("a").toInt()));
|
||||
|
||||
+123
-8
@@ -28,36 +28,151 @@
|
||||
#include "ui/labelslider.h"
|
||||
#include "ui/colorbutton.h"
|
||||
|
||||
/**
|
||||
* @brief The TextEditDialog class
|
||||
*
|
||||
* A separate window for editing text. This window can be resized arbitrarily and also provides a toolbar for rich text
|
||||
* editing (if rich text is enabled). This dialog can be run from anywhere. Once the dialog has closed (i.e. returned
|
||||
* from exec() ), the text entered into it can be retrieved using get_string().
|
||||
*
|
||||
* TODO: Add a live signal for updating the calling function.
|
||||
*/
|
||||
class TextEditDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief TextEditDialog Constructor
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* QWidget parent. Usually MainWindow.
|
||||
*
|
||||
* @param s
|
||||
*
|
||||
* The starting string when the dialog opens. It'll be read as rich text HTML or plain text based on the `rich_text`
|
||||
* parameter (which defaults to rich text HTML). It can also be left empty to start blank.
|
||||
*
|
||||
* @param rich_text
|
||||
*
|
||||
* Set the editing mode of the editor. If TRUE, the dialog will interpret the string in `s` as rich text HTML and also
|
||||
* return rich text HTML through get_string(). It'll also show a toolbar with rich text options (i.e. font, italic,
|
||||
* underline, size, etc.) If FALSE, the dialog will run in plain text mode interpreting the string in `s` as plain
|
||||
* text and returning plain text through get_string(). It also will not show the rich text editing toolbar.
|
||||
*/
|
||||
TextEditDialog(QWidget* parent = nullptr, const QString& s = nullptr, bool rich_text = true);
|
||||
const QString& get_string();
|
||||
signals:
|
||||
void cursorPositionChanged();
|
||||
private slots:
|
||||
void save();
|
||||
void cancel();
|
||||
|
||||
void SetBold(bool bold);
|
||||
/**
|
||||
* @brief Retrieve the current text in the dialog
|
||||
*
|
||||
* This function can be called after the user has accepted the dialog (i.e. made changes and clicked OK).
|
||||
* This will return either plain text or rich text (HTML) depending on the mode it's running in (rich/plain text mode
|
||||
* is set in the constructor). The value this returns only gets updated when the user clicks OK so it cannot be
|
||||
* used to retrieve live text updates from the dialog.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* The text entered once the user accepted this dialog.
|
||||
*/
|
||||
const QString& get_string();
|
||||
private slots:
|
||||
/**
|
||||
* @brief Override of accept() to store the entered text string so it can be retrieved by get_string().
|
||||
*/
|
||||
virtual void accept() override;
|
||||
|
||||
/**
|
||||
* @brief Slot for the font_weight combobox to set the font weight based on its data value
|
||||
*
|
||||
* @param i
|
||||
*
|
||||
* Index of the font_weight to retrieve the desired font weight from
|
||||
*/
|
||||
void SetFontWeight(int i);
|
||||
void SetLetterSpacing(qreal spacing);
|
||||
|
||||
/**
|
||||
* @brief Slot for text alignment buttons to set alignment based on their properties
|
||||
*
|
||||
* Intended slot for left_align_button, center_align_button, right_align_button, and justify_align_button. Pulls
|
||||
* from their property("a") value which should be a member of the Qt::Alignment enum.
|
||||
*/
|
||||
void SetAlignmentFromProperty();
|
||||
|
||||
/**
|
||||
* @brief Slot for when the text edit widget's cursor moves so the rich text toolbar can stay up to date
|
||||
*
|
||||
* In rich text mode, different parts of a text document can be formatted in different ways. As the user moves
|
||||
* around the text, the UI buttons should be consistent with whatever text is currently selected. This slot should
|
||||
* therefore be connected to QTextEdit::cursorPositionChanged() and will change the "checked" state of the formatting
|
||||
* buttons and current index of the comboboxes to match the currently selected text.
|
||||
*/
|
||||
void UpdateUIFromTextCursor();
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Internal rich text mode value
|
||||
*
|
||||
* This is set in the constructor and cannot be changed during the lifetime of this dialog.
|
||||
*/
|
||||
bool rich_text_;
|
||||
|
||||
/**
|
||||
* @brief Internal storage of text entered, saved when the user clicks OK
|
||||
*/
|
||||
QString result_str;
|
||||
|
||||
/**
|
||||
* @brief Main text editing widget
|
||||
*/
|
||||
QTextEdit* textEdit;
|
||||
|
||||
/**
|
||||
* @brief Toggle button for setting the italic state of the currently selected text
|
||||
*/
|
||||
QPushButton* italic_button;
|
||||
|
||||
/**
|
||||
* @brief Toggle button for setting the underlined state of the currently selected text
|
||||
*/
|
||||
QPushButton* underline_button;
|
||||
|
||||
/**
|
||||
* @brief ComboBox for the list of font families that the selected text can be set to
|
||||
*/
|
||||
QFontComboBox* font_list;
|
||||
|
||||
/**
|
||||
* @brief ComboBox for the list of font weights that the selected text can be set to
|
||||
*/
|
||||
QComboBox* font_weight;
|
||||
|
||||
/**
|
||||
* @brief A slider to set the current font size
|
||||
*/
|
||||
LabelSlider* font_size;
|
||||
|
||||
/**
|
||||
* @brief A color selector for setting the current text color
|
||||
*/
|
||||
ColorButton* font_color;
|
||||
|
||||
/**
|
||||
* @brief Button for setting the current text row(s) to left alignment
|
||||
*/
|
||||
QPushButton* left_align_button;
|
||||
|
||||
/**
|
||||
* @brief Button for setting the current text row(s) to center alignment
|
||||
*/
|
||||
QPushButton* center_align_button;
|
||||
|
||||
/**
|
||||
* @brief Button for setting the current text row(s) to right alignment
|
||||
*/
|
||||
QPushButton* right_align_button;
|
||||
|
||||
/**
|
||||
* @brief Button for setting the current text row(s) to justified alignment
|
||||
*/
|
||||
QPushButton* justify_align_button;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user