diff --git a/data/geany.glade b/data/geany.glade index 71327353c4..ea74821233 100644 --- a/data/geany.glade +++ b/data/geany.glade @@ -8543,7 +8543,7 @@ True False 6 - 5 + 6 2 6 6 @@ -8757,6 +8757,44 @@ GTK_FILL + + + True + False + 0 + 0 + Relative files: + True + entry_project_dialog_file_patterns + + + 5 + 6 + GTK_FILL + GTK_FILL + + + + + Use relative file for the session file + True + True + False + This option allows to store the relative path instead of the absolute path of the opened files when the session is saved. + +Warning: +If this is convenient to share a project, think twice before adding a ``.geany`` file to a version control system (like svn or git). You or other people risk to commit this file and broadcast to the world the paths of all your opened files. + 0 + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + diff --git a/doc/geany.txt b/doc/geany.txt index bdeac023ab..9b47cb31ec 100644 --- a/doc/geany.txt +++ b/doc/geany.txt @@ -2833,6 +2833,15 @@ relative to the project's file name. The *File patterns* field allows to specify a list of file patterns for the project, which can be used in the `Find in files`_ dialog. +The *Relatives files* option allows to store the relative path instead +of the absolute path of the opened files when the session is saved. + +.. Warning:: + If this is convenient to share a project, think twice before + adding a ``.geany`` file to a version control system (like svn or git). + You or other people risk to commit this file and broadcast to the world + the paths of all your opened files. + The *Indentation* tab allows you to override the default `Indentation`_ settings. diff --git a/src/keyfile.c b/src/keyfile.c index 90ad79a86e..dfeeae0e9b 100644 --- a/src/keyfile.c +++ b/src/keyfile.c @@ -351,17 +351,39 @@ static void save_recent_files(GKeyFile *config, GQueue *queue, gchar const *key) } -static gchar *get_session_file_string(GeanyDocument *doc) +static gchar *get_session_file_string(GeanyDocument *doc, gchar * project_root_folder) { gchar *fname; + gchar *relative_filename; + gchar *doc_filename; gchar *locale_filename; gchar *escaped_filename; GeanyFiletype *ft = doc->file_type; + GFile *file_doc; + GFile *file_root_folder; if (ft == NULL) /* can happen when saving a new file when quitting */ ft = filetypes[GEANY_FILETYPES_NONE]; - locale_filename = utils_get_locale_from_utf8(doc->file_name); + /* project_root_folder contain a path only if the project use relative path */ + if(project_root_folder){ + file_root_folder = g_file_new_for_path(project_root_folder); + file_doc = g_file_new_for_path(doc->file_name); + relative_filename = g_file_get_relative_path(file_root_folder, file_doc); + if(relative_filename){ + doc_filename = g_strdup(relative_filename); + }else{ + doc_filename = g_strdup(doc->file_name); + } + g_object_unref(file_root_folder); + g_object_unref(file_doc); + g_free(relative_filename); + }else{ + doc_filename = g_strdup(doc->file_name); + } + + + locale_filename = utils_get_locale_from_utf8(doc_filename); escaped_filename = g_uri_escape_string(locale_filename, NULL, TRUE); fname = g_strdup_printf("%d;%s;%d;E%s;%d;%d;%d;%s;%d;%d", @@ -375,6 +397,7 @@ static gchar *get_session_file_string(GeanyDocument *doc) escaped_filename, doc->editor->line_breaking, doc->editor->indent_width); + g_free(doc_filename); g_free(escaped_filename); g_free(locale_filename); return fname; @@ -395,7 +418,7 @@ static void remove_session_files(GKeyFile *config) } -void configuration_save_session_files(GKeyFile *config) +void configuration_save_session_files(GKeyFile *config, gchar * project_root_folder) { gint npage; gchar entry[16]; @@ -418,7 +441,7 @@ void configuration_save_session_files(GKeyFile *config) gchar *fname; g_snprintf(entry, sizeof(entry), "FILE_NAME_%d", j); - fname = get_session_file_string(doc); + fname = get_session_file_string(doc, project_root_folder); g_key_file_set_string(config, "files", entry, fname); g_free(fname); j++; @@ -647,7 +670,7 @@ void configuration_save(void) save_recent_files(config, ui_prefs.recent_projects_queue, "recent_projects"); if (cl_options.load_session) - configuration_save_session_files(config); + configuration_save_session_files(config, NULL); #ifdef HAVE_VTE else if (vte_info.have_vte) { @@ -1110,7 +1133,7 @@ void configuration_save_default_session(void) g_key_file_load_from_file(config, configfile, G_KEY_FILE_NONE, NULL); if (cl_options.load_session) - configuration_save_session_files(config); + configuration_save_session_files(config, NULL); /* write the file */ data = g_key_file_to_data(config, NULL, NULL); @@ -1187,7 +1210,7 @@ gboolean configuration_load(void) } -static gboolean open_session_file(gchar **tmp, guint len) +static gboolean open_session_file(gchar **tmp, guint len, gchar *root_folder) { guint pos; const gchar *ft_name; @@ -1199,7 +1222,7 @@ static gboolean open_session_file(gchar **tmp, guint len) /** TODO when we have a global pref for line breaking, use its value */ gboolean line_breaking = FALSE; gboolean ret = FALSE; - + pos = atoi(tmp[0]); ft_name = tmp[1]; ro = atoi(tmp[2]); @@ -1218,6 +1241,25 @@ static gboolean open_session_file(gchar **tmp, guint len) unescaped_filename = g_uri_unescape_string(tmp[7], NULL); locale_filename = utils_get_locale_from_utf8(unescaped_filename); + /* is the locale_filename absolute or relative ? */ + if(!g_path_is_absolute(locale_filename) && root_folder) + { + geany_debug("Relative path %s, root folder %s", locale_filename, root_folder); + gchar *absolute_path; + absolute_path = g_build_path(G_DIR_SEPARATOR_S, root_folder, locale_filename, NULL); + geany_debug("absolute_path : %s",absolute_path); + g_free(locale_filename); + locale_filename = absolute_path; + } + else if(!g_path_is_absolute(locale_filename)) + { + geany_debug("Relative path %s, can't get root folder"); + } + else + { + geany_debug("Absolute path"); + } + if (len > 8) line_breaking = atoi(tmp[8]); @@ -1254,7 +1296,7 @@ static gboolean open_session_file(gchar **tmp, guint len) /* 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(gchar *root_folder) { gint i; gboolean failure = FALSE; @@ -1270,7 +1312,7 @@ void configuration_open_files(void) if (tmp != NULL && (len = g_strv_length(tmp)) >= 8) { - if (! open_session_file(tmp, len)) + if (! open_session_file(tmp, len, root_folder)) failure = TRUE; } g_strfreev(tmp); diff --git a/src/keyfile.h b/src/keyfile.h index 0ef551f16d..331cc10a57 100644 --- a/src/keyfile.h +++ b/src/keyfile.h @@ -44,7 +44,7 @@ void configuration_save(void); gboolean configuration_load(void); -void configuration_open_files(void); +void configuration_open_files(gchar *); void configuration_reload_default_session(void); @@ -54,7 +54,7 @@ void configuration_clear_default_session(void); void configuration_load_session_files(GKeyFile *config, gboolean read_recent_files); -void configuration_save_session_files(GKeyFile *config); +void configuration_save_session_files(GKeyFile *config, gchar * project_root_path); /* set some settings which are already read from the config file, but need other things, like the * realisation of the main window */ diff --git a/src/libmain.c b/src/libmain.c index 80722af91c..79e7eba924 100644 --- a/src/libmain.c +++ b/src/libmain.c @@ -977,7 +977,18 @@ static void load_startup_files(gint argc, gchar **argv) if (load_session) { /* load session files into tabs, as they are found in the session_files variable */ - configuration_open_files(); + gchar* root_path=NULL; + if(app->project) + { + root_path = g_path_get_dirname(app->project->file_name); + configuration_open_files(root_path); + g_free( root_path); + } + else + { + configuration_open_files(NULL); + } + if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook)) == 0) { diff --git a/src/project.c b/src/project.c index 53cab8130a..b67ed69ead 100644 --- a/src/project.c +++ b/src/project.c @@ -73,6 +73,7 @@ typedef struct _PropertyDialogElements GtkWidget *file_name; GtkWidget *base_path; GtkWidget *patterns; + GtkWidget *use_relative_filename; BuildTableData build_properties; gint build_page_num; gboolean entries_modified; @@ -266,7 +267,7 @@ static void run_new_dialog(PropertyDialogElements *e) { // reload any documents that were closed configuration_reload_default_session(); - configuration_open_files(); + configuration_open_files(NULL); } } @@ -277,9 +278,14 @@ gboolean project_load_file_with_session(const gchar *locale_file_name) { if (project_prefs.project_session) { - configuration_open_files(); + gchar * root_path_locale = g_path_get_dirname(locale_file_name); + gchar * root_path_utf8 = utils_get_utf8_from_locale(root_path_locale); + configuration_open_files(root_path_utf8); document_new_file_if_non_open(); ui_focus_current_document(); + + g_free(root_path_locale); + g_free(root_path_utf8); } return TRUE; } @@ -467,7 +473,7 @@ static void destroy_project(gboolean open_default) if (open_default && cl_options.load_session) { configuration_reload_default_session(); - configuration_open_files(); + configuration_open_files(NULL); document_new_file_if_non_open(); ui_focus_current_document(); } @@ -535,6 +541,7 @@ static void create_properties_dialog(PropertyDialogElements *e) e->description = ui_lookup_widget(e->dialog, "textview_project_dialog_description"); e->base_path = ui_lookup_widget(e->dialog, "entry_project_dialog_base_path"); e->patterns = ui_lookup_widget(e->dialog, "entry_project_dialog_file_patterns"); + e->use_relative_filename = ui_lookup_widget(e->dialog, "checkbutton_project_dialog_file_relative"); gtk_entry_set_max_length(GTK_ENTRY(e->name), MAX_NAME_LEN); @@ -611,6 +618,10 @@ static void show_project_properties(gboolean show_build) gtk_entry_set_text(GTK_ENTRY(e.patterns), entry_text); g_free(entry_text); + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(e.use_relative_filename), + p->use_relative_filename ); + g_signal_emit_by_name(geany_object, "project-dialog-open", e.notebook); gtk_widget_show_all(e.dialog); @@ -823,6 +834,8 @@ static gboolean update_config(const PropertyDialogElements *e, gboolean new_proj gtk_text_buffer_get_end_iter(buffer, &end); SETPTR(p->description, gtk_text_buffer_get_text(buffer, &start, &end, FALSE)); + p->use_relative_filename = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(e->use_relative_filename)); + foreach_slist(node, stash_groups) stash_group_update(node->data, e->dialog); @@ -1063,6 +1076,7 @@ static gboolean load_config(const gchar *filename) p->file_name = utils_get_utf8_from_locale(filename); p->base_path = utils_get_setting_string(config, "project", "base_path", ""); p->file_patterns = g_key_file_get_string_list(config, "project", "file_patterns", NULL, NULL); + p->use_relative_filename = utils_get_setting_boolean(config, "project", "relative_files", FALSE); p->priv->long_line_behaviour = utils_get_setting_integer(config, "long line marker", "long_line_behaviour", 1 /* follow global */); @@ -1104,6 +1118,7 @@ static gboolean write_config(void) GeanyProject *p; GKeyFile *config; gchar *filename; + gchar *project_dir=NULL; /* Should be set only if project use relative filename */ gchar *data; gboolean ret = FALSE; GSList *node; @@ -1128,6 +1143,10 @@ static gboolean write_config(void) if (p->file_patterns) g_key_file_set_string_list(config, "project", "file_patterns", (const gchar**) p->file_patterns, g_strv_length(p->file_patterns)); + g_key_file_set_boolean(config, "project", "relative_files", p->use_relative_filename); + if(p->use_relative_filename){ + project_dir=g_path_get_dirname(p->file_name); + } // editor settings g_key_file_set_integer(config, "long line marker", "long_line_behaviour", p->priv->long_line_behaviour); @@ -1135,7 +1154,8 @@ static gboolean write_config(void) /* store the session files into the project too */ if (project_prefs.project_session) - configuration_save_session_files(config); + configuration_save_session_files(config, project_dir); + 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..eefb36f01a 100644 --- a/src/project.h +++ b/src/project.h @@ -41,6 +41,7 @@ typedef struct GeanyProject * by a plugin. */ gint type; GStrv file_patterns; /**< Array of filename extension patterns. */ + gboolean use_relative_filename; struct GeanyProjectPrivate *priv; /* must be last, append fields before this item */ }