fix: run restore in background thread to prevent GUI crash
Restore was blocking the main thread via popen(), causing the GUI to freeze and crash. Now runs rsync in a separate thread like backup.
This commit is contained in:
+57
-12
@@ -628,9 +628,20 @@ gboolean MainWindow::on_file_button_press(GtkWidget*, GdkEventButton* event, gpo
|
|||||||
g_signal_connect_data(restore_item, "activate", G_CALLBACK(+[](GtkWidget*, gpointer d) {
|
g_signal_connect_data(restore_item, "activate", G_CALLBACK(+[](GtkWidget*, gpointer d) {
|
||||||
auto* c = static_cast<RestoreCtx*>(d);
|
auto* c = static_cast<RestoreCtx*>(d);
|
||||||
c->self->show_sudo_dialog([c](const std::string& pw) {
|
c->self->show_sudo_dialog([c](const std::string& pw) {
|
||||||
std::vector<std::string> files = {c->path};
|
struct Ctx { MainWindow* self; std::string path; std::string password; };
|
||||||
c->self->snapshots_.restore_selected(c->self->current_snapshot_, files, pw);
|
auto* ctx = new Ctx{c->self, c->path, pw};
|
||||||
c->self->tray_.show_notification("x3-Backup", "File restored: " + c->path);
|
g_thread_new("restore", [](gpointer data) -> gpointer {
|
||||||
|
auto* cx = static_cast<Ctx*>(data);
|
||||||
|
std::vector<std::string> files = {cx->path};
|
||||||
|
cx->self->snapshots_.restore_selected(cx->self->current_snapshot_, files, cx->password);
|
||||||
|
g_idle_add([](gpointer d) -> gboolean {
|
||||||
|
auto* cx2 = static_cast<Ctx*>(d);
|
||||||
|
cx2->self->tray_.show_notification("x3-Backup", "File restored: " + cx2->path);
|
||||||
|
delete cx2;
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}, cx);
|
||||||
|
return nullptr;
|
||||||
|
}, ctx);
|
||||||
});
|
});
|
||||||
delete c;
|
delete c;
|
||||||
}), ctx, nullptr, (GConnectFlags)0);
|
}), ctx, nullptr, (GConnectFlags)0);
|
||||||
@@ -657,9 +668,20 @@ gboolean MainWindow::on_file_button_press(GtkWidget*, GdkEventButton* event, gpo
|
|||||||
g_signal_connect_data(restore_item, "activate", G_CALLBACK(+[](GtkWidget*, gpointer d) {
|
g_signal_connect_data(restore_item, "activate", G_CALLBACK(+[](GtkWidget*, gpointer d) {
|
||||||
auto* c = static_cast<RestoreCtx*>(d);
|
auto* c = static_cast<RestoreCtx*>(d);
|
||||||
c->self->show_sudo_dialog([c](const std::string& pw) {
|
c->self->show_sudo_dialog([c](const std::string& pw) {
|
||||||
std::vector<std::string> files = {c->path};
|
struct Ctx { MainWindow* self; std::string path; std::string password; };
|
||||||
c->self->snapshots_.restore_selected(c->self->current_snapshot_, files, pw);
|
auto* ctx = new Ctx{c->self, c->path, pw};
|
||||||
c->self->tray_.show_notification("x3-Backup", "Directory restored: " + c->path);
|
g_thread_new("restore", [](gpointer data) -> gpointer {
|
||||||
|
auto* cx = static_cast<Ctx*>(data);
|
||||||
|
std::vector<std::string> files = {cx->path};
|
||||||
|
cx->self->snapshots_.restore_selected(cx->self->current_snapshot_, files, cx->password);
|
||||||
|
g_idle_add([](gpointer d) -> gboolean {
|
||||||
|
auto* cx2 = static_cast<Ctx*>(d);
|
||||||
|
cx2->self->tray_.show_notification("x3-Backup", "Directory restored: " + cx2->path);
|
||||||
|
delete cx2;
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}, cx);
|
||||||
|
return nullptr;
|
||||||
|
}, ctx);
|
||||||
});
|
});
|
||||||
delete c;
|
delete c;
|
||||||
}), ctx, nullptr, (GConnectFlags)0);
|
}), ctx, nullptr, (GConnectFlags)0);
|
||||||
@@ -939,11 +961,23 @@ void MainWindow::on_restore(GtkWidget*, gpointer d) {
|
|||||||
g_free(name);
|
g_free(name);
|
||||||
|
|
||||||
self->show_sudo_dialog([self, file_path](const std::string& pw) {
|
self->show_sudo_dialog([self, file_path](const std::string& pw) {
|
||||||
std::vector<std::string> files = {file_path};
|
|
||||||
self->tray_.set_status("x3-Backup - Restoring...", true);
|
self->tray_.set_status("x3-Backup - Restoring...", true);
|
||||||
self->snapshots_.restore_selected(self->current_snapshot_, files, pw);
|
|
||||||
self->tray_.set_status("x3-Backup - Idle");
|
struct RestoreCtx { MainWindow* self; std::string file_path; std::string password; };
|
||||||
self->tray_.show_notification("x3-Backup", "Restored: " + file_path);
|
auto* ctx = new RestoreCtx{self, file_path, pw};
|
||||||
|
g_thread_new("restore", [](gpointer data) -> gpointer {
|
||||||
|
auto* c = static_cast<RestoreCtx*>(data);
|
||||||
|
std::vector<std::string> files = {c->file_path};
|
||||||
|
c->self->snapshots_.restore_selected(c->self->current_snapshot_, files, c->password);
|
||||||
|
g_idle_add([](gpointer d) -> gboolean {
|
||||||
|
auto* c2 = static_cast<RestoreCtx*>(d);
|
||||||
|
c2->self->tray_.set_status("x3-Backup - Idle");
|
||||||
|
c2->self->tray_.show_notification("x3-Backup", "Restored: " + c2->file_path);
|
||||||
|
delete c2;
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}, c);
|
||||||
|
return nullptr;
|
||||||
|
}, ctx);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1067,8 +1101,19 @@ void MainWindow::on_system_restore(GtkWidget*, gpointer d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self->show_sudo_dialog([self](const std::string& pw) {
|
self->show_sudo_dialog([self](const std::string& pw) {
|
||||||
self->snapshots_.restore_full(self->current_snapshot_, pw);
|
struct SysRestoreCtx { MainWindow* self; std::string password; };
|
||||||
self->tray_.show_notification("x3-Backup", "Full system restore completed");
|
auto* ctx = new SysRestoreCtx{self, pw};
|
||||||
|
g_thread_new("sysrestore", [](gpointer data) -> gpointer {
|
||||||
|
auto* cx = static_cast<SysRestoreCtx*>(data);
|
||||||
|
cx->self->snapshots_.restore_full(cx->self->current_snapshot_, cx->password);
|
||||||
|
g_idle_add([](gpointer d) -> gboolean {
|
||||||
|
auto* cx2 = static_cast<SysRestoreCtx*>(d);
|
||||||
|
cx2->self->tray_.show_notification("x3-Backup", "Full system restore completed");
|
||||||
|
delete cx2;
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}, cx);
|
||||||
|
return nullptr;
|
||||||
|
}, ctx);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
gtk_widget_destroy(dialog);
|
gtk_widget_destroy(dialog);
|
||||||
|
|||||||
Reference in New Issue
Block a user