From a7bb4cee5f72fb706aa995791879d2be9a739fc4 Mon Sep 17 00:00:00 2001 From: Philipp Lopaur Date: Fri, 30 Oct 2026 06:00:00 +0100 Subject: [PATCH] Prevent opening the same module twice Opening a module that is already open created a second copy that shared the same .mod file. Both copies wrote their settings on exit, so the last one saved won, and both names were stored in OPEN_MODULES. The duplicate was then restored on every start. Two copies of a module also meant two map views, which is how the crash when closing one of several map views was found. That crash is fixed separately by "Fix crash when closing one of several map views". When a module that is already open is selected in File > Open, bring it to the front instead of opening a second copy. When restoring the open modules on startup, skip names that appear more than once, so existing configs with duplicates are repaired. --- src/menubar.c | 13 ++++++++++++ src/mod-mgr.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/mod-mgr.h | 2 ++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/menubar.c b/src/menubar.c index e6e082bf8..d99cf860c 100644 --- a/src/menubar.c +++ b/src/menubar.c @@ -409,6 +409,19 @@ static void menubar_open_mod_cb(GtkWidget * widget, gpointer data) sat_log_log(SAT_LOG_LEVEL_DEBUG, _("%s: Open module %s."), __func__, modnam); + /* if the module is already open, bring it to the front instead of + opening a second copy that shares the same .mod file */ + module = mod_mgr_get_module(modnam); + if (module != NULL) + { + sat_log_log(SAT_LOG_LEVEL_INFO, + _("%s: Module %s is already open."), __func__, + modnam); + mod_mgr_raise_module(module); + g_free(modnam); + return; + } + confdir = get_modules_dir(); modfile = g_strconcat(confdir, G_DIR_SEPARATOR_S, modnam, ".mod", NULL); diff --git a/src/mod-mgr.c b/src/mod-mgr.c index 6e9a89776..089abe96a 100644 --- a/src/mod-mgr.c +++ b/src/mod-mgr.c @@ -86,7 +86,7 @@ GtkWidget *mod_mgr_create(void) { gchar *openmods = NULL; gchar **mods; - gint count, i; + gint count, i, j; GtkWidget *module; gchar *modfile; gchar *confdir; @@ -108,6 +108,23 @@ GtkWidget *mod_mgr_create(void) for (i = 0; i < count; i++) { + /* skip modules listed more than once */ + for (j = 0; j < i; j++) + if (!g_strcmp0(mods[i], mods[j])) + break; + + if (j < i) + { + sat_log_log(SAT_LOG_LEVEL_INFO, + _("%s: Skipping duplicate module %s"), + __func__, mods[i]); + + /* keep the saved page pointing at the same module */ + if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(nbook)) < page) + page--; + + continue; + } confdir = get_modules_dir(); modfile = g_strconcat(confdir, G_DIR_SEPARATOR_S, @@ -392,6 +409,44 @@ gboolean mod_mgr_mod_is_visible(GtkWidget * module) return retcode; } +/* Find an open module by name. Returns NULL if no such module is open. */ +GtkWidget *mod_mgr_get_module(const gchar * name) +{ + GSList *node; + + for (node = modules; node != NULL; node = node->next) + { + if (!g_strcmp0(GTK_SAT_MODULE(node->data)->name, name)) + return GTK_WIDGET(node->data); + } + + return NULL; +} + +/* + * Bring an open module to the front. + * + * A docked module is selected in the notebook and the main window is + * raised. An undocked module has its own window raised. + */ +void mod_mgr_raise_module(GtkWidget * module) +{ + gint page; + + if (GTK_SAT_MODULE(module)->state == GTK_SAT_MOD_STATE_DOCKED) + { + page = gtk_notebook_page_num(GTK_NOTEBOOK(nbook), module); + if (page != -1) + gtk_notebook_set_current_page(GTK_NOTEBOOK(nbook), page); + + gtk_window_present(GTK_WINDOW(app)); + } + else if (GTK_SAT_MODULE(module)->win != NULL) + { + gtk_window_present(GTK_WINDOW(GTK_SAT_MODULE(module)->win)); + } +} + /* * Dock a module into the notebook. * diff --git a/src/mod-mgr.h b/src/mod-mgr.h index 7ec8bcfaf..ffc6256f3 100644 --- a/src/mod-mgr.h +++ b/src/mod-mgr.h @@ -9,5 +9,7 @@ gboolean mod_mgr_mod_is_visible(GtkWidget * module); gint mod_mgr_dock_module(GtkWidget * module); gint mod_mgr_undock_module(GtkWidget * module); void mod_mgr_reload_sats(void); +GtkWidget *mod_mgr_get_module(const gchar * name); +void mod_mgr_raise_module(GtkWidget * module); #endif