diff --git a/data/geany.glade b/data/geany.glade index f292317f4f..56d0e510f2 100644 --- a/data/geany.glade +++ b/data/geany.glade @@ -1445,22 +1445,6 @@ True False - - - Use project-based session files - True - True - False - Whether to store a project's session files and open them when re-opening the project - True - True - - - False - False - 0 - - Store project file inside the project base directory diff --git a/src/keyfile.c b/src/keyfile.c index 117a6b8d3c..dc40a01622 100644 --- a/src/keyfile.c +++ b/src/keyfile.c @@ -106,11 +106,10 @@ static gchar *scribble_text = NULL; static gint scribble_pos = -1; -static GPtrArray *session_files = NULL; +static GPtrArray *default_session_files = NULL; static gint session_notebook_page; static gint hpan_position; static gint vpan_position; -static guint document_list_update_idle_func_id = 0; static const gchar atomic_file_saving_key[] = "use_atomic_file_saving"; typedef enum @@ -458,7 +457,6 @@ static void save_dialog_prefs(GKeyFile *config) /* general */ g_key_file_set_boolean(config, PACKAGE, "pref_main_load_session", prefs.load_session); - g_key_file_set_boolean(config, PACKAGE, "pref_main_project_session", project_prefs.project_session); g_key_file_set_boolean(config, PACKAGE, "pref_main_project_file_in_basedir", project_prefs.project_file_in_basedir); g_key_file_set_boolean(config, PACKAGE, "pref_main_save_winpos", prefs.save_winpos); g_key_file_set_boolean(config, PACKAGE, "pref_main_save_wingeom", prefs.save_wingeom); @@ -666,7 +664,7 @@ void write_config_file(gchar const *filename, ConfigPayload payload) save_recent_files(config, ui_prefs.recent_projects_queue, "recent_projects"); project_save_prefs(config); /* save project filename, etc. */ save_ui_session(config); - if (cl_options.load_session) + if (cl_options.load_session && app->project == NULL) configuration_save_session_files(config); #ifdef HAVE_VTE else if (vte_info.have_vte) @@ -718,34 +716,20 @@ static void load_recent_files(GKeyFile *config, GQueue *queue, const gchar *key) /* - * Load session list from the given keyfile, and store it in the global - * session_files variable for later file loading + * Load session list from the given keyfile and return an array containg the file names * */ -void configuration_load_session_files(GKeyFile *config, gboolean read_recent_files) +GPtrArray *configuration_load_session_files(GKeyFile *config) { guint i; gboolean have_session_files; gchar entry[16]; gchar **tmp_array; GError *error = NULL; + GPtrArray *files; session_notebook_page = utils_get_setting_integer(config, "files", "current_page", -1); - if (read_recent_files) - { - load_recent_files(config, ui_prefs.recent_queue, "recent_files"); - load_recent_files(config, ui_prefs.recent_projects_queue, "recent_projects"); - } - - /* the project may load another list than the main setting */ - if (session_files != NULL) - { - foreach_ptr_array(tmp_array, i, session_files) - g_strfreev(tmp_array); - g_ptr_array_free(session_files, TRUE); - } - - session_files = g_ptr_array_new(); + files = g_ptr_array_new(); have_session_files = TRUE; i = 0; while (have_session_files) @@ -758,7 +742,7 @@ void configuration_load_session_files(GKeyFile *config, gboolean read_recent_fil error = NULL; have_session_files = FALSE; } - g_ptr_array_add(session_files, tmp_array); + g_ptr_array_add(files, tmp_array); i++; } @@ -771,6 +755,8 @@ void configuration_load_session_files(GKeyFile *config, gboolean read_recent_fil g_free(tmp_string); } #endif + + return files; } @@ -815,7 +801,6 @@ static void load_dialog_prefs(GKeyFile *config) prefs.confirm_exit = utils_get_setting_boolean(config, PACKAGE, "pref_main_confirm_exit", FALSE); prefs.suppress_status_messages = utils_get_setting_boolean(config, PACKAGE, "pref_main_suppress_status_messages", FALSE); prefs.load_session = utils_get_setting_boolean(config, PACKAGE, "pref_main_load_session", TRUE); - project_prefs.project_session = utils_get_setting_boolean(config, PACKAGE, "pref_main_project_session", TRUE); project_prefs.project_file_in_basedir = utils_get_setting_boolean(config, PACKAGE, "pref_main_project_file_in_basedir", FALSE); prefs.save_winpos = utils_get_setting_boolean(config, PACKAGE, "pref_main_save_winpos", TRUE); prefs.save_wingeom = utils_get_setting_boolean(config, PACKAGE, "pref_main_save_wingeom", prefs.save_winpos); @@ -1172,15 +1157,17 @@ void configuration_clear_default_session(void) /* * Only reload the session part of the default configuration */ -void configuration_reload_default_session(void) +void configuration_load_default_session(void) { gchar *configfile = g_build_filename(app->configdir, SESSION_FILE, NULL); GKeyFile *config = g_key_file_new(); + g_return_if_fail(default_session_files == NULL); + g_key_file_load_from_file(config, configfile, G_KEY_FILE_NONE, NULL); g_free(configfile); - configuration_load_session_files(config, FALSE); + default_session_files = configuration_load_session_files(config); g_key_file_free(config); } @@ -1219,8 +1206,8 @@ gboolean read_config_file(gchar const *filename, ConfigPayload payload) case SESSION: project_load_prefs(config); load_ui_session(config); - /* read stash prefs */ - configuration_load_session_files(config, TRUE); + load_recent_files(config, ui_prefs.recent_queue, "recent_files"); + load_recent_files(config, ui_prefs.recent_projects_queue, "recent_projects"); break; } @@ -1309,17 +1296,39 @@ static gboolean open_session_file(gchar **tmp, guint len) return ret; } +/* trigger a notebook page switch after unsetting main_status.opening_session_files + * for callbacks to run (and update window title, encoding settings, and so on) + */ +static gboolean switch_to_session_page(gpointer data) +{ + gint n_pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook)); + gint cur_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(main_widgets.notebook)); + gint target_page = session_notebook_page >= 0 ? session_notebook_page : cur_page; + + if (n_pages > 0) + { + if (target_page != cur_page) + gtk_notebook_set_current_page(GTK_NOTEBOOK(main_widgets.notebook), target_page); + else + g_signal_emit_by_name(GTK_NOTEBOOK(main_widgets.notebook), "switch-page", + gtk_notebook_get_nth_page(GTK_NOTEBOOK(main_widgets.notebook), target_page), + target_page); + } + session_notebook_page = -1; + + return G_SOURCE_REMOVE; +} /* Open session files * Note: notebook page switch handler and adding to recent files list is always disabled * for all files opened within this function */ -void configuration_open_files(void) +void configuration_open_files(GPtrArray *session_files) { gint i; gboolean failure = FALSE; /* necessary to set it to TRUE for project session support */ - main_status.opening_session_files = TRUE; + main_status.opening_session_files++; i = file_prefs.tab_order_ltr ? 0 : (session_files->len - 1); while (TRUE) @@ -1349,26 +1358,25 @@ void configuration_open_files(void) } g_ptr_array_free(session_files, TRUE); - session_files = NULL; if (failure) ui_set_statusbar(TRUE, _("Failed to load one or more session files.")); else - { - /* explicitly trigger a notebook page switch after unsetting main_status.opening_session_files - * for callbacks to run (and update window title, encoding settings, and so on) */ - gint n_pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook)); - gint cur_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(main_widgets.notebook)); - gint target_page = session_notebook_page >= 0 ? session_notebook_page : cur_page; - - /* if target page is current page, switch to another page first to really trigger an event */ - if (target_page == cur_page && n_pages > 0) - gtk_notebook_set_current_page(GTK_NOTEBOOK(main_widgets.notebook), (cur_page + 1) % n_pages); - - main_status.opening_session_files = FALSE; - gtk_notebook_set_current_page(GTK_NOTEBOOK(main_widgets.notebook), target_page); - } - main_status.opening_session_files = FALSE; + g_idle_add(switch_to_session_page, NULL); + + main_status.opening_session_files--; +} + + +/* Open session files + * Note: notebook page switch handler and adding to recent files list is always disabled + * for all files opened within this function */ +void configuration_open_default_session(void) +{ + g_return_if_fail(default_session_files != NULL); + + configuration_open_files(default_session_files); + default_session_files = NULL; } @@ -1410,12 +1418,10 @@ void configuration_apply_settings(void) static gboolean save_configuration_cb(gpointer data) { - configuration_save(); if (app->project != NULL) - { project_write_config(); - } - document_list_update_idle_func_id = 0; + else + configuration_save_default_session(); return G_SOURCE_REMOVE; } @@ -1431,10 +1437,8 @@ static void document_list_changed_cb(GObject *obj, GeanyDocument *doc, gpointer !main_status.opening_session_files && !main_status.quitting) { - if (document_list_update_idle_func_id == 0) - { - document_list_update_idle_func_id = g_idle_add(save_configuration_cb, NULL); - } + g_idle_remove_by_data(save_configuration_cb); + g_idle_add(save_configuration_cb, save_configuration_cb); } } diff --git a/src/keyfile.h b/src/keyfile.h index 2179d30e30..7eec0694eb 100644 --- a/src/keyfile.h +++ b/src/keyfile.h @@ -46,15 +46,17 @@ void configuration_save(void); gboolean configuration_load(void); -void configuration_open_files(void); +void configuration_open_files(GPtrArray *session_files); -void configuration_reload_default_session(void); +void configuration_load_default_session(void); + +void configuration_open_default_session(void); void configuration_save_default_session(void); void configuration_clear_default_session(void); -void configuration_load_session_files(GKeyFile *config, gboolean read_recent_files); +GPtrArray *configuration_load_session_files(GKeyFile *config); void configuration_save_session_files(GKeyFile *config); diff --git a/src/libmain.c b/src/libmain.c index d316f440ac..0fbc503da0 100644 --- a/src/libmain.c +++ b/src/libmain.c @@ -46,6 +46,7 @@ #include "navqueue.h" #include "notebook.h" #include "plugins.h" +#include "projectprivate.h" #include "prefs.h" #include "printing.h" #include "sidebar.h" @@ -263,7 +264,7 @@ static void main_init(void) ignore_callback = FALSE; ui_prefs.recent_queue = g_queue_new(); ui_prefs.recent_projects_queue = g_queue_new(); - main_status.opening_session_files = FALSE; + main_status.opening_session_files = 0; main_widgets.window = create_window1(); g_signal_connect(main_widgets.window, "notify::is-active", G_CALLBACK(on_window_active_changed), NULL); @@ -957,7 +958,7 @@ static void load_startup_files(gint argc, gchar **argv) main_load_project_from_command_line(filename, FALSE); argc--, argv++; /* force session load if using project-based session files */ - load_session = project_prefs.project_session; + load_session = TRUE; g_free(filename); } @@ -970,13 +971,23 @@ static void load_startup_files(gint argc, gchar **argv) { if (app->project == NULL) load_session_project_file(); + if (app->project == NULL) + configuration_load_default_session(); load_session = TRUE; } if (load_session) { /* load session files into tabs, as they are found in the session_files variable */ - configuration_open_files(); + if (app->project != NULL) + { + configuration_open_files(app->project->priv->session_files); + app->project->priv->session_files = NULL; + } + else + { + configuration_open_default_session(); + } if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook)) == 0) { @@ -1194,9 +1205,9 @@ gint main_lib(gint argc, gchar **argv) tools_create_insert_custom_command_menu_items(); /* load any command line files or session files */ - main_status.opening_session_files = TRUE; + main_status.opening_session_files++; load_startup_files(argc, argv); - main_status.opening_session_files = FALSE; + main_status.opening_session_files--; /* open a new file if no other file was opened */ document_new_file_if_non_open(); diff --git a/src/main.h b/src/main.h index 34f471acbd..1a5837c625 100644 --- a/src/main.h +++ b/src/main.h @@ -53,7 +53,7 @@ extern CommandLineOptions cl_options; typedef struct GeanyStatus { - gboolean opening_session_files; /* state at startup while opening session files */ + gint opening_session_files; /* >0 indicates batch-opening of session files */ gboolean closing_all; /* the state while closing all tabs * (used to prevent notebook switch page signals) */ gboolean quitting; /* state when Geany is quitting completely */ diff --git a/src/prefs.c b/src/prefs.c index a5d4761217..228ae6b2be 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -409,9 +409,6 @@ static void prefs_init_dialog(void) widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_load_session"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), prefs.load_session); - widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_project_session"); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), project_prefs.project_session); - widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_project_file_in_basedir"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), project_prefs.project_file_in_basedir); @@ -892,9 +889,6 @@ on_prefs_dialog_response(GtkDialog *dialog, gint response, gpointer user_data) widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_load_session"); prefs.load_session = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_project_session"); - project_prefs.project_session = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_project_file_in_basedir"); project_prefs.project_file_in_basedir = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); diff --git a/src/project.c b/src/project.c index 7a19990648..74bdd08a77 100644 --- a/src/project.c +++ b/src/project.c @@ -50,7 +50,7 @@ #include -ProjectPrefs project_prefs = { NULL, FALSE, FALSE }; +ProjectPrefs project_prefs = { NULL, FALSE }; static GeanyProjectPrivate priv; @@ -112,7 +112,7 @@ static gboolean have_session_docs(void) static gboolean handle_current_session(void) { - if (!app->project && project_prefs.project_session) + if (!app->project) { /* save session in case the dialog is cancelled */ configuration_save_default_session(); @@ -265,8 +265,8 @@ static void run_new_dialog(PropertyDialogElements *e) else { // reload any documents that were closed - configuration_reload_default_session(); - configuration_open_files(); + configuration_load_default_session(); + configuration_open_default_session(); } } @@ -275,12 +275,10 @@ gboolean project_load_file_with_session(const gchar *locale_file_name) { if (project_load_file(locale_file_name)) { - if (project_prefs.project_session) - { - configuration_open_files(); - document_new_file_if_non_open(); - ui_focus_current_document(); - } + configuration_open_files(app->project->priv->session_files); + app->project->priv->session_files = NULL; + document_new_file_if_non_open(); + ui_focus_current_document(); return TRUE; } return FALSE; @@ -413,12 +411,10 @@ gboolean project_close(gboolean open_default) if (!write_config()) g_warning("Project file \"%s\" could not be written", app->project->file_name); - if (project_prefs.project_session) - { - /* close all existing tabs first */ - if (!document_close_all()) - return FALSE; - } + /* close all existing tabs first */ + if (!document_close_all()) + return FALSE; + ui_set_statusbar(TRUE, _("Project \"%s\" closed."), app->project->name); destroy_project(open_default); return TRUE; @@ -461,16 +457,13 @@ static void destroy_project(gboolean open_default) apply_editor_prefs(); /* ensure that global settings are restored */ - if (project_prefs.project_session) + /* after closing all tabs let's open the tabs found in the default config */ + if (open_default && cl_options.load_session) { - /* after closing all tabs let's open the tabs found in the default config */ - if (open_default && cl_options.load_session) - { - configuration_reload_default_session(); - configuration_open_files(); - document_new_file_if_non_open(); - ui_focus_current_document(); - } + configuration_load_default_session(); + configuration_open_default_session(); + document_new_file_if_non_open(); + ui_focus_current_document(); } g_signal_emit_by_name(geany_object, "project-close"); @@ -1072,15 +1065,15 @@ static gboolean load_config(const gchar *filename) apply_editor_prefs(); build_load_menu(config, GEANY_BCS_PROJ, (gpointer)p); - if (project_prefs.project_session) + /* save current (non-project) session (it could have been changed since program startup) */ + if (!main_status.opening_session_files) { - /* save current (non-project) session (it could have been changed since program startup) */ configuration_save_default_session(); /* now close all open files */ document_close_all(); - /* read session files so they can be opened with configuration_open_files() */ - configuration_load_session_files(config, FALSE); } + /* read session files so they can be opened with configuration_open_files() */ + p->priv->session_files = configuration_load_session_files(config); g_signal_emit_by_name(geany_object, "project-open", config); g_key_file_free(config); @@ -1135,8 +1128,7 @@ static gboolean write_config(void) g_key_file_set_integer(config, "long line marker", "long_line_column", p->priv->long_line_column); /* store the session files into the project too */ - if (project_prefs.project_session) - configuration_save_session_files(config); + configuration_save_session_files(config); build_save_menu(config, (gpointer)p, GEANY_BCS_PROJ); g_signal_emit_by_name(geany_object, "project-save", config); /* write the file */ diff --git a/src/project.h b/src/project.h index 4fdacb65bb..c4699fe0c4 100644 --- a/src/project.h +++ b/src/project.h @@ -55,7 +55,6 @@ void project_write_config(void); typedef struct ProjectPrefs { gchar *session_file; - gboolean project_session; gboolean project_file_in_basedir; } ProjectPrefs; diff --git a/src/projectprivate.h b/src/projectprivate.h index 50f3157ffc..df59bb346a 100644 --- a/src/projectprivate.h +++ b/src/projectprivate.h @@ -45,6 +45,7 @@ typedef struct GeanyProjectPrivate gint long_line_column; /* Long line marker position. */ GPtrArray *build_filetypes_list; /* Project has custom filetype builds for these. */ + GPtrArray *session_files; } GeanyProjectPrivate;