app: migrate all engine access to the C ABI facade (nm U _ZN5olive = 0)

Every app module now reaches liboakengine exclusively through
oakengine_* C calls, EngineEventBridge subscriptions and app-side
handle headers (cliphandle/keyframehandle/nodevaluehandle/oakvaluehelper).
Direct C++ command construction, engine signal connect()s, and engine
type usage in MOC-visible signatures are gone: 557 -> 0 undefined
olive:: symbols in oak-editor.
This commit is contained in:
2026-07-26 22:43:21 +08:00
parent f95590e924
commit 0aa5879f35
256 changed files with 12357 additions and 4044 deletions
+22 -12
View File
@@ -26,8 +26,9 @@
#include <QEvent>
#include <QStyleFactory>
#include "config/config.h"
#include "core.h"
#include "oakengine/project.h"
#include "oakengine/undo.h"
#include "dialog/actionsearch/actionsearch.h"
#include "dialog/diskcache/diskcachedialog.h"
#include "dialog/proxy/proxydialog.h"
@@ -38,6 +39,7 @@
#include "undo/undostack.h"
#include "widget/menu/menushared.h"
#include "mainwindow.h"
#include "common/configwrapper.h"
namespace olive
{
@@ -89,10 +91,10 @@ MainMenu::MainMenu(MainWindow *parent)
connect(edit_menu_, &Menu::aboutToHide, this,
&MainMenu::edit_menu_about_to_hide);
edit_undo_item_ = Core::instance()->undo_stack()->GetUndoAction();
edit_undo_item_ = reinterpret_cast<QAction*>(oakengine_undo_undo_action());
Menu::conform_item(edit_undo_item_, "undo", tr("Ctrl+Z"));
edit_menu_->addAction(edit_undo_item_);
edit_redo_item_ = Core::instance()->undo_stack()->GetRedoAction();
edit_redo_item_ = reinterpret_cast<QAction*>(oakengine_undo_redo_action());
Menu::conform_item(edit_redo_item_, "redo", tr("Ctrl+Shift+Z"));
edit_menu_->addAction(edit_redo_item_);
@@ -365,7 +367,7 @@ MainMenu::MainMenu(MainWindow *parent)
Menu::conform_item(tools_use_proxy_item_, "useproxymedia");
tools_use_proxy_item_->setCheckable(true);
tools_use_proxy_item_->setChecked(
Config::current()[QStringLiteral("UseProxyMedia")].toBool());
OAK_CONFIG("UseProxyMedia").toBool());
connect(tools_use_proxy_item_, &QAction::triggered, Core::instance(),
&Core::set_use_proxy_media);
tools_menu_->addAction(tools_use_proxy_item_);
@@ -439,9 +441,13 @@ void MainMenu::file_menu_about_to_show()
file_save_as_item_->setEnabled(active_project);
if (active_project) {
file_save_item_->setText(tr("&Save '%1'").arg(active_project->name()));
char name_buf[256];
oakengine_project_name(
reinterpret_cast<OakEngineProject *>(active_project),
name_buf, sizeof(name_buf));
file_save_item_->setText(tr("&Save '%1'").arg(name_buf));
file_save_as_item_->setText(
tr("Save '%1' &As").arg(active_project->name()));
tr("Save '%1' &As").arg(name_buf));
} else {
file_save_item_->setText(tr("&Save Project"));
file_save_as_item_->setText(tr("Save Project &As"));
@@ -543,7 +549,7 @@ void MainMenu::window_menu_about_to_show()
void MainMenu::populate_open_recent()
{
if (Core::instance()->get_recent_projects().isEmpty()) {
if (Core::instance()->get_recent_project_count() == 0) {
// Insert dummy/disabled action to show there's nothing
QAction *a = new QAction(tr("(None)"));
a->setEnabled(false);
@@ -551,9 +557,9 @@ void MainMenu::populate_open_recent()
} else {
// Populate menu with recently opened projects
for (int i = 0; i < Core::instance()->get_recent_projects().size(); i++) {
for (int i = 0; i < Core::instance()->get_recent_project_count(); i++) {
QAction *a =
new QAction(Core::instance()->get_recent_projects().at(i));
new QAction(Core::instance()->get_recent_project_at(i));
a->setData(i);
connect(a, &QAction::triggered, this,
&MainMenu::open_recent_item_triggered);
@@ -796,8 +802,12 @@ void MainMenu::sequence_cache_in_out_triggered()
void MainMenu::sequence_cache_clear_triggered()
{
DiskCacheDialog::clear_disk_cache(
Core::instance()->get_active_project()->cache_path(),
char cache_buf[512];
oakengine_project_cache_path(
reinterpret_cast<OakEngineProject *>(
Core::instance()->get_active_project()),
cache_buf, sizeof(cache_buf));
DiskCacheDialog::clear_disk_cache(cache_buf,
Core::instance()->main_window());
}
@@ -827,7 +837,7 @@ void MainMenu::retranslate()
// Edit menu
edit_menu_->setTitle(tr("&Edit"));
Core::instance()->undo_stack()->update_actions(); // Update undo and redo
oakengine_undo_update_actions(); // Update undo and redo
edit_delete2_item_->setText(tr("Delete (alt)"));
edit_insert_item_->setText(tr("Insert"));
edit_overwrite_item_->setText(tr("Overwrite"));
+59 -42
View File
@@ -23,13 +23,17 @@
#include <QCoreApplication>
#include "engineeventbridge.h"
namespace olive
{
MainStatusBar::MainStatusBar(QWidget *parent)
: QStatusBar(parent)
, manager_(nullptr)
, bridge_(nullptr)
, connected_task_(nullptr)
, task_progress_sub_(0)
, task_finished_sub_(0)
{
setSizeGripEnabled(false);
@@ -46,56 +50,69 @@ MainStatusBar::MainStatusBar(QWidget *parent)
10000);
}
void MainStatusBar::connect_task_manager(TaskManager *manager)
void MainStatusBar::connect_task_manager(EngineEventBridge *bridge)
{
if (manager_) {
disconnect(manager_, &TaskManager::task_list_changed, this,
&MainStatusBar::update_status);
}
bridge_ = bridge;
bridge_->subscribe(oakengine_task_manager_handle(),
OAKENGINE_EVENT_TASK_MANAGER_LIST_CHANGED);
connect(bridge_, &EngineEventBridge::task_manager_list_changed,
this, &MainStatusBar::update_status);
manager_ = manager;
if (manager_) {
connect(manager_, &TaskManager::task_list_changed, this,
&MainStatusBar::update_status);
}
// Route progress/finished events for any task we track
connect(bridge_, &EngineEventBridge::task_progress,
this, [this](OakEngineTask *task, double d) {
if (task == connected_task_) {
set_progress_bar_value(d);
}
});
connect(bridge_, &EngineEventBridge::task_finished,
this, [this](OakEngineTask *task, bool) {
if (task == connected_task_) {
connected_task_finished();
}
});
}
void MainStatusBar::update_status()
{
if (!manager_) {
return;
}
if (manager_->get_task_count() == 0) {
const int count = oakengine_task_manager_count();
if (count <= 0) {
clearMessage();
bar_->setVisible(false);
bar_->setValue(0);
} else {
Task *t = manager_->get_first_task();
if (manager_->get_task_count() == 1) {
showMessage(t->get_title());
} else {
showMessage(tr("Running %n background task(s)", nullptr,
manager_->get_task_count()));
}
bar_->setVisible(true);
if (connected_task_) {
disconnect(connected_task_, &Task::progress_changed, this,
&MainStatusBar::set_progress_bar_value);
disconnect(connected_task_, &Task::destroyed, this,
&MainStatusBar::connected_task_deleted);
}
connected_task_ = t;
connect(connected_task_, &Task::progress_changed, this,
&MainStatusBar::set_progress_bar_value);
connect(connected_task_, &Task::destroyed, this,
&MainStatusBar::connected_task_deleted);
connected_task_ = nullptr;
return;
}
OakEngineTask *t = oakengine_task_manager_first();
if (count == 1) {
char title[256];
oakengine_task_title(t, title, sizeof(title));
showMessage(QString::fromUtf8(title));
} else {
showMessage(tr("Running %n background task(s)", nullptr, count));
}
bar_->setVisible(true);
// Unsubscribe from previous task events
if (task_progress_sub_ > 0) {
bridge_->unsubscribe(task_progress_sub_);
task_progress_sub_ = 0;
}
if (task_finished_sub_ > 0) {
bridge_->unsubscribe(task_finished_sub_);
task_finished_sub_ = 0;
}
connected_task_ = t;
// Subscribe to progress and finished events on this task
task_progress_sub_ = bridge_->subscribe(
t, OAKENGINE_EVENT_TASK_PROGRESS);
task_finished_sub_ = bridge_->subscribe(
t, OAKENGINE_EVENT_TASK_FINISHED);
}
void MainStatusBar::set_progress_bar_value(double d)
@@ -103,7 +120,7 @@ void MainStatusBar::set_progress_bar_value(double d)
bar_->setValue(qRound(100.0 * d));
}
void MainStatusBar::connected_task_deleted()
void MainStatusBar::connected_task_finished()
{
connected_task_ = nullptr;
}
+12 -6
View File
@@ -25,20 +25,22 @@
#include <QProgressBar>
#include <QStatusBar>
#include "task/taskmanager.h"
#include "oakengine/task.h"
namespace olive
{
class EngineEventBridge;
/**
* @brief Shows abbreviated information from a TaskManager object
* @brief Shows abbreviated information from the global TaskManager
*/
class MainStatusBar : public QStatusBar {
Q_OBJECT
public:
MainStatusBar(QWidget *parent = nullptr);
void connect_task_manager(TaskManager *manager);
void connect_task_manager(EngineEventBridge *bridge);
signals:
void double_clicked();
@@ -51,14 +53,18 @@ private slots:
void set_progress_bar_value(double d);
void connected_task_deleted();
void connected_task_finished();
private:
TaskManager *manager_;
EngineEventBridge *bridge_;
QProgressBar *bar_;
Task *connected_task_;
OakEngineTask *connected_task_;
int64_t task_progress_sub_;
int64_t task_finished_sub_;
};
}
+79 -40
View File
@@ -32,11 +32,17 @@
#include "KDDockWidgets/src/qtwidgets/Window_p.h"
#include "dialog/about/about.h"
#include "engineeventbridge.h"
#include "mainmenu.h"
#include "mainstatusbar.h"
#include "KDDockWidgets/src/LayoutSaver.h"
#include "timeline/timelineundoworkarea.h"
#include "oakengine/timeline.h"
#include "common/configwrapper.h"
#include "oakengine/project.h"
#include "oakengine/viewer.h"
#include "oakengine/undo.h"
#include "widget/viewer/vieweroutpututils.h"
namespace olive
{
@@ -47,6 +53,9 @@ MainWindow::MainWindow(QWidget *parent)
parent)
, project_(nullptr)
{
bridge_ = new EngineEventBridge(this);
connect(bridge_, &EngineEventBridge::node_removed_from_graph, this,
&MainWindow::viewer_with_panel_removed_from_graph);
// Resizes main window to desktop geometry on startup. Fixes the following issues:
// * Qt on Windows has a bug that "de-maximizes" the window when widgets are added, resizing the
// window beforehand works around that issue and we just set it to whatever size is available.
@@ -71,8 +80,9 @@ MainWindow::MainWindow(QWidget *parent)
load_custom_shortcuts();
// Create and set status bar
event_bridge_ = new EngineEventBridge(this);
MainStatusBar *status_bar = new MainStatusBar(this);
status_bar->connect_task_manager(TaskManager::instance());
status_bar->connect_task_manager(event_bridge_);
connect(status_bar, &MainStatusBar::double_clicked, this,
&MainWindow::status_bar_double_clicked);
setStatusBar(status_bar);
@@ -151,21 +161,21 @@ MainWindow::~MainWindow()
#endif
}
void MainWindow::load_layout(const MainWindowLayoutInfo &info)
void MainWindow::load_layout(const SerializedLayoutInfo &info)
{
foreach (Folder *folder, info.open_folders()) {
foreach (Folder *folder, info.open_folders) {
open_folder(folder, true);
}
foreach (Sequence *sequence, info.open_sequences()) {
open_sequence(sequence, info.open_sequences().size() == 1);
foreach (Sequence *sequence, info.open_sequences) {
open_sequence(sequence, info.open_sequences.size() == 1);
}
foreach (ViewerOutput *viewer, info.open_viewers()) {
foreach (ViewerOutput *viewer, info.open_viewers) {
open_node_in_viewer(viewer);
}
for (auto it = info.panel_data().cbegin(); it != info.panel_data().cend();
for (auto it = info.panel_data.cbegin(); it != info.panel_data.cend();
it++) {
// Find panel with this ID
if (PanelWidget *panel =
@@ -174,7 +184,7 @@ void MainWindow::load_layout(const MainWindowLayoutInfo &info)
}
}
KDDockWidgets::LayoutSaver().restoreLayout(qUncompress(info.state()));
KDDockWidgets::LayoutSaver().restoreLayout(qUncompress(info.state));
}
QString transform_name_for_serialization(const QString &unique, int i)
@@ -184,46 +194,47 @@ QString transform_name_for_serialization(const QString &unique, int i)
}
void correct_panel_data_if_necessary(const QString &unique_name, int index,
MainWindowLayoutInfo &info, QByteArray &layout)
SerializedLayoutInfo &info, QByteArray &layout)
{
QString corrected = transform_name_for_serialization(unique_name, index);
if (corrected != unique_name) {
info.move_panel_data(unique_name, corrected);
info.panel_data[corrected] = info.panel_data[unique_name];
info.panel_data.erase(unique_name);
layout.replace(unique_name.toUtf8(), corrected.toUtf8());
}
}
MainWindowLayoutInfo MainWindow::save_layout() const
SerializedLayoutInfo MainWindow::save_layout() const
{
MainWindowLayoutInfo info;
SerializedLayoutInfo info;
QByteArray layout = premaximized_state_.isEmpty() ?
KDDockWidgets::LayoutSaver().serializeLayout() :
premaximized_state_;
foreach (PanelWidget *panel, PanelManager::instance()->panels()) {
info.set_panel_data(panel->uniqueName(), panel->save_data());
info.panel_data[panel->uniqueName()] = panel->save_data();
}
for (int i = 0; i < folder_panels_.size(); i++) {
auto panel = folder_panels_.at(i);
info.add_folder(panel->get_root());
info.open_folders.push_back(panel->get_root());
correct_panel_data_if_necessary(panel->uniqueName(), i, info, layout);
}
for (int i = 0; i < timeline_panels_.size(); i++) {
auto panel = timeline_panels_.at(i);
info.add_sequence(panel->get_sequence());
info.open_sequences.push_back(panel->get_sequence());
correct_panel_data_if_necessary(panel->uniqueName(), i, info, layout);
}
for (int i = 0; i < viewer_panels_.size(); i++) {
auto panel = viewer_panels_.at(i);
info.add_viewer(panel->get_connected_viewer());
info.open_viewers.push_back(panel->get_connected_viewer());
correct_panel_data_if_necessary(panel->uniqueName(), i, info, layout);
}
info.set_state(qCompress(layout));
info.state = qCompress(layout);
return info;
}
@@ -325,8 +336,10 @@ void MainWindow::open_node_in_viewer(ViewerOutput *node)
connect(viewer, &ViewerPanel::close_requested, this,
&MainWindow::viewer_close_requested);
connect(node, &ViewerOutput::removed_from_graph, this,
&MainWindow::viewer_with_panel_removed_from_graph);
auto sub = bridge_->subscribe(
reinterpret_cast<void *>(node),
OAKENGINE_EVENT_NODE_REMOVED_FROM_GRAPH);
removed_from_graph_subs_[node] = sub;
}
}
@@ -538,13 +551,18 @@ void MainWindow::node_panel_group_opened_or_closed()
param_panel_->set_contexts(p->get_contexts());
}
void MainWindow::timeline_panel_selection_changed(const QVector<Block *> &blocks)
void MainWindow::timeline_panel_selection_changed(const QVector<OakEngineBlock *> &blocks)
{
TimelinePanel *panel = static_cast<TimelinePanel *>(sender());
if (PanelManager::instance()->currently_focused(false) == panel) {
update_node_panel_context_from_timeline_panel(panel);
sequence_viewer_panel_->set_timeline_selected_blocks(blocks);
QVector<Block *> native_blocks;
native_blocks.reserve(blocks.size());
for (OakEngineBlock *b : blocks) {
native_blocks.append(reinterpret_cast<Block *>(b));
}
sequence_viewer_panel_->set_timeline_selected_blocks(native_blocks);
}
}
@@ -556,32 +574,46 @@ void MainWindow::show_welcome_dialog()
}
}
void MainWindow::reveal_viewer_in_project(ViewerOutput *r)
void MainWindow::reveal_viewer_in_project(OakEngineNode *r)
{
// Rather than just using the resident ProjectPanel, find the most recently focused one since
// that's probably the one people will want
auto panels = PanelManager::instance()->get_panels_of_type<ProjectPanel>();
ViewerOutput *viewer = reinterpret_cast<ViewerOutput *>(r);
foreach (ProjectPanel *p, panels) {
if (p->select_item(r)) {
if (p->select_item(viewer)) {
break;
}
}
}
void MainWindow::reveal_viewer_in_footage_viewer(ViewerOutput *r,
void MainWindow::reveal_viewer_in_footage_viewer(OakEngineNode *r,
const TimeRange &range)
{
footage_viewer_panel_->connect_viewer_node(r);
ViewerOutput *viewer = reinterpret_cast<ViewerOutput *>(r);
auto command = new MultiUndoCommand();
if (!r->get_work_area()->enabled()) {
command->add_child(new WorkareaSetEnabledCommand(
r->project(), r->get_work_area(), true));
footage_viewer_panel_->connect_viewer_node(viewer);
auto command = oakengine_undo_command_create_multi();
OakEngineWorkarea *wa = reinterpret_cast<OakEngineWorkarea *>(viewer->get_work_area());
if (!viewer->get_work_area()->enabled()) {
oakengine_workarea_set_enabled_undoable(wa, 1, command);
}
command->add_child(new WorkareaSetRangeCommand(r->get_work_area(), range));
Core::instance()->undo_stack()->push(command, tr("Set Footage Workarea"));
{
int64_t old_in_num, old_in_den, old_out_num, old_out_den;
int old_enabled;
oakengine_workarea_get(wa, &old_in_num, &old_in_den,
&old_out_num, &old_out_den, &old_enabled);
oakengine_workarea_set_range_undoable(wa,
range.in().numerator(), range.in().denominator(),
range.out().numerator(), range.out().denominator(),
old_in_num, old_in_den, old_out_num, old_out_den, command);
}
oakengine_undo_push(command, tr("Set Footage Workarea").toUtf8().constData());
r->set_playhead(range.in());
oakengine_viewer_set_playhead(
r,
range.in().numerator(), range.in().denominator());
}
#ifdef Q_OS_LINUX
@@ -599,11 +631,15 @@ void MainWindow::show_nouveau_warning()
void MainWindow::update_title()
{
if (Core::instance()->get_active_project()) {
char name_buf[256];
oakengine_project_pretty_filename(
reinterpret_cast<OakEngineProject *>(
Core::instance()->get_active_project()),
name_buf, sizeof(name_buf));
setWindowTitle(
QStringLiteral("%1 %2 - [*]%3")
.arg(QApplication::applicationName(),
QApplication::applicationVersion(),
Core::instance()->get_active_project()->pretty_filename()));
QApplication::applicationVersion(), name_buf));
} else {
setWindowTitle(
QStringLiteral("%1 %2").arg(QApplication::applicationName(),
@@ -630,9 +666,9 @@ void MainWindow::viewer_close_requested()
panel->deleteLater();
}
void MainWindow::viewer_with_panel_removed_from_graph()
void MainWindow::viewer_with_panel_removed_from_graph(OakEngineNode *source)
{
ViewerOutput *vo = static_cast<ViewerOutput *>(sender());
ViewerOutput *vo = reinterpret_cast<ViewerOutput *>(source);
ViewerPanel *panel = nullptr;
foreach (ViewerPanel *p, viewer_panels_) {
@@ -645,8 +681,11 @@ void MainWindow::viewer_with_panel_removed_from_graph()
if (panel) {
remove_panel_internal(viewer_panels_, panel);
panel->deleteLater();
disconnect(vo, &ViewerOutput::removed_from_graph, this,
&MainWindow::viewer_with_panel_removed_from_graph);
auto it = removed_from_graph_subs_.find(vo);
if (it != removed_from_graph_subs_.end()) {
bridge_->unsubscribe(it.value());
removed_from_graph_subs_.erase(it);
}
}
}
@@ -815,7 +854,7 @@ void MainWindow::save_custom_shortcuts()
void MainWindow::update_audio_monitor_params(ViewerOutput *viewer)
{
if (!audio_monitor_panel_->is_playing()) {
audio_monitor_panel_->set_params(viewer ? viewer->get_audio_params() :
audio_monitor_panel_->set_params(viewer ? viewer_output_audio_params(viewer) :
AudioParams());
}
}
+21 -9
View File
@@ -25,7 +25,7 @@
#include <kddockwidgets/Config.h>
#include <kddockwidgets/MainWindow.h>
#include "node/project/serializer/mainwindowlayoutinfo.h"
#include "node/project/serializer/serializedlayoutinfo.h"
#include "node/project.h"
#include "panel/multicam/multicampanel.h"
#include "panel/panelmanager.h"
@@ -43,6 +43,7 @@
#include "panel/footageviewer/footageviewer.h"
#include "panel/sequenceviewer/sequenceviewer.h"
#include "panel/pixelsampler/pixelsamplerpanel.h"
#include "engineeventbridge.h"
#ifdef Q_OS_WINDOWS
#include <shobjidl.h>
@@ -51,6 +52,8 @@
namespace olive
{
class EngineEventBridge;
/**
* @brief Olive's main window responsible for docking widgets and the main menu bar.
*/
@@ -61,9 +64,9 @@ public:
virtual ~MainWindow() override;
void load_layout(const MainWindowLayoutInfo &info);
void load_layout(const SerializedLayoutInfo &info);
MainWindowLayoutInfo save_layout() const;
SerializedLayoutInfo save_layout() const;
TimelinePanel *open_sequence(Sequence *sequence, bool enable_focus = true);
@@ -94,9 +97,13 @@ public:
void select_footage(const QVector<Footage *> &e);
public slots:
public:
// Not a slot: signature uses the engine C++ type Project*, which must not
// be exposed to MOC (it would pull Project::staticMetaObject across the ABI
// boundary). It is only ever called directly, never via connect().
void set_project(Project *p);
public slots:
void set_fullscreen(bool fullscreen);
void toggle_maximized_panel();
@@ -157,6 +164,7 @@ private:
QList<TimelinePanel *> timeline_panels_;
AudioMonitorPanel *audio_monitor_panel_;
TaskManagerPanel *task_man_panel_;
EngineEventBridge *event_bridge_;
PixelSamplerPanel *pixel_sampler_panel_;
ScopePanel *scope_panel_;
QList<ViewerPanel *> viewer_panels_;
@@ -182,7 +190,7 @@ private slots:
void viewer_close_requested();
void viewer_with_panel_removed_from_graph();
void viewer_with_panel_removed_from_graph(OakEngineNode *source);
void folder_panel_close_requested();
@@ -194,12 +202,16 @@ private slots:
void show_nouveau_warning();
#endif
void timeline_panel_selection_changed(const QVector<Block *> &blocks);
void show_welcome_dialog();
void reveal_viewer_in_project(ViewerOutput *r);
void reveal_viewer_in_footage_viewer(ViewerOutput *r, const TimeRange &range);
void reveal_viewer_in_project(OakEngineNode *r);
void reveal_viewer_in_footage_viewer(OakEngineNode *r, const TimeRange &range);
private:
void timeline_panel_selection_changed(const QVector<OakEngineBlock *> &blocks);
EngineEventBridge *bridge_ = nullptr;
QHash<ViewerOutput *, int64_t> removed_from_graph_subs_;
};
}
+44 -8
View File
@@ -24,27 +24,63 @@
#include "core.h"
#include "window/mainwindow/mainwindow.h"
#include "oakengine/undo.h"
namespace olive
{
void OpenSequenceCommand::redo()
namespace {
struct OpenCloseSequenceData {
Sequence *sequence;
};
void open_sequence_redo(void *userdata)
{
Core::instance()->main_window()->open_sequence(sequence_);
auto *d = static_cast<OpenCloseSequenceData *>(userdata);
Core::instance()->main_window()->open_sequence(d->sequence);
}
void OpenSequenceCommand::undo()
void open_sequence_undo(void *userdata)
{
Core::instance()->main_window()->close_sequence(sequence_);
auto *d = static_cast<OpenCloseSequenceData *>(userdata);
Core::instance()->main_window()->close_sequence(d->sequence);
}
void CloseSequenceCommand::redo()
void close_sequence_redo(void *userdata)
{
Core::instance()->main_window()->close_sequence(sequence_);
auto *d = static_cast<OpenCloseSequenceData *>(userdata);
Core::instance()->main_window()->close_sequence(d->sequence);
}
void CloseSequenceCommand::undo()
void close_sequence_undo(void *userdata)
{
Core::instance()->main_window()->open_sequence(sequence_);
auto *d = static_cast<OpenCloseSequenceData *>(userdata);
Core::instance()->main_window()->open_sequence(d->sequence);
}
void open_close_sequence_free(void *userdata)
{
delete static_cast<OpenCloseSequenceData *>(userdata);
}
} // anonymous namespace
void *make_open_sequence_command(Sequence *sequence)
{
auto *d = new OpenCloseSequenceData;
d->sequence = sequence;
return oakengine_undo_command_create(nullptr, open_sequence_redo,
open_sequence_undo,
open_close_sequence_free, d);
}
void *make_close_sequence_command(Sequence *sequence)
{
auto *d = new OpenCloseSequenceData;
d->sequence = sequence;
return oakengine_undo_command_create(nullptr, close_sequence_redo,
close_sequence_undo,
open_close_sequence_free, d);
}
}
+3 -40
View File
@@ -23,51 +23,14 @@
#define OAK_MAINWINDOWUNDO_H
#include "node/project/sequence/sequence.h"
#include "oakengine/undo.h"
namespace olive
{
class OpenSequenceCommand : public UndoCommand {
public:
OpenSequenceCommand(Sequence *sequence)
: sequence_(sequence)
{
}
void *make_open_sequence_command(Sequence *sequence);
virtual Project *get_relevant_project() const override
{
return nullptr;
}
protected:
virtual void redo() override;
virtual void undo() override;
private:
Sequence *sequence_;
};
class CloseSequenceCommand : public UndoCommand {
public:
CloseSequenceCommand(Sequence *sequence)
: sequence_(sequence)
{
}
virtual Project *get_relevant_project() const override
{
return nullptr;
}
protected:
virtual void redo() override;
virtual void undo() override;
private:
Sequence *sequence_;
};
void *make_close_sequence_command(Sequence *sequence);
}