mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-25 00:14:15 +02:00
Fix bugtracker #273: skip crash-recovery backups of an unchanged project
writeBackup() rebuilds the whole project's XML with toXml() on the GUI thread before handing the file write to a worker thread. On a big project that freezes the interface for seconds (bugtracker #273, and #329, where the interval was raised from 2 to 20 minutes to make it rarer). It ran right after every project was opened, and then every 20 minutes whether or not anything had changed. Only write a backup when something changed since the last one: the undo stack moved, setModified(true) was called, or the embedded element or title block collections changed. A project just opened from a file starts clean, since the file is already what a crash would restore. New projects and projects restored from a backup are backed up at once, as before. Measured on examples/industrial.qet (50 folios), each backup blocks the GUI thread for about 0.28 s on a fast machine; with a 2 s test interval, the old code backed up on every tick, the new code only after a change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -132,6 +132,9 @@ QETProject::QETProject(const QString &path, QObject *parent) :
|
||||
return;
|
||||
}
|
||||
|
||||
//The file just read already holds everything a crash could lose, so
|
||||
//there is nothing to back up until the project is changed.
|
||||
m_backup_needed = false;
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -258,6 +261,19 @@ void QETProject::init()
|
||||
m_undo_stack = new QUndoStack(this);
|
||||
connect(m_undo_stack, &QUndoStack::cleanChanged, this, &QETProject::undoStackChanged);
|
||||
|
||||
//What counts as a change for writeBackup(): the undo stack moving,
|
||||
//setModified(true), and the embedded collections, which can change
|
||||
//without going through either.
|
||||
const auto backup_needed = [this]() { m_backup_needed = true; };
|
||||
connect(m_undo_stack, &QUndoStack::indexChanged, this, backup_needed);
|
||||
connect(&m_titleblocks_collection, &TitleBlockTemplatesCollection::changed, this, backup_needed);
|
||||
connect(&m_titleblocks_collection, &TitleBlockTemplatesCollection::aboutToRemove, this, backup_needed);
|
||||
connect(m_elements_collection, &XmlElementCollection::elementAdded, this, backup_needed);
|
||||
connect(m_elements_collection, &XmlElementCollection::elementChanged, this, backup_needed);
|
||||
connect(m_elements_collection, &XmlElementCollection::elementRemoved, this, backup_needed);
|
||||
connect(m_elements_collection, &XmlElementCollection::directorieAdded, this, backup_needed);
|
||||
connect(m_elements_collection, &XmlElementCollection::directoryRemoved, this, backup_needed);
|
||||
|
||||
m_save_backup_timer.setInterval(BACKUP_INTERVAL);
|
||||
connect(&m_save_backup_timer, &QTimer::timeout, this, &QETProject::writeBackup);
|
||||
m_save_backup_timer.start();
|
||||
@@ -1564,6 +1580,9 @@ void QETProject::diagramOrderChanged(int old_index, int new_index) {
|
||||
Mark this project as modified and emit the projectModified() signal.
|
||||
*/
|
||||
void QETProject::setModified(bool modified) {
|
||||
if (modified) {
|
||||
m_backup_needed = true;
|
||||
}
|
||||
if (m_modified != modified) {
|
||||
m_modified = modified;
|
||||
emit projectModified(this, m_modified);
|
||||
@@ -2146,6 +2165,12 @@ void QETProject::writeBackup()
|
||||
//both would write through &m_backup_file on different threads.
|
||||
if (m_backup_future.isRunning())
|
||||
return;
|
||||
//toXml() walks the whole project on the GUI thread, which freezes
|
||||
//big projects for seconds (bugtracker #273, #329). A backup of an
|
||||
//unchanged project would be identical to the last one, so skip it.
|
||||
if (!m_backup_needed)
|
||||
return;
|
||||
m_backup_needed = false;
|
||||
//Capture the document by value (implicitly shared, so cheap): the
|
||||
//Qt5-style QtConcurrent::run(function, reference-args) call did not
|
||||
//survive the Qt6 API change, a lambda behaves identically on both.
|
||||
|
||||
Reference in New Issue
Block a user