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:
itsmattkc
2023-02-08 12:15:05 -08:00
parent c322bb6463
commit 70d34c674b
6 changed files with 129 additions and 391 deletions
+114 -301
View File
@@ -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(new Project());
AddOpenProject(already_open);
return;
}
} }
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,9 +502,7 @@ 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();
}
} }
} }
@@ -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,65 +939,63 @@ 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;
// Write human-readable real name so it's not just a UUID // Write human-readable real name so it's not just a UUID
{ {
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();
} }
int64_t max_recoveries_per_file = OLIVE_CONFIG("AutorecoveryMaximum").toLongLong(); int64_t max_recoveries_per_file = OLIVE_CONFIG("AutorecoveryMaximum").toLongLong();
// Since we write an extra file, increment total allowed files by 1 // Since we write an extra file, increment total allowed files by 1
max_recoveries_per_file++; max_recoveries_per_file++;
// Delete old entries // Delete old entries
QStringList recovery_files = project_autorecovery_dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name); QStringList recovery_files = project_autorecovery_dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name);
while (recovery_files.size() > max_recoveries_per_file) { while (recovery_files.size() > max_recoveries_per_file) {
bool deleted = false; bool deleted = false;
for (int i=0; i<recovery_files.size(); i++) { for (int i=0; i<recovery_files.size(); i++) {
const QString& f = recovery_files.at(i); const QString& f = recovery_files.at(i);
if (f.endsWith(QStringLiteral(".ove"), Qt::CaseInsensitive)) { if (f.endsWith(QStringLiteral(".ove"), Qt::CaseInsensitive)) {
QString delete_full_path = project_autorecovery_dir.filePath(f); QString delete_full_path = project_autorecovery_dir.filePath(f);
qDebug() << "Deleted old recovery:" << delete_full_path; qDebug() << "Deleted old recovery:" << delete_full_path;
QFile::remove(delete_full_path); QFile::remove(delete_full_path);
recovery_files.removeAt(i); recovery_files.removeAt(i);
deleted = true; deleted = true;
break;
}
}
if (!deleted) {
// For some reason none of the files were deletable. Break so we don't end up in
// an infinite loop.
break; break;
} }
} }
} else {
QMessageBox::critical(main_window_, tr("Auto-Recovery Error"), if (!deleted) {
tr("Failed to save auto-recovery to \"%1\". " // For some reason none of the files were deletable. Break so we don't end up in
"Olive may not have permission to this directory.") // an infinite loop.
.arg(project_autorecovery_dir.absolutePath())); break;
}
} }
} else {
QMessageBox::critical(main_window_, tr("Auto-Recovery Error"),
tr("Failed to save auto-recovery to \"%1\". "
"Olive may not have permission to this directory.")
.arg(project_autorecovery_dir.absolutePath()));
} }
} }
@@ -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,133 +1441,54 @@ 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) {
} QMessageBox mb(main_window_);
bool Core::CloseProject(Project* p, bool auto_open_new, CloseProjectBehavior &confirm_behavior) mb.setWindowModality(Qt::WindowModal);
{ mb.setIcon(QMessageBox::Question);
for (int i=0;i<open_projects_.size();i++) { mb.setWindowTitle(tr("Unsaved Changes"));
if (open_projects_.at(i) == p) { mb.setText(tr("The project '%1' has unsaved changes. Would you like to save them?")
.arg(open_project_->name()));
if (p->is_modified() && confirm_behavior != kCloseProjectDontSave) { QPushButton* yes_btn = mb.addButton(tr("Save"), QMessageBox::YesRole);
bool save_this_project; mb.addButton(tr("Don't Save"), QMessageBox::NoRole);
if (confirm_behavior == kCloseProjectAsk || confirm_behavior == kCloseProjectOnlyOne) { QPushButton* cancel_btn = mb.addButton(QMessageBox::Cancel);
QMessageBox mb(main_window_);
mb.setWindowModality(Qt::WindowModal); mb.exec();
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);
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);
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);
mb.exec();
if (mb.clickedButton() == cancel_btn) {
// Stop closing projects if the user clicked cancel
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);
} else {
// We must be saving this project
save_this_project = true;
}
if (save_this_project && !SaveProject(p)) {
// The save failed, stop closing projects
return false;
}
if (mb.clickedButton() == cancel_btn) {
// Stop closing projects if the user clicked cancel
return false;
} }
// For safety, the undo stack is cleared so no commands try to affect a freed project if (mb.clickedButton() == yes_btn && !SaveProject()) {
undo_stack_.clear(); // The save failed, stop closing projects
return false;
disconnect(p, &Project::ModifiedChanged, this, &Core::ProjectWasModified); }
emit ProjectClosed(p);
open_projects_.removeAt(i);
delete p;
break;
} }
// For safety, the undo stack is cleared so no commands try to affect a freed project
undo_stack_.clear();
disconnect(open_project_, &Project::ModifiedChanged, this, &Core::ProjectWasModified);
emit ProjectClosed(open_project_);
delete open_project_;
open_project_ = nullptr;
} }
// 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
View File
@@ -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
+1 -1
View File
@@ -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
+3 -17
View File
@@ -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"));
-4
View File
@@ -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_;
+2 -5
View File
@@ -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()