diff --git a/dialogs/autocutsilencedialog.cpp b/dialogs/autocutsilencedialog.cpp index b1d801b99..9280dbe66 100644 --- a/dialogs/autocutsilencedialog.cpp +++ b/dialogs/autocutsilencedialog.cpp @@ -31,7 +31,7 @@ #include "panels/panels.h" #include "panels/timeline.h" -AutoCutSilenceDialog::AutoCutSilenceDialog(QWidget *parent, QVector clips) : +AutoCutSilenceDialog::AutoCutSilenceDialog(QWidget *parent, QVector clips) : QDialog(parent), clips_(clips) { @@ -119,10 +119,12 @@ void AutoCutSilenceDialog::accept() { } void AutoCutSilenceDialog::cut_silence() { + ComboAction* ca = new ComboAction(); + // Loop over clips provided to this dialog for (int j=0;jclips.at(clips_.at(j)).get(); // Check if this clip is an audio footage clip if (clip->track() >= 0 @@ -200,23 +202,14 @@ void AutoCutSilenceDialog::cut_silence() { } } - ComboAction* ca = new ComboAction(); - - // NO GOOD VERY BAD TEST CODE - int clip_index = -1; - for (int i=0;iclips.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); + panel_timeline->split_clip_at_positions(ca, clips_.at(j), split_positions); } + } + if (ca->hasActions()) { + olive::UndoStack.push(ca); + } else { + delete ca; } } diff --git a/dialogs/autocutsilencedialog.h b/dialogs/autocutsilencedialog.h index 32c572e16..6f156679c 100644 --- a/dialogs/autocutsilencedialog.h +++ b/dialogs/autocutsilencedialog.h @@ -31,7 +31,7 @@ class AutoCutSilenceDialog : public QDialog { Q_OBJECT public: - AutoCutSilenceDialog(QWidget* parent, QVector clips); + AutoCutSilenceDialog(QWidget* parent, QVector clips); public slots: virtual int exec() override; private slots: @@ -39,7 +39,7 @@ private slots: private: void cut_silence(); - QVector clips_; + QVector clips_; LabelSlider* attack_threshold; LabelSlider* release_threshold; diff --git a/effects/fields/boolfield.h b/effects/fields/boolfield.h index dc933408c..d84e24c95 100644 --- a/effects/fields/boolfield.h +++ b/effects/fields/boolfield.h @@ -6,14 +6,14 @@ /** * @brief The BoolField class * - * An EffectField derivative the uses boolean values (true or false) and uses a checkbox as its visual representation. + * An EffectField derivative the produces boolean values (true or false) and uses a checkbox as its visual representation. */ class BoolField : public EffectField { Q_OBJECT public: /** - * @brief See Effect::Effect(). + * @brief Reimplementation of EffectField::EffectField(). */ BoolField(EffectRow* parent, const QString& id); @@ -33,22 +33,24 @@ public: bool GetBoolAt(double timecode); /** - * @brief See EffectField::CreateWidget() + * @brief Reimplementation of EffectField::CreateWidget() + * + * Creates and connects to a QCheckBox. */ virtual QWidget* CreateWidget(QWidget *existing = nullptr) override; /** - * @brief See EffectField::UpdateWidgetValue() + * @brief Reimplementation of EffectField::UpdateWidgetValue() */ virtual void UpdateWidgetValue(QWidget* widget, double timecode) override; /** - * @brief See EffectField::ConvertStringToValue() + * @brief Reimplementation of EffectField::ConvertStringToValue() */ virtual QVariant ConvertStringToValue(const QString& s) override; /** - * @brief See EffectField::ConvertValueToString() + * @brief Reimplementation of EffectField::ConvertValueToString() */ virtual QString ConvertValueToString(const QVariant& v) override; signals: diff --git a/effects/fields/buttonfield.h b/effects/fields/buttonfield.h index 38afb938d..2f481af30 100644 --- a/effects/fields/buttonfield.h +++ b/effects/fields/buttonfield.h @@ -20,7 +20,7 @@ class ButtonField : public EffectField Q_OBJECT public: /** - * @brief See Effect::Effect(). + * @brief Reimplementation of EffectField::EffectField(). */ ButtonField(EffectRow* parent, const QString& string); @@ -40,7 +40,9 @@ public: void SetCheckable(bool c); /** - * @brief See EffectField::CreateWidget() + * @brief Reimplementation of EffectField::CreateWidget() + * + * Creates and connects to a QPushButton. */ virtual QWidget* CreateWidget(QWidget *existing = nullptr) override; diff --git a/effects/fields/colorfield.h b/effects/fields/colorfield.h index ab32e4b52..c37427f31 100644 --- a/effects/fields/colorfield.h +++ b/effects/fields/colorfield.h @@ -3,20 +3,65 @@ #include "../effectfield.h" +/** + * @brief The ColorField class + * + * An EffectField derivative that produces color values and uses a ColorButton as its UI representative. + */ class ColorField : public EffectField { Q_OBJECT public: + /** + * @brief Reimplementation of EffectField::EffectField(). + */ ColorField(EffectRow* parent, const QString& id); + /** + * @brief Get the color value at a given timecode + * + * A convenience function, equivalent to GetValueAt(timecode).value(). + * + * @param timecode + * + * The timecode to retrieve the color at + * + * @return + * + * The color value at this timecode + */ QColor GetColorAt(double timecode); + /** + * @brief CreateWidget + * + * Creates and connects to a ColorButton. + */ virtual QWidget* CreateWidget(QWidget *existing = nullptr) override; + + /** + * @brief Reimplementation of EffectField::UpdateWidgetValue() + */ virtual void UpdateWidgetValue(QWidget* widget, double timecode) override; + /** + * @brief Reimplementation of EffectField::ConvertStringToValue() + */ virtual QVariant ConvertStringToValue(const QString& s) override; + + /** + * @brief Reimplementation of EffectField::ConvertValueToString() + */ virtual QString ConvertValueToString(const QVariant& v) override; private slots: + /** + * @brief Internal function connected to any QWidget made from CreateWidget() to update the value based on user input + * + * @param b + * + * The current color selected by the QWidget (ColorButton in this case). Automatically triggered when this slot is + * connected to the ColorButton::color_changed() signal. + */ void UpdateFromWidget(const QColor &c); }; diff --git a/effects/fields/combofield.h b/effects/fields/combofield.h index c2b1cb295..b5d288f41 100644 --- a/effects/fields/combofield.h +++ b/effects/fields/combofield.h @@ -3,29 +3,90 @@ #include "../effectfield.h" +/** + * @brief The ComboFieldItem struct + * + * An internal string+value pair used to represent a combobox item. name is used for the UI + * representation of the choices and the data is what can be retrieved by code. + * + * \see ComboField::AddItem. + */ struct ComboFieldItem { QString name; QVariant data; }; +/** + * @brief The ComboField class + * + * An EffectField derivative to produce arbitrary data based on a fixed selection of items. + */ class ComboField : public EffectField { Q_OBJECT public: + /** + * @brief Reimplementation of EffectField::EffectField(). + */ ComboField(EffectRow* parent, const QString& id); + /** + * @brief Add an item to this ComboField + * + * Adds a choice that the user can choose from this ComboField. All choices need text (for the on-screen + * choice) and data, which gets read on the backend. The selected data is what gets saved and loaded from + * project files, and therefore the data should be unique to this item. In case more items get added to + * this ComboField later, old project files will still open correctly. This is also why simple selected + * indices are not available. The text is only shown on the UI so it can be safely translated during runtime. + * + * @param text + * + * The text to show at this index. + * + * @param data + * + * The data to be retrieved at this index. + */ void AddItem(const QString& text, const QVariant& data); + /** + * @brief Reimplementation of EffectField::CreateWidget() + * + * Creates and connects to a QComboBox with the set of items added in AddItem(). + */ virtual QWidget *CreateWidget(QWidget *existing = nullptr) override; + + /** + * @brief Reimplementation of EffectField::UpdateWidgetValue() + */ virtual void UpdateWidgetValue(QWidget* widget, double timecode) override; signals: + /** + * @brief Signal emitted whenever a connected widget's data gets changed + * + * Useful for UI events that need to occur with the change of this ComboField's value. + */ void DataChanged(const QVariant&); private: + /** + * @brief Internal array of string+value pair items. + * + * \see ComboFieldItem + */ QVector items_; private slots: + /** + * @brief Internal function connected to any QWidget made from CreateWidget() to update the value based on user input + * + * @param b + * + * The current index of the QWidget (QComboBox in this case). Automatically set when this slot is connected + * to the QComboBox::currentIndexChanged() signal. This is the only time ComboFields deal with indices since the + * QComboBox's indices will match precisely to the items_ array. Outside of this function, QVariant data is prefered. + */ void UpdateFromWidget(int index); }; diff --git a/effects/fields/doublefield.h b/effects/fields/doublefield.h index 9b2882f4e..90d1351a8 100644 --- a/effects/fields/doublefield.h +++ b/effects/fields/doublefield.h @@ -4,10 +4,19 @@ #include "../effectfield.h" #include "ui/labelslider.h" +/** + * @brief The DoubleField class + * + * An EffectField derivative the produces number values (integer or floating-point) and uses a LabelSlider as its + * visual representation. + */ class DoubleField : public EffectField { Q_OBJECT public: + /** + * @brief Reimplementation of EffectField::EffectField(). + */ DoubleField(EffectRow* parent, const QString& id); /** @@ -25,34 +34,154 @@ public: */ double GetDoubleAt(double timecode); + /** + * @brief Sets the minimum allowed number for the user to set to `minimum`. + */ void SetMinimum(double minimum); - void SetMaximum(double maximum); - void SetDefault(double maximum); + /** + * @brief Sets the maximum allowed number for the user to set to `maximum`. + */ + void SetMaximum(double maximum); + + /** + * @brief Sets the default number for this field to `d`. + */ + void SetDefault(double d); + + /** + * @brief Sets the UI display type to a member of LabelSlider::DisplayType. + */ void SetDisplayType(LabelSlider::DisplayType type); + + /** + * @brief For a timecode-based display type, sets the frame rate to be used for the displayed timecode + * + * \see SetDisplayType() and LabelSlider::SetFrameRate(). + */ void SetFrameRate(const double& rate); + /** + * @brief Reimplementation of EffectField::ConvertStringToValue() + */ virtual QVariant ConvertStringToValue(const QString& s) override; + + /** + * @brief Reimplementation of EffectField::ConvertValueToString() + */ virtual QString ConvertValueToString(const QVariant& v) override; + /** + * @brief Reimplementation of EffectField::CreateWidget() + * + * Creates and connects to a LabelSlider. + */ virtual QWidget* CreateWidget(QWidget *existing = nullptr) override; + + /** + * @brief Reimplementation of EffectField::UpdateWidgetValue() + */ virtual void UpdateWidgetValue(QWidget* widget, double timecode) override; signals: + /** + * @brief Signal emitted when the field's maximum value has changed + * + * This signal gets connected to any LabelSlider created from CreateWidget() so the maximum value is + * always synchronized between them. + * + * Note: A connection is not made both ways as you should never manipulate a UI object created from + * an EffectField directly. Always access data through the EffectField itself. + * + * \see SetMaximum() + * + * @param maximum + * + * The new maximum value. + */ void MaximumChanged(double maximum); - void MinimumChanged(double maximum); + + /** + * @brief Signal emitted when the field's minimum value has changed + * + * This signal gets connected to any LabelSlider created from CreateWidget() so the minimum value is + * always synchronized between them. + * + * Note: A connection is not made both ways as you should never manipulate a UI object created from + * an EffectField directly. Always access data through the EffectField itself. + * + * \see SetMinimum() + * + * @param minimum + * + * The new minimum value. + */ + void MinimumChanged(double minimum); private: + /** + * @brief Internal minimum value + * + * \see SetMinimum(). + */ double min_; + + /** + * @brief Internal maximum value + * + * \see SetMaximum(). + */ double max_; + + /** + * @brief Internal default value + * + * \see SetDefault(). + */ double default_; + /** + * @brief Internal display type value + * + * \see SetDisplayType(). + */ LabelSlider::DisplayType display_type_; + + /** + * @brief Internal frame rate value + * + * \see SetFrameRate(). + */ double frame_rate_; + /** + * @brief Internal value used to allow SetDefault() to set the value as well if none has been set + * + * Initialized to FALSE, then set to TRUE indefinitely whenever the value gets set on this field. + */ bool value_set_; + /** + * @brief An internal KeyframeDataChange undoable command + * + * This is stored to allow for the value to be changed by dragging without every single "step" being pushed to + * the undo stack. Instead an undo command can be created at the start of a drag, and then pushed at the end + * to make it one single undoable action. + */ KeyframeDataChange* kdc_; private slots: + /** + * @brief Connected to EffectField::Changed() to ensure value_set_ gets set to TRUE whenever a value is set on this + * field. + */ void ValueHasBeenSet(); + + /** + * @brief Internal function connected to any QWidget made from CreateWidget() to update the value based on user input + * + * @param b + * + * The current number value of the QWidget (LabelSlider in this case). Automatically set when this slot is connected + * to the LabelSlider::valueChanged() signal. + */ void UpdateFromWidget(double d); }; diff --git a/effects/fields/filefield.h b/effects/fields/filefield.h index 317e324bf..f0717f9c0 100644 --- a/effects/fields/filefield.h +++ b/effects/fields/filefield.h @@ -3,17 +3,56 @@ #include "../effectfield.h" +/** + * @brief The FileField class + * + * An EffectField derivative that produces filenames in string and uses an EmbeddedFileChooser + * as its visual representation. + */ class FileField : public EffectField { Q_OBJECT public: + /** + * @brief Reimplementation of EffectField::EffectField(). + */ FileField(EffectRow* parent, const QString& id); + /** + * @brief Get the filename at the given timecode + * + * A convenience function, equivalent to GetValueAt(timecode).toString() + * + * @param timecode + * + * The timecode to retrieve the filename at + * + * @return + * + * The filename at this timecode + */ QString GetFileAt(double timecode); + /** + * @brief Reimplementation of EffectField::CreateWidget() + * + * Creates and connects to a EmbeddedFileChooser. + */ virtual QWidget* CreateWidget(QWidget *existing = nullptr) override; + + /** + * @brief Reimplementation of EffectField::UpdateWidgetValue() + */ virtual void UpdateWidgetValue(QWidget *widget, double timecode) override; private slots: + /** + * @brief Internal function connected to any QWidget made from CreateWidget() to update the value based on user input + * + * @param b + * + * The current string of the QWidget (TextEditEx in this case). Automatically set when this slot + * is connected to the TextEditEx::textModified() signal. + */ void UpdateFromWidget(const QString &s); }; diff --git a/effects/fields/fontfield.h b/effects/fields/fontfield.h index 9df3e76ae..b34b122d5 100644 --- a/effects/fields/fontfield.h +++ b/effects/fields/fontfield.h @@ -3,19 +3,65 @@ #include "combofield.h" +/** + * @brief The FontField class + * + * An EffectField derivative the produces font family names in string and uses a QComboBox + * as its visual representation. + * + * TODO Upgrade to QFontComboBox. + */ class FontField : public EffectField { Q_OBJECT public: + /** + * @brief Reimplementation of EffectField::EffectField(). + */ FontField(EffectRow* parent, const QString& id); + /** + * @brief Get the font family name at the given timecode + * + * A convenience function, equivalent to GetValueAt(timecode).toString() + * + * @param timecode + * + * The timecode to retrieve the font family name at + * + * @return + * + * The font family name at this timecode + */ QString GetFontAt(double timecode); + /** + * @brief Reimplementation of EffectField::CreateWidget() + * + * Creates and connects to a QComboBox. + */ virtual QWidget *CreateWidget(QWidget *existing = nullptr) override; + + /** + * @brief Reimplementation of EffectField::UpdateWidgetValue() + */ virtual void UpdateWidgetValue(QWidget* widget, double timecode) override; private: + /** + * @brief Internal list of fonts to add to a QComboBox when creating one in CreateWidget(). + * + * NOTE: Deprecated. Once QComboBox is replaced by QFontComboBox this will be completely unnecessary. + */ QStringList font_list; private slots: + /** + * @brief Internal function connected to any QWidget made from CreateWidget() to update the value based on user input + * + * @param b + * + * The current font name specified by the QWidget (QComboBox in this case). Automatically set when this slot + * is connected to the QComboBox::currentTextChanged() signal. + */ void UpdateFromWidget(const QString& index); }; diff --git a/effects/fields/labelfield.h b/effects/fields/labelfield.h index 67b4728f4..64aa78ddb 100644 --- a/effects/fields/labelfield.h +++ b/effects/fields/labelfield.h @@ -3,14 +3,32 @@ #include "../effectfield.h" +/** + * @brief The LabelField class + * + * A UI-type EffectField. This field is largely an EffectField wrapper around a QLabel and provides no data that's + * usable in the Effect. It's primarily useful for showing UI information. This field is not exposed to the external + * shader API as it requires raw C++ code to connect it to other elements. + */ class LabelField : public EffectField { Q_OBJECT public: + /** + * @brief Reimplementation of EffectField::EffectField(). + */ LabelField(EffectRow* parent, const QString& string); + /** + * @brief Reimplementation of EffectField::CreateWidget() + * + * Creates and connects to a QLabel. + */ virtual QWidget* CreateWidget(QWidget *existing = nullptr) override; private: + /** + * @brief Internal text string + */ QString label_text_; }; diff --git a/effects/fields/stringfield.h b/effects/fields/stringfield.h index 01eb26e9d..d8ee9f360 100644 --- a/effects/fields/stringfield.h +++ b/effects/fields/stringfield.h @@ -3,19 +3,64 @@ #include "../effectfield.h" +/** + * @brief The StringField class + * + * An EffectField derivative that produces arbitrary strings entered by the user and uses a TextEditEx as its + * visual representation. + */ class StringField : public EffectField { Q_OBJECT public: + /** + * @brief Reimplementation of EffectField::EffectField(). + * + * Provides a setting for whether this StringField - and its attached TextEditEx objects - should operate in rich + * text or plain text mode, defaulting to rich text mode. + */ StringField(EffectRow* parent, const QString& id, bool rich_text = true); + /** + * @brief Get the string at the given timecode + * + * A convenience function, equivalent to GetValueAt(timecode).toString() + * + * @param timecode + * + * The timecode to retrieve the string at + * + * @return + * + * The string at this timecode + */ QString GetStringAt(double timecode); + /** + * @brief Reimplementation of EffectField::CreateWidget() + * + * Creates and connects to a TextEditEx. + */ virtual QWidget *CreateWidget(QWidget *existing = nullptr) override; + + /** + * @brief Reimplementation of EffectField::UpdateWidgetValue() + */ virtual void UpdateWidgetValue(QWidget* widget, double timecode) override; private slots: + /** + * @brief Internal function connected to any QWidget made from CreateWidget() to update the value based on user input + * + * @param b + * + * The current checked state of the QWidget (EmbeddedFileChooser in this case). Automatically set when this slot + * is connected to the EmbeddedFileChooser::changed() signal. + */ void UpdateFromWidget(const QString& b); private: + /** + * @brief Internal value for whether this field is in rich text or plain text mode + */ bool rich_text_; }; diff --git a/global/global.cpp b/global/global.cpp index 382bb3a16..9f7ada144 100644 --- a/global/global.cpp +++ b/global/global.cpp @@ -441,7 +441,7 @@ void OliveGlobal::open_speed_dialog() { void OliveGlobal::open_autocut_silence_dialog() { if (CheckForActiveSequence()) { - QVector selected_clips = olive::ActiveSequence->SelectedClips(); + QVector selected_clips = olive::ActiveSequence->SelectedClipIndexes(); if (selected_clips.isEmpty()) { QMessageBox::critical(olive::MainWindow, diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp index 5f79b151b..09747ffb5 100644 --- a/ui/mainwindow.cpp +++ b/ui/mainwindow.cpp @@ -1080,13 +1080,13 @@ void MainWindow::maximize_panel() { // store the current state of panels temp_panel_state = saveState(); - // remove all dock widgets (kind of painful having to do each individually) - if (focused_panel != panel_project) removeDockWidget(panel_project); - if (focused_panel != panel_effect_controls) removeDockWidget(panel_effect_controls); - if (focused_panel != panel_timeline) removeDockWidget(panel_timeline); - if (focused_panel != panel_sequence_viewer) removeDockWidget(panel_sequence_viewer); - if (focused_panel != panel_footage_viewer) removeDockWidget(panel_footage_viewer); - if (focused_panel != panel_graph_editor) removeDockWidget(panel_graph_editor); + // remove all dock widgets + for (int i=0;isetVisible(false); + olive::panels.at(i)->setFloating(true); + } + } } } else { // we must be maximized, restore previous state