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 15000
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
;
65 register_stock_icons (AnjutaPlugin
*plugin
)
67 static gboolean registered
= FALSE
;
73 /* Register stock icons */
74 BEGIN_REGISTER_ICON (plugin
);
75 REGISTER_ICON (ICON_FILE
, "symbol-db-plugin-icon");
79 static GtkActionEntry actions[] =
81 { "ActionMenuGoto", NULL, N_("_Goto"), NULL, NULL, NULL},
83 "ActionSymbolBrowserGotoDef",
85 N_("Tag _Definition"),
87 N_("Goto symbol definition"),
88 G_CALLBACK (on_goto_file_tag_def_activate)
91 "ActionSymbolBrowserGotoDecl",
93 N_("Tag De_claration"),
95 N_("Goto symbol declaration"),
96 G_CALLBACK (on_goto_file_tag_decl_activate)
102 on_editor_buffer_symbols_update_timeout (gpointer user_data
)
104 SymbolDBPlugin
*sdb_plugin
;
106 gchar
*current_buffer
= NULL
;
107 gint buffer_size
= 0;
109 gdouble seconds_elapsed
;
111 g_return_val_if_fail (user_data
!= NULL
, FALSE
);
113 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (user_data
);
115 if (sdb_plugin
->current_editor
== NULL
)
118 /* check the timer. If it's elapsed enought time since the last time the user
119 * typed in something, than proceed with updating, elsewhere don't do nothing
124 seconds_elapsed
= g_timer_elapsed (timer
, NULL
);
126 /* DEBUG_PRINT ("seconds_elapsed %f", seconds_elapsed ); */
127 if (seconds_elapsed
< TIMEOUT_SECONDS_AFTER_LAST_TIP
)
131 /* we won't proceed with the updating of the symbols if we didn't type in
133 if (!need_symbols_update
)
136 DEBUG_PRINT ("on_editor_buffer_symbols_update_timeout()");
138 if (sdb_plugin
->current_editor
)
140 ed
= IANJUTA_EDITOR (sdb_plugin
->current_editor
);
142 buffer_size
= ianjuta_editor_get_length (ed
, NULL
);
143 current_buffer
= ianjuta_editor_get_text (ed
, 0, -1, NULL
);
145 uri
= ianjuta_file_get_uri (IANJUTA_FILE (ed
), NULL
);
152 DEBUG_PRINT ("uri for buffer updating: %s", uri
);
154 GPtrArray
*real_files_list
;
155 GPtrArray
*text_buffers
;
156 GPtrArray
*buffer_sizes
;
159 gchar
* local_path
= gnome_vfs_get_local_path_from_uri (uri
);
161 real_files_list
= g_ptr_array_new ();
162 g_ptr_array_add (real_files_list
, local_path
);
164 text_buffers
= g_ptr_array_new ();
165 g_ptr_array_add (text_buffers
, current_buffer
);
167 buffer_sizes
= g_ptr_array_new ();
168 g_ptr_array_add (buffer_sizes
, (gpointer
)buffer_size
);
170 project_name
= symbol_db_engine_get_opened_project_name (sdb_plugin
->sdbe
);
172 symbol_db_engine_update_buffer_symbols (sdb_plugin
->sdbe
,
177 g_free (project_name
);
182 g_free (current_buffer
);
184 need_symbols_update
= FALSE
;
190 on_editor_destroy (SymbolDBPlugin
*sdb_plugin
, IAnjutaEditor
*editor
)
194 if (!sdb_plugin
->editor_connected
|| !sdb_plugin
->dbv_view_tree
)
197 uri
= g_hash_table_lookup (sdb_plugin
->editor_connected
, G_OBJECT (editor
));
198 if (uri
&& strlen (uri
) > 0)
200 DEBUG_PRINT ("Removing file tags of %s", uri
);
202 anjuta_symbol_view_workspace_remove_file (ANJUTA_SYMBOL_VIEW (sv_plugin->sv_tree),
206 g_hash_table_remove (sdb_plugin
->editor_connected
, G_OBJECT (editor
));
210 on_editor_update_ui (IAnjutaEditor
*editor
, SymbolDBPlugin
*sdb_plugin
)
213 gint lineno
= ianjuta_editor_get_lineno (editor
, NULL
);
215 GtkTreeModel
* model
= anjuta_symbol_view_get_file_symbol_model
216 (ANJUTA_SYMBOL_VIEW(sv_plugin
->sv_tree
));
218 gboolean found
= FALSE
;
220 if (sv_plugin
->locals_line_number
== lineno
)
222 sv_plugin
->locals_line_number
= lineno
;
224 if (!gtk_tree_model_get_iter_first (model
, &iter
))
226 while (!found
&& lineno
>= 0)
228 gtk_tree_model_get_iter_first (model
, &iter
);
231 found
= iter_matches (sv_plugin
, &iter
, model
, lineno
);
235 while (gtk_tree_model_iter_next (model
, &iter
));
242 on_char_added (IAnjutaEditor
*editor
, gint position
, gchar ch
,
243 SymbolDBPlugin
*sdb_plugin
)
245 DEBUG_PRINT ("char added @ %d : %c [int %d]", position
, ch
, ch
);
249 /* creates and start a new timer. */
250 timer
= g_timer_new ();
254 g_timer_reset (timer
);
258 /* try to force the update if a "." or a "->" is pressed */
259 if ((ch
== '.') || (prev_char_added
== '-' && ch
== '>'))
260 on_editor_buffer_symbols_update_timeout (sdb_plugin
);
262 need_symbols_update
= TRUE
;
264 prev_char_added
= ch
;
269 on_editor_saved (IAnjutaEditor
*editor
, const gchar
*saved_uri
,
270 SymbolDBPlugin
*sdb_plugin
)
272 const gchar
*old_uri
;
273 gboolean tags_update
;
275 /* FIXME: Do this only if automatic tags update is enabled */
277 anjuta_preferences_get_int (te->preferences, AUTOMATIC_TAGS_UPDATE);
282 gchar
*local_filename
;
283 GPtrArray
*files_array
;
285 /* Verify that it's local file */
286 local_filename
= gnome_vfs_get_local_path_from_uri (saved_uri
);
287 g_return_if_fail (local_filename
!= NULL
);
289 files_array
= g_ptr_array_new();
290 DEBUG_PRINT ("local_filename saved is %s", local_filename
);
291 g_ptr_array_add (files_array
, local_filename
);
292 /* no need to free local_filename now */
294 if (!sdb_plugin
->editor_connected
)
297 old_uri
= g_hash_table_lookup (sdb_plugin
->editor_connected
, editor
);
299 if (old_uri
&& strlen (old_uri
) <= 0)
302 /* files_array will be freed once updating has taken place */
303 symbol_db_engine_update_files_symbols (sdb_plugin
->sdbe
,
304 sdb_plugin
->project_root_dir
, files_array
, TRUE
);
305 g_hash_table_insert (sdb_plugin
->editor_connected
, editor
,
306 g_strdup (saved_uri
));
308 on_editor_update_ui (editor
, sdb_plugin
);
313 //files = anjuta_session_get_string_list (session, "File Loader", "Files");
315 value_added_current_editor (AnjutaPlugin
*plugin
, const char *name
,
316 const GValue
*value
, gpointer data
)
321 SymbolDBPlugin
*sdb_plugin
;
323 editor
= g_value_get_object (value
);
324 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
326 if (!sdb_plugin
->editor_connected
)
328 sdb_plugin
->editor_connected
= g_hash_table_new_full (g_direct_hash
,
332 sdb_plugin
->current_editor
= editor
;
334 uri
= ianjuta_file_get_uri (IANJUTA_FILE (editor
), NULL
);
339 local_path
= gnome_vfs_get_local_path_from_uri (uri
);
340 symbol_db_view_locals_update_list (
341 SYMBOL_DB_VIEW_LOCALS (sdb_plugin
->dbv_view_tree_locals
),
342 sdb_plugin
->sdbe
, local_path
);
344 if (g_hash_table_lookup (sdb_plugin
->editor_connected
, editor
) == NULL
)
346 g_object_weak_ref (G_OBJECT (editor
),
347 (GWeakNotify
) (on_editor_destroy
),
351 g_hash_table_insert (sdb_plugin
->editor_connected
, editor
,
356 g_hash_table_insert (sdb_plugin
->editor_connected
, editor
,
360 g_signal_connect (G_OBJECT (editor
), "saved",
361 G_CALLBACK (on_editor_saved
),
364 g_signal_connect (G_OBJECT (editor
), "char-added",
365 G_CALLBACK (on_char_added
),
367 g_signal_connect (G_OBJECT(editor
), "update_ui",
368 G_CALLBACK (on_editor_update_ui
),
374 /* add a default timeout to the updating of buffer symbols */
375 timeout_id
= g_timeout_add (TIMEOUT_INTERVAL_SYMBOLS_UPDATE
,
376 on_editor_buffer_symbols_update_timeout
,
378 need_symbols_update
= FALSE
;
382 on_editor_foreach_disconnect (gpointer key
, gpointer value
, gpointer user_data
)
384 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
385 G_CALLBACK (on_editor_saved
),
387 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
388 G_CALLBACK (on_editor_update_ui
),
390 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
391 G_CALLBACK (on_char_added
),
393 g_object_weak_unref (G_OBJECT(key
),
394 (GWeakNotify
) (on_editor_destroy
),
399 goto_file_line (AnjutaPlugin
*plugin
, const gchar
*filename
, gint lineno
)
402 IAnjutaFileLoader
*loader
;
404 g_return_if_fail (filename
!= NULL
);
406 /* Go to file and line number */
407 loader
= anjuta_shell_get_interface (plugin
->shell
, IAnjutaFileLoader
,
410 uri
= g_strdup_printf ("file:///%s#%d", filename
, lineno
);
411 ianjuta_file_loader_load (loader
, uri
, FALSE
, NULL
);
417 goto_tree_iter (SymbolDBPlugin
*sdb_plugin
, GtkTreeIter
*iter
)
421 line
= symbol_db_view_locals_get_line (SYMBOL_DB_VIEW_LOCALS (
422 sdb_plugin
->dbv_view_tree_locals
),
426 DEBUG_PRINT ("got line %d", line
);
428 if (line
> 0 && sdb_plugin
->current_editor
)
430 /* Goto line number */
431 ianjuta_editor_goto_line (IANJUTA_EDITOR (sdb_plugin
->current_editor
),
433 if (IANJUTA_IS_MARKABLE (sdb_plugin
->current_editor
))
435 ianjuta_markable_delete_all_markers (IANJUTA_MARKABLE (sdb_plugin
->current_editor
),
436 IANJUTA_MARKABLE_LINEMARKER
,
439 ianjuta_markable_mark (IANJUTA_MARKABLE (sdb_plugin
->current_editor
),
440 line
, IANJUTA_MARKABLE_LINEMARKER
, NULL
);
446 * will manage the click of mouse and other events on search->hitlist treeview
449 on_treesearch_symbol_selected_event (SymbolDBViewSearch
*search
,
452 SymbolDBPlugin
*sdb_plugin
) {
454 DEBUG_PRINT ("on_treesearch_symbol_selected_event (), %s %d", file
, line
);
455 goto_file_line (ANJUTA_PLUGIN (sdb_plugin
), file
, line
);
460 on_local_treeview_row_activated (GtkTreeView
*view
, GtkTreePath
*arg1
,
461 GtkTreeViewColumn
*arg2
,
462 SymbolDBPlugin
*sdb_plugin
)
465 GtkTreeSelection
*selection
;
468 DEBUG_PRINT ("on_local_treeview_row_activated ()");
469 selection
= gtk_tree_view_get_selection (view
);
470 if (!gtk_tree_selection_get_selected (selection
, &model
, &iter
)) {
473 goto_tree_iter (sdb_plugin
, &iter
);
478 on_editor_foreach_clear (gpointer key
, gpointer value
, gpointer user_data
)
482 uri
= (const gchar
*)value
;
483 if (uri
&& strlen (uri
) > 0)
487 DEBUG_PRINT ("Removing file tags of %s", uri
);
488 anjuta_symbol_view_workspace_remove_file (ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
),
495 value_removed_current_editor (AnjutaPlugin
*plugin
,
496 const char *name
, gpointer data
)
498 SymbolDBPlugin
*sdb_plugin
;
500 /* let's remove the timeout for symbols refresh */
501 g_source_remove (timeout_id
);
502 need_symbols_update
= FALSE
;
504 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
506 ui = anjuta_shell_get_ui (plugin->shell, NULL);
507 action = anjuta_ui_get_action (ui, "ActionGroupSymbolNavigation",
509 g_object_set (G_OBJECT (action), "sensitive", FALSE, NULL);
511 sdb_plugin
->current_editor
= NULL
;
516 on_project_element_added (IAnjutaProjectManager
*pm
, const gchar
*uri
,
517 SymbolDBPlugin
*sv_plugin
)
521 g_return_if_fail (sv_plugin
->project_root_uri
!= NULL
);
522 g_return_if_fail (sv_plugin
->project_root_dir
!= NULL
);
524 DEBUG_PRINT ("on_project_element_added");
526 filename
= gnome_vfs_get_local_path_from_uri (uri
);
529 GPtrArray
*files_array
;
530 const gchar
* file_mime
;
531 IAnjutaLanguageId lang_id
;
533 IAnjutaLanguage
* lang_manager
=
534 anjuta_shell_get_interface (ANJUTA_PLUGIN(sv_plugin
)->shell
, IAnjutaLanguage
, NULL
);
535 file_mime
= gnome_vfs_get_mime_type_for_name (filename
);
537 lang_id
= ianjuta_language_get_from_mime_type (lang_manager
, file_mime
, NULL
);
539 /* No supported language... */
546 lang
= ianjuta_language_get_name (lang_manager
, lang_id
, NULL
);
547 files_array
= g_ptr_array_new();
548 g_ptr_array_add (files_array
, filename
);
549 DEBUG_PRINT ("gonna opening %s",
550 filename
+ strlen(sv_plugin
->project_root_dir
) );
551 DEBUG_PRINT ("poject_root_dir %s", sv_plugin
->project_root_dir
);
553 symbol_db_engine_add_new_files (sv_plugin
->sdbe
,
554 sv_plugin
->project_root_dir
, files_array
, lang
, TRUE
);
557 g_ptr_array_free (files_array
, TRUE
);
562 on_project_element_removed (IAnjutaProjectManager
*pm
, const gchar
*uri
,
563 SymbolDBPlugin
*sv_plugin
)
567 if (!sv_plugin
->project_root_uri
)
570 filename
= gnome_vfs_get_local_path_from_uri (uri
);
573 DEBUG_PRINT ("on_project_element_removed");
574 DEBUG_PRINT ("gonna removing %s",
575 filename
+ strlen(sv_plugin
->project_root_dir
));
576 DEBUG_PRINT ("poject_root_dir %s", sv_plugin
->project_root_dir
);
577 symbol_db_engine_remove_file (sv_plugin
->sdbe
,
578 sv_plugin
->project_root_dir
, filename
);
585 sources_array_free (gpointer data
)
587 GPtrArray
* sources
= (GPtrArray
*) data
;
588 g_ptr_array_foreach (sources
, (GFunc
)g_free
, NULL
);
589 g_ptr_array_free (sources
, TRUE
);
594 SymbolDBEngine
* sdbe
;
595 const gchar
* root_dir
;
596 } SourcesForeachData
;
599 sources_array_add_foreach (gpointer key
, gpointer value
, gpointer user_data
)
601 const gchar
* lang
= (const gchar
*) key
;
602 GPtrArray
* sources_array
= (GPtrArray
*) value
;
603 SourcesForeachData
* data
= (SourcesForeachData
*) user_data
;
605 if (symbol_db_engine_add_new_files (data
->sdbe
, data
->root_dir
,
606 sources_array
, lang
, TRUE
) == FALSE
)
608 DEBUG_PRINT ("__FUNCTION__ failed for lang %s, root_dir %s",
609 lang
, data
->root_dir
);
613 /* add a new project */
615 project_root_added (AnjutaPlugin
*plugin
, const gchar
*name
,
616 const GValue
*value
, gpointer user_data
)
618 AnjutaStatus
*status
;
619 IAnjutaProjectManager
*pm
;
620 SymbolDBPlugin
*sdb_plugin
;
621 const gchar
*root_uri
;
623 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
625 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
,
626 IAnjutaProjectManager
, NULL
);
628 g_free (sdb_plugin
->project_root_uri
);
629 sdb_plugin
->project_root_uri
= NULL
;
630 root_uri
= g_value_get_string (value
);
633 gchar
*root_dir
= gnome_vfs_get_local_path_from_uri (root_uri
);
634 DEBUG_PRINT ("Symbol-DB: added project %s", root_dir
);
637 gboolean needs_sources_scan
= FALSE
;
639 GHashTable
* lang_hash
=
640 g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, sources_array_free
);
642 status
= anjuta_shell_get_status (plugin
->shell
, NULL
);
643 anjuta_status_progress_add_ticks (status
, 1);
645 DEBUG_PRINT ("Symbol-DB: creating new project.");
647 /* is it a fresh-new project? is it an imported project with
648 * no 'new' symbol-db database but the 'old' one symbol-browser?
650 if (symbol_db_engine_db_exists (sdb_plugin
->sdbe
, root_dir
) == FALSE
)
652 needs_sources_scan
= TRUE
;
655 if (symbol_db_engine_open_db (sdb_plugin
->sdbe
, root_dir
) == FALSE
)
656 g_error ("error in opening db");
658 symbol_db_engine_add_new_project (sdb_plugin
->sdbe
,
659 NULL
, /* still no workspace */
662 /* open the project. we can do this only if the db was loaded */
663 if (symbol_db_engine_open_project (sdb_plugin
->sdbe
, root_dir
) == FALSE
)
664 g_warning ("error in opening project");
666 if (needs_sources_scan
== TRUE
)
668 GList
* prj_elements_list
;
670 DEBUG_PRINT ("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
671 DEBUG_PRINT ("Retrieving gbf sources of the project...");
673 prj_elements_list
= ianjuta_project_manager_get_elements (pm
,
674 IANJUTA_PROJECT_MANAGER_SOURCE
,
677 GPtrArray
* sources_array
;
679 for (i
=0; i
< g_list_length (prj_elements_list
); i
++)
681 gchar
*local_filename
;
682 const gchar
*file_mime
;
684 IAnjutaLanguageId lang_id
;
685 IAnjutaLanguage
* lang_manager
=
686 anjuta_shell_get_interface (plugin
->shell
, IAnjutaLanguage
, NULL
);
690 g_critical ("LanguageManager not found");
695 gnome_vfs_get_local_path_from_uri (g_list_nth_data (
696 prj_elements_list
, i
));
697 file_mime
= gnome_vfs_get_mime_type_for_name (local_filename
);
699 lang_id
= ianjuta_language_get_from_mime_type (lang_manager
, file_mime
, NULL
);
703 g_free (local_filename
);
707 lang
= ianjuta_language_get_name (lang_manager
, lang_id
, NULL
);
708 DEBUG_PRINT ("Language of %s is %s", local_filename
, file_mime
);
709 /* test its existence */
710 if (g_file_test (local_filename
, G_FILE_TEST_EXISTS
) == FALSE
)
712 g_free (local_filename
);
716 sources_array
= g_hash_table_lookup (lang_hash
, lang
);
719 sources_array
= g_ptr_array_new ();
720 g_hash_table_insert (lang_hash
, (gpointer
) lang
, sources_array
);
723 g_ptr_array_add (sources_array
, local_filename
);
726 DEBUG_PRINT ("calling symbol_db_engine_add_new_files with root_dir %s",
729 SourcesForeachData
* data
= g_new0 (SourcesForeachData
, 1);
730 data
->sdbe
= sdb_plugin
->sdbe
;
731 data
->root_dir
= root_dir
;
733 g_hash_table_foreach (lang_hash
, (GHFunc
) sources_array_add_foreach
,
737 g_hash_table_unref (lang_hash
);
740 anjuta_status_progress_tick (status
, NULL
, _("Created symbols..."));
742 symbol_db_view_open (SYMBOL_DB_VIEW (sdb_plugin
->dbv_view_tree
),
746 sdb_plugin
->project_root_dir
= root_dir
;
749 sdb_plugin
->project_root_uri
= g_strdup (root_uri
);
752 g_signal_connect (G_OBJECT (pm
), "element_added",
753 G_CALLBACK (on_project_element_added
), sdb_plugin
);
754 g_signal_connect (G_OBJECT (pm
), "element_removed",
755 G_CALLBACK (on_project_element_removed
), sdb_plugin
);
759 project_root_removed (AnjutaPlugin
*plugin
, const gchar
*name
,
762 IAnjutaProjectManager
*pm
;
763 SymbolDBPlugin
*sdb_plugin
;
765 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
767 /* Disconnect events from project manager */
769 /* FIXME: There should be a way to ensure that this project manager
770 * is indeed the one that has opened the project_uri
772 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
,
773 IAnjutaProjectManager
, NULL
);
774 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
775 on_project_element_added
,
777 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
778 on_project_element_removed
,
781 /* don't forget to close the project */
782 symbol_db_engine_close_project (sdb_plugin
->sdbe
,
783 sdb_plugin
->project_root_dir
);
785 g_free (sdb_plugin
->project_root_uri
);
786 g_free (sdb_plugin
->project_root_dir
);
787 sdb_plugin
->project_root_uri
= NULL
;
788 sdb_plugin
->project_root_dir
= NULL
;
792 on_session_load (AnjutaShell
*shell
, AnjutaSessionPhase phase
,
793 AnjutaSession
*session
, SymbolDBPlugin
*plugin
)
797 DEBUG_PRINT ("on_session_load ()");
799 if (phase
!= ANJUTA_SESSION_PHASE_NORMAL
)
802 files
= anjuta_session_get_string_list (session
, "File Loader", "Files");
804 for (i
=0; i
< g_list_length (files
); i
++)
806 gchar
* node
= g_list_nth_data (files
, i
);
807 DEBUG_PRINT ("file %s", node
);
812 g_list_foreach (files
, (GFunc
)g_free
, NULL
);
818 symbol_db_activate (AnjutaPlugin
*plugin
)
820 SymbolDBPlugin
*symbol_db
;
822 DEBUG_PRINT ("SymbolDBPlugin: Activating SymbolDBPlugin plugin ...");
824 register_stock_icons (plugin
);
826 symbol_db
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
827 symbol_db
->ui
= anjuta_shell_get_ui (plugin
->shell
, NULL
);
829 /* connect for session load event
830 g_signal_connect (plugin->shell, "load-session",
831 G_CALLBACK (on_session_load),
836 /* create SymbolDBEngine */
837 symbol_db
->sdbe
= symbol_db_engine_new ();
840 symbol_db
->dbv_notebook
= gtk_notebook_new();
843 symbol_db
->scrolled_locals
= gtk_scrolled_window_new (NULL
, NULL
);
844 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (symbol_db
->scrolled_locals
),
846 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (symbol_db
->scrolled_locals
),
847 GTK_POLICY_AUTOMATIC
,
848 GTK_POLICY_AUTOMATIC
);
850 symbol_db
->dbv_view_locals_tab_label
= gtk_label_new (_("Local" ));
851 symbol_db
->dbv_view_tree_locals
= symbol_db_view_locals_new ();
853 g_object_add_weak_pointer (G_OBJECT (symbol_db
->dbv_view_tree_locals
),
854 (gpointer
)&symbol_db
->dbv_view_tree_locals
);
855 g_signal_connect (G_OBJECT (symbol_db
->dbv_view_tree_locals
), "row_activated",
856 G_CALLBACK (on_local_treeview_row_activated
), plugin
);
858 gtk_container_add (GTK_CONTAINER(symbol_db
->scrolled_locals
),
859 symbol_db
->dbv_view_tree_locals
);
863 symbol_db
->scrolled_global
= gtk_scrolled_window_new (NULL
, NULL
);
864 gtk_scrolled_window_set_shadow_type (
865 GTK_SCROLLED_WINDOW (symbol_db
->scrolled_global
),
867 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (symbol_db
->scrolled_global
),
868 GTK_POLICY_AUTOMATIC
,
869 GTK_POLICY_AUTOMATIC
);
871 symbol_db
->dbv_view_tab_label
= gtk_label_new (_("Global" ));
872 symbol_db
->dbv_view_tree
= symbol_db_view_new ();
873 g_object_add_weak_pointer (G_OBJECT (symbol_db
->dbv_view_tree
),
874 (gpointer
)&symbol_db
->dbv_view_tree
);
876 g_signal_connect (G_OBJECT (symbol_db
->dbv_view_tree
), "event-after",
877 G_CALLBACK (on_treeview_event
), plugin
);
879 g_signal_connect (G_OBJECT (symbol_db
->dbv_view_tree
), "row_activated",
880 G_CALLBACK (on_treeview_row_activated
), plugin
);
882 gtk_container_add (GTK_CONTAINER(symbol_db
->scrolled_global
),
883 symbol_db
->dbv_view_tree
);
886 symbol_db
->dbv_view_tree_search
=
887 (GtkWidget
*) symbol_db_view_search_new (symbol_db
->sdbe
);
888 symbol_db
->dbv_view_search_tab_label
= gtk_label_new (_("Search" ));
890 g_signal_connect (G_OBJECT (symbol_db
->dbv_view_tree_search
), "symbol_selected",
891 G_CALLBACK (on_treesearch_symbol_selected_event
),
894 g_object_add_weak_pointer (G_OBJECT (symbol_db
->dbv_view_tree_search
),
895 (gpointer
)&symbol_db
->dbv_view_tree_search
);
897 /* add the scrolled windows to the notebook */
898 gtk_notebook_append_page (GTK_NOTEBOOK (symbol_db
->dbv_notebook
),
899 symbol_db
->scrolled_locals
,
900 symbol_db
->dbv_view_locals_tab_label
);
902 gtk_notebook_append_page (GTK_NOTEBOOK (symbol_db
->dbv_notebook
),
903 symbol_db
->scrolled_global
,
904 symbol_db
->dbv_view_tab_label
);
906 gtk_notebook_append_page (GTK_NOTEBOOK (symbol_db
->dbv_notebook
),
907 symbol_db
->dbv_view_tree_search
,
908 symbol_db
->dbv_view_search_tab_label
);
910 gtk_widget_show_all (symbol_db
->dbv_notebook
);
912 /* setting focus to the tree_view*/
913 gtk_notebook_set_current_page (GTK_NOTEBOOK (symbol_db
->dbv_notebook
), 0);
915 symbol_db
->editor_watch_id
=
916 anjuta_plugin_add_watch (plugin
, "document_manager_current_editor",
917 value_added_current_editor
,
918 value_removed_current_editor
, NULL
);
921 symbol_db
->merge_id
=
922 anjuta_ui_merge (symbol_db
->ui
, UI_FILE
);
925 anjuta_shell_add_widget (plugin
->shell
, symbol_db
->dbv_notebook
,
926 "SymbolDBView", _("Symbols"),
927 "symbol-db-plugin-icon",
928 ANJUTA_SHELL_PLACEMENT_LEFT
, NULL
);
930 /* set up project directory watch */
931 symbol_db
->root_watch_id
= anjuta_plugin_add_watch (plugin
,
934 project_root_removed
, NULL
);
941 symbol_db_deactivate (AnjutaPlugin
*plugin
)
943 SymbolDBPlugin
*sdb_plugin
;
945 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
947 DEBUG_PRINT ("SymbolDBPlugin: Dectivating SymbolDBPlugin plugin ...");
949 DEBUG_PRINT ("SymbolDBPlugin: destroying engine ...");
950 g_object_unref (sdb_plugin
->sdbe
);
951 sdb_plugin
->sdbe
= NULL
;
953 /* disconnect some signals */
954 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->dbv_view_tree_locals
),
955 on_local_treeview_row_activated
,
958 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->dbv_view_tree_search
),
959 on_treesearch_symbol_selected_event
,
963 DEBUG_PRINT ("SymbolDBPlugin: destroying locals view ...");
964 g_object_unref (sdb_plugin->dbv_view_tree_locals);
966 DEBUG_PRINT ("SymbolDBPlugin: destroying globals view ...");
967 g_object_unref (sdb_plugin->dbv_view_tree);
969 DEBUG_PRINT ("SymbolDBPlugin: destroying search ...");
970 g_object_unref (sdb_plugin->dbv_view_tree_search);
973 /* Ensure all editor cached info are released */
974 if (sdb_plugin
->editor_connected
)
976 g_hash_table_foreach (sdb_plugin
->editor_connected
,
977 on_editor_foreach_disconnect
, plugin
);
978 g_hash_table_foreach (sdb_plugin
->editor_connected
,
979 on_editor_foreach_clear
, plugin
);
980 g_hash_table_destroy (sdb_plugin
->editor_connected
);
981 sdb_plugin
->editor_connected
= NULL
;
985 anjuta_plugin_remove_watch (plugin
, sdb_plugin
->root_watch_id
, FALSE
);
986 anjuta_plugin_remove_watch (plugin
, sdb_plugin
->editor_watch_id
, TRUE
);
988 /* Remove widgets: Widgets will be destroyed when dbv_notebook is removed */
989 anjuta_shell_remove_widget (plugin
->shell
, sdb_plugin
->dbv_notebook
, NULL
);
993 anjuta_ui_unmerge (sdb_plugin
->ui
, sdb_plugin
->merge_id
);
995 /* Remove action group */
996 anjuta_ui_remove_action_group (sv_plugin
->ui
, sv_plugin
->action_group
);
997 anjuta_ui_remove_action_group (sv_plugin
->ui
, sv_plugin
->popup_action_group
);
998 anjuta_ui_remove_action_group (sdb_plugin
->ui
, sdb_plugin
->action_group_nav
);
999 ui
= anjuta_shell_get_ui (plugin
->shell
, NULL
);
1000 /* anjuta_ui_remove_action_group (ui, ((SymbolDBPlugin*)plugin)->action_group); */
1001 anjuta_ui_unmerge (ui
, ((SymbolDBPlugin
*)plugin
)->uiid
);
1004 sdb_plugin
->root_watch_id
= 0;
1005 sdb_plugin
->editor_watch_id
= 0;
1006 sdb_plugin
->dbv_notebook
= NULL
;
1007 sdb_plugin
->scrolled_global
= NULL
;
1008 sdb_plugin
->scrolled_locals
= NULL
;
1009 sdb_plugin
->dbv_view_tree
= NULL
;
1010 sdb_plugin
->dbv_view_tab_label
= NULL
;
1011 sdb_plugin
->dbv_view_tree_locals
= NULL
;
1012 sdb_plugin
->dbv_view_locals_tab_label
= NULL
;
1013 sdb_plugin
->dbv_view_tree_search
= NULL
;
1014 sdb_plugin
->dbv_view_search_tab_label
= NULL
;
1019 symbol_db_finalize (GObject
*obj
)
1021 /* Finalization codes here */
1022 GNOME_CALL_PARENT (G_OBJECT_CLASS
, finalize
, (obj
));
1026 symbol_db_dispose (GObject
*obj
)
1028 /* Disposition codes */
1029 GNOME_CALL_PARENT (G_OBJECT_CLASS
, dispose
, (obj
));
1033 symbol_db_instance_init (GObject
*obj
)
1035 SymbolDBPlugin
*plugin
= (SymbolDBPlugin
*)obj
;
1038 plugin
->widget
= NULL
;
1042 symbol_db_class_init (GObjectClass
*klass
)
1044 AnjutaPluginClass
*plugin_class
= ANJUTA_PLUGIN_CLASS (klass
);
1046 parent_class
= g_type_class_peek_parent (klass
);
1048 plugin_class
->activate
= symbol_db_activate
;
1049 plugin_class
->deactivate
= symbol_db_deactivate
;
1050 klass
->finalize
= symbol_db_finalize
;
1051 klass
->dispose
= symbol_db_dispose
;
1054 static IAnjutaIterable
*
1055 isymbol_manager_search (IAnjutaSymbolManager
*sm
,
1056 IAnjutaSymbolType match_types
,
1057 const gchar
*match_name
,
1058 gboolean partial_name_match
,
1059 gboolean global_search
,
1062 SymbolDBEngineIterator
*iterator
= NULL
;
1063 SymbolDBPlugin
*sdb_plugin
;
1064 SymbolDBEngine
*dbe
;
1067 DEBUG_PRINT ("called isymbol_manager_search()! %s", match_name
);
1069 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (sm
);
1070 dbe
= SYMBOL_DB_ENGINE (sdb_plugin
->sdbe
);
1073 if (match_name
&& strlen (match_name
) > 0)
1080 symbol_db_engine_find_symbol_by_name_pattern (dbe
,
1081 name
, SYMINFO_SIMPLE
|
1083 SYMINFO_IMPLEMENTATION
|
1089 SYMINFO_FILE_IGNORE
|
1090 SYMINFO_FILE_INCLUDE
|
1091 SYMINFO_PROJECT_NAME
|
1092 SYMINFO_WORKSPACE_NAME
);
1094 return IANJUTA_ITERABLE (iterator
);
1097 static IAnjutaIterable
*
1098 isymbol_manager_get_members (IAnjutaSymbolManager
*sm
,
1099 const gchar
*symbol_name
,
1100 gboolean global_search
,
1104 const GPtrArray
*tags_array
;
1105 AnjutaSymbolIter
*iter
= NULL
;
1107 tags_array
= tm_workspace_find_scope_members (NULL
, symbol_name
,
1108 global_search
, TRUE
);
1113 iter
= anjuta_symbol_iter_new (tags_array
);
1114 return IANJUTA_ITERABLE (iter
);
1120 static IAnjutaIterable
*
1121 isymbol_manager_get_parents (IAnjutaSymbolManager
*sm
,
1122 const gchar
*symbol_name
,
1126 const GPtrArray
*tags_array
;
1127 AnjutaSymbolIter
*iter
= NULL
;
1129 tags_array
= tm_workspace_get_parents (symbol_name
);
1132 iter
= anjuta_symbol_iter_new (tags_array
);
1133 return IANJUTA_ITERABLE (iter
);
1139 static IAnjutaIterable
*
1140 isymbol_manager_get_completions_at_position (IAnjutaSymbolManager
*sm
,
1141 const gchar
*file_uri
,
1142 const gchar
*text_buffer
,
1148 SymbolBrowserPlugin
*sv_plugin
;
1149 const TMTag
*func_scope_tag
;
1150 TMSourceFile
*tm_file
;
1152 AnjutaSymbolView
*symbol_view
;
1154 gulong scope_position
;
1155 gchar
*needed_text
= NULL
;
1157 GPtrArray
* completable_tags_array
;
1158 AnjutaSymbolIter
*iter
= NULL
;
1160 sv_plugin
= ANJUTA_PLUGIN_SYMBOL_BROWSER (sm
);
1161 ed
= IANJUTA_EDITOR (sv_plugin
->current_editor
);
1162 symbol_view
= ANJUTA_SYMBOL_VIEW (sv_plugin
->sv_tree
);
1164 line
= ianjuta_editor_get_line_from_position (ed
, text_pos
, NULL
);
1166 /* get the function scope */
1167 tm_file
= anjuta_symbol_view_get_tm_file (symbol_view
, file_uri
);
1169 /* check whether the current file_uri is listed in the tm_workspace or not... */
1170 if (tm_file
== NULL
)
1174 // FIXME: remove DEBUG_PRINT
1176 DEBUG_PRINT ("tags in file &s\n");
1177 if (tm_file->work_object.tags_array != NULL) {
1179 for (i=0; i < tm_file->work_object.tags_array->len; i++) {
1182 cur_tag = (TMTag*)g_ptr_array_index (tm_file->work_object.tags_array, i);
1183 tm_tag_print (cur_tag, stdout);
1188 func_scope_tag = tm_get_current_function (tm_file->work_object.tags_array, line);
1190 if (func_scope_tag == NULL) {
1191 DEBUG_PRINT ("func_scope_tag is NULL, seems like it's a completion on a global scope");
1195 DEBUG_PRINT ("current expression scope: %s", func_scope_tag->name);
1198 scope_position = ianjuta_editor_get_line_begin_position (ed, func_scope_tag->atts.entry.line, NULL);
1199 needed_text = ianjuta_editor_get_text (ed, scope_position,
1200 text_pos - scope_position, NULL);
1202 if (needed_text == NULL)
1203 DEBUG_PRINT ("needed_text is null");
1204 DEBUG_PRINT ("text needed is %s", needed_text );
1207 /* we'll pass only the text of the current scope: i.e. only the current function
1208 * in which we request the completion. */
1209 TMTag
* found_type
= anjuta_symbol_view_get_type_of_expression (symbol_view
,
1210 needed_text
, text_pos
- scope_position
, func_scope_tag
, &access_method
);
1213 if (found_type
== NULL
) {
1214 DEBUG_PRINT ("type not found.");
1218 /* get the completable memebers. If the access is COMPLETION_ACCESS_STATIC we don't
1219 * want to know the parents members of the class.
1221 if (access_method
== COMPLETION_ACCESS_STATIC
)
1222 completable_tags_array
= anjuta_symbol_view_get_completable_members (found_type
, FALSE
);
1224 completable_tags_array
= anjuta_symbol_view_get_completable_members (found_type
, TRUE
);
1226 if (completable_tags_array
)
1228 iter
= anjuta_symbol_iter_new (completable_tags_array
);
1229 return IANJUTA_ITERABLE (iter
);
1237 isymbol_manager_iface_init (IAnjutaSymbolManagerIface
*iface
)
1239 iface
->search
= isymbol_manager_search
;
1240 iface
->get_members
= isymbol_manager_get_members
;
1241 iface
->get_parents
= isymbol_manager_get_parents
;
1242 iface
->get_completions_at_position
= isymbol_manager_get_completions_at_position
;
1245 ANJUTA_PLUGIN_BEGIN (SymbolDBPlugin
, symbol_db
);
1246 ANJUTA_PLUGIN_ADD_INTERFACE (isymbol_manager
, IANJUTA_TYPE_SYMBOL_MANAGER
);
1249 ANJUTA_SIMPLE_PLUGIN (SymbolDBPlugin
, symbol_db
);