Branch: refs/heads/master Author: Frank Lanitz frank@frank.uvena.de Committer: Frank Lanitz frank@frank.uvena.de Date: Thu, 11 Sep 2014 20:38:54 UTC Commit: 7d56db1c77c3c04a2cad3f79f616b83dc5554bf7 https://github.com/geany/geany-plugins/commit/7d56db1c77c3c04a2cad3f79f616b8...
Log Message: ----------- Merge pull request #148 from federeghe/codenav
codenav implementation
Modified Paths: -------------- codenav/AUTHORS codenav/ChangeLog codenav/README codenav/src/codenavigation.c codenav/src/codenavigation.h codenav/src/goto_file.c codenav/src/switch_head_impl.c codenav/src/switch_head_impl.h codenav/src/utils.c codenav/src/utils.h
Modified: codenav/AUTHORS 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -1 +1,2 @@ Lionel Fuentes funto66@gmail.com +Federico Reghenzani federico.dev@reghe.net
Modified: codenav/ChangeLog 18 lines changed, 18 insertions(+), 0 deletions(-) =================================================================== @@ -1,3 +1,21 @@ +2014-04-24 Federico Reghenzani <federico(dot)dev(at)reghe(dot)net> + * src/*: + Implementation of plugin preferences and minor fixes + +2014-03-26 Federico Reghenzani <federico(dot)dev(at)reghe(dot)net> + * src/goto_file.c: + Implementation directory (absolute/relative path) support. + * src/utils.c, src/utils.h: + Changes strpos() into strrpos() (reverse order) + +2014-03-23 Federico Reghenzani <federico(dot)dev(at)reghe(dot)net> + * src/codenavigation.h: + Resolve some compiler warnings. + * src/goto_file.c: + Implementation goto_file. + * src/utils.c, src/utils.h: + Added strpos(). + 2011-04-23 Frank Lanitz frlan@frank.uvena.de
* src/switch_head_impl.c:
Modified: codenav/README 23 lines changed, 18 insertions(+), 5 deletions(-) =================================================================== @@ -6,13 +6,13 @@ Code navigation About -----
-This plugin adds some facilities for navigating in the code. +This plugin adds some facilities for navigating in code files.
Features --------
-* switch between header and implementation -* go to a file by typing its name +* Switch between header and implementation +* Go to a file by typing its name
Usage ----- @@ -21,6 +21,20 @@ After installed successfully, load the plugin in Geany's plugin manager and new menu items in the Edit menu will appear. You can change the keyboard shortcuts in Geany's preferences dialog.
+ +*Switch header/implementation* +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +This feature allows you to switch between implementation and header code +(e.g. between 'c' and 'h' files) using defined shortcut or by click on +menu item. You can edit the extensions association via preferences in +Geany's plugin manager. + +*Go to File* +^^^^^^^^^^^^ +You can open a file in current document directory typing its name. You +can also enter an absolute or relative path to a file. + + Requirements ------------
@@ -28,5 +42,4 @@ Requirements
Contact developers ------------------ - -Lionel Fuentes funto66@gmail.com +Federico Reghenzani <federico(dot)dev(at)reghe(dot)net>
Modified: codenav/src/codenavigation.c 558 lines changed, 501 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,150 @@ #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_reset_to_default(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 +183,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 +193,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 +208,396 @@ 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, empty_lines; + gchar** head_list = NULL; + gchar** impl_list = NULL; + + GtkTreeIter iter;
- if(response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY) + 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); + + empty_lines = 0; + + 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... */ + + 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); + + /* If one field is empty, ignore this line (it will be replaces + at next execution) */ + if ( strlen(impl_list[i])==0 || strlen(head_list[i])==0 ) + empty_lines++; + else + 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 - empty_lines); + g_key_file_set_string_list(config, "switch_head_impl", "headers_list", + (const gchar * const*)head_list, list_len - empty_lines); + + /* Try to create directory if not exists */ + if (! g_file_test(config_dir, G_FILE_TEST_IS_DIR) && utils_mkdir(config_dir, TRUE) != 0) { - /* 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 - */ + 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); + }
- /* Open the GKeyFile */ - key_file = g_key_file_new(); + /* Replace the current (runtime) languages list */ + fill_languages_list((const gchar**)impl_list, (const gchar**)head_list, list_len - empty_lines); + + /* 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);
- config_dir = g_strconcat(geany->app->configdir, - G_DIR_SEPARATOR_S "plugins" G_DIR_SEPARATOR_S "codenav" G_DIR_SEPARATOR_S, NULL); +}
- config_filename = g_strconcat(config_dir, "codenav.conf", NULL); + /** + * @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;
- /* Load configuration */ - g_key_file_load_from_file(key_file, config_filename, G_KEY_FILE_NONE, 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); + }
- /* Write configuration */ - write_switch_head_impl_config(key_file); + return p_str; +}
- /* Cleanup */ - g_free(config_filename); - g_free(config_dir); - g_key_file_free(key_file); +/** + * @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, *reset_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); + + + /* ========= 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); + 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); + + /* Add the "reset to default" button to the frame's hbox */ + reset_button = gtk_button_new_with_label(_("Reset to Default")); + g_signal_connect(G_OBJECT(reset_button), "clicked", G_CALLBACK(on_configure_reset_to_default), NULL); + gtk_box_pack_start(GTK_BOX(hbox_buttons), reset_button, FALSE, FALSE, 0); + 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 for reset to default languages in the configuration dialog + * @param button the button, not used here + * @param data null + * + * @return void + * + */ +static void +on_configure_reset_to_default(GtkWidget* button, gpointer data) +{ + GSList *iter_lang; + GtkWidget* dialog_new; + + /* ask to user if he's sure */ + dialog_new = gtk_message_dialog_new(GTK_WINDOW(geany_data->main_widgets->window), + GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK_CANCEL, + _("Are you sure you want to delete all languages " \ + "and restore defaults?\nThis action cannot be undone.")); + gtk_window_set_title(GTK_WINDOW(dialog_new), "Geany"); + + if(gtk_dialog_run(GTK_DIALOG(dialog_new)) == GTK_RESPONSE_OK) + { + /* OK, reset! */ + fill_default_languages_list(); + + /* clear and refill the GtkListStore with default extensions */ + gtk_list_store_clear(list_store); + + for(iter_lang = switch_head_impl_get_languages(); + iter_lang != NULL ; iter_lang = iter_lang->next) + add_language(list_store, (Language*)(iter_lang->data)); + } + gtk_widget_destroy(dialog_new); + +} + + +/** + * @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; + gchar character; + gint i; + Column col = (Column)(GPOINTER_TO_INT(data)); + + log_func(); + + character=text[0]; + i=1; + while (character != '\0') { + if ( ! g_ascii_isalpha(character) && character != ',' ) { + log_debug("Not-valid char"); + return; // invalid extension + } + character=text[i++]; + } + + /* 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 40 lines changed, 21 insertions(+), 19 deletions(-) =================================================================== @@ -1,23 +1,22 @@ /* - * codenavigation.h - this file is part of "codenavigation", which is - * part of the "geany-plugins" project. + * codenavigation.h - this file is part of "codenavigation", which is + * part of the "geany-plugins" project. * - * Copyright 2009 Lionel Fuentes <funto66(at)gmail(dot)com> + * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, see http://www.gnu.org/licenses/. */
#ifndef CODENAVIGATION_H @@ -36,6 +35,7 @@ #include "keybindings.h" #include "filetypes.h" #include <gdk/gdkkeysyms.h> + #include <string.h>
#include "switch_head_impl.h" @@ -45,13 +45,15 @@ #include "geanyfunctions.h" /* this wraps geany_functions function pointers */
/* Debug flag */ -/*#define CODE_NAVIGATION_DEBUG -*/ +/*#define CODE_NAVIGATION_DEBUG*/
-#define CODE_NAVIGATION_VERSION "0.1" +#define CODE_NAVIGATION_VERSION "0.2"
/* Log utilities */ #ifdef CODE_NAVIGATION_DEBUG +#include <glib/gprintf.h> + + static void log_debug(const gchar* s, ...) { gchar* format = g_strconcat("[CODENAV DEBUG] : ", s, "\n", NULL); @@ -64,7 +66,7 @@ static void log_debug(const gchar* s, ...)
#define log_func() g_print("[CODENAV FUNC] : %s", G_STRFUNC) #else -static void log_debug(const gchar* s, ...) {} +#define log_debug(...) {} #define log_func() {} #endif
Modified: codenav/src/goto_file.c 299 lines changed, 253 insertions(+), 46 deletions(-) =================================================================== @@ -1,23 +1,22 @@ /* - * goto_file.c - this file is part of "codenavigation", which is - * part of the "geany-plugins" project. + * goto_file.c - this file is part of "codenavigation", which is + * part of the "geany-plugins" project. * - * Copyright 2009 Lionel Fuentes <funto66(at)gmail(dot)com> + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, see http://www.gnu.org/licenses/. */
#ifdef HAVE_CONFIG_H @@ -26,23 +25,35 @@ #include <geanyplugin.h>
#include "goto_file.h" +#include "utils.h" + +#define MAX_FILENAME_LENGTH 255
/******************* Global variables for the feature *****************/
static GtkWidget* menu_item = NULL; +gchar *directory_ref = NULL;
-/********************** Functions for the feature *********************/ +/********************** Prototypes *********************/ +static void +menu_item_activate(guint); + +static GtkTreeModel* +build_file_list(const gchar*, const gchar*);
-/* --------------------------------------------------------------------- - * Callback when the menu item is clicked. - * --------------------------------------------------------------------- - */ static void -menu_item_activate(guint key_id); +directory_check(GtkEntry*, GtkEntryCompletion*); + +static GtkWidget* +create_dialog(GtkWidget**, GtkTreeModel*);
-/* --------------------------------------------------------------------- - * Initialization - * --------------------------------------------------------------------- +/********************** Functions for the feature *********************/ + +/** + * @brief Initialization function called in plugin_init + * @param void + * @return void + * */ void goto_file_init(void) @@ -54,7 +65,7 @@ goto_file_init(void) edit_menu = ui_lookup_widget(geany->main_widgets->window, "edit1_menu");
/* Add the menu item, sensitive only when a document is opened */ - menu_item = gtk_menu_item_new_with_mnemonic(_("Goto file")); + menu_item = gtk_menu_item_new_with_mnemonic(_("Go to File...")); gtk_widget_show(menu_item); gtk_container_add(GTK_CONTAINER(edit_menu), menu_item); ui_add_document_sensitive(menu_item); @@ -68,46 +79,242 @@ goto_file_init(void) (GeanyKeyCallback)(&menu_item_activate), GDK_g, GDK_MOD1_MASK | GDK_SHIFT_MASK, "goto_file", - _("Goto file"), /* used in the Preferences dialog */ + _("Go to File"), /* used in the Preferences dialog */ menu_item); }
-/* --------------------------------------------------------------------- - * Cleanup - * --------------------------------------------------------------------- +/** + * @brief Cleanup function called in plugin_cleanup + * @param void + * @return void + * */ void goto_file_cleanup(void) { log_func(); - gtk_widget_destroy(menu_item); }
-/* --------------------------------------------------------------------- - * Callback when the menu item is clicked. - * --------------------------------------------------------------------- +/** + * @brief Populate the file list with file list of directory + * @param const char* dirname the directory where to find files + * @param const char* prefix file prefix (the path) + * @return GtkTreeModel* + * + */ +static GtkTreeModel* +build_file_list(const gchar* dirname, const gchar* prefix) +{ + GtkListStore *ret_list; + GtkTreeIter iter; + ret_list = gtk_list_store_new (1, G_TYPE_STRING); + + GSList* file_iterator; + GSList* files_list; /* used to free later the sub-elements*/ + gchar *file; + gchar *pathfile; + guint files_n; + + files_list = file_iterator = utils_get_file_list(dirname, &files_n, NULL); + + for( ; file_iterator; file_iterator = file_iterator->next) + { + file = file_iterator->data; + + pathfile = g_build_filename(dirname,file,NULL); + + /* Append the element to model list */ + gtk_list_store_append (ret_list, &iter); + gtk_list_store_set (ret_list, &iter, 0, + g_strconcat(prefix, file, NULL), -1); + g_free(pathfile); + } + + g_slist_foreach(files_list, (GFunc) g_free, NULL); + g_slist_free(files_list); + + return GTK_TREE_MODEL(ret_list); + +} + +/** + * @brief Entry callback function for sub-directory search + * @param GtkEntry* entry entry object + * @param GtkEntryCompletion* completion completion object + * @return void + * + */ +static void +directory_check(GtkEntry* entry, GtkEntryCompletion* completion) +{ + static GtkTreeModel *old_model = NULL; + GtkTreeModel* completion_list; + static gchar *curr_dir = NULL; + gchar *new_dir, *new_dir_path; + const gchar *text; + + text = gtk_entry_get_text(entry); + gint dir_sep = strrpos(text, G_DIR_SEPARATOR_S); + + /* No subdir separator found */ + if (dir_sep == -1) + { + if (old_model != NULL) + { /* Restore the no-sub-directory model */ + log_debug("Restoring old model!"); + gtk_entry_completion_set_model (completion, old_model); + old_model = NULL; + g_free(curr_dir); + curr_dir = NULL; + } + return; + } + + new_dir = g_strndup (text, dir_sep+1); + /* I've already inserted new model completion for sub-dir elements? */ + if ( g_strcmp0 (new_dir, curr_dir) == 0 ) + return; + + if ( curr_dir != NULL ) + g_free(curr_dir); + + curr_dir = new_dir; + + /* Save the completion_mode for future restore. */ + if (old_model == NULL) + old_model = gtk_entry_completion_get_model(completion); + + log_debug("New completion list!"); + + if ( g_path_is_absolute(new_dir) ) + new_dir_path = new_dir; + else + new_dir_path = g_build_filename(directory_ref, new_dir, NULL); + + /* Build the new file list for completion */ + completion_list = build_file_list(new_dir_path, new_dir); + gtk_entry_completion_set_model (completion, completion_list); + g_object_unref(completion_list); +} + + +/** + * @brief Create the dialog, return the entry object to get the + * response from user + * @param GtkWidget **dialog entry object + * @param GtkTreeModel *completion_model completion object + * @return GtkWidget* entry + * + */ +static GtkWidget* +create_dialog(GtkWidget **dialog, GtkTreeModel *completion_model) +{ + GtkWidget *entry; + GtkWidget *label; + GtkWidget *vbox; + GtkEntryCompletion *completion; + + *dialog = gtk_dialog_new_with_buttons(_("Go to File..."), GTK_WINDOW(geany->main_widgets->window), + GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); + + gtk_dialog_set_default_response(GTK_DIALOG(*dialog), GTK_RESPONSE_ACCEPT); + + gtk_widget_set_name(*dialog, "GotoFile"); + vbox = ui_dialog_vbox_new(GTK_DIALOG(*dialog)); + + label = gtk_label_new(_("Enter the file you want to open:")); + gtk_container_add(GTK_CONTAINER(vbox), label); + + /* Entry definition */ + entry = gtk_entry_new(); + gtk_container_add(GTK_CONTAINER(vbox), entry); + gtk_entry_set_text(GTK_ENTRY(entry), ""); + gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_FILENAME_LENGTH); + gtk_entry_set_width_chars(GTK_ENTRY(entry), 40); + gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); /* 'enter' key */ + + /* Completion definition */ + completion = gtk_entry_completion_new(); + gtk_entry_set_completion(GTK_ENTRY(entry), completion); + gtk_entry_completion_set_model (completion, completion_model); + + /* Completion options */ + gtk_entry_completion_set_inline_completion(completion, 1); + gtk_entry_completion_set_text_column (completion, 0); + + /* Signals */ + g_signal_connect_after(GTK_ENTRY(entry), "changed", + G_CALLBACK(directory_check), completion); + + gtk_widget_show_all(*dialog); + + return entry; +} + +/** + * @brief Callback when the menu item is clicked. + * @param guint key_id not used + * @return void + * */ static void menu_item_activate(guint key_id) { - GtkWidget *dialog; + GtkWidget* dialog; + GtkWidget* dialog_new = NULL; + GtkWidget* dialog_entry; + GtkTreeModel* completion_list; + GeanyDocument* current_doc = document_get_current(); + gchar *chosen_path; + const gchar *chosen_file; + gint response;
log_func();
- /* TODO */ - dialog = gtk_message_dialog_new( - GTK_WINDOW(geany->main_widgets->window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_INFO, - GTK_BUTTONS_OK, - "Open by name : TODO"); + if(current_doc == NULL || current_doc->file_name == NULL || current_doc->file_name[0] == '\0') + return; + + /* Build current directory listing */ + directory_ref = g_path_get_dirname(current_doc->file_name); + completion_list = build_file_list(directory_ref, ""); + + /* Create the user dialog and get response */ + dialog_entry = create_dialog(&dialog, completion_list); + response = gtk_dialog_run(GTK_DIALOG(dialog)); + + /* Filename */ + chosen_file = gtk_entry_get_text(GTK_ENTRY(dialog_entry)); + /* Path + Filename */ + chosen_path = g_build_filename(directory_ref, chosen_file, NULL);
- gtk_window_set_title(GTK_WINDOW(dialog), "Goto file..."); + if ( response == GTK_RESPONSE_ACCEPT ) + { + log_debug("Trying to open: %s", chosen_path); + if ( ! g_file_test(chosen_path, G_FILE_TEST_EXISTS) ) + { + log_debug("File not found.");
- gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), - _("(From the %s plugin)"), geany_plugin->info->name); + dialog_new = gtk_message_dialog_new(GTK_WINDOW(geany_data->main_widgets->window), + GTK_DIALOG_MODAL, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_OK_CANCEL, + _("%s not found, create it?"), chosen_file); + gtk_window_set_title(GTK_WINDOW(dialog_new), "Geany"); + if(gtk_dialog_run(GTK_DIALOG(dialog_new)) == GTK_RESPONSE_OK) + { + document_new_file(chosen_path, current_doc->file_type, NULL); + document_set_text_changed(document_get_current(), TRUE); + } + gtk_widget_destroy(dialog_new); + } + else + document_open_file(chosen_path, FALSE, NULL, NULL); + }
- gtk_dialog_run(GTK_DIALOG(dialog)); + /* Freeing memory */ gtk_widget_destroy(dialog); + g_free(directory_ref); + g_object_unref (completion_list); }
Modified: codenav/src/switch_head_impl.c 353 lines changed, 100 insertions(+), 253 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 @@ -28,55 +29,39 @@ #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); - -static void -on_configure_remove_language(GtkWidget* widget, gpointer data); - -static void -on_configure_cell_edited(GtkCellRendererText* text, gchar* arg1, gchar* arg2, gpointer data); +/********************** Functions for the feature *********************/
-/* --------------------------------------------------------------------- - * Initialization - * --------------------------------------------------------------------- +/** + * @brief Initialization + * @param void + * @return void + * */ void switch_head_impl_init(void) { GtkWidget* edit_menu; - log_func();
edit_menu = ui_lookup_widget(geany->main_widgets->window, "edit1_menu"); @@ -99,53 +84,107 @@ 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(); }
-/* --------------------------------------------------------------------- - * Cleanup - * --------------------------------------------------------------------- + +/** + * @brief Default plugin cleanup + * @param void + * @return void + * */ void switch_head_impl_cleanup(void) { - GSList* iter = NULL; - log_func();
gtk_widget_destroy(menu_item); + languages_clean(); +} + +/** + * @brief Free and cleanup all item in languages array, and set languages + * to null + * @param void + * @return void + * + */ +void languages_clean(void) +{ + GSList* iter = NULL;
for(iter = languages ; iter != NULL ; iter = iter->next) { Language* lang = (Language*)(iter->data);
- g_slist_foreach(lang->head_extensions, (GFunc)(&g_free), NULL); /* free the data */ - g_slist_free(lang->head_extensions); /* free the list */ + g_slist_foreach(lang->head_extensions, (GFunc)(&g_free), NULL); + g_slist_free(lang->head_extensions);
g_slist_foreach(lang->impl_extensions, (GFunc)(&g_free), NULL); g_slist_free(lang->impl_extensions); }
g_slist_free(languages); + + languages = NULL; }
+/** + * @brief Fill the languages variable with passed arguments. + * @param impl_list list of implementation extensions + * @param head_list list of header extensions + * @return void + * + */ +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)); + + /* check if current item has no head or impl */ + if ( strlen(impl_list[i])==0 || strlen(head_list[i])==0 ) + continue; + + /* 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 - * --------------------------------------------------------------------- +/** + * @brief Initialize the "languages" list to the default known languages + * @param void + * @return void + * */ -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)); } + languages_clean();
/* C/C++ */ lang = g_malloc0(sizeof(Language)); @@ -195,13 +234,13 @@ fill_default_languages_list(void) /* Done : */ languages = g_slist_reverse(languages);
-#undef HEAD_PREPEND -#undef IMPL_PREPEND }
-/* --------------------------------------------------------------------- - * Callback when the menu item is clicked. - * --------------------------------------------------------------------- +/** + * @brief Callback when the menu item is clicked. + * @param key_id not used + * @return void + * */ static void menu_item_activate(guint key_id) @@ -395,205 +434,13 @@ menu_item_activate(guint key_id) } }
-/* --------------------------------------------------------------------- - * Configuration widget - * --------------------------------------------------------------------- +/** + * @brief Extern function to get languages. + * @param void + * @return GSList* languages list + * */ - -/* ----- Utility function to concatenate the extensions of a ----- - * language, separated with a comma. */ -static gchar* -concatenate_extensions(GSList* extensions) +GSList* switch_head_impl_get_languages() { - 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) -{ - 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 */
Modified: codenav/src/utils.c 67 lines changed, 48 insertions(+), 19 deletions(-) =================================================================== @@ -1,29 +1,32 @@ /* - * utils.c - this file is part of "codenavigation", which is - * part of the "geany-plugins" project. + * utils.c - this file is part of "codenavigation", which is + * part of the "geany-plugins" project. * - * Copyright 2009 Lionel Fuentes <funto66(at)gmail(dot)com> + * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, see http://www.gnu.org/licenses/. */
#include "utils.h"
-/* Function which returns a newly-allocated string containing the - * extension of the file path which is given, or NULL if it did not found any extension. + /** + * @brief Function which returns the extension of the file path which + * is given, or NULL if it did not found any extension. + * @param gchar* the file path + * @return gchar* newly-allocated string containing the extension + * */ gchar* get_extension(gchar* path) @@ -43,7 +46,11 @@ get_extension(gchar* path) return g_strdup(extension); }
-/* Copy a path and remove the extension +/** + * @brief Copy a path and remove the extension + * @param gchar* the file path + * @return gchar* newly-allocated string containing the filename without ext + * */ gchar* copy_and_remove_extension(gchar* path) @@ -73,9 +80,31 @@ copy_and_remove_extension(gchar* path) return str; }
-/* Comparison of strings, for use with g_slist_find_custom */ +/** + * @brief Comparison of strings, for use with g_slist_find_custom + * @param const gchar*, const gchar* + * @return gint + * + */ gint compare_strings(const gchar* a, const gchar* b) { return (gint)(!utils_str_equal(a, b)); } + +/** + * @brief A PHP-like reverse strpos implementation + * @param const gchar* haystack + * @param const gchar* needle + * @return gint position or -1 if not found + * + */ +gint +strrpos(const gchar *haystack, const gchar *needle) +{ + char *p = g_strrstr_len(haystack, -1, needle); + if (p) + return p - haystack; + return -1; // not found +} +
Modified: codenav/src/utils.h 4 lines changed, 4 insertions(+), 0 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 @@ -40,4 +41,7 @@ copy_and_remove_extension(gchar* path); gint compare_strings(const gchar* a, const gchar* b);
+gint +strrpos(const gchar *haystack, const gchar *needle); + #endif /* UTILS_H */
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
plugins-commits@lists.geany.org