various: implemented multiple project support
This required various changes to various parts of the infrastructure (mostly using paths to finding the "root project" of any given object throughout). Now theoretically infinite projects can be opened and accounted for at any given time.
This commit is contained in:
+162
-50
@@ -67,8 +67,7 @@ Core::Core() :
|
||||
main_window_(nullptr),
|
||||
tool_(Tool::kPointer),
|
||||
addable_object_(Tool::kAddableEmpty),
|
||||
snapping_(true),
|
||||
queue_autorecovery_(false)
|
||||
snapping_(true)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -157,7 +156,7 @@ void Core::Start()
|
||||
|
||||
if (startup_project_.isEmpty()) {
|
||||
// If no load project is set, create a new one on open
|
||||
AddOpenProject(std::make_shared<Project>());
|
||||
CreateNewProject();
|
||||
} else {
|
||||
OpenProjectInternal(startup_project_);
|
||||
}
|
||||
@@ -252,6 +251,19 @@ void Core::ClearOpenRecentList()
|
||||
recent_projects_.clear();
|
||||
}
|
||||
|
||||
void Core::CreateNewProject()
|
||||
{
|
||||
// If we already have an empty/new project, switch to it
|
||||
foreach (ProjectPtr already_open, open_projects_) {
|
||||
if (already_open->is_new()) {
|
||||
AddOpenProject(already_open);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
AddOpenProject(std::make_shared<Project>());
|
||||
}
|
||||
|
||||
const bool &Core::snapping() const
|
||||
{
|
||||
return snapping_;
|
||||
@@ -316,7 +328,7 @@ void Core::DialogPreferencesShow()
|
||||
|
||||
void Core::DialogProjectPropertiesShow()
|
||||
{
|
||||
ProjectPropertiesDialog ppd(main_window_);
|
||||
ProjectPropertiesDialog ppd(GetActiveProject(), main_window_);
|
||||
ppd.exec();
|
||||
}
|
||||
|
||||
@@ -406,6 +418,21 @@ void Core::CreateNewSequence()
|
||||
|
||||
void Core::AddOpenProject(ProjectPtr p)
|
||||
{
|
||||
// Ensure project is not open at the moment
|
||||
foreach (ProjectPtr already_open, open_projects_) {
|
||||
if (already_open == p) {
|
||||
// Signal UI to switch to this project
|
||||
emit ProjectOpened(p.get());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If we currently have an empty project, close it first
|
||||
if (!open_projects_.isEmpty() && open_projects_.last()->is_new()) {
|
||||
CloseProject(open_projects_.last().get(), false);
|
||||
}
|
||||
|
||||
connect(p.get(), &Project::ModifiedChanged, this, &Core::ProjectWasModified);
|
||||
open_projects_.append(p);
|
||||
|
||||
PushRecentlyOpenedProject(p->filename());
|
||||
@@ -433,6 +460,27 @@ bool Core::ConfirmImageSequence(const QString& filename)
|
||||
return (mb.exec() == QMessageBox::Yes);
|
||||
}
|
||||
|
||||
void Core::ProjectWasModified(bool e)
|
||||
{
|
||||
//Project* p = static_cast<Project*>(sender());
|
||||
|
||||
if (e) {
|
||||
// If this project is modified, we know for sure the window should show a "modified" flag (the * in the titlebar)
|
||||
main_window_->setWindowModified(true);
|
||||
} else {
|
||||
// If we just set this project to "not modified", see if all projects are not modified in which case we can hide
|
||||
// the modified flag
|
||||
foreach (ProjectPtr open, open_projects_) {
|
||||
if (open->is_modified()) {
|
||||
main_window_->setWindowModified(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
main_window_->setWindowModified(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Core::DeclareTypesForQt()
|
||||
{
|
||||
qRegisterMetaType<NodeDependency>();
|
||||
@@ -490,6 +538,7 @@ void Core::StartGUI(bool full_screen)
|
||||
|
||||
// When a new project is opened, update the mainwindow
|
||||
connect(this, &Core::ProjectOpened, main_window_, &MainWindow::ProjectOpen);
|
||||
connect(this, &Core::ProjectClosed, main_window_, &MainWindow::ProjectClose);
|
||||
|
||||
// Start autorecovery timer using the config value as its interval
|
||||
SetAutorecoveryInterval(Config::Current()["AutorecoveryInterval"].toInt());
|
||||
@@ -501,7 +550,7 @@ void Core::SaveProjectInternal(Project *project)
|
||||
// Create save manager
|
||||
ProjectSaveManager* psm = new ProjectSaveManager(project);
|
||||
|
||||
connect(psm, &Task::Succeeded, this, &Core::ProjectSaveSucceeded);
|
||||
connect(psm, &ProjectSaveManager::ProjectSaveSucceeded, this, &Core::ProjectSaveSucceeded);
|
||||
|
||||
TaskDialog* task_dialog = new TaskDialog(psm, tr("Save Project"), main_window());
|
||||
task_dialog->open();
|
||||
@@ -509,21 +558,22 @@ void Core::SaveProjectInternal(Project *project)
|
||||
|
||||
void Core::SaveAutorecovery()
|
||||
{
|
||||
if (queue_autorecovery_) {
|
||||
// FIXME: Save autorecovery of projects open
|
||||
|
||||
queue_autorecovery_ = false;
|
||||
foreach (ProjectPtr p, open_projects_) {
|
||||
if (!p->has_autorecovery_been_saved()) {
|
||||
// FIXME: SAVE AN AUTORECOVERY PROJECT
|
||||
p->set_autorecovery_saved(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Core::ProjectSaveSucceeded()
|
||||
void Core::ProjectSaveSucceeded(Project* p)
|
||||
{
|
||||
PushRecentlyOpenedProject(GetActiveProject()->filename());
|
||||
PushRecentlyOpenedProject(p->filename());
|
||||
|
||||
SetProjectModified(false);
|
||||
p->set_modified(false);
|
||||
}
|
||||
|
||||
Project *Core::GetActiveProject()
|
||||
Project *Core::GetActiveProject() const
|
||||
{
|
||||
ProjectPanel* active_project_panel = PanelManager::instance()->MostRecentlyFocused<ProjectPanel>();
|
||||
|
||||
@@ -534,7 +584,7 @@ Project *Core::GetActiveProject()
|
||||
}
|
||||
}
|
||||
|
||||
ProjectViewModel *Core::GetActiveProjectModel()
|
||||
ProjectViewModel *Core::GetActiveProjectModel() const
|
||||
{
|
||||
ProjectPanel* active_project_panel = PanelManager::instance()->MostRecentlyFocused<ProjectPanel>();
|
||||
|
||||
@@ -545,7 +595,7 @@ ProjectViewModel *Core::GetActiveProjectModel()
|
||||
}
|
||||
}
|
||||
|
||||
Folder *Core::GetSelectedFolderInActiveProject()
|
||||
Folder *Core::GetSelectedFolderInActiveProject() const
|
||||
{
|
||||
ProjectPanel* active_project_panel = PanelManager::instance()->MostRecentlyFocused<ProjectPanel>();
|
||||
|
||||
@@ -568,17 +618,6 @@ void Core::SetTimecodeDisplay(Timecode::Display d)
|
||||
emit TimecodeDisplayChanged(d);
|
||||
}
|
||||
|
||||
void Core::SetProjectModified(bool e)
|
||||
{
|
||||
main_window()->setWindowModified(e);
|
||||
queue_autorecovery_ = e;
|
||||
}
|
||||
|
||||
bool Core::IsProjectModified() const
|
||||
{
|
||||
return main_window_->isWindowModified();
|
||||
}
|
||||
|
||||
void Core::SetAutorecoveryInterval(int minutes)
|
||||
{
|
||||
// Convert minutes to milliseconds
|
||||
@@ -599,38 +638,19 @@ bool Core::SaveActiveProject()
|
||||
{
|
||||
Project* active_project = GetActiveProject();
|
||||
|
||||
if (!active_project) {
|
||||
return false;
|
||||
if (active_project) {
|
||||
return SaveProject(active_project);
|
||||
}
|
||||
|
||||
if (active_project->filename().isEmpty()) {
|
||||
return SaveActiveProjectAs();
|
||||
} else {
|
||||
SaveProjectInternal(active_project);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Core::SaveActiveProjectAs()
|
||||
{
|
||||
Project* active_project = GetActiveProject();
|
||||
|
||||
if (!active_project) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QString fn = QFileDialog::getSaveFileName(main_window_,
|
||||
tr("Save Project As"),
|
||||
QString(),
|
||||
GetProjectFilter());
|
||||
|
||||
if (!fn.isEmpty()) {
|
||||
active_project->set_filename(fn);
|
||||
|
||||
SaveProjectInternal(active_project);
|
||||
|
||||
return true;
|
||||
if (active_project) {
|
||||
return SaveProjectAs(active_project);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -722,6 +742,35 @@ QString Core::GetRecentProjectsFilePath()
|
||||
return QDir(GetConfigurationLocation()).filePath(QStringLiteral("recent"));
|
||||
}
|
||||
|
||||
bool Core::SaveProject(Project *p)
|
||||
{
|
||||
if (p->filename().isEmpty()) {
|
||||
return SaveProjectAs(p);
|
||||
} else {
|
||||
SaveProjectInternal(p);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Core::SaveProjectAs(Project *p)
|
||||
{
|
||||
QString fn = QFileDialog::getSaveFileName(main_window_,
|
||||
tr("Save Project As"),
|
||||
QString(),
|
||||
GetProjectFilter());
|
||||
|
||||
if (!fn.isEmpty()) {
|
||||
p->set_filename(fn);
|
||||
|
||||
SaveProjectInternal(p);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Core::PushRecentlyOpenedProject(const QString& s)
|
||||
{
|
||||
if (s.isEmpty()) {
|
||||
@@ -739,6 +788,15 @@ void Core::PushRecentlyOpenedProject(const QString& s)
|
||||
|
||||
void Core::OpenProjectInternal(const QString &filename)
|
||||
{
|
||||
// See if this project is open already
|
||||
foreach (ProjectPtr p, open_projects_) {
|
||||
if (p->filename() == filename) {
|
||||
// This project is already open
|
||||
AddOpenProject(p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ProjectLoadManager* plm = new ProjectLoadManager(filename);
|
||||
|
||||
// We use a blocking queued connection here because we want to ensure we have this project instance before the
|
||||
@@ -818,6 +876,60 @@ void Core::OpenProjectFromRecentList(int index)
|
||||
}
|
||||
}
|
||||
|
||||
bool Core::CloseProject(Project *p, bool auto_open_new)
|
||||
{
|
||||
for (int i=0;i<open_projects_.size();i++) {
|
||||
if (open_projects_.at(i).get() == p) {
|
||||
|
||||
if (p->is_modified()) {
|
||||
QMessageBox mb(main_window_);
|
||||
|
||||
mb.setIcon(QMessageBox::Question);
|
||||
mb.setWindowTitle(tr("Unsaved Changes"));
|
||||
mb.setText(tr("The project '%1' has unsaved changes. Would you like to save them?")
|
||||
.arg(p->name()));
|
||||
|
||||
QPushButton* yes_btn = mb.addButton(tr("Save"), QMessageBox::YesRole);
|
||||
mb.addButton(tr("Don't Save"), QMessageBox::NoRole);
|
||||
QPushButton* cancel_btn = mb.addButton(QMessageBox::Cancel);
|
||||
|
||||
mb.exec();
|
||||
|
||||
if (mb.clickedButton() == cancel_btn
|
||||
|| (mb.clickedButton() == yes_btn && !SaveActiveProject())) {
|
||||
// Don't close if the user clicked cancel on this messagebox OR they cancelled a save as operation
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
disconnect(p, &Project::ModifiedChanged, this, &Core::ProjectWasModified);
|
||||
emit ProjectClosed(p);
|
||||
open_projects_.removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure a project is always active
|
||||
if (auto_open_new && open_projects_.isEmpty()) {
|
||||
CreateNewProject();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Core::CloseAllProjects(bool auto_open_new)
|
||||
{
|
||||
QList<ProjectPtr> copy = open_projects_;
|
||||
|
||||
foreach (ProjectPtr p, copy) {
|
||||
if (!CloseProject(p.get(), auto_open_new)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Core::OpenProject()
|
||||
{
|
||||
QString file = QFileDialog::getOpenFileName(main_window_,
|
||||
|
||||
+36
-22
@@ -134,9 +134,9 @@ public:
|
||||
*
|
||||
* The active Project file, or nullptr if the heuristic couldn't find one.
|
||||
*/
|
||||
Project* GetActiveProject();
|
||||
ProjectViewModel* GetActiveProjectModel();
|
||||
Folder* GetSelectedFolderInActiveProject();
|
||||
Project* GetActiveProject() const;
|
||||
ProjectViewModel* GetActiveProjectModel() const;
|
||||
Folder* GetSelectedFolderInActiveProject() const;
|
||||
|
||||
/**
|
||||
* @brief Gets current timecode display mode
|
||||
@@ -148,16 +148,6 @@ public:
|
||||
*/
|
||||
void SetTimecodeDisplay(Timecode::Display d);
|
||||
|
||||
/**
|
||||
* @brief Sets state to "modified" so that the GUI will prompt the user to save before closing
|
||||
*
|
||||
* Call this function whenever a change is made to a currently active project. Saving the project will automatically
|
||||
* unset this.
|
||||
*/
|
||||
void SetProjectModified(bool e);
|
||||
|
||||
bool IsProjectModified() const;
|
||||
|
||||
/**
|
||||
* @brief Set how frequently an autorecovery should be saved (if the project has changed, see SetProjectModified())
|
||||
*/
|
||||
@@ -216,6 +206,16 @@ public:
|
||||
*/
|
||||
void OpenProjectFromRecentList(int index);
|
||||
|
||||
/**
|
||||
* @brief Closes a project
|
||||
*/
|
||||
bool CloseProject(Project* p, bool auto_open_new);
|
||||
|
||||
/**
|
||||
* @brief Closes all open projects
|
||||
*/
|
||||
bool CloseAllProjects(bool auto_open_new);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief Starts an open file dialog to load a project from file
|
||||
@@ -291,6 +291,11 @@ public slots:
|
||||
*/
|
||||
void ClearOpenRecentList();
|
||||
|
||||
/**
|
||||
* @brief Creates a new empty project and opens it
|
||||
*/
|
||||
void CreateNewProject();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief Signal emitted when a project is opened
|
||||
@@ -301,6 +306,11 @@ signals:
|
||||
*/
|
||||
void ProjectOpened(Project* p);
|
||||
|
||||
/**
|
||||
* @brief Signal emitted when a project is closed
|
||||
*/
|
||||
void ProjectClosed(Project* p);
|
||||
|
||||
/**
|
||||
* @brief Signal emitted when the tool is changed from somewhere
|
||||
*/
|
||||
@@ -327,6 +337,16 @@ private:
|
||||
*/
|
||||
static QString GetRecentProjectsFilePath();
|
||||
|
||||
/**
|
||||
* @brief Saves a specific project
|
||||
*/
|
||||
bool SaveProject(Project* p);
|
||||
|
||||
/**
|
||||
* @brief Performs a "save as" on a specific project
|
||||
*/
|
||||
bool SaveProjectAs(Project* p);
|
||||
|
||||
/**
|
||||
* @brief Adds a filename to the top of the recently opened projects list (or moves it if it already exists)
|
||||
*/
|
||||
@@ -391,14 +411,6 @@ private:
|
||||
*/
|
||||
bool snapping_;
|
||||
|
||||
/**
|
||||
* @brief Internal value for whether to make an autorecovery next interval
|
||||
*
|
||||
* True if the project has changed since the last autorecovery and we should save next time. False if the project has
|
||||
* not changed and saving another autorecovery would be a waste.
|
||||
*/
|
||||
bool queue_autorecovery_;
|
||||
|
||||
/**
|
||||
* @brief Internal timer for saving autorecovery files
|
||||
*/
|
||||
@@ -422,7 +434,7 @@ private:
|
||||
private slots:
|
||||
void SaveAutorecovery();
|
||||
|
||||
void ProjectSaveSucceeded();
|
||||
void ProjectSaveSucceeded(Project *p);
|
||||
|
||||
/**
|
||||
* @brief Adds a project to the "open projects" list
|
||||
@@ -433,6 +445,8 @@ private slots:
|
||||
|
||||
bool ConfirmImageSequence(const QString &filename);
|
||||
|
||||
void ProjectWasModified(bool e);
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -143,6 +143,11 @@ FootagePropertiesDialog::FootageChangeCommand::FootageChangeCommand(Footage *foo
|
||||
{
|
||||
}
|
||||
|
||||
Project *FootagePropertiesDialog::FootageChangeCommand::GetRelevantProject() const
|
||||
{
|
||||
return footage_->project();
|
||||
}
|
||||
|
||||
void FootagePropertiesDialog::FootageChangeCommand::redo_internal()
|
||||
{
|
||||
old_name_ = footage_->name();
|
||||
@@ -163,6 +168,11 @@ FootagePropertiesDialog::StreamEnableChangeCommand::StreamEnableChangeCommand(St
|
||||
{
|
||||
}
|
||||
|
||||
Project *FootagePropertiesDialog::StreamEnableChangeCommand::GetRelevantProject() const
|
||||
{
|
||||
return stream_->footage()->project();
|
||||
}
|
||||
|
||||
void FootagePropertiesDialog::StreamEnableChangeCommand::redo_internal()
|
||||
{
|
||||
stream_->set_enabled(new_enabled_);
|
||||
|
||||
@@ -62,6 +62,8 @@ private:
|
||||
const QString& name,
|
||||
QUndoCommand *command = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -79,6 +81,8 @@ private:
|
||||
bool enabled,
|
||||
QUndoCommand* command = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
@@ -158,6 +158,11 @@ VideoStreamProperties::VideoStreamChangeCommand::VideoStreamChangeCommand(ImageS
|
||||
{
|
||||
}
|
||||
|
||||
Project *VideoStreamProperties::VideoStreamChangeCommand::GetRelevantProject() const
|
||||
{
|
||||
return stream_->footage()->project();
|
||||
}
|
||||
|
||||
void VideoStreamProperties::VideoStreamChangeCommand::redo_internal()
|
||||
{
|
||||
old_premultiplied_ = stream_->premultiplied_alpha();
|
||||
@@ -181,6 +186,11 @@ VideoStreamProperties::ImageSequenceChangeCommand::ImageSequenceChangeCommand(Vi
|
||||
{
|
||||
}
|
||||
|
||||
Project *VideoStreamProperties::ImageSequenceChangeCommand::GetRelevantProject() const
|
||||
{
|
||||
return video_stream_->footage()->project();
|
||||
}
|
||||
|
||||
void VideoStreamProperties::ImageSequenceChangeCommand::redo_internal()
|
||||
{
|
||||
old_start_index_ = video_stream_->start_time();
|
||||
|
||||
@@ -75,6 +75,8 @@ private:
|
||||
QString colorspace,
|
||||
QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -97,6 +99,8 @@ private:
|
||||
int64_t duration,
|
||||
QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
@@ -36,9 +36,9 @@ namespace OCIO = OCIO_NAMESPACE::v1;
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
ProjectPropertiesDialog::ProjectPropertiesDialog(QWidget *parent) :
|
||||
ProjectPropertiesDialog::ProjectPropertiesDialog(Project* p, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
working_project_(Core::instance()->GetActiveProject())
|
||||
working_project_(p)
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ class ProjectPropertiesDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ProjectPropertiesDialog(QWidget* parent);
|
||||
ProjectPropertiesDialog(Project *p, QWidget* parent);
|
||||
|
||||
public slots:
|
||||
virtual void accept() override;
|
||||
|
||||
@@ -211,6 +211,11 @@ SequenceDialog::SequenceParamCommand::SequenceParamCommand(Sequence* s,
|
||||
{
|
||||
}
|
||||
|
||||
Project *SequenceDialog::SequenceParamCommand::GetRelevantProject() const
|
||||
{
|
||||
return sequence_->project();
|
||||
}
|
||||
|
||||
void SequenceDialog::SequenceParamCommand::redo_internal()
|
||||
{
|
||||
sequence_->set_video_params(new_video_params_);
|
||||
|
||||
@@ -122,6 +122,8 @@ private:
|
||||
const QString& name,
|
||||
QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
@@ -360,6 +360,11 @@ BlockReverseCommand::BlockReverseCommand(Block *block, QUndoCommand *parent) :
|
||||
{
|
||||
}
|
||||
|
||||
Project *BlockReverseCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(block_->parent())->project();
|
||||
}
|
||||
|
||||
void BlockReverseCommand::redo_internal()
|
||||
{
|
||||
block_->set_media_in(block_->media_out());
|
||||
|
||||
@@ -70,6 +70,8 @@ class BlockReverseCommand : public UndoCommand {
|
||||
public:
|
||||
BlockReverseCommand(Block* block, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
@@ -50,6 +50,8 @@ public:
|
||||
|
||||
int TrackCount() const;
|
||||
|
||||
NodeGraph* GetParentGraph() const;
|
||||
|
||||
signals:
|
||||
void BlockAdded(Block* block, int index);
|
||||
|
||||
@@ -66,8 +68,6 @@ signals:
|
||||
void TrackHeightChanged(int index, int height);
|
||||
|
||||
private:
|
||||
NodeGraph* GetParentGraph() const;
|
||||
|
||||
/**
|
||||
* @brief A cache of connected Tracks
|
||||
*/
|
||||
|
||||
@@ -82,6 +82,7 @@ void ProjectPanel::set_project(Project *p)
|
||||
if (project()) {
|
||||
disconnect(project(), &Project::NameChanged, this, &ProjectPanel::UpdateSubtitle);
|
||||
disconnect(project(), &Project::NameChanged, this, &ProjectPanel::ProjectNameChanged);
|
||||
disconnect(project(), &Project::ModifiedChanged, this, &ProjectPanel::setWindowModified);
|
||||
}
|
||||
|
||||
explorer_->set_project(p);
|
||||
@@ -89,9 +90,16 @@ void ProjectPanel::set_project(Project *p)
|
||||
if (project()) {
|
||||
connect(project(), &Project::NameChanged, this, &ProjectPanel::UpdateSubtitle);
|
||||
connect(project(), &Project::NameChanged, this, &ProjectPanel::ProjectNameChanged);
|
||||
connect(project(), &Project::ModifiedChanged, this, &ProjectPanel::setWindowModified);
|
||||
}
|
||||
|
||||
UpdateSubtitle();
|
||||
|
||||
if (p) {
|
||||
setWindowModified(p->is_modified());
|
||||
} else {
|
||||
setWindowModified(false);
|
||||
}
|
||||
}
|
||||
|
||||
QList<Item *> ProjectPanel::SelectedItems()
|
||||
@@ -182,7 +190,7 @@ void ProjectPanel::UpdateSubtitle()
|
||||
if (project() == nullptr) {
|
||||
SetSubtitle(tr("(none)"));
|
||||
} else {
|
||||
SetSubtitle(project()->name());
|
||||
SetSubtitle(QStringLiteral("[*]%1").arg(project()->name()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,7 @@
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
TimelinePanel::TimelinePanel(QWidget *parent) :
|
||||
TimeBasedPanel(parent),
|
||||
signal_instead_of_close_(false)
|
||||
TimeBasedPanel(parent)
|
||||
{
|
||||
// FIXME: This won't work if there's ever more than one of this panel
|
||||
setObjectName("TimelinePanel");
|
||||
@@ -168,11 +167,6 @@ void TimelinePanel::OverwriteFootageAtPlayhead(const QList<Footage *> &footage)
|
||||
static_cast<TimelineWidget*>(GetTimeBasedWidget())->OverwriteFootageAtPlayhead(footage);
|
||||
}
|
||||
|
||||
void TimelinePanel::SetSignalInsteadOfClose(bool e)
|
||||
{
|
||||
signal_instead_of_close_ = e;
|
||||
}
|
||||
|
||||
void TimelinePanel::Retranslate()
|
||||
{
|
||||
TimeBasedPanel::Retranslate();
|
||||
@@ -180,14 +174,4 @@ void TimelinePanel::Retranslate()
|
||||
SetTitle(tr("Timeline"));
|
||||
}
|
||||
|
||||
void TimelinePanel::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
if (signal_instead_of_close_) {
|
||||
event->ignore();
|
||||
emit CloseRequested();
|
||||
} else {
|
||||
PanelWidget::closeEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -83,21 +83,12 @@ public:
|
||||
|
||||
void OverwriteFootageAtPlayhead(const QList<Footage *> &footage);
|
||||
|
||||
void SetSignalInsteadOfClose(bool e);
|
||||
|
||||
protected:
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual void closeEvent(QCloseEvent* event) override;
|
||||
|
||||
signals:
|
||||
void SelectionChanged(const QList<Node*>& selected_blocks);
|
||||
|
||||
void CloseRequested();
|
||||
|
||||
private:
|
||||
bool signal_instead_of_close_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -132,7 +132,7 @@ const Item *Item::root() const
|
||||
{
|
||||
const Item* item = this;
|
||||
|
||||
while (item->parent() != nullptr) {
|
||||
while (item->parent()) {
|
||||
item = item->parent();
|
||||
}
|
||||
|
||||
|
||||
+31
-1
@@ -30,7 +30,9 @@
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
Project::Project()
|
||||
Project::Project() :
|
||||
is_modified_(false),
|
||||
autorecovery_saved_(true)
|
||||
{
|
||||
root_.set_project(this);
|
||||
}
|
||||
@@ -156,4 +158,32 @@ QList<ItemPtr> Project::get_items_of_type(Item::Type type) const
|
||||
return root_.get_children_of_type(type, true);
|
||||
}
|
||||
|
||||
bool Project::is_modified() const
|
||||
{
|
||||
return is_modified_;
|
||||
}
|
||||
|
||||
void Project::set_modified(bool e)
|
||||
{
|
||||
is_modified_ = e;
|
||||
autorecovery_saved_ = !e;
|
||||
|
||||
emit ModifiedChanged(is_modified_);
|
||||
}
|
||||
|
||||
bool Project::has_autorecovery_been_saved() const
|
||||
{
|
||||
return autorecovery_saved_;
|
||||
}
|
||||
|
||||
void Project::set_autorecovery_saved(bool e)
|
||||
{
|
||||
autorecovery_saved_ = e;
|
||||
}
|
||||
|
||||
bool Project::is_new() const
|
||||
{
|
||||
return !is_modified_ && filename_.isEmpty();
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -68,9 +68,19 @@ public:
|
||||
|
||||
QList<ItemPtr> get_items_of_type(Item::Type type) const;
|
||||
|
||||
bool is_modified() const;
|
||||
void set_modified(bool e);
|
||||
|
||||
bool has_autorecovery_been_saved() const;
|
||||
void set_autorecovery_saved(bool e);
|
||||
|
||||
bool is_new() const;
|
||||
|
||||
signals:
|
||||
void NameChanged();
|
||||
|
||||
void ModifiedChanged(bool e);
|
||||
|
||||
private:
|
||||
Folder root_;
|
||||
|
||||
@@ -80,6 +90,10 @@ private:
|
||||
|
||||
ColorManager color_manager_;
|
||||
|
||||
bool is_modified_;
|
||||
|
||||
bool autorecovery_saved_;
|
||||
|
||||
};
|
||||
|
||||
using ProjectPtr = std::shared_ptr<Project>;
|
||||
|
||||
@@ -55,6 +55,7 @@ void ProjectSaveManager::Action()
|
||||
}
|
||||
|
||||
emit Succeeded();
|
||||
emit ProjectSaveSucceeded(project_);
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -32,6 +32,9 @@ class ProjectSaveManager : public Task
|
||||
public:
|
||||
ProjectSaveManager(Project* project);
|
||||
|
||||
signals:
|
||||
void ProjectSaveSucceeded(Project* p);
|
||||
|
||||
protected:
|
||||
virtual void Action() override;
|
||||
|
||||
|
||||
@@ -511,6 +511,11 @@ ProjectViewModel::MoveItemCommand::MoveItemCommand(ProjectViewModel *model,
|
||||
setText(tr("Move Item"));
|
||||
}
|
||||
|
||||
Project *ProjectViewModel::MoveItemCommand::GetRelevantProject() const
|
||||
{
|
||||
return model_->project();
|
||||
}
|
||||
|
||||
void ProjectViewModel::MoveItemCommand::redo_internal()
|
||||
{
|
||||
model_->MoveItemInternal(item_, destination_);
|
||||
@@ -532,6 +537,11 @@ ProjectViewModel::RenameItemCommand::RenameItemCommand(ProjectViewModel* model,
|
||||
setText(tr("Rename Item"));
|
||||
}
|
||||
|
||||
Project *ProjectViewModel::RenameItemCommand::GetRelevantProject() const
|
||||
{
|
||||
return model_->project();
|
||||
}
|
||||
|
||||
void ProjectViewModel::RenameItemCommand::redo_internal()
|
||||
{
|
||||
model_->RenameChild(item_, new_name_);
|
||||
@@ -551,6 +561,11 @@ ProjectViewModel::AddItemCommand::AddItemCommand(ProjectViewModel* model, Item*
|
||||
{
|
||||
}
|
||||
|
||||
Project *ProjectViewModel::AddItemCommand::GetRelevantProject() const
|
||||
{
|
||||
return model_->project();
|
||||
}
|
||||
|
||||
void ProjectViewModel::AddItemCommand::redo_internal()
|
||||
{
|
||||
model_->AddChild(parent_, child_);
|
||||
@@ -572,6 +587,11 @@ ProjectViewModel::RemoveItemCommand::RemoveItemCommand(ProjectViewModel *model,
|
||||
{
|
||||
}
|
||||
|
||||
Project *ProjectViewModel::RemoveItemCommand::GetRelevantProject() const
|
||||
{
|
||||
return model_->project();
|
||||
}
|
||||
|
||||
void ProjectViewModel::RemoveItemCommand::redo_internal()
|
||||
{
|
||||
parent_ = item_->parent();
|
||||
|
||||
@@ -114,6 +114,8 @@ public:
|
||||
public:
|
||||
MoveItemCommand(ProjectViewModel* model, Item* item, Folder* destination, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
|
||||
@@ -134,6 +136,8 @@ public:
|
||||
public:
|
||||
RenameItemCommand(ProjectViewModel* model, Item* item, const QString& name, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
|
||||
@@ -153,6 +157,8 @@ public:
|
||||
public:
|
||||
AddItemCommand(ProjectViewModel* model, Item* folder, ItemPtr child, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
|
||||
@@ -172,6 +178,8 @@ public:
|
||||
public:
|
||||
RemoveItemCommand(ProjectViewModel* model, ItemPtr item, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
|
||||
|
||||
@@ -42,14 +42,14 @@ QList<StyleDescriptor> StyleManager::ListInternal()
|
||||
return style_list;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
void StyleManager::UseNativeWindowsStyling(QWidget *widget)
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
QStyle* s = QStyleFactory::create(QStringLiteral("windowsvista"));
|
||||
widget->setStyle(s);
|
||||
widget->setPalette(s->standardPalette());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
QPalette StyleManager::ParsePalette(const QString& ini_path)
|
||||
{
|
||||
|
||||
@@ -52,7 +52,9 @@ public:
|
||||
|
||||
static QList<StyleDescriptor> ListInternal();
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
static void UseNativeWindowsStyling(QWidget* widget);
|
||||
#endif
|
||||
|
||||
private:
|
||||
static QPalette ParsePalette(const QString& ini_path);
|
||||
|
||||
@@ -33,15 +33,15 @@ void UndoCommand::redo()
|
||||
{
|
||||
redo_internal();
|
||||
|
||||
modified_ = Core::instance()->IsProjectModified();
|
||||
Core::instance()->SetProjectModified(true);
|
||||
modified_ = GetRelevantProject()->is_modified();
|
||||
GetRelevantProject()->set_modified(true);
|
||||
}
|
||||
|
||||
void UndoCommand::undo()
|
||||
{
|
||||
undo_internal();
|
||||
|
||||
Core::instance()->SetProjectModified(modified_);
|
||||
GetRelevantProject()->set_modified(modified_);
|
||||
}
|
||||
|
||||
void UndoCommand::redo_internal()
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <QUndoCommand>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "project/project.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
@@ -35,6 +36,8 @@ public:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
virtual Project* GetRelevantProject() const = 0;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal();
|
||||
virtual void undo_internal();
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
|
||||
#include "keyframeviewundo.h"
|
||||
|
||||
#include "node/input.h"
|
||||
#include "node/node.h"
|
||||
#include "project/item/sequence/sequence.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
KeyframeSetTypeCommand::KeyframeSetTypeCommand(NodeKeyframePtr key, NodeKeyframe::Type type, QUndoCommand *parent) :
|
||||
@@ -30,6 +34,11 @@ KeyframeSetTypeCommand::KeyframeSetTypeCommand(NodeKeyframePtr key, NodeKeyframe
|
||||
{
|
||||
}
|
||||
|
||||
Project *KeyframeSetTypeCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(key_->parent()->parentNode()->parent())->project();
|
||||
}
|
||||
|
||||
void KeyframeSetTypeCommand::redo_internal()
|
||||
{
|
||||
key_->set_type(new_type_);
|
||||
@@ -58,6 +67,11 @@ KeyframeSetBezierControlPoint::KeyframeSetBezierControlPoint(NodeKeyframePtr key
|
||||
{
|
||||
}
|
||||
|
||||
Project *KeyframeSetBezierControlPoint::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(key_->parent()->parentNode()->parent())->project();
|
||||
}
|
||||
|
||||
void KeyframeSetBezierControlPoint::redo_internal()
|
||||
{
|
||||
key_->set_bezier_control(mode_, new_point_);
|
||||
|
||||
@@ -30,6 +30,8 @@ class KeyframeSetTypeCommand : public UndoCommand {
|
||||
public:
|
||||
KeyframeSetTypeCommand(NodeKeyframePtr key, NodeKeyframe::Type type, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -48,6 +50,8 @@ public:
|
||||
KeyframeSetBezierControlPoint(NodeKeyframePtr key, NodeKeyframe::BezierType mode, const QPointF& point, QUndoCommand* parent = nullptr);
|
||||
KeyframeSetBezierControlPoint(NodeKeyframePtr key, NodeKeyframe::BezierType mode, const QPointF& new_point, const QPointF& old_point, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
@@ -41,13 +41,13 @@ Menu::Menu(Menu *menu)
|
||||
Menu::Menu(QWidget *parent) :
|
||||
QMenu(parent)
|
||||
{
|
||||
StyleManager::UseNativeWindowsStyling(this);
|
||||
Init();
|
||||
}
|
||||
|
||||
Menu::Menu(const QString &s, QWidget *parent) :
|
||||
QMenu(s, parent)
|
||||
{
|
||||
StyleManager::UseNativeWindowsStyling(this);
|
||||
Init();
|
||||
}
|
||||
|
||||
QAction* Menu::InsertAlphabetically(const QString &s)
|
||||
@@ -101,7 +101,9 @@ void Menu::SetBooleanAction(QAction *a, bool* boolean)
|
||||
|
||||
void Menu::Init()
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
StyleManager::UseNativeWindowsStyling(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -31,7 +31,7 @@ MenuShared* MenuShared::instance_ = nullptr;
|
||||
MenuShared::MenuShared()
|
||||
{
|
||||
// "New" menu shared items
|
||||
new_project_item_ = Menu::CreateItem(this, "newproj", this, &MenuShared::NewProjectTriggered, "Ctrl+N");
|
||||
new_project_item_ = Menu::CreateItem(this, "newproj", Core::instance(), &Core::CreateNewProject, "Ctrl+N");
|
||||
new_sequence_item_ = Menu::CreateItem(this, "newseq", Core::instance(), &Core::CreateNewSequence, "Ctrl+Shift+N");
|
||||
new_folder_item_ = Menu::CreateItem(this, "newfolder", Core::instance(), &Core::CreateNewFolder);
|
||||
|
||||
@@ -114,11 +114,6 @@ MenuShared *MenuShared::instance()
|
||||
return instance_;
|
||||
}
|
||||
|
||||
void MenuShared::NewProjectTriggered()
|
||||
{
|
||||
qDebug() << "FIXME: Stub";
|
||||
}
|
||||
|
||||
void MenuShared::SplitAtPlayheadTriggered()
|
||||
{
|
||||
TimelinePanel* timeline = PanelManager::instance()->MostRecentlyFocused<TimelinePanel>();
|
||||
|
||||
@@ -77,8 +77,6 @@ private:
|
||||
static MenuShared* instance_;
|
||||
|
||||
private slots:
|
||||
void NewProjectTriggered();
|
||||
|
||||
void SplitAtPlayheadTriggered();
|
||||
|
||||
void DeleteSelectedTriggered();
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
|
||||
#include "nodeparamviewundo.h"
|
||||
|
||||
#include "node/node.h"
|
||||
#include "project/item/sequence/sequence.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
NodeParamSetKeyframingCommand::NodeParamSetKeyframingCommand(NodeInput *input, bool setting, QUndoCommand *parent) :
|
||||
@@ -30,6 +33,11 @@ NodeParamSetKeyframingCommand::NodeParamSetKeyframingCommand(NodeInput *input, b
|
||||
Q_ASSERT(setting != input_->is_keyframing());
|
||||
}
|
||||
|
||||
Project *NodeParamSetKeyframingCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(input_->parentNode()->parent())->project();
|
||||
}
|
||||
|
||||
void NodeParamSetKeyframingCommand::redo_internal()
|
||||
{
|
||||
input_->set_is_keyframing(setting_);
|
||||
@@ -57,6 +65,11 @@ NodeParamSetKeyframeValueCommand::NodeParamSetKeyframeValueCommand(NodeKeyframeP
|
||||
|
||||
}
|
||||
|
||||
Project *NodeParamSetKeyframeValueCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(key_->parent()->parentNode()->parent())->project();
|
||||
}
|
||||
|
||||
void NodeParamSetKeyframeValueCommand::redo_internal()
|
||||
{
|
||||
key_->set_value(new_value_);
|
||||
@@ -83,6 +96,11 @@ NodeParamInsertKeyframeCommand::NodeParamInsertKeyframeCommand(NodeInput *input,
|
||||
{
|
||||
}
|
||||
|
||||
Project *NodeParamInsertKeyframeCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(input_->parentNode()->parent())->project();
|
||||
}
|
||||
|
||||
void NodeParamInsertKeyframeCommand::redo_internal()
|
||||
{
|
||||
if (!done_) {
|
||||
@@ -103,6 +121,11 @@ NodeParamRemoveKeyframeCommand::NodeParamRemoveKeyframeCommand(NodeInput *input,
|
||||
{
|
||||
}
|
||||
|
||||
Project *NodeParamRemoveKeyframeCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(input_->parentNode()->parent())->project();
|
||||
}
|
||||
|
||||
void NodeParamRemoveKeyframeCommand::redo_internal()
|
||||
{
|
||||
input_->remove_keyframe(keyframe_);
|
||||
@@ -129,6 +152,11 @@ NodeParamSetKeyframeTimeCommand::NodeParamSetKeyframeTimeCommand(NodeKeyframePtr
|
||||
{
|
||||
}
|
||||
|
||||
Project *NodeParamSetKeyframeTimeCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(key_->parent()->parentNode()->parent())->project();
|
||||
}
|
||||
|
||||
void NodeParamSetKeyframeTimeCommand::redo_internal()
|
||||
{
|
||||
key_->set_time(new_time_);
|
||||
@@ -157,6 +185,11 @@ NodeParamSetStandardValueCommand::NodeParamSetStandardValueCommand(NodeInput *in
|
||||
{
|
||||
}
|
||||
|
||||
Project *NodeParamSetStandardValueCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(input_->parentNode()->parent())->project();
|
||||
}
|
||||
|
||||
void NodeParamSetStandardValueCommand::redo_internal()
|
||||
{
|
||||
input_->set_standard_value(new_value_, track_);
|
||||
|
||||
@@ -30,6 +30,8 @@ class NodeParamSetKeyframingCommand : public UndoCommand {
|
||||
public:
|
||||
NodeParamSetKeyframingCommand(NodeInput* input, bool setting, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -44,6 +46,8 @@ public:
|
||||
NodeParamInsertKeyframeCommand(NodeInput* input, NodeKeyframePtr keyframe, QUndoCommand *parent = nullptr);
|
||||
NodeParamInsertKeyframeCommand(NodeInput* input, NodeKeyframePtr keyframe, bool already_done, QUndoCommand *parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -61,6 +65,8 @@ class NodeParamRemoveKeyframeCommand : public UndoCommand {
|
||||
public:
|
||||
NodeParamRemoveKeyframeCommand(NodeInput* input, NodeKeyframePtr keyframe, QUndoCommand *parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -77,6 +83,8 @@ public:
|
||||
NodeParamSetKeyframeTimeCommand(NodeKeyframePtr key, const rational& time, QUndoCommand* parent = nullptr);
|
||||
NodeParamSetKeyframeTimeCommand(NodeKeyframePtr key, const rational& new_time, const rational& old_time, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -94,6 +102,8 @@ public:
|
||||
NodeParamSetKeyframeValueCommand(NodeKeyframePtr key, const QVariant& value, QUndoCommand* parent = nullptr);
|
||||
NodeParamSetKeyframeValueCommand(NodeKeyframePtr key, const QVariant& new_value, const QVariant& old_value, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -111,6 +121,8 @@ public:
|
||||
NodeParamSetStandardValueCommand(NodeInput* input, int track, const QVariant& value, QUndoCommand* parent = nullptr);
|
||||
NodeParamSetStandardValueCommand(NodeInput* input, int track, const QVariant& new_value, const QVariant& old_value, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
#include "nodeviewundo.h"
|
||||
|
||||
#include "project/item/sequence/sequence.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
NodeEdgeAddCommand::NodeEdgeAddCommand(NodeOutput *output, NodeInput *input, QUndoCommand *parent) :
|
||||
@@ -59,6 +61,11 @@ void NodeEdgeAddCommand::undo_internal()
|
||||
done_ = false;
|
||||
}
|
||||
|
||||
Project *NodeEdgeAddCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(output_->parentNode()->parent())->project();
|
||||
}
|
||||
|
||||
NodeEdgeRemoveCommand::NodeEdgeRemoveCommand(NodeOutput *output, NodeInput *input, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
output_(output),
|
||||
@@ -95,6 +102,11 @@ void NodeEdgeRemoveCommand::undo_internal()
|
||||
done_ = false;
|
||||
}
|
||||
|
||||
Project *NodeEdgeRemoveCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(output_->parentNode()->parent())->project();
|
||||
}
|
||||
|
||||
NodeAddCommand::NodeAddCommand(NodeGraph *graph, Node *node, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
graph_(graph),
|
||||
@@ -114,6 +126,11 @@ void NodeAddCommand::undo_internal()
|
||||
graph_->TakeNode(node_, &memory_manager_);
|
||||
}
|
||||
|
||||
Project *NodeAddCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(graph_)->project();
|
||||
}
|
||||
|
||||
NodeRemoveCommand::NodeRemoveCommand(NodeGraph *graph, const QList<Node *> &nodes, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
graph_(graph),
|
||||
@@ -156,6 +173,11 @@ void NodeRemoveCommand::undo_internal()
|
||||
edges_.clear();
|
||||
}
|
||||
|
||||
Project *NodeRemoveCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(graph_)->project();
|
||||
}
|
||||
|
||||
NodeRemoveWithExclusiveDeps::NodeRemoveWithExclusiveDeps(NodeGraph *graph, Node *node, QUndoCommand *parent) :
|
||||
UndoCommand(parent)
|
||||
{
|
||||
@@ -166,8 +188,13 @@ NodeRemoveWithExclusiveDeps::NodeRemoveWithExclusiveDeps(NodeGraph *graph, Node
|
||||
remove_command_ = new NodeRemoveCommand(graph, node_and_its_deps, this);
|
||||
}
|
||||
|
||||
Project *NodeRemoveWithExclusiveDeps::GetRelevantProject() const
|
||||
{
|
||||
return remove_command_->GetRelevantProject();
|
||||
}
|
||||
|
||||
NodeCopyInputsCommand::NodeCopyInputsCommand(Node *src, Node *dest, bool include_connections, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
QUndoCommand(parent),
|
||||
src_(src),
|
||||
dest_(dest),
|
||||
include_connections_(include_connections)
|
||||
@@ -175,14 +202,14 @@ NodeCopyInputsCommand::NodeCopyInputsCommand(Node *src, Node *dest, bool include
|
||||
}
|
||||
|
||||
NodeCopyInputsCommand::NodeCopyInputsCommand(Node *src, Node *dest, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
QUndoCommand(parent),
|
||||
src_(src),
|
||||
dest_(dest),
|
||||
include_connections_(true)
|
||||
{
|
||||
}
|
||||
|
||||
void NodeCopyInputsCommand::redo_internal()
|
||||
void NodeCopyInputsCommand::redo()
|
||||
{
|
||||
Node::CopyInputs(src_, dest_, include_connections_);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ class NodeEdgeAddCommand : public UndoCommand {
|
||||
public:
|
||||
NodeEdgeAddCommand(NodeOutput* output, NodeInput* input, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -62,6 +64,8 @@ public:
|
||||
NodeEdgeRemoveCommand(NodeOutput* output, NodeInput* input, QUndoCommand* parent = nullptr);
|
||||
NodeEdgeRemoveCommand(NodeEdgePtr edge, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -77,6 +81,8 @@ class NodeAddCommand : public UndoCommand {
|
||||
public:
|
||||
NodeAddCommand(NodeGraph* graph, Node* node, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -94,6 +100,8 @@ public:
|
||||
const QList<Node*>& nodes,
|
||||
QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -112,11 +120,13 @@ public:
|
||||
Node* node,
|
||||
QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
private:
|
||||
NodeRemoveCommand* remove_command_;
|
||||
};
|
||||
|
||||
class NodeCopyInputsCommand : public UndoCommand {
|
||||
class NodeCopyInputsCommand : public QUndoCommand {
|
||||
public:
|
||||
NodeCopyInputsCommand(Node* src,
|
||||
Node* dest,
|
||||
@@ -128,7 +138,7 @@ public:
|
||||
QUndoCommand* parent = nullptr);
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void redo() override;
|
||||
|
||||
private:
|
||||
Node* src_;
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
#include "panel.h"
|
||||
|
||||
#include <QCloseEvent>
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QStyle>
|
||||
#include <QStyleOption>
|
||||
@@ -29,9 +31,12 @@ OLIVE_NAMESPACE_ENTER
|
||||
|
||||
PanelWidget::PanelWidget(QWidget *parent) :
|
||||
QDockWidget(parent),
|
||||
border_visible_(false)
|
||||
border_visible_(false),
|
||||
signal_instead_of_close_(false)
|
||||
{
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
|
||||
connect(this, &PanelWidget::visibilityChanged, this, &PanelWidget::PanelVisibilityChanged);
|
||||
}
|
||||
|
||||
void PanelWidget::SetMovementLocked(bool locked)
|
||||
@@ -104,6 +109,28 @@ void PanelWidget::UpdateTitle()
|
||||
}
|
||||
}
|
||||
|
||||
void PanelWidget::PanelVisibilityChanged(bool e)
|
||||
{
|
||||
if (e) {
|
||||
setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
void PanelWidget::SetSignalInsteadOfClose(bool e)
|
||||
{
|
||||
signal_instead_of_close_ = e;
|
||||
}
|
||||
|
||||
void PanelWidget::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
if (signal_instead_of_close_) {
|
||||
event->ignore();
|
||||
emit CloseRequested();
|
||||
} else {
|
||||
QDockWidget::closeEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void PanelWidget::changeEvent(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
|
||||
@@ -56,6 +56,13 @@ public:
|
||||
*/
|
||||
void SetBorderVisible(bool enabled);
|
||||
|
||||
/**
|
||||
* @brief If enabled, sends signal CloseRequested() when the user closes instead of closing
|
||||
*
|
||||
* Defaults to FALSE. Use this to override default panel closing functionality.
|
||||
*/
|
||||
void SetSignalInsteadOfClose(bool e);
|
||||
|
||||
/**
|
||||
* @brief Called whenever this panel is focused and user uses "Zoom In" (either in menus or as a keyboard shortcut)
|
||||
*
|
||||
@@ -156,6 +163,9 @@ public:
|
||||
|
||||
virtual void ToggleSelectedEnabled(){}
|
||||
|
||||
signals:
|
||||
void CloseRequested();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief paintEvent
|
||||
@@ -165,6 +175,8 @@ protected:
|
||||
|
||||
virtual void changeEvent(QEvent* e) override;
|
||||
|
||||
virtual void closeEvent(QCloseEvent* event) override;
|
||||
|
||||
virtual void Retranslate();
|
||||
|
||||
protected slots:
|
||||
@@ -204,20 +216,17 @@ private:
|
||||
*/
|
||||
void UpdateTitle();
|
||||
|
||||
/**
|
||||
* @brief Internal title string
|
||||
*/
|
||||
QString title_;
|
||||
|
||||
/**
|
||||
* @brief Internal subtitle string
|
||||
*/
|
||||
QString subtitle_;
|
||||
|
||||
/**
|
||||
* @brief Internal border visibility value
|
||||
*/
|
||||
bool border_visible_;
|
||||
|
||||
bool signal_instead_of_close_;
|
||||
|
||||
private slots:
|
||||
void PanelVisibilityChanged(bool e);
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -189,6 +189,11 @@ TimelinePoints *TimeBasedWidget::ConnectTimelinePoints()
|
||||
return static_cast<Sequence*>(viewer_node_->parent());
|
||||
}
|
||||
|
||||
Project *TimeBasedWidget::GetTimelinePointsProject()
|
||||
{
|
||||
return static_cast<Sequence*>(viewer_node_->parent())->project();
|
||||
}
|
||||
|
||||
TimelinePoints *TimeBasedWidget::GetConnectedTimelinePoints() const
|
||||
{
|
||||
return points_;
|
||||
@@ -339,7 +344,7 @@ void TimeBasedWidget::SetPoint(Timeline::MovementMode m, const rational& time)
|
||||
|
||||
// Enable workarea if it isn't already enabled
|
||||
if (!points_->workarea()->enabled()) {
|
||||
new WorkareaSetEnabledCommand(points_, true, command);
|
||||
new WorkareaSetEnabledCommand(GetTimelinePointsProject(), points_, true, command);
|
||||
}
|
||||
|
||||
// Determine our new range
|
||||
@@ -364,7 +369,7 @@ void TimeBasedWidget::SetPoint(Timeline::MovementMode m, const rational& time)
|
||||
}
|
||||
|
||||
// Set workarea
|
||||
new WorkareaSetRangeCommand(points_, TimeRange(in_point, out_point), command);
|
||||
new WorkareaSetRangeCommand(GetTimelinePointsProject(), points_, TimeRange(in_point, out_point), command);
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
@@ -383,7 +388,7 @@ void TimeBasedWidget::ResetPoint(Timeline::MovementMode m)
|
||||
r.set_out(TimelineWorkArea::kResetOut);
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(new WorkareaSetRangeCommand(points_, r));
|
||||
Core::instance()->undo_stack()->push(new WorkareaSetRangeCommand(GetTimelinePointsProject(), points_, r));
|
||||
}
|
||||
|
||||
void TimeBasedWidget::SetInAtPlayhead()
|
||||
@@ -413,7 +418,7 @@ void TimeBasedWidget::ClearInOutPoints()
|
||||
}
|
||||
|
||||
|
||||
Core::instance()->undo_stack()->push(new WorkareaSetEnabledCommand(points_, false));
|
||||
Core::instance()->undo_stack()->push(new WorkareaSetEnabledCommand(GetTimelinePointsProject(), points_, false));
|
||||
}
|
||||
|
||||
void TimeBasedWidget::SetMarker()
|
||||
|
||||
@@ -116,6 +116,8 @@ protected:
|
||||
|
||||
virtual TimelinePoints* ConnectTimelinePoints();
|
||||
|
||||
virtual Project* GetTimelinePointsProject();
|
||||
|
||||
TimelinePoints* GetConnectedTimelinePoints() const;
|
||||
|
||||
void ConnectTimelineView(TimelineViewBase* base);
|
||||
|
||||
@@ -156,16 +156,13 @@ TimelineWidget::~TimelineWidget()
|
||||
|
||||
void TimelineWidget::Clear()
|
||||
{
|
||||
SetTimebase(0);
|
||||
|
||||
QMap<Block*, TimelineViewBlockItem*>::iterator iterator = block_items_.begin();
|
||||
|
||||
while (iterator != block_items_.end()) {
|
||||
QMap<Block*, TimelineViewBlockItem*>::const_iterator iterator;
|
||||
for (iterator=block_items_.begin(); iterator!=block_items_.end(); iterator++) {
|
||||
delete iterator.value();
|
||||
iterator = block_items_.erase(iterator);
|
||||
}
|
||||
|
||||
block_items_.clear();
|
||||
|
||||
SetTimebase(0);
|
||||
}
|
||||
|
||||
void TimelineWidget::TimebaseChangedEvent(const rational &timebase)
|
||||
@@ -725,7 +722,7 @@ void TimelineWidget::DeleteInToOut(bool ripple)
|
||||
}
|
||||
|
||||
// Clear workarea after this
|
||||
new WorkareaSetEnabledCommand(GetConnectedTimelinePoints(), false, command);
|
||||
new WorkareaSetEnabledCommand(GetTimelinePointsProject(), GetConnectedTimelinePoints(), false, command);
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
|
||||
@@ -42,6 +42,11 @@ BlockResizeCommand::BlockResizeCommand(Block *block, rational new_length, QUndoC
|
||||
{
|
||||
}
|
||||
|
||||
Project *BlockResizeCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(block_->parent())->project();
|
||||
}
|
||||
|
||||
void BlockResizeCommand::redo_internal()
|
||||
{
|
||||
block_->set_length_and_media_out(new_length_);
|
||||
@@ -60,6 +65,11 @@ BlockResizeWithMediaInCommand::BlockResizeWithMediaInCommand(Block *block, ratio
|
||||
{
|
||||
}
|
||||
|
||||
Project *BlockResizeWithMediaInCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(block_->parent())->project();
|
||||
}
|
||||
|
||||
void BlockResizeWithMediaInCommand::redo_internal()
|
||||
{
|
||||
block_->set_length_and_media_in(new_length_);
|
||||
@@ -78,6 +88,11 @@ BlockSetMediaInCommand::BlockSetMediaInCommand(Block *block, rational new_media_
|
||||
{
|
||||
}
|
||||
|
||||
Project *BlockSetMediaInCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(block_->parent())->project();
|
||||
}
|
||||
|
||||
void BlockSetMediaInCommand::redo_internal()
|
||||
{
|
||||
block_->set_media_in(new_media_in_);
|
||||
@@ -95,6 +110,11 @@ TrackRippleRemoveBlockCommand::TrackRippleRemoveBlockCommand(TrackOutput *track,
|
||||
{
|
||||
}
|
||||
|
||||
Project *TrackRippleRemoveBlockCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(block_->parent())->project();
|
||||
}
|
||||
|
||||
void TrackRippleRemoveBlockCommand::redo_internal()
|
||||
{
|
||||
before_ = block_->previous();
|
||||
@@ -111,9 +131,9 @@ void TrackRippleRemoveBlockCommand::undo_internal()
|
||||
}
|
||||
|
||||
TrackInsertBlockAfterCommand::TrackInsertBlockAfterCommand(TrackOutput *track,
|
||||
Block *block,
|
||||
Block *before,
|
||||
QUndoCommand *parent) :
|
||||
Block *block,
|
||||
Block *before,
|
||||
QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
track_(track),
|
||||
block_(block),
|
||||
@@ -121,6 +141,11 @@ TrackInsertBlockAfterCommand::TrackInsertBlockAfterCommand(TrackOutput *track,
|
||||
{
|
||||
}
|
||||
|
||||
Project *TrackInsertBlockAfterCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(block_->parent())->project();
|
||||
}
|
||||
|
||||
void TrackInsertBlockAfterCommand::redo_internal()
|
||||
{
|
||||
track_->InsertBlockAfter(block_, before_);
|
||||
@@ -143,6 +168,11 @@ TrackRippleRemoveAreaCommand::TrackRippleRemoveAreaCommand(TrackOutput *track, r
|
||||
{
|
||||
}
|
||||
|
||||
Project *TrackRippleRemoveAreaCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(track_->parent())->project();
|
||||
}
|
||||
|
||||
void TrackRippleRemoveAreaCommand::SetInsert(Block *insert)
|
||||
{
|
||||
insert_ = insert;
|
||||
@@ -386,10 +416,15 @@ BlockSplitCommand::BlockSplitCommand(TrackOutput* track, Block *block, rational
|
||||
}
|
||||
}
|
||||
|
||||
Project *BlockSplitCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(block_->parent())->project();
|
||||
}
|
||||
|
||||
void BlockSplitCommand::redo_internal()
|
||||
{
|
||||
// FIXME: Reintroduce this optimization when block waveforms update automatically
|
||||
// track_->BlockInvalidateCache();
|
||||
// track_->BlockInvalidateCache();
|
||||
|
||||
static_cast<NodeGraph*>(block_->parent())->AddNode(new_block_);
|
||||
Node::CopyInputs(block_, new_block_);
|
||||
@@ -407,12 +442,12 @@ void BlockSplitCommand::redo_internal()
|
||||
NodeParam::ConnectEdge(new_block_->output(), transition);
|
||||
}
|
||||
|
||||
// track_->UnblockInvalidateCache();
|
||||
// track_->UnblockInvalidateCache();
|
||||
}
|
||||
|
||||
void BlockSplitCommand::undo_internal()
|
||||
{
|
||||
// track_->BlockInvalidateCache();
|
||||
// track_->BlockInvalidateCache();
|
||||
|
||||
block_->set_length_and_media_out(old_length_);
|
||||
track_->RippleRemoveBlock(new_block_);
|
||||
@@ -424,7 +459,7 @@ void BlockSplitCommand::undo_internal()
|
||||
NodeParam::ConnectEdge(block_->output(), transition);
|
||||
}
|
||||
|
||||
// track_->UnblockInvalidateCache();
|
||||
// track_->UnblockInvalidateCache();
|
||||
}
|
||||
|
||||
Block *BlockSplitCommand::new_block()
|
||||
@@ -433,7 +468,8 @@ Block *BlockSplitCommand::new_block()
|
||||
}
|
||||
|
||||
TrackSplitAtTimeCommand::TrackSplitAtTimeCommand(TrackOutput *track, rational point, QUndoCommand *parent) :
|
||||
UndoCommand(parent)
|
||||
UndoCommand(parent),
|
||||
track_(track)
|
||||
{
|
||||
// Find Block that contains this time
|
||||
foreach (Block* b, track->Blocks()) {
|
||||
@@ -442,12 +478,17 @@ TrackSplitAtTimeCommand::TrackSplitAtTimeCommand(TrackOutput *track, rational po
|
||||
return;
|
||||
} else if (b->in() < point && b->out() > point) {
|
||||
// We found the Block, split it
|
||||
new BlockSplitCommand(track, b, point, this);
|
||||
new BlockSplitCommand(track_, b, point, this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Project *TrackSplitAtTimeCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(track_->parent())->project();
|
||||
}
|
||||
|
||||
TrackReplaceBlockCommand::TrackReplaceBlockCommand(TrackOutput* track, Block *old, Block *replace, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
track_(track),
|
||||
@@ -456,6 +497,11 @@ TrackReplaceBlockCommand::TrackReplaceBlockCommand(TrackOutput* track, Block *ol
|
||||
{
|
||||
}
|
||||
|
||||
Project *TrackReplaceBlockCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(track_->parent())->project();
|
||||
}
|
||||
|
||||
void TrackReplaceBlockCommand::redo_internal()
|
||||
{
|
||||
track_->ReplaceBlock(old_, replace_);
|
||||
@@ -473,6 +519,11 @@ TrackPrependBlockCommand::TrackPrependBlockCommand(TrackOutput *track, Block *bl
|
||||
{
|
||||
}
|
||||
|
||||
Project *TrackPrependBlockCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(track_->parent())->project();
|
||||
}
|
||||
|
||||
void TrackPrependBlockCommand::redo_internal()
|
||||
{
|
||||
track_->PrependBlock(block_);
|
||||
@@ -535,6 +586,11 @@ BlockSplitPreservingLinksCommand::BlockSplitPreservingLinksCommand(const QVector
|
||||
}
|
||||
}
|
||||
|
||||
Project *BlockSplitPreservingLinksCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(blocks_.first()->parent())->project();
|
||||
}
|
||||
|
||||
TrackCleanGapsCommand::TrackCleanGapsCommand(TrackList *track_list, int index, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
track_list_(track_list),
|
||||
@@ -542,6 +598,11 @@ TrackCleanGapsCommand::TrackCleanGapsCommand(TrackList *track_list, int index, Q
|
||||
{
|
||||
}
|
||||
|
||||
Project *TrackCleanGapsCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(track_list_->GetParentGraph())->project();
|
||||
}
|
||||
|
||||
void TrackCleanGapsCommand::redo_internal()
|
||||
{
|
||||
GapBlock* on_gap = nullptr;
|
||||
@@ -632,6 +693,11 @@ BlockSetSpeedCommand::BlockSetSpeedCommand(Block *block, const rational &new_spe
|
||||
{
|
||||
}
|
||||
|
||||
Project *BlockSetSpeedCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(block_->parent())->project();
|
||||
}
|
||||
|
||||
void BlockSetSpeedCommand::redo_internal()
|
||||
{
|
||||
block_->set_speed(new_speed_);
|
||||
@@ -649,6 +715,11 @@ TimelineRippleDeleteGapsAtRegionsCommand::TimelineRippleDeleteGapsAtRegionsComma
|
||||
{
|
||||
}
|
||||
|
||||
Project *TimelineRippleDeleteGapsAtRegionsCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(timeline_->parent())->project();
|
||||
}
|
||||
|
||||
void TimelineRippleDeleteGapsAtRegionsCommand::redo_internal()
|
||||
{
|
||||
foreach (const TimeRange& range, regions_) {
|
||||
@@ -699,14 +770,20 @@ void TimelineRippleDeleteGapsAtRegionsCommand::undo_internal()
|
||||
commands_.empty();
|
||||
}
|
||||
|
||||
WorkareaSetEnabledCommand::WorkareaSetEnabledCommand(TimelinePoints *points, bool enabled, QUndoCommand *parent) :
|
||||
WorkareaSetEnabledCommand::WorkareaSetEnabledCommand(Project* project, TimelinePoints *points, bool enabled, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
project_(project),
|
||||
points_(points),
|
||||
old_enabled_(points_->workarea()->enabled()),
|
||||
new_enabled_(enabled)
|
||||
{
|
||||
}
|
||||
|
||||
Project *WorkareaSetEnabledCommand::GetRelevantProject() const
|
||||
{
|
||||
return project_;
|
||||
}
|
||||
|
||||
void WorkareaSetEnabledCommand::redo_internal()
|
||||
{
|
||||
points_->workarea()->set_enabled(new_enabled_);
|
||||
@@ -717,14 +794,20 @@ void WorkareaSetEnabledCommand::undo_internal()
|
||||
points_->workarea()->set_enabled(old_enabled_);
|
||||
}
|
||||
|
||||
WorkareaSetRangeCommand::WorkareaSetRangeCommand(TimelinePoints *points, const TimeRange &range, QUndoCommand *parent) :
|
||||
WorkareaSetRangeCommand::WorkareaSetRangeCommand(Project* project, TimelinePoints *points, const TimeRange &range, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
project_(project),
|
||||
points_(points),
|
||||
old_range_(points_->workarea()->range()),
|
||||
new_range_(range)
|
||||
{
|
||||
}
|
||||
|
||||
Project *WorkareaSetRangeCommand::GetRelevantProject() const
|
||||
{
|
||||
return project_;
|
||||
}
|
||||
|
||||
void WorkareaSetRangeCommand::redo_internal()
|
||||
{
|
||||
points_->workarea()->set_range(new_range_);
|
||||
@@ -743,6 +826,11 @@ BlockLinkCommand::BlockLinkCommand(Block *a, Block *b, bool link, QUndoCommand *
|
||||
{
|
||||
}
|
||||
|
||||
Project *BlockLinkCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(a_->parent())->project();
|
||||
}
|
||||
|
||||
void BlockLinkCommand::redo_internal()
|
||||
{
|
||||
if (link_) {
|
||||
@@ -769,6 +857,11 @@ BlockUnlinkAllCommand::BlockUnlinkAllCommand(Block *block, QUndoCommand *parent)
|
||||
{
|
||||
}
|
||||
|
||||
Project *BlockUnlinkAllCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(block_->parent())->project();
|
||||
}
|
||||
|
||||
void BlockUnlinkAllCommand::redo_internal()
|
||||
{
|
||||
unlinked_ = block_->linked_clips();
|
||||
@@ -788,10 +881,11 @@ void BlockUnlinkAllCommand::undo_internal()
|
||||
}
|
||||
|
||||
BlockLinkManyCommand::BlockLinkManyCommand(const QList<Block *> blocks, bool link, QUndoCommand *parent) :
|
||||
UndoCommand(parent)
|
||||
UndoCommand(parent),
|
||||
blocks_(blocks)
|
||||
{
|
||||
foreach (Block* a, blocks) {
|
||||
foreach (Block* b, blocks) {
|
||||
foreach (Block* a, blocks_) {
|
||||
foreach (Block* b, blocks_) {
|
||||
if (a != b) {
|
||||
new BlockLinkCommand(a, b, link, this);
|
||||
}
|
||||
@@ -799,6 +893,11 @@ BlockLinkManyCommand::BlockLinkManyCommand(const QList<Block *> blocks, bool lin
|
||||
}
|
||||
}
|
||||
|
||||
Project *BlockLinkManyCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(blocks_.first()->parent())->project();
|
||||
}
|
||||
|
||||
BlockEnableDisableCommand::BlockEnableDisableCommand(Block *block, bool enabled, QUndoCommand *parent) :
|
||||
UndoCommand(parent),
|
||||
block_(block),
|
||||
@@ -807,6 +906,11 @@ BlockEnableDisableCommand::BlockEnableDisableCommand(Block *block, bool enabled,
|
||||
{
|
||||
}
|
||||
|
||||
Project *BlockEnableDisableCommand::GetRelevantProject() const
|
||||
{
|
||||
return static_cast<Sequence*>(block_->parent())->project();
|
||||
}
|
||||
|
||||
void BlockEnableDisableCommand::redo_internal()
|
||||
{
|
||||
block_->set_enabled(new_enabled_);
|
||||
|
||||
@@ -36,6 +36,8 @@ class BlockResizeCommand : public UndoCommand {
|
||||
public:
|
||||
BlockResizeCommand(Block* block, rational new_length, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -50,6 +52,8 @@ class BlockResizeWithMediaInCommand : public UndoCommand {
|
||||
public:
|
||||
BlockResizeWithMediaInCommand(Block* block, rational new_length, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -64,6 +68,8 @@ class BlockSetMediaInCommand : public UndoCommand {
|
||||
public:
|
||||
BlockSetMediaInCommand(Block* block, rational new_media_in, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -78,6 +84,8 @@ class BlockSetSpeedCommand : public UndoCommand {
|
||||
public:
|
||||
BlockSetSpeedCommand(Block* block, const rational& new_speed, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -93,6 +101,8 @@ class TrackRippleRemoveBlockCommand : public UndoCommand {
|
||||
public:
|
||||
TrackRippleRemoveBlockCommand(TrackOutput* track, Block* block, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -109,6 +119,8 @@ class TrackPrependBlockCommand : public UndoCommand {
|
||||
public:
|
||||
TrackPrependBlockCommand(TrackOutput* track, Block* block, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -122,6 +134,8 @@ class TrackInsertBlockAfterCommand : public UndoCommand {
|
||||
public:
|
||||
TrackInsertBlockAfterCommand(TrackOutput* track, Block* block, Block* before, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -145,6 +159,8 @@ class TrackRippleRemoveAreaCommand : public UndoCommand {
|
||||
public:
|
||||
TrackRippleRemoveAreaCommand(TrackOutput* track, rational in, rational out, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
void SetInsert(Block* insert);
|
||||
|
||||
protected:
|
||||
@@ -203,6 +219,8 @@ class BlockSplitCommand : public UndoCommand {
|
||||
public:
|
||||
BlockSplitCommand(TrackOutput* track, Block* block, rational point, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
Block* new_block();
|
||||
|
||||
protected:
|
||||
@@ -228,12 +246,20 @@ private:
|
||||
class TrackSplitAtTimeCommand : public UndoCommand {
|
||||
public:
|
||||
TrackSplitAtTimeCommand(TrackOutput* track, rational point, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
private:
|
||||
TrackOutput* track_;
|
||||
|
||||
};
|
||||
|
||||
class BlockSplitPreservingLinksCommand : public UndoCommand {
|
||||
public:
|
||||
BlockSplitPreservingLinksCommand(const QVector<Block *> &blocks, const QList<rational>& times, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
private:
|
||||
QVector<Block *> blocks_;
|
||||
|
||||
@@ -249,6 +275,8 @@ class TrackReplaceBlockCommand : public UndoCommand {
|
||||
public:
|
||||
TrackReplaceBlockCommand(TrackOutput* track, Block* old, Block* replace, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -263,6 +291,8 @@ class TrackCleanGapsCommand : public UndoCommand {
|
||||
public:
|
||||
TrackCleanGapsCommand(TrackList* track_list, int index, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -290,6 +320,8 @@ class TimelineRippleDeleteGapsAtRegionsCommand : public UndoCommand {
|
||||
public:
|
||||
TimelineRippleDeleteGapsAtRegionsCommand(ViewerOutput* vo, const TimeRangeList& regions, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -304,13 +336,17 @@ private:
|
||||
|
||||
class WorkareaSetEnabledCommand : public UndoCommand {
|
||||
public:
|
||||
WorkareaSetEnabledCommand(TimelinePoints* points, bool enabled, QUndoCommand* parent = nullptr);
|
||||
WorkareaSetEnabledCommand(Project *project, TimelinePoints* points, bool enabled, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
Project* project_;
|
||||
|
||||
TimelinePoints* points_;
|
||||
|
||||
bool old_enabled_;
|
||||
@@ -321,13 +357,17 @@ private:
|
||||
|
||||
class WorkareaSetRangeCommand : public UndoCommand {
|
||||
public:
|
||||
WorkareaSetRangeCommand(TimelinePoints* points, const TimeRange& range, QUndoCommand* parent = nullptr);
|
||||
WorkareaSetRangeCommand(Project *project, TimelinePoints* points, const TimeRange& range, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
Project* project_;
|
||||
|
||||
TimelinePoints* points_;
|
||||
|
||||
TimeRange old_range_;
|
||||
@@ -339,12 +379,20 @@ private:
|
||||
class BlockLinkManyCommand : public UndoCommand {
|
||||
public:
|
||||
BlockLinkManyCommand(const QList<Block*> blocks, bool link, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
private:
|
||||
QList<Block*> blocks_;
|
||||
|
||||
};
|
||||
|
||||
class BlockLinkCommand : public UndoCommand {
|
||||
public:
|
||||
BlockLinkCommand(Block* a, Block* b, bool link, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -364,6 +412,8 @@ class BlockUnlinkAllCommand : public UndoCommand {
|
||||
public:
|
||||
BlockUnlinkAllCommand(Block* block, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
@@ -379,6 +429,8 @@ class BlockEnableDisableCommand : public UndoCommand {
|
||||
public:
|
||||
BlockEnableDisableCommand(Block* block, bool enabled, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
@@ -98,6 +98,11 @@ TimelinePoints *FootageViewerWidget::ConnectTimelinePoints()
|
||||
return footage_;
|
||||
}
|
||||
|
||||
Project *FootageViewerWidget::GetTimelinePointsProject()
|
||||
{
|
||||
return footage_->project();
|
||||
}
|
||||
|
||||
void FootageViewerWidget::StartFootageDragInternal(bool enable_video, bool enable_audio)
|
||||
{
|
||||
if (!GetFootage()) {
|
||||
|
||||
@@ -40,6 +40,8 @@ public:
|
||||
protected:
|
||||
virtual TimelinePoints* ConnectTimelinePoints() override;
|
||||
|
||||
virtual Project* GetTimelinePointsProject() override;
|
||||
|
||||
private:
|
||||
void StartFootageDragInternal(bool enable_video, bool enable_audio);
|
||||
|
||||
|
||||
@@ -38,7 +38,9 @@ OLIVE_NAMESPACE_ENTER
|
||||
MainMenu::MainMenu(MainWindow *parent) :
|
||||
QMenuBar(parent)
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
StyleManager::UseNativeWindowsStyling(this);
|
||||
#endif
|
||||
|
||||
//
|
||||
// FILE MENU
|
||||
@@ -300,7 +302,7 @@ void MainMenu::TimecodeDisplayTriggered()
|
||||
|
||||
void MainMenu::FileMenuAboutToShow()
|
||||
{
|
||||
file_project_properties_item_->setEnabled(Core::instance()->GetActiveProject() != nullptr);
|
||||
file_project_properties_item_->setEnabled(Core::instance()->GetActiveProject());
|
||||
}
|
||||
|
||||
void MainMenu::ViewMenuAboutToShow()
|
||||
|
||||
@@ -70,7 +70,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
param_panel_ = PanelManager::instance()->CreatePanel<ParamPanel>(this);
|
||||
sequence_viewer_panel_ = PanelManager::instance()->CreatePanel<SequenceViewerPanel>(this);
|
||||
pixel_sampler_panel_ = PanelManager::instance()->CreatePanel<PixelSamplerPanel>(this);
|
||||
project_panel_ = PanelManager::instance()->CreatePanel<ProjectPanel>(this);
|
||||
AppendProjectPanel();
|
||||
tool_panel_ = PanelManager::instance()->CreatePanel<ToolPanel>(this);
|
||||
task_man_panel_ = PanelManager::instance()->CreatePanel<TaskManagerPanel>(this);
|
||||
curve_panel_ = PanelManager::instance()->CreatePanel<CurvePanel>(this);
|
||||
@@ -98,8 +98,9 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
footage_viewer_panel_->ConnectPixelSamplerPanel(pixel_sampler_panel_);
|
||||
sequence_viewer_panel_->ConnectPixelSamplerPanel(pixel_sampler_panel_);
|
||||
|
||||
connect(project_panel_, &ProjectPanel::ProjectNameChanged, this, &MainWindow::UpdateTitle);
|
||||
UpdateTitle();
|
||||
|
||||
QMetaObject::invokeMethod(this, "SetDefaultLayout", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
@@ -114,9 +115,7 @@ MainWindow::~MainWindow()
|
||||
void MainWindow::OpenSequence(Sequence *sequence)
|
||||
{
|
||||
// See if this sequence is already open, and switch to it if so
|
||||
for (int i=0;i<timeline_panels_.size();i++) {
|
||||
TimelinePanel* tl = timeline_panels_.at(i);
|
||||
|
||||
foreach (TimelinePanel* tl, timeline_panels_) {
|
||||
if (tl->GetConnectedViewer() == sequence->viewer_output()) {
|
||||
tl->raise();
|
||||
return;
|
||||
@@ -222,42 +221,54 @@ void MainWindow::ToggleMaximizedPanel()
|
||||
|
||||
void MainWindow::ProjectOpen(Project* p)
|
||||
{
|
||||
// FIXME Use settings data to create panels and restore state if they exist
|
||||
project_panel_->set_project(p);
|
||||
|
||||
UpdateTitle();
|
||||
|
||||
SetDefaultLayout();
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent *e)
|
||||
{
|
||||
if (isWindowModified()) {
|
||||
QMessageBox mb(this);
|
||||
|
||||
mb.setIcon(QMessageBox::Question);
|
||||
mb.setWindowTitle(tr("Unsaved Changes"));
|
||||
mb.setText(tr("The project '%1' has unsaved changes. Would you like to save them?")
|
||||
.arg(Core::instance()->GetActiveProject()->name()));
|
||||
|
||||
QPushButton* yes_btn = mb.addButton(tr("Save"), QMessageBox::YesRole);
|
||||
mb.addButton(tr("Don't Save"), QMessageBox::NoRole);
|
||||
QPushButton* cancel_btn = mb.addButton(QMessageBox::Cancel);
|
||||
|
||||
mb.exec();
|
||||
|
||||
if (mb.clickedButton() == cancel_btn
|
||||
|| (mb.clickedButton() == yes_btn && !Core::instance()->SaveActiveProject())) {
|
||||
// Don't close if the user clicked cancel on this messagebox OR they cancelled a save as operation
|
||||
e->ignore();
|
||||
// See if this project is already open, and switch to it if so
|
||||
foreach (ProjectPanel* pl, project_panels_) {
|
||||
if (pl->project() == p) {
|
||||
pl->raise();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Close viewers first since we don't want to delete any nodes while they might be mid-render
|
||||
QList<ViewerPanelBase*> viewers = PanelManager::instance()->GetPanelsOfType<ViewerPanelBase>();
|
||||
foreach (ViewerPanelBase* viewer, viewers) {
|
||||
viewer->ConnectViewerNode(nullptr);
|
||||
ProjectPanel* panel;
|
||||
|
||||
if (!project_panels_.first()->project()) {
|
||||
panel = project_panels_.first();
|
||||
} else {
|
||||
panel = AppendProjectPanel();
|
||||
}
|
||||
|
||||
panel->set_project(p);
|
||||
|
||||
// FIXME Use settings data to create panels and restore state if they exist
|
||||
}
|
||||
|
||||
void MainWindow::ProjectClose(Project *p)
|
||||
{
|
||||
// Close project from project panel
|
||||
foreach (ProjectPanel* panel, project_panels_) {
|
||||
if (panel->project() == p) {
|
||||
RemoveProjectPanel(panel);
|
||||
}
|
||||
}
|
||||
|
||||
// Close any open sequences from project
|
||||
QList<ItemPtr> open_sequences = p->get_items_of_type(Item::kSequence);
|
||||
|
||||
foreach (ItemPtr item, open_sequences) {
|
||||
Sequence* seq = static_cast<Sequence*>(item.get());
|
||||
|
||||
if (IsSequenceOpen(seq)) {
|
||||
CloseSequence(seq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent *e)
|
||||
{
|
||||
// Try to close all projects (this will return false if the user chooses not to close)
|
||||
if (!Core::instance()->CloseAllProjects(false)) {
|
||||
e->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
PanelManager::instance()->DeleteAllPanels();
|
||||
@@ -292,10 +303,10 @@ bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *r
|
||||
|
||||
void MainWindow::UpdateTitle()
|
||||
{
|
||||
if (project_panel_->project()) {
|
||||
if (Core::instance()->GetActiveProject()) {
|
||||
setWindowTitle(QStringLiteral("%1 %2 - [*]%3").arg(QApplication::applicationName(),
|
||||
QApplication::applicationVersion(),
|
||||
project_panel_->project()->pretty_filename()));
|
||||
Core::instance()->GetActiveProject()->pretty_filename()));
|
||||
} else {
|
||||
setWindowTitle(QStringLiteral("%1 %2").arg(QApplication::applicationName(),
|
||||
QApplication::applicationVersion()));
|
||||
@@ -307,24 +318,19 @@ void MainWindow::TimelineCloseRequested()
|
||||
RemoveTimelinePanel(static_cast<TimelinePanel*>(sender()));
|
||||
}
|
||||
|
||||
void MainWindow::ProjectCloseRequested()
|
||||
{
|
||||
ProjectPanel* panel = static_cast<ProjectPanel*>(sender());
|
||||
Project* p = panel->project();
|
||||
|
||||
Core::instance()->CloseProject(p, true);
|
||||
}
|
||||
|
||||
TimelinePanel* MainWindow::AppendTimelinePanel()
|
||||
{
|
||||
TimelinePanel* panel = PanelManager::instance()->CreatePanel<TimelinePanel>(this);;
|
||||
|
||||
if (!timeline_panels_.isEmpty()) {
|
||||
tabifyDockWidget(timeline_panels_.last(), panel);
|
||||
|
||||
// For some reason raise() on its own doesn't do anything, we need both
|
||||
panel->show();
|
||||
panel->raise();
|
||||
}
|
||||
|
||||
timeline_panels_.append(panel);
|
||||
|
||||
// Let us handle the panel closing rather than the panel itself
|
||||
panel->SetSignalInsteadOfClose(true);
|
||||
connect(panel, &TimelinePanel::CloseRequested, this, &MainWindow::TimelineCloseRequested);
|
||||
TimelinePanel* panel = AppendPanelInternal<TimelinePanel>(timeline_panels_);
|
||||
|
||||
connect(panel, &PanelWidget::CloseRequested, this, &MainWindow::TimelineCloseRequested);
|
||||
connect(panel, &TimelinePanel::TimeChanged, param_panel_, &ParamPanel::SetTime);
|
||||
connect(panel, &TimelinePanel::TimeChanged, sequence_viewer_panel_, &SequenceViewerPanel::SetTime);
|
||||
connect(panel, &TimelinePanel::TimeChanged, curve_panel_, &CurvePanel::SetTime);
|
||||
@@ -340,6 +346,16 @@ TimelinePanel* MainWindow::AppendTimelinePanel()
|
||||
return panel;
|
||||
}
|
||||
|
||||
ProjectPanel *MainWindow::AppendProjectPanel()
|
||||
{
|
||||
ProjectPanel* panel = AppendPanelInternal<ProjectPanel>(project_panels_);
|
||||
|
||||
connect(panel, &PanelWidget::CloseRequested, this, &MainWindow::ProjectCloseRequested);
|
||||
connect(panel, &ProjectPanel::ProjectNameChanged, this, &MainWindow::UpdateTitle);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
void MainWindow::RemoveTimelinePanel(TimelinePanel *panel)
|
||||
{
|
||||
// Stop showing this timeline in the viewer
|
||||
@@ -354,6 +370,16 @@ void MainWindow::RemoveTimelinePanel(TimelinePanel *panel)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::RemoveProjectPanel(ProjectPanel *panel)
|
||||
{
|
||||
if (project_panels_.size() == 1) {
|
||||
panel->set_project(nullptr);
|
||||
} else {
|
||||
project_panels_.removeOne(panel);
|
||||
panel->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::TimelineFocused(ViewerOutput* viewer)
|
||||
{
|
||||
sequence_viewer_panel_->ConnectViewerNode(viewer);
|
||||
@@ -373,6 +399,14 @@ void MainWindow::FocusedPanelChanged(PanelWidget *panel)
|
||||
|
||||
if (timeline) {
|
||||
TimelineFocused(timeline->GetConnectedViewer());
|
||||
return;
|
||||
}
|
||||
|
||||
ProjectPanel* project = dynamic_cast<ProjectPanel*>(panel);
|
||||
|
||||
if (project) {
|
||||
UpdateTitle();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,8 +429,8 @@ void MainWindow::SetDefaultLayout()
|
||||
pixel_sampler_panel_->setFloating(true);
|
||||
addDockWidget(Qt::TopDockWidgetArea, pixel_sampler_panel_);
|
||||
|
||||
project_panel_->show();
|
||||
addDockWidget(Qt::BottomDockWidgetArea, project_panel_);
|
||||
project_panels_.first()->show();
|
||||
addDockWidget(Qt::BottomDockWidgetArea, project_panels_.first());
|
||||
|
||||
tool_panel_->show();
|
||||
addDockWidget(Qt::BottomDockWidgetArea, tool_panel_);
|
||||
@@ -419,13 +453,34 @@ void MainWindow::SetDefaultLayout()
|
||||
{width()/3, width()/3, width()/3},
|
||||
Qt::Horizontal);
|
||||
|
||||
resizeDocks({project_panel_, tool_panel_, timeline_panels_.first(), audio_monitor_panel_},
|
||||
resizeDocks({project_panels_.first(), tool_panel_, timeline_panels_.first(), audio_monitor_panel_},
|
||||
{width()/4, 1, width(), 1},
|
||||
Qt::Horizontal);
|
||||
|
||||
resizeDocks({node_panel_, project_panel_},
|
||||
resizeDocks({node_panel_, project_panels_.first()},
|
||||
{height()/2, height()/2},
|
||||
Qt::Vertical);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T *MainWindow::AppendPanelInternal(QList<T*>& list)
|
||||
{
|
||||
T* panel = PanelManager::instance()->CreatePanel<T>(this);
|
||||
|
||||
if (!list.isEmpty()) {
|
||||
tabifyDockWidget(list.last(), panel);
|
||||
}
|
||||
|
||||
// For some reason raise() on its own doesn't do anything, we need both
|
||||
panel->show();
|
||||
panel->raise();
|
||||
|
||||
list.append(panel);
|
||||
|
||||
// Let us handle the panel closing rather than the panel itself
|
||||
panel->SetSignalInsteadOfClose(true);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -67,7 +67,11 @@ public:
|
||||
|
||||
public slots:
|
||||
void ProjectOpen(Project *p);
|
||||
|
||||
void ProjectClose(Project* p);
|
||||
|
||||
void SetFullscreen(bool fullscreen);
|
||||
|
||||
void ToggleMaximizedPanel();
|
||||
|
||||
void SetDefaultLayout();
|
||||
@@ -82,8 +86,15 @@ protected:
|
||||
private:
|
||||
TimelinePanel* AppendTimelinePanel();
|
||||
|
||||
ProjectPanel* AppendProjectPanel();
|
||||
|
||||
template <typename T>
|
||||
T* AppendPanelInternal(QList<T*>& list);
|
||||
|
||||
void RemoveTimelinePanel(TimelinePanel *panel);
|
||||
|
||||
void RemoveProjectPanel(ProjectPanel* panel);
|
||||
|
||||
void TimelineFocused(ViewerOutput *viewer);
|
||||
|
||||
QByteArray premaximized_state_;
|
||||
@@ -93,7 +104,7 @@ private:
|
||||
ParamPanel* param_panel_;
|
||||
SequenceViewerPanel* sequence_viewer_panel_;
|
||||
FootageViewerPanel* footage_viewer_panel_;
|
||||
ProjectPanel* project_panel_;
|
||||
QList<ProjectPanel*> project_panels_;
|
||||
ToolPanel* tool_panel_;
|
||||
QList<TimelinePanel*> timeline_panels_;
|
||||
AudioMonitorPanel* audio_monitor_panel_;
|
||||
@@ -114,6 +125,8 @@ private slots:
|
||||
|
||||
void TimelineCloseRequested();
|
||||
|
||||
void ProjectCloseRequested();
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
Reference in New Issue
Block a user