[geany/geany-plugins] 7d56db: Merge pull request #148 from federeghe/codenav
Frank Lanitz
git-noreply at xxxxx
Thu Sep 11 20:38:54 UTC 2014
Branch: refs/heads/master
Author: Frank Lanitz <frank at frank.uvena.de>
Committer: Frank Lanitz <frank at frank.uvena.de>
Date: Thu, 11 Sep 2014 20:38:54 UTC
Commit: 7d56db1c77c3c04a2cad3f79f616b83dc5554bf7
https://github.com/geany/geany-plugins/commit/7d56db1c77c3c04a2cad3f79f616b83dc5554bf7
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 at gmail.com>
+Federico Reghenzani <federico.dev at 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 at 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 at 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).
More information about the Plugins-Commits
mailing list