engine: internals supporting the facade migration

UndoStack push_pre_executed, FolderAddChild-based true folder moves,
NodeViewDeleteCommand delete-then-reconnect support, event emission
points for the facade event bus, and related internal adjustments.
This commit is contained in:
2026-07-26 22:43:09 +08:00
parent e9f173916f
commit f95590e924
38 changed files with 302 additions and 746 deletions
+3
View File
@@ -69,6 +69,9 @@ public:
static QString format_string(const QString &input, const QStringList &args);
/** @brief Access the text gizmo. */
TextGizmo *text_gizmo() { return text_gizmo_; }
protected:
virtual void InputValueChangedEvent(const QString &input,
int element) override;
+6 -7
View File
@@ -34,7 +34,6 @@
#include "project.h"
#include "serializeddata.h"
#include "ui/colorcoding.h"
#include "ui/icons/icons.h"
namespace olive
{
@@ -109,7 +108,7 @@ QVariant Node::data(const DataType &d) const
{
if (d == icon) {
// Just a meaningless default icon to be used where necessary
return icon::New;
return QStringLiteral("new");
}
return QVariant();
@@ -2481,7 +2480,7 @@ void Node::childEvent(QChildEvent *event)
connect(key, &NodeKeyframe::bezier_control_out_changed, this,
&Node::invalidate_from_keyframe_bezier_out_change);
emit keyframe_added(key);
emit keyframe_added(reinterpret_cast<OakEngineKeyframe *>(key));
parameter_value_changed(i, get_range_affected_by_keyframe(key));
} else if (event->type() == QEvent::ChildRemoved) {
TimeRange time_affected = get_range_affected_by_keyframe(key);
@@ -2497,7 +2496,7 @@ void Node::childEvent(QChildEvent *event)
disconnect(key, &NodeKeyframe::bezier_control_out_changed, this,
&Node::invalidate_from_keyframe_bezier_out_change);
emit keyframe_removed(key);
emit keyframe_removed(reinterpret_cast<OakEngineKeyframe *>(key));
get_immediate(key->input(), key->element())->remove_keyframe(key);
parameter_value_changed(i, time_affected);
@@ -2570,7 +2569,7 @@ void Node::invalidate_from_keyframe_time_change()
parameter_value_changed(key->key_track_ref().input(), r);
}
emit keyframe_time_changed(key);
emit keyframe_time_changed(reinterpret_cast<OakEngineKeyframe *>(key));
}
void Node::invalidate_from_keyframe_value_change()
@@ -2579,7 +2578,7 @@ void Node::invalidate_from_keyframe_value_change()
parameter_value_changed(key->key_track_ref().input(),
get_range_affected_by_keyframe(key));
emit keyframe_value_changed(key);
emit keyframe_value_changed(reinterpret_cast<OakEngineKeyframe *>(key));
}
void Node::invalidate_from_keyframe_type_changed()
@@ -2597,7 +2596,7 @@ void Node::invalidate_from_keyframe_type_changed()
get_range_around_index(key->input(), track.indexOf(key),
key->track(), key->element()));
emit keyframe_type_changed(key);
emit keyframe_type_changed(reinterpret_cast<OakEngineKeyframe *>(key));
}
void Node::set_value_at_time(const NodeInput &input, const Rational &time,
+9 -5
View File
@@ -47,6 +47,10 @@
#include "render/shadercode.h"
#include "splitvalue.h"
/* Forward declaration for C ABI keyframe handle used in signals that cross
* the app/engine boundary. */
struct OakEngineKeyframe;
namespace olive
{
@@ -1319,17 +1323,17 @@ signals:
void input_array_size_changed(const QString &input, int old_size,
int new_size);
void keyframe_added(NodeKeyframe *key);
void keyframe_added(OakEngineKeyframe *key);
void keyframe_removed(NodeKeyframe *key);
void keyframe_removed(OakEngineKeyframe *key);
void keyframe_time_changed(NodeKeyframe *key);
void keyframe_time_changed(OakEngineKeyframe *key);
void message_count_changed();
void keyframe_type_changed(NodeKeyframe *key);
void keyframe_type_changed(OakEngineKeyframe *key);
void keyframe_value_changed(NodeKeyframe *key);
void keyframe_value_changed(OakEngineKeyframe *key);
void keyframe_enable_changed(const NodeInput &input, bool enabled);
+1 -2
View File
@@ -25,7 +25,6 @@
#include "node/nodeundo.h"
#include "node/project/footage/footage.h"
#include "node/project/sequence/sequence.h"
#include "ui/icons/icons.h"
namespace olive
{
@@ -45,7 +44,7 @@ Folder::Folder()
QVariant Folder::data(const DataType &d) const
{
if (d == icon) {
return icon::folder;
return QStringLiteral("folder");
}
return super::data(d);
+5 -6
View File
@@ -37,7 +37,6 @@
#include "node/color/colormanager/colormanager.h"
#include "node/project.h"
#include "render/job/footagejob.h"
#include "ui/icons/icons.h"
namespace olive
{
@@ -613,18 +612,18 @@ QVariant Footage::data(const DataType &d) const
if (s.is_valid() &&
s.video_type() != VideoParams::k_video_type_still) {
return icon::video;
return QStringLiteral("video");
} else if (has_enabled_audio_streams()) {
return icon::audio;
return QStringLiteral("audio");
} else if (s.is_valid() &&
s.video_type() == VideoParams::k_video_type_still) {
return icon::image;
return QStringLiteral("image");
} else if (has_enabled_subtitle_streams()) {
return icon::subtitles;
return QStringLiteral("subtitles");
}
}
return icon::error;
return QStringLiteral("error");
}
case tooltip: {
if (valid_) {
+1 -2
View File
@@ -23,7 +23,6 @@
#include <QThread>
#include "ui/icons/icons.h"
#include "timeline/timelineundogeneral.h"
namespace olive
@@ -81,7 +80,7 @@ void Sequence::add_default_nodes(MultiUndoCommand *command)
QVariant Sequence::data(const DataType &d) const
{
if (d == icon) {
return icon::sequence;
return QStringLiteral("sequence");
}
return super::data(d);
@@ -33,8 +33,8 @@ set(OLIVE_SOURCES
node/project/serializer/serializer230220.h
node/project/serializer/mainwindowlayoutinfo.cpp
node/project/serializer/mainwindowlayoutinfo.h
node/project/serializer/serializedlayoutinfo.cpp
node/project/serializer/serializedlayoutinfo.h
node/project/serializer/typeserializer.cpp
node/project/serializer/typeserializer.h
@@ -16,19 +16,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "mainwindowlayoutinfo.h"
#include "serializedlayoutinfo.h"
namespace olive
{
void MainWindowLayoutInfo::to_xml(QXmlStreamWriter *writer) const
void SerializedLayoutInfo::to_xml(QXmlStreamWriter *writer) const
{
writer->writeAttribute(QStringLiteral("version"),
QString::number(k_version));
writer->writeStartElement(QStringLiteral("folders"));
foreach (Folder *folder, open_folders_) {
foreach (Folder *folder, open_folders) {
writer->writeTextElement(
QStringLiteral("folder"),
QString::number(reinterpret_cast<quintptr>(folder)));
@@ -38,7 +38,7 @@ void MainWindowLayoutInfo::to_xml(QXmlStreamWriter *writer) const
writer->writeStartElement(QStringLiteral("timeline"));
foreach (Sequence *sequence, open_sequences_) {
foreach (Sequence *sequence, open_sequences) {
writer->writeTextElement(
QStringLiteral("sequence"),
QString::number(reinterpret_cast<quintptr>(sequence)));
@@ -48,7 +48,7 @@ void MainWindowLayoutInfo::to_xml(QXmlStreamWriter *writer) const
writer->writeStartElement(QStringLiteral("viewers"));
foreach (ViewerOutput *viewer, open_viewers_) {
foreach (ViewerOutput *viewer, open_viewers) {
writer->writeTextElement(
QStringLiteral("viewer"),
QString::number(reinterpret_cast<quintptr>(viewer)));
@@ -58,7 +58,7 @@ void MainWindowLayoutInfo::to_xml(QXmlStreamWriter *writer) const
writer->writeStartElement(QStringLiteral("data"));
for (auto it = panel_data_.cbegin(); it != panel_data_.cend(); it++) {
for (auto it = panel_data.cbegin(); it != panel_data.cend(); it++) {
writer->writeStartElement(QStringLiteral("panel"));
writer->writeAttribute(QStringLiteral("id"), it->first);
@@ -80,14 +80,14 @@ void MainWindowLayoutInfo::to_xml(QXmlStreamWriter *writer) const
writer->writeEndElement(); // data
writer->writeTextElement(QStringLiteral("state"),
QString(state_.toBase64()));
QString(state.toBase64()));
}
MainWindowLayoutInfo
MainWindowLayoutInfo::from_xml(QXmlStreamReader *reader,
SerializedLayoutInfo
SerializedLayoutInfo::from_xml(QXmlStreamReader *reader,
const QHash<quintptr, Node *> &node_ptrs)
{
MainWindowLayoutInfo info;
SerializedLayoutInfo info;
unsigned int file_version = 0;
@@ -110,7 +110,7 @@ MainWindowLayoutInfo::from_xml(QXmlStreamReader *reader,
Folder *open_item =
static_cast<Folder *>(node_ptrs.value(item_id));
info.open_folders_.push_back(open_item);
info.open_folders.push_back(open_item);
} else {
reader->skipCurrentElement();
}
@@ -123,7 +123,7 @@ MainWindowLayoutInfo::from_xml(QXmlStreamReader *reader,
Sequence *open_seq =
static_cast<Sequence *>(node_ptrs.value(item_id));
info.open_sequences_.push_back(open_seq);
info.open_sequences.push_back(open_seq);
} else {
reader->skipCurrentElement();
}
@@ -136,14 +136,14 @@ MainWindowLayoutInfo::from_xml(QXmlStreamReader *reader,
ViewerOutput *open_viewer =
static_cast<ViewerOutput *>(node_ptrs.value(item_id));
info.open_viewers_.push_back(open_viewer);
info.open_viewers.push_back(open_viewer);
} else {
reader->skipCurrentElement();
}
}
} else if (reader->name() == QStringLiteral("state")) {
info.state_ =
info.state =
QByteArray::fromBase64(reader->readElementText().toLatin1());
} else if (reader->name() == QStringLiteral("data")) {
@@ -179,7 +179,7 @@ MainWindowLayoutInfo::from_xml(QXmlStreamReader *reader,
}
}
info.panel_data_[id] = i;
info.panel_data[id] = i;
}
} else {
@@ -195,38 +195,4 @@ MainWindowLayoutInfo::from_xml(QXmlStreamReader *reader,
return info;
}
void MainWindowLayoutInfo::add_folder(olive::Folder *f)
{
open_folders_.push_back(f);
}
void MainWindowLayoutInfo::add_sequence(Sequence *seq)
{
open_sequences_.push_back(seq);
}
void MainWindowLayoutInfo::add_viewer(ViewerOutput *viewer)
{
open_viewers_.push_back(viewer);
}
void MainWindowLayoutInfo::set_panel_data(const QString &id,
const PanelLayoutInfo &data)
{
panel_data_[id] = data;
}
void MainWindowLayoutInfo::move_panel_data(const QString &old,
const QString &now)
{
PanelLayoutInfo tmp = panel_data_.at(old);
panel_data_.erase(old);
panel_data_[now] = tmp;
}
void MainWindowLayoutInfo::set_state(const QByteArray &layout)
{
state_ = layout;
}
}
@@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OAK_MAINWINDOWLAYOUTINFO_H
#define OAK_MAINWINDOWLAYOUTINFO_H
#ifndef OAK_SERIALIZEDLAYOUTINFO_H
#define OAK_SERIALIZEDLAYOUTINFO_H
#include <map>
@@ -35,68 +35,38 @@ namespace olive
*/
using PanelLayoutInfo = std::map<QString, QString>;
class MainWindowLayoutInfo {
/**
* @brief Plain data container for a serialized main window layout
*
* Pure data structure with no behavior beyond XML (de)serialization, so
* consumers (app, tests) can use it without pulling in any engine-side
* C++ symbols.
*/
class SerializedLayoutInfo {
public:
MainWindowLayoutInfo() = default;
SerializedLayoutInfo() = default;
void to_xml(QXmlStreamWriter *writer) const;
static MainWindowLayoutInfo
static SerializedLayoutInfo
from_xml(QXmlStreamReader *reader, const QHash<quintptr, Node *> &node_map);
void add_folder(Folder *f);
QByteArray state;
void add_sequence(Sequence *seq);
std::vector<Folder *> open_folders;
void add_viewer(ViewerOutput *viewer);
std::vector<Sequence *> open_sequences;
void set_panel_data(const QString &id, const PanelLayoutInfo &data);
std::vector<ViewerOutput *> open_viewers;
void move_panel_data(const QString &old, const QString &now);
void set_state(const QByteArray &layout);
const std::vector<Folder *> &open_folders() const
{
return open_folders_;
}
const std::vector<Sequence *> &open_sequences() const
{
return open_sequences_;
}
const std::vector<ViewerOutput *> &open_viewers() const
{
return open_viewers_;
}
const std::map<QString, PanelLayoutInfo> &panel_data() const
{
return panel_data_;
}
const QByteArray &state() const
{
return state_;
}
std::map<QString, PanelLayoutInfo> panel_data;
private:
QByteArray state_;
std::vector<Folder *> open_folders_;
std::vector<Sequence *> open_sequences_;
std::vector<ViewerOutput *> open_viewers_;
std::map<QString, PanelLayoutInfo> panel_data_;
static const unsigned int k_version = 1;
};
}
Q_DECLARE_METATYPE(olive::MainWindowLayoutInfo)
Q_DECLARE_METATYPE(olive::SerializedLayoutInfo)
#endif // OAK_MAINWINDOWLAYOUTINFO_H
#endif // OAK_SERIALIZEDLAYOUTINFO_H
+5 -5
View File
@@ -26,7 +26,7 @@
#include "common/define.h"
#include "node/project.h"
#include "node/project/serializer/mainwindowlayoutinfo.h"
#include "node/project/serializer/serializedlayoutinfo.h"
#include "typeserializer.h"
namespace olive
@@ -80,7 +80,7 @@ public:
SerializedKeyframes keyframes;
MainWindowLayoutInfo layout;
SerializedLayoutInfo layout;
QVector<Node *> nodes;
@@ -173,11 +173,11 @@ public:
return type_;
}
const MainWindowLayoutInfo &get_layout() const
const SerializedLayoutInfo &get_layout() const
{
return layout_;
}
void set_layout(const MainWindowLayoutInfo &layout)
void set_layout(const SerializedLayoutInfo &layout)
{
layout_ = layout;
}
@@ -226,7 +226,7 @@ public:
QString filename_;
MainWindowLayoutInfo layout_;
SerializedLayoutInfo layout_;
QVector<Node *> only_serialize_nodes_;
@@ -55,7 +55,7 @@ ProjectSerializer220403::load(Project *project, QXmlStreamReader *reader,
// can continue loading and queue it with the main window so it can handle the data
// appropriately in its own thread.
load_data.layout = MainWindowLayoutInfo::from_xml(
load_data.layout = SerializedLayoutInfo::from_xml(
reader, xml_node_data.node_ptrs);
} else if (reader->name() == QStringLiteral("uuid")) {
@@ -49,7 +49,7 @@ ProjectSerializer230220::load(Project *project, QXmlStreamReader *reader,
project_data = project->load(reader);
load_data.node_ptrs = project_data.node_ptrs;
} else if (reader->name() == QStringLiteral("layout")) {
load_data.layout = MainWindowLayoutInfo::from_xml(
load_data.layout = SerializedLayoutInfo::from_xml(
reader, project_data.node_ptrs);
} else {
reader->skipCurrentElement();