From 2353c38e4e910705169f13049aecc7516a60fdf1 Mon Sep 17 00:00:00 2001 From: BrimsonBhin <40442071+BrimsonBhin@users.noreply.github.com> Date: Fri, 19 Apr 2019 20:37:15 -0700 Subject: [PATCH 1/7] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 47 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 27 +++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..fc0db0811 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,47 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG]" +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** +- Olive version: [e.g. Git hash from window title or Help > About] +- Source: [e.g. AppImage, Website etc.] +- Operating system: [e.g. Ubuntu 18.04 64-bit] +- CPU: [e.g. Intel i5-4300U] +- RAM: [e.g. 8GB] +- GPU: [e.g. NVIDIA Geforce GT 1030 2GB (Driver ver xxx.xx.xx)] + +### Output Log + +``` +[Paste output log] +``` + +### GDB/CDB Backtrace (for crashes) + +``` +[If you can reproduce this issue, try running Olive through GDB and retrieving a backtrace, then paste the backtrace here. Instructions are available in the Wiki on how to acquire this backtrace.] +``` + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..4195442a2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,27 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**I have read the following** +- [ ] The Olive Wiki +- [ ] Previous issues that include "FR" or "Feature Request" +- [ ] Olive's Project Tab + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Do you know any libraries or sources that can help the Olive Team include the feature?** + +**Additional context** +Add any other context or screenshots about the feature request here. From 3bdc3f7438d2ead2569d6c7383aac5bd2d163c09 Mon Sep 17 00:00:00 2001 From: BrimsonBhin <40442071+BrimsonBhin@users.noreply.github.com> Date: Fri, 19 Apr 2019 20:38:10 -0700 Subject: [PATCH 2/7] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index fc0db0811..b189e59e8 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,7 +1,7 @@ --- name: Bug report about: Create a report to help us improve -title: "[BUG]" +title: "[Bug]" labels: '' assignees: '' diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 4195442a2..bbbe2f1ea 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,7 +1,7 @@ --- name: Feature request about: Suggest an idea for this project -title: '' +title: "[Feature Request]" labels: '' assignees: '' From 0e31dbdb72010e634771de1db941c33b5536455f Mon Sep 17 00:00:00 2001 From: BrimsonBhin <40442071+BrimsonBhin@users.noreply.github.com> Date: Fri, 19 Apr 2019 20:42:43 -0700 Subject: [PATCH 3/7] Update issue templates --- .github/ISSUE_TEMPLATE/feature_request.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index bbbe2f1ea..11d81bb48 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -22,6 +22,7 @@ A clear and concise description of what you want to happen. A clear and concise description of any alternative solutions or features you've considered. **Do you know any libraries or sources that can help the Olive Team include the feature?** +List open-source libraries related to the feature. **Additional context** Add any other context or screenshots about the feature request here. From fa6409d4228bd6466234390ed375cb83491f9863 Mon Sep 17 00:00:00 2001 From: BrimsonBhin <40442071+BrimsonBhin@users.noreply.github.com> Date: Fri, 19 Apr 2019 20:44:15 -0700 Subject: [PATCH 4/7] Delete ISSUE_TEMPLATE.md --- ISSUE_TEMPLATE.md | 55 ----------------------------------------------- 1 file changed, 55 deletions(-) delete mode 100644 ISSUE_TEMPLATE.md diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md deleted file mode 100644 index 62e0d8064..000000000 --- a/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,55 +0,0 @@ -[If you are requesting a feature, please try to fill out all the information below. If you are reporting a bug, you can clear the template below.] - -### I have read the following - -- [ ] The [Olive Wiki](https://github.com/olive-editor/olive/wiki) - -- [ ] Previous issues that include ["FR"](https://github.com/olive-editor/olive/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+FR)or ["Feature Request"](https://github.com/olive-editor/olive/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+Feature+Request) - -- [ ] Olive's [Project Goals](https://github.com/olive-editor/olive/projects) - -### Detailed description of the feature request - -[Describe the feature request to the best of your ability. Do you know any libraries/sources that can help the Olive Team include the feature?] - -### Why should Olive include the feature? What are the benefits? - -[Explain the feature's importance to Olive and NLEs in general.] - ---- - -[If you are reporting a bug, please try to fill out all the information below. If you are requesting a feature, you can clear the template above.] - -### System Information - -**Olive version:** [e.g. Git hash from window title or Help > About] - -**Source:** [e.g. AppImage, Website etc.] - -**Operating system:** [e.g. Ubuntu 18.04 64-bit] - -**CPU:** [e.g. Intel i5-4300U] - -**RAM:** [e.g. 8GB] - -**GPU:** [e.g. NVIDIA Geforce GT 1030 2GB (Driver ver xxx.xx.xx)] - -### Detailed Description - -[Describe the issue you're having] - -### Steps to reproduce - -[Describe the steps to demonstrate the issue you're reporting] - -### Output Log - -``` -[Paste output log] -``` - -### GDB/CDB Backtrace (for crashes) - -``` -[If you can reproduce this issue, try running Olive through GDB and retrieving a backtrace, then paste the backtrace here. Instructions are available in the Wiki on how to acquire this backtrace.] -``` From dca99cdf80df58d59b2ce38591b3b5dd9f3ead01 Mon Sep 17 00:00:00 2001 From: BrimsonBhin <40442071+BrimsonBhin@users.noreply.github.com> Date: Fri, 19 Apr 2019 20:54:00 -0700 Subject: [PATCH 5/7] Update Month --- global/global.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global/global.cpp b/global/global.cpp index 9f7ada144..f956662ae 100644 --- a/global/global.cpp +++ b/global/global.cpp @@ -62,7 +62,7 @@ OliveGlobal::OliveGlobal() : version_id = QString(" | %1").arg(GITHASH); #endif - olive::AppName = QString("Olive (March 2019 | Alpha%1)").arg(version_id); + 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)"); From 9e6226df2922031bc8514cd7df29a0669d32cbb4 Mon Sep 17 00:00:00 2001 From: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Thu, 2 May 2019 21:35:43 +1000 Subject: [PATCH 6/7] Delete global.cpp --- global/global.cpp | 466 ---------------------------------------------- 1 file changed, 466 deletions(-) delete mode 100644 global/global.cpp diff --git a/global/global.cpp b/global/global.cpp deleted file mode 100644 index f956662ae..000000000 --- a/global/global.cpp +++ /dev/null @@ -1,466 +0,0 @@ -/*** - - 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(); -} From 389d0a84a98e27e001afff16daaf44f55e6cb787 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 2 May 2019 21:37:06 +1000 Subject: [PATCH 7/7] 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(); +}