core: switch to single-project implementation
This has never worked right, it's caused a number of complexities within the code, and I think there are better ways to do this.
This commit is contained in:
+54
-241
@@ -83,6 +83,7 @@ Core* Core::instance_ = nullptr;
|
|||||||
|
|
||||||
Core::Core(const CoreParams& params) :
|
Core::Core(const CoreParams& params) :
|
||||||
main_window_(nullptr),
|
main_window_(nullptr),
|
||||||
|
open_project_(nullptr),
|
||||||
tool_(Tool::kPointer),
|
tool_(Tool::kPointer),
|
||||||
addable_object_(Tool::kAddableEmpty),
|
addable_object_(Tool::kAddableEmpty),
|
||||||
snapping_(true),
|
snapping_(true),
|
||||||
@@ -291,14 +292,9 @@ void Core::ClearOpenRecentList()
|
|||||||
void Core::CreateNewProject()
|
void Core::CreateNewProject()
|
||||||
{
|
{
|
||||||
// If we already have an empty/new project, switch to it
|
// If we already have an empty/new project, switch to it
|
||||||
foreach (Project* already_open, open_projects_) {
|
if (CloseProject(false)) {
|
||||||
if (already_open->is_new()) {
|
|
||||||
AddOpenProject(already_open);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AddOpenProject(new Project());
|
AddOpenProject(new Project());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool &Core::snapping() const
|
const bool &Core::snapping() const
|
||||||
@@ -471,21 +467,19 @@ void Core::CreateNewSequence()
|
|||||||
void Core::AddOpenProject(Project* p, bool add_to_recents)
|
void Core::AddOpenProject(Project* p, bool add_to_recents)
|
||||||
{
|
{
|
||||||
// Ensure project is not open at the moment
|
// Ensure project is not open at the moment
|
||||||
foreach (Project* already_open, open_projects_) {
|
if (open_project_ == p) {
|
||||||
if (already_open == p) {
|
|
||||||
// Signal UI to switch to this project
|
// Signal UI to switch to this project
|
||||||
emit ProjectOpened(p);
|
emit ProjectOpened(p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If we currently have an empty project, close it first
|
// If we currently have an empty project, close it first
|
||||||
if (!open_projects_.isEmpty() && open_projects_.last()->is_new()) {
|
if (open_project_) {
|
||||||
CloseProject(open_projects_.last(), false);
|
CloseProject(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(p, &Project::ModifiedChanged, this, &Core::ProjectWasModified);
|
connect(p, &Project::ModifiedChanged, this, &Core::ProjectWasModified);
|
||||||
open_projects_.append(p);
|
open_project_ = p;
|
||||||
|
|
||||||
if (!p->filename().isEmpty() && add_to_recents) {
|
if (!p->filename().isEmpty() && add_to_recents) {
|
||||||
PushRecentlyOpenedProject(p->filename());
|
PushRecentlyOpenedProject(p->filename());
|
||||||
@@ -508,11 +502,9 @@ bool Core::AddOpenProjectFromTask(Task *task, bool add_to_recents)
|
|||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
delete project;
|
delete project;
|
||||||
if (open_projects_.empty()) {
|
|
||||||
CreateNewProject();
|
CreateNewProject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -593,23 +585,7 @@ bool Core::ConfirmImageSequence(const QString& filename)
|
|||||||
|
|
||||||
void Core::ProjectWasModified(bool e)
|
void Core::ProjectWasModified(bool e)
|
||||||
{
|
{
|
||||||
//Project* p = static_cast<Project*>(sender());
|
main_window_->setWindowModified(e);
|
||||||
|
|
||||||
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 (Project* open, open_projects_) {
|
|
||||||
if (open->is_modified()) {
|
|
||||||
main_window_->setWindowModified(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main_window_->setWindowModified(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Core::StartHeadlessExport()
|
bool Core::StartHeadlessExport()
|
||||||
@@ -805,15 +781,15 @@ void Core::StartGUI(bool full_screen)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::SaveProjectInternal(Project* project, const QString& override_filename)
|
void Core::SaveProjectInternal(const QString& override_filename)
|
||||||
{
|
{
|
||||||
// Create save manager
|
// Create save manager
|
||||||
Task* psm;
|
Task* psm;
|
||||||
|
|
||||||
// Put layout into project
|
// Put layout into project
|
||||||
project->SetLayoutInfo(main_window_->SaveLayout());
|
open_project_->SetLayoutInfo(main_window_->SaveLayout());
|
||||||
|
|
||||||
if (project->filename().endsWith(QStringLiteral(".otio"), Qt::CaseInsensitive)) {
|
if (open_project_->filename().endsWith(QStringLiteral(".otio"), Qt::CaseInsensitive)) {
|
||||||
#ifdef USE_OTIO
|
#ifdef USE_OTIO
|
||||||
psm = new SaveOTIOTask(project);
|
psm = new SaveOTIOTask(project);
|
||||||
#else
|
#else
|
||||||
@@ -824,8 +800,8 @@ void Core::SaveProjectInternal(Project* project, const QString& override_filenam
|
|||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
bool use_compression = !project->filename().endsWith(QStringLiteral(".ovexml"), Qt::CaseInsensitive);
|
bool use_compression = !open_project_->filename().endsWith(QStringLiteral(".ovexml"), Qt::CaseInsensitive);
|
||||||
psm = new ProjectSaveTask(project, use_compression);
|
psm = new ProjectSaveTask(open_project_, use_compression);
|
||||||
|
|
||||||
if (!override_filename.isEmpty()) {
|
if (!override_filename.isEmpty()) {
|
||||||
// Set override filename if provided
|
// Set override filename if provided
|
||||||
@@ -915,9 +891,9 @@ void Core::SaveUnrecoveredList()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Core::RevertProjectInternal(Project *p, bool by_opening_existing)
|
bool Core::RevertProjectInternal(bool by_opening_existing)
|
||||||
{
|
{
|
||||||
if (p->filename().isEmpty()) {
|
if (open_project_->filename().isEmpty()) {
|
||||||
QMessageBox::critical(main_window_, tr("Revert"),
|
QMessageBox::critical(main_window_, tr("Revert"),
|
||||||
tr("This project has not yet been saved, therefore there is no last saved state to revert to."));
|
tr("This project has not yet been saved, therefore there is no last saved state to revert to."));
|
||||||
} else {
|
} else {
|
||||||
@@ -925,21 +901,20 @@ bool Core::RevertProjectInternal(Project *p, bool by_opening_existing)
|
|||||||
|
|
||||||
if (by_opening_existing) {
|
if (by_opening_existing) {
|
||||||
msg = tr("The project \"%1\" is already open. By re-opening it, the project will revert to "
|
msg = tr("The project \"%1\" is already open. By re-opening it, the project will revert to "
|
||||||
"its last saved state. Any unsaved changes will be lost. Do you wish to continue?").arg(p->filename());
|
"its last saved state. Any unsaved changes will be lost. Do you wish to continue?").arg(open_project_->filename());
|
||||||
} else {
|
} else {
|
||||||
msg = tr("This will revert the project \"%1\" back to its last saved state. "
|
msg = tr("This will revert the project \"%1\" back to its last saved state. "
|
||||||
"All unsaved changes will be lost. Do you wish to continue?").arg(p->name());
|
"All unsaved changes will be lost. Do you wish to continue?").arg(open_project_->name());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (QMessageBox::question(main_window_, tr("Revert"), msg, QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
|
if (QMessageBox::question(main_window_, tr("Revert"), msg, QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
|
||||||
// Copy filename because CloseProject is going to delete `p`
|
// Copy filename because CloseProject is going to delete `p`
|
||||||
QString filename = p->filename();
|
QString filename = open_project_->filename();
|
||||||
|
|
||||||
// Close project without prompting to save it
|
// Close project without prompting to save it
|
||||||
CloseProjectBehavior b = kCloseProjectDontSave;
|
CloseProject(false, true);
|
||||||
CloseProject(p, false, b);
|
|
||||||
|
|
||||||
// NOTE: `p` will be deleted now, so don't try accessing it
|
// NOTE: `open_project_` will be deleted now, so don't try accessing it
|
||||||
|
|
||||||
// Re-open project at the filename
|
// Re-open project at the filename
|
||||||
OpenProjectInternal(filename);
|
OpenProjectInternal(filename);
|
||||||
@@ -964,19 +939,18 @@ void Core::SaveRecentProjectsList()
|
|||||||
void Core::SaveAutorecovery()
|
void Core::SaveAutorecovery()
|
||||||
{
|
{
|
||||||
if (OLIVE_CONFIG("AutorecoveryEnabled").toBool()) {
|
if (OLIVE_CONFIG("AutorecoveryEnabled").toBool()) {
|
||||||
foreach (Project* p, open_projects_) {
|
if (!open_project_->has_autorecovery_been_saved()) {
|
||||||
if (!p->has_autorecovery_been_saved()) {
|
QDir project_autorecovery_dir(QDir(FileFunctions::GetAutoRecoveryRoot()).filePath(open_project_->GetUuid().toString()));
|
||||||
QDir project_autorecovery_dir(QDir(FileFunctions::GetAutoRecoveryRoot()).filePath(p->GetUuid().toString()));
|
|
||||||
if (FileFunctions::DirectoryIsValid(project_autorecovery_dir)) {
|
if (FileFunctions::DirectoryIsValid(project_autorecovery_dir)) {
|
||||||
QString this_autorecovery_path = project_autorecovery_dir.filePath(QStringLiteral("%1.ove").arg(QString::number(QDateTime::currentSecsSinceEpoch())));
|
QString this_autorecovery_path = project_autorecovery_dir.filePath(QStringLiteral("%1.ove").arg(QString::number(QDateTime::currentSecsSinceEpoch())));
|
||||||
|
|
||||||
SaveProjectInternal(p, this_autorecovery_path);
|
SaveProjectInternal(this_autorecovery_path);
|
||||||
|
|
||||||
p->set_autorecovery_saved(true);
|
open_project_->set_autorecovery_saved(true);
|
||||||
|
|
||||||
// Keep track of projects that where the "newest" save is the recovery project
|
// Keep track of projects that where the "newest" save is the recovery project
|
||||||
if (!autorecovered_projects_.contains(p->GetUuid())) {
|
if (!autorecovered_projects_.contains(open_project_->GetUuid())) {
|
||||||
autorecovered_projects_.append(p->GetUuid());
|
autorecovered_projects_.append(open_project_->GetUuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Saved auto-recovery to:" << this_autorecovery_path;
|
qDebug() << "Saved auto-recovery to:" << this_autorecovery_path;
|
||||||
@@ -985,7 +959,7 @@ void Core::SaveAutorecovery()
|
|||||||
{
|
{
|
||||||
QFile realname_file(project_autorecovery_dir.filePath(QStringLiteral("realname.txt")));
|
QFile realname_file(project_autorecovery_dir.filePath(QStringLiteral("realname.txt")));
|
||||||
realname_file.open(QFile::WriteOnly);
|
realname_file.open(QFile::WriteOnly);
|
||||||
realname_file.write(p->pretty_filename().toUtf8());
|
realname_file.write(open_project_->pretty_filename().toUtf8());
|
||||||
realname_file.close();
|
realname_file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1024,7 +998,6 @@ void Core::SaveAutorecovery()
|
|||||||
.arg(project_autorecovery_dir.absolutePath()));
|
.arg(project_autorecovery_dir.absolutePath()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Save index
|
// Save index
|
||||||
SaveUnrecoveredList();
|
SaveUnrecoveredList();
|
||||||
@@ -1047,24 +1020,7 @@ void Core::ProjectSaveSucceeded(Task* task)
|
|||||||
|
|
||||||
Project* Core::GetActiveProject() const
|
Project* Core::GetActiveProject() const
|
||||||
{
|
{
|
||||||
ProjectPanel* active_project_panel = PanelManager::instance()->MostRecentlyFocused<ProjectPanel>();
|
return open_project_;
|
||||||
|
|
||||||
if (active_project_panel && active_project_panel->project()) {
|
|
||||||
return active_project_panel->project();
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProjectViewModel *Core::GetActiveProjectModel() const
|
|
||||||
{
|
|
||||||
ProjectPanel* active_project_panel = PanelManager::instance()->MostRecentlyFocused<ProjectPanel>();
|
|
||||||
|
|
||||||
if (active_project_panel) {
|
|
||||||
return active_project_panel->model();
|
|
||||||
} else {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Folder *Core::GetSelectedFolderInActiveProject() const
|
Folder *Core::GetSelectedFolderInActiveProject() const
|
||||||
@@ -1106,69 +1062,6 @@ QString Core::PasteStringFromClipboard()
|
|||||||
return QGuiApplication::clipboard()->text();
|
return QGuiApplication::clipboard()->text();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Core::SaveActiveProject()
|
|
||||||
{
|
|
||||||
Project* active_project = GetActiveProject();
|
|
||||||
|
|
||||||
if (active_project) {
|
|
||||||
return SaveProject(active_project);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Core::SaveActiveProjectAs()
|
|
||||||
{
|
|
||||||
Project* active_project = GetActiveProject();
|
|
||||||
|
|
||||||
if (active_project) {
|
|
||||||
return SaveProjectAs(active_project);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Core::SaveAllProjects()
|
|
||||||
{
|
|
||||||
foreach (Project* p, open_projects_) {
|
|
||||||
if (!SaveProject(p)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::RevertActiveProject()
|
|
||||||
{
|
|
||||||
Project *p = GetActiveProject();
|
|
||||||
|
|
||||||
if (p) {
|
|
||||||
RevertProjectInternal(p, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Core::CloseActiveProject()
|
|
||||||
{
|
|
||||||
return CloseProject(GetActiveProject(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Core::CloseAllExceptActiveProject()
|
|
||||||
{
|
|
||||||
Project* active_proj = GetActiveProject();
|
|
||||||
QList<Project*> copy = open_projects_;
|
|
||||||
|
|
||||||
foreach (Project* p, copy) {
|
|
||||||
if (p != active_proj) {
|
|
||||||
if (!CloseProject(p, true)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Core::GetProjectFilter(bool include_any_filter)
|
QString Core::GetProjectFilter(bool include_any_filter)
|
||||||
{
|
{
|
||||||
static const QVector< QPair<QString, QString> > FILTERS = {
|
static const QVector< QPair<QString, QString> > FILTERS = {
|
||||||
@@ -1230,12 +1123,12 @@ void Core::SetStartupLocale()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Core::SaveProject(Project* p)
|
bool Core::SaveProject()
|
||||||
{
|
{
|
||||||
if (p->filename().isEmpty()) {
|
if (open_project_->filename().isEmpty()) {
|
||||||
return SaveProjectAs(p);
|
return SaveProjectAs();
|
||||||
} else {
|
} else {
|
||||||
SaveProjectInternal(p);
|
SaveProjectInternal();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1339,7 +1232,7 @@ void Core::WarnCacheFull()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Core::SaveProjectAs(Project* p)
|
bool Core::SaveProjectAs()
|
||||||
{
|
{
|
||||||
QFileDialog fd(main_window_, tr("Save Project As"));
|
QFileDialog fd(main_window_, tr("Save Project As"));
|
||||||
|
|
||||||
@@ -1356,9 +1249,9 @@ bool Core::SaveProjectAs(Project* p)
|
|||||||
|
|
||||||
fn = FileFunctions::EnsureFilenameExtension(fn, extension);
|
fn = FileFunctions::EnsureFilenameExtension(fn, extension);
|
||||||
|
|
||||||
p->set_filename(fn);
|
open_project_->set_filename(fn);
|
||||||
|
|
||||||
SaveProjectInternal(p);
|
SaveProjectInternal();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1366,6 +1259,11 @@ bool Core::SaveProjectAs(Project* p)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Core::RevertProject()
|
||||||
|
{
|
||||||
|
RevertProjectInternal(false);
|
||||||
|
}
|
||||||
|
|
||||||
void Core::PushRecentlyOpenedProject(const QString& s)
|
void Core::PushRecentlyOpenedProject(const QString& s)
|
||||||
{
|
{
|
||||||
if (s.isEmpty()) {
|
if (s.isEmpty()) {
|
||||||
@@ -1392,17 +1290,16 @@ void Core::PushRecentlyOpenedProject(const QString& s)
|
|||||||
|
|
||||||
void Core::OpenProjectInternal(const QString &filename, bool recovery_project)
|
void Core::OpenProjectInternal(const QString &filename, bool recovery_project)
|
||||||
{
|
{
|
||||||
// See if this project is open already
|
if (open_project_) {
|
||||||
foreach (Project* p, open_projects_) {
|
|
||||||
// Comparing QFileInfos will handle case insensitivity and both slash directions on platforms
|
// Comparing QFileInfos will handle case insensitivity and both slash directions on platforms
|
||||||
// where this is necessary (not naming any names *cough* Windows)
|
// where this is necessary (not naming any names *cough* Windows)
|
||||||
if (QFileInfo(p->filename()) == QFileInfo(filename)) {
|
if (QFileInfo(open_project_->filename()) == QFileInfo(filename)) {
|
||||||
// This project is already open
|
// This project is already open
|
||||||
bool reverted = RevertProjectInternal(p, true);
|
bool reverted = RevertProjectInternal(true);
|
||||||
|
|
||||||
if (!reverted) {
|
if (!reverted) {
|
||||||
// Calling this will focus attention to the project that the user just tried to re-open
|
// Calling this will focus attention to the project that the user just tried to re-open
|
||||||
AddOpenProject(p);
|
AddOpenProject(open_project_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't do anything else
|
// Don't do anything else
|
||||||
@@ -1544,48 +1441,22 @@ void Core::OpenProjectFromRecentList(int index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Core::CloseProject(Project *p, bool auto_open_new)
|
bool Core::CloseProject(bool auto_open_new, bool ignore_modified)
|
||||||
{
|
{
|
||||||
CloseProjectBehavior b = kCloseProjectOnlyOne;
|
if (open_project_) {
|
||||||
return CloseProject(p, auto_open_new, b);
|
if (open_project_->is_modified() && !ignore_modified) {
|
||||||
}
|
|
||||||
|
|
||||||
bool Core::CloseProject(Project* p, bool auto_open_new, CloseProjectBehavior &confirm_behavior)
|
|
||||||
{
|
|
||||||
for (int i=0;i<open_projects_.size();i++) {
|
|
||||||
if (open_projects_.at(i) == p) {
|
|
||||||
|
|
||||||
if (p->is_modified() && confirm_behavior != kCloseProjectDontSave) {
|
|
||||||
|
|
||||||
bool save_this_project;
|
|
||||||
|
|
||||||
if (confirm_behavior == kCloseProjectAsk || confirm_behavior == kCloseProjectOnlyOne) {
|
|
||||||
QMessageBox mb(main_window_);
|
QMessageBox mb(main_window_);
|
||||||
|
|
||||||
mb.setWindowModality(Qt::WindowModal);
|
mb.setWindowModality(Qt::WindowModal);
|
||||||
mb.setIcon(QMessageBox::Question);
|
mb.setIcon(QMessageBox::Question);
|
||||||
mb.setWindowTitle(tr("Unsaved Changes"));
|
mb.setWindowTitle(tr("Unsaved Changes"));
|
||||||
mb.setText(tr("The project '%1' has unsaved changes. Would you like to save them?")
|
mb.setText(tr("The project '%1' has unsaved changes. Would you like to save them?")
|
||||||
.arg(p->name()));
|
.arg(open_project_->name()));
|
||||||
|
|
||||||
QPushButton* yes_btn = mb.addButton(tr("Save"), QMessageBox::YesRole);
|
QPushButton* yes_btn = mb.addButton(tr("Save"), QMessageBox::YesRole);
|
||||||
|
|
||||||
QPushButton* yes_to_all_btn;
|
|
||||||
if (confirm_behavior == kCloseProjectOnlyOne) {
|
|
||||||
yes_to_all_btn = nullptr;
|
|
||||||
} else {
|
|
||||||
yes_to_all_btn = mb.addButton(tr("Save All"), QMessageBox::YesRole);
|
|
||||||
}
|
|
||||||
|
|
||||||
mb.addButton(tr("Don't Save"), QMessageBox::NoRole);
|
mb.addButton(tr("Don't Save"), QMessageBox::NoRole);
|
||||||
|
|
||||||
QPushButton* no_to_all_btn;
|
|
||||||
if (confirm_behavior == kCloseProjectOnlyOne) {
|
|
||||||
no_to_all_btn = nullptr;
|
|
||||||
} else {
|
|
||||||
no_to_all_btn = mb.addButton(tr("Don't Save All"), QMessageBox::NoRole);
|
|
||||||
}
|
|
||||||
|
|
||||||
QPushButton* cancel_btn = mb.addButton(QMessageBox::Cancel);
|
QPushButton* cancel_btn = mb.addButton(QMessageBox::Cancel);
|
||||||
|
|
||||||
mb.exec();
|
mb.exec();
|
||||||
@@ -1593,84 +1464,31 @@ bool Core::CloseProject(Project* p, bool auto_open_new, CloseProjectBehavior &co
|
|||||||
if (mb.clickedButton() == cancel_btn) {
|
if (mb.clickedButton() == cancel_btn) {
|
||||||
// Stop closing projects if the user clicked cancel
|
// Stop closing projects if the user clicked cancel
|
||||||
return false;
|
return false;
|
||||||
} else if (mb.clickedButton() == yes_to_all_btn) {
|
|
||||||
// Set flag that other CloseProject commands are going to use
|
|
||||||
confirm_behavior = kCloseProjectSave;
|
|
||||||
} else if (mb.clickedButton() == no_to_all_btn) {
|
|
||||||
// Set flag that other CloseProject commands are going to use
|
|
||||||
confirm_behavior = kCloseProjectDontSave;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
save_this_project = (mb.clickedButton() == yes_btn || mb.clickedButton() == yes_to_all_btn);
|
if (mb.clickedButton() == yes_btn && !SaveProject()) {
|
||||||
|
|
||||||
} else {
|
|
||||||
// We must be saving this project
|
|
||||||
save_this_project = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (save_this_project && !SaveProject(p)) {
|
|
||||||
// The save failed, stop closing projects
|
// The save failed, stop closing projects
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For safety, the undo stack is cleared so no commands try to affect a freed project
|
// For safety, the undo stack is cleared so no commands try to affect a freed project
|
||||||
undo_stack_.clear();
|
undo_stack_.clear();
|
||||||
|
|
||||||
disconnect(p, &Project::ModifiedChanged, this, &Core::ProjectWasModified);
|
disconnect(open_project_, &Project::ModifiedChanged, this, &Core::ProjectWasModified);
|
||||||
emit ProjectClosed(p);
|
emit ProjectClosed(open_project_);
|
||||||
open_projects_.removeAt(i);
|
delete open_project_;
|
||||||
delete p;
|
open_project_ = nullptr;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure a project is always active
|
// Ensure a project is always active
|
||||||
if (auto_open_new && open_projects_.isEmpty()) {
|
if (auto_open_new) {
|
||||||
CreateNewProject();
|
CreateNewProject();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Core::CloseAllProjects(bool auto_open_new)
|
|
||||||
{
|
|
||||||
QList<Project*> copy = open_projects_;
|
|
||||||
|
|
||||||
// See how many projects are modified so we can set "behavior" correctly
|
|
||||||
// (i.e. whether to show "Yes/No To All" buttons or not)
|
|
||||||
int modified_count = 0;
|
|
||||||
foreach (Project* p, copy) {
|
|
||||||
if (p->is_modified()) {
|
|
||||||
modified_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseProjectBehavior behavior;
|
|
||||||
|
|
||||||
if (modified_count > 1) {
|
|
||||||
behavior = kCloseProjectAsk;
|
|
||||||
} else {
|
|
||||||
behavior = kCloseProjectOnlyOne;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Project* p, copy) {
|
|
||||||
// If this is the only remaining project and the user hasn't chose "yes/no to all", hide those buttons
|
|
||||||
if (modified_count == 1 && behavior == kCloseProjectAsk) {
|
|
||||||
behavior = kCloseProjectOnlyOne;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CloseProject(p, auto_open_new, behavior)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
modified_count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::CacheActiveSequence(bool in_out_only)
|
void Core::CacheActiveSequence(bool in_out_only)
|
||||||
{
|
{
|
||||||
TimeBasedPanel* p = PanelManager::instance()->MostRecentlyFocused<TimeBasedPanel>();
|
TimeBasedPanel* p = PanelManager::instance()->MostRecentlyFocused<TimeBasedPanel>();
|
||||||
@@ -1787,11 +1605,6 @@ bool Core::SetLanguage(const QString &locale)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Core::CloseAllProjects()
|
|
||||||
{
|
|
||||||
return CloseAllProjects(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::OpenProject()
|
void Core::OpenProject()
|
||||||
{
|
{
|
||||||
QString file = QFileDialog::getOpenFileName(main_window_,
|
QString file = QFileDialog::getOpenFileName(main_window_,
|
||||||
|
|||||||
+9
-63
@@ -219,7 +219,6 @@ public:
|
|||||||
* The active Project file, or nullptr if the heuristic couldn't find one.
|
* The active Project file, or nullptr if the heuristic couldn't find one.
|
||||||
*/
|
*/
|
||||||
Project* GetActiveProject() const;
|
Project* GetActiveProject() const;
|
||||||
ProjectViewModel* GetActiveProjectModel() const;
|
|
||||||
Folder* GetSelectedFolderInActiveProject() const;
|
Folder* GetSelectedFolderInActiveProject() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -265,23 +264,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
void OpenProjectFromRecentList(int index);
|
void OpenProjectFromRecentList(int index);
|
||||||
|
|
||||||
enum CloseProjectBehavior {
|
|
||||||
kCloseProjectOnlyOne,
|
|
||||||
kCloseProjectAsk,
|
|
||||||
kCloseProjectSave,
|
|
||||||
kCloseProjectDontSave
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Closes a project
|
* @brief Closes a project
|
||||||
*/
|
*/
|
||||||
bool CloseProject(Project* p, bool auto_open_new, CloseProjectBehavior& confirm_behavior);
|
bool CloseProject(bool auto_open_new, bool ignore_modified = false);
|
||||||
bool CloseProject(Project* p, bool auto_open_new);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Closes all open projects
|
|
||||||
*/
|
|
||||||
bool CloseAllProjects(bool auto_open_new);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Runs a modal cache task on the currently active sequence
|
* @brief Runs a modal cache task on the currently active sequence
|
||||||
@@ -298,11 +284,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool SetLanguage(const QString& locale);
|
bool SetLanguage(const QString& locale);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Saves a specific project
|
|
||||||
*/
|
|
||||||
bool SaveProject(Project *p);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Show message in main window's status bar
|
* @brief Show message in main window's status bar
|
||||||
*
|
*
|
||||||
@@ -327,46 +308,16 @@ public slots:
|
|||||||
void OpenProject();
|
void OpenProject();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Save the currently active project
|
* @brief Saves the current project
|
||||||
*
|
|
||||||
* If the project hasn't been saved before, this will be equivalent to calling SaveActiveProjectAs().
|
|
||||||
*/
|
*/
|
||||||
bool SaveActiveProject();
|
bool SaveProject();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Save the currently active project with a new filename
|
* @brief Performs a "save as" on the current project
|
||||||
*/
|
*/
|
||||||
bool SaveActiveProjectAs();
|
bool SaveProjectAs();
|
||||||
|
|
||||||
/**
|
void RevertProject();
|
||||||
* @brief Save all currently open projects
|
|
||||||
*/
|
|
||||||
bool SaveAllProjects();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Revert project to last saved state (basically close and open it)
|
|
||||||
*/
|
|
||||||
void RevertActiveProject();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Closes the active project
|
|
||||||
*
|
|
||||||
* If no other projects are open, a new one is created automatically.
|
|
||||||
*/
|
|
||||||
bool CloseActiveProject();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Closes all projects except the active project
|
|
||||||
*/
|
|
||||||
bool CloseAllExceptActiveProject();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Closes all open projects
|
|
||||||
*
|
|
||||||
* Equivalent to `CloseAllProjects(true)`, but useful for the signal/slot system where you may not be able to specify
|
|
||||||
* parameters.
|
|
||||||
*/
|
|
||||||
bool CloseAllProjects();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the current application-wide tool
|
* @brief Set the current application-wide tool
|
||||||
@@ -523,11 +474,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
void SetStartupLocale();
|
void SetStartupLocale();
|
||||||
|
|
||||||
/**
|
|
||||||
* @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)
|
* @brief Adds a filename to the top of the recently opened projects list (or moves it if it already exists)
|
||||||
*/
|
*/
|
||||||
@@ -552,7 +498,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* @brief Internal function for saving a project to a file
|
* @brief Internal function for saving a project to a file
|
||||||
*/
|
*/
|
||||||
void SaveProjectInternal(Project *project, const QString &override_filename = QString());
|
void SaveProjectInternal(const QString &override_filename = QString());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieves the currently most active sequence for exporting
|
* @brief Retrieves the currently most active sequence for exporting
|
||||||
@@ -563,7 +509,7 @@ private:
|
|||||||
|
|
||||||
void SaveUnrecoveredList();
|
void SaveUnrecoveredList();
|
||||||
|
|
||||||
bool RevertProjectInternal(Project *p, bool by_opening_existing);
|
bool RevertProjectInternal(bool by_opening_existing);
|
||||||
|
|
||||||
void SaveRecentProjectsList();
|
void SaveRecentProjectsList();
|
||||||
|
|
||||||
@@ -582,7 +528,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* @brief List of currently open projects
|
* @brief List of currently open projects
|
||||||
*/
|
*/
|
||||||
QList<Project*> open_projects_;
|
Project *open_project_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Currently active tool
|
* @brief Currently active tool
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ void ProjectPanel::UpdateSubtitle()
|
|||||||
|
|
||||||
void ProjectPanel::SaveConnectedProject()
|
void ProjectPanel::SaveConnectedProject()
|
||||||
{
|
{
|
||||||
Core::instance()->SaveProject(this->project());
|
Core::instance()->SaveProject();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<ViewerOutput *> ProjectPanel::GetSelectedFootage() const
|
QVector<ViewerOutput *> ProjectPanel::GetSelectedFootage() const
|
||||||
|
|||||||
@@ -52,21 +52,16 @@ MainMenu::MainMenu(MainWindow *parent) :
|
|||||||
file_open_recent_menu_ = new Menu(file_menu_);
|
file_open_recent_menu_ = new Menu(file_menu_);
|
||||||
file_open_recent_separator_ = file_open_recent_menu_->addSeparator();
|
file_open_recent_separator_ = file_open_recent_menu_->addSeparator();
|
||||||
file_open_recent_clear_item_ = file_open_recent_menu_->AddItem("clearopenrecent", Core::instance(), &Core::ClearOpenRecentList);
|
file_open_recent_clear_item_ = file_open_recent_menu_->AddItem("clearopenrecent", Core::instance(), &Core::ClearOpenRecentList);
|
||||||
file_save_item_ = file_menu_->AddItem("saveproj", Core::instance(), &Core::SaveActiveProject, tr("Ctrl+S"));
|
file_save_item_ = file_menu_->AddItem("saveproj", Core::instance(), &Core::SaveProject, tr("Ctrl+S"));
|
||||||
file_save_as_item_ = file_menu_->AddItem("saveprojas", Core::instance(), &Core::SaveActiveProjectAs, tr("Ctrl+Shift+S"));
|
file_save_as_item_ = file_menu_->AddItem("saveprojas", Core::instance(), &Core::SaveProjectAs, tr("Ctrl+Shift+S"));
|
||||||
file_save_all_item_ = file_menu_->AddItem("saveallproj", Core::instance(), &Core::SaveAllProjects);
|
|
||||||
file_menu_->addSeparator();
|
file_menu_->addSeparator();
|
||||||
file_revert_item_ = file_menu_->AddItem("revert", Core::instance(), &Core::RevertActiveProject, tr("F12"));
|
file_revert_item_ = file_menu_->AddItem("revert", Core::instance(), &Core::RevertProject, tr("F12"));
|
||||||
file_menu_->addSeparator();
|
file_menu_->addSeparator();
|
||||||
file_import_item_ = file_menu_->AddItem("import", Core::instance(), &Core::DialogImportShow, tr("Ctrl+I"));
|
file_import_item_ = file_menu_->AddItem("import", Core::instance(), &Core::DialogImportShow, tr("Ctrl+I"));
|
||||||
file_menu_->addSeparator();
|
file_menu_->addSeparator();
|
||||||
file_export_menu_ = new Menu(file_menu_);
|
file_export_menu_ = new Menu(file_menu_);
|
||||||
file_export_media_item_ = file_export_menu_->AddItem("export", Core::instance(), &Core::DialogExportShow, tr("Ctrl+M"));
|
file_export_media_item_ = file_export_menu_->AddItem("export", Core::instance(), &Core::DialogExportShow, tr("Ctrl+M"));
|
||||||
file_menu_->addSeparator();
|
file_menu_->addSeparator();
|
||||||
file_close_project_item_ = file_menu_->AddItem("closeproj", Core::instance(), &Core::CloseActiveProject);
|
|
||||||
file_close_all_projects_item_ = file_menu_->AddItem("closeallproj", Core::instance(), static_cast<bool(Core::*)()>(&Core::CloseAllProjects));
|
|
||||||
file_close_all_except_item_ = file_menu_->AddItem("closeallexcept", Core::instance(), &Core::CloseAllExceptActiveProject);
|
|
||||||
file_menu_->addSeparator();
|
|
||||||
file_project_properties_item_ = file_menu_->AddItem("projectproperties", Core::instance(), &Core::DialogProjectPropertiesShow, tr("Shift+F10"));
|
file_project_properties_item_ = file_menu_->AddItem("projectproperties", Core::instance(), &Core::DialogProjectPropertiesShow, tr("Shift+F10"));
|
||||||
file_menu_->addSeparator();
|
file_menu_->addSeparator();
|
||||||
file_exit_item_ = file_menu_->AddItem("exit", parent, &MainWindow::close);
|
file_exit_item_ = file_menu_->AddItem("exit", parent, &MainWindow::close);
|
||||||
@@ -328,20 +323,13 @@ void MainMenu::FileMenuAboutToShow()
|
|||||||
|
|
||||||
file_save_item_->setEnabled(active_project);
|
file_save_item_->setEnabled(active_project);
|
||||||
file_save_as_item_->setEnabled(active_project);
|
file_save_as_item_->setEnabled(active_project);
|
||||||
file_close_project_item_->setEnabled(active_project);
|
|
||||||
file_close_all_projects_item_->setEnabled(active_project);
|
|
||||||
file_close_all_except_item_->setEnabled(active_project);
|
|
||||||
|
|
||||||
if (active_project) {
|
if (active_project) {
|
||||||
file_save_item_->setText(tr("&Save '%1'").arg(active_project->name()));
|
file_save_item_->setText(tr("&Save '%1'").arg(active_project->name()));
|
||||||
file_save_as_item_->setText(tr("Save '%1' &As").arg(active_project->name()));
|
file_save_as_item_->setText(tr("Save '%1' &As").arg(active_project->name()));
|
||||||
file_close_project_item_->setText(tr("Close '%1'").arg(active_project->name()));
|
|
||||||
file_close_all_except_item_->setText(tr("Close All Except '%1'").arg(active_project->name()));
|
|
||||||
} else {
|
} else {
|
||||||
file_save_item_->setText(tr("&Save Project"));
|
file_save_item_->setText(tr("&Save Project"));
|
||||||
file_save_as_item_->setText(tr("Save Project &As"));
|
file_save_as_item_->setText(tr("Save Project &As"));
|
||||||
file_close_project_item_->setText(tr("Close Project"));
|
|
||||||
file_close_all_except_item_->setText(tr("Close All Except Current Project"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -704,12 +692,10 @@ void MainMenu::Retranslate()
|
|||||||
file_open_item_->setText(tr("&Open Project"));
|
file_open_item_->setText(tr("&Open Project"));
|
||||||
file_open_recent_menu_->setTitle(tr("Open &Recent"));
|
file_open_recent_menu_->setTitle(tr("Open &Recent"));
|
||||||
file_open_recent_clear_item_->setText(tr("&Clear Recent List"));
|
file_open_recent_clear_item_->setText(tr("&Clear Recent List"));
|
||||||
file_save_all_item_->setText(tr("Sa&ve All Projects"));
|
|
||||||
file_revert_item_->setText(tr("Revert"));
|
file_revert_item_->setText(tr("Revert"));
|
||||||
file_import_item_->setText(tr("&Import..."));
|
file_import_item_->setText(tr("&Import..."));
|
||||||
file_export_menu_->setTitle(tr("&Export"));
|
file_export_menu_->setTitle(tr("&Export"));
|
||||||
file_export_media_item_->setText(tr("&Media..."));
|
file_export_media_item_->setText(tr("&Media..."));
|
||||||
file_close_all_projects_item_->setText(tr("Close All Projects"));
|
|
||||||
file_project_properties_item_->setText(tr("Project Properties"));
|
file_project_properties_item_->setText(tr("Project Properties"));
|
||||||
file_exit_item_->setText(tr("E&xit"));
|
file_exit_item_->setText(tr("E&xit"));
|
||||||
|
|
||||||
|
|||||||
@@ -202,14 +202,10 @@ private:
|
|||||||
QAction* file_open_recent_clear_item_;
|
QAction* file_open_recent_clear_item_;
|
||||||
QAction* file_save_item_;
|
QAction* file_save_item_;
|
||||||
QAction* file_save_as_item_;
|
QAction* file_save_as_item_;
|
||||||
QAction* file_save_all_item_;
|
|
||||||
QAction* file_revert_item_;
|
QAction* file_revert_item_;
|
||||||
QAction* file_import_item_;
|
QAction* file_import_item_;
|
||||||
Menu* file_export_menu_;
|
Menu* file_export_menu_;
|
||||||
QAction* file_export_media_item_;
|
QAction* file_export_media_item_;
|
||||||
QAction* file_close_project_item_;
|
|
||||||
QAction* file_close_all_projects_item_;
|
|
||||||
QAction* file_close_all_except_item_;
|
|
||||||
QAction* file_project_properties_item_;
|
QAction* file_project_properties_item_;
|
||||||
QAction* file_exit_item_;
|
QAction* file_exit_item_;
|
||||||
|
|
||||||
|
|||||||
@@ -431,7 +431,7 @@ void MainWindow::SelectFootage(const QVector<Footage *> &e)
|
|||||||
void MainWindow::closeEvent(QCloseEvent *e)
|
void MainWindow::closeEvent(QCloseEvent *e)
|
||||||
{
|
{
|
||||||
// Try to close all projects (this will return false if the user chooses not to close)
|
// Try to close all projects (this will return false if the user chooses not to close)
|
||||||
if (!Core::instance()->CloseAllProjects(false)) {
|
if (!Core::instance()->CloseProject(false)) {
|
||||||
e->ignore();
|
e->ignore();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -555,10 +555,7 @@ void MainWindow::TimelineCloseRequested()
|
|||||||
|
|
||||||
void MainWindow::ProjectCloseRequested()
|
void MainWindow::ProjectCloseRequested()
|
||||||
{
|
{
|
||||||
ProjectPanel* panel = static_cast<ProjectPanel*>(sender());
|
Core::instance()->CloseProject(true);
|
||||||
Project* p = panel->project();
|
|
||||||
|
|
||||||
Core::instance()->CloseProject(p, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::ViewerCloseRequested()
|
void MainWindow::ViewerCloseRequested()
|
||||||
|
|||||||
Reference in New Issue
Block a user