mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
mobile: save changes from main event loop
When autosync to cloud was enabled, the old code would crash, because it synced to cloud from a signal handler, which executed the main loop when checking the cloud connection, which deleted the object which was causing the original signal. Or something like that. See discussion in #4119. To avoid such problems, send a signal via a 'QueuedConnection' from QMLManager to itself. The slot will be called once the signal handler terminates and the main event loop retakes control. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
2172e18298
commit
de313bd01a
2 changed files with 25 additions and 3 deletions
|
@ -602,6 +602,14 @@ void QMLManager::finishSetup()
|
||||||
// this could have brought in new cache directories, so make sure QML
|
// this could have brought in new cache directories, so make sure QML
|
||||||
// calls our getter function again and doesn't show us outdated information
|
// calls our getter function again and doesn't show us outdated information
|
||||||
emit cloudCacheListChanged();
|
emit cloudCacheListChanged();
|
||||||
|
|
||||||
|
// This is used to instruct the main-thread to sync the current state to disk/cloud.
|
||||||
|
// We must not sync to cloud from signal-handlers in the main thread, because cloud
|
||||||
|
// access runs the main event loop and that might delete the object that caused the
|
||||||
|
// signal. By using a connection of the "QueuedConnection" type, the signal will be
|
||||||
|
// queued and only executed once the signal handler finishes and the main event
|
||||||
|
// loop retakes control.
|
||||||
|
connect(this, &QMLManager::changesNeedSavingSignal, this, &QMLManager::saveUnsaved, Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
QMLManager::~QMLManager()
|
QMLManager::~QMLManager()
|
||||||
|
@ -1441,21 +1449,29 @@ void QMLManager::addDiveToTrip(int id, int tripId)
|
||||||
changesNeedSaving();
|
changesNeedSaving();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMLManager::changesNeedSaving(bool fromUndo)
|
void QMLManager::saveUnsaved()
|
||||||
{
|
{
|
||||||
|
// There might have been spurious signals, so let's check if there is anything to save first.
|
||||||
|
if (!unsavedChanges())
|
||||||
|
return;
|
||||||
|
|
||||||
// we no longer save right away on iOS because file access is so slow; on the other hand,
|
// we no longer save right away on iOS because file access is so slow; on the other hand,
|
||||||
// on Android the save as the user switches away doesn't seem to work... drat.
|
// on Android the save as the user switches away doesn't seem to work... drat.
|
||||||
// as a compromise for now we save just to local storage on Android right away (that appears
|
// as a compromise for now we save just to local storage on Android right away (that appears
|
||||||
// to be reasonably fast), but don't save at all (and only remember that we need to save things
|
// to be reasonably fast), but don't save at all (and only remember that we need to save things
|
||||||
// on iOS
|
// on iOS
|
||||||
// on all other platforms we just save the changes and be done with it
|
// on all other platforms we just save the changes and be done with it
|
||||||
mark_divelist_changed(true);
|
|
||||||
emit syncStateChanged();
|
|
||||||
#if defined(Q_OS_IOS)
|
#if defined(Q_OS_IOS)
|
||||||
saveChangesLocal();
|
saveChangesLocal();
|
||||||
#else
|
#else
|
||||||
saveChangesCloud(false);
|
saveChangesCloud(false);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMLManager::changesNeedSaving(bool fromUndo)
|
||||||
|
{
|
||||||
|
mark_divelist_changed(true);
|
||||||
|
emit syncStateChanged();
|
||||||
updateAllGlobalLists();
|
updateAllGlobalLists();
|
||||||
|
|
||||||
// provide a useful undo/redo notification
|
// provide a useful undo/redo notification
|
||||||
|
@ -1467,6 +1483,9 @@ void QMLManager::changesNeedSaving(bool fromUndo)
|
||||||
setNotificationText(msgFormat.arg(tr("Redo")).arg(tr("Undo: %1").arg(getRedoText())));
|
setNotificationText(msgFormat.arg(tr("Redo")).arg(tr("Undo: %1").arg(getRedoText())));
|
||||||
else
|
else
|
||||||
setNotificationText(msgFormat.arg(tr("Undo")).arg(getUndoText()));
|
setNotificationText(msgFormat.arg(tr("Undo")).arg(getUndoText()));
|
||||||
|
|
||||||
|
// Asl the main event loop to save the changes to disk
|
||||||
|
emit changesNeedSavingSignal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMLManager::openNoCloudRepo()
|
void QMLManager::openNoCloudRepo()
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#include "core/btdiscovery.h"
|
#include "core/btdiscovery.h"
|
||||||
#include "core/downloadfromdcthread.h"
|
#include "core/downloadfromdcthread.h"
|
||||||
|
@ -299,6 +300,7 @@ signals:
|
||||||
void restartDownloadSignal();
|
void restartDownloadSignal();
|
||||||
void syncStateChanged();
|
void syncStateChanged();
|
||||||
void passwordStateChanged();
|
void passwordStateChanged();
|
||||||
|
void changesNeedSavingSignal();
|
||||||
|
|
||||||
// From upload process
|
// From upload process
|
||||||
void uploadFinish(bool success, const QString &text);
|
void uploadFinish(bool success, const QString &text);
|
||||||
|
@ -306,6 +308,7 @@ signals:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void uploadFinishSlot(bool success, const QString &text, const QByteArray &html);
|
void uploadFinishSlot(bool success, const QString &text, const QByteArray &html);
|
||||||
|
void saveUnsaved();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue