Perform autosaves on a background thread rather than blocking the UI
This commit is contained in:
parent
44b76d38d2
commit
d253388c8e
2 changed files with 47 additions and 31 deletions
|
@ -32,6 +32,7 @@
|
|||
#include "subtitle_format.h"
|
||||
#include "text_selection_controller.h"
|
||||
|
||||
#include <libaegisub/dispatch.h>
|
||||
#include <libaegisub/format_path.h>
|
||||
#include <libaegisub/fs.h>
|
||||
#include <libaegisub/path.h>
|
||||
|
@ -146,27 +147,18 @@ SubsController::SubsController(agi::Context *context)
|
|||
: context(context)
|
||||
, undo_connection(context->ass->AddUndoManager(&SubsController::OnCommit, this))
|
||||
, text_selection_connection(context->textSelectionController->AddSelectionListener(&SubsController::OnTextSelectionChanged, this))
|
||||
, autosave_queue(agi::dispatch::Create())
|
||||
{
|
||||
autosave_timer_changed(&autosave_timer);
|
||||
OPT_SUB("App/Auto/Save", [=] { autosave_timer_changed(&autosave_timer); });
|
||||
OPT_SUB("App/Auto/Save Every Seconds", [=] { autosave_timer_changed(&autosave_timer); });
|
||||
|
||||
autosave_timer.Bind(wxEVT_TIMER, [=](wxTimerEvent&) {
|
||||
try {
|
||||
auto fn = AutoSave();
|
||||
if (!fn.empty())
|
||||
context->frame->StatusTimeout(fmt_tl("File backup saved as \"%s\".", fn));
|
||||
}
|
||||
catch (const agi::Exception& err) {
|
||||
context->frame->StatusTimeout(to_wx("Exception when attempting to autosave file: " + err.GetMessage()));
|
||||
}
|
||||
catch (...) {
|
||||
context->frame->StatusTimeout("Unhandled exception when attempting to autosave file.");
|
||||
}
|
||||
});
|
||||
autosave_timer.Bind(wxEVT_TIMER, [=](wxTimerEvent&) { AutoSave(); });
|
||||
}
|
||||
|
||||
SubsController::~SubsController() { }
|
||||
SubsController::~SubsController() {
|
||||
// Make sure there are no autosaves in progress
|
||||
autosave_queue->Sync([]{ });
|
||||
}
|
||||
|
||||
void SubsController::SetSelectionController(SelectionController *selection_controller) {
|
||||
active_line_connection = context->selectionController->AddActiveLineListener(&SubsController::OnActiveLineChanged, this);
|
||||
|
@ -260,26 +252,43 @@ int SubsController::TryToClose(bool allow_cancel) const {
|
|||
return result;
|
||||
}
|
||||
|
||||
agi::fs::path SubsController::AutoSave() {
|
||||
void SubsController::AutoSave() {
|
||||
if (commit_id == autosaved_commit_id)
|
||||
return "";
|
||||
return;
|
||||
|
||||
auto path = config::path->Decode(OPT_GET("Path/Auto/Save")->GetString());
|
||||
if (path.empty())
|
||||
path = filename.parent_path();
|
||||
|
||||
agi::fs::CreateDirectory(path);
|
||||
auto directory = config::path->Decode(OPT_GET("Path/Auto/Save")->GetString());
|
||||
if (directory.empty())
|
||||
directory = filename.parent_path();
|
||||
|
||||
auto name = filename.filename();
|
||||
if (name.empty())
|
||||
name = "Untitled";
|
||||
|
||||
path /= agi::format("%s.%s.AUTOSAVE.ass", name.string(), agi::util::strftime("%Y-%m-%d-%H-%M-%S"));
|
||||
|
||||
SubtitleFormat::GetWriter(path)->WriteFile(context->ass.get(), path, 0);
|
||||
autosaved_commit_id = commit_id;
|
||||
auto frame = context->frame;
|
||||
auto subs_copy = new AssFile(*context->ass);
|
||||
autosave_queue->Async([subs_copy, name, directory, frame] {
|
||||
wxString msg;
|
||||
std::unique_ptr<AssFile> subs(subs_copy);
|
||||
|
||||
return path;
|
||||
try {
|
||||
agi::fs::CreateDirectory(directory);
|
||||
auto path = directory / agi::format("%s.%s.AUTOSAVE.ass", name.string(),
|
||||
agi::util::strftime("%Y-%m-%d-%H-%M-%S"));
|
||||
SubtitleFormat::GetWriter(path)->WriteFile(subs.get(), path, 0);
|
||||
msg = fmt_tl("File backup saved as \"%s\".", path);
|
||||
}
|
||||
catch (const agi::Exception& err) {
|
||||
msg = to_wx("Exception when attempting to autosave file: " + err.GetMessage());
|
||||
}
|
||||
catch (...) {
|
||||
msg = "Unhandled exception when attempting to autosave file.";
|
||||
}
|
||||
|
||||
agi::dispatch::Main().Async([frame, msg] {
|
||||
frame->StatusTimeout(msg);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
bool SubsController::CanSave() const {
|
||||
|
|
|
@ -22,7 +22,12 @@
|
|||
#include <wx/timer.h>
|
||||
|
||||
class SelectionController;
|
||||
namespace agi { struct Context; }
|
||||
namespace agi {
|
||||
namespace dispatch {
|
||||
class Queue;
|
||||
}
|
||||
struct Context;
|
||||
}
|
||||
struct AssFileCommit;
|
||||
struct ProjectProperties;
|
||||
|
||||
|
@ -47,6 +52,9 @@ class SubsController {
|
|||
/// Timer for triggering autosaves
|
||||
wxTimer autosave_timer;
|
||||
|
||||
/// Queue which autosaves are performed on
|
||||
std::unique_ptr<agi::dispatch::Queue> autosave_queue;
|
||||
|
||||
/// A new file has been opened (filename)
|
||||
agi::signal::Signal<agi::fs::path> FileOpen;
|
||||
/// The file has been saved
|
||||
|
@ -58,6 +66,9 @@ class SubsController {
|
|||
/// Set the filename, updating things like the MRU and last used path
|
||||
void SetFileName(agi::fs::path const& file);
|
||||
|
||||
/// Autosave the file if there have been any chances since the last autosave
|
||||
void AutoSave();
|
||||
|
||||
void OnCommit(AssFileCommit c);
|
||||
void OnActiveLineChanged();
|
||||
void OnSelectionChanged();
|
||||
|
@ -97,10 +108,6 @@ public:
|
|||
/// @return wxYES, wxNO or wxCANCEL (note: all three are true in a boolean context)
|
||||
int TryToClose(bool allow_cancel = true) const;
|
||||
|
||||
/// @brief Autosave the file if there have been any chances since the last autosave
|
||||
/// @return File name used or empty if no save was performed
|
||||
agi::fs::path AutoSave();
|
||||
|
||||
/// Can the file be saved in its current format?
|
||||
bool CanSave() const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue