1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 Copyright (C) Naba Kumar <naba@gnome.org>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <libgnomevfs/gnome-vfs-utils.h>
23 #include <libanjuta/anjuta-shell.h>
24 #include <libanjuta/anjuta-debug.h>
25 #include <libanjuta/anjuta-utils.h>
26 #include <libanjuta/interfaces/ianjuta-help.h>
27 #include <libanjuta/interfaces/ianjuta-document-manager.h>
28 #include <libanjuta/interfaces/ianjuta-project-manager.h>
29 #include <libanjuta/interfaces/ianjuta-file-manager.h>
30 #include <libanjuta/interfaces/ianjuta-file.h>
31 #include <libanjuta/interfaces/ianjuta-file-loader.h>
32 #include <libanjuta/interfaces/ianjuta-editor.h>
33 #include <libanjuta/interfaces/ianjuta-markable.h>
34 #include <libanjuta/interfaces/ianjuta-symbol-manager.h>
35 #include <libanjuta/interfaces/ianjuta-preferences.h>
37 #include <tm_tagmanager.h>
38 #include "an_symbol_view.h"
39 #include "an_symbol_search.h"
40 #include "anjuta-symbol-locals.h"
41 #include "an_symbol_info.h"
42 #include "an_symbol_prefs.h"
43 #include "an_symbol_iter.h"
46 #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta-symbol-browser-plugin.ui"
47 #define PREFS_GLADE PACKAGE_DATA_DIR"/glade/anjuta-symbol-browser-plugin.glade"
48 #define ICON_FILE "anjuta-symbol-browser-plugin-48.png"
49 #define SYMBOL_BROWSER_TAGS "symbol.browser.tags"
51 #define TIMEOUT_INTERVAL_SYMBOLS_UPDATE 10000
53 static gpointer parent_class
= NULL
;
55 /* these will block signals on treeview and treesearch callbacks functions */
56 static void trees_signals_block (SymbolBrowserPlugin
*sv_plugin
);
57 static void trees_signals_unblock (SymbolBrowserPlugin
*sv_plugin
);
59 static void on_treesearch_symbol_selected_event (AnjutaSymbolSearch
*search
,
60 AnjutaSymbolInfo
*sym
,
61 SymbolBrowserPlugin
*sv_plugin
);
62 static void update_editor_symbol_model (SymbolBrowserPlugin
*sv_plugin
);
64 static void on_editor_update_ui (IAnjutaEditor
*editor
,
65 SymbolBrowserPlugin
*sv_plugin
);
67 register_stock_icons (AnjutaPlugin
*plugin
)
69 static gboolean registered
= FALSE
;
75 /* Register stock icons */
76 BEGIN_REGISTER_ICON (plugin
);
77 REGISTER_ICON (ICON_FILE
, "symbol-browser-plugin-icon");
82 goto_file_line (AnjutaPlugin
*plugin
, const gchar
*filename
, gint lineno
)
85 IAnjutaDocumentManager
*docman
;
87 g_return_if_fail (filename
!= NULL
);
89 /* Go to file and line number */
90 docman
= anjuta_shell_get_interface (plugin
->shell
, IAnjutaDocumentManager
,
93 file
= g_file_new_for_path (filename
);
94 ianjuta_document_manager_goto_file_line (docman
, file
, lineno
, NULL
);
95 g_object_unref (file
);
99 goto_file_tag (SymbolBrowserPlugin
*sv_plugin
, const char *symbol
,
100 gboolean prefer_definition
)
106 ret
= anjuta_symbol_view_get_file_symbol (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
),
107 symbol
, prefer_definition
,
111 goto_file_line (ANJUTA_PLUGIN (sv_plugin
), file
, line
);
116 on_goto_def_activate (GtkAction
*action
, SymbolBrowserPlugin
*sv_plugin
)
122 ret
= anjuta_symbol_view_get_current_symbol_def (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
),
126 goto_file_line (ANJUTA_PLUGIN (sv_plugin
), file
, line
);
132 on_goto_decl_activate (GtkAction
*action
, SymbolBrowserPlugin
*sv_plugin
)
138 ret
= anjuta_symbol_view_get_current_symbol_decl (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
),
142 goto_file_line (ANJUTA_PLUGIN (sv_plugin
), file
, line
);
148 on_goto_file_tag_decl_activate (GtkAction
* action
,
149 SymbolBrowserPlugin
*sv_plugin
)
154 if (sv_plugin
->current_editor
)
156 ed
= IANJUTA_EDITOR (sv_plugin
->current_editor
);
157 word
= ianjuta_editor_get_current_word (ed
, NULL
);
160 goto_file_tag (sv_plugin
, word
, FALSE
);
167 on_goto_file_tag_def_activate (GtkAction
* action
,
168 SymbolBrowserPlugin
*sv_plugin
)
173 if (sv_plugin
->current_editor
)
175 ed
= IANJUTA_EDITOR (sv_plugin
->current_editor
);
176 word
= ianjuta_editor_get_current_word (ed
, NULL
);
179 goto_file_tag (sv_plugin
, word
, TRUE
);
186 on_find_activate (GtkAction
*action
, SymbolBrowserPlugin
*sv_plugin
)
189 symbol
= anjuta_symbol_view_get_current_symbol (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
));
192 g_warning ("TODO: Unimplemented");
198 on_refresh_idle (gpointer user_data
)
200 IAnjutaProjectManager
*pm
;
203 AnjutaStatus
*status
;
204 SymbolBrowserPlugin
*sv_plugin
= ANJUTA_PLUGIN_SYMBOL_BROWSER (user_data
);
206 /* FIXME: There should be a way to ensure that this project manager
207 * is indeed the one that has opened the project_uri
209 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sv_plugin
)->shell
,
210 IAnjutaProjectManager
, NULL
);
211 g_return_val_if_fail (pm
!= NULL
, FALSE
);
213 status
= anjuta_shell_get_status (ANJUTA_PLUGIN (sv_plugin
)->shell
, NULL
);
214 anjuta_status_push (status
, "Refreshing symbol tree...");
215 anjuta_status_busy_push (status
);
217 source_uris
= source_files
= NULL
;
218 source_uris
= ianjuta_project_manager_get_elements (pm
,
219 IANJUTA_PROJECT_MANAGER_SOURCE
,
231 uri
= (const gchar
*)node
->data
;
232 file_path
= gnome_vfs_get_local_path_from_uri (uri
);
234 source_files
= g_list_prepend (source_files
, file_path
);
235 node
= g_list_next (node
);
237 source_files
= g_list_reverse (source_files
);
239 anjuta_symbol_view_update (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
),
241 g_list_foreach (source_files
, (GFunc
)g_free
, NULL
);
242 g_list_foreach (source_uris
, (GFunc
)g_free
, NULL
);
243 g_list_free (source_files
);
244 g_list_free (source_uris
);
246 /* Current editor symbol model may have changed */
247 update_editor_symbol_model (sv_plugin
);
249 anjuta_status_busy_pop (status
);
250 anjuta_status_pop (status
);
255 on_refresh_activate (GtkAction
*action
, SymbolBrowserPlugin
*sv_plugin
)
257 if (!sv_plugin
->project_root_uri
)
259 g_idle_add (on_refresh_idle
, sv_plugin
);
262 static GtkActionEntry actions
[] =
264 { "ActionMenuGoto", NULL
, N_("_Goto"), NULL
, NULL
, NULL
},
266 "ActionSymbolBrowserGotoDef",
268 N_("Tag _Definition"),
270 N_("Goto symbol definition"),
271 G_CALLBACK (on_goto_file_tag_def_activate
)
274 "ActionSymbolBrowserGotoDecl",
276 N_("Tag De_claration"),
278 N_("Goto symbol declaration"),
279 G_CALLBACK (on_goto_file_tag_decl_activate
)
283 static GtkActionEntry popup_actions
[] =
286 "ActionPopupSymbolBrowserGotoDef",
288 N_("Goto _Definition"),
290 N_("Goto symbol definition"),
291 G_CALLBACK (on_goto_def_activate
)
294 "ActionPopupSymbolBrowserGotoDecl",
296 N_("Goto De_claration"),
298 N_("Goto symbol declaration"),
299 G_CALLBACK (on_goto_decl_activate
)
302 "ActionPopupSymbolBrowserFind",
306 N_("Find usage of symbol in project"),
307 G_CALLBACK (on_find_activate
)
310 "ActionPopupSymbolBrowserRefresh",
314 N_("Refresh symbol browser tree"),
315 G_CALLBACK (on_refresh_activate
)
320 on_project_element_added (IAnjutaProjectManager
*pm
, const gchar
*uri
,
321 SymbolBrowserPlugin
*sv_plugin
)
325 if (!sv_plugin
->project_root_uri
)
328 filename
= gnome_vfs_get_local_path_from_uri (uri
);
331 anjuta_symbol_view_add_source (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
),
338 on_project_element_removed (IAnjutaProjectManager
*pm
, const gchar
*uri
,
339 SymbolBrowserPlugin
*sv_plugin
)
343 if (!sv_plugin
->project_root_uri
)
346 filename
= gnome_vfs_get_local_path_from_uri (uri
);
349 anjuta_symbol_view_remove_source (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
),
355 #define LOCAL_TAGS_SUBDIR "tags/"
359 project_root_added (AnjutaPlugin
*plugin
, const gchar
*name
,
360 const GValue
*value
, gpointer user_data
)
362 AnjutaStatus
*status
;
363 IAnjutaProjectManager
*pm
;
364 SymbolBrowserPlugin
*sv_plugin
;
365 const gchar
*root_uri
;
368 sv_plugin
= ANJUTA_PLUGIN_SYMBOL_BROWSER (plugin
);
370 g_free (sv_plugin
->project_root_uri
);
371 sv_plugin
->project_root_uri
= NULL
;
372 root_uri
= g_value_get_string (value
);
375 gchar
*root_dir
= gnome_vfs_get_local_path_from_uri (root_uri
);
378 status
= anjuta_shell_get_status (plugin
->shell
, NULL
);
379 anjuta_status_progress_add_ticks (status
, 1);
380 trees_signals_block (sv_plugin
);
381 anjuta_symbol_view_open (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
),
384 /* Current editor symbol model may have changed */
385 update_editor_symbol_model (sv_plugin
);
386 anjuta_status_progress_tick (status
, NULL
, _("Created symbols..."));
387 trees_signals_unblock (sv_plugin
);
390 sv_plugin
->project_root_uri
= g_strdup (root_uri
);
392 /* FIXME: There should be a way to ensure that this project manager
393 * is indeed the one that has opened the project_uri
395 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sv_plugin
)->shell
,
396 IAnjutaProjectManager
, NULL
);
397 g_signal_connect (G_OBJECT (pm
), "element_added",
398 G_CALLBACK (on_project_element_added
), sv_plugin
);
399 g_signal_connect (G_OBJECT (pm
), "element_removed",
400 G_CALLBACK (on_project_element_removed
), sv_plugin
);
401 /* Load from project */
402 if (anjuta_preferences_get_int (sv_plugin
->prefs
,
403 "symbol_browser.tags_auto_load"))
405 gchar
* pref_symbols
= anjuta_preferences_get (sv_plugin
->prefs
, SYMBOL_BROWSER_TAGS
);
406 gchar
* dirname
= anjuta_util_get_user_cache_file_path (LOCAL_TAGS_SUBDIR
,NULL
);
407 GList
* packages
= ianjuta_project_manager_get_packages (pm
, NULL
);
409 GString
* str
= g_string_new (pref_symbols
);
410 g_free (pref_symbols
);
411 for (node
= packages
; node
!= NULL
; node
= g_list_next (node
))
413 gchar
* pathname
= g_build_filename (dirname
, node
->data
, NULL
);
414 if (!strstr (str
->str
, pathname
))
417 g_string_append_c (str
, ':');
418 g_string_append (str
, pathname
);
419 g_string_append (str
, ".anjutatags.gz");
423 g_list_foreach (packages
, (GFunc
) g_free
, NULL
);
424 g_list_free (packages
);
425 anjuta_preferences_set (sv_plugin
->prefs
, SYMBOL_BROWSER_TAGS
, str
->str
);
426 g_string_free (str
, TRUE
);
432 project_root_removed (AnjutaPlugin
*plugin
, const gchar
*name
,
435 IAnjutaProjectManager
*pm
;
436 SymbolBrowserPlugin
*sv_plugin
;
438 sv_plugin
= ANJUTA_PLUGIN_SYMBOL_BROWSER (plugin
);
440 /* Disconnect events from project manager */
442 /* FIXME: There should be a way to ensure that this project manager
443 * is indeed the one that has opened the project_uri
445 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sv_plugin
)->shell
,
446 IAnjutaProjectManager
, NULL
);
447 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
448 on_project_element_added
,
450 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
451 on_project_element_removed
,
454 /* clear anjuta_symbol_search side */
456 anjuta_symbol_search_clear(ANJUTA_SYMBOL_SEARCH(sv_plugin
->ss
));
458 /* clear glist's sfiles */
459 if (sv_plugin
->sv_tree
)
460 anjuta_symbol_view_clear (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
));
462 g_free (sv_plugin
->project_root_uri
);
463 sv_plugin
->project_root_uri
= NULL
;
467 on_treeview_event (GtkWidget
*widget
,
469 SymbolBrowserPlugin
*sv_plugin
)
473 GtkTreeSelection
*selection
;
475 g_return_val_if_fail (GTK_IS_TREE_VIEW (widget
), FALSE
);
477 view
= GTK_TREE_VIEW (widget
);
478 model
= gtk_tree_view_get_model (view
);
479 selection
= gtk_tree_view_get_selection (view
);
484 if (event
->type
== GDK_BUTTON_PRESS
) {
485 GdkEventButton
*e
= (GdkEventButton
*) event
;
487 if (e
->button
== 3) {
490 /* Popup project menu */
491 menu
= gtk_ui_manager_get_widget (GTK_UI_MANAGER (sv_plugin
->ui
),
492 "/PopupSymbolBrowser");
493 gtk_menu_popup (GTK_MENU (menu
), NULL
, NULL
,
494 NULL
, NULL
, e
->button
, e
->time
);
497 } else if (event
->type
== GDK_KEY_PRESS
) {
498 GdkEventKey
*e
= (GdkEventKey
*) event
;
502 anjuta_ui_activate_action_by_group (sv_plugin
->ui
,
503 sv_plugin
->popup_action_group
,
504 "ActionPopupSymbolBrowserGotoDef");
514 on_treeview_row_activated (GtkTreeView
*view
, GtkTreePath
*arg1
,
515 GtkTreeViewColumn
*arg2
,
516 SymbolBrowserPlugin
*sv_plugin
)
519 GtkTreeSelection
*selection
;
522 selection
= gtk_tree_view_get_selection (view
);
523 if (!gtk_tree_selection_get_selected (selection
, &model
, &iter
))
525 anjuta_ui_activate_action_by_group (sv_plugin
->ui
,
526 sv_plugin
->popup_action_group
,
527 "ActionPopupSymbolBrowserGotoDef");
531 trees_signals_block (SymbolBrowserPlugin
*sv_plugin
)
533 g_signal_handlers_block_by_func (G_OBJECT (sv_plugin
->sv_tree
),
534 G_CALLBACK (on_treeview_event
), NULL
);
536 g_signal_handlers_block_by_func (G_OBJECT (sv_plugin
->ss
),
537 G_CALLBACK (on_treesearch_symbol_selected_event
),
543 trees_signals_unblock (SymbolBrowserPlugin
*sv_plugin
)
545 g_signal_handlers_unblock_by_func (G_OBJECT (sv_plugin
->sv_tree
),
546 G_CALLBACK (on_treeview_event
), NULL
);
548 g_signal_handlers_unblock_by_func (G_OBJECT (sv_plugin
->ss
),
549 G_CALLBACK (on_treesearch_symbol_selected_event
),
554 goto_tree_iter (SymbolBrowserPlugin
*sv_plugin
, GtkTreeIter
*iter
)
559 line
= anjuta_symbol_view_workspace_get_line (ANJUTA_SYMBOL_VIEW
560 (sv_plugin
->sv_tree
),
563 if (line
> 0 && sv_plugin
->current_editor
)
565 /* Goto line number */
566 ianjuta_editor_goto_line (IANJUTA_EDITOR (sv_plugin
->current_editor
),
568 if (IANJUTA_IS_MARKABLE (sv_plugin
->current_editor
))
570 ianjuta_markable_delete_all_markers (IANJUTA_MARKABLE (sv_plugin
->current_editor
),
571 IANJUTA_MARKABLE_LINEMARKER
,
574 ianjuta_markable_mark (IANJUTA_MARKABLE (sv_plugin
->current_editor
),
575 line
, IANJUTA_MARKABLE_LINEMARKER
, NULL
);
581 on_local_treeview_row_activated (GtkTreeView
*view
, GtkTreePath
*arg1
,
582 GtkTreeViewColumn
*arg2
,
583 SymbolBrowserPlugin
*sv_plugin
)
586 GtkTreeSelection
*selection
;
589 selection
= gtk_tree_view_get_selection (view
);
590 if (!gtk_tree_selection_get_selected (selection
, &model
, &iter
))
592 goto_tree_iter (sv_plugin
, &iter
);
595 /* -----------------------------------------------------------------------------
596 * will manage the click of mouse and other events on search->hitlist treeview
599 on_treesearch_symbol_selected_event (AnjutaSymbolSearch
*search
,
600 AnjutaSymbolInfo
*sym
,
601 SymbolBrowserPlugin
*sv_plugin
) {
606 ret
= anjuta_symbol_view_get_file_symbol (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
),
611 goto_file_line (ANJUTA_PLUGIN (sv_plugin
), file
, line
);
616 on_editor_destroy (SymbolBrowserPlugin
*sv_plugin
, IAnjutaEditor
*editor
)
620 if (!sv_plugin
->editor_connected
|| !sv_plugin
->sv_tree
)
622 uri
= g_hash_table_lookup (sv_plugin
->editor_connected
, G_OBJECT (editor
));
623 if (uri
&& strlen (uri
) > 0)
625 DEBUG_PRINT ("Removing file tags of %s", uri
);
626 anjuta_symbol_view_workspace_remove_file (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
),
629 g_hash_table_remove (sv_plugin
->editor_connected
, G_OBJECT (editor
));
633 on_editor_saved (IAnjutaEditor
*editor
, GFile
* file
,
634 SymbolBrowserPlugin
*sv_plugin
)
636 const gchar
*old_uri
;
637 gboolean tags_update
;
638 GtkTreeModel
*file_symbol_model
;
642 /* FIXME: Do this only if automatic tags update is enabled */
644 anjuta_preferences_get_int (te->preferences, AUTOMATIC_TAGS_UPDATE);
653 gchar
*local_filename
;
654 gchar
*saved_uri
= g_file_get_uri (file
);
656 /* Verify that it's local file */
657 local_filename
= g_file_get_path (file
);
658 g_return_if_fail (local_filename
!= NULL
);
659 g_free (local_filename
);
661 if (!sv_plugin
->editor_connected
)
664 old_uri
= g_hash_table_lookup (sv_plugin
->editor_connected
, editor
);
666 if (old_uri
&& strlen (old_uri
) <= 0)
668 anjuta_symbol_view_workspace_update_file (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
),
670 g_hash_table_insert (sv_plugin
->editor_connected
, editor
,
671 g_strdup (saved_uri
));
673 /* Update File symbol view */
674 ui
= anjuta_shell_get_ui (ANJUTA_PLUGIN (sv_plugin
)->shell
, NULL
);
678 anjuta_symbol_view_get_file_symbol_model (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
));
679 g_object_set_data (G_OBJECT (editor
), "tm_file",
680 g_object_get_data (G_OBJECT (file_symbol_model
),
682 /* Set local view version */
683 gtk_tree_view_set_model (GTK_TREE_VIEW (sv_plugin
->sl_tree
),
685 sv_plugin
->locals_line_number
= 0;
686 on_editor_update_ui (editor
, sv_plugin
);
690 /* FIXME: Re-hilite all editors on tags update */
693 for (tmp
= app
->text_editor_list
; tmp
; tmp
= g_list_next(tmp
))
695 te1
= TEXT_EDITOR (tmp
->data
);
696 text_editor_set_hilite_type(te1
);
704 on_editor_foreach_disconnect (gpointer key
, gpointer value
, gpointer user_data
)
706 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
707 G_CALLBACK (on_editor_saved
),
709 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
710 G_CALLBACK (on_editor_update_ui
),
712 g_object_weak_unref (G_OBJECT(key
),
713 (GWeakNotify
) (on_editor_destroy
),
718 on_editor_foreach_clear (gpointer key
, gpointer value
, gpointer user_data
)
721 SymbolBrowserPlugin
*sv_plugin
= ANJUTA_PLUGIN_SYMBOL_BROWSER (user_data
);
723 uri
= (const gchar
*)value
;
724 if (uri
&& strlen (uri
) > 0)
726 DEBUG_PRINT ("Removing file tags of %s", uri
);
727 anjuta_symbol_view_workspace_remove_file (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
),
733 update_editor_symbol_model (SymbolBrowserPlugin
*sv_plugin
)
738 GObject
*editor
= sv_plugin
->current_editor
;
743 ui
= anjuta_shell_get_ui (ANJUTA_PLUGIN (sv_plugin
)->shell
, NULL
);
744 file
= ianjuta_file_get_file (IANJUTA_FILE (editor
), NULL
);
745 uri
= g_file_get_uri (file
);
746 g_object_unref (file
);
749 gchar
*local_filename
;
750 GtkTreeModel
*file_symbol_model
;
753 /* Verify that it's local file */
754 local_filename
= gnome_vfs_get_local_path_from_uri (uri
);
755 g_return_if_fail (local_filename
!= NULL
);
756 g_free (local_filename
);
758 anjuta_symbol_view_workspace_add_file (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
), uri
);
762 anjuta_symbol_view_get_file_symbol_model (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
));
763 if (file_symbol_model
)
765 g_object_set_data (G_OBJECT (editor
), "tm_file",
766 g_object_get_data (G_OBJECT (file_symbol_model
),
769 /* Set local view version */
770 gtk_tree_view_set_model (GTK_TREE_VIEW (sv_plugin
->sl_tree
),
772 sv_plugin
->locals_line_number
= 0;
773 on_editor_update_ui (IANJUTA_EDITOR (editor
), sv_plugin
);
779 iter_matches (SymbolBrowserPlugin
*sv_plugin
, GtkTreeIter
* iter
,
780 GtkTreeModel
* model
, gint lineno
)
783 gtk_tree_model_get (model
, iter
, COL_LINE
, &line
, -1);
786 GtkTreePath
* path
= gtk_tree_model_get_path (model
, iter
);
788 gtk_tree_view_set_cursor (GTK_TREE_VIEW (sv_plugin
->sl_tree
), path
, NULL
,
790 gtk_tree_path_free (path
);
797 on_editor_update_ui (IAnjutaEditor
*editor
, SymbolBrowserPlugin
*sv_plugin
)
799 gint lineno
= ianjuta_editor_get_lineno (editor
, NULL
);
801 GtkTreeModel
* model
= anjuta_symbol_view_get_file_symbol_model
802 (ANJUTA_SYMBOL_VIEW(sv_plugin
->sv_tree
));
804 gboolean found
= FALSE
;
806 if (sv_plugin
->locals_line_number
== lineno
)
808 sv_plugin
->locals_line_number
= lineno
;
810 if (!gtk_tree_model_get_iter_first (model
, &iter
))
812 while (!found
&& lineno
>= 0)
814 gtk_tree_model_get_iter_first (model
, &iter
);
817 found
= iter_matches (sv_plugin
, &iter
, model
, lineno
);
821 while (gtk_tree_model_iter_next (model
, &iter
));
827 value_added_current_editor (AnjutaPlugin
*plugin
, const char *name
,
828 const GValue
*value
, gpointer data
)
832 SymbolBrowserPlugin
*sv_plugin
;
835 editor
= g_value_get_object (value
);
837 if (!IANJUTA_IS_EDITOR(editor
))
840 sv_plugin
= ANJUTA_PLUGIN_SYMBOL_BROWSER (plugin
);
842 if (!sv_plugin
->editor_connected
)
844 sv_plugin
->editor_connected
= g_hash_table_new_full (g_direct_hash
,
848 sv_plugin
->current_editor
= editor
;
850 update_editor_symbol_model (sv_plugin
);
852 file
= ianjuta_file_get_file (IANJUTA_FILE (editor
), NULL
);
853 uri
= file
? g_file_get_uri (file
) : NULL
;
855 g_object_unref (file
);
856 if (g_hash_table_lookup (sv_plugin
->editor_connected
, editor
) == NULL
)
858 g_object_weak_ref (G_OBJECT (editor
),
859 (GWeakNotify
) (on_editor_destroy
),
863 g_hash_table_insert (sv_plugin
->editor_connected
, editor
, uri
); //g_strdup (uri));
868 g_hash_table_insert (sv_plugin
->editor_connected
, editor
,
871 g_signal_connect (G_OBJECT (editor
), "saved",
872 G_CALLBACK (on_editor_saved
),
874 g_signal_connect (G_OBJECT(editor
), "update_ui",
875 G_CALLBACK (on_editor_update_ui
),
881 value_removed_current_editor (AnjutaPlugin
*plugin
,
882 const char *name
, gpointer data
)
885 SymbolBrowserPlugin
*sv_plugin
;
888 /* let's remove the timeout for symbols refresh */
890 sv_plugin
= ANJUTA_PLUGIN_SYMBOL_BROWSER (plugin
);
891 ui
= anjuta_shell_get_ui (plugin
->shell
, NULL
);
892 sv_plugin
->current_editor
= NULL
;
896 activate_plugin (AnjutaPlugin
*plugin
)
898 GtkActionGroup
*group
;
899 SymbolBrowserPlugin
*sv_plugin
;
901 DEBUG_PRINT ("SymbolBrowserPlugin: Activating Symbol Manager plugin...");
903 register_stock_icons (plugin
);
905 sv_plugin
= ANJUTA_PLUGIN_SYMBOL_BROWSER (plugin
);
906 sv_plugin
->ui
= anjuta_shell_get_ui (plugin
->shell
, NULL
);
907 sv_plugin
->prefs
= anjuta_shell_get_preferences (plugin
->shell
, NULL
);
910 sv_plugin
->sw
= gtk_notebook_new();
913 sv_plugin
->sl
= gtk_scrolled_window_new (NULL
, NULL
);
914 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sv_plugin
->sl
),
916 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sv_plugin
->sl
),
917 GTK_POLICY_AUTOMATIC
,
918 GTK_POLICY_AUTOMATIC
);
919 /* Local symbols of the file */
920 sv_plugin
->sl_tab_label
= gtk_label_new (_("Local" ));
921 sv_plugin
->sl_tree
= anjuta_symbol_locals_new ();
922 g_object_add_weak_pointer (G_OBJECT (sv_plugin
->sl_tree
),
923 (gpointer
)&sv_plugin
->sl_tree
);
924 g_signal_connect (G_OBJECT (sv_plugin
->sl_tree
), "row_activated",
925 G_CALLBACK (on_local_treeview_row_activated
), plugin
);
926 gtk_container_add (GTK_CONTAINER(sv_plugin
->sl
), sv_plugin
->sl_tree
);
928 /* add the scrolled window to the notebook */
929 gtk_notebook_append_page (GTK_NOTEBOOK(sv_plugin
->sw
),
930 sv_plugin
->sl
, sv_plugin
->sl_tab_label
);
933 sv_plugin
->sv
= gtk_scrolled_window_new (NULL
, NULL
);
934 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sv_plugin
->sv
),
936 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sv_plugin
->sv
),
937 GTK_POLICY_AUTOMATIC
,
938 GTK_POLICY_AUTOMATIC
);
939 /* Global project-wide symbols */
940 sv_plugin
->sv_tab_label
= gtk_label_new (_("Global" ));
941 sv_plugin
->sv_tree
= anjuta_symbol_view_new ();
942 symbol_browser_load_global_tags (plugin
);
944 g_object_add_weak_pointer (G_OBJECT (sv_plugin
->sv_tree
),
945 (gpointer
)&sv_plugin
->sv_tree
);
947 g_signal_connect (G_OBJECT (sv_plugin
->sv_tree
), "event-after",
948 G_CALLBACK (on_treeview_event
), plugin
);
949 g_signal_connect (G_OBJECT (sv_plugin
->sv_tree
), "row_activated",
950 G_CALLBACK (on_treeview_row_activated
), plugin
);
952 gtk_container_add (GTK_CONTAINER(sv_plugin
->sv
), sv_plugin
->sv_tree
);
954 /* add the scrolled window to the notebook */
955 gtk_notebook_append_page (GTK_NOTEBOOK(sv_plugin
->sw
),
956 sv_plugin
->sv
, sv_plugin
->sv_tab_label
);
958 /* anjuta symbol search */
960 anjuta_symbol_search_new (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
));
961 sv_plugin
->ss_tab_label
= gtk_label_new (_("Search" ));
963 g_object_add_weak_pointer (G_OBJECT (sv_plugin
->ss
),
964 (gpointer
)&sv_plugin
->ss
);
966 gtk_notebook_append_page (GTK_NOTEBOOK(sv_plugin
->sw
), sv_plugin
->ss
,
967 sv_plugin
->ss_tab_label
);
969 gtk_widget_show_all (sv_plugin
->sw
);
971 /* connect some signals */
972 g_signal_connect (G_OBJECT (sv_plugin
->ss
), "symbol_selected",
973 G_CALLBACK (on_treesearch_symbol_selected_event
),
977 /* setting focus to the tree_view*/
978 gtk_notebook_set_current_page (GTK_NOTEBOOK (sv_plugin
->sw
), 0);
980 /* Add action group */
981 sv_plugin
->action_group
=
982 anjuta_ui_add_action_group_entries (sv_plugin
->ui
,
983 "ActionGroupSymbolBrowser",
984 _("Symbol browser actions"),
986 G_N_ELEMENTS (actions
),
987 GETTEXT_PACKAGE
, TRUE
, plugin
);
988 sv_plugin
->popup_action_group
=
989 anjuta_ui_add_action_group_entries (sv_plugin
->ui
,
990 "ActionGroupPopupSymbolBrowser",
991 _("Symbol browser popup actions"),
993 G_N_ELEMENTS (popup_actions
),
994 GETTEXT_PACKAGE
, FALSE
, plugin
);
995 group
= gtk_action_group_new ("ActionGroupSymbolNavigation");
997 anjuta_ui_add_action_group (sv_plugin
->ui
, "ActionGroupSymbolNavigation",
998 N_("Symbol navigations"), group
, FALSE
);
999 sv_plugin
->action_group_nav
= group
;
1002 sv_plugin
->merge_id
=
1003 anjuta_ui_merge (sv_plugin
->ui
, UI_FILE
);
1006 anjuta_shell_add_widget (plugin
->shell
, sv_plugin
->sw
,
1007 "AnjutaSymbolBrowser", _("Symbols"),
1008 "symbol-browser-plugin-icon",
1009 ANJUTA_SHELL_PLACEMENT_LEFT
, NULL
);
1011 /* set up project directory watch */
1012 sv_plugin
->root_watch_id
= anjuta_plugin_add_watch (plugin
,
1013 IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI
,
1015 project_root_removed
, NULL
);
1016 sv_plugin
->editor_watch_id
=
1017 anjuta_plugin_add_watch (plugin
, IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT
,
1018 value_added_current_editor
,
1019 value_removed_current_editor
, NULL
);
1024 deactivate_plugin (AnjutaPlugin
*plugin
)
1026 SymbolBrowserPlugin
*sv_plugin
;
1027 sv_plugin
= ANJUTA_PLUGIN_SYMBOL_BROWSER (plugin
);
1029 /* Ensure all editor cached info are released */
1030 if (sv_plugin
->editor_connected
)
1032 g_hash_table_foreach (sv_plugin
->editor_connected
,
1033 on_editor_foreach_disconnect
, plugin
);
1034 g_hash_table_foreach (sv_plugin
->editor_connected
,
1035 on_editor_foreach_clear
, plugin
);
1036 g_hash_table_destroy (sv_plugin
->editor_connected
);
1037 sv_plugin
->editor_connected
= NULL
;
1039 /* Remove watches */
1040 anjuta_plugin_remove_watch (plugin
, sv_plugin
->root_watch_id
, FALSE
);
1041 anjuta_plugin_remove_watch (plugin
, sv_plugin
->editor_watch_id
, TRUE
);
1043 /* Remove widgets: Widgets will be destroyed when sw is removed */
1044 anjuta_shell_remove_widget (plugin
->shell
, sv_plugin
->sw
, NULL
);
1047 anjuta_ui_unmerge (sv_plugin
->ui
, sv_plugin
->merge_id
);
1049 /* Remove action group */
1050 anjuta_ui_remove_action_group (sv_plugin
->ui
, sv_plugin
->action_group
);
1051 anjuta_ui_remove_action_group (sv_plugin
->ui
, sv_plugin
->popup_action_group
);
1052 anjuta_ui_remove_action_group (sv_plugin
->ui
, sv_plugin
->action_group_nav
);
1054 sv_plugin
->root_watch_id
= 0;
1055 sv_plugin
->editor_watch_id
= 0;
1056 sv_plugin
->merge_id
= 0;
1057 sv_plugin
->sw
= NULL
;
1058 sv_plugin
->sl
= NULL
;
1059 sv_plugin
->sl_tree
= NULL
;
1060 sv_plugin
->sv
= NULL
;
1061 sv_plugin
->sv_tree
= NULL
;
1062 sv_plugin
->ss
= NULL
;
1067 dispose (GObject
*obj
)
1069 SymbolBrowserPlugin
*sv_plugin
= ANJUTA_PLUGIN_SYMBOL_BROWSER (obj
);
1070 /* Ensure all editors are disconnected */
1071 if (sv_plugin
->editor_connected
)
1073 g_hash_table_foreach (sv_plugin
->editor_connected
,
1074 on_editor_foreach_disconnect
,
1076 g_hash_table_destroy (sv_plugin
->editor_connected
);
1077 sv_plugin
->editor_connected
= NULL
;
1082 g_object_unref (G_OBJECT (plugin->sw));
1087 g_object_remove_weak_pointer (G_OBJECT (sv_plugin
->ss
),
1088 (gpointer
)&sv_plugin
->ss
);
1091 G_OBJECT_CLASS (parent_class
)->dispose (obj
);
1095 finalize (GObject
*obj
)
1097 /* SymbolBrowserPlugin *plugin = ANJUTA_PLUGIN_SYMBOL_BROWSER (obj); */
1098 G_OBJECT_CLASS (parent_class
)->finalize (obj
);
1102 symbol_browser_plugin_instance_init (GObject
*obj
)
1104 SymbolBrowserPlugin
*plugin
= ANJUTA_PLUGIN_SYMBOL_BROWSER (obj
);
1105 plugin
->current_editor
= NULL
;
1106 plugin
->editor_connected
= NULL
;
1109 plugin
->gconf_notify_ids
= NULL
;
1110 plugin
->locals_line_number
= 0;
1111 plugin
->launcher
= NULL
;
1115 symbol_browser_plugin_class_init (SymbolBrowserPluginClass
*klass
)
1117 GObjectClass
*object_class
;
1118 AnjutaPluginClass
*plugin_class
;
1120 parent_class
= g_type_class_peek_parent (klass
);
1121 object_class
= G_OBJECT_CLASS (klass
);
1122 plugin_class
= ANJUTA_PLUGIN_CLASS (klass
);
1124 plugin_class
->activate
= activate_plugin
;
1125 plugin_class
->deactivate
= deactivate_plugin
;
1127 object_class
->dispose
= dispose
;
1128 object_class
->finalize
= finalize
;
1131 static IAnjutaIterable
*
1132 isymbol_manager_search (IAnjutaSymbolManager
*sm
,
1133 IAnjutaSymbolType match_types
,
1134 gboolean include_types
,
1135 IAnjutaSymbolField info_fields
,
1136 const gchar
*match_name
,
1137 gboolean partial_name_match
,
1138 gboolean global_symbols_search
,
1139 gboolean global_tags_search
, /* unused */
1140 gint results_limit
, /* unused */
1141 gint results_offset
, /* unused */
1144 const GPtrArray
*tags_array
;
1145 AnjutaSymbolIter
*iter
= NULL
;
1148 if (match_name
&& strlen (match_name
) > 0)
1153 tags_array
= tm_workspace_find (name
, match_types
, NULL
,
1154 partial_name_match
, global_symbols_search
);
1155 if (tags_array
&& tags_array
->len
)
1157 iter
= anjuta_symbol_iter_new (tags_array
);
1158 return IANJUTA_ITERABLE (iter
);
1163 static IAnjutaIterable
*
1164 isymbol_manager_get_members (IAnjutaSymbolManager
*sm
,
1165 IAnjutaSymbol
*symbol
,
1166 IAnjutaSymbolField info_fields
,
1167 gboolean global_search
,
1170 const GPtrArray
*tags_array
;
1171 AnjutaSymbolIter
*iter
= NULL
;
1174 s
= ANJUTA_SYMBOL (symbol
);
1176 tags_array
= tm_workspace_find_scope_members (NULL
, anjuta_symbol_get_name (s
),
1177 global_search
, TRUE
);
1180 if (tags_array
&& tags_array
->len
)
1182 iter
= anjuta_symbol_iter_new (tags_array
);
1183 return IANJUTA_ITERABLE (iter
);
1188 static IAnjutaIterable
*
1189 isymbol_manager_get_class_parents (IAnjutaSymbolManager
*sm
,
1190 IAnjutaSymbol
*symbol
,
1191 IAnjutaSymbolField info_fields
,
1194 const GPtrArray
*tags_array
;
1195 AnjutaSymbolIter
*iter
= NULL
;
1198 s
= ANJUTA_SYMBOL (symbol
);
1200 tags_array
= tm_workspace_get_parents (anjuta_symbol_get_name (s
));
1201 if (tags_array
&& tags_array
->len
)
1203 iter
= anjuta_symbol_iter_new (tags_array
);
1204 return IANJUTA_ITERABLE (iter
);
1210 isymbol_manager_iface_init (IAnjutaSymbolManagerIface
*iface
)
1212 iface
->search
= isymbol_manager_search
;
1213 iface
->get_members
= isymbol_manager_get_members
;
1214 iface
->get_class_parents
= isymbol_manager_get_class_parents
;
1218 ipreferences_merge(IAnjutaPreferences
* ipref
, AnjutaPreferences
* prefs
, GError
** e
)
1220 symbol_browser_prefs_init(ANJUTA_PLUGIN_SYMBOL_BROWSER (ipref
));
1224 ipreferences_unmerge(IAnjutaPreferences
* ipref
, AnjutaPreferences
* prefs
, GError
** e
)
1226 symbol_browser_prefs_finalize (ANJUTA_PLUGIN_SYMBOL_BROWSER (ipref
));
1230 ipreferences_iface_init(IAnjutaPreferencesIface
* iface
)
1232 iface
->merge
= ipreferences_merge
;
1233 iface
->unmerge
= ipreferences_unmerge
;
1236 ANJUTA_PLUGIN_BEGIN (SymbolBrowserPlugin
, symbol_browser_plugin
);
1237 ANJUTA_PLUGIN_ADD_INTERFACE (isymbol_manager
, IANJUTA_TYPE_SYMBOL_MANAGER
);
1238 ANJUTA_PLUGIN_ADD_INTERFACE (ipreferences
, IANJUTA_TYPE_PREFERENCES
);
1241 ANJUTA_SIMPLE_PLUGIN (SymbolBrowserPlugin
, symbol_browser_plugin
);