From 899dce26b681b83b74ed78b73555ef19a3ca81a9 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Wed, 26 Nov 2008 13:15:53 +0000 Subject: [PATCH] Add 'Tools->Configuration Files' menu with items to open filetype_extensions.conf and ignore.tags. These files are also reloaded automatically when saved. - Code changes: Make app->configdir a realpath(). Add ui_add_config_file_menu_item(). Add utils_build_path(), similar to g_build_path() but (re)using a fixed buffer, so the result is never freed. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@3279 ea778897-0a13-0410-b9d1-a72fbfd435f5 --- ChangeLog | 14 ++++++++++++ src/filetypes.c | 22 ++++++++++++++++++ src/geany.h | 1 + src/main.c | 1 + src/symbols.c | 15 +++++++++++++ src/ui_utils.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ src/ui_utils.h | 3 +++ src/utils.c | 32 ++++++++++++++++++++++++++ src/utils.h | 2 ++ 9 files changed, 150 insertions(+) diff --git a/ChangeLog b/ChangeLog index 6988b13b9..a5e81cf6f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2008-11-26 Nick Treleaven + + * src/utils.c, src/ui_utils.h, src/utils.h, src/geany.h, + src/filetypes.c, src/main.c, src/symbols.c, src/ui_utils.c: + Add 'Tools->Configuration Files' menu with items to open + filetype_extensions.conf and ignore.tags. These files are also + reloaded automatically when saved. + - Code changes: + Make app->configdir a realpath(). + Add ui_add_config_file_menu_item(). + Add utils_build_path(), similar to g_build_path() but (re)using a + fixed buffer, so the result is never freed. + + 2008-11-25 Nick Treleaven * src/main.c, src/symbols.c, src/symbols.h: diff --git a/src/filetypes.c b/src/filetypes.c index c03c3097b..deee2cf7a 100644 --- a/src/filetypes.c +++ b/src/filetypes.c @@ -40,6 +40,8 @@ #include "utils.h" #include "sciwrappers.h" #include "ui_utils.h" +#include "keyfile.h" +#include "geanyobject.h" #include @@ -583,6 +585,25 @@ void filetypes_init_types() } +static void on_document_save(G_GNUC_UNUSED GObject *object, GeanyDocument *doc) +{ + g_return_if_fail(NZV(doc->real_path)); + + if (utils_str_equal(doc->real_path, + utils_build_path(app->configdir, "filetype_extensions.conf", NULL))) + configuration_read_filetype_extensions(); +} + + +static void setup_config_file_menus(void) +{ + ui_add_config_file_menu_item( + utils_build_path(app->configdir, "filetype_extensions.conf", NULL), NULL, NULL); + + g_signal_connect(geany_object, "document-save", G_CALLBACK(on_document_save), NULL); +} + + #define create_sub_menu(menu, item, title) \ (menu) = gtk_menu_new(); \ (item) = gtk_menu_item_new_with_mnemonic((title)); \ @@ -645,6 +666,7 @@ void filetypes_init() { filetypes_init_types(); create_set_filetype_menu(); + setup_config_file_menus(); } diff --git a/src/geany.h b/src/geany.h index d3a086fcb..be99afce5 100644 --- a/src/geany.h +++ b/src/geany.h @@ -64,6 +64,7 @@ typedef struct GeanyApp { gboolean debug_mode; /**< @c TRUE if debug messages should be printed. */ /** User configuration directory, usually @c ~/.config/geany. + * This is a full path read by @ref tm_get_real_path(). * @note Plugin configuration files should be saved as: * @code g_build_path(G_DIR_SEPARATOR_S, geany->app->configdir, "plugins", "pluginname", * "file.conf"); @endcode */ diff --git a/src/main.c b/src/main.c index 85578aec7..430ccee1e 100644 --- a/src/main.c +++ b/src/main.c @@ -544,6 +544,7 @@ static void parse_command_line_options(gint *argc, gchar ***argv) { app->configdir = g_build_filename(g_get_user_config_dir(), "geany", NULL); } + setptr(app->configdir, tm_get_real_path(app->configdir)); #ifdef GEANY_DEBUG if (generate_datafiles) diff --git a/src/symbols.c b/src/symbols.c index 52fcef822..3f0b51e86 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -50,6 +50,7 @@ #include "ui_utils.h" #include "editor.h" #include "sciwrappers.h" +#include "geanyobject.h" const guint TM_GLOBAL_TYPE_MASK = @@ -1774,9 +1775,23 @@ static void create_taglist_popup_menu(void) } +static void on_document_save(G_GNUC_UNUSED GObject *object, GeanyDocument *doc) +{ + g_return_if_fail(NZV(doc->real_path)); + + if (utils_str_equal(doc->real_path, + utils_build_path(app->configdir, "ignore.tags", NULL))) + load_c_ignore_tags(); +} + + void symbols_init(void) { create_taglist_popup_menu(); + + ui_add_config_file_menu_item(utils_build_path(app->configdir, "ignore.tags", NULL), + NULL, NULL); + g_signal_connect(geany_object, "document-save", G_CALLBACK(on_document_save), NULL); } diff --git a/src/ui_utils.c b/src/ui_utils.c index e251af86e..d86a329b8 100644 --- a/src/ui_utils.c +++ b/src/ui_utils.c @@ -67,6 +67,7 @@ static struct GtkWidget *redo_items[3]; GtkWidget *undo_items[3]; GtkWidget *save_buttons[4]; + GtkWidget *config_files_menu; } widgets; @@ -1564,6 +1565,64 @@ void ui_table_add_row(GtkTable *table, gint row, ...) } +static void on_config_file_clicked(GtkWidget *widget, gpointer user_data) +{ + const gchar *file_name = user_data; + + if (g_file_test(file_name, G_FILE_TEST_EXISTS)) + document_open_file(file_name, FALSE, NULL, NULL); + else + { + gchar *utf8 = utils_get_utf8_from_locale(file_name); + + document_new_file(utf8, NULL, NULL); + g_free(utf8); + } +} + + +/* @note You should connect to the "document-save" signal yourself to detect + * if the user has just saved the config file, reloading it. */ +void ui_add_config_file_menu_item(const gchar *real_path, const gchar *label, + GtkContainer *parent) +{ + GtkWidget *item; + + if (!parent) + parent = GTK_CONTAINER(widgets.config_files_menu); + + if (!label) + { + gchar *base_name; + + base_name = g_path_get_basename(real_path); + item = gtk_menu_item_new_with_label(base_name); + g_free(base_name); + } + else + item = gtk_menu_item_new_with_mnemonic(label); + + gtk_widget_show(item); + gtk_container_add(parent, item); + g_signal_connect(item, "activate", G_CALLBACK(on_config_file_clicked), + /* this memory is kept */ + g_strdup(real_path)); +} + + +static void create_config_files_menu(void) +{ + GtkWidget *menu, *item; + + widgets.config_files_menu = menu = gtk_menu_new(); + + item = ui_image_menu_item_new(GTK_STOCK_FILE, _("C_onfiguration Files")); + gtk_widget_show(item); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu); + gtk_container_add(GTK_CONTAINER(main_widgets.tools_menu), item); +} + + void ui_init(void) { ui_widgets.statusbar = lookup_widget(main_widgets.window, "statusbar"); @@ -1593,6 +1652,7 @@ void ui_init(void) widgets.undo_items[2] = lookup_widget(main_widgets.window, "toolbutton_undo"); init_document_widgets(); + create_config_files_menu(); } diff --git a/src/ui_utils.h b/src/ui_utils.h index a3d5f2071..2d389619d 100644 --- a/src/ui_utils.h +++ b/src/ui_utils.h @@ -172,6 +172,9 @@ void ui_auto_separator_add_ref(GeanyAutoSeparator *autosep, GtkWidget *item); void ui_init(void); +void ui_add_config_file_menu_item(const gchar *real_path, const gchar *label, + GtkContainer *parent); + void ui_set_statusbar(gboolean log, const gchar *format, ...) G_GNUC_PRINTF (2, 3); diff --git a/src/utils.c b/src/utils.c index 5ea5c0825..f15a5d41b 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1518,3 +1518,35 @@ gboolean utils_spawn_async(const gchar *dir, gchar **argv, gchar **env, GSpawnFl #endif return result; } + + +/* Similar to g_build_path() but (re)using a fixed buffer, so never free it. + * This assumes a small enough resulting string length to be kept without freeing, + * but this should be the case for filenames. */ +const gchar *utils_build_path(const gchar *first, ...) +{ + static GString *buffer; + const gchar *str; + va_list args; + + if (!buffer) + buffer = g_string_new(first); + else + g_string_assign(buffer, first); + + va_start(args, first); + while (1) + { + str = va_arg(args, const gchar *); + if (!str) + break; + + g_string_append_c(buffer, G_DIR_SEPARATOR); + g_string_append(buffer, str); + } + va_end(args); + + return buffer->str; +} + + diff --git a/src/utils.h b/src/utils.h index 2eb92c44d..42ac070b9 100644 --- a/src/utils.h +++ b/src/utils.h @@ -141,4 +141,6 @@ gboolean utils_spawn_async(const gchar *dir, gchar **argv, gchar **env, GSpawnFl gint utils_str_casecmp(const gchar *s1, const gchar *s2); +const gchar *utils_build_path(const gchar *first, ...) G_GNUC_NULL_TERMINATED; + #endif