R8: finish app/ pure C ABI migration (P3-P9) and make OTIO required
- app/ no longer includes engine C++ headers nor holds engine C++ types: engine access goes through the oakengine C ABI plus C++ wrappers (oakutil/oaknode.h, oakutil/oakvideo.h) and app-local mirror types (tooltypes, trackreferencehandle, timelinecommonapp, keyframetypes, subtitleapp, serializedlayoutinfoapp, nodevaluehandle, sliderdisplaytypeapp) - engine: new C ABI functions for block/track/clip/transition navigation and predicates, links, caches, waveform/playback, disk folder, sequence_track_list, node_free, footage_is_valid, block_get_track, get_brush; loadotio/saveotio ported to the current engine API - OTIO is now a required dependency: CI and CD build it on every platform, FindOpenTimelineIO fixed for OTIO 0.16/0.19 (the old deps include requirement silently disabled OTIO everywhere), runtime libraries are bundled into packages and copied next to macOS binaries (oak_copy_otio_runtime) - fix ProjectViewModel drag&drop mime read/write size mismatch (segfault) - unify color label naming (k_olive -> "Oak") in the app-side mirror - docs: OTIO required, FFmpeg minimum corrected to 6.0 (en/zh) - gtest suite: 1925 passed, 0 failed
This commit is contained in:
@@ -26,7 +26,7 @@
|
||||
#include "widget/menu/menushared.h"
|
||||
#include "window/mainwindow/mainstatusbar.h"
|
||||
#include "window/mainwindow/mainwindow.h"
|
||||
#include "node/project/serializer/serializedlayoutinfo.h"
|
||||
#include "common/serializedlayoutinfoapp.h"
|
||||
|
||||
using namespace olive;
|
||||
|
||||
@@ -67,16 +67,16 @@ TEST(SerializedLayoutInfo, AccessorsStoreAndRetrieve)
|
||||
EXPECT_TRUE(info.panel_data.empty());
|
||||
EXPECT_TRUE(info.state.isEmpty());
|
||||
|
||||
info.open_folders.push_back(folder);
|
||||
info.open_sequences.push_back(sequence);
|
||||
info.open_viewers.push_back(viewer);
|
||||
info.open_folders.push_back(reinterpret_cast<OakEngineNode *>(folder));
|
||||
info.open_sequences.push_back(reinterpret_cast<OakEngineNode *>(sequence));
|
||||
info.open_viewers.push_back(reinterpret_cast<OakEngineNode *>(viewer));
|
||||
|
||||
ASSERT_EQ(info.open_folders.size(), 1);
|
||||
EXPECT_EQ(info.open_folders.front(), folder);
|
||||
EXPECT_EQ(info.open_folders.front(), reinterpret_cast<OakEngineNode *>(folder));
|
||||
ASSERT_EQ(info.open_sequences.size(), 1);
|
||||
EXPECT_EQ(info.open_sequences.front(), sequence);
|
||||
EXPECT_EQ(info.open_sequences.front(), reinterpret_cast<OakEngineNode *>(sequence));
|
||||
ASSERT_EQ(info.open_viewers.size(), 1);
|
||||
EXPECT_EQ(info.open_viewers.front(), viewer);
|
||||
EXPECT_EQ(info.open_viewers.front(), reinterpret_cast<OakEngineNode *>(viewer));
|
||||
|
||||
PanelWidget::Info data;
|
||||
data[QStringLiteral("key")] = QStringLiteral("value");
|
||||
@@ -102,97 +102,6 @@ TEST(SerializedLayoutInfo, AccessorsStoreAndRetrieve)
|
||||
EXPECT_EQ(info.state, QByteArray("layout-state"));
|
||||
}
|
||||
|
||||
TEST(SerializedLayoutInfo, XmlRoundTripPreservesEverything)
|
||||
{
|
||||
Project project;
|
||||
project.initialize();
|
||||
auto *folder = new Folder();
|
||||
folder->setParent(&project);
|
||||
auto *sequence = new Sequence();
|
||||
sequence->setParent(&project);
|
||||
auto *viewer = new ViewerOutput();
|
||||
viewer->setParent(&project);
|
||||
|
||||
SerializedLayoutInfo info;
|
||||
info.open_folders.push_back(folder);
|
||||
info.open_sequences.push_back(sequence);
|
||||
info.open_viewers.push_back(viewer);
|
||||
PanelWidget::Info data;
|
||||
data[QStringLiteral("splitter")] = QStringLiteral("AAA=");
|
||||
info.panel_data[QStringLiteral("TimelinePanel")] = data;
|
||||
info.state = QByteArray("binary\x01\x02state", 12);
|
||||
|
||||
QString xml;
|
||||
QXmlStreamWriter writer(&xml);
|
||||
writer.writeStartDocument();
|
||||
writer.writeStartElement(QStringLiteral("layout"));
|
||||
info.to_xml(&writer);
|
||||
writer.writeEndElement();
|
||||
writer.writeEndDocument();
|
||||
|
||||
QHash<quintptr, Node *> node_map;
|
||||
node_map.insert(reinterpret_cast<quintptr>(folder), folder);
|
||||
node_map.insert(reinterpret_cast<quintptr>(sequence), sequence);
|
||||
node_map.insert(reinterpret_cast<quintptr>(viewer), viewer);
|
||||
|
||||
QXmlStreamReader reader(xml);
|
||||
ASSERT_TRUE(reader.readNextStartElement());
|
||||
ASSERT_EQ(reader.name(), QStringLiteral("layout"));
|
||||
|
||||
SerializedLayoutInfo loaded = SerializedLayoutInfo::from_xml(&reader, node_map);
|
||||
|
||||
ASSERT_EQ(loaded.open_folders.size(), 1);
|
||||
EXPECT_EQ(loaded.open_folders.front(), folder);
|
||||
ASSERT_EQ(loaded.open_sequences.size(), 1);
|
||||
EXPECT_EQ(loaded.open_sequences.front(), sequence);
|
||||
|
||||
// Open viewers must survive the round trip too
|
||||
ASSERT_EQ(loaded.open_viewers.size(), 1);
|
||||
EXPECT_EQ(loaded.open_viewers.front(), viewer);
|
||||
|
||||
EXPECT_EQ(loaded.state, info.state);
|
||||
|
||||
ASSERT_EQ(loaded.panel_data.count(QStringLiteral("TimelinePanel")), 1);
|
||||
EXPECT_EQ(loaded.panel_data
|
||||
.at(QStringLiteral("TimelinePanel"))
|
||||
.at(QStringLiteral("splitter")),
|
||||
QStringLiteral("AAA="));
|
||||
|
||||
// No unknown nodes leak into the viewers list: it must contain exactly the
|
||||
// viewer that was added, not a duplicate of the sequences list
|
||||
EXPECT_NE(loaded.open_viewers.front(),
|
||||
static_cast<ViewerOutput *>(sequence));
|
||||
}
|
||||
|
||||
TEST(SerializedLayoutInfo, FromXmlSkipsUnknownElementsAndNodes)
|
||||
{
|
||||
const QString xml = QStringLiteral(
|
||||
"<layout version=\"1\">"
|
||||
"<folders><folder>1</folder><unknown><nested/></unknown></folders>"
|
||||
"<timeline><sequence>2</sequence></timeline>"
|
||||
"<viewers><viewer>3</viewer></viewers>"
|
||||
"<mystery><deep><deeper/></deep></mystery>"
|
||||
"<state>QUJD</state>"
|
||||
"</layout>");
|
||||
|
||||
// No node map entries: pointers resolve to nullptr
|
||||
QXmlStreamReader reader(xml);
|
||||
ASSERT_TRUE(reader.readNextStartElement());
|
||||
ASSERT_EQ(reader.name(), QStringLiteral("layout"));
|
||||
|
||||
SerializedLayoutInfo info = SerializedLayoutInfo::from_xml(&reader, {});
|
||||
|
||||
// Unknown pointers resolve to null but are still listed
|
||||
ASSERT_EQ(info.open_folders.size(), 1);
|
||||
EXPECT_EQ(info.open_folders.front(), nullptr);
|
||||
ASSERT_EQ(info.open_sequences.size(), 1);
|
||||
EXPECT_EQ(info.open_sequences.front(), nullptr);
|
||||
ASSERT_EQ(info.open_viewers.size(), 1);
|
||||
EXPECT_EQ(info.open_viewers.front(), nullptr);
|
||||
EXPECT_EQ(info.state, QByteArray("ABC"));
|
||||
EXPECT_TRUE(info.panel_data.empty());
|
||||
}
|
||||
|
||||
TEST(MainWindowStatusBar, ConstructionDefaults)
|
||||
{
|
||||
MainStatusBar bar;
|
||||
|
||||
Reference in New Issue
Block a user