new undo system

Also enables undoing when working with node input arrays
This commit is contained in:
itsmattkc
2021-01-29 16:10:34 +11:00
parent 4e5db91c17
commit ad4b83a098
69 changed files with 1218 additions and 837 deletions
+2 -2
View File
@@ -26,14 +26,14 @@
namespace olive {
void XMLConnectNodes(const XMLNodeData &xml_node_data, QUndoCommand *command)
void XMLConnectNodes(const XMLNodeData &xml_node_data, MultiUndoCommand *command)
{
foreach (const XMLNodeData::SerializedConnection& con, xml_node_data.desired_connections) {
Node* out = xml_node_data.node_ptrs.value(con.output);
if (out) {
if (command) {
new NodeEdgeAddCommand(out, con.input, con.element, command);
command->add_child(new NodeEdgeAddCommand(out, con.input, con.element));
} else {
Node::ConnectEdge(out, con.input, con.element);
}
+2 -2
View File
@@ -21,10 +21,10 @@
#ifndef XMLREADLOOP_H
#define XMLREADLOOP_H
#include <QUndoCommand>
#include <QXmlStreamReader>
#include "project/item/footage/stream.h"
#include "undo/undocommand.h"
namespace olive {
@@ -63,7 +63,7 @@ struct XMLNodeData {
};
void XMLConnectNodes(const XMLNodeData& xml_node_data, QUndoCommand* command = nullptr);
void XMLConnectNodes(const XMLNodeData& xml_node_data, MultiUndoCommand *command = nullptr);
bool XMLReadNextStartElement(QXmlStreamReader* reader);
+1 -1
View File
@@ -479,7 +479,7 @@ void Core::ImportTaskComplete(Task* task)
{
ProjectImportTask* import_task = static_cast<ProjectImportTask*>(task);
QUndoCommand *command = import_task->GetCommand();
MultiUndoCommand *command = import_task->GetCommand();
if (import_task->HasInvalidFiles()) {
ProjectImportErrorDialog d(import_task->GetInvalidFiles(), main_window_);
@@ -124,21 +124,19 @@ void FootagePropertiesDialog::accept() {
}
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
if (footage_->name() != footage_name_field_->text()) {
new FootageChangeCommand(footage_,
footage_name_field_->text(),
command);
command->add_child(new FootageChangeCommand(footage_,
footage_name_field_->text()));
}
for (int i=0;i<footage_->streams().size();i++) {
bool stream_enabled = (track_list->item(i)->checkState() == Qt::Checked);
if (footage_->stream(i)->enabled() != stream_enabled) {
new StreamEnableChangeCommand(footage_->stream(i),
stream_enabled,
command);
command->add_child(new StreamEnableChangeCommand(footage_->stream(i),
stream_enabled));
}
}
@@ -151,8 +149,7 @@ void FootagePropertiesDialog::accept() {
QDialog::accept();
}
FootagePropertiesDialog::FootageChangeCommand::FootageChangeCommand(Footage *footage, const QString &name, QUndoCommand* command) :
UndoCommand(command),
FootagePropertiesDialog::FootageChangeCommand::FootageChangeCommand(Footage *footage, const QString &name) :
footage_(footage),
new_name_(name)
{
@@ -163,20 +160,19 @@ Project *FootagePropertiesDialog::FootageChangeCommand::GetRelevantProject() con
return footage_->project();
}
void FootagePropertiesDialog::FootageChangeCommand::redo_internal()
void FootagePropertiesDialog::FootageChangeCommand::redo()
{
old_name_ = footage_->name();
footage_->set_name(new_name_);
}
void FootagePropertiesDialog::FootageChangeCommand::undo_internal()
void FootagePropertiesDialog::FootageChangeCommand::undo()
{
footage_->set_name(old_name_);
}
FootagePropertiesDialog::StreamEnableChangeCommand::StreamEnableChangeCommand(Stream *stream, bool enabled, QUndoCommand *command) :
UndoCommand(command),
FootagePropertiesDialog::StreamEnableChangeCommand::StreamEnableChangeCommand(Stream *stream, bool enabled) :
stream_(stream),
old_enabled_(stream->enabled()),
new_enabled_(enabled)
@@ -188,12 +184,12 @@ Project *FootagePropertiesDialog::StreamEnableChangeCommand::GetRelevantProject(
return stream_->footage()->project();
}
void FootagePropertiesDialog::StreamEnableChangeCommand::redo_internal()
void FootagePropertiesDialog::StreamEnableChangeCommand::redo()
{
stream_->set_enabled(new_enabled_);
}
void FootagePropertiesDialog::StreamEnableChangeCommand::undo_internal()
void FootagePropertiesDialog::StreamEnableChangeCommand::undo()
{
stream_->set_enabled(old_enabled_);
}
@@ -59,14 +59,12 @@ private:
class FootageChangeCommand : public UndoCommand {
public:
FootageChangeCommand(Footage* footage,
const QString& name,
QUndoCommand *command = nullptr);
const QString& name);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
Footage* footage_;
@@ -78,14 +76,12 @@ private:
class StreamEnableChangeCommand : public UndoCommand {
public:
StreamEnableChangeCommand(Stream* stream,
bool enabled,
QUndoCommand* command = nullptr);
bool enabled);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
Stream* stream_;
@@ -27,7 +27,7 @@ AudioStreamProperties::AudioStreamProperties(AudioStream *stream) :
{
}
void AudioStreamProperties::Accept(QUndoCommand*)
void AudioStreamProperties::Accept(MultiUndoCommand*)
{
Q_UNUSED(stream_)
}
@@ -31,7 +31,7 @@ class AudioStreamProperties : public StreamProperties
public:
AudioStreamProperties(AudioStream* stream);
virtual void Accept(QUndoCommand* parent) override;
virtual void Accept(MultiUndoCommand* parent) override;
private:
AudioStream* stream_;
@@ -21,10 +21,10 @@
#ifndef STREAMPROPERTIES_H
#define STREAMPROPERTIES_H
#include <QUndoCommand>
#include <QWidget>
#include "common/define.h"
#include "undo/undocommand.h"
namespace olive {
@@ -33,7 +33,7 @@ class StreamProperties : public QWidget
public:
StreamProperties(QWidget* parent = nullptr);
virtual void Accept(QUndoCommand*){}
virtual void Accept(MultiUndoCommand*){}
virtual bool SanityCheck(){return true;}
@@ -124,7 +124,7 @@ VideoStreamProperties::VideoStreamProperties(VideoStream *stream) :
}
}
void VideoStreamProperties::Accept(QUndoCommand *parent)
void VideoStreamProperties::Accept(MultiUndoCommand *parent)
{
QString set_colorspace;
@@ -137,12 +137,11 @@ void VideoStreamProperties::Accept(QUndoCommand *parent)
|| static_cast<VideoParams::Interlacing>(video_interlace_combo_->currentIndex()) != stream_->interlacing()
|| pixel_aspect_combo_->GetPixelAspectRatio() != stream_->pixel_aspect_ratio()) {
new VideoStreamChangeCommand(stream_,
parent->add_child(new VideoStreamChangeCommand(stream_,
video_premultiply_alpha_ ? video_premultiply_alpha_->isChecked() : stream_->premultiplied_alpha(),
set_colorspace,
static_cast<VideoParams::Interlacing>(video_interlace_combo_->currentIndex()),
pixel_aspect_combo_->GetPixelAspectRatio(),
parent);
pixel_aspect_combo_->GetPixelAspectRatio()));
}
if (stream_->video_type() == VideoStream::kVideoTypeImageSequence) {
@@ -153,11 +152,10 @@ void VideoStreamProperties::Accept(QUndoCommand *parent)
if (video_stream->start_time() != imgseq_start_time_->GetValue()
|| video_stream->duration() != new_dur
|| video_stream->frame_rate() != imgseq_frame_rate_->GetFrameRate()) {
new ImageSequenceChangeCommand(video_stream,
parent->add_child(new ImageSequenceChangeCommand(video_stream,
imgseq_start_time_->GetValue(),
new_dur,
imgseq_frame_rate_->GetFrameRate(),
parent);
imgseq_frame_rate_->GetFrameRate()));
}
}
}
@@ -181,9 +179,7 @@ VideoStreamProperties::VideoStreamChangeCommand::VideoStreamChangeCommand(VideoS
bool premultiplied,
QString colorspace,
VideoParams::Interlacing interlacing,
const rational &pixel_ar,
QUndoCommand *parent) :
UndoCommand(parent),
const rational &pixel_ar) :
stream_(stream),
new_premultiplied_(premultiplied),
new_colorspace_(colorspace),
@@ -197,7 +193,7 @@ Project *VideoStreamProperties::VideoStreamChangeCommand::GetRelevantProject() c
return stream_->footage()->project();
}
void VideoStreamProperties::VideoStreamChangeCommand::redo_internal()
void VideoStreamProperties::VideoStreamChangeCommand::redo()
{
old_premultiplied_ = stream_->premultiplied_alpha();
old_colorspace_ = stream_->colorspace(false);
@@ -210,7 +206,7 @@ void VideoStreamProperties::VideoStreamChangeCommand::redo_internal()
stream_->set_pixel_aspect_ratio(new_pixel_ar_);
}
void VideoStreamProperties::VideoStreamChangeCommand::undo_internal()
void VideoStreamProperties::VideoStreamChangeCommand::undo()
{
stream_->set_premultiplied_alpha(old_premultiplied_);
stream_->set_colorspace(old_colorspace_);
@@ -218,8 +214,7 @@ void VideoStreamProperties::VideoStreamChangeCommand::undo_internal()
stream_->set_pixel_aspect_ratio(old_pixel_ar_);
}
VideoStreamProperties::ImageSequenceChangeCommand::ImageSequenceChangeCommand(VideoStream *video_stream, int64_t start_index, int64_t duration, const rational &frame_rate, QUndoCommand *parent) :
UndoCommand(parent),
VideoStreamProperties::ImageSequenceChangeCommand::ImageSequenceChangeCommand(VideoStream *video_stream, int64_t start_index, int64_t duration, const rational &frame_rate) :
video_stream_(video_stream),
new_start_index_(start_index),
new_duration_(duration),
@@ -232,7 +227,7 @@ Project *VideoStreamProperties::ImageSequenceChangeCommand::GetRelevantProject()
return video_stream_->footage()->project();
}
void VideoStreamProperties::ImageSequenceChangeCommand::redo_internal()
void VideoStreamProperties::ImageSequenceChangeCommand::redo()
{
old_start_index_ = video_stream_->start_time();
video_stream_->set_start_time(new_start_index_);
@@ -245,7 +240,7 @@ void VideoStreamProperties::ImageSequenceChangeCommand::redo_internal()
video_stream_->set_timebase(new_frame_rate_.flipped());
}
void VideoStreamProperties::ImageSequenceChangeCommand::undo_internal()
void VideoStreamProperties::ImageSequenceChangeCommand::undo()
{
video_stream_->set_start_time(old_start_index_);
video_stream_->set_duration(old_duration_);
@@ -26,7 +26,6 @@
#include "project/item/footage/videostream.h"
#include "streamproperties.h"
#include "undo/undocommand.h"
#include "widget/slider/integerslider.h"
#include "widget/standardcombos/standardcombos.h"
@@ -38,7 +37,7 @@ class VideoStreamProperties : public StreamProperties
public:
VideoStreamProperties(VideoStream* stream);
virtual void Accept(QUndoCommand* parent) override;
virtual void Accept(MultiUndoCommand *parent) override;
virtual bool SanityCheck() override;
@@ -89,14 +88,12 @@ private:
bool premultiplied,
QString colorspace,
VideoParams::Interlacing interlacing,
const rational& pixel_ar,
QUndoCommand* parent = nullptr);
const rational& pixel_ar);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
VideoStream* stream_;
@@ -118,14 +115,12 @@ private:
ImageSequenceChangeCommand(VideoStream* video_stream,
int64_t start_index,
int64_t duration,
const rational& frame_rate,
QUndoCommand* parent = nullptr);
const rational& frame_rate);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
VideoStream* video_stream_;
@@ -194,30 +194,28 @@ KeyframePropertiesDialog::KeyframePropertiesDialog(const QVector<NodeKeyframe*>
void KeyframePropertiesDialog::accept()
{
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
rational new_time = Timecode::timestamp_to_time(time_slider_->GetValue(), timebase_);
int new_type = type_select_->currentData().toInt();
foreach (NodeKeyframe* key, keys_) {
if (time_slider_->isEnabled() && !time_slider_->IsTristate()) {
new NodeParamSetKeyframeTimeCommand(key, new_time, command);
command->add_child(new NodeParamSetKeyframeTimeCommand(key, new_time));
}
if (new_type > -1) {
new KeyframeSetTypeCommand(key, static_cast<NodeKeyframe::Type>(new_type), command);
command->add_child(new KeyframeSetTypeCommand(key, static_cast<NodeKeyframe::Type>(new_type)));
}
if (bezier_group_->isEnabled()) {
new KeyframeSetBezierControlPoint(key,
command->add_child(new KeyframeSetBezierControlPoint(key,
NodeKeyframe::kInHandle,
QPointF(bezier_in_x_slider_->GetValue(), bezier_in_y_slider_->GetValue()),
command);
QPointF(bezier_in_x_slider_->GetValue(), bezier_in_y_slider_->GetValue())));
new KeyframeSetBezierControlPoint(key,
command->add_child(new KeyframeSetBezierControlPoint(key,
NodeKeyframe::kOutHandle,
QPointF(bezier_out_x_slider_->GetValue(), bezier_out_y_slider_->GetValue()),
command);
QPointF(bezier_out_x_slider_->GetValue(), bezier_out_y_slider_->GetValue())));
}
}
+3 -5
View File
@@ -139,9 +139,7 @@ void SequenceDialog::accept()
SequenceDialog::SequenceParamCommand::SequenceParamCommand(Sequence* s,
const VideoParams& video_params,
const AudioParams &audio_params,
const QString& name,
QUndoCommand* parent) :
UndoCommand(parent),
const QString& name) :
sequence_(s),
new_video_params_(video_params),
new_audio_params_(audio_params),
@@ -157,14 +155,14 @@ Project *SequenceDialog::SequenceParamCommand::GetRelevantProject() const
return sequence_->project();
}
void SequenceDialog::SequenceParamCommand::redo_internal()
void SequenceDialog::SequenceParamCommand::redo()
{
sequence_->set_video_params(new_video_params_);
sequence_->set_audio_params(new_audio_params_);
sequence_->set_name(new_name_);
}
void SequenceDialog::SequenceParamCommand::undo_internal()
void SequenceDialog::SequenceParamCommand::undo()
{
sequence_->set_video_params(old_video_params_);
sequence_->set_audio_params(old_audio_params_);
+5 -7
View File
@@ -38,7 +38,7 @@ namespace olive {
* This dialog exposes all the parameters of a Sequence to users allowing them to set up a Sequence however they wish.
* A Sequence can be sent to this dialog through the constructor. All fields will be filled using that Sequence's
* parameters, allowing the user to view and edit them. Accepting the dialog will apply them back to that Sequence,
* either directly or using a QUndoCommand (see SetUndoable()).
* either directly or using an UndoCommand (see SetUndoable()).
*
* If creating a new Sequence, the Sequence must still be constructed first before sending it to SequenceDialog.
* SequenceDialog does not create any new objects. In most cases when creating a new Sequence, editing its parameters
@@ -104,21 +104,19 @@ private:
QLineEdit* name_field_;
/**
* @brief A QUndoCommand for setting the parameters on a sequence
* @brief An UndoCommand for setting the parameters on a sequence
*/
class SequenceParamCommand : public UndoCommand {
public:
SequenceParamCommand(Sequence* s,
const VideoParams& video_params,
const AudioParams& audio_params,
const QString& name,
QUndoCommand* parent = nullptr);
const QString& name);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
Sequence* sequence_;
+1
View File
@@ -43,6 +43,7 @@ set(OLIVE_SOURCES
node/node.cpp
node/nodecopypaste.h
node/nodecopypaste.cpp
node/splitvalue.h
node/traverser.h
node/traverser.cpp
node/value.h
+1 -1
View File
@@ -27,7 +27,7 @@ namespace olive {
PolygonGenerator::PolygonGenerator()
{
points_input_ = new NodeInput(this, QStringLiteral("points_in"), NodeValue::kVec2);
points_input_ = new NodeInput(this, QStringLiteral("points_in"), NodeValue::kVec2, QVector2D(0, 0));
points_input_->SetIsArray(true);
color_input_ = new NodeInput(this, QStringLiteral("color_in"), NodeValue::kColor, QVariant::fromValue(Color(1.0, 1.0, 1.0)));
+108 -47
View File
@@ -23,14 +23,16 @@
#include "common/bezier.h"
#include "common/lerp.h"
#include "common/xmlutils.h"
#include "core.h"
#include "node.h"
#include "project/item/footage/stream.h"
#include "widget/nodeview/nodeviewundo.h"
#define super NodeConnectable
namespace olive {
NodeInput::NodeInput(Node* parent, const QString& id, NodeValue::Type type, const QVector<QVariant> &default_value)
NodeInput::NodeInput(Node* parent, const QString& id, NodeValue::Type type, const SplitValue &default_value)
{
Init(parent, id, type, default_value);
}
@@ -42,7 +44,7 @@ NodeInput::NodeInput(Node *parent, const QString &id, NodeValue::Type type, cons
NodeInput::NodeInput(Node* parent, const QString &id, NodeValue::Type type)
{
Init(parent, id, type, QVector<QVariant>());
Init(parent, id, type, SplitValue());
}
NodeInput::~NodeInput()
@@ -217,7 +219,16 @@ void NodeInput::childEvent(QChildEvent *event)
}
}
void NodeInput::Init(Node* parent, const QString &id, NodeValue::Type type, const QVector<QVariant>& default_val)
void NodeInput::ClearElement(int index)
{
GetImmediate(index)->delete_all_keyframes();
SetIsKeyframing(false, index);
SetSplitStandardValue(default_value_, index);
}
void NodeInput::Init(Node* parent, const QString &id, NodeValue::Type type, const SplitValue& default_val)
{
setParent(parent);
@@ -381,12 +392,26 @@ void NodeInput::SaveImmediate(QXmlStreamWriter* writer, int element) const
}
}
void NodeInput::ChangeArraySizeInternal(int size)
void NodeInput::ArrayResizeInternal(int size)
{
if (array_size_ != size) {
// Update array size
if (array_size_ < size) {
// Size is larger, create any immediates that don't exist
for (int i=subinputs_.size(); i<size; i++) {
subinputs_.append(CreateImmediate());
}
// Note that we do not delete any immediates when decreasing size since the user might still
// want that data. Therefore it's important to note that array_size_ does NOT necessarily
// equal subinputs_.size()
}
array_size_ = size;
emit ArraySizeChanged(array_size_);
emit ValueChanged(TimeRange(RATIONAL_MIN, RATIONAL_MAX), -1);
}
}
NodeInputImmediate *NodeInput::CreateImmediate()
{
@@ -440,12 +465,18 @@ QVector<Node *> NodeInput::GetImmediateDependencies() const
return GetDependencies(false, false);
}
void NodeInput::ArrayInsert(int index)
void NodeInput::ArrayAppend(bool undoable)
{
// Add new input
subinputs_.insert(index, CreateImmediate());
ArrayResize(ArraySize() + 1, undoable);
}
ChangeArraySizeInternal(array_size_ + 1);
void NodeInput::ArrayInsert(int index, bool undoable)
{
if (undoable) {
Core::instance()->undo_stack()->push(new ArrayInsertCommand(this, index));
} else {
// Add new input
ArrayResizeInternal(ArraySize() + 1);
// Move connections down
std::map<int, Node*> copied_edges = edges();
@@ -456,13 +487,24 @@ void NodeInput::ArrayInsert(int index)
ConnectEdge(it->second, this, it->first + 1);
}
}
// Shift values and keyframes up one element
for (int i=ArraySize()-1; i>index; i--) {
CopyValuesOfElement(this, this, i-1, i);
}
void NodeInput::ArrayRemove(int index)
// Reset value of element we just "inserted"
ClearElement(index);
}
}
void NodeInput::ArrayRemove(int index, bool undoable)
{
if (undoable) {
Core::instance()->undo_stack()->push(new ArrayRemoveCommand(this, index));
} else {
// Remove input
delete subinputs_.takeAt(index);
ChangeArraySizeInternal(array_size_ - 1);
ArrayResizeInternal(ArraySize() - 1);
// Move connections up
std::map<int, Node*> copied_edges = edges();
@@ -476,43 +518,42 @@ void NodeInput::ArrayRemove(int index)
}
}
}
// Shift values and keyframes down one element
for (int i=index; i<ArraySize(); i++) {
// Copying ArraySize()+1 is actually legal because immediates are never deleted
CopyValuesOfElement(this, this, i+1, i);
}
void NodeInput::ArrayPrepend()
// Reset value of last element
ClearElement(ArraySize());
}
}
void NodeInput::ArrayPrepend(bool undoable)
{
ArrayInsert(0);
ArrayInsert(0, undoable);
}
void NodeInput::ArrayResize(int size)
void NodeInput::ArrayResize(int size, bool undoable)
{
if (array_size_ != size) {
// Update array size
if (array_size_ < size) {
// Size is larger, create any immediates that don't exist
for (int i=subinputs_.size(); i<size; i++) {
subinputs_.append(CreateImmediate());
if (array_size_ == size) {
return;
}
ArrayResizeCommand* c = new ArrayResizeCommand(this, size);
if (undoable) {
Core::instance()->undo_stack()->push(c);
} else {
c->redo();
delete c;
}
}
ChangeArraySizeInternal(size);
if (array_size_ > size) {
// Decreasing in size, disconnect any extraneous edges
for (int i=size; i<array_size_; i++) {
try {
DisconnectEdge(edges().at(i), this, i);
} catch (std::out_of_range&) {}
}
// Note that we do not delete any immediates since the user might still want that data.
// Therefore it's important to note that array_size_ does NOT necessarily equal subinputs_.size()
}
}
}
void NodeInput::ArrayRemoveLast()
void NodeInput::ArrayRemoveLast(bool undoable)
{
ArrayResize(ArraySize() - 1);
ArrayResize(ArraySize() - 1, undoable);
}
QVariant NodeInput::GetValueAtTime(const rational &time, int element) const
@@ -520,9 +561,9 @@ QVariant NodeInput::GetValueAtTime(const rational &time, int element) const
return NodeValue::combine_track_values_into_normal_value(data_type_, GetSplitValuesAtTime(time, element));
}
QVector<QVariant> NodeInput::GetSplitValuesAtTime(const rational &time, int element) const
SplitValue NodeInput::GetSplitValuesAtTime(const rational &time, int element) const
{
QVector<QVariant> vals;
SplitValue vals;
int nb_tracks = GetNumberOfKeyframeTracks();
@@ -669,26 +710,31 @@ void NodeInput::CopyValues(NodeInput *source, NodeInput *dest, bool include_conn
}
}
void NodeInput::CopyValuesOfElement(NodeInput *src, NodeInput *dst, int element)
void NodeInput::CopyValuesOfElement(NodeInput *src, NodeInput *dst, int src_element, int dst_element)
{
if (dst_element >= dst->subinputs_.size()) {
qDebug() << "Ignored destination element that was out of array bounds";
return;
}
// Copy standard value
dst->SetSplitStandardValue(src->GetSplitStandardValue(element), element);
dst->SetSplitStandardValue(src->GetSplitStandardValue(src_element), dst_element);
// Copy keyframes
dst->GetImmediate(element)->delete_all_keyframes();
foreach (const NodeKeyframeTrack& track, src->GetImmediate(element)->keyframe_tracks()) {
dst->GetImmediate(dst_element)->delete_all_keyframes();
foreach (const NodeKeyframeTrack& track, src->GetImmediate(src_element)->keyframe_tracks()) {
foreach (NodeKeyframe* key, track) {
key->copy(dst);
key->copy(dst_element, dst);
}
}
// Copy keyframing state
if (src->IsKeyframable()) {
dst->SetIsKeyframing(src->IsKeyframing(element), element);
dst->SetIsKeyframing(src->IsKeyframing(src_element), dst_element);
}
// If this is the root of an array, copy the array size
if (element == -1) {
if (src_element == -1 && dst_element == -1) {
dst->ArrayResize(src->ArraySize());
}
}
@@ -839,4 +885,19 @@ uint qHash(const NodeInput::KeyframeTrackReference &ref, uint seed)
return qHash(ref.input, seed) ^ qHash(ref.element, seed) ^ qHash(ref.track, seed);
}
Project *NodeInput::ArrayRemoveCommand::GetRelevantProject() const
{
return input_->parent()->parent()->project();
}
Project *NodeInput::ArrayResizeCommand::GetRelevantProject() const
{
return input_->parent()->parent()->project();
}
Project *NodeInput::ArrayInsertCommand::GetRelevantProject() const
{
return input_->parent()->parent()->project();
}
}
+155 -20
View File
@@ -26,6 +26,8 @@
#include "node/connectable.h"
#include "node/inputimmediate.h"
#include "node/value.h"
#include "splitvalue.h"
#include "undo/undocommand.h"
namespace olive {
@@ -47,7 +49,7 @@ public:
* saving/loading data from this Node so that parameter order can be changed without issues loading data saved by an
* older version. This of course assumes that parameters don't change their ID.
*/
NodeInput(Node* parent, const QString &id, NodeValue::Type type, const QVector<QVariant>& default_value);
NodeInput(Node* parent, const QString &id, NodeValue::Type type, const SplitValue& default_value);
NodeInput(Node* parent, const QString &id, NodeValue::Type type, const QVariant& default_value);
NodeInput(Node* parent, const QString &id, NodeValue::Type type);
@@ -176,7 +178,7 @@ public:
/**
* @brief Get non-keyframed value split into components (the way it's stored)
*/
const QVector<QVariant>& GetSplitStandardValue(int element = -1) const
const SplitValue& GetSplitStandardValue(int element = -1) const
{
return GetImmediate(element)->get_split_standard_value();
}
@@ -197,7 +199,7 @@ public:
SetSplitStandardValue(NodeValue::split_normal_value_into_track_values(data_type_, value), element);
}
void SetSplitStandardValue(const QVector<QVariant>& value, int element = -1)
void SetSplitStandardValue(const SplitValue& value, int element = -1)
{
GetImmediate(element)->set_split_standard_value(value);
@@ -231,7 +233,11 @@ public:
*/
static void CopyValues(NodeInput* source, NodeInput* dest, bool include_connections = true, bool traverse_arrays = true);
static void CopyValuesOfElement(NodeInput* source, NodeInput* dst, int element);
static void CopyValuesOfElement(NodeInput* source, NodeInput* dst, int src_element, int dst_element);
static void CopyValuesOfElement(NodeInput* source, NodeInput* dst, int element)
{
CopyValuesOfElement(source, dst, element, element);
}
QStringList get_combobox_strings() const;
@@ -244,7 +250,7 @@ public:
return NodeValue::combine_track_values_into_normal_value(data_type_, default_value_);
}
const QVector<QVariant>& GetSplitDefaultValue() const
const SplitValue& GetSplitDefaultValue() const
{
return default_value_;
}
@@ -279,33 +285,36 @@ public:
void SetIsKeyframing(bool keyframing, int element)
{
Q_ASSERT(IsKeyframable());
if (IsKeyframable()) {
qDebug() << "Ignored set keyframing because this input is not keyframable";
return;
}
GetImmediate(element)->set_is_keyframing(keyframing);
emit KeyframeEnableChanged(keyframing, element);
}
void ArrayAppend()
{
ArrayResize(ArraySize() + 1);
}
/// Alias for ArrayResize(ArraySize() + 1)
void ArrayAppend(bool undoable = false);
void ArrayInsert(int index);
void ArrayInsert(int index, bool undoable = false);
void ArrayRemove(int index);
void ArrayRemove(int index, bool undoable = false);
void ArrayPrepend();
/// Alias for ArrayInsert(0)
void ArrayPrepend(bool undoable = false);
void ArrayResize(int size);
void ArrayResize(int size, bool undoable = false);
/// Alias for ArrayResize(ArraySize() - 1)
void ArrayRemoveLast(bool undoable = false);
int ArraySize() const
{
return array_size_;
}
void ArrayRemoveLast();
int GetNumberOfKeyframeTracks() const
{
return NodeValue::get_number_of_keyframe_tracks(data_type_);
@@ -318,7 +327,7 @@ public:
*/
QVariant GetValueAtTime(const rational& time, int element = -1) const;
QVector<QVariant> GetSplitValuesAtTime(const rational& time, int element = -1) const;
SplitValue GetSplitValuesAtTime(const rational& time, int element = -1) const;
/**
* @brief Calculate the stored value for a specific track
@@ -378,13 +387,139 @@ protected:
virtual void childEvent(QChildEvent* e) override;
private:
void Init(Node *parent, const QString& id, NodeValue::Type type, const QVector<QVariant> &default_val);
class ArrayInsertCommand : public UndoCommand
{
public:
ArrayInsertCommand(NodeInput* input, int index) :
input_(input),
index_(index)
{
}
virtual Project* GetRelevantProject() const override;
virtual void redo() override
{
input_->ArrayInsert(index_, false);
}
virtual void undo() override
{
input_->ArrayRemove(index_, false);
}
private:
NodeInput* input_;
int index_;
};
class ArrayRemoveCommand : public UndoCommand
{
public:
ArrayRemoveCommand(NodeInput* input, int index) :
input_(input),
index_(index)
{
}
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo() override
{
// Save immediate data
is_keyframing_ = input_->IsKeyframing(index_);
standard_value_ = input_->GetSplitStandardValue(index_);
keyframes_ = input_->GetImmediate(index_)->keyframe_tracks();
input_->GetImmediate(index_)->delete_all_keyframes(&memory_manager_);
input_->ArrayRemove(index_, false);
}
virtual void undo() override
{
input_->ArrayInsert(index_, false);
// Restore keyframes
foreach (const NodeKeyframeTrack& track, keyframes_) {
foreach (NodeKeyframe* key, track) {
key->setParent(input_);
}
}
input_->SetSplitStandardValue(standard_value_, index_);
input_->SetIsKeyframing(is_keyframing_, index_);
}
private:
NodeInput* input_;
int index_;
SplitValue standard_value_;
bool is_keyframing_;
QVector<NodeKeyframeTrack> keyframes_;
QObject memory_manager_;
};
class ArrayResizeCommand : public UndoCommand
{
public:
ArrayResizeCommand(NodeInput* input, int size) :
input_(input),
size_(size)
{}
virtual void redo() override
{
old_size_ = input_->array_size_;
if (old_size_ > size_) {
// Decreasing in size, disconnect any extraneous edges
for (int i=size_; i<old_size_; i++) {
try {
Node* output = input_->edges().at(i);
removed_connections_.insert(i, output);
DisconnectEdge(output, input_, i);
} catch (std::out_of_range&) {}
}
}
input_->ArrayResizeInternal(size_);
}
virtual void undo() override
{
for (auto it=removed_connections_.cbegin(); it!=removed_connections_.cend(); it++) {
ConnectEdge(it.value(), input_, it.key());
}
removed_connections_.clear();
input_->ArrayResizeInternal(old_size_);
}
virtual Project* GetRelevantProject() const override;
private:
NodeInput* input_;
int size_;
int old_size_;
QHash<int, Node*> removed_connections_;
};
void ClearElement(int index);
void Init(Node *parent, const QString& id, NodeValue::Type type, const SplitValue &default_val);
void LoadImmediate(QXmlStreamReader *reader, int element, XMLNodeData& xml_node_data, const QAtomicInt* cancelled);
void SaveImmediate(QXmlStreamWriter *writer, int element) const;
void ChangeArraySizeInternal(int size);
void ArrayResizeInternal(int size);
NodeInputImmediate* CreateImmediate();
@@ -426,7 +561,7 @@ private:
QVector<NodeInputImmediate*> subinputs_;
QVector<QVariant> default_value_;
SplitValue default_value_;
/**
* @brief Unique identifier of this input within this node
+4 -4
View File
@@ -106,21 +106,21 @@ void NodeInputDragger::End()
return;
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
if (input_->IsKeyframing(element_)) {
if (drag_created_key_) {
// We created a keyframe in this process
new NodeParamInsertKeyframeCommand(input_, dragging_key_, command);
command->add_child(new NodeParamInsertKeyframeCommand(input_, dragging_key_));
}
// We just set a keyframe's value
// We do this even when inserting a keyframe because we don't actually perform an insert in this undo command
// so this will ensure the ValueChanged() signal is sent correctly
new NodeParamSetKeyframeValueCommand(dragging_key_, end_value_, start_value_, command);
command->add_child(new NodeParamSetKeyframeValueCommand(dragging_key_, end_value_, start_value_));
} else {
// We just set the standard value
new NodeParamSetStandardValueCommand(input_, track_, element_, end_value_, start_value_, command);
command->add_child(new NodeParamSetStandardValueCommand(input_, track_, element_, end_value_, start_value_));
}
Core::instance()->undo_stack()->push(command);
+7 -3
View File
@@ -27,7 +27,7 @@
namespace olive {
NodeInputImmediate::NodeInputImmediate(NodeValue::Type type, const QVector<QVariant> &default_val) :
NodeInputImmediate::NodeInputImmediate(NodeValue::Type type, const SplitValue &default_val) :
keyframing_(false)
{
int track_size = NodeValue::get_number_of_keyframe_tracks(type);
@@ -43,7 +43,7 @@ void NodeInputImmediate::set_standard_value_on_track(const QVariant &value, int
standard_value_.replace(track, value);
}
void NodeInputImmediate::set_split_standard_value(const QVector<QVariant> &value)
void NodeInputImmediate::set_split_standard_value(const SplitValue &value)
{
for (int i=0; i<value.size() && i<standard_value_.size(); i++) {
standard_value_[i] = value[i];
@@ -267,13 +267,17 @@ void NodeInputImmediate::remove_keyframe(NodeKeyframe *key)
keyframe_tracks_[key->track()].removeOne(key);
}
void NodeInputImmediate::delete_all_keyframes()
void NodeInputImmediate::delete_all_keyframes(QObject* parent)
{
for (NodeKeyframeTrack& track : keyframe_tracks_) {
while (!track.isEmpty()) {
if (parent) {
track.first()->setParent(parent);
} else {
delete track.first();
}
}
}
}
}
+6 -5
View File
@@ -25,6 +25,7 @@
#include "common/xmlutils.h"
#include "node/keyframe.h"
#include "node/value.h"
#include "splitvalue.h"
namespace olive {
@@ -33,7 +34,7 @@ class NodeInput;
class NodeInputImmediate
{
public:
NodeInputImmediate(NodeValue::Type type, const QVector<QVariant>& default_val);
NodeInputImmediate(NodeValue::Type type, const SplitValue& default_val);
/**
* @brief Internal insert function, automatically does an insertion sort based on the keyframe's time
@@ -42,19 +43,19 @@ public:
void remove_keyframe(NodeKeyframe* key);
void delete_all_keyframes();
void delete_all_keyframes(QObject *parent = nullptr);
/**
* @brief Get non-keyframed value split into components (the way it's stored)
*/
const QVector<QVariant>& get_split_standard_value() const
const SplitValue& get_split_standard_value() const
{
return standard_value_;
}
void set_standard_value_on_track(const QVariant &value, int track = 0);
void set_split_standard_value(const QVector<QVariant>& value);
void set_split_standard_value(const SplitValue& value);
/**
* @brief Retrieve a list of keyframe objects for all tracks at a given time
@@ -149,7 +150,7 @@ private:
/**
* @brief Non-keyframed value
*/
QVector<QVariant> standard_value_;
SplitValue standard_value_;
/**
* @brief Internal keyframe array
+7 -2
View File
@@ -45,14 +45,19 @@ NodeKeyframe::~NodeKeyframe()
setParent(nullptr);
}
NodeKeyframe *NodeKeyframe::copy(QObject* parent) const
NodeKeyframe *NodeKeyframe::copy(int element, QObject *parent) const
{
NodeKeyframe* copy = new NodeKeyframe(time_, value_, type_, track_, element_, parent);
NodeKeyframe* copy = new NodeKeyframe(time_, value_, type_, track_, element, parent);
copy->bezier_control_in_ = bezier_control_in_;
copy->bezier_control_out_ = bezier_control_out_;
return copy;
}
NodeKeyframe *NodeKeyframe::copy(QObject* parent) const
{
return copy(element_, parent);
}
NodeInput *NodeKeyframe::parent() const
{
return static_cast<NodeInput*>(QObject::parent());
+1
View File
@@ -65,6 +65,7 @@ public:
virtual ~NodeKeyframe() override;
NodeKeyframe* copy(int element, QObject* parent = nullptr) const;
NodeKeyframe* copy(QObject* parent = nullptr) const;
NodeInput* parent() const;
+4 -4
View File
@@ -247,7 +247,7 @@ TimeRange Node::OutputTimeAdjustment(NodeInput *, int, const TimeRange &input_ti
return input_time;
}
QVector<Node *> Node::CopyDependencyGraph(const QVector<Node *> &nodes, QUndoCommand* command)
QVector<Node *> Node::CopyDependencyGraph(const QVector<Node *> &nodes, MultiUndoCommand *command)
{
int nb_nodes = nodes.size();
@@ -263,7 +263,7 @@ QVector<Node *> Node::CopyDependencyGraph(const QVector<Node *> &nodes, QUndoCom
// Add to graph
NodeGraph* graph = static_cast<NodeGraph*>(nodes.at(i)->parent());
if (command) {
new NodeAddCommand(graph, c, command);
command->add_child(new NodeAddCommand(graph, c));
} else {
c->setParent(graph);
}
@@ -277,7 +277,7 @@ QVector<Node *> Node::CopyDependencyGraph(const QVector<Node *> &nodes, QUndoCom
return copies;
}
void Node::CopyDependencyGraph(const QVector<Node *> &src, const QVector<Node *> &dst, QUndoCommand *command)
void Node::CopyDependencyGraph(const QVector<Node *> &src, const QVector<Node *> &dst, MultiUndoCommand *command)
{
for (int i=0; i<src.size(); i++) {
foreach (NodeInput* input, src.at(i)->inputs()) {
@@ -290,7 +290,7 @@ void Node::CopyDependencyGraph(const QVector<Node *> &src, const QVector<Node *>
NodeInput* dst_input = dst.at(i)->GetInputWithID(input->id());
if (command) {
new NodeEdgeAddCommand(dst_output, dst_input, it->first, command);
command->add_child(new NodeEdgeAddCommand(dst_output, dst_input, it->first));
} else {
ConnectEdge(dst_output, dst_input, it->first);
}
+2 -2
View File
@@ -368,8 +368,8 @@ public:
/**
* @brief Clones a set of nodes and connects the new ones the way the old ones were
*/
static QVector<Node*> CopyDependencyGraph(const QVector<Node*>& nodes, QUndoCommand *command);
static void CopyDependencyGraph(const QVector<Node*>& src, const QVector<Node*>& dst, QUndoCommand *command);
static QVector<Node*> CopyDependencyGraph(const QVector<Node*>& nodes, MultiUndoCommand *command);
static void CopyDependencyGraph(const QVector<Node*>& src, const QVector<Node*>& dst, MultiUndoCommand *command);
/**
* @brief Return whether this Node can be deleted or not
+2 -2
View File
@@ -56,7 +56,7 @@ void NodeCopyPasteService::CopyNodesToClipboard(const QVector<Node *> &nodes, vo
Core::CopyStringToClipboard(copy_str);
}
QVector<Node *> NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph, QUndoCommand* command, void *userdata)
QVector<Node *> NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph, MultiUndoCommand* command, void *userdata)
{
QString clipboard = Core::PasteStringFromClipboard();
@@ -121,7 +121,7 @@ QVector<Node *> NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph,
// Add all nodes to graph
foreach (Node* n, pasted_nodes) {
new NodeAddCommand(graph, n, command);
command->add_child(new NodeAddCommand(graph, n));
}
// Make connections
+1 -1
View File
@@ -37,7 +37,7 @@ public:
protected:
void CopyNodesToClipboard(const QVector<Node *> &nodes, void* userdata = nullptr);
QVector<Node*> PasteNodesFromClipboard(NodeGraph *graph, QUndoCommand *command, void* userdata = nullptr);
QVector<Node*> PasteNodesFromClipboard(NodeGraph *graph, MultiUndoCommand *command, void* userdata = nullptr);
virtual void CopyNodesToClipboardInternal(QXmlStreamWriter *writer, void* userdata);
+33
View File
@@ -0,0 +1,33 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2020 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 SPLITVALUE_H
#define SPLITVALUE_H
#include <QVariant>
#include <QVector>
namespace olive {
using SplitValue = QVector<QVariant>;
}
#endif // SPLITVALUE_H
+17 -24
View File
@@ -330,9 +330,9 @@ bool ProjectViewModel::dropMimeData(const QMimeData *data, Qt::DropAction action
quint64 enabled_streams;
// Loop through all data
QUndoCommand* move_command = new QUndoCommand();
MultiUndoCommand* move_command = new MultiUndoCommand();
move_command->setText(tr("Move Items"));
move_command->set_name(tr("Move Items"));
while (!stream.atEnd()) {
stream >> enabled_streams >> r >> item_ptr;
@@ -343,9 +343,7 @@ bool ProjectViewModel::dropMimeData(const QMimeData *data, Qt::DropAction action
// no-op
if (item != drop_location && item->parent() != drop_location && !ItemIsParentOfChild(item, drop_location)) {
MoveItemCommand* mic = new MoveItemCommand(this, item, static_cast<Folder*>(drop_location), move_command);
Q_UNUSED(mic)
move_command->add_child(new MoveItemCommand(this, item, static_cast<Folder*>(drop_location)));
}
}
@@ -499,16 +497,14 @@ QModelIndex ProjectViewModel::CreateIndexFromItem(Item *item, int column)
ProjectViewModel::MoveItemCommand::MoveItemCommand(ProjectViewModel *model,
Item *item,
Folder *destination,
QUndoCommand *parent) :
UndoCommand(parent),
Folder *destination) :
model_(model),
item_(item),
destination_(destination)
{
source_ = static_cast<Folder*>(item->parent());
setText(QCoreApplication::translate("MoveItemCommand", "Move Item"));
set_name(QCoreApplication::translate("MoveItemCommand", "Move Item"));
}
Project *ProjectViewModel::MoveItemCommand::GetRelevantProject() const
@@ -516,25 +512,24 @@ Project *ProjectViewModel::MoveItemCommand::GetRelevantProject() const
return model_->project();
}
void ProjectViewModel::MoveItemCommand::redo_internal()
void ProjectViewModel::MoveItemCommand::redo()
{
model_->MoveItemInternal(item_, destination_);
}
void ProjectViewModel::MoveItemCommand::undo_internal()
void ProjectViewModel::MoveItemCommand::undo()
{
model_->MoveItemInternal(item_, source_);
}
ProjectViewModel::RenameItemCommand::RenameItemCommand(ProjectViewModel* model, Item *item, const QString &name, QUndoCommand *parent) :
UndoCommand(parent),
ProjectViewModel::RenameItemCommand::RenameItemCommand(ProjectViewModel* model, Item *item, const QString &name) :
model_(model),
item_(item),
new_name_(name)
{
old_name_ = item->name();
setText(QCoreApplication::translate("RenameItemCommand", "Rename Item"));
set_name(QCoreApplication::translate("RenameItemCommand", "Rename Item"));
}
Project *ProjectViewModel::RenameItemCommand::GetRelevantProject() const
@@ -542,18 +537,17 @@ Project *ProjectViewModel::RenameItemCommand::GetRelevantProject() const
return model_->project();
}
void ProjectViewModel::RenameItemCommand::redo_internal()
void ProjectViewModel::RenameItemCommand::redo()
{
model_->RenameChild(item_, new_name_);
}
void ProjectViewModel::RenameItemCommand::undo_internal()
void ProjectViewModel::RenameItemCommand::undo()
{
model_->RenameChild(item_, old_name_);
}
ProjectViewModel::AddItemCommand::AddItemCommand(ProjectViewModel* model, Item* folder, Item* child, QUndoCommand* parent) :
UndoCommand(parent),
ProjectViewModel::AddItemCommand::AddItemCommand(ProjectViewModel* model, Item* folder, Item* child) :
model_(model),
parent_(folder),
child_(child)
@@ -571,18 +565,17 @@ Project *ProjectViewModel::AddItemCommand::GetRelevantProject() const
return model_->project();
}
void ProjectViewModel::AddItemCommand::redo_internal()
void ProjectViewModel::AddItemCommand::redo()
{
model_->AddChild(parent_, child_);
}
void ProjectViewModel::AddItemCommand::undo_internal()
void ProjectViewModel::AddItemCommand::undo()
{
model_->RemoveChild(parent_, child_, &memory_manager_);
}
ProjectViewModel::RemoveItemCommand::RemoveItemCommand(ProjectViewModel *model, Item *item, QUndoCommand *parent) :
UndoCommand(parent),
ProjectViewModel::RemoveItemCommand::RemoveItemCommand(ProjectViewModel *model, Item *item) :
model_(model),
item_(item)
{
@@ -599,12 +592,12 @@ Project *ProjectViewModel::RemoveItemCommand::GetRelevantProject() const
return model_->project();
}
void ProjectViewModel::RemoveItemCommand::redo_internal()
void ProjectViewModel::RemoveItemCommand::redo()
{
model_->RemoveChild(parent_, item_, &memory_manager_);
}
void ProjectViewModel::RemoveItemCommand::undo_internal()
void ProjectViewModel::RemoveItemCommand::undo()
{
model_->AddChild(parent_, item_);
}
+17 -21
View File
@@ -110,18 +110,17 @@ public:
QModelIndex CreateIndexFromItem(Item* item, int column = 0);
/**
* @brief A QUndoCommand for moving an item from one folder to another folder
* @brief An UndoCommand for moving an item from one folder to another folder
*/
class MoveItemCommand : public UndoCommand {
public:
MoveItemCommand(ProjectViewModel* model, Item* item, Folder* destination, QUndoCommand* parent = nullptr);
MoveItemCommand(ProjectViewModel* model, Item* item, Folder* destination);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void redo() override;
virtual void undo_internal() override;
virtual void undo() override;
private:
ProjectViewModel* model_;
@@ -132,18 +131,17 @@ public:
};
/**
* @brief A QUndoCommand for renaming an item
* @brief An UndoCommand for renaming an item
*/
class RenameItemCommand : public UndoCommand {
public:
RenameItemCommand(ProjectViewModel* model, Item* item, const QString& name, QUndoCommand* parent = nullptr);
RenameItemCommand(ProjectViewModel* model, Item* item, const QString& name);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void redo() override;
virtual void undo_internal() override;
virtual void undo() override;
private:
ProjectViewModel* model_;
@@ -153,18 +151,17 @@ public:
};
/**
* @brief A QUndoCommand for adding an item
* @brief An UndoCommand for adding an item
*/
class AddItemCommand : public UndoCommand {
public:
AddItemCommand(ProjectViewModel* model, Item* folder, Item *child, QUndoCommand* parent = nullptr);
AddItemCommand(ProjectViewModel* model, Item* folder, Item *child);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void redo() override;
virtual void undo_internal() override;
virtual void undo() override;
private:
ProjectViewModel* model_;
@@ -179,14 +176,13 @@ public:
*/
class RemoveItemCommand : public UndoCommand {
public:
RemoveItemCommand(ProjectViewModel* model, Item* item, QUndoCommand* parent = nullptr);
RemoveItemCommand(ProjectViewModel* model, Item* item);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void redo() override;
virtual void undo_internal() override;
virtual void undo() override;
private:
ProjectViewModel* model_;
@@ -240,8 +236,8 @@ private:
* This function will emit a signal indicating that rows are moving, set `destination` as the new parent of `item`,
* and then emit a signal that the row has finished moving.
*
* It's not recommended to use this function directly in most cases since it does not create a QUndoCommand allowing
* the user to undo the move. Instead this function should primarily be called from QUndoCommands belonging to this
* It's not recommended to use this function directly in most cases since it does not create an UndoCommand allowing
* the user to undo the move. Instead this function should primarily be called from UndoCommands belonging to this
* class (e.g. MoveItemCommand).
*/
void MoveItemInternal(Item* item, Item* destination);
+6 -8
View File
@@ -50,7 +50,7 @@ const int &ProjectImportTask::GetFileCount() const
bool ProjectImportTask::Run()
{
command_ = new QUndoCommand();
command_ = new MultiUndoCommand();
int imported = 0;
@@ -65,7 +65,7 @@ bool ProjectImportTask::Run()
}
}
void ProjectImportTask::Import(Folder *folder, QFileInfoList import, int &counter, QUndoCommand* parent_command)
void ProjectImportTask::Import(Folder *folder, QFileInfoList import, int &counter, MultiUndoCommand* parent_command)
{
for (int i=0; i<import.size(); i++) {
if (IsCancelled()) {
@@ -100,10 +100,9 @@ void ProjectImportTask::Import(Folder *folder, QFileInfoList import, int &counte
f->set_name(file_info.fileName());
// Create undoable command that adds the items to the model
new ProjectViewModel::AddItemCommand(model_,
parent_command->add_child(new ProjectViewModel::AddItemCommand(model_,
folder,
f,
parent_command);
f));
// Recursively follow this path
Import(f, entry_list, counter, parent_command);
@@ -122,10 +121,9 @@ void ProjectImportTask::Import(Folder *folder, QFileInfoList import, int &counte
ValidateImageSequence(footage, import, i);
// Create undoable command that adds the items to the model
new ProjectViewModel::AddItemCommand(model_,
parent_command->add_child(new ProjectViewModel::AddItemCommand(model_,
folder,
footage,
parent_command);
footage));
} else {
// Add to list so we can tell the user about it later
invalid_files_.append(file_info.absoluteFilePath());
+3 -3
View File
@@ -38,7 +38,7 @@ public:
const int& GetFileCount() const;
QUndoCommand* GetCommand() const
MultiUndoCommand* GetCommand() const
{
return command_;
}
@@ -57,7 +57,7 @@ protected:
virtual bool Run() override;
private:
void Import(Folder* folder, QFileInfoList import, int& counter, QUndoCommand *parent_command);
void Import(Folder* folder, QFileInfoList import, int& counter, MultiUndoCommand *parent_command);
void ValidateImageSequence(Footage *footage, QFileInfoList &info_list, int index);
@@ -67,7 +67,7 @@ private:
static int64_t GetImageSequenceLimit(const QString &start_fn, int64_t start, bool up);
QUndoCommand* command_;
MultiUndoCommand* command_;
ProjectViewModel* model_;
+20 -16
View File
@@ -24,34 +24,38 @@
namespace olive {
UndoCommand::UndoCommand(QUndoCommand *parent) :
QUndoCommand(parent)
void MultiUndoCommand::redo()
{
for (auto it=children_.cbegin(); it!=children_.cend(); it++) {
(*it)->redo_and_set_modified();
}
}
void UndoCommand::redo()
void MultiUndoCommand::undo()
{
redo_internal();
modified_ = GetRelevantProject()->is_modified();
GetRelevantProject()->set_modified(true);
for (auto it=children_.crbegin(); it!=children_.crend(); it++) {
(*it)->undo_and_set_modified();
}
}
void UndoCommand::undo()
void UndoCommand::redo_and_set_modified()
{
undo_internal();
redo();
GetRelevantProject()->set_modified(modified_);
project_ = GetRelevantProject();
if (project_) {
modified_ = project_->is_modified();
project_->set_modified(true);
}
}
void UndoCommand::redo_internal()
void UndoCommand::undo_and_set_modified()
{
QUndoCommand::redo();
}
undo();
void UndoCommand::undo_internal()
{
QUndoCommand::undo();
if (project_) {
project_->set_modified(modified_);
}
}
}
+61 -9
View File
@@ -21,31 +21,83 @@
#ifndef UNDOCOMMAND_H
#define UNDOCOMMAND_H
#include <QUndoCommand>
#include <list>
#include <QString>
#include <vector>
#include "common/define.h"
#include "node/graph.h"
namespace olive {
class Project;
class UndoCommand : public QUndoCommand
class UndoCommand
{
public:
UndoCommand(QUndoCommand* parent = nullptr);
UndoCommand() = default;
virtual ~UndoCommand(){}
DISABLE_COPY_MOVE(UndoCommand)
virtual void redo() = 0;
virtual void undo() = 0;
void redo_and_set_modified();
void undo_and_set_modified();
virtual Project* GetRelevantProject() const = 0;
const QString& name() const
{
return name_;
}
void set_name(const QString& name)
{
name_ = name;
}
private:
bool modified_;
QString name_;
Project* project_;
};
class MultiUndoCommand : public UndoCommand
{
public:
MultiUndoCommand() = default;
virtual void redo() override;
virtual void undo() override;
virtual Project* GetRelevantProject() const = 0;
virtual Project* GetRelevantProject() const override
{
return nullptr;
}
protected:
virtual void redo_internal();
virtual void undo_internal();
void add_child(UndoCommand* command)
{
children_.push_back(command);
}
int child_count() const
{
return children_.size();
}
UndoCommand* child(int i) const
{
return children_[i];
}
private:
bool modified_;
std::vector<UndoCommand*> children_;
};
+96 -2
View File
@@ -20,15 +20,109 @@
#include "undostack.h"
#include <QCoreApplication>
namespace olive {
void UndoStack::pushIfHasChildren(QUndoCommand *command)
const int UndoStack::kMaxUndoCommands = 200;
UndoStack::UndoStack()
{
if (command->childCount() > 0) {
undo_action_ = new QAction();
connect(undo_action_, &QAction::triggered, this, &UndoStack::undo);
redo_action_ = new QAction();
connect(redo_action_, &QAction::triggered, this, &UndoStack::redo);
UpdateActions();
}
UndoStack::~UndoStack()
{
clear();
delete undo_action_;
delete redo_action_;
}
void UndoStack::pushIfHasChildren(MultiUndoCommand *command)
{
if (command->child_count() > 0) {
push(command);
} else {
delete command;
}
}
void UndoStack::push(UndoCommand *command)
{
command->redo_and_set_modified();
commands_.push_back(command);
if (commands_.size() > kMaxUndoCommands) {
delete commands_.front();
commands_.pop_front();
}
if (CanRedo()) {
for (auto it=undone_commands_.cbegin(); it!=undone_commands_.cend(); it++) {
delete (*it);
}
undone_commands_.clear();
}
UpdateActions();
}
void UndoStack::undo()
{
if (CanUndo()) {
// Undo most recently done command
commands_.back()->undo_and_set_modified();
// Place at the front of the "undone commands" list
undone_commands_.push_front(commands_.back());
// Remove undone command from the commands list
commands_.pop_back();
// Update actions
UpdateActions();
}
}
void UndoStack::redo()
{
if (CanRedo()) {
// Redo most recently undone command
undone_commands_.front()->redo_and_set_modified();
// Place at the back of the done commands list
commands_.push_back(undone_commands_.front());
// Remove done command from undone list
undone_commands_.pop_front();
// Update actions
UpdateActions();
}
}
void UndoStack::clear()
{
for (auto it=commands_.cbegin(); it!=commands_.cend(); it++) {
delete (*it);
}
commands_.clear();
}
void UndoStack::UpdateActions()
{
undo_action_->setEnabled(CanUndo());
redo_action_->setEnabled(CanRedo());
undo_action_->setText(QCoreApplication::translate("UndoStack", "Undo %1").arg(CanUndo() ? commands_.back()->name() : QString()));
redo_action_->setText(QCoreApplication::translate("UndoStack", "Redo %1").arg(CanRedo() ? undone_commands_.front()->name() : QString()));
}
}
+53 -3
View File
@@ -21,20 +21,70 @@
#ifndef UNDOSTACK_H
#define UNDOSTACK_H
#include <QUndoStack>
#include <QAction>
#include "common/define.h"
#include "undo/undocommand.h"
namespace olive {
class UndoStack : public QUndoStack {
class UndoStack : public QObject
{
Q_OBJECT
public:
UndoStack();
virtual ~UndoStack() override;
/**
* @brief A wrapper for push() that either pushes if the command has children or deletes if not
*
* This function takes ownership of `command`, and may delete it so it should never be accessed after this call.
*/
void pushIfHasChildren(QUndoCommand* command);
void pushIfHasChildren(MultiUndoCommand* command);
void push(UndoCommand* command);
void clear();
bool CanUndo() const
{
return !commands_.empty();
}
bool CanRedo() const
{
return !undone_commands_.empty();
}
void UpdateActions();
QAction* GetUndoAction()
{
return undo_action_;
}
QAction* GetRedoAction()
{
return redo_action_;
}
public slots:
void undo();
void redo();
private:
static const int kMaxUndoCommands;
std::list<UndoCommand*> commands_;
std::list<UndoCommand*> undone_commands_;
QAction* undo_action_;
QAction* redo_action_;
};
}
+2 -2
View File
@@ -336,12 +336,12 @@ void CurveWidget::KeyframeTypeButtonTriggered(bool checked)
// Ensure only the appropriate button is checked
SetKeyframeButtonCheckedFromType(new_type);
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
foreach (QGraphicsItem* item, selected) {
KeyframeViewItem* key_item = static_cast<KeyframeViewItem*>(item);
new KeyframeSetTypeCommand(key_item->key(), new_type, command);
command->add_child(new KeyframeSetTypeCommand(key_item->key(), new_type));
}
Core::instance()->undo_stack()->push(command);
+15 -20
View File
@@ -59,13 +59,13 @@ void KeyframeViewBase::Clear()
void KeyframeViewBase::DeleteSelected()
{
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
QMap<NodeKeyframe*, KeyframeViewItem*>::const_iterator i;
for (i=item_map_.constBegin(); i!=item_map_.constEnd(); i++) {
if (i.value()->isSelected()) {
new NodeParamRemoveKeyframeCommand(i.key(), command);
command->add_child(new NodeParamRemoveKeyframeCommand(i.key()));
}
}
@@ -307,46 +307,42 @@ void KeyframeViewBase::mouseReleaseEvent(QMouseEvent *event)
if (dragging_) {
if (dragging_bezier_point_) {
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
// Create undo command with the current bezier point and the old one
new KeyframeSetBezierControlPoint(dragging_bezier_point_->key(),
command->add_child(new KeyframeSetBezierControlPoint(dragging_bezier_point_->key(),
dragging_bezier_point_->mode(),
dragging_bezier_point_->key()->bezier_control(dragging_bezier_point_->mode()),
dragging_bezier_point_start_,
command);
dragging_bezier_point_start_));
if (!(event->modifiers() & Qt::ControlModifier)) {
auto opposing_type = NodeKeyframe::get_opposing_bezier_type(dragging_bezier_point_->mode());
new KeyframeSetBezierControlPoint(dragging_bezier_point_->key(),
command->add_child(new KeyframeSetBezierControlPoint(dragging_bezier_point_->key(),
opposing_type,
dragging_bezier_point_->key()->bezier_control(opposing_type),
dragging_bezier_point_opposing_start_,
command);
dragging_bezier_point_opposing_start_));
}
dragging_bezier_point_ = nullptr;
Core::instance()->undo_stack()->push(command);
} else if (!selected_keys_.isEmpty()) {
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
foreach (const KeyframeItemAndTime& keypair, selected_keys_) {
NodeKeyframe* item = keypair.key->key();
// Commit movement
new NodeParamSetKeyframeTimeCommand(item,
command->add_child(new NodeParamSetKeyframeTimeCommand(item,
item->time(),
keypair.time,
command);
keypair.time));
// Commit value if we're setting a value
if (IsYAxisEnabled()) {
new NodeParamSetKeyframeValueCommand(item,
command->add_child(new NodeParamSetKeyframeValueCommand(item,
item->value(),
keypair.value,
command);
keypair.value));
}
}
@@ -497,11 +493,10 @@ void KeyframeViewBase::ShowContextMenu()
new_type = NodeKeyframe::kLinear;
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
foreach (QGraphicsItem* item, items) {
new KeyframeSetTypeCommand(static_cast<KeyframeViewItem*>(item)->key(),
new_type,
command);
command->add_child(new KeyframeSetTypeCommand(static_cast<KeyframeViewItem*>(item)->key(),
new_type));
}
Core::instance()->undo_stack()->pushIfHasChildren(command);
}
+7 -10
View File
@@ -26,8 +26,7 @@
namespace olive {
KeyframeSetTypeCommand::KeyframeSetTypeCommand(NodeKeyframe* key, NodeKeyframe::Type type, QUndoCommand *parent) :
UndoCommand(parent),
KeyframeSetTypeCommand::KeyframeSetTypeCommand(NodeKeyframe* key, NodeKeyframe::Type type) :
key_(key),
old_type_(key->type()),
new_type_(type)
@@ -39,18 +38,17 @@ Project *KeyframeSetTypeCommand::GetRelevantProject() const
return key_->parent()->parent()->parent()->project();
}
void KeyframeSetTypeCommand::redo_internal()
void KeyframeSetTypeCommand::redo()
{
key_->set_type(new_type_);
}
void KeyframeSetTypeCommand::undo_internal()
void KeyframeSetTypeCommand::undo()
{
key_->set_type(old_type_);
}
KeyframeSetBezierControlPoint::KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF& point, QUndoCommand *parent) :
UndoCommand(parent),
KeyframeSetBezierControlPoint::KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF& point) :
key_(key),
mode_(mode),
old_point_(key->bezier_control(mode_)),
@@ -58,8 +56,7 @@ KeyframeSetBezierControlPoint::KeyframeSetBezierControlPoint(NodeKeyframe* key,
{
}
KeyframeSetBezierControlPoint::KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF &new_point, const QPointF &old_point, QUndoCommand *parent) :
UndoCommand(parent),
KeyframeSetBezierControlPoint::KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF &new_point, const QPointF &old_point) :
key_(key),
mode_(mode),
old_point_(old_point),
@@ -72,12 +69,12 @@ Project *KeyframeSetBezierControlPoint::GetRelevantProject() const
return key_->parent()->parent()->parent()->project();
}
void KeyframeSetBezierControlPoint::redo_internal()
void KeyframeSetBezierControlPoint::redo()
{
key_->set_bezier_control(mode_, new_point_);
}
void KeyframeSetBezierControlPoint::undo_internal()
void KeyframeSetBezierControlPoint::undo()
{
key_->set_bezier_control(mode_, old_point_);
}
+7 -9
View File
@@ -28,13 +28,12 @@ namespace olive {
class KeyframeSetTypeCommand : public UndoCommand {
public:
KeyframeSetTypeCommand(NodeKeyframe* key, NodeKeyframe::Type type, QUndoCommand* parent = nullptr);
KeyframeSetTypeCommand(NodeKeyframe* key, NodeKeyframe::Type type);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
NodeKeyframe* key_;
@@ -47,14 +46,13 @@ private:
class KeyframeSetBezierControlPoint : public UndoCommand {
public:
KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF& point, QUndoCommand* parent = nullptr);
KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF& new_point, const QPointF& old_point, QUndoCommand* parent = nullptr);
KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF& point);
KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF& new_point, const QPointF& old_point);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
NodeKeyframe* key_;
+2 -2
View File
@@ -118,8 +118,8 @@ void MenuShared::AddItemsForNewMenu(Menu *m)
void MenuShared::AddItemsForEditMenu(Menu *m, bool for_clips)
{
m->addAction(Core::instance()->undo_stack()->createUndoAction(m));
m->addAction(Core::instance()->undo_stack()->createRedoAction(m));
m->addAction(Core::instance()->undo_stack()->GetUndoAction());
m->addAction(Core::instance()->undo_stack()->GetRedoAction());
m->addSeparator();
@@ -38,6 +38,13 @@ NodeParamViewArrayWidget::NodeParamViewArrayWidget(NodeInput *array, QWidget* pa
UpdateCounter();
}
void NodeParamViewArrayWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
QWidget::mouseDoubleClickEvent(event);
emit DoubleClicked();
}
void NodeParamViewArrayWidget::UpdateCounter()
{
count_lbl_->setText(tr("%1 element(s)").arg(array_->ArraySize()));
@@ -56,6 +56,12 @@ class NodeParamViewArrayWidget : public QWidget
public:
NodeParamViewArrayWidget(NodeInput* array, QWidget* parent = nullptr);
signals:
void DoubleClicked();
protected:
virtual void mouseDoubleClickEvent(QMouseEvent* event) override;
private:
NodeInput* array_;
+25 -12
View File
@@ -258,15 +258,14 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, NodeInput *input,
// Default to collapsed
array_collapse_btn->setChecked(false);
// Add data
array_collapse_btn->setProperty("input", Node::PtrToValue(input));
// Collapse button always goes into column 0
layout->addWidget(array_collapse_btn, row, 0);
// Connect signal to show/hide array params when toggled
connect(array_collapse_btn, &CollapseButton::toggled, this, &NodeParamViewItemBody::ArrayCollapseBtnPressed);
array_collapse_buttons_.insert(input, array_collapse_btn);
} else {
NodeParamViewArrayButton* insert_element_btn = new NodeParamViewArrayButton(NodeParamViewArrayButton::kAdd);
@@ -286,6 +285,7 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, NodeInput *input,
// Create a widget/input bridge for this input
ui_objects.widget_bridge = new NodeParamViewWidgetBridge(input, element, this);
connect(ui_objects.widget_bridge, &NodeParamViewWidgetBridge::ArrayWidgetDoubleClicked, this, &NodeParamViewItemBody::ToggleArrayExpanded);
// 0 is for the array collapse button, 1 is for the main label, widgets start at 2
const int widget_start = 2;
@@ -372,7 +372,7 @@ void NodeParamViewItemBody::SignalAllKeyframes()
foreach (const NodeKeyframeTrack& track, input->GetKeyframeTracks(i.key().element)) {
foreach (NodeKeyframe* key, track) {
InputAddedKeyframeInternal(input, key);
InputAddedKeyframeInternal(input, i.key().element, key);
}
}
}
@@ -406,7 +406,7 @@ void NodeParamViewItemBody::InputKeyframeEnableChanged(bool e, int element)
foreach (NodeKeyframe* key, track) {
if (e) {
// Add a keyframe item for each keyframe
InputAddedKeyframeInternal(input, key);
InputAddedKeyframeInternal(input, element, key);
} else {
// Remove each keyframe item
emit KeyframeRemoved(key);
@@ -420,13 +420,13 @@ void NodeParamViewItemBody::InputAddedKeyframe(NodeKeyframe* key)
// Get NodeInput that emitted this signal
NodeInput* input = static_cast<NodeInput*>(sender());
InputAddedKeyframeInternal(input, key);
InputAddedKeyframeInternal(input, key->element(), key);
}
void NodeParamViewItemBody::InputAddedKeyframeInternal(NodeInput *input, NodeKeyframe* keyframe)
void NodeParamViewItemBody::InputAddedKeyframeInternal(NodeInput *input, int element, NodeKeyframe* keyframe)
{
// Find its row in the parameters
QLabel* lbl = input_ui_map_.value(input).main_label;
QLabel* lbl = input_ui_map_.value({input, element}).main_label;
// Find label's Y position
QPoint lbl_center = lbl->rect().center();
@@ -439,7 +439,7 @@ void NodeParamViewItemBody::InputAddedKeyframeInternal(NodeInput *input, NodeKey
void NodeParamViewItemBody::ArrayCollapseBtnPressed(bool checked)
{
NodeInput* input = Node::ValueToPtr<NodeInput>(sender()->property("input"));
NodeInput* input = array_collapse_buttons_.key(static_cast<CollapseButton*>(sender()));
array_ui_.value(input).widget->setVisible(checked);
}
@@ -486,7 +486,7 @@ void NodeParamViewItemBody::ArrayAppendClicked()
{
for (auto it=array_ui_.cbegin(); it!=array_ui_.cend(); it++) {
if (it.value().append_btn == sender()) {
it.key()->ArrayAppend();
it.key()->ArrayAppend(true);
break;
}
}
@@ -498,7 +498,7 @@ void NodeParamViewItemBody::ArrayInsertClicked()
if (it.value().array_insert_btn == sender()) {
// Found our input and element
const Node::InputConnection& ic = it.key();
ic.input->ArrayInsert(ic.element);
ic.input->ArrayInsert(ic.element, true);
break;
}
}
@@ -510,12 +510,25 @@ void NodeParamViewItemBody::ArrayRemoveClicked()
if (it.value().array_remove_btn == sender()) {
// Found our input and element
const Node::InputConnection& ic = it.key();
ic.input->ArrayRemove(ic.element);
ic.input->ArrayRemove(ic.element, true);
break;
}
}
}
void NodeParamViewItemBody::ToggleArrayExpanded()
{
NodeParamViewWidgetBridge* bridge = static_cast<NodeParamViewWidgetBridge*>(sender());
for (auto it=input_ui_map_.cbegin(); it!=input_ui_map_.cend(); it++) {
if (it.value().widget_bridge == bridge) {
CollapseButton* b = array_collapse_buttons_.value(it.key().input);
b->setChecked(!b->isChecked());
return;
}
}
}
NodeParamViewItemBody::InputUI::InputUI() :
main_label(nullptr),
widget_bridge(nullptr),
+5 -1
View File
@@ -97,7 +97,7 @@ private:
void UpdateUIForEdgeConnection(NodeInput* input, int element);
void InputAddedKeyframeInternal(NodeInput* input, NodeKeyframe* keyframe);
void InputAddedKeyframeInternal(NodeInput* input, int element, NodeKeyframe* keyframe);
struct InputUI {
InputUI();
@@ -121,6 +121,8 @@ private:
QHash<NodeInput*, ArrayUI> array_ui_;
QHash<NodeInput*, CollapseButton*> array_collapse_buttons_;
/**
* @brief The column to place the keyframe controls in
*
@@ -149,6 +151,8 @@ private slots:
void ArrayRemoveClicked();
void ToggleArrayExpanded();
};
class NodeParamViewItem : public QDockWidget
@@ -145,7 +145,7 @@ void NodeParamViewKeyframeControl::ToggleKeyframe(bool e)
QVector<NodeKeyframe*> keys = input_->GetKeyframesAtTime(node_time, element_);
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
int nb_tracks = input_->GetNumberOfKeyframeTracks();
@@ -158,20 +158,19 @@ void NodeParamViewKeyframeControl::ToggleKeyframe(bool e)
i,
element_);
new NodeParamInsertKeyframeCommand(input_, key, command);
command->add_child(new NodeParamInsertKeyframeCommand(input_, key));
}
} else if (!e && !keys.isEmpty()) {
// Remove all keyframes at this time
foreach (NodeKeyframe* key, keys) {
new NodeParamRemoveKeyframeCommand(key, command);
command->add_child(new NodeParamRemoveKeyframeCommand(key));
if (input_->GetKeyframeTracks(key->track()).size() == 1) {
// If this was the last keyframe on this track, set the standard value to the value at this time too
new NodeParamSetStandardValueCommand(input_,
command->add_child(new NodeParamSetStandardValueCommand(input_,
key->track(),
element_,
input_->GetValueAtTimeForTrack(node_time, key->track(), element_),
command);
input_->GetValueAtTimeForTrack(node_time, key->track(), element_)));
}
}
}
@@ -228,11 +227,11 @@ void NodeParamViewKeyframeControl::KeyframeEnableChanged(bool e)
return;
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
if (e) {
// Enable keyframing
new NodeParamSetKeyframingCommand(input_, element_, true, command);
command->add_child(new NodeParamSetKeyframingCommand(input_, element_, true));
// Create one keyframe across all tracks here
const QVector<QVariant>& key_vals = input_->GetSplitStandardValue(element_);
@@ -244,7 +243,7 @@ void NodeParamViewKeyframeControl::KeyframeEnableChanged(bool e)
i,
element_);
new NodeParamInsertKeyframeCommand(input_, key, command);
command->add_child(new NodeParamInsertKeyframeCommand(input_, key));
}
} else {
// Confirm the user wants to clear all keyframes
@@ -259,17 +258,17 @@ void NodeParamViewKeyframeControl::KeyframeEnableChanged(bool e)
// Delete all keyframes
foreach (const NodeKeyframeTrack& track, input_->GetKeyframeTracks(element_)) {
for (int i=track.size()-1;i>=0;i--) {
new NodeParamRemoveKeyframeCommand(track.at(i), command);
command->add_child(new NodeParamRemoveKeyframeCommand(track.at(i)));
}
}
// Update standard value
for (int i=0;i<stored_vals.size();i++) {
new NodeParamSetStandardValueCommand(input_, i, element_, stored_vals.at(i), command);
command->add_child(new NodeParamSetStandardValueCommand(input_, i, element_, stored_vals.at(i)));
}
// Disable keyframing
new NodeParamSetKeyframingCommand(input_, element_, false, command);
command->add_child(new NodeParamSetKeyframingCommand(input_, element_, false));
} else {
// Disable action has effectively been ignored
+26 -30
View File
@@ -25,8 +25,7 @@
namespace olive {
NodeParamSetKeyframingCommand::NodeParamSetKeyframingCommand(NodeInput *input, int element, bool setting, QUndoCommand *parent) :
UndoCommand(parent),
NodeParamSetKeyframingCommand::NodeParamSetKeyframingCommand(NodeInput *input, int element, bool setting) :
input_(input),
setting_(setting),
element_(element)
@@ -39,26 +38,24 @@ Project *NodeParamSetKeyframingCommand::GetRelevantProject() const
return input_->parent()->parent()->project();
}
void NodeParamSetKeyframingCommand::redo_internal()
void NodeParamSetKeyframingCommand::redo()
{
input_->SetIsKeyframing(setting_, element_);
}
void NodeParamSetKeyframingCommand::undo_internal()
void NodeParamSetKeyframingCommand::undo()
{
input_->SetIsKeyframing(!setting_, element_);
}
NodeParamSetKeyframeValueCommand::NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant& value, QUndoCommand* parent) :
UndoCommand(parent),
NodeParamSetKeyframeValueCommand::NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant& value) :
key_(key),
old_value_(key_->value()),
new_value_(value)
{
}
NodeParamSetKeyframeValueCommand::NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant &new_value, const QVariant &old_value, QUndoCommand *parent) :
UndoCommand(parent),
NodeParamSetKeyframeValueCommand::NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant &new_value, const QVariant &old_value) :
key_(key),
old_value_(old_value),
new_value_(new_value)
@@ -71,18 +68,17 @@ Project *NodeParamSetKeyframeValueCommand::GetRelevantProject() const
return key_->parent()->parent()->parent()->project();
}
void NodeParamSetKeyframeValueCommand::redo_internal()
void NodeParamSetKeyframeValueCommand::redo()
{
key_->set_value(new_value_);
}
void NodeParamSetKeyframeValueCommand::undo_internal()
void NodeParamSetKeyframeValueCommand::undo()
{
key_->set_value(old_value_);
}
NodeParamInsertKeyframeCommand::NodeParamInsertKeyframeCommand(NodeInput *input, NodeKeyframe* keyframe, QUndoCommand* parent) :
UndoCommand(parent),
NodeParamInsertKeyframeCommand::NodeParamInsertKeyframeCommand(NodeInput *input, NodeKeyframe* keyframe) :
input_(input),
keyframe_(keyframe)
{
@@ -94,18 +90,17 @@ Project *NodeParamInsertKeyframeCommand::GetRelevantProject() const
return input_->parent()->parent()->project();
}
void NodeParamInsertKeyframeCommand::redo_internal()
void NodeParamInsertKeyframeCommand::redo()
{
keyframe_->setParent(input_);
}
void NodeParamInsertKeyframeCommand::undo_internal()
void NodeParamInsertKeyframeCommand::undo()
{
keyframe_->setParent(&memory_manager_);
}
NodeParamRemoveKeyframeCommand::NodeParamRemoveKeyframeCommand(NodeKeyframe* keyframe, QUndoCommand *parent) :
UndoCommand(parent),
NodeParamRemoveKeyframeCommand::NodeParamRemoveKeyframeCommand(NodeKeyframe* keyframe) :
input_(keyframe->parent()),
keyframe_(keyframe)
{
@@ -116,27 +111,25 @@ Project *NodeParamRemoveKeyframeCommand::GetRelevantProject() const
return input_->parent()->parent()->project();
}
void NodeParamRemoveKeyframeCommand::redo_internal()
void NodeParamRemoveKeyframeCommand::redo()
{
// Removes from input
keyframe_->setParent(&memory_manager_);
}
void NodeParamRemoveKeyframeCommand::undo_internal()
void NodeParamRemoveKeyframeCommand::undo()
{
keyframe_->setParent(input_);
}
NodeParamSetKeyframeTimeCommand::NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational &time, QUndoCommand *parent) :
UndoCommand(parent),
NodeParamSetKeyframeTimeCommand::NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational &time) :
key_(key),
old_time_(key->time()),
new_time_(time)
{
}
NodeParamSetKeyframeTimeCommand::NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational &new_time, const rational &old_time, QUndoCommand *parent) :
UndoCommand(parent),
NodeParamSetKeyframeTimeCommand::NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational &new_time, const rational &old_time) :
key_(key),
old_time_(old_time),
new_time_(new_time)
@@ -148,18 +141,17 @@ Project *NodeParamSetKeyframeTimeCommand::GetRelevantProject() const
return key_->parent()->parent()->parent()->project();
}
void NodeParamSetKeyframeTimeCommand::redo_internal()
void NodeParamSetKeyframeTimeCommand::redo()
{
key_->set_time(new_time_);
}
void NodeParamSetKeyframeTimeCommand::undo_internal()
void NodeParamSetKeyframeTimeCommand::undo()
{
key_->set_time(old_time_);
}
NodeParamSetStandardValueCommand::NodeParamSetStandardValueCommand(NodeInput *input, int track, int element, const QVariant &value, QUndoCommand *parent) :
UndoCommand(parent),
NodeParamSetStandardValueCommand::NodeParamSetStandardValueCommand(NodeInput *input, int track, int element, const QVariant &value) :
input_(input),
element_(element),
track_(track),
@@ -168,8 +160,7 @@ NodeParamSetStandardValueCommand::NodeParamSetStandardValueCommand(NodeInput *in
{
}
NodeParamSetStandardValueCommand::NodeParamSetStandardValueCommand(NodeInput *input, int track, int element, const QVariant &new_value, const QVariant &old_value, QUndoCommand *parent) :
UndoCommand(parent),
NodeParamSetStandardValueCommand::NodeParamSetStandardValueCommand(NodeInput *input, int track, int element, const QVariant &new_value, const QVariant &old_value) :
input_(input),
element_(element),
track_(track),
@@ -183,14 +174,19 @@ Project *NodeParamSetStandardValueCommand::GetRelevantProject() const
return input_->parent()->parent()->project();
}
void NodeParamSetStandardValueCommand::redo_internal()
void NodeParamSetStandardValueCommand::redo()
{
input_->SetStandardValueOnTrack(new_value_, track_, element_);
}
void NodeParamSetStandardValueCommand::undo_internal()
void NodeParamSetStandardValueCommand::undo()
{
input_->SetStandardValueOnTrack(old_value_, track_, element_);
}
Project *NodeParamArrayInsertCommand::GetRelevantProject() const
{
return input_->parent()->parent()->project();
}
}
+60 -33
View File
@@ -26,15 +26,15 @@
namespace olive {
class NodeParamSetKeyframingCommand : public UndoCommand {
class NodeParamSetKeyframingCommand : public UndoCommand
{
public:
NodeParamSetKeyframingCommand(NodeInput* input, int element, bool setting, QUndoCommand* parent = nullptr);
NodeParamSetKeyframingCommand(NodeInput* input, int element, bool setting);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
NodeInput* input_;
@@ -43,15 +43,15 @@ private:
};
class NodeParamInsertKeyframeCommand : public UndoCommand {
class NodeParamInsertKeyframeCommand : public UndoCommand
{
public:
NodeParamInsertKeyframeCommand(NodeInput* input, NodeKeyframe* keyframe, QUndoCommand *parent = nullptr);
NodeParamInsertKeyframeCommand(NodeInput* input, NodeKeyframe* keyframe);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
NodeInput* input_;
@@ -62,15 +62,15 @@ private:
};
class NodeParamRemoveKeyframeCommand : public UndoCommand {
class NodeParamRemoveKeyframeCommand : public UndoCommand
{
public:
NodeParamRemoveKeyframeCommand(NodeKeyframe* keyframe, QUndoCommand *parent = nullptr);
NodeParamRemoveKeyframeCommand(NodeKeyframe* keyframe);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
NodeInput* input_;
@@ -81,16 +81,16 @@ private:
};
class NodeParamSetKeyframeTimeCommand : public UndoCommand {
class NodeParamSetKeyframeTimeCommand : public UndoCommand
{
public:
NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational& time, QUndoCommand* parent = nullptr);
NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational& new_time, const rational& old_time, QUndoCommand* parent = nullptr);
NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational& time);
NodeParamSetKeyframeTimeCommand(NodeKeyframe* key, const rational& new_time, const rational& old_time);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
NodeKeyframe* key_;
@@ -100,16 +100,16 @@ private:
};
class NodeParamSetKeyframeValueCommand : public UndoCommand {
class NodeParamSetKeyframeValueCommand : public UndoCommand
{
public:
NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant& value, QUndoCommand* parent = nullptr);
NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant& new_value, const QVariant& old_value, QUndoCommand* parent = nullptr);
NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant& value);
NodeParamSetKeyframeValueCommand(NodeKeyframe* key, const QVariant& new_value, const QVariant& old_value);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
NodeKeyframe* key_;
@@ -119,16 +119,16 @@ private:
};
class NodeParamSetStandardValueCommand : public UndoCommand {
class NodeParamSetStandardValueCommand : public UndoCommand
{
public:
NodeParamSetStandardValueCommand(NodeInput* input, int track, int element, const QVariant& value, QUndoCommand* parent = nullptr);
NodeParamSetStandardValueCommand(NodeInput* input, int track, int element, const QVariant& new_value, const QVariant& old_value, QUndoCommand* parent = nullptr);
NodeParamSetStandardValueCommand(NodeInput* input, int track, int element, const QVariant& value);
NodeParamSetStandardValueCommand(NodeInput* input, int track, int element, const QVariant& new_value, const QVariant& old_value);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
NodeInput* input_;
@@ -140,6 +140,33 @@ private:
};
class NodeParamArrayInsertCommand : public UndoCommand
{
public:
NodeParamArrayInsertCommand(NodeInput* input, int index) :
input_(input),
index_(index)
{
}
virtual Project* GetRelevantProject() const override;
virtual void redo() override
{
input_->ArrayInsert(index_);
}
virtual void undo() override
{
input_->ArrayRemove(index_);
}
private:
NodeInput* input_;
int index_;
};
}
#endif // NODEPARAMVIEWUNDO_H
@@ -70,6 +70,7 @@ void NodeParamViewWidgetBridge::CreateWidgets()
if (input_->IsArray() && element_ == -1) {
NodeParamViewArrayWidget* w = new NodeParamViewArrayWidget(input_);
connect(w, &NodeParamViewArrayWidget::DoubleClicked, this, &NodeParamViewWidgetBridge::ArrayWidgetDoubleClicked);
widgets_.append(w);
} else {
@@ -190,14 +191,14 @@ void NodeParamViewWidgetBridge::CreateWidgets()
void NodeParamViewWidgetBridge::SetInputValue(const QVariant &value, int track)
{
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
SetInputValueInternal(value, track, command);
Core::instance()->undo_stack()->pushIfHasChildren(command);
}
void NodeParamViewWidgetBridge::SetInputValueInternal(const QVariant &value, int track, QUndoCommand *command)
void NodeParamViewWidgetBridge::SetInputValueInternal(const QVariant &value, int track, MultiUndoCommand *command)
{
rational node_time = GetCurrentTimeAsNodeTime();
@@ -205,7 +206,7 @@ void NodeParamViewWidgetBridge::SetInputValueInternal(const QVariant &value, int
NodeKeyframe* existing_key = input_->GetKeyframeAtTimeOnTrack(node_time, track, element_);
if (existing_key) {
new NodeParamSetKeyframeValueCommand(existing_key, value, command);
command->add_child(new NodeParamSetKeyframeValueCommand(existing_key, value));
} else {
// No existing key, create a new one
NodeKeyframe* new_key = new NodeKeyframe(node_time,
@@ -214,10 +215,10 @@ void NodeParamViewWidgetBridge::SetInputValueInternal(const QVariant &value, int
track,
element_);
new NodeParamInsertKeyframeCommand(input_, new_key, command);
command->add_child(new NodeParamInsertKeyframeCommand(input_, new_key));
}
} else {
new NodeParamSetStandardValueCommand(input_, track, element_, value, command);
command->add_child(new NodeParamSetStandardValueCommand(input_, track, element_, value));
}
}
@@ -231,13 +232,11 @@ void NodeParamViewWidgetBridge::ProcessSlider(SliderBase *slider, const QVariant
// While we're dragging, we block the input's normal signalling and create our own
if (!dragger_.IsStarted()) {
dragger_.Start(input_, node_time, slider_track);
dragger_.Start(input_, node_time, slider_track, element_);
}
dragger_.Drag(value);
//input_->parentNode()->InvalidateVisible(input_, input_);
} else if (dragger_.IsStarted()) {
// We were dragging and just stopped
@@ -245,8 +244,10 @@ void NodeParamViewWidgetBridge::ProcessSlider(SliderBase *slider, const QVariant
dragger_.End();
} else {
// No drag was involved, we can just push the value
SetInputValue(value, slider_track);
}
}
@@ -321,7 +322,7 @@ void NodeParamViewWidgetBridge::WidgetCallback()
// Sender is a ColorButton
ManagedColor c = static_cast<ColorButton*>(sender())->GetColor();
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
SetInputValueInternal(c.red(), 0, command);
SetInputValueInternal(c.green(), 1, command);
@@ -394,7 +395,7 @@ void NodeParamViewWidgetBridge::CreateSliders(int count)
void NodeParamViewWidgetBridge::UpdateWidgetValues()
{
if (input_->IsArray()) {
if (input_->IsArray() && element_ == -1) {
return;
}
@@ -428,7 +429,7 @@ void NodeParamViewWidgetBridge::UpdateWidgetValues()
}
case NodeValue::kVec2:
{
QVector2D vec2 = input_->GetValueAtTime(node_time, -1).value<QVector2D>();
QVector2D vec2 = input_->GetValueAtTime(node_time, element_).value<QVector2D>();
QVector2D offset = input_->property("offset").value<QVector2D>();
static_cast<FloatSlider*>(widgets_.at(0))->SetValue(static_cast<double>(vec2.x() + offset.x()));
@@ -510,9 +511,11 @@ rational NodeParamViewWidgetBridge::GetCurrentTimeAsNodeTime() const
return GetAdjustedTime(GetTimeTarget(), input_->parent(), time_, true);
}
void NodeParamViewWidgetBridge::InputValueChanged(const TimeRange &range)
void NodeParamViewWidgetBridge::InputValueChanged(const TimeRange &range, int element)
{
if (!dragger_.IsStarted() && range.in() <= time_ && range.out() >= time_) {
if (element == element_
&& !dragger_.IsStarted()
&& range.in() <= time_ && range.out() >= time_) {
// We'll need to update the widgets because the values have changed on our current time
UpdateWidgetValues();
}
@@ -47,12 +47,15 @@ public:
const QList<QWidget*>& widgets() const;
signals:
void ArrayWidgetDoubleClicked();
private:
void CreateWidgets();
void SetInputValue(const QVariant& value, int track);
void SetInputValueInternal(const QVariant& value, int track, QUndoCommand* command);
void SetInputValueInternal(const QVariant& value, int track, MultiUndoCommand *command);
void ProcessSlider(SliderBase* slider, const QVariant& value);
@@ -77,7 +80,7 @@ private:
private slots:
void WidgetCallback();
void InputValueChanged(const TimeRange& range);
void InputValueChanged(const TimeRange& range, int element);
void PropertyChanged(const QString& key, const QVariant& value);
+9 -9
View File
@@ -118,13 +118,13 @@ void NodeView::DeleteSelected()
return;
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
{
QVector<NodeViewEdge *> selected_edges = scene_.GetSelectedEdges();
foreach (NodeViewEdge* edge, selected_edges) {
new NodeEdgeRemoveCommand(edge->output(), edge->input(), edge->element(), command);
command->add_child(new NodeEdgeRemoveCommand(edge->output(), edge->input(), edge->element()));
}
}
@@ -141,7 +141,7 @@ void NodeView::DeleteSelected()
if (!selected_nodes.isEmpty()) {
foreach (Node* node, selected_nodes) {
new NodeRemoveAndDisconnectCommand(node, command);
command->add_child(new NodeRemoveAndDisconnectCommand(node));
}
}
}
@@ -292,7 +292,7 @@ void NodeView::Paste()
return;
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
QVector<Node*> pasted_nodes = PasteNodesFromClipboard(graph_, command);
@@ -315,7 +315,7 @@ void NodeView::Duplicate()
return;
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
QVector<Node*> duplicated_nodes = Node::CopyDependencyGraph(selected, command);
@@ -536,14 +536,14 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event)
if (drop_edge_) {
// We have everything we need to place the node in between
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
// Remove old edge
new NodeEdgeRemoveCommand(drop_edge_->output(), drop_edge_->input(), drop_edge_->element(), command);
command->add_child(new NodeEdgeRemoveCommand(drop_edge_->output(), drop_edge_->input(), drop_edge_->element()));
// Place new edges
new NodeEdgeAddCommand(drop_edge_->output(), drop_input_, -1, command);
new NodeEdgeAddCommand(dropping_node, drop_edge_->input(), drop_edge_->element(), command);
command->add_child(new NodeEdgeAddCommand(drop_edge_->output(), drop_input_, -1));
command->add_child(new NodeEdgeAddCommand(dropping_node, drop_edge_->input(), drop_edge_->element()));
Core::instance()->undo_stack()->push(command);
}
-1
View File
@@ -24,7 +24,6 @@
#include <QFontMetrics>
#include <QGraphicsRectItem>
#include <QLinearGradient>
#include <QUndoCommand>
#include <QWidget>
#include "node/node.h"
+35 -19
View File
@@ -25,22 +25,41 @@
namespace olive {
NodeEdgeAddCommand::NodeEdgeAddCommand(Node *output, NodeInput *input, int element, QUndoCommand *parent) :
UndoCommand(parent),
NodeEdgeAddCommand::NodeEdgeAddCommand(Node *output, NodeInput *input, int element) :
output_(output),
input_(input),
element_(element)
element_(element),
remove_command_(nullptr)
{
}
void NodeEdgeAddCommand::redo_internal()
NodeEdgeAddCommand::~NodeEdgeAddCommand()
{
delete remove_command_;
}
void NodeEdgeAddCommand::redo()
{
if (input_->IsConnected(element_)) {
if (!remove_command_) {
remove_command_ = new NodeEdgeRemoveCommand(input_->GetConnectedNode(element_),
input_,
element_);
}
remove_command_->redo();
}
Node::ConnectEdge(output_, input_, element_);
}
void NodeEdgeAddCommand::undo_internal()
void NodeEdgeAddCommand::undo()
{
Node::DisconnectEdge(output_, input_, element_);
if (remove_command_) {
remove_command_->undo();
}
}
Project *NodeEdgeAddCommand::GetRelevantProject() const
@@ -48,20 +67,19 @@ Project *NodeEdgeAddCommand::GetRelevantProject() const
return output_->parent()->project();
}
NodeEdgeRemoveCommand::NodeEdgeRemoveCommand(Node *output, NodeInput *input, int element, QUndoCommand *parent) :
UndoCommand(parent),
NodeEdgeRemoveCommand::NodeEdgeRemoveCommand(Node *output, NodeInput *input, int element) :
output_(output),
input_(input),
element_(element)
{
}
void NodeEdgeRemoveCommand::redo_internal()
void NodeEdgeRemoveCommand::redo()
{
Node::DisconnectEdge(output_, input_, element_);
}
void NodeEdgeRemoveCommand::undo_internal()
void NodeEdgeRemoveCommand::undo()
{
Node::ConnectEdge(output_, input_, element_);
}
@@ -71,8 +89,7 @@ Project *NodeEdgeRemoveCommand::GetRelevantProject() const
return output_->parent()->project();
}
NodeAddCommand::NodeAddCommand(NodeGraph *graph, Node *node, QUndoCommand *parent) :
UndoCommand(parent),
NodeAddCommand::NodeAddCommand(NodeGraph *graph, Node *node) :
graph_(graph),
node_(node)
{
@@ -80,12 +97,12 @@ NodeAddCommand::NodeAddCommand(NodeGraph *graph, Node *node, QUndoCommand *paren
node_->setParent(&memory_manager_);
}
void NodeAddCommand::redo_internal()
void NodeAddCommand::redo()
{
node_->setParent(graph_);
}
void NodeAddCommand::undo_internal()
void NodeAddCommand::undo()
{
node_->setParent(&memory_manager_);
}
@@ -95,8 +112,7 @@ Project *NodeAddCommand::GetRelevantProject() const
return graph_->project();
}
NodeCopyInputsCommand::NodeCopyInputsCommand(Node *src, Node *dest, bool include_connections, QUndoCommand *parent) :
QUndoCommand(parent),
NodeCopyInputsCommand::NodeCopyInputsCommand(Node *src, Node *dest, bool include_connections) :
src_(src),
dest_(dest),
include_connections_(include_connections)
@@ -110,21 +126,21 @@ void NodeCopyInputsCommand::redo()
void NodeRemoveAndDisconnectCommand::prep()
{
command_ = new QUndoCommand();
command_ = new MultiUndoCommand();
// If this is a block, remove all links
if (node_->HasLinks()) {
new NodeUnlinkAllCommand(node_, command_);
command_->add_child(new NodeUnlinkAllCommand(node_));
}
// Disconnect everything
foreach (const Node::InputConnection& conn, node_->edges()) {
new NodeEdgeRemoveCommand(node_, conn.input, conn.element, command_);
command_->add_child(new NodeEdgeRemoveCommand(node_, conn.input, conn.element));
}
foreach (NodeInput* input, node_->inputs()) {
for (auto it=input->edges().cbegin(); it!=input->edges().cend(); it++) {
new NodeEdgeRemoveCommand(it->second, input, it->first, command_);
command_->add_child(new NodeEdgeRemoveCommand(it->second, input, it->first));
}
}
}
+45 -53
View File
@@ -21,8 +21,6 @@
#ifndef NODEVIEWUNDO_H
#define NODEVIEWUNDO_H
#include <QUndoCommand>
#include "node/graph.h"
#include "node/node.h"
#include "undo/undocommand.h"
@@ -30,19 +28,18 @@
namespace olive {
/**
* @brief An undoable command for connecting two NodeParams together
* @brief An undoable command for disconnecting two NodeParams
*
* Can be considered a QUndoCommand wrapper for NodeParam::ConnectEdge()/
* Can be considered a UndoCommand wrapper for NodeParam::DisonnectEdge()/
*/
class NodeEdgeAddCommand : public UndoCommand {
class NodeEdgeRemoveCommand : public UndoCommand {
public:
NodeEdgeAddCommand(Node* output, NodeInput* input, int element, QUndoCommand* parent = nullptr);
NodeEdgeRemoveCommand(Node* output, NodeInput* input, int element);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
Node* output_;
@@ -52,36 +49,38 @@ private:
};
/**
* @brief An undoable command for disconnecting two NodeParams
* @brief An undoable command for connecting two NodeParams together
*
* Can be considered a QUndoCommand wrapper for NodeParam::DisonnectEdge()/
* Can be considered a UndoCommand wrapper for NodeParam::ConnectEdge()/
*/
class NodeEdgeRemoveCommand : public UndoCommand {
class NodeEdgeAddCommand : public UndoCommand {
public:
NodeEdgeRemoveCommand(Node* output, NodeInput* input, int element, QUndoCommand* parent = nullptr);
NodeEdgeAddCommand(Node* output, NodeInput* input, int element);
virtual ~NodeEdgeAddCommand() override;
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
Node* output_;
NodeInput* input_;
int element_;
NodeEdgeRemoveCommand* remove_command_;
};
class NodeAddCommand : public UndoCommand {
public:
NodeAddCommand(NodeGraph* graph, Node* node, QUndoCommand* parent = nullptr);
NodeAddCommand(NodeGraph* graph, Node* node);
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
QObject memory_manager_;
@@ -92,8 +91,7 @@ private:
class NodeRemoveAndDisconnectCommand : public UndoCommand {
public:
NodeRemoveAndDisconnectCommand(Node* node, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
NodeRemoveAndDisconnectCommand(Node* node) :
node_(node),
graph_(nullptr),
command_(nullptr),
@@ -115,8 +113,7 @@ public:
}
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
if (!prepped_) {
prep();
@@ -129,7 +126,7 @@ protected:
node_->setParent(&memory_manager_);
}
virtual void undo_internal() override
virtual void undo() override
{
node_->setParent(graph_);
graph_ = nullptr;
@@ -145,7 +142,7 @@ private:
Node* node_;
NodeGraph* graph_;
QUndoCommand* command_;
MultiUndoCommand* command_;
bool prepped_;
@@ -153,8 +150,7 @@ private:
class NodeRemoveWithExclusiveDependenciesAndDisconnect : public UndoCommand {
public:
NodeRemoveWithExclusiveDependenciesAndDisconnect(Node* node, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
NodeRemoveWithExclusiveDependenciesAndDisconnect(Node* node) :
node_(node),
command_(nullptr),
prepped_(false)
@@ -175,8 +171,7 @@ public:
}
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
if (!prepped_) {
prep();
@@ -186,7 +181,7 @@ protected:
command_->redo();
}
virtual void undo_internal() override
virtual void undo() override
{
command_->undo();
}
@@ -194,33 +189,35 @@ protected:
private:
void prep()
{
command_ = new QUndoCommand();
command_ = new MultiUndoCommand();
new NodeRemoveAndDisconnectCommand(node_, command_);
command_->add_child(new NodeRemoveAndDisconnectCommand(node_));
// Remove exclusive dependencies
QVector<Node*> deps = node_->GetExclusiveDependencies();
foreach (Node* d, deps) {
new NodeRemoveAndDisconnectCommand(d, command_);
command_->add_child(new NodeRemoveAndDisconnectCommand(d));
}
}
Node* node_;
QUndoCommand* command_;
MultiUndoCommand* command_;
bool prepped_;
};
class NodeCopyInputsCommand : public QUndoCommand {
class NodeCopyInputsCommand : public UndoCommand {
public:
NodeCopyInputsCommand(Node* src,
Node* dest,
bool include_connections,
QUndoCommand* parent = nullptr);
bool include_connections);
protected:
virtual void redo() override;
virtual void undo() override {}
virtual Project* GetRelevantProject() const override {return nullptr;}
private:
Node* src_;
@@ -232,8 +229,7 @@ private:
class NodeLinkCommand : public UndoCommand {
public:
NodeLinkCommand(Node* a, Node* b, bool link, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
NodeLinkCommand(Node* a, Node* b, bool link) :
a_(a),
b_(b),
link_(link)
@@ -245,8 +241,7 @@ public:
return a_->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
if (link_) {
done_ = Node::Link(a_, b_);
@@ -255,7 +250,7 @@ protected:
}
}
virtual void undo_internal() override
virtual void undo() override
{
if (done_) {
if (link_) {
@@ -276,8 +271,7 @@ private:
class NodeUnlinkAllCommand : public UndoCommand {
public:
NodeUnlinkAllCommand(Node* node, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
NodeUnlinkAllCommand(Node* node) :
node_(node)
{
}
@@ -287,8 +281,7 @@ public:
return node_->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
unlinked_ = node_->links();
@@ -297,7 +290,7 @@ protected:
}
}
virtual void undo_internal() override
virtual void undo() override
{
foreach (Node* link, unlinked_) {
Node::Link(node_, link);
@@ -313,16 +306,15 @@ private:
};
class NodeLinkManyCommand : public UndoCommand {
class NodeLinkManyCommand : public MultiUndoCommand {
public:
NodeLinkManyCommand(const QVector<Node*> nodes, bool link, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
NodeLinkManyCommand(const QVector<Node*> nodes, bool link) :
nodes_(nodes)
{
foreach (Node* a, nodes_) {
foreach (Node* b, nodes_) {
if (a != b) {
new NodeLinkCommand(a, b, link, this);
add_child(new NodeLinkCommand(a, b, link));
}
}
}
@@ -571,7 +571,7 @@ void ProjectExplorer::DeleteSelected()
return;
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
foreach (Item* item, selected) {
// Verify whether this item is in use anywhere
@@ -629,7 +629,7 @@ void ProjectExplorer::DeleteSelected()
if (msgbox.clickedButton() == offline_btn || msgbox.clickedButton() == delete_clip_btn) {
// For safety, even if we're deleting clips, we'll offline the footage nodes too
new OfflineFootageCommand(footage_nodes, command);
command->add_child(new OfflineFootageCommand(footage_nodes));
}
@@ -676,7 +676,7 @@ void ProjectExplorer::DeleteSelected()
break;
}
new ProjectViewModel::RemoveItemCommand(&model_, item, command);
command->add_child(new ProjectViewModel::RemoveItemCommand(&model_, item));
}
Core::instance()->undo_stack()->pushIfHasChildren(command);
@@ -31,8 +31,7 @@ namespace olive {
*/
class OfflineFootageCommand : public UndoCommand {
public:
OfflineFootageCommand(const QVector<MediaInput*>& media, QUndoCommand* parent = nullptr) :
UndoCommand(parent)
OfflineFootageCommand(const QVector<MediaInput*>& media)
{
foreach (MediaInput* i, media) {
stream_data_.insert(i, i->stream());
@@ -46,15 +45,14 @@ public:
return project_;
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
for (auto it=stream_data_.cbegin(); it!=stream_data_.cend(); it++) {
it.key()->SetStream(nullptr);
}
}
virtual void undo_internal() override
virtual void undo() override
{
for (auto it=stream_data_.cbegin(); it!=stream_data_.cend(); it++) {
it.key()->SetStream(it.value());
+5 -6
View File
@@ -21,7 +21,6 @@
#include "timebasedwidget.h"
#include <QInputDialog>
#include <QUndoCommand>
#include "common/autoscroll.h"
#include "common/timecodefunctions.h"
@@ -435,11 +434,11 @@ void TimeBasedWidget::SetPoint(Timeline::MovementMode m, const rational& time)
return;
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
// Enable workarea if it isn't already enabled
if (!points_->workarea()->enabled()) {
new WorkareaSetEnabledCommand(GetTimelinePointsProject(), points_, true, command);
command->add_child(new WorkareaSetEnabledCommand(GetTimelinePointsProject(), points_, true));
}
// Determine our new range
@@ -464,7 +463,7 @@ void TimeBasedWidget::SetPoint(Timeline::MovementMode m, const rational& time)
}
// Set workarea
new WorkareaSetRangeCommand(GetTimelinePointsProject(), points_, TimeRange(in_point, out_point), command);
command->add_child(new WorkareaSetRangeCommand(GetTimelinePointsProject(), points_, TimeRange(in_point, out_point)));
Core::instance()->undo_stack()->push(command);
}
@@ -647,12 +646,12 @@ Project *TimeBasedWidget::MarkerAddCommand::GetRelevantProject() const
return project_;
}
void TimeBasedWidget::MarkerAddCommand::redo_internal()
void TimeBasedWidget::MarkerAddCommand::redo()
{
added_marker_ = marker_list_->AddMarker(range_, name_);
}
void TimeBasedWidget::MarkerAddCommand::undo_internal()
void TimeBasedWidget::MarkerAddCommand::undo()
{
marker_list_->RemoveMarker(added_marker_);
}
+2 -3
View File
@@ -152,9 +152,8 @@ private:
virtual Project* GetRelevantProject() const override;
protected:
virtual void redo_internal() override;
virtual void undo_internal() override;
virtual void redo() override;
virtual void undo() override;
private:
Project* project_;
+91 -143
View File
@@ -21,8 +21,6 @@
#ifndef TIMELINEUNDOABLE_H
#define TIMELINEUNDOABLE_H
#include <QUndoCommand>
#include "config/config.h"
#include "core.h"
#include "node/block/block.h"
@@ -46,22 +44,21 @@ inline bool NodeCanBeRemoved(Node* n)
return n->edges().empty();
}
inline QUndoCommand* CreateRemoveCommand(Node* n)
inline UndoCommand* CreateRemoveCommand(Node* n)
{
return new NodeRemoveWithExclusiveDependenciesAndDisconnect(n);
}
inline QUndoCommand* CreateAndRunRemoveCommand(Node* n)
inline UndoCommand* CreateAndRunRemoveCommand(Node* n)
{
QUndoCommand* command = CreateRemoveCommand(n);
UndoCommand* command = CreateRemoveCommand(n);
command->redo();
return command;
}
class BlockResizeCommand : public UndoCommand {
public:
BlockResizeCommand(Block* block, rational new_length, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
BlockResizeCommand(Block* block, rational new_length) :
block_(block),
new_length_(new_length)
{
@@ -72,14 +69,13 @@ public:
return block_->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
old_length_ = block_->length();
block_->set_length_and_media_out(new_length_);
}
virtual void undo_internal() override
virtual void undo() override
{
block_->set_length_and_media_out(old_length_);
}
@@ -93,8 +89,7 @@ private:
class BlockResizeWithMediaInCommand : public UndoCommand {
public:
BlockResizeWithMediaInCommand(Block* block, rational new_length, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
BlockResizeWithMediaInCommand(Block* block, rational new_length) :
block_(block),
new_length_(new_length)
{
@@ -105,14 +100,13 @@ public:
return block_->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
old_length_ = block_->length();
block_->set_length_and_media_in(new_length_);
}
virtual void undo_internal() override
virtual void undo() override
{
block_->set_length_and_media_in(old_length_);
}
@@ -135,8 +129,7 @@ private:
*/
class BlockTrimCommand : public UndoCommand {
public:
BlockTrimCommand(Track *track, Block* block, rational new_length, Timeline::MovementMode mode, QUndoCommand* command = nullptr) :
UndoCommand(command),
BlockTrimCommand(Track *track, Block* block, rational new_length, Timeline::MovementMode mode) :
prepped_(false),
track_(track),
block_(block),
@@ -177,8 +170,7 @@ public:
remove_block_from_graph_ = e;
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
if (!prepped_) {
prep();
@@ -245,7 +237,7 @@ protected:
track_->InvalidateCache(invalidate_range, track_->block_input());
}
virtual void undo_internal() override
virtual void undo() override
{
if (doing_nothing_) {
return;
@@ -360,7 +352,7 @@ private:
bool needs_adjacent_;
bool we_created_adjacent_;
bool we_removed_adjacent_;
QUndoCommand* deleted_adjacent_command_;
UndoCommand* deleted_adjacent_command_;
bool trim_is_a_roll_edit_;
bool remove_block_from_graph_;
@@ -371,8 +363,7 @@ private:
class BlockSetMediaInCommand : public UndoCommand {
public:
BlockSetMediaInCommand(Block* block, rational new_media_in, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
BlockSetMediaInCommand(Block* block, rational new_media_in) :
block_(block),
new_media_in_(new_media_in)
{
@@ -383,14 +374,13 @@ public:
return block_->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
old_media_in_ = block_->media_in();
block_->set_media_in(new_media_in_);
}
virtual void undo_internal() override
virtual void undo() override
{
block_->set_media_in(old_media_in_);
}
@@ -403,8 +393,7 @@ private:
class TrackRippleRemoveBlockCommand : public UndoCommand {
public:
TrackRippleRemoveBlockCommand(Track* track, Block* block, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
TrackRippleRemoveBlockCommand(Track* track, Block* block) :
track_(track),
block_(block)
{
@@ -415,14 +404,13 @@ public:
return track_->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
before_ = block_->previous();
track_->RippleRemoveBlock(block_);
}
virtual void undo_internal() override
virtual void undo() override
{
track_->InsertBlockAfter(block_, before_);
}
@@ -438,8 +426,7 @@ private:
class TrackPrependBlockCommand : public UndoCommand {
public:
TrackPrependBlockCommand(Track* track, Block* block, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
TrackPrependBlockCommand(Track* track, Block* block) :
track_(track),
block_(block)
{
@@ -450,13 +437,12 @@ public:
return track_->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
track_->PrependBlock(block_);
}
virtual void undo_internal() override
virtual void undo() override
{
track_->RippleRemoveBlock(block_);
}
@@ -468,8 +454,7 @@ private:
class TrackInsertBlockAfterCommand : public UndoCommand {
public:
TrackInsertBlockAfterCommand(Track* track, Block* block, Block* before, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
TrackInsertBlockAfterCommand(Track* track, Block* block, Block* before) :
track_(track),
block_(block),
before_(before)
@@ -481,13 +466,12 @@ public:
return block_->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
track_->InsertBlockAfter(block_, before_);
}
virtual void undo_internal() override
virtual void undo() override
{
track_->RippleRemoveBlock(block_);
}
@@ -502,8 +486,7 @@ private:
class BlockSplitCommand : public UndoCommand {
public:
BlockSplitCommand(Block* block, rational point, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
BlockSplitCommand(Block* block, rational point) :
block_(block),
point_(point),
reconnect_tree_command_(nullptr)
@@ -528,8 +511,7 @@ public:
return static_cast<Block*>(added_nodes_.first());
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
old_length_ = block_->length();
@@ -571,8 +553,8 @@ protected:
if (!reconnect_tree_command_) {
if (copy_dependencies_too) {
// Create equivalent connections among our copied dependency tree
reconnect_tree_command_ = new QUndoCommand();
Node::CopyDependencyGraph(src_nodes_, added_nodes_, reconnect_tree_command_);
reconnect_tree_command_ = new MultiUndoCommand();
Node::CopyDependencyGraph(src_nodes_, added_nodes_, static_cast<MultiUndoCommand*>(reconnect_tree_command_));
} else {
reconnect_tree_command_ = new NodeCopyInputsCommand(block_, new_block(), true);
}
@@ -613,7 +595,7 @@ protected:
track->EndOperation();
}
virtual void undo_internal() override
virtual void undo() override
{
Track* track = block_->track();
@@ -646,7 +628,7 @@ private:
QObject memory_manager_;
QUndoCommand* reconnect_tree_command_;
UndoCommand* reconnect_tree_command_;
NodeInput* moved_transition_;
@@ -657,8 +639,7 @@ private:
class BlockSplitPreservingLinksCommand : public UndoCommand {
public:
BlockSplitPreservingLinksCommand(const QVector<Block *> &blocks, const QList<rational>& times, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
BlockSplitPreservingLinksCommand(const QVector<Block *> &blocks, const QList<rational>& times) :
blocks_(blocks),
times_(times)
{
@@ -674,8 +655,7 @@ public:
return blocks_.first()->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
if (commands_.isEmpty()) {
QVector< QVector<Block*> > split_blocks(times_.size());
@@ -736,7 +716,7 @@ protected:
}
}
virtual void undo_internal() override
virtual void undo() override
{
for (int i=commands_.size()-1; i>=0; i--) {
commands_.at(i)->undo();
@@ -748,14 +728,13 @@ private:
QList<rational> times_;
QVector<QUndoCommand*> commands_;
QVector<UndoCommand*> commands_;
};
class TrackSplitAtTimeCommand : public UndoCommand {
public:
TrackSplitAtTimeCommand(Track* track, rational point, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
TrackSplitAtTimeCommand(Track* track, rational point) :
prepped_(false),
track_(track),
point_(point),
@@ -773,8 +752,7 @@ public:
return track_->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
if (!prepped_) {
// Find Block that contains this time
@@ -792,7 +770,7 @@ protected:
}
}
virtual void undo_internal() override
virtual void undo() override
{
if (command_) {
command_->undo();
@@ -806,7 +784,7 @@ private:
rational point_;
QUndoCommand* command_;
UndoCommand* command_;
};
@@ -819,8 +797,7 @@ private:
*/
class TrackRippleRemoveAreaCommand : public UndoCommand {
public:
TrackRippleRemoveAreaCommand(Track* track, const TimeRange& range, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
TrackRippleRemoveAreaCommand(Track* track, const TimeRange& range) :
prepped_(false),
track_(track),
range_(range),
@@ -858,8 +835,7 @@ public:
return nullptr;
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
if (!prepped_) {
prep();
@@ -900,7 +876,7 @@ protected:
}
}
foreach (QUndoCommand* c, remove_block_commands_) {
foreach (UndoCommand* c, remove_block_commands_) {
c->redo();
}
}
@@ -911,7 +887,7 @@ protected:
track_->InvalidateCache(TimeRange(range_.in(), RATIONAL_MAX));
}
virtual void undo_internal() override
virtual void undo() override
{
// Begin operations
track_->BeginOperation();
@@ -1028,14 +1004,13 @@ private:
Block* insert_previous_;
BlockSplitCommand* splice_split_command_;
QVector<QUndoCommand*> remove_block_commands_;
QVector<UndoCommand*> remove_block_commands_;
};
class TrackListRippleRemoveAreaCommand : public UndoCommand {
public:
TrackListRippleRemoveAreaCommand(TrackList* list, rational in, rational out, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
TrackListRippleRemoveAreaCommand(TrackList* list, rational in, rational out) :
list_(list),
in_(in),
out_(out)
@@ -1052,8 +1027,7 @@ public:
return static_cast<ViewerOutput*>(list_->parent())->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
// Code that's only run on the first redo
if (commands_.isEmpty()) {
@@ -1096,7 +1070,7 @@ protected:
}
}
virtual void undo_internal() override
virtual void undo() override
{
if (all_tracks_unlocked_) {
// We can optimize here by simply shifting the whole cache forward instead of re-caching
@@ -1138,17 +1112,15 @@ private:
};
class TimelineRippleRemoveAreaCommand : public UndoCommand {
class TimelineRippleRemoveAreaCommand : public MultiUndoCommand {
public:
TimelineRippleRemoveAreaCommand(ViewerOutput* timeline, rational in, rational out, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
TimelineRippleRemoveAreaCommand(ViewerOutput* timeline, rational in, rational out) :
timeline_(timeline)
{
for (int i=0; i<Track::kCount; i++) {
new TrackListRippleRemoveAreaCommand(timeline->track_list(static_cast<Track::Type>(i)),
add_child(new TrackListRippleRemoveAreaCommand(timeline->track_list(static_cast<Track::Type>(i)),
in,
out,
this);
out));
}
}
@@ -1173,8 +1145,7 @@ public:
const QHash<Track*, RippleInfo>& info,
const rational& ripple_movement,
const Timeline::MovementMode& movement_mode,
QUndoCommand* parent = nullptr) :
UndoCommand(parent),
UndoCommand* parent = nullptr) :
track_list_(track_list),
info_(info),
ripple_movement_(ripple_movement),
@@ -1188,13 +1159,12 @@ public:
return static_cast<ViewerOutput*>(track_list_->parent())->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
ripple(true);
}
virtual void undo_internal() override
virtual void undo() override
{
ripple(false);
}
@@ -1385,8 +1355,7 @@ private:
class TimelineAddTrackCommand : public UndoCommand {
public:
TimelineAddTrackCommand(TrackList *timeline, QUndoCommand* command = nullptr) :
UndoCommand(command),
TimelineAddTrackCommand(TrackList *timeline) :
timeline_(timeline)
{
track_ = new Track();
@@ -1415,8 +1384,7 @@ public:
return timeline_->GetParentGraph()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
// Add track
track_->setParent(timeline_->GetParentGraph());
@@ -1444,7 +1412,7 @@ protected:
}
}
virtual void undo_internal() override
virtual void undo() override
{
// Remove merge if applicable
if (merge_) {
@@ -1490,8 +1458,7 @@ private:
*/
class TrackPlaceBlockCommand : public UndoCommand {
public:
TrackPlaceBlockCommand(TrackList *timeline, int track, Block* block, rational in, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
TrackPlaceBlockCommand(TrackList *timeline, int track, Block* block, rational in) :
timeline_(timeline),
track_index_(track),
in_(in),
@@ -1512,8 +1479,7 @@ public:
return timeline_->GetParentGraph()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
// Determine if we need to add tracks
if (track_index_ >= timeline_->GetTracks().size()) {
@@ -1560,7 +1526,7 @@ protected:
}
}
virtual void undo_internal() override
virtual void undo() override
{
Track* t = timeline_->GetTrackAt(track_index_);
@@ -1600,8 +1566,7 @@ private:
*/
class TrackReplaceBlockCommand : public UndoCommand {
public:
TrackReplaceBlockCommand(Track* track, Block* old, Block* replace, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
TrackReplaceBlockCommand(Track* track, Block* old, Block* replace) :
track_(track),
old_(old),
replace_(replace)
@@ -1613,13 +1578,12 @@ public:
return track_->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
track_->ReplaceBlock(old_, replace_);
}
virtual void undo_internal() override
virtual void undo() override
{
track_->ReplaceBlock(replace_, old_);
}
@@ -1633,8 +1597,7 @@ private:
class TrackReplaceBlockWithGapCommand : public UndoCommand {
public:
TrackReplaceBlockWithGapCommand(Track* track, Block* block, QUndoCommand* command = nullptr) :
UndoCommand(command),
TrackReplaceBlockWithGapCommand(Track* track, Block* block) :
track_(track),
block_(block),
existing_gap_(nullptr),
@@ -1648,8 +1611,7 @@ public:
return block_->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
track_->BeginOperation();
@@ -1721,7 +1683,7 @@ protected:
track_->InvalidateCache(invalidate_range, track_->block_input());
}
virtual void undo_internal() override
virtual void undo() override
{
track_->BeginOperation();
@@ -1793,8 +1755,7 @@ private:
class TimelineRippleDeleteGapsAtRegionsCommand : public UndoCommand {
public:
TimelineRippleDeleteGapsAtRegionsCommand(ViewerOutput* vo, const TimeRangeList& regions, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
TimelineRippleDeleteGapsAtRegionsCommand(ViewerOutput* vo, const TimeRangeList& regions) :
timeline_(vo),
regions_(regions)
{
@@ -1810,8 +1771,7 @@ public:
return timeline_->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
if (commands_.isEmpty()) {
foreach (const TimeRange& range, regions_) {
@@ -1849,12 +1809,12 @@ protected:
}
}
foreach (QUndoCommand* c, commands_) {
foreach (UndoCommand* c, commands_) {
c->redo();
}
}
virtual void undo_internal() override
virtual void undo() override
{
for (int i=commands_.size()-1;i>=0;i--) {
commands_.at(i)->undo();
@@ -1865,14 +1825,13 @@ private:
ViewerOutput* timeline_;
TimeRangeList regions_;
QVector<QUndoCommand*> commands_;
QVector<UndoCommand*> commands_;
};
class WorkareaSetEnabledCommand : public UndoCommand {
public:
WorkareaSetEnabledCommand(Project *project, TimelinePoints* points, bool enabled, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
WorkareaSetEnabledCommand(Project *project, TimelinePoints* points, bool enabled) :
project_(project),
points_(points),
old_enabled_(points_->workarea()->enabled()),
@@ -1885,13 +1844,12 @@ public:
return project_;
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
points_->workarea()->set_enabled(new_enabled_);
}
virtual void undo_internal() override
virtual void undo() override
{
points_->workarea()->set_enabled(old_enabled_);
}
@@ -1909,8 +1867,7 @@ private:
class WorkareaSetRangeCommand : public UndoCommand {
public:
WorkareaSetRangeCommand(Project *project, TimelinePoints* points, const TimeRange& range, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
WorkareaSetRangeCommand(Project *project, TimelinePoints* points, const TimeRange& range) :
project_(project),
points_(points),
old_range_(points_->workarea()->range()),
@@ -1923,13 +1880,12 @@ public:
return project_;
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
points_->workarea()->set_range(new_range_);
}
virtual void undo_internal() override
virtual void undo() override
{
points_->workarea()->set_range(old_range_);
}
@@ -1947,8 +1903,7 @@ private:
class BlockEnableDisableCommand : public UndoCommand {
public:
BlockEnableDisableCommand(Block* block, bool enabled, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
BlockEnableDisableCommand(Block* block, bool enabled) :
block_(block),
old_enabled_(block_->is_enabled()),
new_enabled_(enabled)
@@ -1960,13 +1915,12 @@ public:
return block_->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
block_->set_enabled(new_enabled_);
}
virtual void undo_internal() override
virtual void undo() override
{
block_->set_enabled(old_enabled_);
}
@@ -1982,8 +1936,7 @@ private:
class TrackSlideCommand : public UndoCommand {
public:
TrackSlideCommand(Track* track, const QList<Block*>& moving_blocks, Block* in_adjacent, Block* out_adjacent, const rational& movement, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
TrackSlideCommand(Track* track, const QList<Block*>& moving_blocks, Block* in_adjacent, Block* out_adjacent, const rational& movement) :
prepped_(false),
track_(track),
blocks_(moving_blocks),
@@ -2007,8 +1960,7 @@ public:
return track_->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
if (!prepped_) {
prep();
@@ -2073,7 +2025,7 @@ protected:
track_->InvalidateCache(invalidate_range, track_->block_input());
}
virtual void undo_internal() override
virtual void undo() override
{
// Make sure all movement blocks' old positions are invalidated
TimeRange invalidate_range(blocks_.first()->in(), blocks_.last()->out());
@@ -2145,10 +2097,10 @@ private:
bool we_created_in_adjacent_;
Block* in_adjacent_;
QUndoCommand* in_adjacent_remove_command_;
UndoCommand* in_adjacent_remove_command_;
bool we_created_out_adjacent_;
Block* out_adjacent_;
QUndoCommand* out_adjacent_remove_command_;
UndoCommand* out_adjacent_remove_command_;
QObject memory_manager_;
@@ -2156,8 +2108,7 @@ private:
class TrackListInsertGaps : public UndoCommand {
public:
TrackListInsertGaps(TrackList* track_list, const rational& point, const rational& length, QUndoCommand* parent = nullptr) :
UndoCommand(parent),
TrackListInsertGaps(TrackList* track_list, const rational& point, const rational& length) :
prepped_(false),
track_list_(track_list),
point_(point),
@@ -2176,8 +2127,7 @@ public:
return static_cast<ViewerOutput*>(track_list_->parent())->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
if (!prepped_) {
prep();
@@ -2221,7 +2171,7 @@ protected:
}
}
virtual void undo_internal() override
virtual void undo() override
{
if (all_tracks_unlocked_) {
// Optimize by shifting over since we have a constant amount of time being inserted
@@ -2340,8 +2290,7 @@ private:
class TransitionRemoveCommand : public UndoCommand {
public:
TransitionRemoveCommand(TransitionBlock* block, QUndoCommand *parent = nullptr) :
UndoCommand(parent),
TransitionRemoveCommand(TransitionBlock* block, UndoCommand *parent = nullptr) :
block_(block)
{
}
@@ -2351,8 +2300,7 @@ public:
return track_->parent()->project();
}
protected:
virtual void redo_internal() override
virtual void redo() override
{
track_ = block_->track();
out_block_ = block_->connected_out_block();
@@ -2387,7 +2335,7 @@ protected:
track_->InvalidateCache(invalidate_range, track_->block_input());
}
virtual void undo_internal() override
virtual void undo() override
{
track_->BeginOperation();
+29 -37
View File
@@ -421,7 +421,7 @@ void TimelineWidget::SplitAtPlayhead()
void TimelineWidget::ReplaceBlocksWithGaps(const QVector<Block *> &blocks,
bool remove_from_graph,
QUndoCommand *command)
MultiUndoCommand *command)
{
foreach (Block* b, blocks) {
if (b->type() == Block::kGap) {
@@ -432,10 +432,10 @@ void TimelineWidget::ReplaceBlocksWithGaps(const QVector<Block *> &blocks,
Track* original_track = b->track();
new TrackReplaceBlockWithGapCommand(original_track, b, command);
command->add_child(new TrackReplaceBlockWithGapCommand(original_track, b));
if (remove_from_graph) {
new NodeRemoveWithExclusiveDependenciesAndDisconnect(b, command);
command->add_child(new NodeRemoveWithExclusiveDependenciesAndDisconnect(b));
}
}
}
@@ -454,7 +454,7 @@ void TimelineWidget::DeleteSelected(bool ripple)
return;
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
QVector<Block*> clips_to_delete;
QVector<TransitionBlock*> transitions_to_delete;
@@ -469,16 +469,16 @@ void TimelineWidget::DeleteSelected(bool ripple)
// For transitions, remove them but extend their attached blocks to fill their place
foreach (TransitionBlock* transition, transitions_to_delete) {
new TransitionRemoveCommand(transition, command);
command->add_child(new TransitionRemoveCommand(transition));
new NodeRemoveWithExclusiveDependenciesAndDisconnect(transition, command);
command->add_child(new NodeRemoveWithExclusiveDependenciesAndDisconnect(transition));
}
// Replace clips with gaps (effectively deleting them)
ReplaceBlocksWithGaps(clips_to_delete, true, command);
// Remove all selections
new SetSelectionsCommand(this, TimelineWidgetSelections(), GetSelections(), command);
command->add_child(new SetSelectionsCommand(this, TimelineWidgetSelections(), GetSelections()));
// Insert ripple command now that it's all cleaned up gaps
if (ripple) {
@@ -488,7 +488,7 @@ void TimelineWidget::DeleteSelected(bool ripple)
range_list.insert(TimeRange(b->in(), b->out()));
}
new TimelineRippleDeleteGapsAtRegionsCommand(GetConnectedNode(), range_list, command);
command->add_child(new TimelineRippleDeleteGapsAtRegionsCommand(GetConnectedNode(), range_list));
}
Core::instance()->undo_stack()->pushIfHasChildren(command);
@@ -593,7 +593,7 @@ void TimelineWidget::Paste(bool insert)
return;
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
QVector<BlockPasteData> paste_data;
QVector<Node*> pasted = PasteNodesFromClipboard(GetConnectedNode()->parent(), command, &paste_data);
@@ -614,11 +614,10 @@ void TimelineWidget::Paste(bool insert)
foreach (const BlockPasteData& bpd, paste_data) {
qDebug() << "Placing" << bpd.block;
new TrackPlaceBlockCommand(GetConnectedNode()->track_list(bpd.track_type),
command->add_child(new TrackPlaceBlockCommand(GetConnectedNode()->track_list(bpd.track_type),
bpd.track_index,
bpd.block,
paste_start + bpd.in,
command);
paste_start + bpd.in));
}
Core::instance()->undo_stack()->pushIfHasChildren(command);
@@ -632,14 +631,13 @@ void TimelineWidget::DeleteInToOut(bool ripple)
return;
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
if (ripple) {
new TimelineRippleRemoveAreaCommand(GetConnectedNode(),
command->add_child(new TimelineRippleRemoveAreaCommand(GetConnectedNode(),
GetConnectedTimelinePoints()->workarea()->in(),
GetConnectedTimelinePoints()->workarea()->out(),
command);
GetConnectedTimelinePoints()->workarea()->out()));
} else {
QVector<Track*> unlocked_tracks = GetConnectedNode()->GetUnlockedTracks();
@@ -649,23 +647,20 @@ void TimelineWidget::DeleteInToOut(bool ripple)
gap->set_length_and_media_out(GetConnectedTimelinePoints()->workarea()->length());
new NodeAddCommand(static_cast<NodeGraph*>(track->parent()),
gap,
command);
command->add_child(new NodeAddCommand(static_cast<NodeGraph*>(track->parent()),
gap));
new TrackPlaceBlockCommand(GetConnectedNode()->track_list(track->type()),
command->add_child(new TrackPlaceBlockCommand(GetConnectedNode()->track_list(track->type()),
track->Index(),
gap,
GetConnectedTimelinePoints()->workarea()->in(),
command);
GetConnectedTimelinePoints()->workarea()->in()));
}
}
// Clear workarea after this
new WorkareaSetEnabledCommand(GetTimelinePointsProject(),
command->add_child(new WorkareaSetEnabledCommand(GetTimelinePointsProject(),
GetConnectedTimelinePoints(),
false,
command);
false));
if (ripple) {
SetTimeAndSignal(Timecode::time_to_timestamp(GetConnectedTimelinePoints()->workarea()->in(),
@@ -683,12 +678,11 @@ void TimelineWidget::ToggleSelectedEnabled()
return;
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
foreach (Block* i, items) {
new BlockEnableDisableCommand(i,
!i->is_enabled(),
command);
command->add_child(new BlockEnableDisableCommand(i,
!i->is_enabled()));
}
Core::instance()->undo_stack()->pushIfHasChildren(command);
@@ -701,13 +695,12 @@ void TimelineWidget::SetColorLabel(int index)
}
}
void TimelineWidget::InsertGapsAt(const rational &earliest_point, const rational &insert_length, QUndoCommand *command)
void TimelineWidget::InsertGapsAt(const rational &earliest_point, const rational &insert_length, MultiUndoCommand *command)
{
for (int i=0;i<Track::kCount;i++) {
new TrackListInsertGaps(GetConnectedNode()->track_list(static_cast<Track::Type>(i)),
command->add_child(new TrackListInsertGaps(GetConnectedNode()->track_list(static_cast<Track::Type>(i)),
earliest_point,
insert_length,
command);
insert_length));
}
}
@@ -1238,7 +1231,7 @@ void TimelineWidget::EditTo(Timeline::MovementMode mode)
return;
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
foreach (const Timeline::EditToInfo& info, tracks) {
if (info.nearest_block
@@ -1253,11 +1246,10 @@ void TimelineWidget::EditTo(Timeline::MovementMode mode)
}
new_len = info.nearest_block->length() - new_len;
new BlockTrimCommand(info.track,
command->add_child(new BlockTrimCommand(info.track,
info.nearest_block,
new_len,
mode,
command);
mode));
}
}
+6 -6
View File
@@ -104,7 +104,7 @@ public:
void RestoreSplitterState(const QByteArray& state);
static void ReplaceBlocksWithGaps(const QVector<Block *> &blocks, bool remove_from_graph, QUndoCommand* command);
static void ReplaceBlocksWithGaps(const QVector<Block *> &blocks, bool remove_from_graph, MultiUndoCommand *command);
/**
* @brief Retrieve the QGraphicsItem at a particular scene position
@@ -136,7 +136,7 @@ public:
return ghost_items_;
}
void InsertGapsAt(const rational& time, const rational& length, QUndoCommand* command);
void InsertGapsAt(const rational& time, const rational& length, MultiUndoCommand *command);
void StartRubberBandSelect(const QPoint& global_cursor_start);
void MoveRubberBandSelect(bool enable_selecting, bool select_links);
@@ -197,17 +197,15 @@ public:
*/
void SignalDeselectedAllBlocks();
class SetSelectionsCommand : public QUndoCommand {
class SetSelectionsCommand : public UndoCommand {
public:
SetSelectionsCommand(TimelineWidget* timeline, const TimelineWidgetSelections& now, const TimelineWidgetSelections& old, QUndoCommand* parent = nullptr) :
QUndoCommand(parent),
SetSelectionsCommand(TimelineWidget* timeline, const TimelineWidgetSelections& now, const TimelineWidgetSelections& old) :
timeline_(timeline),
old_(old),
now_(now)
{
}
protected:
virtual void redo() override
{
timeline_->SetSelections(now_);
@@ -218,6 +216,8 @@ public:
timeline_->SetSelections(old_);
}
virtual Project* GetRelevantProject() const override {return nullptr;}
private:
TimelineWidget* timeline_;
TimelineWidgetSelections old_;
+11 -15
View File
@@ -91,7 +91,7 @@ void AddTool::MouseRelease(TimelineViewMouseEvent *event)
if (ghost_) {
if (!ghost_->GetAdjustedLength().isNull()) {
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
ClipBlock* clip = new ClipBlock();
clip->set_length_and_media_out(ghost_->GetAdjustedLength());
@@ -99,15 +99,13 @@ void AddTool::MouseRelease(TimelineViewMouseEvent *event)
NodeGraph* graph = static_cast<NodeGraph*>(parent()->GetConnectedNode()->parent());
new NodeAddCommand(graph,
clip,
command);
command->add_child(new NodeAddCommand(graph,
clip));
new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track.type()),
command->add_child(new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track.type()),
track.index(),
clip,
ghost_->GetAdjustedIn(),
command);
ghost_->GetAdjustedIn()));
switch (Core::instance()->GetSelectedAddableObject()) {
case olive::Tool::kAddableEmpty:
@@ -117,22 +115,20 @@ void AddTool::MouseRelease(TimelineViewMouseEvent *event)
{
Node* solid = new SolidGenerator();
new NodeAddCommand(graph,
solid,
command);
command->add_child(new NodeAddCommand(graph,
solid));
new NodeEdgeAddCommand(solid, clip->texture_input(), -1, command);
command->add_child(new NodeEdgeAddCommand(solid, clip->texture_input(), -1));
break;
}
case olive::Tool::kAddableTitle:
{
Node* text = new TextGenerator();
new NodeAddCommand(graph,
text,
command);
command->add_child(new NodeAddCommand(graph,
text));
new NodeEdgeAddCommand(text, clip->texture_input(), -1, command);
command->add_child(new NodeEdgeAddCommand(text, clip->texture_input(), -1));
break;
}
case olive::Tool::kAddableBars:
+14 -16
View File
@@ -306,7 +306,7 @@ void ImportTool::PrepGhosts(const rational& frame, const int& track_index)
void ImportTool::DropGhosts(bool insert)
{
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
NodeGraph* dst_graph = nullptr;
ViewerOutput* viewer_node = nullptr;
@@ -383,10 +383,9 @@ void ImportTool::DropGhosts(bool insert)
if (sequence_is_valid) {
new_sequence->add_default_nodes();
new ProjectViewModel::AddItemCommand(Core::instance()->GetActiveProjectModel(),
command->add_child(new ProjectViewModel::AddItemCommand(Core::instance()->GetActiveProjectModel(),
Core::instance()->GetSelectedFolderInActiveProject(),
new_sequence,
command);
new_sequence));
FootageToGhosts(0, dragged_footage_, new_sequence->video_params().time_base(), 0);
@@ -422,44 +421,43 @@ void ImportTool::DropGhosts(bool insert)
clip->set_media_in(ghost->GetMediaIn());
clip->set_length_and_media_out(ghost->GetLength());
clip->SetLabel(footage_stream->footage()->name());
new NodeAddCommand(dst_graph, clip, command);
command->add_child(new NodeAddCommand(dst_graph, clip));
switch (footage_stream->type()) {
case Stream::kVideo:
{
MediaInput* video_input = new MediaInput();
video_input->SetStream(footage_stream);
new NodeAddCommand(dst_graph, video_input, command);
command->add_child(new NodeAddCommand(dst_graph, video_input));
TransformDistortNode* transform = new TransformDistortNode();
new NodeAddCommand(dst_graph, transform, command);
command->add_child(new NodeAddCommand(dst_graph, transform));
new NodeEdgeAddCommand(video_input, transform->texture_input(), -1, command);
new NodeEdgeAddCommand(transform, clip->texture_input(), -1, command);
command->add_child(new NodeEdgeAddCommand(video_input, transform->texture_input(), -1));
command->add_child(new NodeEdgeAddCommand(transform, clip->texture_input(), -1));
break;
}
case Stream::kAudio:
{
MediaInput* audio_input = new MediaInput();
audio_input->SetStream(footage_stream);
new NodeAddCommand(dst_graph, audio_input, command);
command->add_child(new NodeAddCommand(dst_graph, audio_input));
VolumeNode* volume_node = new VolumeNode();
new NodeAddCommand(dst_graph, volume_node, command);
command->add_child(new NodeAddCommand(dst_graph, volume_node));
new NodeEdgeAddCommand(audio_input, volume_node->samples_input(), -1, command);
new NodeEdgeAddCommand(volume_node, clip->texture_input(), -1, command);
command->add_child(new NodeEdgeAddCommand(audio_input, volume_node->samples_input(), -1));
command->add_child(new NodeEdgeAddCommand(volume_node, clip->texture_input(), -1));
break;
}
default:
break;
}
new TrackPlaceBlockCommand(viewer_node->track_list(ghost->GetAdjustedTrack().type()),
command->add_child(new TrackPlaceBlockCommand(viewer_node->track_list(ghost->GetAdjustedTrack().type()),
ghost->GetAdjustedTrack().index(),
clip,
ghost->GetAdjustedIn(),
command);
ghost->GetAdjustedIn()));
block_items.replace(i, clip);
+14 -16
View File
@@ -563,7 +563,7 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
return;
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
if (!blocks_trimming.isEmpty()) {
foreach (const GhostBlockPair& p, blocks_trimming) {
@@ -574,10 +574,11 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
BlockTrimCommand* c = new BlockTrimCommand(parent()->GetTrackFromReference(ghost->GetAdjustedTrack()),
p.block,
ghost->GetAdjustedLength(),
ghost->GetMode(),
command);
ghost->GetMode());
c->SetTrimIsARollEdit(ghost->GetData(TimelineViewGhostItem::kTrimIsARollEdit).toBool());
command->add_child(c);
}
}
@@ -590,7 +591,7 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
} else {
new_sel.TrimOut(reference_ghost->GetOutAdjustment());
}
new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
command->add_child(new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections()));
}
}
@@ -632,11 +633,10 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
} else {
copy = block->copy();
new NodeAddCommand(static_cast<NodeGraph*>(block->parent()),
copy,
command);
command->add_child(new NodeAddCommand(static_cast<NodeGraph*>(block->parent()),
copy));
new NodeCopyInputsCommand(block, copy, true, command);
command->add_child(new NodeCopyInputsCommand(block, copy, true));
}
// Place the copy instead of the original block
@@ -644,18 +644,17 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
}
const Track::Reference& track_ref = p.ghost->GetAdjustedTrack();
new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track_ref.type()),
command->add_child(new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track_ref.type()),
track_ref.index(),
block,
p.ghost->GetAdjustedIn(),
command);
p.ghost->GetAdjustedIn()));
}
// Adjust selections
TimelineWidgetSelections new_sel = parent()->GetSelections();
new_sel.ShiftTime(blocks_moving.first().ghost->GetInAdjustment());
new_sel.ShiftTracks(drag_track_type_, blocks_moving.first().ghost->GetTrackAdjustment());
new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
command->add_child(new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections()));
}
if (!blocks_sliding.isEmpty()) {
@@ -706,18 +705,17 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
if (!movement.isNull()) {
QHash<Track::Reference, QList<Block*> >::const_iterator i;
for (i=slide_info.constBegin(); i!=slide_info.constEnd(); i++) {
new TrackSlideCommand(parent()->GetTrackFromReference(i.key()),
command->add_child(new TrackSlideCommand(parent()->GetTrackFromReference(i.key()),
i.value(),
in_adjacents.value(i.key()),
out_adjacents.value(i.key()),
movement,
command);
movement));
}
// Adjust selections
TimelineWidgetSelections new_sel = parent()->GetSelections();
new_sel.ShiftTime(movement);
new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
command->add_child(new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections()));
}
}
+5 -6
View File
@@ -132,7 +132,7 @@ void RippleTool::FinishDrag(TimelineViewMouseEvent *event)
info_list[track->type()].insert(track, info);
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
rational movement;
@@ -144,15 +144,14 @@ void RippleTool::FinishDrag(TimelineViewMouseEvent *event)
for (int i=0;i<info_list.size();i++) {
if (!info_list.at(i).isEmpty()) {
new TrackListRippleToolCommand(parent()->GetConnectedNode()->track_list(static_cast<Track::Type>(i)),
command->add_child(new TrackListRippleToolCommand(parent()->GetConnectedNode()->track_list(static_cast<Track::Type>(i)),
info_list.at(i),
movement,
drag_movement_mode(),
command);
drag_movement_mode()));
}
}
if (command->childCount() > 0) {
if (command->child_count() > 0) {
TimelineWidgetSelections new_sel = parent()->GetSelections();
TimelineViewGhostItem* reference_ghost = parent()->GetGhostItems().first();
if (drag_movement_mode() == Timeline::kTrimIn) {
@@ -160,7 +159,7 @@ void RippleTool::FinishDrag(TimelineViewMouseEvent *event)
} else {
new_sel.TrimOut(reference_ghost->GetOutAdjustment());
}
new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
command->add_child(new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections()));
Core::instance()->undo_stack()->push(command);
} else {
+2 -2
View File
@@ -68,13 +68,13 @@ void SlipTool::FinishDrag(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
// Find earliest point to ripple around
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
Block* b = Node::ValueToPtr<Block>(ghost->GetData(TimelineViewGhostItem::kAttachedBlock));
new BlockSetMediaInCommand(b, ghost->GetAdjustedMediaIn(), command);
command->add_child(new BlockSetMediaInCommand(b, ghost->GetAdjustedMediaIn()));
}
Core::instance()->undo_stack()->pushIfHasChildren(command);
+1 -1
View File
@@ -128,7 +128,7 @@ void TimelineTool::GetGhostData(rational *earliest_point, rational *latest_point
}
}
void TimelineTool::InsertGapsAtGhostDestination(QUndoCommand *command)
void TimelineTool::InsertGapsAtGhostDestination(olive::MultiUndoCommand *command)
{
rational earliest_point, latest_point;
+1 -1
View File
@@ -75,7 +75,7 @@ protected:
void GetGhostData(rational *earliest_point, rational *latest_point);
void InsertGapsAtGhostDestination(QUndoCommand* command);
void InsertGapsAtGhostDestination(MultiUndoCommand* command);
QVector<rational> snap_points_;
+11 -16
View File
@@ -120,18 +120,16 @@ void TransitionTool::MouseRelease(TimelineViewMouseEvent *event)
transition = static_cast<TransitionBlock*>(NodeFactory::CreateFromID(Core::instance()->GetSelectedTransition()));
}
QUndoCommand* command = new QUndoCommand();
MultiUndoCommand* command = new MultiUndoCommand();
// Place transition in place
new NodeAddCommand(static_cast<NodeGraph*>(parent()->GetConnectedNode()->parent()),
transition,
command);
command->add_child(new NodeAddCommand(static_cast<NodeGraph*>(parent()->GetConnectedNode()->parent()),
transition));
new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track.type()),
command->add_child(new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track.type()),
track.index(),
transition,
ghost_->GetAdjustedIn(),
command);
ghost_->GetAdjustedIn()));
if (dual_transition_) {
transition->set_length_and_media_out(ghost_->GetAdjustedLength());
@@ -148,15 +146,13 @@ void TransitionTool::MouseRelease(TimelineViewMouseEvent *event)
Block* in_block = (ghost_->GetMode() == Timeline::kTrimIn) ? active_block : friend_block;
// Connect block to transition
new NodeEdgeAddCommand(out_block,
command->add_child(new NodeEdgeAddCommand(out_block,
transition->out_block_input(),
-1,
command);
-1));
new NodeEdgeAddCommand(in_block,
command->add_child(new NodeEdgeAddCommand(in_block,
transition->in_block_input(),
-1,
command);
-1));
} else {
Block* block_to_transition = Node::ValueToPtr<Block>(ghost_->GetData(TimelineViewGhostItem::kAttachedBlock));
NodeInput* transition_input_to_connect;
@@ -170,10 +166,9 @@ void TransitionTool::MouseRelease(TimelineViewMouseEvent *event)
}
// Connect block to transition
new NodeEdgeAddCommand(block_to_transition,
command->add_child(new NodeEdgeAddCommand(block_to_transition,
transition_input_to_connect,
-1,
command);
-1));
}
Core::instance()->undo_stack()->push(command);
+2 -2
View File
@@ -75,10 +75,10 @@ MainMenu::MainMenu(MainWindow *parent) :
//
edit_menu_ = new Menu(this);
edit_undo_item_ = Core::instance()->undo_stack()->createUndoAction(this);
edit_undo_item_ = Core::instance()->undo_stack()->GetUndoAction();
Menu::ConformItem(edit_undo_item_, "undo", "Ctrl+Z");
edit_menu_->addAction(edit_undo_item_);
edit_redo_item_ = Core::instance()->undo_stack()->createRedoAction(this);
edit_redo_item_ = Core::instance()->undo_stack()->GetRedoAction();
Menu::ConformItem(edit_redo_item_, "redo", "Ctrl+Shift+Z");
edit_menu_->addAction(edit_redo_item_);