mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-23 23:44:13 +02:00
Keep three crash-recovery snapshots instead of overwriting one
Discussion #598, reviving PR #654. The crash-recovery backup written every 20 minutes went to a single file. If the project was already in a bad state when a backup ran, that bad state replaced the only recovery copy. QETProject now writes the backups in turn to three KAutoSaveFile slots (BackupGenerations), so one bad write only replaces the oldest snapshot. Scope is crash recovery only; the opt-in autosave is unchanged. After a crash, the recovery prompt groups the snapshots by project and offers one row per project with a list to pick the snapshot to reopen, newest selected by default. The snapshots not picked are deleted. Ported onto current master: writeBackup() keeps the "skip if nothing changed" check (bugtracker #273) and offerBackupFiles() keeps its place after the stale-file filter and before the crash report (#901). Tested with the backup interval shortened to 4 s (test build only): after three changes, master holds one recovery file, overwritten each time; this branch holds three, with 4, 5 and 6 folios. After killing QET, the prompt lists the project; picking the oldest snapshot reopens 4 folios, the default reopens 6. Twice each. ctest 34/34 with and without KDE Frameworks; the carried-over KAutoSaveFile test passes in the nokde build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+29
-26
@@ -55,6 +55,7 @@
|
||||
#include <iostream>
|
||||
#define QUOTE(x) STRINGIFY(x)
|
||||
#define STRINGIFY(x) #x
|
||||
#include <QFileInfo>
|
||||
#include <QFontDatabase>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QRegularExpression>
|
||||
@@ -65,6 +66,9 @@
|
||||
#else
|
||||
# include <KAutoSaveFile>
|
||||
#endif
|
||||
#include "ui/backuprestoredialog.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef QET_ALLOW_OVERRIDE_CED_OPTION
|
||||
QString QETApp::m_overrided_common_elements_dir = QString();
|
||||
@@ -2839,48 +2843,47 @@ void QETApp::checkBackupFiles()
|
||||
/**
|
||||
@brief QETApp::offerBackupFiles
|
||||
Ask whether to reopen the recovery files left by a previous run, and
|
||||
open or discard them accordingly.
|
||||
open or discard them accordingly. A project can leave several recovery
|
||||
files, one per snapshot (@see QETProject::writeBackup): they are grouped
|
||||
by project, and the user picks which one to reopen, the newest by default.
|
||||
@param stale_files : the recovery files to offer
|
||||
*/
|
||||
void QETApp::offerBackupFiles(const QList<KAutoSaveFile *> &stale_files)
|
||||
{
|
||||
QString text;
|
||||
if(stale_files.size() == 1) {
|
||||
text.append(tr("<b>Le fichier de restauration suivant a été trouvé,<br>"
|
||||
"Voulez-vous l'ouvrir ?</b><br>"));
|
||||
} else {
|
||||
text.append(tr("<b>Les fichiers de restauration suivant on été trouvé,<br>"
|
||||
"Voulez-vous les ouvrir ?</b><br>"));
|
||||
//Group the snapshots by the project they recover, newest first.
|
||||
QHash<QString, QList<KAutoSaveFile *>> groups;
|
||||
for (KAutoSaveFile *kasf : stale_files) {
|
||||
groups[kasf->managedFile().path()].append(kasf);
|
||||
}
|
||||
for(const KAutoSaveFile *kasf : stale_files)
|
||||
{
|
||||
# ifdef Q_OS_WIN
|
||||
//Remove the first character '/' before the name of the drive
|
||||
text.append("<br>" + kasf->managedFile().path().remove(0,1));
|
||||
# else
|
||||
text.append("<br>" + kasf->managedFile().path());
|
||||
# endif
|
||||
for (auto &snapshots : groups) {
|
||||
std::sort(snapshots.begin(), snapshots.end(),
|
||||
[](KAutoSaveFile *a, KAutoSaveFile *b) {
|
||||
return QFileInfo(*a).lastModified()
|
||||
> QFileInfo(*b).lastModified();
|
||||
});
|
||||
}
|
||||
|
||||
//Open backup file
|
||||
if (QET::QetMessageBox::question(nullptr,
|
||||
tr("Fichier de restauration"),
|
||||
text,
|
||||
QMessageBox::Ok
|
||||
|QMessageBox::Cancel
|
||||
)
|
||||
== QMessageBox::Ok)
|
||||
BackupRestoreDialog dialog(groups, nullptr);
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
//The snapshots not picked are no longer needed.
|
||||
for (KAutoSaveFile *discarded : dialog.discardedFiles())
|
||||
{
|
||||
discarded->open(QIODevice::ReadWrite);
|
||||
delete discarded;
|
||||
}
|
||||
|
||||
const QList<KAutoSaveFile *> to_open = dialog.selectedFiles();
|
||||
//If there are open editors, find those that are visible
|
||||
if (diagramEditors().count())
|
||||
{
|
||||
diagramEditors().first()->setVisible(true);
|
||||
diagramEditors().first()->openBackupFiles(stale_files);
|
||||
diagramEditors().first()->openBackupFiles(to_open);
|
||||
}
|
||||
else
|
||||
{
|
||||
QETDiagramEditor *editor = new QETDiagramEditor();
|
||||
editor->openBackupFiles(stale_files);
|
||||
editor->openBackupFiles(to_open);
|
||||
}
|
||||
}
|
||||
else //Clear backup file
|
||||
|
||||
Reference in New Issue
Block a user