Files
oak-editor/oliveglobal.cpp
T

378 lines
11 KiB
C++

/***
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 <http://www.gnu.org/licenses/>.
***/
#include "oliveglobal.h"
#include "mainwindow.h"
#include "panels/panels.h"
#include "io/path.h"
#include "io/config.h"
#include "ui/mediaiconservice.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 "project/sequence.h"
#include <QMessageBox>
#include <QFileDialog>
#include <QAction>
#include <QApplication>
#include <QDebug>
std::unique_ptr<OliveGlobal> olive::Global;
QString olive::ActiveProjectFilename;
QString olive::AppName;
OliveGlobal::OliveGlobal() {
// sets current app name
QString version_id;
#ifdef GITHASH
version_id = QString(" | %1").arg(GITHASH);
#endif
olive::AppName = QString("Olive (February 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<QTranslator>(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;
open_project_worker(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::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::new_project() {
if (can_close_project()) {
// clear effects panel
panel_effect_controls->clear_effects(true);
// clear project contents (footage, sequences, etc.)
panel_project->new_project();
// clear undo stack
olive::UndoStack.clear();
// empty current project filename
update_project_filename("");
// full update of all panels
update_ui(false);
}
}
void OliveGlobal::open_project() {
QString fn = QFileDialog::getOpenFileName(olive::MainWindow, tr("Open Project..."), "", project_file_filter);
if (!fn.isEmpty() && can_close_project()) {
open_project_worker(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()) {
open_project_worker(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 (olive::MainWindow->isWindowModified()) {
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 (olive::ActiveSequence == nullptr) {
QMessageBox::information(olive::MainWindow,
tr("No active sequence"),
tr("Please open the sequence you wish to export."),
QMessageBox::Ok);
} else {
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)) {
open_project_worker(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
}
}
void OliveGlobal::save_autorecovery_file() {
if (olive::MainWindow->isWindowModified()) {
panel_project->save_project(true);
qInfo() << "Auto-recovery project saved";
}
}
void OliveGlobal::open_preferences() {
panel_sequence_viewer->pause();
panel_footage_viewer->pause();
PreferencesDialog pd(olive::MainWindow);
pd.setup_kbd_shortcuts(olive::MainWindow->menuBar());
pd.exec();
}
void OliveGlobal::set_sequence(SequencePtr s)
{
panel_effect_controls->clear_effects(true);
olive::ActiveSequence = s;
panel_sequence_viewer->set_main_sequence();
panel_timeline->update_sequence();
panel_timeline->setFocus();
}
void OliveGlobal::open_project_worker(const QString& fn, bool autorecovery) {
update_project_filename(fn);
panel_project->load_project(autorecovery);
olive::UndoStack.clear();
}
QIcon OliveGlobal::CreateIconFromSVG(const QString &path)
{
QIcon icon;
QPixmap normal(path);
icon.addPixmap(normal, QIcon::Normal, QIcon::On);
QPixmap disabled(normal.size());
disabled.fill(Qt::transparent);
// draw semi-transparent version of icon for the disabled variant
QPainter p(&disabled);
p.setOpacity(0.5);
p.drawPixmap(0, 0, normal);
p.end();
icon.addPixmap(disabled, QIcon::Disabled, QIcon::On);
return icon;
}
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<Clip*> selected_clips = olive::ActiveSequence->SelectedClips();
if (!selected_clips.isEmpty()) {
SpeedDialog 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();
}