1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Massimo Cora' 2007 <maxcvs@email.it>
6 * plugin.c is free software.
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
13 * plugin.c is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with plugin.c. If not, write to:
20 * The Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301, USA.
26 #include <libgnomevfs/gnome-vfs-utils.h>
27 #include <libgnomevfs/gnome-vfs-mime-utils.h>
28 #include <libanjuta/anjuta-shell.h>
29 #include <libanjuta/anjuta-debug.h>
30 #include <libanjuta/interfaces/ianjuta-document-manager.h>
31 #include <libanjuta/interfaces/ianjuta-symbol-manager.h>
32 #include <libanjuta/interfaces/ianjuta-project-manager.h>
33 #include <libanjuta/interfaces/ianjuta-file-manager.h>
34 #include <libanjuta/interfaces/ianjuta-file.h>
35 #include <libanjuta/interfaces/ianjuta-file-loader.h>
36 #include <libanjuta/interfaces/ianjuta-editor.h>
37 #include <libanjuta/interfaces/ianjuta-markable.h>
38 #include <libanjuta/interfaces/ianjuta-language.h>
39 #include <libanjuta/interfaces/ianjuta-iterable.h>
41 #include <libegg/menu/egg-combo-action.h>
44 #include "symbol-db-view.h"
45 #include "symbol-db-view-locals.h"
46 #include "symbol-db-view-search.h"
47 #include "symbol-db-engine.h"
48 #include "symbol-db-engine-iterator.h"
50 #define UI_FILE ANJUTA_DATA_DIR"/ui/symbol-db.ui"
52 #define GLADE_FILE ANJUTA_DATA_DIR"/glade/symbol-db.glade"
53 #define ICON_FILE "symbol-db.png"
55 #define TIMEOUT_INTERVAL_SYMBOLS_UPDATE 60000
56 #define TIMEOUT_SECONDS_AFTER_LAST_TIP 5
58 static gpointer parent_class
;
59 static gboolean need_symbols_update
= FALSE
;
60 static gchar prev_char_added
= ' ';
61 static gint timeout_id
= 0;
62 static GTimer
*timer
= NULL
;
64 #define REGISTER_ICON(icon, stock_id) \
65 pixbuf = gdk_pixbuf_new_from_file (icon, NULL); \
66 icon_set = gtk_icon_set_new_from_pixbuf (pixbuf); \
67 gtk_icon_factory_add (icon_factory, stock_id, icon_set); \
68 g_object_unref (pixbuf);
71 register_stock_icons (AnjutaPlugin
*plugin
)
74 GtkIconFactory
*icon_factory
;
77 static gboolean registered
= FALSE
;
83 /* Register stock icons */
84 ui
= anjuta_shell_get_ui (plugin
->shell
, NULL
);
85 icon_factory
= anjuta_ui_get_icon_factory (ui
);
86 REGISTER_ICON (PACKAGE_PIXMAPS_DIR
"/"ICON_FILE
, "symbol-db-plugin-icon");
89 static GtkActionEntry actions[] =
91 { "ActionMenuGoto", NULL, N_("_Goto"), NULL, NULL, NULL},
93 "ActionSymbolBrowserGotoDef",
95 N_("Tag _Definition"),
97 N_("Goto symbol definition"),
98 G_CALLBACK (on_goto_file_tag_def_activate)
101 "ActionSymbolBrowserGotoDecl",
103 N_("Tag De_claration"),
105 N_("Goto symbol declaration"),
106 G_CALLBACK (on_goto_file_tag_decl_activate)
112 on_editor_buffer_symbols_update_timeout (gpointer user_data
)
114 SymbolDBPlugin
*sdb_plugin
;
116 gchar
*current_buffer
= NULL
;
117 gint buffer_size
= 0;
119 gdouble seconds_elapsed
;
121 g_return_val_if_fail (user_data
!= NULL
, FALSE
);
123 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (user_data
);
125 if (sdb_plugin
->current_editor
== NULL
)
128 /* check the timer. If it's elapsed enought time since the last time the user
129 * typed in something, than proceed with updating, elsewhere don't do nothing
134 seconds_elapsed
= g_timer_elapsed (timer
, NULL
);
136 /* DEBUG_PRINT ("seconds_elapsed %f", seconds_elapsed ); */
137 if (seconds_elapsed
< TIMEOUT_SECONDS_AFTER_LAST_TIP
)
141 /* we won't proceed with the updating of the symbols if we didn't type in
143 if (!need_symbols_update
)
146 DEBUG_PRINT ("on_editor_buffer_symbols_update_timeout()");
148 if (sdb_plugin
->current_editor
)
150 ed
= IANJUTA_EDITOR (sdb_plugin
->current_editor
);
152 buffer_size
= ianjuta_editor_get_length (ed
, NULL
);
153 current_buffer
= ianjuta_editor_get_text (ed
, 0, -1, NULL
);
155 uri
= ianjuta_file_get_uri (IANJUTA_FILE (ed
), NULL
);
162 DEBUG_PRINT ("uri for buffer updating: %s", uri
);
164 GPtrArray
*real_files_list
;
165 GPtrArray
*text_buffers
;
166 GPtrArray
*buffer_sizes
;
169 gchar
* local_path
= gnome_vfs_get_local_path_from_uri (uri
);
171 real_files_list
= g_ptr_array_new ();
172 g_ptr_array_add (real_files_list
, local_path
);
174 text_buffers
= g_ptr_array_new ();
175 g_ptr_array_add (text_buffers
, current_buffer
);
177 buffer_sizes
= g_ptr_array_new ();
178 g_ptr_array_add (buffer_sizes
, (gpointer
)buffer_size
);
180 project_name
= symbol_db_engine_get_opened_project_name (sdb_plugin
->sdbe
);
182 symbol_db_engine_update_buffer_symbols (sdb_plugin
->sdbe
,
187 g_free (project_name
);
192 g_free (current_buffer
);
194 need_symbols_update
= FALSE
;
200 on_editor_destroy (SymbolDBPlugin
*sdb_plugin
, IAnjutaEditor
*editor
)
204 if (!sdb_plugin
->editor_connected
|| !sdb_plugin
->dbv_view_tree
)
207 uri
= g_hash_table_lookup (sdb_plugin
->editor_connected
, G_OBJECT (editor
));
208 if (uri
&& strlen (uri
) > 0)
210 DEBUG_PRINT ("Removing file tags of %s", uri
);
212 anjuta_symbol_view_workspace_remove_file (ANJUTA_SYMBOL_VIEW (sv_plugin->sv_tree),
216 g_hash_table_remove (sdb_plugin
->editor_connected
, G_OBJECT (editor
));
220 on_editor_update_ui (IAnjutaEditor
*editor
, SymbolDBPlugin
*sdb_plugin
)
223 gint lineno
= ianjuta_editor_get_lineno (editor
, NULL
);
225 GtkTreeModel
* model
= anjuta_symbol_view_get_file_symbol_model
226 (ANJUTA_SYMBOL_VIEW(sv_plugin
->sv_tree
));
228 gboolean found
= FALSE
;
230 if (sv_plugin
->locals_line_number
== lineno
)
232 sv_plugin
->locals_line_number
= lineno
;
234 if (!gtk_tree_model_get_iter_first (model
, &iter
))
236 while (!found
&& lineno
>= 0)
238 gtk_tree_model_get_iter_first (model
, &iter
);
241 found
= iter_matches (sv_plugin
, &iter
, model
, lineno
);
245 while (gtk_tree_model_iter_next (model
, &iter
));
252 on_char_added (IAnjutaEditor
*editor
, gint position
, gchar ch
,
253 SymbolDBPlugin
*sdb_plugin
)
255 DEBUG_PRINT ("char added @ %d : %c [int %d]", position
, ch
, ch
);
259 /* creates and start a new timer. */
260 timer
= g_timer_new ();
264 g_timer_reset (timer
);
268 /* try to force the update if a "." or a "->" is pressed */
269 if ((ch
== '.') || (prev_char_added
== '-' && ch
== '>'))
270 on_editor_buffer_symbols_update_timeout (sdb_plugin
);
272 need_symbols_update
= TRUE
;
274 prev_char_added
= ch
;
279 on_editor_saved (IAnjutaEditor
*editor
, const gchar
*saved_uri
,
280 SymbolDBPlugin
*sdb_plugin
)
282 const gchar
*old_uri
;
283 gboolean tags_update
;
285 /* FIXME: Do this only if automatic tags update is enabled */
287 anjuta_preferences_get_int (te->preferences, AUTOMATIC_TAGS_UPDATE);
292 gchar
*local_filename
;
293 GPtrArray
*files_array
;
295 /* Verify that it's local file */
296 local_filename
= gnome_vfs_get_local_path_from_uri (saved_uri
);
297 g_return_if_fail (local_filename
!= NULL
);
299 files_array
= g_ptr_array_new();
300 DEBUG_PRINT ("local_filename saved is %s", local_filename
);
301 g_ptr_array_add (files_array
, local_filename
);
302 /* no need to free local_filename now */
304 if (!sdb_plugin
->editor_connected
)
307 old_uri
= g_hash_table_lookup (sdb_plugin
->editor_connected
, editor
);
309 if (old_uri
&& strlen (old_uri
) <= 0)
312 /* files_array will be freed once updating has taken place */
313 symbol_db_engine_update_files_symbols (sdb_plugin
->sdbe
,
314 sdb_plugin
->project_root_dir
, files_array
, TRUE
);
315 g_hash_table_insert (sdb_plugin
->editor_connected
, editor
,
316 g_strdup (saved_uri
));
318 on_editor_update_ui (editor
, sdb_plugin
);
324 value_added_current_editor (AnjutaPlugin
*plugin
, const char *name
,
325 const GValue
*value
, gpointer data
)
330 SymbolDBPlugin
*sdb_plugin
;
332 editor
= g_value_get_object (value
);
333 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
335 if (!sdb_plugin
->editor_connected
)
337 sdb_plugin
->editor_connected
= g_hash_table_new_full (g_direct_hash
,
341 sdb_plugin
->current_editor
= editor
;
343 uri
= ianjuta_file_get_uri (IANJUTA_FILE (editor
), NULL
);
348 local_path
= gnome_vfs_get_local_path_from_uri (uri
);
350 symbol_db_view_locals_update_list (
351 SYMBOL_DB_VIEW_LOCALS (sdb_plugin
->dbv_view_tree_locals
),
352 sdb_plugin
->sdbe
, local_path
);
354 if (g_hash_table_lookup (sdb_plugin
->editor_connected
, editor
) == NULL
)
356 g_object_weak_ref (G_OBJECT (editor
),
357 (GWeakNotify
) (on_editor_destroy
),
361 g_hash_table_insert (sdb_plugin
->editor_connected
, editor
,
366 g_hash_table_insert (sdb_plugin->editor_connected, editor,
370 g_signal_connect (G_OBJECT (editor
), "saved",
371 G_CALLBACK (on_editor_saved
),
374 g_signal_connect (G_OBJECT (editor
), "char-added",
375 G_CALLBACK (on_char_added
),
377 g_signal_connect (G_OBJECT(editor
), "update_ui",
378 G_CALLBACK (on_editor_update_ui
),
384 /* add a default timeout to the updating of buffer symbols */
385 timeout_id
= g_timeout_add (TIMEOUT_INTERVAL_SYMBOLS_UPDATE
,
386 on_editor_buffer_symbols_update_timeout
,
388 need_symbols_update
= FALSE
;
392 on_editor_foreach_disconnect (gpointer key
, gpointer value
, gpointer user_data
)
394 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
395 G_CALLBACK (on_editor_saved
),
397 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
398 G_CALLBACK (on_editor_update_ui
),
400 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
401 G_CALLBACK (on_char_added
),
403 g_object_weak_unref (G_OBJECT(key
),
404 (GWeakNotify
) (on_editor_destroy
),
409 goto_file_line (AnjutaPlugin
*plugin
, const gchar
*filename
, gint lineno
)
412 IAnjutaFileLoader
*loader
;
414 g_return_if_fail (filename
!= NULL
);
416 /* Go to file and line number */
417 loader
= anjuta_shell_get_interface (plugin
->shell
, IAnjutaFileLoader
,
420 uri
= g_strdup_printf ("file:///%s#%d", filename
, lineno
);
421 ianjuta_file_loader_load (loader
, uri
, FALSE
, NULL
);
427 goto_tree_iter (SymbolDBPlugin
*sdb_plugin
, GtkTreeIter
*iter
)
431 line
= symbol_db_view_locals_get_line (SYMBOL_DB_VIEW_LOCALS (
432 sdb_plugin
->dbv_view_tree_locals
), iter
);
434 DEBUG_PRINT ("got line %d", line
);
436 if (line
> 0 && sdb_plugin
->current_editor
)
438 /* Goto line number */
439 ianjuta_editor_goto_line (IANJUTA_EDITOR (sdb_plugin
->current_editor
),
441 if (IANJUTA_IS_MARKABLE (sdb_plugin
->current_editor
))
443 ianjuta_markable_delete_all_markers (IANJUTA_MARKABLE (sdb_plugin
->current_editor
),
444 IANJUTA_MARKABLE_LINEMARKER
,
447 ianjuta_markable_mark (IANJUTA_MARKABLE (sdb_plugin
->current_editor
),
448 line
, IANJUTA_MARKABLE_LINEMARKER
, NULL
);
454 * will manage the click of mouse and other events on search->hitlist treeview
457 on_treesearch_symbol_selected_event (SymbolDBViewSearch
*search
,
460 SymbolDBPlugin
*sdb_plugin
) {
462 DEBUG_PRINT ("on_treesearch_symbol_selected_event (), %s %d", file
, line
);
463 goto_file_line (ANJUTA_PLUGIN (sdb_plugin
), file
, line
);
468 on_local_treeview_row_activated (GtkTreeView
*view
, GtkTreePath
*arg1
,
469 GtkTreeViewColumn
*arg2
,
470 SymbolDBPlugin
*sdb_plugin
)
473 GtkTreeSelection
*selection
;
476 DEBUG_PRINT ("on_local_treeview_row_activated ()");
477 selection
= gtk_tree_view_get_selection (view
);
478 if (!gtk_tree_selection_get_selected (selection
, &model
, &iter
)) {
481 goto_tree_iter (sdb_plugin
, &iter
);
486 on_editor_foreach_clear (gpointer key
, gpointer value
, gpointer user_data
)
490 uri
= (const gchar
*)value
;
491 if (uri
&& strlen (uri
) > 0)
495 DEBUG_PRINT ("Removing file tags of %s", uri
);
496 anjuta_symbol_view_workspace_remove_file (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
),
503 value_removed_current_editor (AnjutaPlugin
*plugin
,
504 const char *name
, gpointer data
)
506 SymbolDBPlugin
*sdb_plugin
;
508 /* let's remove the timeout for symbols refresh */
509 g_source_remove (timeout_id
);
510 need_symbols_update
= FALSE
;
512 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
514 ui = anjuta_shell_get_ui (plugin->shell, NULL);
515 action = anjuta_ui_get_action (ui, "ActionGroupSymbolNavigation",
517 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
519 sdb_plugin
->current_editor
= NULL
;
524 on_project_element_added (IAnjutaProjectManager
*pm
, const gchar
*uri
,
525 SymbolDBPlugin
*sv_plugin
)
529 g_return_if_fail (sv_plugin
->project_root_uri
!= NULL
);
530 g_return_if_fail (sv_plugin
->project_root_dir
!= NULL
);
532 DEBUG_PRINT ("on_project_element_added");
534 filename
= gnome_vfs_get_local_path_from_uri (uri
);
537 GPtrArray
*files_array
;
538 const gchar
* file_mime
;
539 IAnjutaLanguageId lang_id
;
541 IAnjutaLanguage
* lang_manager
=
542 anjuta_shell_get_interface (ANJUTA_PLUGIN(sv_plugin
)->shell
, IAnjutaLanguage
, NULL
);
543 file_mime
= gnome_vfs_get_mime_type_for_name (filename
);
545 lang_id
= ianjuta_language_get_from_mime_type (lang_manager
, file_mime
, NULL
);
547 /* No supported language... */
554 lang
= ianjuta_language_get_name (lang_manager
, lang_id
, NULL
);
555 files_array
= g_ptr_array_new();
556 g_ptr_array_add (files_array
, filename
);
557 DEBUG_PRINT ("gonna opening %s",
558 filename
+ strlen(sv_plugin
->project_root_dir
) );
559 DEBUG_PRINT ("poject_root_dir %s", sv_plugin
->project_root_dir
);
561 symbol_db_engine_add_new_files (sv_plugin
->sdbe
,
562 sv_plugin
->project_root_dir
, files_array
, lang
, TRUE
);
565 g_ptr_array_free (files_array
, TRUE
);
570 on_project_element_removed (IAnjutaProjectManager
*pm
, const gchar
*uri
,
571 SymbolDBPlugin
*sv_plugin
)
575 if (!sv_plugin
->project_root_uri
)
578 filename
= gnome_vfs_get_local_path_from_uri (uri
);
581 DEBUG_PRINT ("on_project_element_removed");
582 DEBUG_PRINT ("gonna removing %s",
583 filename
+ strlen(sv_plugin
->project_root_dir
));
584 DEBUG_PRINT ("poject_root_dir %s", sv_plugin
->project_root_dir
);
585 symbol_db_engine_remove_file (sv_plugin
->sdbe
,
586 sv_plugin
->project_root_dir
, filename
);
593 sources_array_free (gpointer data
)
595 GPtrArray
* sources
= (GPtrArray
*) data
;
596 g_ptr_array_foreach (sources
, (GFunc
)g_free
, NULL
);
597 g_ptr_array_free (sources
, TRUE
);
602 SymbolDBEngine
* sdbe
;
603 const gchar
* root_dir
;
604 } SourcesForeachData
;
607 sources_array_add_foreach (gpointer key
, gpointer value
, gpointer user_data
)
609 const gchar
* lang
= (const gchar
*) key
;
610 GPtrArray
* sources_array
= (GPtrArray
*) value
;
611 SourcesForeachData
* data
= (SourcesForeachData
*) user_data
;
613 if (symbol_db_engine_add_new_files (data
->sdbe
, data
->root_dir
,
614 sources_array
, lang
, TRUE
) == FALSE
)
616 DEBUG_PRINT ("__FUNCTION__ failed for lang %s, root_dir %s",
617 lang
, data
->root_dir
);
621 /* add a new project */
623 project_root_added (AnjutaPlugin
*plugin
, const gchar
*name
,
624 const GValue
*value
, gpointer user_data
)
626 AnjutaStatus
*status
;
627 IAnjutaProjectManager
*pm
;
628 SymbolDBPlugin
*sdb_plugin
;
629 const gchar
*root_uri
;
631 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
633 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
,
634 IAnjutaProjectManager
, NULL
);
636 g_free (sdb_plugin
->project_root_uri
);
637 sdb_plugin
->project_root_uri
= NULL
;
638 root_uri
= g_value_get_string (value
);
641 gchar
*root_dir
= gnome_vfs_get_local_path_from_uri (root_uri
);
642 DEBUG_PRINT ("Symbol-DB: added project %s", root_dir
);
645 gboolean needs_sources_scan
= FALSE
;
647 GHashTable
* lang_hash
=
648 g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, sources_array_free
);
650 status
= anjuta_shell_get_status (plugin
->shell
, NULL
);
651 anjuta_status_progress_add_ticks (status
, 1);
653 DEBUG_PRINT ("Symbol-DB: creating new project.");
655 /* is it a fresh-new project? is it an imported project with
656 * no 'new' symbol-db database but the 'old' one symbol-browser?
658 if (symbol_db_engine_db_exists (sdb_plugin
->sdbe
, root_dir
) == FALSE
)
660 needs_sources_scan
= TRUE
;
663 if (symbol_db_engine_open_db (sdb_plugin
->sdbe
, root_dir
) == FALSE
)
664 g_error ("error in opening db");
666 symbol_db_engine_add_new_project (sdb_plugin
->sdbe
,
667 NULL
, /* still no workspace */
670 /* open the project. we can do this only if the db was loaded */
671 if (symbol_db_engine_open_project (sdb_plugin
->sdbe
, root_dir
) == FALSE
)
672 g_warning ("error in opening project");
674 if (needs_sources_scan
== TRUE
)
676 GList
* prj_elements_list
;
678 DEBUG_PRINT ("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
679 DEBUG_PRINT ("Retrieving gbf sources of the project...");
681 prj_elements_list
= ianjuta_project_manager_get_elements (pm
,
682 IANJUTA_PROJECT_MANAGER_SOURCE
,
685 GPtrArray
* sources_array
;
687 for (i
=0; i
< g_list_length (prj_elements_list
); i
++)
689 gchar
*local_filename
;
690 const gchar
*file_mime
;
692 IAnjutaLanguageId lang_id
;
693 IAnjutaLanguage
* lang_manager
=
694 anjuta_shell_get_interface (plugin
->shell
, IAnjutaLanguage
, NULL
);
698 g_critical ("LanguageManager not found");
703 gnome_vfs_get_local_path_from_uri (g_list_nth_data (
704 prj_elements_list
, i
));
705 file_mime
= gnome_vfs_get_mime_type_for_name (local_filename
);
707 lang_id
= ianjuta_language_get_from_mime_type (lang_manager
, file_mime
, NULL
);
711 g_free (local_filename
);
715 lang
= ianjuta_language_get_name (lang_manager
, lang_id
, NULL
);
716 DEBUG_PRINT ("Language of %s is %s", local_filename
, file_mime
);
717 /* test its existence */
718 if (g_file_test (local_filename
, G_FILE_TEST_EXISTS
) == FALSE
)
720 g_free (local_filename
);
724 sources_array
= g_hash_table_lookup (lang_hash
, lang
);
727 sources_array
= g_ptr_array_new ();
728 g_hash_table_insert (lang_hash
, (gpointer
) lang
, sources_array
);
731 g_ptr_array_add (sources_array
, local_filename
);
734 DEBUG_PRINT ("calling symbol_db_engine_add_new_files with root_dir %s",
737 SourcesForeachData
* data
= g_new0 (SourcesForeachData
, 1);
738 data
->sdbe
= sdb_plugin
->sdbe
;
739 data
->root_dir
= root_dir
;
741 g_hash_table_foreach (lang_hash
, (GHFunc
) sources_array_add_foreach
,
745 g_hash_table_unref (lang_hash
);
748 anjuta_status_progress_tick (status
, NULL
, _("Created symbols..."));
750 symbol_db_view_open (SYMBOL_DB_VIEW (sdb_plugin
->dbv_view_tree
),
754 sdb_plugin
->project_root_dir
= root_dir
;
757 sdb_plugin
->project_root_uri
= g_strdup (root_uri
);
760 g_signal_connect (G_OBJECT (pm
), "element_added",
761 G_CALLBACK (on_project_element_added
), sdb_plugin
);
762 g_signal_connect (G_OBJECT (pm
), "element_removed",
763 G_CALLBACK (on_project_element_removed
), sdb_plugin
);
767 project_root_removed (AnjutaPlugin
*plugin
, const gchar
*name
,
770 IAnjutaProjectManager
*pm
;
771 SymbolDBPlugin
*sdb_plugin
;
773 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
775 /* Disconnect events from project manager */
777 /* FIXME: There should be a way to ensure that this project manager
778 * is indeed the one that has opened the project_uri
780 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
,
781 IAnjutaProjectManager
, NULL
);
782 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
783 on_project_element_added
,
785 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
786 on_project_element_removed
,
789 /* don't forget to close the project */
790 symbol_db_engine_close_project (sdb_plugin
->sdbe
,
791 sdb_plugin
->project_root_dir
);
793 g_free (sdb_plugin
->project_root_uri
);
794 g_free (sdb_plugin
->project_root_dir
);
795 sdb_plugin
->project_root_uri
= NULL
;
796 sdb_plugin
->project_root_dir
= NULL
;
800 symbol_db_activate (AnjutaPlugin
*plugin
)
802 SymbolDBPlugin
*symbol_db
;
804 DEBUG_PRINT ("SymbolDBPlugin: Activating SymbolDBPlugin plugin ...");
807 register_stock_icons (plugin
);
809 symbol_db
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
810 symbol_db
->ui
= anjuta_shell_get_ui (plugin
->shell
, NULL
);
812 /* create SymbolDBEngine */
813 symbol_db
->sdbe
= symbol_db_engine_new ();
816 symbol_db
->dbv_notebook
= gtk_notebook_new();
819 symbol_db
->scrolled_locals
= gtk_scrolled_window_new (NULL
, NULL
);
820 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (symbol_db
->scrolled_locals
),
822 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (symbol_db
->scrolled_locals
),
823 GTK_POLICY_AUTOMATIC
,
824 GTK_POLICY_AUTOMATIC
);
826 symbol_db
->dbv_view_locals_tab_label
= gtk_label_new (_("Local" ));
827 symbol_db
->dbv_view_tree_locals
= symbol_db_view_locals_new ();
829 g_object_add_weak_pointer (G_OBJECT (symbol_db
->dbv_view_tree_locals
),
830 (gpointer
)&symbol_db
->dbv_view_tree_locals
);
831 g_signal_connect (G_OBJECT (symbol_db
->dbv_view_tree_locals
), "row_activated",
832 G_CALLBACK (on_local_treeview_row_activated
), plugin
);
834 gtk_container_add (GTK_CONTAINER(symbol_db
->scrolled_locals
),
835 symbol_db
->dbv_view_tree_locals
);
839 symbol_db
->scrolled_global
= gtk_scrolled_window_new (NULL
, NULL
);
840 gtk_scrolled_window_set_shadow_type (
841 GTK_SCROLLED_WINDOW (symbol_db
->scrolled_global
),
843 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (symbol_db
->scrolled_global
),
844 GTK_POLICY_AUTOMATIC
,
845 GTK_POLICY_AUTOMATIC
);
847 symbol_db
->dbv_view_tab_label
= gtk_label_new (_("Global" ));
848 symbol_db
->dbv_view_tree
= symbol_db_view_new ();
849 g_object_add_weak_pointer (G_OBJECT (symbol_db
->dbv_view_tree
),
850 (gpointer
)&symbol_db
->dbv_view_tree
);
852 g_signal_connect (G_OBJECT (symbol_db
->dbv_view_tree
), "event-after",
853 G_CALLBACK (on_treeview_event
), plugin
);
855 g_signal_connect (G_OBJECT (symbol_db
->dbv_view_tree
), "row_activated",
856 G_CALLBACK (on_treeview_row_activated
), plugin
);
858 gtk_container_add (GTK_CONTAINER(symbol_db
->scrolled_global
),
859 symbol_db
->dbv_view_tree
);
862 symbol_db
->dbv_view_tree_search
=
863 (GtkWidget
*) symbol_db_view_search_new (symbol_db
->sdbe
);
864 symbol_db
->dbv_view_search_tab_label
= gtk_label_new (_("Search" ));
866 g_signal_connect (G_OBJECT (symbol_db
->dbv_view_tree_search
), "symbol_selected",
867 G_CALLBACK (on_treesearch_symbol_selected_event
),
870 g_object_add_weak_pointer (G_OBJECT (symbol_db
->dbv_view_tree_search
),
871 (gpointer
)&symbol_db
->dbv_view_tree_search
);
873 /* add the scrolled windows to the notebook */
874 gtk_notebook_append_page (GTK_NOTEBOOK (symbol_db
->dbv_notebook
),
875 symbol_db
->scrolled_locals
,
876 symbol_db
->dbv_view_locals_tab_label
);
878 gtk_notebook_append_page (GTK_NOTEBOOK (symbol_db
->dbv_notebook
),
879 symbol_db
->scrolled_global
,
880 symbol_db
->dbv_view_tab_label
);
882 gtk_notebook_append_page (GTK_NOTEBOOK (symbol_db
->dbv_notebook
),
883 symbol_db
->dbv_view_tree_search
,
884 symbol_db
->dbv_view_search_tab_label
);
886 gtk_widget_show_all (symbol_db
->dbv_notebook
);
888 /* setting focus to the tree_view*/
889 gtk_notebook_set_current_page (GTK_NOTEBOOK (symbol_db
->dbv_notebook
), 0);
891 symbol_db
->editor_watch_id
=
892 anjuta_plugin_add_watch (plugin
, "document_manager_current_editor",
893 value_added_current_editor
,
894 value_removed_current_editor
, NULL
);
897 symbol_db
->merge_id
=
898 anjuta_ui_merge (symbol_db
->ui
, UI_FILE
);
901 anjuta_shell_add_widget (plugin
->shell
, symbol_db
->dbv_notebook
,
902 "SymbolDBView", _("Symbols"),
903 "symbol-db-plugin-icon",
904 ANJUTA_SHELL_PLACEMENT_LEFT
, NULL
);
906 /* set up project directory watch */
907 symbol_db
->root_watch_id
= anjuta_plugin_add_watch (plugin
,
910 project_root_removed
, NULL
);
916 symbol_db_deactivate (AnjutaPlugin
*plugin
)
918 SymbolDBPlugin
*sdb_plugin
;
920 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
922 DEBUG_PRINT ("SymbolDBPlugin: Dectivating SymbolDBPlugin plugin ...");
924 DEBUG_PRINT ("SymbolDBPlugin: destroying engine ...");
925 g_object_unref (sdb_plugin
->sdbe
);
926 sdb_plugin
->sdbe
= NULL
;
928 /* disconnect some signals */
929 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->dbv_view_tree_locals
),
930 on_local_treeview_row_activated
,
933 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->dbv_view_tree_search
),
934 on_treesearch_symbol_selected_event
,
938 DEBUG_PRINT ("SymbolDBPlugin: destroying locals view ...");
939 g_object_unref (sdb_plugin->dbv_view_tree_locals);
941 DEBUG_PRINT ("SymbolDBPlugin: destroying globals view ...");
942 g_object_unref (sdb_plugin->dbv_view_tree);
944 DEBUG_PRINT ("SymbolDBPlugin: destroying search ...");
945 g_object_unref (sdb_plugin->dbv_view_tree_search);
948 /* Ensure all editor cached info are released */
949 if (sdb_plugin
->editor_connected
)
951 g_hash_table_foreach (sdb_plugin
->editor_connected
,
952 on_editor_foreach_disconnect
, plugin
);
953 g_hash_table_foreach (sdb_plugin
->editor_connected
,
954 on_editor_foreach_clear
, plugin
);
955 g_hash_table_destroy (sdb_plugin
->editor_connected
);
956 sdb_plugin
->editor_connected
= NULL
;
960 anjuta_plugin_remove_watch (plugin
, sdb_plugin
->root_watch_id
, FALSE
);
961 anjuta_plugin_remove_watch (plugin
, sdb_plugin
->editor_watch_id
, TRUE
);
963 /* Remove widgets: Widgets will be destroyed when dbv_notebook is removed */
964 anjuta_shell_remove_widget (plugin
->shell
, sdb_plugin
->dbv_notebook
, NULL
);
968 anjuta_ui_unmerge (sdb_plugin
->ui
, sdb_plugin
->merge_id
);
970 /* Remove action group */
971 anjuta_ui_remove_action_group (sv_plugin
->ui
, sv_plugin
->action_group
);
972 anjuta_ui_remove_action_group (sv_plugin
->ui
, sv_plugin
->popup_action_group
);
973 anjuta_ui_remove_action_group (sdb_plugin
->ui
, sdb_plugin
->action_group_nav
);
974 ui
= anjuta_shell_get_ui (plugin
->shell
, NULL
);
975 /* anjuta_ui_remove_action_group (ui, ((SymbolDBPlugin*)plugin)->action_group); */
976 anjuta_ui_unmerge (ui
, ((SymbolDBPlugin
*)plugin
)->uiid
);
979 sdb_plugin
->root_watch_id
= 0;
980 sdb_plugin
->editor_watch_id
= 0;
981 sdb_plugin
->dbv_notebook
= NULL
;
982 sdb_plugin
->scrolled_global
= NULL
;
983 sdb_plugin
->scrolled_locals
= NULL
;
984 sdb_plugin
->dbv_view_tree
= NULL
;
985 sdb_plugin
->dbv_view_tab_label
= NULL
;
986 sdb_plugin
->dbv_view_tree_locals
= NULL
;
987 sdb_plugin
->dbv_view_locals_tab_label
= NULL
;
988 sdb_plugin
->dbv_view_tree_search
= NULL
;
989 sdb_plugin
->dbv_view_search_tab_label
= NULL
;
994 symbol_db_finalize (GObject
*obj
)
996 /* Finalization codes here */
997 GNOME_CALL_PARENT (G_OBJECT_CLASS
, finalize
, (obj
));
1001 symbol_db_dispose (GObject
*obj
)
1003 /* Disposition codes */
1004 GNOME_CALL_PARENT (G_OBJECT_CLASS
, dispose
, (obj
));
1008 symbol_db_instance_init (GObject
*obj
)
1010 SymbolDBPlugin
*plugin
= (SymbolDBPlugin
*)obj
;
1013 plugin
->widget
= NULL
;
1017 symbol_db_class_init (GObjectClass
*klass
)
1019 AnjutaPluginClass
*plugin_class
= ANJUTA_PLUGIN_CLASS (klass
);
1021 parent_class
= g_type_class_peek_parent (klass
);
1023 plugin_class
->activate
= symbol_db_activate
;
1024 plugin_class
->deactivate
= symbol_db_deactivate
;
1025 klass
->finalize
= symbol_db_finalize
;
1026 klass
->dispose
= symbol_db_dispose
;
1029 static IAnjutaIterable
*
1030 isymbol_manager_search (IAnjutaSymbolManager
*sm
,
1031 IAnjutaSymbolType match_types
,
1032 const gchar
*match_name
,
1033 gboolean partial_name_match
,
1034 gboolean global_search
,
1037 SymbolDBEngineIterator
*iterator
= NULL
;
1038 SymbolDBPlugin
*sdb_plugin
;
1039 SymbolDBEngine
*dbe
;
1042 DEBUG_PRINT ("called isymbol_manager_search()! %s", match_name
);
1044 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (sm
);
1045 dbe
= SYMBOL_DB_ENGINE (sdb_plugin
->sdbe
);
1048 if (match_name
&& strlen (match_name
) > 0)
1055 symbol_db_engine_find_symbol_by_name_pattern (dbe
,
1056 name
, SYMINFO_SIMPLE
|
1058 SYMINFO_IMPLEMENTATION
|
1064 SYMINFO_FILE_IGNORE
|
1065 SYMINFO_FILE_INCLUDE
|
1066 SYMINFO_PROJECT_NAME
|
1067 SYMINFO_WORKSPACE_NAME
);
1069 return IANJUTA_ITERABLE (iterator
);
1072 static IAnjutaIterable
*
1073 isymbol_manager_get_members (IAnjutaSymbolManager
*sm
,
1074 const gchar
*symbol_name
,
1075 gboolean global_search
,
1079 const GPtrArray
*tags_array
;
1080 AnjutaSymbolIter
*iter
= NULL
;
1082 tags_array
= tm_workspace_find_scope_members (NULL
, symbol_name
,
1083 global_search
, TRUE
);
1088 iter
= anjuta_symbol_iter_new (tags_array
);
1089 return IANJUTA_ITERABLE (iter
);
1095 static IAnjutaIterable
*
1096 isymbol_manager_get_parents (IAnjutaSymbolManager
*sm
,
1097 const gchar
*symbol_name
,
1101 const GPtrArray
*tags_array
;
1102 AnjutaSymbolIter
*iter
= NULL
;
1104 tags_array
= tm_workspace_get_parents (symbol_name
);
1107 iter
= anjuta_symbol_iter_new (tags_array
);
1108 return IANJUTA_ITERABLE (iter
);
1114 static IAnjutaIterable
*
1115 isymbol_manager_get_completions_at_position (IAnjutaSymbolManager
*sm
,
1116 const gchar
*file_uri
,
1117 const gchar
*text_buffer
,
1123 SymbolBrowserPlugin
*sv_plugin
;
1124 const TMTag
*func_scope_tag
;
1125 TMSourceFile
*tm_file
;
1127 AnjutaSymbolView
*symbol_view
;
1129 gulong scope_position
;
1130 gchar
*needed_text
= NULL
;
1132 GPtrArray
* completable_tags_array
;
1133 AnjutaSymbolIter
*iter
= NULL
;
1135 sv_plugin
= ANJUTA_PLUGIN_SYMBOL_BROWSER (sm
);
1136 ed
= IANJUTA_EDITOR (sv_plugin
->current_editor
);
1137 symbol_view
= ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
);
1139 line
= ianjuta_editor_get_line_from_position (ed
, text_pos
, NULL
);
1141 /* get the function scope */
1142 tm_file
= anjuta_symbol_view_get_tm_file (symbol_view
, file_uri
);
1144 /* check whether the current file_uri is listed in the tm_workspace or not... */
1145 if (tm_file
== NULL
)
1149 // FIXME: remove DEBUG_PRINT
1151 DEBUG_PRINT ("tags in file &s\n");
1152 if (tm_file->work_object.tags_array != NULL) {
1154 for (i=0; i < tm_file->work_object.tags_array->len; i++) {
1157 cur_tag = (TMTag*)g_ptr_array_index (tm_file->work_object.tags_array, i);
1158 tm_tag_print (cur_tag, stdout);
1163 func_scope_tag = tm_get_current_function (tm_file->work_object.tags_array, line);
1165 if (func_scope_tag == NULL) {
1166 DEBUG_PRINT ("func_scope_tag is NULL, seems like it's a completion on a global scope");
1170 DEBUG_PRINT ("current expression scope: %s", func_scope_tag->name);
1173 scope_position = ianjuta_editor_get_line_begin_position (ed, func_scope_tag->atts.entry.line, NULL);
1174 needed_text = ianjuta_editor_get_text (ed, scope_position,
1175 text_pos - scope_position, NULL);
1177 if (needed_text == NULL)
1178 DEBUG_PRINT ("needed_text is null");
1179 DEBUG_PRINT ("text needed is %s", needed_text );
1182 /* we'll pass only the text of the current scope: i.e. only the current function
1183 * in which we request the completion. */
1184 TMTag
* found_type
= anjuta_symbol_view_get_type_of_expression (symbol_view
,
1185 needed_text
, text_pos
- scope_position
, func_scope_tag
, &access_method
);
1188 if (found_type
== NULL
) {
1189 DEBUG_PRINT ("type not found.");
1193 /* get the completable memebers. If the access is COMPLETION_ACCESS_STATIC we don't
1194 * want to know the parents members of the class.
1196 if (access_method
== COMPLETION_ACCESS_STATIC
)
1197 completable_tags_array
= anjuta_symbol_view_get_completable_members (found_type
, FALSE
);
1199 completable_tags_array
= anjuta_symbol_view_get_completable_members (found_type
, TRUE
);
1201 if (completable_tags_array
)
1203 iter
= anjuta_symbol_iter_new (completable_tags_array
);
1204 return IANJUTA_ITERABLE (iter
);
1212 isymbol_manager_iface_init (IAnjutaSymbolManagerIface
*iface
)
1214 iface
->search
= isymbol_manager_search
;
1215 iface
->get_members
= isymbol_manager_get_members
;
1216 iface
->get_parents
= isymbol_manager_get_parents
;
1217 iface
->get_completions_at_position
= isymbol_manager_get_completions_at_position
;
1220 ANJUTA_PLUGIN_BEGIN (SymbolDBPlugin
, symbol_db
);
1221 ANJUTA_PLUGIN_ADD_INTERFACE (isymbol_manager
, IANJUTA_TYPE_SYMBOL_MANAGER
);
1224 ANJUTA_SIMPLE_PLUGIN (SymbolDBPlugin
, symbol_db
);