/*** Olive - Non-Linear Video Editor Copyright (C) 2022 Olive Team Modifications Copyright (C) 2025 mikesolar 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 "autorecoverydialog.h" #include #include #include #include #include #include #include "core.h" #include "oakutil/filefunctions.h" namespace olive { #define super QDialog AutoRecoveryDialog::AutoRecoveryDialog(const QString &message, const QStringList &recoveries, bool autocheck_latest, QWidget *parent) : QDialog(parent) { init(message); populate_tree(recoveries, autocheck_latest); } void AutoRecoveryDialog::accept() { foreach (QTreeWidgetItem *checkable, checkable_items_) { if (checkable->checkState(0) == Qt::Checked) { QString filename = checkable->data(0, k_filename_role).toString(); Core::instance()->open_recovery_project(filename); } } super::accept(); } void AutoRecoveryDialog::init(const QString &header_text) { QVBoxLayout *layout = new QVBoxLayout(this); setWindowTitle(tr("Auto-Recovery")); layout->addWidget(new QLabel(header_text)); tree_widget_ = new QTreeWidget(); tree_widget_->setHeaderHidden(true); layout->addWidget(tree_widget_); QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); buttons->button(QDialogButtonBox::Ok)->setText(tr("Load")); connect(buttons, &QDialogButtonBox::accepted, this, &AutoRecoveryDialog::accept); connect(buttons, &QDialogButtonBox::rejected, this, &AutoRecoveryDialog::reject); layout->addWidget(buttons); } void AutoRecoveryDialog::populate_tree(const QStringList &recoveries, bool autocheck_latest) { // Each entry in `recoveries` is a directory with 1+ recovery projects in it QDir autorecovery_root(FileFunctions::get_auto_recovery_root()); foreach (const QString &recovery_folder, recoveries) { QDir recovery_dir(autorecovery_root.filePath(recovery_folder)); QString pretty_name; { // Retrieve pretty name QFile pretty_name_file( recovery_dir.filePath(QStringLiteral("realname.txt"))); if (pretty_name_file.open(QFile::ReadOnly)) { // Read pretty name that we should have written in the autorecovery process pretty_name = QString::fromUtf8(pretty_name_file.readAll()); pretty_name_file.close(); } if (pretty_name.isEmpty()) { // Fallback to just the UUID. While it won't mean much to the user, it's better than nothing. pretty_name = recovery_dir.dirName(); } } QTreeWidgetItem *top_level = new QTreeWidgetItem(tree_widget_); top_level->setText(0, pretty_name); { // Populate with recoveries QStringList entries = recovery_dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); for (int i = 0; i < entries.size(); i++) { const QString &entry = entries.at(i); if (entry.endsWith(QStringLiteral(".ove"), Qt::CaseInsensitive)) { QTreeWidgetItem *entry_item = new QTreeWidgetItem(top_level); bool ok; qint64 recovery_time = entry.left(entry.indexOf('.')).toLongLong(&ok); QString entry_name; if (ok) { // Set as time/date of recovery entry_name = QDateTime::fromSecsSinceEpoch(recovery_time) .toString(); } else { // Fallback if we couldn't discern a date from this entry_name = entry; } entry_item->setText(0, entry_name); entry_item->setData(0, k_filename_role, recovery_dir.filePath(entry)); // Allow to be checked, auto-checking the first entry entry_item->setCheckState( 0, (autocheck_latest && top_level->childCount() == 1) ? Qt::Checked : Qt::Unchecked); checkable_items_.append(entry_item); } } } } } }