Merge branch 'master' into pr/1875
This commit is contained in:
@@ -39,7 +39,8 @@ NodeParamView::NodeParamView(bool create_keyframe_view, QWidget *parent) :
|
||||
super(true, false, parent),
|
||||
last_scroll_val_(0),
|
||||
focused_node_(nullptr),
|
||||
time_target_(nullptr)
|
||||
time_target_(nullptr),
|
||||
show_all_nodes_(false)
|
||||
{
|
||||
// Create horizontal layout to place scroll area in (and keyframe editing eventually)
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
@@ -453,7 +454,7 @@ void NodeParamView::RemoveContext(Node *ctx)
|
||||
|
||||
void NodeParamView::AddNode(Node *n, Node *ctx, NodeParamViewContext *context)
|
||||
{
|
||||
if ((n->GetFlags() & Node::kDontShowInParamView) && !IsGroupMode()) {
|
||||
if ((n->GetFlags() & Node::kDontShowInParamView) && !IsGroupMode() && !show_all_nodes_) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -143,6 +143,8 @@ private:
|
||||
QVector<Node*> contexts_;
|
||||
QVector<Node*> current_contexts_;
|
||||
|
||||
bool show_all_nodes_;
|
||||
|
||||
private slots:
|
||||
void UpdateGlobalScrollBar();
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <QVector3D>
|
||||
#include <QVector4D>
|
||||
|
||||
#include "common/qtutils.h"
|
||||
#include "core.h"
|
||||
#include "node/node.h"
|
||||
#include "node/project/sequence/sequence.h"
|
||||
@@ -86,11 +87,6 @@ void NodeParamViewWidgetBridge::CreateWidgets()
|
||||
case NodeValue::kTexture:
|
||||
case NodeValue::kMatrix:
|
||||
case NodeValue::kSamples:
|
||||
case NodeValue::kFootageJob:
|
||||
case NodeValue::kShaderJob:
|
||||
case NodeValue::kSampleJob:
|
||||
case NodeValue::kGenerateJob:
|
||||
case NodeValue::kColorTransformJob:
|
||||
case NodeValue::kVideoParams:
|
||||
case NodeValue::kAudioParams:
|
||||
case NodeValue::kDataTypeCount:
|
||||
@@ -241,11 +237,6 @@ void NodeParamViewWidgetBridge::WidgetCallback()
|
||||
case NodeValue::kTexture:
|
||||
case NodeValue::kMatrix:
|
||||
case NodeValue::kSamples:
|
||||
case NodeValue::kFootageJob:
|
||||
case NodeValue::kShaderJob:
|
||||
case NodeValue::kSampleJob:
|
||||
case NodeValue::kGenerateJob:
|
||||
case NodeValue::kColorTransformJob:
|
||||
case NodeValue::kVideoParams:
|
||||
case NodeValue::kAudioParams:
|
||||
case NodeValue::kDataTypeCount:
|
||||
@@ -396,6 +387,10 @@ void NodeParamViewWidgetBridge::CreateSliders(int count)
|
||||
T* fs = new T();
|
||||
fs->SliderBase::SetDefaultValue(GetInnerInput().GetSplitDefaultValueForTrack(i));
|
||||
fs->SetLadderElementCount(2);
|
||||
|
||||
// HACK: Force some spacing between sliders
|
||||
fs->setContentsMargins(0, 0, QtUtils::QFontMetricsWidth(fs->fontMetrics(), QStringLiteral(" ")), 0);
|
||||
|
||||
widgets_.append(fs);
|
||||
connect(fs, &T::ValueChanged, this, &NodeParamViewWidgetBridge::WidgetCallback);
|
||||
}
|
||||
@@ -419,11 +414,6 @@ void NodeParamViewWidgetBridge::UpdateWidgetValues()
|
||||
case NodeValue::kTexture:
|
||||
case NodeValue::kMatrix:
|
||||
case NodeValue::kSamples:
|
||||
case NodeValue::kFootageJob:
|
||||
case NodeValue::kShaderJob:
|
||||
case NodeValue::kSampleJob:
|
||||
case NodeValue::kGenerateJob:
|
||||
case NodeValue::kColorTransformJob:
|
||||
case NodeValue::kVideoParams:
|
||||
case NodeValue::kAudioParams:
|
||||
case NodeValue::kDataTypeCount:
|
||||
|
||||
@@ -139,10 +139,6 @@ void NodeTableView::SetTime(const rational &time)
|
||||
switch (value.type()) {
|
||||
case NodeValue::kVideoParams:
|
||||
case NodeValue::kAudioParams:
|
||||
case NodeValue::kFootageJob:
|
||||
case NodeValue::kShaderJob:
|
||||
case NodeValue::kSampleJob:
|
||||
case NodeValue::kGenerateJob:
|
||||
// These types have no string representation
|
||||
break;
|
||||
case NodeValue::kTexture:
|
||||
|
||||
@@ -97,6 +97,8 @@ ProjectExplorer::ProjectExplorer(QWidget *parent) :
|
||||
connect(tree_view_, &ProjectExplorerTreeView::customContextMenuRequested, this, &ProjectExplorer::ShowContextMenu);
|
||||
connect(list_view_, &ProjectExplorerListView::customContextMenuRequested, this, &ProjectExplorer::ShowContextMenu);
|
||||
connect(icon_view_, &ProjectExplorerIconView::customContextMenuRequested, this, &ProjectExplorer::ShowContextMenu);
|
||||
|
||||
UpdateNavBarText();
|
||||
}
|
||||
|
||||
const ProjectToolbar::ViewType &ProjectExplorer::view_type() const
|
||||
@@ -151,13 +153,7 @@ void ProjectExplorer::BrowseToFolder(const QModelIndex &index)
|
||||
list_view_->setRootIndex(index);
|
||||
|
||||
// Set navbar text to folder's name
|
||||
if (index.isValid()) {
|
||||
Folder* f = static_cast<Folder*>(sort_model_.mapToSource(index).internalPointer());
|
||||
nav_bar_->set_text(f->GetLabel());
|
||||
} else {
|
||||
// Or set it to an empty string if the index is valid (which means we're browsing to the root directory)
|
||||
nav_bar_->set_text(QString());
|
||||
}
|
||||
UpdateNavBarText();
|
||||
|
||||
// Set directory up enabled button based on whether we're in root or not
|
||||
nav_bar_->set_dir_up_enabled(index.isValid());
|
||||
@@ -246,6 +242,21 @@ QString ProjectExplorer::GetHumanReadableNodeName(Node *node)
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectExplorer::UpdateNavBarText()
|
||||
{
|
||||
QString absolute;
|
||||
|
||||
Folder* f = static_cast<Folder*>(sort_model_.mapToSource(list_view_->rootIndex()).internalPointer());
|
||||
while (f && f != project()->root()) {
|
||||
absolute.prepend(QStringLiteral("%1 / ").arg(f->GetLabel()));
|
||||
f = f->folder();
|
||||
}
|
||||
|
||||
absolute.prepend(QStringLiteral("/ "));
|
||||
|
||||
nav_bar_->set_text(absolute);
|
||||
}
|
||||
|
||||
QAbstractItemView *ProjectExplorer::CurrentView() const
|
||||
{
|
||||
return static_cast<QAbstractItemView*>(stacked_widget_->currentWidget());
|
||||
@@ -667,4 +678,32 @@ void ProjectExplorer::DeleteSelected()
|
||||
}
|
||||
}
|
||||
|
||||
bool ProjectExplorer::SelectItem(Node *n)
|
||||
{
|
||||
DeselectAll();
|
||||
|
||||
QModelIndex index = model_.CreateIndexFromItem(n);
|
||||
|
||||
if (index.isValid()) {
|
||||
index = sort_model_.mapFromSource(index);
|
||||
|
||||
QModelIndex parent = index.parent();
|
||||
if (view_type() == ProjectToolbar::TreeView) {
|
||||
// Expand all folders until this index is visible
|
||||
while (parent.isValid()) {
|
||||
tree_view_->expand(parent);
|
||||
parent = parent.parent();
|
||||
}
|
||||
} else {
|
||||
BrowseToFolder(parent);
|
||||
}
|
||||
|
||||
CurrentView()->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -85,6 +85,8 @@ public:
|
||||
|
||||
void DeleteSelected();
|
||||
|
||||
bool SelectItem(Node *n);
|
||||
|
||||
public slots:
|
||||
void set_view_type(ProjectToolbar::ViewType type);
|
||||
|
||||
@@ -138,6 +140,8 @@ private:
|
||||
|
||||
static QString GetHumanReadableNodeName(Node* node);
|
||||
|
||||
void UpdateNavBarText();
|
||||
|
||||
/**
|
||||
* @brief Get the currently active QAbstractItemView
|
||||
*/
|
||||
|
||||
@@ -21,6 +21,7 @@ set(OLIVE_SOURCES
|
||||
widget/standardcombos/interlacedcombobox.h
|
||||
widget/standardcombos/pixelaspectratiocombobox.h
|
||||
widget/standardcombos/pixelformatcombobox.h
|
||||
widget/standardcombos/sampleformatcombobox.h
|
||||
widget/standardcombos/sampleratecombobox.h
|
||||
widget/standardcombos/standardcombos.h
|
||||
widget/standardcombos/videodividercombobox.h
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 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 SAMPLEFORMATCOMBOBOX_H
|
||||
#define SAMPLEFORMATCOMBOBOX_H
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
#include "render/audioparams.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class SampleFormatComboBox : public QComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SampleFormatComboBox(QWidget* parent = nullptr) :
|
||||
QComboBox(parent),
|
||||
attempt_to_restore_format_(true)
|
||||
{
|
||||
}
|
||||
|
||||
void SetAttemptToRestoreFormat(bool e) { attempt_to_restore_format_ = e; }
|
||||
|
||||
void SetAvailableFormats(const std::vector<AudioParams::Format> &formats)
|
||||
{
|
||||
AudioParams::Format tmp = AudioParams::kFormatInvalid;
|
||||
|
||||
if (attempt_to_restore_format_) {
|
||||
tmp = GetSampleFormat();
|
||||
}
|
||||
|
||||
clear();
|
||||
foreach (const AudioParams::Format &of, formats) {
|
||||
AddFormatItem(of);
|
||||
}
|
||||
|
||||
if (attempt_to_restore_format_) {
|
||||
SetSampleFormat(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
AudioParams::Format GetSampleFormat() const
|
||||
{
|
||||
return static_cast<AudioParams::Format>(this->currentData().toInt());
|
||||
}
|
||||
|
||||
void SetSampleFormat(AudioParams::Format fmt)
|
||||
{
|
||||
for (int i=0; i<this->count(); i++) {
|
||||
if (this->itemData(i).toInt() == fmt) {
|
||||
this->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void AddFormatItem(AudioParams::Format f)
|
||||
{
|
||||
this->addItem(AudioParams::FormatToString(f), f);
|
||||
}
|
||||
|
||||
bool attempt_to_restore_format_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SAMPLEFORMATCOMBOBOX_H
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "interlacedcombobox.h"
|
||||
#include "pixelaspectratiocombobox.h"
|
||||
#include "pixelformatcombobox.h"
|
||||
#include "sampleformatcombobox.h"
|
||||
#include "sampleratecombobox.h"
|
||||
#include "videodividercombobox.h"
|
||||
|
||||
|
||||
@@ -1071,6 +1071,14 @@ void TimelineWidget::ShowContextMenu()
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
if (ClipBlock *clip = dynamic_cast<ClipBlock*>(selected.first())) {
|
||||
if (clip->connected_viewer()) {
|
||||
QAction *reveal_in_project = menu.addAction(tr("Reveal in Project"));
|
||||
reveal_in_project->setData(reinterpret_cast<quintptr>(clip->connected_viewer()));
|
||||
connect(reveal_in_project, &QAction::triggered, this, &TimelineWidget::RevealInProject);
|
||||
}
|
||||
}
|
||||
|
||||
QAction* properties_action = menu.addAction(tr("Properties"));
|
||||
connect(properties_action, &QAction::triggered, this, &TimelineWidget::ShowSpeedDurationDialogForSelectedClips);
|
||||
}
|
||||
@@ -1215,6 +1223,15 @@ void TimelineWidget::SignalBlockSelectionChange()
|
||||
signal_block_change_timer_->start();
|
||||
}
|
||||
|
||||
void TimelineWidget::RevealInProject()
|
||||
{
|
||||
QAction *a = static_cast<QAction*>(sender());
|
||||
|
||||
ViewerOutput *item_to_reveal = reinterpret_cast<ViewerOutput*>(a->data().value<quintptr>());
|
||||
|
||||
emit RevealViewerInProject(item_to_reveal);
|
||||
}
|
||||
|
||||
void TimelineWidget::AddGhost(TimelineViewGhostItem *ghost)
|
||||
{
|
||||
ghost_items_.append(ghost);
|
||||
|
||||
@@ -269,6 +269,8 @@ signals:
|
||||
|
||||
void RequestCaptureStart(const TimeRange &time, const Track::Reference &track);
|
||||
|
||||
void RevealViewerInProject(ViewerOutput *r);
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
@@ -410,6 +412,8 @@ private slots:
|
||||
|
||||
void SignalBlockSelectionChange();
|
||||
|
||||
void RevealInProject();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ void RecordTool::MousePress(TimelineViewMouseEvent *event)
|
||||
return;
|
||||
}
|
||||
|
||||
if (t->type() != Track::kAudio) {
|
||||
if (t && t->type() != Track::kAudio) {
|
||||
// We only support audio tracks here
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ void SeekableWidget::SeekToScenePoint(qreal scene)
|
||||
return;
|
||||
}
|
||||
|
||||
rational playhead_time = SceneToTime(scene);
|
||||
rational playhead_time = qMax(rational(0), SceneToTime(scene));
|
||||
|
||||
if (Core::instance()->snapping() && GetSnapService()) {
|
||||
rational movement;
|
||||
|
||||
@@ -388,7 +388,6 @@ void ViewerWidget::StartCapture(TimelineWidget *source, const TimeRange &time, c
|
||||
SetTimeAndSignal(time.in());
|
||||
ArmForRecording();
|
||||
|
||||
recording_filename_ = QStringLiteral("/home/matt/Desktop/ass.mp3");
|
||||
recording_callback_ = source;
|
||||
recording_range_ = time;
|
||||
recording_track_ = track;
|
||||
@@ -1167,7 +1166,31 @@ void ViewerWidget::Play(bool in_to_out_only)
|
||||
in_to_out_only = false;
|
||||
}
|
||||
} else if (record_armed_) {
|
||||
if (AudioManager::instance()->StartRecording(recording_filename_, GetConnectedNode()->GetAudioParams())) {
|
||||
DisarmRecording();
|
||||
|
||||
if (GetConnectedNode()->project()->filename().isEmpty()) {
|
||||
QMessageBox::critical(this, tr("Audio Recording"), tr("Project must be saved before you can record audio."));
|
||||
return;
|
||||
}
|
||||
|
||||
QDir audio_path(QFileInfo(GetConnectedNode()->project()->filename()).dir().filePath(tr("audio")));
|
||||
if (!audio_path.exists()) {
|
||||
audio_path.mkpath(QStringLiteral("."));
|
||||
}
|
||||
|
||||
recording_filename_ = audio_path.filePath(QStringLiteral("%1.%2").arg(
|
||||
QDateTime::currentDateTime().toString("yyyy-MM-dd hh-mm-ss"),
|
||||
ExportFormat::GetExtension(static_cast<ExportFormat::Format>(Config::Current()[QStringLiteral("AudioRecordingFormat")].toInt())))
|
||||
);
|
||||
|
||||
AudioParams ap(OLIVE_CONFIG("AudioRecordingSampleRate").toInt(), OLIVE_CONFIG("AudioRecordingChannelLayout").toULongLong(), static_cast<AudioParams::Format>(OLIVE_CONFIG("AudioRecordingSampleFormat").toInt()));
|
||||
|
||||
EncodingParams encode_param;
|
||||
encode_param.EnableAudio(ap, static_cast<ExportCodec::Codec>(OLIVE_CONFIG("AudioRecordingCodec").toInt()));
|
||||
encode_param.SetFilename(recording_filename_);
|
||||
encode_param.set_audio_bit_rate(OLIVE_CONFIG("AudioRecordingBitRate").toInt() * 1000);
|
||||
|
||||
if (AudioManager::instance()->StartRecording(encode_param)) {
|
||||
recording_ = true;
|
||||
controls_->SetPauseButtonRecordingState(true);
|
||||
recording_callback_->EnableRecordingOverlay(TimelineCoordinate(recording_range_.in(), recording_track_));
|
||||
@@ -1175,8 +1198,6 @@ void ViewerWidget::Play(bool in_to_out_only)
|
||||
QMessageBox::critical(this, tr("Audio Recording"), tr("Failed to start audio recording"));
|
||||
return;
|
||||
}
|
||||
|
||||
DisarmRecording();
|
||||
}
|
||||
|
||||
PlayInternal(1, in_to_out_only);
|
||||
|
||||
Reference in New Issue
Block a user