From 389d0a84a98e27e001afff16daaf44f55e6cb787 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 2 May 2019 21:37:06 +1000 Subject: [PATCH] Revert "Delete global.cpp" This reverts commit 9e6226df2922031bc8514cd7df29a0669d32cbb4. --- global/global.cpp | 466 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 466 insertions(+) create mode 100644 global/global.cpp diff --git a/global/global.cpp b/global/global.cpp new file mode 100644 index 000000000..f956662ae --- /dev/null +++ b/global/global.cpp @@ -0,0 +1,466 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#include "global/global.h" + +#include +#include +#include +#include +#include +#include + +#include "panels/panels.h" +#include "global/path.h" +#include "global/config.h" +#include "rendering/audio.h" +#include "dialogs/demonotice.h" +#include "dialogs/preferencesdialog.h" +#include "dialogs/exportdialog.h" +#include "dialogs/debugdialog.h" +#include "dialogs/aboutdialog.h" +#include "dialogs/speeddialog.h" +#include "dialogs/actionsearch.h" +#include "dialogs/loaddialog.h" +#include "dialogs/autocutsilencedialog.h" +#include "project/loadthread.h" +#include "timeline/sequence.h" +#include "ui/mediaiconservice.h" +#include "ui/mainwindow.h" +#include "ui/updatenotification.h" +#include "undo/undostack.h" + +std::unique_ptr olive::Global; +QString olive::ActiveProjectFilename; +QString olive::AppName; + +OliveGlobal::OliveGlobal() : + changed_since_last_autorecovery(false) +{ + // sets current app name + QString version_id; + + // if available, append the current Git hash (defined by `qmake` and the Makefile) +#ifdef GITHASH + version_id = QString(" | %1").arg(GITHASH); +#endif + + olive::AppName = QString("Olive (April 2019 | Alpha%1)").arg(version_id); + + // set the file filter used in all file dialogs pertaining to Olive project files. + project_file_filter = tr("Olive Project %1").arg("(*.ove)"); + + // set default value + enable_load_project_on_init = false; + + // alloc QTranslator + translator = std::unique_ptr(new QTranslator()); +} + +const QString &OliveGlobal::get_project_file_filter() { + return project_file_filter; +} + +void OliveGlobal::update_project_filename(const QString &s) { + // set filename to s + olive::ActiveProjectFilename = s; + + // update main window title to reflect new project filename + olive::MainWindow->updateTitle(); +} + +void OliveGlobal::check_for_autorecovery_file() { + QString data_dir = get_data_path(); + if (!data_dir.isEmpty()) { + // detect auto-recovery file + autorecovery_filename = data_dir + "/autorecovery.ove"; + if (QFile::exists(autorecovery_filename)) { + if (QMessageBox::question(nullptr, + tr("Auto-recovery"), + tr("Olive didn't close properly and an autorecovery file " + "was detected. Would you like to open it?"), + QMessageBox::Yes, + QMessageBox::No) == QMessageBox::Yes) { + enable_load_project_on_init = false; + OpenProjectWorker(autorecovery_filename, true); + } + } + autorecovery_timer.setInterval(60000); + QObject::connect(&autorecovery_timer, SIGNAL(timeout()), this, SLOT(save_autorecovery_file())); + autorecovery_timer.start(); + } +} + +void OliveGlobal::set_rendering_state(bool rendering) { + audio_rendering = rendering; + if (rendering) { + autorecovery_timer.stop(); + } else { + autorecovery_timer.start(); + } +} + +void OliveGlobal::set_modified(bool modified) +{ + olive::MainWindow->setWindowModified(modified); + changed_since_last_autorecovery = modified; +} + +bool OliveGlobal::is_modified() +{ + return olive::MainWindow->isWindowModified(); +} + +void OliveGlobal::load_project_on_launch(const QString& s) { + olive::ActiveProjectFilename = s; + enable_load_project_on_init = true; +} + +QString OliveGlobal::get_recent_project_list_file() { + return get_data_dir().filePath("recents"); +} + +void OliveGlobal::load_translation_from_config() { + QString language_file = olive::CurrentRuntimeConfig.external_translation_file.isEmpty() ? + olive::CurrentConfig.language_file : + olive::CurrentRuntimeConfig.external_translation_file; + + // clear runtime language file so if the user sets a different language, we won't load it next time + olive::CurrentRuntimeConfig.external_translation_file.clear(); + + // remove current translation if there is one + QApplication::removeTranslator(translator.get()); + + if (!language_file.isEmpty()) { + + // translation files are stored relative to app path (see GitHub issue #454) + QString full_language_path = QDir(get_app_path()).filePath(language_file); + + // load translation file + if (QFileInfo::exists(full_language_path) + && translator->load(full_language_path)) { + QApplication::installTranslator(translator.get()); + } else { + qWarning() << "Failed to load translation file" << full_language_path << ". No language will be loaded."; + } + } +} + +void OliveGlobal::SetNativeStyling(QWidget *w) +{ +#ifdef Q_OS_WIN + w->setStyleSheet(""); + w->setPalette(w->style()->standardPalette()); + w->setStyle(QStyleFactory::create("windowsvista")); +#endif +} + +void OliveGlobal::LoadProject(const QString &fn, bool autorecovery) +{ + // QSortFilterProxyModels are not thread-safe, and as we'll be loading in another thread, leaving it connected + // can cause glitches in its presentation. Therefore for the duration of the loading process, we disconnect it, + // and reconnect it later once the loading is complete. + + panel_project->DisconnectFilterToModel(); + + LoadDialog ld(olive::MainWindow); + + ld.open(); + + LoadThread* lt = new LoadThread(fn, autorecovery); + connect(&ld, SIGNAL(cancel()), lt, SLOT(cancel())); + connect(lt, SIGNAL(success()), &ld, SLOT(accept())); + connect(lt, SIGNAL(error()), &ld, SLOT(reject())); + connect(lt, SIGNAL(error()), this, SLOT(new_project())); + connect(lt, SIGNAL(report_progress(int)), &ld, SLOT(setValue(int))); + lt->start(); + + panel_project->ConnectFilterToModel(); +} + +void OliveGlobal::ClearProject() +{ + // clear graph editor + panel_graph_editor->set_row(nullptr); + + // clear effects panel + panel_effect_controls->Clear(true); + + // clear existing project + olive::Global->set_sequence(nullptr); + panel_footage_viewer->set_media(nullptr); + + // clear project contents (footage, sequences, etc.) + panel_project->clear(); + + // clear undo stack + olive::UndoStack.clear(); + + // empty current project filename + update_project_filename(""); + + // full update of all panels + update_ui(false); + + // set to unmodified + olive::Global->set_modified(false); +} + +void OliveGlobal::ImportProject(const QString &fn) +{ + LoadProject(fn, false); + set_modified(true); +} + +void OliveGlobal::new_project() { + if (can_close_project()) { + ClearProject(); + } +} + +void OliveGlobal::OpenProject() { + QString fn = QFileDialog::getOpenFileName(olive::MainWindow, tr("Open Project..."), "", project_file_filter); + if (!fn.isEmpty() && can_close_project()) { + OpenProjectWorker(fn, false); + } +} + +void OliveGlobal::open_recent(int index) { + QString recent_url = recent_projects.at(index); + if (!QFile::exists(recent_url)) { + if (QMessageBox::question( + olive::MainWindow, + tr("Missing recent project"), + tr("The project '%1' no longer exists. Would you like to remove it from the recent projects list?").arg(recent_url), + QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) { + recent_projects.removeAt(index); + panel_project->save_recent_projects(); + } + } else if (can_close_project()) { + OpenProjectWorker(recent_url, false); + } +} + +bool OliveGlobal::save_project_as() { + QString fn = QFileDialog::getSaveFileName(olive::MainWindow, tr("Save Project As..."), "", project_file_filter); + if (!fn.isEmpty()) { + if (!fn.endsWith(".ove", Qt::CaseInsensitive)) { + fn += ".ove"; + } + update_project_filename(fn); + panel_project->save_project(false); + return true; + } + return false; +} + +bool OliveGlobal::save_project() { + if (olive::ActiveProjectFilename.isEmpty()) { + return save_project_as(); + } else { + panel_project->save_project(false); + return true; + } +} + +bool OliveGlobal::can_close_project() { + if (is_modified()) { + QMessageBox* m = new QMessageBox( + QMessageBox::Question, + tr("Unsaved Project"), + tr("This project has changed since it was last saved. Would you like to save it before closing?"), + QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel, + olive::MainWindow + ); + m->setWindowModality(Qt::WindowModal); + int r = m->exec(); + delete m; + if (r == QMessageBox::Yes) { + return save_project(); + } else if (r == QMessageBox::Cancel) { + return false; + } + } + return true; +} + +void OliveGlobal::open_export_dialog() { + if (CheckForActiveSequence()) { + ExportDialog e(olive::MainWindow); + e.exec(); + } +} + +void OliveGlobal::finished_initialize() { + if (enable_load_project_on_init) { + + // if a project was set as a command line argument, we load it here + if (QFileInfo::exists(olive::ActiveProjectFilename)) { + OpenProjectWorker(olive::ActiveProjectFilename, false); + } else { + QMessageBox::critical(olive::MainWindow, + tr("Missing Project File"), + tr("Specified project '%1' does not exist.").arg(olive::ActiveProjectFilename), + QMessageBox::Ok); + update_project_filename(nullptr); + } + + enable_load_project_on_init = false; + + } else { + // if we are not loading a project on launch and are running a release build, open the demo notice dialog +#ifndef QT_DEBUG + DemoNotice* d = new DemoNotice(olive::MainWindow); + connect(d, SIGNAL(finished(int)), d, SLOT(deleteLater())); + d->open(); +#endif + } + + // Check for updates + olive::update_notifier.check(); +} + +void OliveGlobal::save_autorecovery_file() { + if (changed_since_last_autorecovery) { + panel_project->save_project(true); + + changed_since_last_autorecovery = false; + + qInfo() << "Auto-recovery project saved"; + } +} + +void OliveGlobal::open_preferences() { + panel_sequence_viewer->pause(); + panel_footage_viewer->pause(); + + PreferencesDialog pd(olive::MainWindow); + pd.exec(); +} + +void OliveGlobal::set_sequence(SequencePtr s) +{ + panel_graph_editor->set_row(nullptr); + panel_effect_controls->Clear(true); + + olive::ActiveSequence = s; + panel_sequence_viewer->set_main_sequence(); + panel_timeline->update_sequence(); + panel_timeline->setFocus(); +} + +void OliveGlobal::OpenProjectWorker(QString fn, bool autorecovery) { + ClearProject(); + update_project_filename(fn); + LoadProject(fn, autorecovery); + olive::UndoStack.clear(); +} + +bool OliveGlobal::CheckForActiveSequence(bool show_msg) +{ + if (olive::ActiveSequence == nullptr) { + + if (show_msg) { + QMessageBox::information(olive::MainWindow, + tr("No active sequence"), + tr("Please open the sequence to perform this action."), + QMessageBox::Ok); + } + + return false; + } + return true; +} + +void OliveGlobal::undo() { + // workaround to prevent crash (and also users should never need to do this) + if (!panel_timeline->importing) { + olive::UndoStack.undo(); + update_ui(true); + } +} + +void OliveGlobal::redo() { + // workaround to prevent crash (and also users should never need to do this) + if (!panel_timeline->importing) { + olive::UndoStack.redo(); + update_ui(true); + } +} + +void OliveGlobal::paste() { + if (olive::ActiveSequence != nullptr) { + panel_timeline->paste(false); + } +} + +void OliveGlobal::paste_insert() { + if (olive::ActiveSequence != nullptr) { + panel_timeline->paste(true); + } +} + +void OliveGlobal::open_about_dialog() { + AboutDialog a(olive::MainWindow); + a.exec(); +} + +void OliveGlobal::open_debug_log() { + olive::DebugDialog->show(); +} + +void OliveGlobal::open_speed_dialog() { + if (olive::ActiveSequence != nullptr) { + + QVector selected_clips = olive::ActiveSequence->SelectedClips(); + + if (!selected_clips.isEmpty()) { + SpeedDialog s(olive::MainWindow, selected_clips); + s.exec(); + } + } +} + +void OliveGlobal::open_autocut_silence_dialog() { + if (CheckForActiveSequence()) { + + QVector selected_clips = olive::ActiveSequence->SelectedClipIndexes(); + + if (selected_clips.isEmpty()) { + QMessageBox::critical(olive::MainWindow, + tr("No clips selected"), + tr("Select the clips you wish to auto-cut"), + QMessageBox::Ok); + } else { + AutoCutSilenceDialog s(olive::MainWindow, selected_clips); + s.exec(); + } + + } +} + +void OliveGlobal::clear_undo_stack() { + olive::UndoStack.clear(); +} + +void OliveGlobal::open_action_search() { + ActionSearch as(olive::MainWindow); + as.exec(); +}