[GTK3] Check if config changed before saving

This uses the file modification date and opens a choice dialog if
the date has changed since.
This commit is contained in:
Maximilian Mader 2020-05-13 00:25:13 +02:00
parent f6838a901c
commit 6ea36bbc39
Signed by: Max
GPG Key ID: F71D56A3151C4FB3
3 changed files with 64 additions and 20 deletions

View File

@ -54,6 +54,7 @@ typedef struct GuiData {
GFile *file; GFile *file;
gint sample_rate; gint sample_rate;
GDateTime *config_modification_date;
char *battery_save_path; char *battery_save_path;
char *cheats_save_path; char *cheats_save_path;
@ -1615,7 +1616,14 @@ static void run(void) {
// //
// TODO: Make sure we have a way to quit our emulation loop before `shutdown` gets called // TODO: Make sure we have a way to quit our emulation loop before `shutdown` gets called
static void quit(void) { static void quit(void) {
g_debug("quit(void);");
stop(); stop();
while (gui_data.stopping);
GtkWindow *window = gui_data.main_window ? GTK_WINDOW(gui_data.main_window) : NULL;
save_settings(window, gui_data.config_modification_date);
free_settings();
for (unsigned i = 0; i < gui_data.controller_count; i++) { for (unsigned i = 0; i < gui_data.controller_count; i++) {
struct Controller_t *s = &gui_data.controllers[i]; struct Controller_t *s = &gui_data.controllers[i];
@ -1630,12 +1638,16 @@ static void quit(void) {
} }
static void quit_interrupt(int ignored) { static void quit_interrupt(int ignored) {
g_debug("quit_interrupt(%d);", ignored);
quit(); quit();
} }
// `destroy` signal GCallback // `destroy` signal GCallback
// Exits the application // Exits the application
static void on_quit(GtkWidget *w, gpointer app) { static void on_quit(GtkWidget *w, gpointer app) {
g_debug("on_quit(%p, %p);", w, &app);
quit(); quit();
} }
@ -1994,7 +2006,7 @@ static void startup(GApplication *app, gpointer null_ptr) {
gui_data.preferences = GTK_WINDOW(get_object("preferences")); gui_data.preferences = GTK_WINDOW(get_object("preferences"));
g_signal_connect(gui_data.preferences, "realize", G_CALLBACK(on_preferences_realize), (gpointer) gui_data.builder); g_signal_connect(gui_data.preferences, "realize", G_CALLBACK(on_preferences_realize), (gpointer) gui_data.builder);
init_settings(app, gui_data.cli_options.config_path, gui_data.preferences); init_settings(app, gui_data.cli_options.config_path, &gui_data.config_modification_date, gui_data.preferences);
gui_data.vram_viewer = GTK_WINDOW(get_object("vram_viewer")); gui_data.vram_viewer = GTK_WINDOW(get_object("vram_viewer"));
gui_data.memory_viewer = GTK_WINDOW(get_object("memory_viewer")); gui_data.memory_viewer = GTK_WINDOW(get_object("memory_viewer"));
@ -2311,11 +2323,6 @@ static void shutdown(GApplication *app, GFile **files, gint n_files, const gchar
stop(); stop();
while (gui_data.stopping); while (gui_data.stopping);
g_object_unref(gui_data.builder);
save_settings();
free_settings();
SDL_Quit(); SDL_Quit();
if (gui_data.image_buffers[0]) g_free(gui_data.image_buffers[0]); if (gui_data.image_buffers[0]) g_free(gui_data.image_buffers[0]);
@ -2325,6 +2332,8 @@ static void shutdown(GApplication *app, GFile **files, gint n_files, const gchar
free_master_shader(); free_master_shader();
GB_free(&gb); GB_free(&gb);
g_object_unref(gui_data.builder);
} }
// This function gets called when there are files to open. // This function gets called when there are files to open.

View File

@ -3,6 +3,9 @@
#define get_object(id) gtk_builder_get_object(builder, id) #define get_object(id) gtk_builder_get_object(builder, id)
#define builder_get(type, id) type(get_object(id)) #define builder_get(type, id) type(get_object(id))
gchar* settings_file_path;
GKeyFile *key_file;
static void print_config_error(GError *error) { static void print_config_error(GError *error) {
if (error == NULL) return; if (error == NULL) return;
@ -108,6 +111,13 @@ void save_config_to_key_file(config_t *config, GKeyFile *key_file) {
#undef EXPAND_GROUP_MEMBER_IF_EVAL #undef EXPAND_GROUP_MEMBER_IF_EVAL
#undef EXPAND_GROUP_MEMBER_IF_0 #undef EXPAND_GROUP_MEMBER_IF_0
#undef EXPAND_GROUP_MEMBER_IF_1 #undef EXPAND_GROUP_MEMBER_IF_1
// Save config to disk
if (!g_key_file_save_to_file(key_file, settings_file_path, &error)) {
g_warning ("Failed to save %s: %s", settings_file_path, error->message);
g_error_free(error);
return;
}
} }
void on_preferences_realize(GtkWidget *w, gpointer builder_ptr) { void on_preferences_realize(GtkWidget *w, gpointer builder_ptr) {
@ -147,7 +157,7 @@ void on_preferences_realize(GtkWidget *w, gpointer builder_ptr) {
#endif #endif
} }
void init_settings(GApplication *app, gchar *path, GtkWindow *preferences) { void init_settings(GApplication *app, gchar *path, GDateTime **modification_date, GtkWindow *preferences) {
free_settings(); free_settings();
key_file = g_key_file_new(); key_file = g_key_file_new();
@ -158,14 +168,18 @@ void init_settings(GApplication *app, gchar *path, GtkWindow *preferences) {
settings_file_path = g_build_filename(g_get_user_config_dir(), SETTINGS_FILE, NULL); settings_file_path = g_build_filename(g_get_user_config_dir(), SETTINGS_FILE, NULL);
} }
load_settings(app); load_settings(app, modification_date);
} }
int load_settings(GApplication *app) { int load_settings(GApplication *app, GDateTime **modification_date) {
GError *error = NULL; GError *error = NULL;
g_message("Trying to load settings from %s", settings_file_path); g_message("Trying to load settings from %s", settings_file_path);
g_autoptr(GFile) file = g_file_new_for_path(settings_file_path);
g_autoptr(GFileInfo) file_info = g_file_query_info(file, "time::*", G_FILE_QUERY_INFO_NONE, NULL, NULL);
*modification_date = g_file_info_get_modification_date_time(file_info);
if (!g_key_file_load_from_file(key_file, settings_file_path, G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error)) { if (!g_key_file_load_from_file(key_file, settings_file_path, G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error)) {
if (error->domain == G_FILE_ERROR) { if (error->domain == G_FILE_ERROR) {
g_warning("Unable to load %s: %s", settings_file_path, error->message); g_warning("Unable to load %s: %s", settings_file_path, error->message);
@ -186,17 +200,40 @@ int load_settings(GApplication *app) {
return 0; return 0;
} }
void save_settings(void) { void save_settings(GtkWindow *main_window, GDateTime *saved_modification_date) {
GError *error = NULL; GError *error = NULL;
g_message("Trying to save settings to %s", settings_file_path); g_message("Trying to save settings to %s", settings_file_path);
save_config_to_key_file(&config, key_file); g_autoptr(GFile) file = g_file_new_for_path(settings_file_path);
g_autoptr(GFileInfo) file_info = g_file_query_info(file, "time::*", G_FILE_QUERY_INFO_NONE, NULL, NULL);
GDateTime *modification_date = g_file_info_get_modification_date_time(file_info);
if (!g_key_file_save_to_file(key_file, settings_file_path, &error)) { if (!g_date_time_equal(saved_modification_date, modification_date)) {
g_warning ("Failed to save %s: %s", settings_file_path, error->message); GtkMessageDialog *dialog = GTK_MESSAGE_DIALOG(gtk_message_dialog_new(
g_error_free(error); main_window,
return; GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_YES_NO,
"It looks like the configuration has changed on disk. Overwrite?"
));
gtk_window_set_title(GTK_WINDOW(dialog), "SameBoy");
gint result = gtk_dialog_run(GTK_DIALOG(dialog));
switch (result) {
case GTK_RESPONSE_YES:
save_config_to_key_file(&config, key_file);
break;
default:
// Action has been canceled
break;
}
}
else {
save_config_to_key_file(&config, key_file);
} }
} }

View File

@ -76,8 +76,6 @@ enum menubar_type_t {
MENUBAR_SHOW_HAMBURGER MENUBAR_SHOW_HAMBURGER
}; };
gchar* settings_file_path;
GKeyFile *key_file;
config_t config; config_t config;
void on_preferences_realize(GtkWidget *w, gpointer builder_ptr); void on_preferences_realize(GtkWidget *w, gpointer builder_ptr);
@ -85,9 +83,9 @@ void on_preferences_realize(GtkWidget *w, gpointer builder_ptr);
void print_config(config_t *config); void print_config(config_t *config);
void load_config_from_key_file(config_t *config, GKeyFile *key_file); void load_config_from_key_file(config_t *config, GKeyFile *key_file);
void init_settings(GApplication *app, gchar *path, GtkWindow *preferences); void init_settings(GApplication *app, gchar *path, GDateTime **modification_date, GtkWindow *preferences);
int load_settings(GApplication *app); int load_settings(GApplication *app, GDateTime **modification_date);
void save_settings(void); void save_settings(GtkWindow *main_window, GDateTime *saved_modification_date);
void free_settings(void); void free_settings(void);
void update_boot_rom_selector(GtkBuilder *builder); void update_boot_rom_selector(GtkBuilder *builder);