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
+
+
+
+ 5
+ 6
+ GTK_FILL
+ GTK_FILL
+
+
+
+
+
+ 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 */
}