Revision: 4974 http://geany.svn.sourceforge.net/geany/?rev=4974&view=rev Author: statc Date: 2010-05-31 09:25:37 +0000 (Mon, 31 May 2010)
Log Message: ----------- Update lists of recent files and projects in geany.conf immediately instead of writing them on exit.
Modified Paths: -------------- branches/sm/ChangeLog.sm branches/sm/src/callbacks.c branches/sm/src/document.c branches/sm/src/document.h branches/sm/src/keyfile.c branches/sm/src/keyfile.h branches/sm/src/main.c branches/sm/src/ui_utils.c branches/sm/src/ui_utils.h
Modified: branches/sm/ChangeLog.sm =================================================================== --- branches/sm/ChangeLog.sm 2010-05-31 09:25:02 UTC (rev 4973) +++ branches/sm/ChangeLog.sm 2010-05-31 09:25:37 UTC (rev 4974) @@ -1,3 +1,11 @@ +2010-05-31 Eugene Arshinov <earshinov(at)gmail(dot)com> + + * src/callbacks.c, src/document.c, src/document.h, src/keyfile.c, + src/keyfile.h, src/main.c, src/ui_utils.c, src/ui_utils.h: + Update lists of recent files and projects in geany.conf immediately + instead of writing them on exit. + + 2010-05-30 Eugene Arshinov <earshinov(at)gmail(dot)com>
* src/main.c:
Modified: branches/sm/src/callbacks.c =================================================================== --- branches/sm/src/callbacks.c 2010-05-31 09:25:02 UTC (rev 4973) +++ branches/sm/src/callbacks.c 2010-05-31 09:25:37 UTC (rev 4974) @@ -233,8 +233,13 @@ on_file1_activate (GtkMenuItem *menuitem, gpointer user_data) { - gtk_widget_set_sensitive(ui_widgets.recent_files_menuitem, - g_queue_get_length(ui_prefs.recent_queue) > 0); + GList *children; + + /* how to determine if submenu is empty efficiently? */ + children = gtk_container_get_children(GTK_CONTAINER(ui_widgets.recent_files_menu_menubar)); + gtk_widget_set_sensitive(ui_widgets.recent_files_menuitem, children != NULL); + g_list_free(children); + #if GTK_CHECK_VERSION(2, 10, 0) /* hide Page setup when GTK printing is not used * (on GTK < 2.10 the menu item is hidden completely) */ @@ -1750,6 +1755,7 @@ on_menu_project1_activate (GtkMenuItem *menuitem, gpointer user_data) { + static GList *children; static GtkWidget *item_close = NULL; static GtkWidget *item_properties = NULL;
@@ -1761,8 +1767,11 @@
gtk_widget_set_sensitive(item_close, (app->project != NULL)); gtk_widget_set_sensitive(item_properties, (app->project != NULL)); - gtk_widget_set_sensitive(ui_widgets.recent_projects_menuitem, - g_queue_get_length(ui_prefs.recent_projects_queue) > 0); + + /* how to determine if submenu is empty efficiently? */ + children = gtk_container_get_children(GTK_CONTAINER(ui_widgets.recent_projects_menu_menubar)); + gtk_widget_set_sensitive(ui_widgets.recent_projects_menuitem, children != NULL); + g_list_free(children); }
@@ -2299,4 +2308,3 @@ plugin_show_configure(NULL); #endif } -
Modified: branches/sm/src/document.c =================================================================== --- branches/sm/src/document.c 2010-05-31 09:25:02 UTC (rev 4973) +++ branches/sm/src/document.c 2010-05-31 09:25:37 UTC (rev 4974) @@ -636,7 +636,7 @@
/* Checking real_path makes it likely the file exists on disk */ if (! main_status.closing_all && doc->real_path != NULL) - ui_add_recent_file(doc->file_name); + ui_add_recent_file(doc->file_name, TRUE);
doc->is_valid = FALSE;
@@ -793,7 +793,7 @@ GeanyDocument *document_open_file(const gchar *locale_filename, gboolean readonly, GeanyFiletype *ft, const gchar *forced_enc) { - return document_open_file_full(NULL, locale_filename, 0, readonly, ft, forced_enc); + return document_open_file_full(NULL, locale_filename, 0, readonly, ft, forced_enc, TRUE); }
@@ -1204,7 +1204,8 @@ * forced_enc can be NULL to detect the file encoding. * Returns: doc of the opened file or NULL if an error occurred. */ GeanyDocument *document_open_file_full(GeanyDocument *doc, const gchar *filename, gint pos, - gboolean readonly, GeanyFiletype *ft, const gchar *forced_enc) + gboolean readonly, GeanyFiletype *ft, const gchar *forced_enc, + gboolean update_recent_files_config) { gint editor_mode; gboolean reload = (doc == NULL) ? FALSE : TRUE; @@ -1244,7 +1245,7 @@ doc = document_find_by_filename(utf8_filename); if (doc != NULL) { - ui_add_recent_file(utf8_filename); /* either add or reorder recent item */ + ui_add_recent_file(utf8_filename, update_recent_files_config); /* either add or reorder recent item */ /* show the doc before reload dialog */ gtk_notebook_set_current_page(GTK_NOTEBOOK(main_widgets.notebook), gtk_notebook_page_num(GTK_NOTEBOOK(main_widgets.notebook), @@ -1333,7 +1334,7 @@
/* finally add current file to recent files menu, but not the files from the last session */ if (! main_status.opening_session_files) - ui_add_recent_file(utf8_filename); + ui_add_recent_file(utf8_filename, update_recent_files_config);
if (! reload) g_signal_emit_by_name(geany_object, "document-open", doc); @@ -1397,9 +1398,10 @@ filename = g_filename_from_uri(list[i], NULL, NULL); if (G_UNLIKELY(filename == NULL)) continue; - document_open_file(filename, FALSE, NULL, NULL); + document_open_file_full(NULL, filename, 0, FALSE, NULL, NULL, FALSE); g_free(filename); } + configuration_save_recent_files();
g_strfreev(list); } @@ -1407,7 +1409,6 @@
/** * Opens each file in the list @a filenames. - * Internally, document_open_file() is called for every list item. * * @param filenames A list of filenames to load, in locale encoding. * @param readonly Whether to open the document in read-only mode. @@ -1421,8 +1422,9 @@
for (item = filenames; item != NULL; item = g_slist_next(item)) { - document_open_file(item->data, readonly, ft, forced_enc); + document_open_file_full(NULL, item->data, 0, readonly, ft, forced_enc, FALSE); } + configuration_save_recent_files(); }
@@ -1444,7 +1446,7 @@
/* try to set the cursor to the position before reloading */ pos = sci_get_current_position(doc->editor->sci); - new_doc = document_open_file_full(doc, NULL, pos, doc->readonly, doc->file_type, forced_enc); + new_doc = document_open_file_full(doc, NULL, pos, doc->readonly, doc->file_type, forced_enc, TRUE);
return (new_doc != NULL); } @@ -1618,7 +1620,7 @@ doc->priv->file_disk_status = FILE_IGNORE;
if (ret) - ui_add_recent_file(doc->file_name); + ui_add_recent_file(doc->file_name, TRUE); return ret; }
@@ -3012,5 +3014,3 @@ } return ret; } - -
Modified: branches/sm/src/document.h =================================================================== --- branches/sm/src/document.h 2010-05-31 09:25:02 UTC (rev 4973) +++ branches/sm/src/document.h 2010-05-31 09:25:37 UTC (rev 4974) @@ -206,7 +206,8 @@ GeanyDocument *document_clone(GeanyDocument *old_doc, const gchar *utf8_filename);
GeanyDocument *document_open_file_full(GeanyDocument *doc, const gchar *filename, gint pos, - gboolean readonly, GeanyFiletype *ft, const gchar *forced_enc); + gboolean readonly, GeanyFiletype *ft, const gchar *forced_enc, + gboolean update_recent_files_config);
void document_open_file_list(const gchar *data, gssize length);
Modified: branches/sm/src/keyfile.c =================================================================== --- branches/sm/src/keyfile.c 2010-05-31 09:25:02 UTC (rev 4973) +++ branches/sm/src/keyfile.c 2010-05-31 09:25:37 UTC (rev 4974) @@ -249,29 +249,38 @@ }
+static void load_recent_files(GKeyFile *config, GQueue *queue, const gchar *key) +{ + gchar **recent_files; + gsize i, len = 0; + + recent_files = g_key_file_get_string_list(config, "files", key, &len, NULL); + if (recent_files != NULL) + { + len = MIN(len, file_prefs.mru_length - queue->length); + for (i = 0; i < len; i++) + if (!g_queue_find_custom(queue, recent_files[i], (GCompareFunc) strcmp)) + g_queue_push_tail(queue, g_strdup(recent_files[i])); + g_strfreev(recent_files); + } +} + + static void save_recent_files(GKeyFile *config, GQueue *queue, gchar const *key) { gchar **recent_files = g_new0(gchar*, file_prefs.mru_length + 1); guint i; + guint len = MIN(queue->length, file_prefs.mru_length);
- for (i = 0; i < file_prefs.mru_length; i++) - { - if (! g_queue_is_empty(queue)) - { - /* copy the values, this is necessary when this function is called from the - * preferences dialog or when quitting is canceled to keep the queue intact */ - recent_files[i] = g_strdup(g_queue_peek_nth(queue, i)); - } - else - { - recent_files[i] = NULL; - break; - } - } + for (i = 0; i < len; i++) + recent_files[i] = g_queue_pop_head(queue); + while (queue->length > 0) + g_free(g_queue_pop_head(queue)); + /* There is a bug in GTK 2.6 g_key_file_set_string_list, we must NULL terminate. */ - recent_files[file_prefs.mru_length] = NULL; + recent_files[len] = NULL; g_key_file_set_string_list(config, "files", key, - (const gchar**)recent_files, file_prefs.mru_length); + (const gchar**)recent_files, len); g_strfreev(recent_files); }
@@ -576,8 +585,6 @@
save_ui_prefs(config); project_save_prefs(config); /* save project filename, etc. */ - save_recent_files(config, ui_prefs.recent_queue, "recent_files"); - save_recent_files(config, ui_prefs.recent_projects_queue, "recent_projects");
if (cl_options.load_session) configuration_save_session_files(config); @@ -587,24 +594,38 @@ }
-static void load_recent_files(GKeyFile *config, GQueue *queue, const gchar *key) +/* Write recent file names to geany.conf. + * Clears `ui_prefs.recent_queue'. */ +void configuration_save_recent_files(void) { - gchar **recent_files; - gsize i, len = 0; + GKeyFile *config; + gchar *configfile; + open_config(&config, &configfile);
- recent_files = g_key_file_get_string_list(config, "files", key, &len, NULL); - if (recent_files != NULL) - { - for (i = 0; (i < len) && (i < file_prefs.mru_length); i++) - { - gchar *filename = g_strdup(recent_files[i]); - g_queue_push_tail(queue, filename); - } - g_strfreev(recent_files); - } + load_recent_files(config, ui_prefs.recent_queue, "recent_files"); + save_recent_files(config, ui_prefs.recent_queue, "recent_files"); + + write_config(config, configfile); + close_config(config, configfile); }
+/* Write recent project file names to geany.conf. + * Clears `ui_prefs.recent_projects_queue'. */ +void configuration_save_recent_projects(void) +{ + GKeyFile *config; + gchar *configfile; + open_config(&config, &configfile); + + load_recent_files(config, ui_prefs.recent_projects_queue, "recent_projects"); + save_recent_files(config, ui_prefs.recent_projects_queue, "recent_projects"); + + write_config(config, configfile); + close_config(config, configfile); +} + + /* * Load session list from the given keyfile, and store it in the global * session_files variable for later file loading @@ -1004,10 +1025,10 @@ if (g_file_test(locale_filename, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK)) { GeanyFiletype *ft = filetypes_lookup_by_name(ft_name); + const gchar *forced_enc = (enc_idx >= 0 && enc_idx < GEANY_ENCODINGS_MAX) ? + encodings[enc_idx].charset : NULL; GeanyDocument *doc = document_open_file_full( - NULL, locale_filename, pos, ro, ft, - (enc_idx >= 0 && enc_idx < GEANY_ENCODINGS_MAX) ? - encodings[enc_idx].charset : NULL); + NULL, locale_filename, pos, ro, ft, forced_enc, TRUE);
if (doc) {
Modified: branches/sm/src/keyfile.h =================================================================== --- branches/sm/src/keyfile.h 2010-05-31 09:25:02 UTC (rev 4973) +++ branches/sm/src/keyfile.h 2010-05-31 09:25:37 UTC (rev 4974) @@ -41,6 +41,10 @@
void configuration_save(void);
+void configuration_save_recent_files(void); + +void configuration_save_recent_projects(void); + gboolean configuration_load(void);
void configuration_open_files(void);
Modified: branches/sm/src/main.c =================================================================== --- branches/sm/src/main.c 2010-05-31 09:25:02 UTC (rev 4973) +++ branches/sm/src/main.c 2010-05-31 09:25:37 UTC (rev 4974) @@ -780,7 +780,10 @@
/* Used for command-line arguments at startup or from socket. - * this will strip any :line:col filename suffix from locale_filename */ + * this will strip any :line:col filename suffix from locale_filename. + * + * After calling this function use configuration_save_recent_files() to + * update list of recent files stored in geany.conf. */ gboolean main_handle_filename(const gchar *locale_filename) { GeanyDocument *doc; @@ -805,7 +808,7 @@ doc = document_open_file(filename, FALSE, NULL, NULL); /* add recent file manually if opening_session_files is set */ if (doc != NULL && main_status.opening_session_files) - ui_add_recent_file(doc->file_name); + ui_add_recent_file(doc->file_name, FALSE); g_free(filename); return TRUE; } @@ -815,7 +818,7 @@
doc = document_new_file(utf8_filename, NULL, NULL); if (doc != NULL) - ui_add_recent_file(doc->file_name); + ui_add_recent_file(doc->file_name, FALSE); g_free(utf8_filename); g_free(filename); return TRUE; @@ -847,6 +850,7 @@ } g_free(filename); } + configuration_save_recent_files(); }
@@ -1269,7 +1273,11 @@ g_free(printing_prefs.page_header_datefmt); g_strfreev(ui_prefs.custom_commands);
+ if (ui_prefs.recent_queue->length > 0) + g_warning("Unsaved recent files (%d)", ui_prefs.recent_queue->length); queue_free(ui_prefs.recent_queue); + if (ui_prefs.recent_projects_queue->length > 0) + g_warning("Unsaved recent projects (%d)", ui_prefs.recent_projects_queue->length); queue_free(ui_prefs.recent_projects_queue);
if (ui_widgets.prefs_dialog && GTK_IS_WIDGET(ui_widgets.prefs_dialog)) gtk_widget_destroy(ui_widgets.prefs_dialog);
Modified: branches/sm/src/ui_utils.c =================================================================== --- branches/sm/src/ui_utils.c 2010-05-31 09:25:02 UTC (rev 4973) +++ branches/sm/src/ui_utils.c 2010-05-31 09:25:37 UTC (rev 4974) @@ -935,6 +935,21 @@ }
+static gint find_recent_file_item(gconstpointer list_data, gconstpointer user_data) +{ + gchar *menu_text = ui_menu_item_get_text(GTK_MENU_ITEM(list_data)); + gint result; + + if (utils_str_equal(menu_text, user_data)) + result = 0; + else + result = 1; + + g_free(menu_text); + return result; +} + + static void recent_create_menu(GeanyRecentFiles *grf) { GtkWidget *tmp; @@ -993,10 +1008,17 @@ }
+/* Create recent menus. + * Clears `ui_prefs.recent_queue' and `ui_prefs.recent_projects_queue'. */ void ui_create_recent_menus(void) { - recent_create_menu(recent_get_recent_files()); - recent_create_menu(recent_get_recent_projects()); + GeanyRecentFiles *grf = recent_get_recent_files(); + recent_create_menu(grf); + g_queue_clear(grf->recent_queue); + + grf = recent_get_recent_projects(); + recent_create_menu(grf); + g_queue_clear(grf->recent_queue); }
@@ -1006,7 +1028,10 @@ gchar *locale_filename = utils_get_locale_from_utf8(utf8_filename);
if (document_open_file(locale_filename, FALSE, NULL, NULL) != NULL) + { recent_file_loaded(utf8_filename, recent_get_recent_files()); + configuration_save_recent_files(); + }
g_free(locale_filename); g_free(utf8_filename); @@ -1019,7 +1044,10 @@ gchar *locale_filename = utils_get_locale_from_utf8(utf8_filename);
if (project_ask_close() && project_load_file_with_session(locale_filename)) + { recent_file_loaded(utf8_filename, recent_get_recent_projects()); + configuration_save_recent_projects(); + }
g_free(locale_filename); g_free(utf8_filename); @@ -1028,7 +1056,15 @@
static void add_recent_file(const gchar *utf8_filename, GeanyRecentFiles *grf) { - if (g_queue_find_custom(grf->recent_queue, utf8_filename, (GCompareFunc) strcmp) == NULL) + GList *items, *item; + gboolean already_exists; + + items = gtk_container_get_children(GTK_CONTAINER(grf->menubar)); + item = g_list_find_custom(items, utf8_filename, (GCompareFunc) find_recent_file_item); + already_exists = (item != NULL); + g_list_free(items); + + if (!already_exists) { #if GTK_CHECK_VERSION(2, 10, 0) if (grf->type == RECENT_FILE_FILE) @@ -1055,15 +1091,18 @@ }
-void ui_add_recent_file(const gchar *utf8_filename) +void ui_add_recent_file(const gchar *utf8_filename, gboolean update_config) { add_recent_file(utf8_filename, recent_get_recent_files()); + if (update_config) + configuration_save_recent_files(); }
void ui_add_recent_project_file(const gchar *utf8_filename) { add_recent_file(utf8_filename, recent_get_recent_projects()); + configuration_save_recent_projects(); }
@@ -1084,21 +1123,6 @@ }
-static gint find_recent_file_item(gconstpointer list_data, gconstpointer user_data) -{ - gchar *menu_text = ui_menu_item_get_text(GTK_MENU_ITEM(list_data)); - gint result; - - if (utils_str_equal(menu_text, user_data)) - result = 0; - else - result = 1; - - g_free(menu_text); - return result; -} - - static void recent_file_loaded(const gchar *utf8_filename, GeanyRecentFiles *grf) { GList *item, *children; @@ -1107,10 +1131,13 @@
/* first reorder the queue */ item = g_queue_find_custom(grf->recent_queue, utf8_filename, (GCompareFunc) strcmp); - g_return_if_fail(item != NULL); - - data = item->data; - g_queue_remove(grf->recent_queue, data); + if (item != NULL) + { + data = item->data; + g_queue_remove(grf->recent_queue, data); + } + else + data = g_strdup(utf8_filename); g_queue_push_head(grf->recent_queue, data);
/* remove the old menuitem for the filename */
Modified: branches/sm/src/ui_utils.h =================================================================== --- branches/sm/src/ui_utils.h 2010-05-31 09:25:02 UTC (rev 4973) +++ branches/sm/src/ui_utils.h 2010-05-31 09:25:37 UTC (rev 4974) @@ -94,9 +94,13 @@ gboolean msgwindow_visible; gboolean allow_always_save; /* if set, files can always be saved, even if unchanged */
- /* Menu-item related data */ + /* Queues which temporarily store recent files and projects until they are + * written to geany.conf. Should contain file_prefs.mru_length elements max. + * Element type: gchar *. */ GQueue *recent_queue; GQueue *recent_projects_queue; + + /* Other menu-item related data */ gchar *custom_date_format; gchar **custom_commands; } @@ -279,7 +283,7 @@
void ui_create_recent_menus(void);
-void ui_add_recent_file(const gchar *utf8_filename); +void ui_add_recent_file(const gchar *utf8_filename, gboolean update_config);
void ui_add_recent_project_file(const gchar *utf8_filename);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.