Branch: refs/heads/master Author: federeghe federico.dev@reghe.net Committer: federeghe federico.dev@reghe.net Date: Tue, 15 Apr 2014 06:52:28 UTC Commit: d645bf57477277725851ee6aed2c7a9aa7d96edc https://github.com/geany/geany-plugins/commit/d645bf57477277725851ee6aed2c7a...
Log Message: ----------- Complete the configuration widget of codenav plugin
Modified Paths: -------------- codenav/src/codenavigation.c codenav/src/codenavigation.h codenav/src/switch_head_impl.c codenav/src/switch_head_impl.h
Modified: codenav/src/codenavigation.c 493 lines changed, 436 insertions(+), 57 deletions(-) =================================================================== @@ -3,6 +3,7 @@ * part of the "geany-plugins" project. * * Copyright 2009 Lionel Fuentes <funto66(at)gmail(dot)com> + * Copyright 2014 Federico Reghenzani <federico(dot)dev(at)reghe(dot)net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,11 +21,6 @@ * MA 02110-1301, USA. */
-/** - * Code navigation plugin - plugin which adds facilities for navigating between files. - * 2009 Lionel Fuentes. - */ - #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -34,55 +30,147 @@ #include "switch_head_impl.h" #include "goto_file.h"
-/************************* Global variables ***************************/ - -/* These items are set by Geany before plugin_init() is called. */ -GeanyPlugin *geany_plugin; -GeanyData *geany_data; -GeanyFunctions *geany_functions; +/************************* Plugin utilities ***************************/
/* Check that the running Geany supports the plugin API used below, and check * for binary compatibility. */ -PLUGIN_VERSION_CHECK(112) +PLUGIN_VERSION_CHECK(200)
/* All plugins must set name, description, version and author. */ PLUGIN_SET_TRANSLATABLE_INFO( LOCALEDIR, GETTEXT_PACKAGE, _("Code navigation"), - _( "This plugin adds features to facilitate navigation between source files.\n" - "As for the moment, it implements :\n" - "- switching between a .cpp file and the corresponding .h file\n" - "- [opening a file by typing its name -> TODO]"), CODE_NAVIGATION_VERSION, "Lionel Fuentes") + _( "This plugin adds features to facilitate navigation between source files."), + CODE_NAVIGATION_VERSION, "Lionel Fuentes, Federico Reghenzani")
/* Declare "GeanyKeyGroupInfo plugin_key_group_info[1]" and "GeanyKeyGroup *plugin_key_group", * for Geany to find the keybindings */ PLUGIN_KEY_GROUP(code_navigation, NB_KEY_IDS)
-/***************************** Functions ******************************/ + +/********************* Data types for the feature *********************/ +/* Column for the configuration widget */ +typedef enum +{ + COLUMN_IMPL = 0, + COLUMN_HEAD, + NB_COLUMNS +} Column; + +/************************* Global variables ***************************/ + +/* These items are set by Geany before plugin_init() is called. */ +GeanyPlugin *geany_plugin; +GeanyData *geany_data; +GeanyFunctions *geany_functions; + +static GtkListStore *list_store; /* for settings dialog */ + + +/**************************** Prototypes ******************************/ + +GtkWidget* +config_widget(void); + +static void +load_configuration(); + +static void +on_configure_add_language(GtkWidget* widget, gpointer data); + +static void +on_configure_remove_language(GtkWidget* widget, gpointer data); + +static void +on_configure_cell_edited(GtkCellRendererText* text, gchar* arg1, gchar* arg2, gpointer data);
static void on_configure_response(GtkDialog *dialog, gint response, gpointer user_data);
-/* --------------------------------------------------------------------- - * Called by Geany to initialize the plugin. - * Note: data is the same as geany_data. - * --------------------------------------------------------------------- +/***************************** Functions ******************************/ + +/** + * @brief Called by Geany to initialize the plugin. + * @note data is the same as geany_data. */ void plugin_init(GeanyData *data) { log_func();
+ /* Load configuration */ + load_configuration(); /* Initialize the features */ switch_head_impl_init(); goto_file_init(); }
-/* --------------------------------------------------------------------- - * Called by Geany to show the plugin's configure dialog. This function - * is always called after plugin_init() is called. - * --------------------------------------------------------------------- +/** + * @brief load plugin's configuration or set default values + * @param void + * @return void + * + */ +static void load_configuration() +{ + GKeyFile *config = NULL; + gchar *config_filename = NULL; + gchar **impl_list = NULL, **head_list = NULL; + gsize head_list_len, impl_list_len; + int i; + + /* Load user configuration */ + config = g_key_file_new(); + config_filename = g_strconcat(geany->app->configdir, G_DIR_SEPARATOR_S, + "plugins", G_DIR_SEPARATOR_S, "codenav", G_DIR_SEPARATOR_S, "codenav.conf", NULL); + gboolean is_configured = g_key_file_load_from_file(config, config_filename, G_KEY_FILE_NONE, NULL); + + if ( is_configured ) { + log_debug("Loading user configuration"); + impl_list = g_key_file_get_string_list(config, "switch_head_impl", "implementations_list", &impl_list_len, NULL); + head_list = g_key_file_get_string_list(config, "switch_head_impl", "headers_list", &head_list_len, NULL); + + // Wrong lists + if ( head_list_len != impl_list_len ) { + dialogs_show_msgbox(GTK_MESSAGE_WARNING, + _("Codenav head/impl lists should have been same length. " \ + "Geany will use the default configuration.")); + fill_default_languages_list(); + } + else + fill_languages_list((const gchar**) impl_list, (const gchar**) head_list, head_list_len); + } + else { + log_debug("Fresh configuration"); + fill_default_languages_list(); + } + + + /* Freeing memory */ + g_key_file_free(config); + g_free(config_filename); + + if ( impl_list != NULL ) { + for ( i = 0; i < impl_list_len; i++ ) + g_free(impl_list[i]); + g_free(impl_list); + } + if ( head_list != NULL ) { + for ( i = 0; i < head_list_len; i++ ) + g_free(head_list[i]); + g_free(head_list); + } + +} + +/** + * @brief Called by Geany to show the plugin's configure dialog. This function + * is always called after plugin_init() is called. + * @param the plugin GtkWidget* + * @return the GtkDialog from Geany + * */ + GtkWidget *plugin_configure(GtkDialog *dialog) { GtkWidget *vbox; @@ -92,7 +180,7 @@ GtkWidget *plugin_configure(GtkDialog *dialog) vbox = gtk_vbox_new(FALSE, 6);
/* Switch header/implementation widget */ - gtk_box_pack_start(GTK_BOX(vbox), switch_head_impl_config_widget(), TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbox), config_widget(), TRUE, TRUE, 0);
gtk_widget_show_all(vbox);
@@ -102,9 +190,11 @@ GtkWidget *plugin_configure(GtkDialog *dialog) return vbox; }
-/* --------------------------------------------------------------------- - * Called by Geany before unloading the plugin. - * --------------------------------------------------------------------- +/** + * @brief Called by Geany before unloading the plugin + * @param void + * @return void + * */ void plugin_cleanup(void) { @@ -115,45 +205,334 @@ void plugin_cleanup(void) switch_head_impl_cleanup(); }
-/* --------------------------------------------------------------------- - * Callback called when validating the configuration of the plug-in - * --------------------------------------------------------------------- +/** + * @brief Callback called when validating the configuration of the plug-in + * @param dialog the parent dialog, not very interesting here + * @param response OK/Cancel/Apply user action + * @param user_data NULL + * + * @return void + * */ static void on_configure_response(GtkDialog* dialog, gint response, gpointer user_data) { - /* TODO */ -#if 0 - GKeyFile* key_file = NULL; - gchar* config_dir = NULL; - gchar* config_filename = NULL; + gint i=0; + + GKeyFile *config = NULL; + gchar *config_filename = NULL; + gchar *config_dir = NULL; + gchar *data; + + gsize list_len; + gchar** head_list = NULL; + gchar** impl_list = NULL; + + GtkTreeIter iter; + + log_func(); + + if(response != GTK_RESPONSE_OK && response != GTK_RESPONSE_APPLY) + return; + + /* Write the settings into a file, using GLib's GKeyFile API. + * File name : + * geany->app->configdir G_DIR_SEPARATOR_S "plugins" G_DIR_SEPARATOR_S + * "codenav" G_DIR_SEPARATOR_S "codenav.conf" + * e.g. this could be: ~/.config/geany/plugins/codenav/codenav.conf + */ + + /* Open the GKeyFile */ + config = g_key_file_new(); + config_filename = g_strconcat(geany->app->configdir, G_DIR_SEPARATOR_S, + "plugins", G_DIR_SEPARATOR_S, "codenav", + G_DIR_SEPARATOR_S, "codenav.conf", NULL); + config_dir = g_path_get_dirname(config_filename); + + /* Allocate the list */ + list_len = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(list_store), NULL); + impl_list = g_malloc0( sizeof(gchar**) * list_len); + head_list = g_malloc0( sizeof(gchar**) * list_len); + + if ( list_len > 0 ) { + // Get the first item + gtk_tree_model_iter_children (GTK_TREE_MODEL(list_store),&iter,NULL); + + do { /* forall elements in list... */ + + /* TODO: remove empty lines */ + + gtk_tree_model_get (GTK_TREE_MODEL(list_store),&iter, + COLUMN_IMPL,&impl_list[i], -1); + gtk_tree_model_get (GTK_TREE_MODEL(list_store),&iter, + COLUMN_HEAD,&head_list[i], -1); + i++; + } while ( gtk_tree_model_iter_next(GTK_TREE_MODEL(list_store), &iter) ); + } + + /* write lists */ + g_key_file_set_string_list(config, "switch_head_impl", "implementations_list", + (const gchar * const*)impl_list, list_len); + g_key_file_set_string_list(config, "switch_head_impl", "headers_list", + (const gchar * const*)head_list, list_len); + + if (! g_file_test(config_dir, G_FILE_TEST_IS_DIR) && utils_mkdir(config_dir, TRUE) != 0) + { + dialogs_show_msgbox(GTK_MESSAGE_ERROR, + _("Plugin configuration directory could not be created.")); + } + else + { + /* write config to file */ + data = g_key_file_to_data(config, NULL, NULL); + utils_write_file(config_filename, data); + g_free(data); + } + + fill_languages_list((const gchar**)impl_list, (const gchar**)head_list, list_len); + + /* Freeing memory */ + for ( i=0; i < list_len; i++ ) { + g_free(impl_list[i]); + g_free(head_list[i]); + } + g_free(impl_list); + g_free(head_list); + + g_free(config_dir); + g_free(config_filename); + g_key_file_free(config); + +} + + /** + * @brief Utility function to concatenate the extensions of a language, + * separated with a comma, like PHP-implode function. + * @param extensions a list of (string) extensions + * + * @return concatenated string. + * + */ +static gchar* +concatenate_extensions(GSList* extensions) +{ + GSList* iter_ext; + gchar* p_str = NULL; + gchar* temp = NULL;
- if(response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY) + for(iter_ext = extensions ; iter_ext != NULL ; iter_ext = iter_ext->next) { - /* Write the settings into a file, using GLib's GKeyFile API. - * File name : - * geany->app->configdir G_DIR_SEPARATOR_S "plugins" G_DIR_SEPARATOR_S "codenav" G_DIR_SEPARATOR_S "codenav.conf" - * e.g. this could be: ~/.config/geany/plugins/codenav/codenav.conf - */ + temp = p_str; + p_str = g_strjoin(",", (const gchar*)(iter_ext->data), p_str, NULL); + g_free(temp); + } + + return p_str; +} + +/** + * @brief Utility function to add a language to a GtkListStore + * @param list the list where to add lang + * @param lang the item to add + * + * @return void + * + */ +static void +add_language(GtkListStore* list, Language* lang) +{ + gchar* p_str = NULL; + GtkTreeIter tree_iter; + + if(lang->head_extensions == NULL || lang->impl_extensions == NULL) + return; + + /* Append an empty row */ + gtk_list_store_append(list, &tree_iter); + + /* Header extensions */ + p_str = concatenate_extensions(lang->head_extensions); + gtk_list_store_set(list, &tree_iter, COLUMN_HEAD, p_str, -1); + g_free(p_str); + + /* Implementation extensions */ + p_str = concatenate_extensions(lang->impl_extensions); + gtk_list_store_set(list, &tree_iter, COLUMN_IMPL, p_str, -1); + g_free(p_str); +} + +/** + * @brief The configuration widget + * + * @return The configuration widget + * + */ +GtkWidget* +config_widget(void) +{ + GtkWidget *help_label; + GtkWidget *frame, *vbox, *tree_view; + GtkWidget *hbox_buttons, *add_button, *remove_button; + GtkTreeViewColumn *column; + GtkCellRenderer *cell_renderer; + + GSList *iter_lang; + + log_func(); + + /* Frame, which is the returned widget */ + frame = gtk_frame_new(_("Switch header/implementation")); + + /* Main VBox */ + vbox = gtk_vbox_new(FALSE, 0); + gtk_container_add(GTK_CONTAINER(frame), vbox); + + /* Help label */ + help_label = gtk_label_new(_("You can specify multiple extensions by " \ + "separating them by commas.")); + gtk_box_pack_start(GTK_BOX(vbox), help_label, FALSE, FALSE, 6); + + /* ======= Extensions list ======= */ + + /* Add a list containing the extensions for each language (headers / implementations) */ + /* - create the GtkListStore */ + list_store = gtk_list_store_new(NB_COLUMNS, G_TYPE_STRING, G_TYPE_STRING); + + /* - fill the GtkListStore with the extensions of the languages */ + for(iter_lang = switch_head_impl_get_languages(); + iter_lang != NULL ; iter_lang = iter_lang->next) + add_language(list_store, (Language*)(iter_lang->data)); + + /* - create the GtkTreeView */ + tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store)); + + /* - add the columns */ + /* -> implementations : */ + cell_renderer = gtk_cell_renderer_text_new(); + g_object_set(G_OBJECT(cell_renderer), "editable", TRUE, NULL); + g_signal_connect_after(G_OBJECT(cell_renderer), "edited", G_CALLBACK(on_configure_cell_edited), GINT_TO_POINTER(COLUMN_IMPL)); + column = gtk_tree_view_column_new_with_attributes( _("Implementations extensions"), cell_renderer, + "text", COLUMN_IMPL, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column); + + /* -> headers : */ + cell_renderer = gtk_cell_renderer_text_new(); + g_object_set(G_OBJECT(cell_renderer), "editable", TRUE, NULL); + g_signal_connect_after(G_OBJECT(cell_renderer), "edited", G_CALLBACK(on_configure_cell_edited), GINT_TO_POINTER(COLUMN_HEAD)); + column = gtk_tree_view_column_new_with_attributes( _("Headers extensions"), cell_renderer, + "text", COLUMN_HEAD, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column); + + + /* - finally add the GtkTreeView to the frame's vbox */ + gtk_box_pack_start(GTK_BOX(vbox), tree_view, TRUE, TRUE, 6);
- /* Open the GKeyFile */ - key_file = g_key_file_new();
- config_dir = g_strconcat(geany->app->configdir, - G_DIR_SEPARATOR_S "plugins" G_DIR_SEPARATOR_S "codenav" G_DIR_SEPARATOR_S, NULL); + /* ========= Buttons ======== */
- config_filename = g_strconcat(config_dir, "codenav.conf", NULL); + /* HBox */ + hbox_buttons = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox_buttons, FALSE, FALSE, 0);
- /* Load configuration */ - g_key_file_load_from_file(key_file, config_filename, G_KEY_FILE_NONE, NULL); + /* Add the "add" button to the frame's hbox */ + add_button = gtk_button_new_from_stock(GTK_STOCK_ADD); + g_signal_connect(G_OBJECT(add_button), "clicked", G_CALLBACK(on_configure_add_language), tree_view); + gtk_box_pack_start(GTK_BOX(hbox_buttons), add_button, FALSE, FALSE, 0);
- /* Write configuration */ - write_switch_head_impl_config(key_file); + /* Add the "remove" button to the frame's hbox */ + remove_button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); + g_signal_connect(G_OBJECT(remove_button), "clicked", G_CALLBACK(on_configure_remove_language), tree_view); + gtk_box_pack_start(GTK_BOX(hbox_buttons), remove_button, FALSE, FALSE, 0);
- /* Cleanup */ - g_free(config_filename); - g_free(config_dir); - g_key_file_free(key_file); + + gtk_widget_grab_focus(tree_view); + + return frame; +} + + /** + * @brief Callback for adding a language in the configuration dialog + * @param button the button, not used here + * @param data gtktreeview where to act + * + * @return void + * + */ +static void +on_configure_add_language(GtkWidget* button, gpointer data) +{ + GtkWidget* tree_view = (GtkWidget*)data; + GtkTreeIter tree_iter; + GtkTreePath *path; + GtkTreeViewColumn* column = NULL; + gint nb_lines; + + log_func(); + + /* Add a line */ + gtk_list_store_append(list_store, &tree_iter); + + /* and give the focus to it */ + nb_lines = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(list_store), NULL); + path = gtk_tree_path_new_from_indices(nb_lines-1, -1); + column = gtk_tree_view_get_column(GTK_TREE_VIEW(tree_view), 0); + gtk_tree_view_set_cursor(GTK_TREE_VIEW(tree_view), path, column, TRUE); + + gtk_tree_path_free(path); +} + +/** + * @brief Callback for removing a language in the configuration dialog + * @param button the button, not used here + * @param data gtktreeview where to act + * + * @return void + * + */ +static void +on_configure_remove_language(GtkWidget* button, gpointer data) +{ + GtkTreeView* tree_view = (GtkTreeView*)data; + GtkTreeSelection *selection; + GtkTreeIter tree_iter; + + log_func(); + + selection = gtk_tree_view_get_selection (tree_view); + + if ( ! gtk_tree_selection_get_selected(selection, NULL, &tree_iter) ) { + log_debug("Delete without selection!"); + return; } -#endif + /* Remove the element */ + gtk_list_store_remove(list_store, &tree_iter); +} + +/** + * @brief Callback called when a cell has been edited in the configuration + * dialog + * @param renderer field object + * @param path + * @param text the new text + * @param data column where event is called + * + * @return void + * + */ +static void +on_configure_cell_edited(GtkCellRendererText* renderer, gchar* path, gchar* text, gpointer data) +{ + GtkTreeIter iter; + Column col = (Column)(GPOINTER_TO_INT(data)); + + log_func(); + + /* TODO: check correctness of text inserted */ + + /* Replace old text with new */ + gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(list_store), &iter, path); + gtk_list_store_set(list_store, &iter, col, text, -1); + }
Modified: codenav/src/codenavigation.h 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -45,7 +45,7 @@ #include "geanyfunctions.h" /* this wraps geany_functions function pointers */
/* Debug flag */ -/* #define CODE_NAVIGATION_DEBUG */ +#define CODE_NAVIGATION_DEBUG
#define CODE_NAVIGATION_VERSION "0.2"
Modified: codenav/src/switch_head_impl.c 290 lines changed, 52 insertions(+), 238 deletions(-) =================================================================== @@ -28,45 +28,29 @@ #include "switch_head_impl.h" #include "utils.h"
-/********************* Data types for the feature *********************/
-/* Structure representing a handled language */ -typedef struct -{ - const gchar* name; - GSList* head_extensions; /* e.g. : "h", "hpp", ... */ - GSList* impl_extensions; /* e.g. : "cpp", "cxx", ... */ -} Language; +/****************************** Useful macro **************************/ +#define HEAD_PREPEND(str_ext) \ + { lang->head_extensions = g_slist_prepend(lang->head_extensions, g_strdup(str_ext)); } +#define IMPL_PREPEND(str_ext) \ + { lang->impl_extensions = g_slist_prepend(lang->impl_extensions, g_strdup(str_ext)); }
-/* Column for the configuration widget */ -typedef enum -{ - COLUMN_HEAD, - COLUMN_IMPL, - NB_COLUMNS -} Column;
/******************* Global variables for the feature *****************/
static GtkWidget* menu_item = NULL; static GSList* languages = NULL; /* handled languages */
-/********************** Functions for the feature *********************/
-static void -fill_default_languages_list(void); +/**************************** Prototypes ******************************/ +void +languages_clean(void);
static void menu_item_activate(guint key_id);
-static void -on_configure_add_language(GtkWidget* widget, gpointer data); +/********************** Functions for the feature *********************/
-static void -on_configure_remove_language(GtkWidget* widget, gpointer data); - -static void -on_configure_cell_edited(GtkCellRendererText* text, gchar* arg1, gchar* arg2, gpointer data);
/* --------------------------------------------------------------------- * Initialization @@ -76,7 +60,6 @@ void switch_head_impl_init(void) { GtkWidget* edit_menu; - log_func();
edit_menu = ui_lookup_widget(geany->main_widgets->window, "edit1_menu"); @@ -99,8 +82,6 @@ switch_head_impl_init(void) _("Switch header/implementation"), /* used in the Preferences dialog */ menu_item);
- /* TODO : we should use the languages specified by the user or the default list */ - fill_default_languages_list(); }
/* --------------------------------------------------------------------- @@ -110,11 +91,15 @@ switch_head_impl_init(void) void switch_head_impl_cleanup(void) { - GSList* iter = NULL; - log_func();
gtk_widget_destroy(menu_item); + languages_clean(); +} + +void languages_clean(void) +{ + GSList* iter = NULL;
for(iter = languages ; iter != NULL ; iter = iter->next) { @@ -128,25 +113,54 @@ switch_head_impl_cleanup(void) }
g_slist_free(languages); + + languages = NULL; }
+void +fill_languages_list(const gchar** impl_list, const gchar** head_list, gsize n) +{ + gchar **splitted_list; + Language* lang = NULL; + gint i, j; + + languages_clean(); + + for ( i=0; i<n; i++ ) { + lang = g_malloc0(sizeof(Language)); + + /* Set language implementation extensions */ + splitted_list = g_strsplit(impl_list[i], ",", 0); + for ( j=0; splitted_list[j] != NULL; j++ ) + IMPL_PREPEND(splitted_list[j]); + g_strfreev(splitted_list); + + /* Set language header extensions */ + splitted_list = g_strsplit(head_list[i], ",", 0); + for ( j=0; splitted_list[j] != NULL; j++ ) + HEAD_PREPEND(splitted_list[j]); + g_strfreev(splitted_list); + + /* add current language to main list */ + languages = g_slist_prepend(languages, lang); + } + + /* reverse the list to match correct order */ + languages = g_slist_reverse(languages); + +}
/* --------------------------------------------------------------------- * Initialize the "languages" list to the default known languages * --------------------------------------------------------------------- */ -static void +void fill_default_languages_list(void) { Language* lang = NULL;
languages = NULL;
-#define HEAD_PREPEND(str_ext) \ - { lang->head_extensions = g_slist_prepend(lang->head_extensions, g_strdup(str_ext)); } -#define IMPL_PREPEND(str_ext) \ - { lang->impl_extensions = g_slist_prepend(lang->impl_extensions, g_strdup(str_ext)); } - /* C/C++ */ lang = g_malloc0(sizeof(Language)); lang->name = "c_cpp"; @@ -195,8 +209,6 @@ fill_default_languages_list(void) /* Done : */ languages = g_slist_reverse(languages);
-#undef HEAD_PREPEND -#undef IMPL_PREPEND }
/* --------------------------------------------------------------------- @@ -395,205 +407,7 @@ menu_item_activate(guint key_id) } }
-/* --------------------------------------------------------------------- - * Configuration widget - * --------------------------------------------------------------------- - */ - -/* ----- Utility function to concatenate the extensions of a ----- - * language, separated with a comma. */ -static gchar* -concatenate_extensions(GSList* extensions) -{ - GSList* iter_ext; - gchar* p_str = NULL; - gchar* temp = NULL; - - for(iter_ext = extensions ; iter_ext != NULL ; iter_ext = iter_ext->next) - { - temp = p_str; - p_str = g_strjoin(",", (const gchar*)(iter_ext->data), p_str, NULL); - g_free(temp); - } - - return p_str; -} - -/* ----- Utility function to add a language to a GtkListStore ----- */ -static void -add_language(GtkListStore* list_store, Language* lang) -{ - gchar* p_str = NULL; - GtkTreeIter tree_iter; - - if(lang->head_extensions == NULL || lang->impl_extensions == NULL) - return; - - /* Append an empty row */ - gtk_list_store_append(list_store, &tree_iter); - - /* Header extensions */ - p_str = concatenate_extensions(lang->head_extensions); - gtk_list_store_set(list_store, &tree_iter, COLUMN_HEAD, p_str, -1); - g_free(p_str); - - /* Implementation extensions */ - p_str = concatenate_extensions(lang->impl_extensions); - gtk_list_store_set(list_store, &tree_iter, COLUMN_IMPL, p_str, -1); - g_free(p_str); -} - -/* ----- Finally, the configuration widget ----- */ -GtkWidget* -switch_head_impl_config_widget(void) +GSList* switch_head_impl_get_languages() { - GtkWidget *frame, *vbox, *tree_view; - GtkWidget *hbox_buttons, *add_button, *remove_button; - GtkListStore *list_store; - GtkTreeViewColumn *column; - GtkCellRenderer *cell_renderer; - - GSList *iter_lang; - - log_func(); - - /* Frame, which is the returned widget */ - frame = gtk_frame_new(_("Switch header/implementation")); - - /* Main VBox */ - vbox = gtk_vbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(frame), vbox); - - /* ======= Extensions list ======= */ - - /* Add a list containing the extensions for each language (headers / implementations) */ - /* - create the GtkListStore */ - list_store = gtk_list_store_new(NB_COLUMNS, G_TYPE_STRING, G_TYPE_STRING); - - /* - fill the GtkListStore with the extensions of the languages */ - for(iter_lang = languages ; iter_lang != NULL ; iter_lang = iter_lang->next) - add_language(list_store, (Language*)(iter_lang->data)); - - /* - create the GtkTreeView */ - tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store)); - - /* - add the columns */ - /* -> headers : */ - cell_renderer = gtk_cell_renderer_text_new(); - g_object_set(G_OBJECT(cell_renderer), "editable", TRUE, NULL); - g_signal_connect(G_OBJECT(cell_renderer), "edited", G_CALLBACK(on_configure_cell_edited), GINT_TO_POINTER(COLUMN_HEAD)); - column = gtk_tree_view_column_new_with_attributes( _("Headers extensions"), cell_renderer, - "text", COLUMN_HEAD, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column); - - /* -> implementations : */ - cell_renderer = gtk_cell_renderer_text_new(); - g_object_set(G_OBJECT(cell_renderer), "editable", TRUE, NULL); - g_signal_connect(G_OBJECT(cell_renderer), "edited", G_CALLBACK(on_configure_cell_edited), GINT_TO_POINTER(COLUMN_IMPL)); - column = gtk_tree_view_column_new_with_attributes( _("Implementations extensions"), cell_renderer, - "text", COLUMN_IMPL, - NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column); - - - /* - finally add the GtkTreeView to the frame's vbox */ - gtk_box_pack_start(GTK_BOX(vbox), tree_view, TRUE, TRUE, 6); - - - /* ========= Buttons ======== */ - - /* HBox */ - hbox_buttons = gtk_hbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), hbox_buttons, FALSE, FALSE, 0); - - /* Add the "add" button to the frame's hbox */ - add_button = gtk_button_new_from_stock(GTK_STOCK_ADD); - g_signal_connect(G_OBJECT(add_button), "clicked", G_CALLBACK(on_configure_add_language), tree_view); - gtk_box_pack_start(GTK_BOX(hbox_buttons), add_button, FALSE, FALSE, 0); - - /* Add the "remove" button to the frame's hbox */ - remove_button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); - gtk_widget_set_sensitive(remove_button, FALSE); /* TODO ! */ - g_signal_connect(G_OBJECT(remove_button), "clicked", G_CALLBACK(on_configure_remove_language), tree_view); - gtk_box_pack_start(GTK_BOX(hbox_buttons), remove_button, FALSE, FALSE, 0); - - return frame; -} - -/* --------------------------------------------------------------------- - * Callback for adding a language in the configuration dialog - * --------------------------------------------------------------------- - */ -static void -on_configure_add_language(GtkWidget* widget, gpointer data) -{ - GtkWidget* tree_view = (GtkWidget*)data; - GtkListStore *list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view))); - GtkTreeIter tree_iter; - GtkTreePath *path; - GtkTreeViewColumn* column = NULL; - gint nb_lines; - - /* Add a line */ - gtk_list_store_append(list_store, &tree_iter); - - /* and give the focus to it */ - nb_lines = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(list_store), NULL); - - path = gtk_tree_path_new_from_indices(nb_lines-1, -1); - - column = gtk_tree_view_get_column(GTK_TREE_VIEW(tree_view), 0); - - /* TODO : why isn't the cell being edited, although we say "TRUE" as last parameter ?? */ - gtk_tree_view_set_cursor(GTK_TREE_VIEW(tree_view), path, column, TRUE); - gtk_widget_grab_focus(tree_view); - - gtk_tree_path_free(path); -} - -/* --------------------------------------------------------------------- - * Callback for removing a language in the configuration dialog - * --------------------------------------------------------------------- - */ -static void -on_configure_remove_language(GtkWidget* widget, gpointer data) -{ - /* TODO ! */ -} - -/* --------------------------------------------------------------------- - * Callback called when a cell has been edited in the configuration dialog - * --------------------------------------------------------------------- - */ -static void -on_configure_cell_edited(GtkCellRendererText* text, gchar* arg1, gchar* arg2, gpointer data) -{ - /* TODO !! */ - /* Column col = (Column)(GPOINTER_TO_INT(data)); */ - log_debug("arg1 == %s, arg2 == %s\n", arg1, arg2); -} - -/* --------------------------------------------------------------------- - * Write the configuration of the feature - * --------------------------------------------------------------------- - */ -void -write_switch_head_impl_config(GKeyFile* key_file) -{ - /* TODO ! */ - /* This is old code which needs to be updated */ - -/* lang_names = g_malloc(nb_languages * sizeof(gchar*)); - for(lang_iterator = languages_extensions, i=0 ; - lang_iterator != NULL ; - lang_iterator = lang_iterator->next, i++) - { - lang_names[i] = ((const LanguageExtensions*)(lang_iterator->data))->language_name; - } - - g_key_file_set_string_list(key_file, "switching", "languages", lang_names, nb_languages); - - g_free(lang_names); -*/ + return languages; }
Modified: codenav/src/switch_head_impl.h 23 lines changed, 18 insertions(+), 5 deletions(-) =================================================================== @@ -3,6 +3,7 @@ * part of the "geany-plugins" project. * * Copyright 2009 Lionel Fuentes <funto66(at)gmail(dot)com> + * Copyright 2014 Federico Reghenzani <federico(dot)dev(at)reghe(dot)net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +26,14 @@
#include "codenavigation.h"
+/* Structure representing a handled language */ +typedef struct +{ + const gchar* name; /* currently not used */ + GSList* head_extensions; /* e.g. : "h", "hpp", ... */ + GSList* impl_extensions; /* e.g. : "cpp", "cxx", ... */ +} Language; + /* Initialization */ void switch_head_impl_init(void); @@ -33,12 +42,16 @@ switch_head_impl_init(void); void switch_head_impl_cleanup(void);
-/* Configuration widget */ -GtkWidget* -switch_head_impl_config_widget(void); +/* Languages-related */ +void +fill_default_languages_list(void);
-/* Write the configuration of the feature */ void -write_switch_head_impl_config(GKeyFile* key_file); +fill_languages_list(const gchar**, const gchar**, gsize); + + + +GSList* switch_head_impl_get_languages(); +
#endif /* SWITCH_HEAD_IMPL_H */
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).