From 0b7e66e429633d8455e0a80af5b360165d803e42 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Fri, 22 Mar 2019 18:00:45 +1100 Subject: [PATCH] more documentation and cleanup --- dialogs/aboutdialog.h | 3 +- dialogs/actionsearch.h | 2 +- dialogs/advancedvideodialog.h | 2 +- dialogs/clippropertiesdialog.h | 3 +- dialogs/debugdialog.h | 6 +- dialogs/demonotice.h | 5 +- dialogs/exportdialog.h | 4 +- dialogs/loaddialog.h | 4 +- dialogs/mediapropertiesdialog.h | 3 +- dialogs/newsequencedialog.h | 2 +- dialogs/preferencesdialog.cpp | 23 +---- dialogs/preferencesdialog.h | 156 ++++++++++++++++++++++++++++- dialogs/proxydialog.h | 3 +- dialogs/replaceclipmediadialog.cpp | 24 ++--- dialogs/replaceclipmediadialog.h | 51 ++++++++-- dialogs/speeddialog.cpp | 14 +-- dialogs/speeddialog.h | 92 +++++++++++++++-- dialogs/texteditdialog.cpp | 42 ++------ dialogs/texteditdialog.h | 131 ++++++++++++++++++++++-- global/config.cpp | 5 - global/config.h | 10 -- ui/icons.cpp | 4 +- 22 files changed, 462 insertions(+), 127 deletions(-) diff --git a/dialogs/aboutdialog.h b/dialogs/aboutdialog.h index f0a5f14bd..08ec184e1 100644 --- a/dialogs/aboutdialog.h +++ b/dialogs/aboutdialog.h @@ -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 { diff --git a/dialogs/actionsearch.h b/dialogs/actionsearch.h index e00fb2025..54688a71e 100644 --- a/dialogs/actionsearch.h +++ b/dialogs/actionsearch.h @@ -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 { diff --git a/dialogs/advancedvideodialog.h b/dialogs/advancedvideodialog.h index 0ff8c1fae..e4279092b 100644 --- a/dialogs/advancedvideodialog.h +++ b/dialogs/advancedvideodialog.h @@ -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 diff --git a/dialogs/clippropertiesdialog.h b/dialogs/clippropertiesdialog.h index dc169a597..439f870de 100644 --- a/dialogs/clippropertiesdialog.h +++ b/dialogs/clippropertiesdialog.h @@ -10,7 +10,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 diff --git a/dialogs/debugdialog.h b/dialogs/debugdialog.h index a1b6aab3c..6d5797dc0 100644 --- a/dialogs/debugdialog.h +++ b/dialogs/debugdialog.h @@ -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; } diff --git a/dialogs/demonotice.h b/dialogs/demonotice.h index a986e51ab..0407864ab 100644 --- a/dialogs/demonotice.h +++ b/dialogs/demonotice.h @@ -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 { diff --git a/dialogs/exportdialog.h b/dialogs/exportdialog.h index c39c8af2a..bb5a4e486 100644 --- a/dialogs/exportdialog.h +++ b/dialogs/exportdialog.h @@ -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 { diff --git a/dialogs/loaddialog.h b/dialogs/loaddialog.h index 5fa357155..ea13f515f 100644 --- a/dialogs/loaddialog.h +++ b/dialogs/loaddialog.h @@ -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 { diff --git a/dialogs/mediapropertiesdialog.h b/dialogs/mediapropertiesdialog.h index c13e2c1f6..5c0fdc839 100644 --- a/dialogs/mediapropertiesdialog.h +++ b/dialogs/mediapropertiesdialog.h @@ -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 diff --git a/dialogs/newsequencedialog.h b/dialogs/newsequencedialog.h index 4acd69853..631923647 100644 --- a/dialogs/newsequencedialog.h +++ b/dialogs/newsequencedialog.h @@ -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 { diff --git a/dialogs/preferencesdialog.cpp b/dialogs/preferencesdialog.cpp index b8742926d..eb5ee4b3a 100644 --- a/dialogs/preferencesdialog.cpp +++ b/dialogs/preferencesdialog.cpp @@ -72,7 +72,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; } @@ -81,12 +81,8 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) : QDialog(parent) { setWindowTitle(tr("Preferences")); - setup_ui(); - accurateSeekButton->setChecked(!olive::CurrentConfig.fast_seeking); - fastSeekButton->setChecked(olive::CurrentConfig.fast_seeking); - recordingComboBox->setCurrentIndex(olive::CurrentConfig.recording_mode - 1); - imgSeqFormatEdit->setText(olive::CurrentConfig.img_seq_formats); + setup_ui(); setup_kbd_shortcuts(olive::MainWindow->menuBar()); } @@ -244,7 +240,6 @@ void PreferencesDialog::accept() { olive::CurrentConfig.recording_mode = recordingComboBox->currentIndex() + 1; olive::CurrentConfig.img_seq_formats = imgSeqFormatEdit->text(); - olive::CurrentConfig.fast_seeking = fastSeekButton->isChecked(); 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(); @@ -515,6 +510,7 @@ void PreferencesDialog::setup_ui() { general_layout->addWidget(new QLabel(tr("Image sequence formats:"), this), row, 0); imgSeqFormatEdit = new QLineEdit(general_tab); + imgSeqFormatEdit->setText(olive::CurrentConfig.img_seq_formats); general_layout->addWidget(imgSeqFormatEdit, row, 1, 1, 4); @@ -625,18 +621,6 @@ void PreferencesDialog::setup_ui() { QWidget* playback_tab = new QWidget(this); QVBoxLayout* playback_tab_layout = new QVBoxLayout(playback_tab); - // Playback -> Seeking - QGroupBox* seeking_group = new QGroupBox(playback_tab); - seeking_group->setTitle(tr("Seeking")); - QVBoxLayout* seeking_group_layout = new QVBoxLayout(seeking_group); - accurateSeekButton = new QRadioButton(seeking_group); - accurateSeekButton->setText(tr("Accurate Seeking\nAlways show the correct frame (visual may pause briefly as correct frame is retrieved)")); - seeking_group_layout->addWidget(accurateSeekButton); - fastSeekButton = new QRadioButton(seeking_group); - fastSeekButton->setText(tr("Fast Seeking\nSeek quickly (may briefly show inaccurate frames when seeking - doesn't affect playback/export)")); - seeking_group_layout->addWidget(fastSeekButton); - playback_tab_layout->addWidget(seeking_group); - // Playback -> Memory Usage QGroupBox* memory_usage_group = new QGroupBox(playback_tab); memory_usage_group->setTitle(tr("Memory Usage")); @@ -739,6 +723,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++; diff --git a/dialogs/preferencesdialog.h b/dialogs/preferencesdialog.h index 347212f4b..67538b7a7 100644 --- a/dialogs/preferencesdialog.h +++ b/dialogs/preferencesdialog.h @@ -41,7 +41,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 { @@ -162,45 +163,192 @@ private: */ void delete_previews(char type); + /** + * @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; - QRadioButton* accurateSeekButton; - QRadioButton* fastSeekButton; + + /** + * @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; + + /** + * @brief UI widget for enabling/disabling software fallbacks + */ 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; + + /** + * @brief UI widget for enabling/disabling default effects + */ QCheckBox* add_default_effects_to_clips; + + /** + * @brief UI widget for selecting the current UI style + */ QComboBox* ui_style; - Sequence sequence_settings; #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 + * key_shortcut_fields) + */ QVector 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 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 key_shortcut_fields; }; +/** + * @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; }; diff --git a/dialogs/proxydialog.h b/dialogs/proxydialog.h index 3a7fd579a..6a036d830 100644 --- a/dialogs/proxydialog.h +++ b/dialogs/proxydialog.h @@ -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 diff --git a/dialogs/replaceclipmediadialog.cpp b/dialogs/replaceclipmediadialog.cpp index a8aec4cfd..8efda92a9 100644 --- a/dialogs/replaceclipmediadialog.cpp +++ b/dialogs/replaceclipmediadialog.cpp @@ -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(selected_items.at(0).internalPointer()); + Media* new_item = static_cast(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;iclips.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(); } } diff --git a/dialogs/replaceclipmediadialog.h b/dialogs/replaceclipmediadialog.h index 7b1867a71..c0695f56f 100644 --- a/dialogs/replaceclipmediadialog.h +++ b/dialogs/replaceclipmediadialog.h @@ -28,16 +28,55 @@ #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 + 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; - QTreeView* tree; - QCheckBox* use_same_media_in_points; + /** + * @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; }; #endif // REPLACECLIPMEDIADIALOG_H diff --git a/dialogs/speeddialog.cpp b/dialogs/speeddialog.cpp index c0a08d652..8a87916bc 100644 --- a/dialogs/speeddialog.cpp +++ b/dialogs/speeddialog.cpp @@ -85,16 +85,16 @@ SpeedDialog::SpeedDialog(QWidget *parent, QVector 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;iSetDefault(default_length); duration->SetValue((current_length == -1) ? qSNaN() : current_length); - exec(); + return QDialog::exec(); } void SpeedDialog::percent_update() { diff --git a/dialogs/speeddialog.h b/dialogs/speeddialog.h index ac68c51dc..c52b2a862 100644 --- a/dialogs/speeddialog.h +++ b/dialogs/speeddialog.h @@ -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 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 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 diff --git a/dialogs/texteditdialog.cpp b/dialogs/texteditdialog.cpp index 185b7c357..e7a5d9fa0 100644 --- a/dialogs/texteditdialog.cpp +++ b/dialogs/texteditdialog.cpp @@ -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(sender()->property("a").toInt())); diff --git a/dialogs/texteditdialog.h b/dialogs/texteditdialog.h index c2ced7d2e..be812dd85 100644 --- a/dialogs/texteditdialog.h +++ b/dialogs/texteditdialog.h @@ -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; }; diff --git a/global/config.cpp b/global/config.cpp index 29ea9be76..d4c548d03 100644 --- a/global/config.cpp +++ b/global/config.cpp @@ -54,7 +54,6 @@ Config::Config() drop_on_media_to_replace(true), autoscroll(olive::AUTOSCROLL_PAGE_SCROLL), audio_rate(48000), - fast_seeking(false), hover_focus(false), project_view_type(olive::PROJECT_VIEW_TREE), set_name_with_marker(true), @@ -150,9 +149,6 @@ void Config::load(QString path) { } else if (stream.name() == "AudioRate") { stream.readNext(); audio_rate = stream.text().toInt(); - } else if (stream.name() == "FastSeeking") { - stream.readNext(); - fast_seeking = (stream.text() == "1"); } else if (stream.name() == "HoverFocus") { stream.readNext(); hover_focus = (stream.text() == "1"); @@ -265,7 +261,6 @@ void Config::save(QString path) { stream.writeTextElement("DropFileOnMediaToReplace", QString::number(drop_on_media_to_replace)); stream.writeTextElement("Autoscroll", QString::number(autoscroll)); stream.writeTextElement("AudioRate", QString::number(audio_rate)); - stream.writeTextElement("FastSeeking", QString::number(fast_seeking)); stream.writeTextElement("HoverFocus", QString::number(hover_focus)); stream.writeTextElement("ProjectViewType", QString::number(project_view_type)); stream.writeTextElement("SetNameWithMarker", QString::number(set_name_with_marker)); diff --git a/global/config.h b/global/config.h index 849acc2e1..f11183ef5 100644 --- a/global/config.h +++ b/global/config.h @@ -317,16 +317,6 @@ struct Config { */ int audio_rate; - /** - * @brief Enable fast seeking - * - * Olive supports a seek mode that shows frames faster with the risk of briefly showing a "best-effort" frame that - * may not be the accurate frame at that point of the Timeline. This does not affect exporting. - * - * Set to **TRUE** if this mode should be enabled. - */ - bool fast_seeking; - /** * @brief Enable hover focus * diff --git a/ui/icons.cpp b/ui/icons.cpp index 5cf63f81e..60997e8c0 100644 --- a/ui/icons.cpp +++ b/ui/icons.cpp @@ -76,8 +76,8 @@ void olive::icon::Initialize() Diamond = CreateIconFromSVG(":/icons/diamond.svg", false); Clock = CreateIconFromSVG(":/icons/clock.svg", false); - MediaVideo = CreateIconFromSVG(":/icons/videosource.svg", false); - MediaAudio = CreateIconFromSVG(":/icons/audiosource.svg", false); + MediaVideo = CreateIconFromSVG(":/icons/videosource.svg"); + MediaAudio = CreateIconFromSVG(":/icons/audiosource.svg"); MediaImage = CreateIconFromSVG(":/icons/imagesource.svg", false); MediaError = CreateIconFromSVG(":/icons/error.svg", false); MediaSequence = CreateIconFromSVG(":/icons/sequence.svg", false);