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:
@@ -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"));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user