Fix a Gtk warning when checking path input in the log viewer.
[anjuta-git-plugin.git] / plugins / symbol-db / plugin.c
blob8693d8cb4af0421080acc97cbf12e00148352081
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * plugin.c
4 * Copyright (C) Massimo Cora' 2007-2008 <maxcvs@email.it>
5 *
6 * plugin.c is free software.
7 *
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)
11 * any later version.
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.
25 #include <config.h>
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/anjuta-utils.h>
31 #include <libanjuta/interfaces/ianjuta-document-manager.h>
32 #include <libanjuta/interfaces/ianjuta-symbol-manager.h>
33 #include <libanjuta/interfaces/ianjuta-project-manager.h>
34 #include <libanjuta/interfaces/ianjuta-file-manager.h>
35 #include <libanjuta/interfaces/ianjuta-file.h>
36 #include <libanjuta/interfaces/ianjuta-file-loader.h>
37 #include <libanjuta/interfaces/ianjuta-editor.h>
38 #include <libanjuta/interfaces/ianjuta-markable.h>
39 #include <libanjuta/interfaces/ianjuta-language.h>
40 #include <libanjuta/interfaces/ianjuta-iterable.h>
41 #include <libanjuta/interfaces/ianjuta-preferences.h>
43 #include "plugin.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"
49 #include "symbol-db-prefs.h"
51 #define ICON_FILE "anjuta-symbol-db-plugin-48.png"
53 #define TIMEOUT_INTERVAL_SYMBOLS_UPDATE 10000
54 #define TIMEOUT_SECONDS_AFTER_LAST_TIP 5
56 #define CHOOSER_WIDGET "preferences_folder:text:/:0:symboldb.root"
57 #define PROJECT_GLOBALS "/"
58 #define CTAGS_PREFS_KEY "symboldb.ctags"
59 #define SESSION_SECTION "SymbolDB"
60 #define SESSION_KEY "SystemPackages"
62 static gpointer parent_class;
63 static gboolean need_symbols_update = FALSE;
64 static gint timeout_id = 0;
65 static GTimer *timer = NULL;
67 static void
68 register_stock_icons (AnjutaPlugin *plugin)
70 static gboolean registered = FALSE;
72 if (registered)
73 return;
74 registered = TRUE;
76 /* Register stock icons */
77 BEGIN_REGISTER_ICON (plugin);
78 REGISTER_ICON (ICON_FILE, "symbol-db-plugin-icon");
79 END_REGISTER_ICON;
82 static gboolean
83 on_editor_buffer_symbols_update_timeout (gpointer user_data)
85 SymbolDBPlugin *sdb_plugin;
86 IAnjutaEditor *ed;
87 gchar *current_buffer = NULL;
88 gint buffer_size = 0;
89 gchar *uri = NULL;
90 gdouble seconds_elapsed;
92 g_return_val_if_fail (user_data != NULL, FALSE);
94 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (user_data);
96 if (sdb_plugin->current_editor == NULL)
97 return FALSE;
99 /* check the timer. If it's elapsed enought time since the last time the user
100 * typed in something, than proceed with updating, elsewhere don't do nothing
102 if (timer == NULL)
103 return TRUE;
105 seconds_elapsed = g_timer_elapsed (timer, NULL);
107 /* DEBUG_PRINT ("seconds_elapsed %f", seconds_elapsed ); */
108 if (seconds_elapsed < TIMEOUT_SECONDS_AFTER_LAST_TIP)
109 return TRUE;
112 /* we won't proceed with the updating of the symbols if we didn't type in
113 anything */
114 if (!need_symbols_update)
115 return TRUE;
117 DEBUG_PRINT ("on_editor_buffer_symbols_update_timeout()");
119 if (sdb_plugin->current_editor)
121 GFile* file;
122 ed = IANJUTA_EDITOR (sdb_plugin->current_editor);
124 buffer_size = ianjuta_editor_get_length (ed, NULL);
125 current_buffer = ianjuta_editor_get_text_all (ed, NULL);
127 file = ianjuta_file_get_file (IANJUTA_FILE (ed), NULL);
128 uri = g_file_get_uri (file);
129 g_object_unref (file);
131 else
132 return FALSE;
134 if (uri)
136 DEBUG_PRINT ("uri for buffer updating: %s", uri);
138 GPtrArray *real_files_list;
139 GPtrArray *text_buffers;
140 GPtrArray *buffer_sizes;
142 gchar * local_path = gnome_vfs_get_local_path_from_uri (uri);
144 real_files_list = g_ptr_array_new ();
145 g_ptr_array_add (real_files_list, local_path);
147 text_buffers = g_ptr_array_new ();
148 g_ptr_array_add (text_buffers, current_buffer);
150 buffer_sizes = g_ptr_array_new ();
151 g_ptr_array_add (buffer_sizes, (gpointer)buffer_size);
153 symbol_db_engine_update_buffer_symbols (sdb_plugin->sdbe_project,
154 sdb_plugin->project_opened,
155 real_files_list,
156 text_buffers,
157 buffer_sizes);
159 g_free (uri);
162 g_free (current_buffer);
164 need_symbols_update = FALSE;
166 return TRUE;
169 static void
170 on_editor_destroy (SymbolDBPlugin *sdb_plugin, IAnjutaEditor *editor)
172 const gchar *uri;
173 DEBUG_PRINT ("on_editor_destroy ()");
174 if (!sdb_plugin->editor_connected || !sdb_plugin->dbv_view_tree)
175 return;
177 uri = g_hash_table_lookup (sdb_plugin->editor_connected, G_OBJECT (editor));
178 g_hash_table_remove (sdb_plugin->editor_connected, G_OBJECT (editor));
181 static void
182 on_editor_update_ui (IAnjutaEditor *editor, SymbolDBPlugin *sdb_plugin)
184 if (timer == NULL)
186 /* creates and start a new timer. */
187 timer = g_timer_new ();
189 else
191 g_timer_reset (timer);
195 static void
196 on_char_added (IAnjutaEditor *editor, IAnjutaIterable *position, gchar ch,
197 SymbolDBPlugin *sdb_plugin)
199 if (timer == NULL)
201 /* creates and start a new timer. */
202 timer = g_timer_new ();
204 else
206 g_timer_reset (timer);
209 /* Update when the user enters a newline */
210 if (ch == '\n')
211 need_symbols_update = TRUE;
215 static void
216 on_editor_saved (IAnjutaEditor *editor, GFile* file,
217 SymbolDBPlugin *sdb_plugin)
219 const gchar *old_uri;
220 gboolean tags_update;
221 /* FIXME: Do this only if automatic tags update is enabled */
222 /* tags_update =
223 anjuta_preferences_get_int (te->preferences, AUTOMATIC_TAGS_UPDATE);
225 tags_update = TRUE;
226 if (tags_update)
228 gchar *local_filename = g_file_get_path (file);
229 gchar *saved_uri = g_file_get_uri (file);
230 GPtrArray *files_array;
232 /* Verify that it's local file */
233 g_return_if_fail (local_filename != NULL);
235 files_array = g_ptr_array_new();
236 DEBUG_PRINT ("local_filename saved is %s", local_filename);
237 g_ptr_array_add (files_array, local_filename);
238 /* no need to free local_filename now */
240 if (!sdb_plugin->editor_connected)
241 return;
243 old_uri = g_hash_table_lookup (sdb_plugin->editor_connected, editor);
245 if (old_uri && strlen (old_uri) <= 0)
246 old_uri = NULL;
248 /* files_array will be freed once updating has taken place */
249 symbol_db_engine_update_files_symbols (sdb_plugin->sdbe_project,
250 sdb_plugin->project_root_dir, files_array, TRUE);
251 g_hash_table_insert (sdb_plugin->editor_connected, editor,
252 g_strdup (saved_uri));
254 on_editor_update_ui (editor, sdb_plugin);
255 g_free (saved_uri);
259 static void
260 value_added_current_editor (AnjutaPlugin *plugin, const char *name,
261 const GValue *value, gpointer data)
263 gchar *uri;
264 GFile* file;
265 gchar *local_path;
266 GObject *editor;
267 SymbolDBPlugin *sdb_plugin;
269 editor = g_value_get_object (value);
270 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
272 if (sdb_plugin->session_loading)
274 DEBUG_PRINT ("session_loading");
275 return;
277 else
278 DEBUG_PRINT ("Updating symbols");
280 if (!sdb_plugin->editor_connected)
282 sdb_plugin->editor_connected = g_hash_table_new_full (g_direct_hash,
283 g_direct_equal,
284 NULL, g_free);
286 sdb_plugin->current_editor = editor;
288 if (!IANJUTA_IS_EDITOR (editor))
289 return;
291 file = ianjuta_file_get_file (IANJUTA_FILE (editor), NULL);
293 if (file == NULL)
294 return;
296 local_path = g_file_get_path (file);
297 uri = g_file_get_uri (file);
298 DEBUG_PRINT ("value_added_current_editor () gonna refresh local syms: local_path %s "
299 "uri %s", local_path, uri);
300 if (local_path == NULL)
302 g_critical ("FIXME local_path == NULL");
303 return;
306 if (strstr (local_path, "//") != NULL)
308 g_critical ("WARNING FIXME: bad file uri passed to symbol-db from editor. There's "
309 "a trailing slash left. Please fix this at editor side");
312 symbol_db_view_locals_update_list (
313 SYMBOL_DB_VIEW_LOCALS (sdb_plugin->dbv_view_tree_locals),
314 sdb_plugin->sdbe_project, local_path);
316 if (g_hash_table_lookup (sdb_plugin->editor_connected, editor) == NULL)
318 g_object_weak_ref (G_OBJECT (editor),
319 (GWeakNotify) (on_editor_destroy),
320 sdb_plugin);
321 if (uri)
323 g_hash_table_insert (sdb_plugin->editor_connected, editor,
324 g_strdup (uri));
326 else
328 g_hash_table_insert (sdb_plugin->editor_connected, editor,
329 g_strdup (""));
332 g_signal_connect (G_OBJECT (editor), "saved",
333 G_CALLBACK (on_editor_saved),
334 sdb_plugin);
335 g_signal_connect (G_OBJECT (editor), "char-added",
336 G_CALLBACK (on_char_added),
337 sdb_plugin);
338 g_signal_connect (G_OBJECT(editor), "update_ui",
339 G_CALLBACK (on_editor_update_ui),
340 sdb_plugin);
342 g_free (uri);
343 g_free (local_path);
345 /* add a default timeout to the updating of buffer symbols */
346 timeout_id = g_timeout_add (TIMEOUT_INTERVAL_SYMBOLS_UPDATE,
347 on_editor_buffer_symbols_update_timeout,
348 plugin);
349 need_symbols_update = FALSE;
352 static void
353 on_session_save (AnjutaShell *shell, AnjutaSessionPhase phase,
354 AnjutaSession *session,
355 SymbolDBPlugin *sdb_plugin)
357 if (phase != ANJUTA_SESSION_PHASE_NORMAL)
358 return;
360 DEBUG_PRINT ("SymbolDB: session_save");
362 anjuta_session_set_string_list (session,
363 SESSION_SECTION,
364 SESSION_KEY,
365 sdb_plugin->session_packages);
368 static void
369 on_session_load (AnjutaShell *shell, AnjutaSessionPhase phase,
370 AnjutaSession *session,
371 SymbolDBPlugin *sdb_plugin)
373 IAnjutaProjectManager *pm;
374 pm = anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin)->shell,
375 IAnjutaProjectManager, NULL);
377 if (phase == ANJUTA_SESSION_PHASE_START)
379 DEBUG_PRINT ("SymbolDB: session_loading started. Getting info from %s",
380 anjuta_session_get_session_directory (session));
381 sdb_plugin->session_loading = TRUE;
383 GList *session_packages = anjuta_session_get_string_list (session,
384 SESSION_SECTION,
385 SESSION_KEY);
387 GList *to_scan_packages = NULL;
389 if (session_packages == NULL)
391 GList *project_default_packages =
392 ianjuta_project_manager_get_packages (pm, NULL);
394 /* take the project's defaults */
395 to_scan_packages = project_default_packages;
397 else
399 to_scan_packages = session_packages;
402 /* system's packages management */
403 GList *item = to_scan_packages;
404 while (item != NULL)
406 /* the function will take care of checking if the package is already
407 * scanned and present on db
409 DEBUG_PRINT ("ianjuta_project_manager_get_packages: package required: %s",
410 (gchar*)item->data);
411 symbol_db_system_scan_package (sdb_plugin->sdbs, item->data);
413 item = item->next;
416 sdb_plugin->session_packages = to_scan_packages;
418 /* no need to free the GList(s) */
420 else if (phase == ANJUTA_SESSION_PHASE_END)
422 IAnjutaDocumentManager* docman;
423 sdb_plugin->session_loading = FALSE;
424 DEBUG_PRINT ("SymbolDB: session_loading finished");
426 /* Show the symbols for the current editor */
427 docman = anjuta_shell_get_interface (shell, IAnjutaDocumentManager, NULL);
428 if (docman)
430 IAnjutaDocument* cur_doc =
431 ianjuta_document_manager_get_current_document (docman, NULL);
432 if (cur_doc)
434 GValue value = {0, };
435 g_value_init (&value, G_TYPE_OBJECT);
436 g_value_set_object (&value, cur_doc);
437 value_added_current_editor (ANJUTA_PLUGIN (sdb_plugin),
438 "document_manager_current_editor",
439 &value, NULL);
440 g_value_unset(&value);
446 static void
447 on_editor_foreach_disconnect (gpointer key, gpointer value, gpointer user_data)
449 g_signal_handlers_disconnect_by_func (G_OBJECT(key),
450 G_CALLBACK (on_editor_saved),
451 user_data);
452 g_signal_handlers_disconnect_by_func (G_OBJECT(key),
453 G_CALLBACK (on_editor_update_ui),
454 user_data);
455 g_signal_handlers_disconnect_by_func (G_OBJECT(key),
456 G_CALLBACK (on_char_added),
457 user_data);
458 g_object_weak_unref (G_OBJECT(key),
459 (GWeakNotify) (on_editor_destroy),
460 user_data);
463 static void
464 goto_file_line (AnjutaPlugin *plugin, const gchar *filename, gint lineno)
466 IAnjutaDocumentManager *docman;
467 GFile* file;
469 g_return_if_fail (filename != NULL);
471 /* Go to file and line number */
472 docman = anjuta_shell_get_interface (plugin->shell, IAnjutaDocumentManager,
473 NULL);
474 file = g_file_new_for_path (filename);
475 ianjuta_document_manager_goto_file_line (docman, file, lineno, NULL);
477 g_object_unref (file);
481 static void
482 goto_local_tree_iter (SymbolDBPlugin *sdb_plugin, GtkTreeIter *iter)
484 gint line;
486 line = symbol_db_view_locals_get_line (SYMBOL_DB_VIEW_LOCALS (
487 sdb_plugin->dbv_view_tree_locals),
488 sdb_plugin->sdbe_project,
489 iter);
491 DEBUG_PRINT ("got line %d", line);
493 if (line > 0 && sdb_plugin->current_editor)
495 /* Goto line number */
496 ianjuta_editor_goto_line (IANJUTA_EDITOR (sdb_plugin->current_editor),
497 line, NULL);
498 if (IANJUTA_IS_MARKABLE (sdb_plugin->current_editor))
500 ianjuta_markable_delete_all_markers (IANJUTA_MARKABLE (sdb_plugin->current_editor),
501 IANJUTA_MARKABLE_LINEMARKER,
502 NULL);
504 ianjuta_markable_mark (IANJUTA_MARKABLE (sdb_plugin->current_editor),
505 line, IANJUTA_MARKABLE_LINEMARKER, NULL);
510 static void
511 goto_global_tree_iter (SymbolDBPlugin *sdb_plugin, GtkTreeIter *iter)
513 gint line;
514 gchar *file;
516 if (symbol_db_view_get_file_and_line (
517 SYMBOL_DB_VIEW (sdb_plugin->dbv_view_tree), sdb_plugin->sdbe_project,
518 iter, &line, &file) == FALSE)
520 g_warning ("goto_global_tree_iter (): error while trying to get file/line");
521 return;
525 DEBUG_PRINT ("got line %d and file %s", line, file);
527 if (line > 0 && sdb_plugin->current_editor)
529 goto_file_line (ANJUTA_PLUGIN (sdb_plugin), file, line);
530 if (IANJUTA_IS_MARKABLE (sdb_plugin->current_editor))
532 ianjuta_markable_delete_all_markers (IANJUTA_MARKABLE (sdb_plugin->current_editor),
533 IANJUTA_MARKABLE_LINEMARKER,
534 NULL);
536 ianjuta_markable_mark (IANJUTA_MARKABLE (sdb_plugin->current_editor),
537 line, IANJUTA_MARKABLE_LINEMARKER, NULL);
541 g_free (file);
545 * will manage the click of mouse and other events on search->hitlist treeview
547 static void
548 on_treesearch_symbol_selected_event (SymbolDBViewSearch *search,
549 gint line,
550 gchar* file,
551 SymbolDBPlugin *sdb_plugin)
554 DEBUG_PRINT ("on_treesearch_symbol_selected_event (), %s %d", file, line);
555 goto_file_line (ANJUTA_PLUGIN (sdb_plugin), file, line);
559 static void
560 on_local_treeview_row_activated (GtkTreeView *view, GtkTreePath *arg1,
561 GtkTreeViewColumn *arg2,
562 SymbolDBPlugin *sdb_plugin)
564 GtkTreeModel *model;
565 GtkTreeSelection *selection;
566 GtkTreeIter iter;
568 DEBUG_PRINT ("on_local_treeview_row_activated ()");
569 selection = gtk_tree_view_get_selection (view);
570 if (!gtk_tree_selection_get_selected (selection, &model, &iter))
572 return;
574 goto_local_tree_iter (sdb_plugin, &iter);
577 static void
578 on_global_treeview_row_activated (GtkTreeView *view, GtkTreePath *arg1,
579 GtkTreeViewColumn *arg2,
580 SymbolDBPlugin *sdb_plugin)
582 GtkTreeModel *model;
583 GtkTreeSelection *selection;
584 GtkTreeIter iter;
586 DEBUG_PRINT ("on_global_treeview_row_activated ()");
587 selection = gtk_tree_view_get_selection (view);
588 if (!gtk_tree_selection_get_selected (selection, &model, &iter))
590 return;
593 goto_global_tree_iter (sdb_plugin, &iter);
596 static void
597 on_global_treeview_row_expanded (GtkTreeView *tree_view,
598 GtkTreeIter *iter,
599 GtkTreePath *path,
600 SymbolDBPlugin *user_data)
602 DEBUG_PRINT ("on_global_treeview_row_expanded ()");
604 symbol_db_view_row_expanded (SYMBOL_DB_VIEW (user_data->dbv_view_tree),
605 user_data->sdbe_project, iter);
608 static void
609 on_global_treeview_row_collapsed (GtkTreeView *tree_view,
610 GtkTreeIter *iter,
611 GtkTreePath *path,
612 SymbolDBPlugin *user_data)
614 DEBUG_PRINT ("on_global_treeview_row_collapsed ()");
616 symbol_db_view_row_collapsed (SYMBOL_DB_VIEW (user_data->dbv_view_tree),
617 user_data->sdbe_project, iter);
621 static void
622 value_removed_current_editor (AnjutaPlugin *plugin,
623 const char *name, gpointer data)
625 SymbolDBPlugin *sdb_plugin;
627 if (!IANJUTA_IS_EDITOR (data))
628 return;
630 DEBUG_PRINT ("value_removed_current_editor ()");
631 /* let's remove the timeout for symbols refresh */
632 g_source_remove (timeout_id);
633 need_symbols_update = FALSE;
635 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
636 sdb_plugin->current_editor = NULL;
640 static void
641 on_project_element_added (IAnjutaProjectManager *pm, const gchar *uri,
642 SymbolDBPlugin *sdb_plugin)
644 gchar *filename;
645 IAnjutaLanguage* lang_manager;
647 g_return_if_fail (sdb_plugin->project_root_uri != NULL);
648 g_return_if_fail (sdb_plugin->project_root_dir != NULL);
650 lang_manager = anjuta_shell_get_interface (ANJUTA_PLUGIN(sdb_plugin)->shell,
651 IAnjutaLanguage, NULL);
653 g_return_if_fail (lang_manager != NULL);
655 DEBUG_PRINT ("on_project_element_added");
657 filename = gnome_vfs_get_local_path_from_uri (uri);
658 if (filename)
660 GPtrArray *files_array;
661 GPtrArray *languages_array;
662 const gchar* file_mime;
663 IAnjutaLanguageId lang_id;
664 const gchar* lang;
665 file_mime = gnome_vfs_get_mime_type_for_name (filename);
667 lang_id = ianjuta_language_get_from_mime_type (lang_manager, file_mime,
668 NULL);
670 /* No supported language... */
671 if (!lang_id)
673 g_free (filename);
674 return;
677 lang = ianjuta_language_get_name (lang_manager, lang_id, NULL);
678 files_array = g_ptr_array_new();
679 languages_array = g_ptr_array_new();
681 g_ptr_array_add (files_array, filename);
682 g_ptr_array_add (languages_array, g_strdup (lang));
684 symbol_db_engine_add_new_files (sdb_plugin->sdbe_project,
685 sdb_plugin->project_opened, files_array, languages_array, TRUE);
687 g_free (filename);
688 g_ptr_array_free (files_array, TRUE);
690 g_ptr_array_foreach (languages_array, (GFunc)g_free, NULL);
691 g_ptr_array_free (languages_array, TRUE);
695 static void
696 on_project_element_removed (IAnjutaProjectManager *pm, const gchar *uri,
697 SymbolDBPlugin *sdb_plugin)
699 gchar *filename;
701 if (!sdb_plugin->project_root_uri)
702 return;
704 filename = gnome_vfs_get_local_path_from_uri (uri);
705 if (filename)
707 DEBUG_PRINT ("on_project_element_removed");
708 DEBUG_PRINT ("project_root_dir %s", sdb_plugin->project_root_dir );
709 symbol_db_engine_remove_file (sdb_plugin->sdbe_project,
710 sdb_plugin->project_root_dir, filename);
712 g_free (filename);
716 static void
717 sources_array_free (gpointer data)
719 GPtrArray* sources = (GPtrArray*) data;
720 g_ptr_array_foreach (sources, (GFunc)g_free, NULL);
721 g_ptr_array_free (sources, TRUE);
725 static void
726 on_system_scan_package_start (SymbolDBEngine *dbe, guint num_files,
727 const gchar *package, gpointer user_data)
729 SymbolDBPlugin *sdb_plugin;
730 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (user_data);
732 sdb_plugin->files_count_system_done = 0;
733 sdb_plugin->files_count_system = num_files;
735 DEBUG_PRINT ("on_system_scan_package_start () [%s]", package);
737 /* show the global bar */
738 gtk_widget_show (sdb_plugin->progress_bar_system);
740 if (sdb_plugin->current_scanned_package != NULL)
741 g_free (sdb_plugin->current_scanned_package);
742 sdb_plugin->current_scanned_package = g_strdup (package);
745 static void
746 on_system_scan_package_end (SymbolDBEngine *dbe, const gchar *package,
747 gpointer user_data)
749 SymbolDBPlugin *sdb_plugin;
750 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (user_data);
752 DEBUG_PRINT ("on_system_scan_package_end () [%s]", package);
754 /* hide the progress bar */
755 gtk_widget_hide (sdb_plugin->progress_bar_system);
757 sdb_plugin->files_count_system_done = 0;
758 sdb_plugin->files_count_system = 0;
761 static void
762 on_system_single_file_scan_end (SymbolDBEngine *dbe, gpointer data)
764 AnjutaPlugin *plugin;
765 SymbolDBPlugin *sdb_plugin;
766 gchar *message;
767 gdouble fraction = 0;
769 plugin = ANJUTA_PLUGIN (data);
770 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
772 DEBUG_PRINT ("on_system_single_file_scan_end ()");
774 sdb_plugin->files_count_system_done++;
775 if (sdb_plugin->files_count_system_done >= sdb_plugin->files_count_system)
776 message = g_strdup_printf (_("%s: Generating inheritances..."),
777 sdb_plugin->current_scanned_package);
778 else
779 message = g_strdup_printf (_("%s: %d files scanned out of %d"),
780 sdb_plugin->current_scanned_package,
781 sdb_plugin->files_count_system_done,
782 sdb_plugin->files_count_system);
784 if (sdb_plugin->files_count_system > 0)
786 fraction = (gdouble) sdb_plugin->files_count_system_done /
787 (gdouble) sdb_plugin->files_count_system;
789 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_system),
790 fraction);
791 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_system), message);
792 gtk_widget_show (sdb_plugin->progress_bar_system);
793 g_free (message);
796 static void
797 on_project_single_file_scan_end (SymbolDBEngine *dbe, gpointer data)
799 AnjutaPlugin *plugin;
800 SymbolDBPlugin *sdb_plugin;
801 gchar *message;
802 gdouble fraction = 0;
804 plugin = ANJUTA_PLUGIN (data);
805 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
807 sdb_plugin->files_count_project_done++;
808 if (sdb_plugin->files_count_project_done >= sdb_plugin->files_count_project)
809 message = g_strdup_printf (_("Generating inheritances..."));
810 else
811 message = g_strdup_printf (_("%d files scanned out of %d"),
812 sdb_plugin->files_count_project_done, sdb_plugin->files_count_project);
814 if (sdb_plugin->files_count_project > 0)
816 fraction = (gdouble) sdb_plugin->files_count_project_done /
817 (gdouble) sdb_plugin->files_count_project;
819 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_project),
820 fraction);
821 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_project), message);
822 gtk_widget_show (sdb_plugin->progress_bar_project);
823 g_free (message);
826 static void
827 on_importing_project_end (SymbolDBEngine *dbe, gpointer data)
829 SymbolDBPlugin *sdb_plugin;
831 g_return_if_fail (data != NULL);
833 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (data);
835 DEBUG_PRINT ("on_importing_project_end ()");
837 /* hide the progress bar */
838 gtk_widget_hide (sdb_plugin->progress_bar_project);
840 /* re-enable signals receiving on local-view */
841 symbol_db_view_locals_recv_signals_from_engine (
842 SYMBOL_DB_VIEW_LOCALS (sdb_plugin->dbv_view_tree_locals),
843 sdb_plugin->sdbe_project, TRUE);
845 /* and on global view */
846 symbol_db_view_recv_signals_from_engine (SYMBOL_DB_VIEW (sdb_plugin->dbv_view_tree),
847 sdb_plugin->sdbe_project, TRUE);
849 /* re-active global symbols */
850 symbol_db_view_open (SYMBOL_DB_VIEW (sdb_plugin->dbv_view_tree), sdb_plugin->sdbe_project);
852 /* disconnect this coz it's not important after the process of importing */
853 g_signal_handlers_disconnect_by_func (dbe, on_project_single_file_scan_end, data);
855 /* disconnect it as we don't need it anymore. */
856 g_signal_handlers_disconnect_by_func (dbe, on_importing_project_end, data);
858 sdb_plugin->files_count_project_done = 0;
859 sdb_plugin->files_count_project = 0;
862 static void
863 do_import_system_src_after_abort (AnjutaPlugin *plugin,
864 const GPtrArray *sources_array)
866 SymbolDBPlugin *sdb_plugin;
867 GPtrArray* languages_array = NULL;
868 GPtrArray *to_scan_array = NULL;
869 IAnjutaLanguage* lang_manager;
870 gint i;
872 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
874 lang_manager = anjuta_shell_get_interface (plugin->shell, IAnjutaLanguage,
875 NULL);
877 DEBUG_PRINT ("do_import_system_src_after_abort %d", sources_array->len);
878 /* create array of languages */
879 languages_array = g_ptr_array_new ();
880 to_scan_array = g_ptr_array_new ();
882 if (!lang_manager)
884 g_critical ("LanguageManager not found");
885 return;
888 for (i=0; i < sources_array->len; i++)
890 const gchar *file_mime;
891 const gchar *lang;
892 const gchar *local_filename;
893 IAnjutaLanguageId lang_id;
895 local_filename = g_ptr_array_index (sources_array, i);
897 if (local_filename == NULL)
898 continue;
899 file_mime = gnome_vfs_get_mime_type_for_name (local_filename);
901 lang_id = ianjuta_language_get_from_mime_type (lang_manager,
902 file_mime, NULL);
904 if (!lang_id)
905 continue;
907 lang = ianjuta_language_get_name (lang_manager, lang_id, NULL);
909 /* test its existence */
910 if (g_file_test (local_filename, G_FILE_TEST_EXISTS) == FALSE)
911 continue;
913 g_ptr_array_add (languages_array, g_strdup (lang));
914 g_ptr_array_add (to_scan_array, g_strdup (local_filename));
917 symbol_db_parse_aborted_package (sdb_plugin->sdbs,
918 to_scan_array,
919 languages_array);
921 /* no need to free the GPtrArray, Huston. They'll be auto-destroyed in that
922 * function
926 /* we assume that sources_array has already unique elements */
927 static void
928 do_import_project_src_after_abort (AnjutaPlugin *plugin,
929 const GPtrArray *sources_array)
931 SymbolDBPlugin *sdb_plugin;
932 GPtrArray* languages_array = NULL;
933 GPtrArray *to_scan_array = NULL;
934 IAnjutaLanguage* lang_manager;
935 gint i;
937 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
940 lang_manager = anjuta_shell_get_interface (plugin->shell, IAnjutaLanguage,
941 NULL);
943 /* create array of languages */
944 languages_array = g_ptr_array_new ();
945 to_scan_array = g_ptr_array_new ();
947 if (!lang_manager)
949 g_critical ("LanguageManager not found");
950 return;
953 for (i=0; i < sources_array->len; i++)
955 const gchar *file_mime;
956 const gchar *lang;
957 const gchar *local_filename;
958 IAnjutaLanguageId lang_id;
960 local_filename = g_ptr_array_index (sources_array, i);
962 if (local_filename == NULL)
963 continue;
964 file_mime = gnome_vfs_get_mime_type_for_name (local_filename);
966 lang_id = ianjuta_language_get_from_mime_type (lang_manager,
967 file_mime, NULL);
969 if (!lang_id)
971 continue;
974 lang = ianjuta_language_get_name (lang_manager, lang_id, NULL);
976 /* test its existence */
977 if (g_file_test (local_filename, G_FILE_TEST_EXISTS) == FALSE)
979 continue;
982 sdb_plugin->files_count_project++;
983 g_ptr_array_add (languages_array, g_strdup (lang));
984 g_ptr_array_add (to_scan_array, g_strdup (local_filename));
987 /* connect to receive signals on single file scan complete. We'll
988 * update a status bar notifying the user about the status
990 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_project), "single-file-scan-end",
991 G_CALLBACK (on_project_single_file_scan_end), plugin);
993 symbol_db_engine_add_new_files (sdb_plugin->sdbe_project, sdb_plugin->project_opened,
994 sources_array, languages_array, TRUE);
996 g_ptr_array_foreach (languages_array, (GFunc)g_free, NULL);
997 g_ptr_array_free (languages_array, TRUE);
999 g_ptr_array_foreach (to_scan_array, (GFunc)g_free, NULL);
1000 g_ptr_array_free (to_scan_array, TRUE);
1003 static void
1004 do_import_sources (AnjutaPlugin *plugin, IAnjutaProjectManager *pm,
1005 const gchar *root_dir)
1007 SymbolDBPlugin *sdb_plugin;
1008 GList* prj_elements_list;
1009 GPtrArray* sources_array = NULL;
1010 GPtrArray* languages_array = NULL;
1011 GHashTable *check_unique_file;
1012 IAnjutaLanguage* lang_manager;
1013 gint i;
1015 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
1017 /* if we're importing first shut off the signal receiving.
1018 * We'll re-enable that on scan-end
1020 symbol_db_view_locals_recv_signals_from_engine (
1021 SYMBOL_DB_VIEW_LOCALS (sdb_plugin->dbv_view_tree_locals),
1022 sdb_plugin->sdbe_project, FALSE);
1024 symbol_db_view_recv_signals_from_engine (
1025 SYMBOL_DB_VIEW (sdb_plugin->dbv_view_tree),
1026 sdb_plugin->sdbe_project, FALSE);
1028 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_project), "scan-end",
1029 G_CALLBACK (on_importing_project_end), plugin);
1031 lang_manager = anjuta_shell_get_interface (plugin->shell, IAnjutaLanguage,
1032 NULL);
1034 if (!lang_manager)
1036 g_critical ("LanguageManager not found");
1037 return;
1040 prj_elements_list = ianjuta_project_manager_get_elements (pm,
1041 IANJUTA_PROJECT_MANAGER_SOURCE,
1042 NULL);
1044 /* to speed the things up we must avoid the dups */
1045 check_unique_file = g_hash_table_new_full (g_str_hash,
1046 g_str_equal, g_free, g_free);
1048 DEBUG_PRINT ("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
1049 DEBUG_PRINT ("Retrieving %d gbf sources of the project...",
1050 g_list_length (prj_elements_list));
1052 for (i=0; i < g_list_length (prj_elements_list); i++)
1054 gchar *local_filename;
1055 const gchar *file_mime;
1056 const gchar *lang;
1057 IAnjutaLanguageId lang_id;
1059 local_filename =
1060 gnome_vfs_get_local_path_from_uri (g_list_nth_data (
1061 prj_elements_list, i));
1063 if (local_filename == NULL)
1064 continue;
1066 /* check if it's already present in the list. This avoids
1067 * duplicates.
1069 if (g_hash_table_lookup (check_unique_file,
1070 local_filename) == NULL)
1072 g_hash_table_insert (check_unique_file,
1073 g_strdup (local_filename),
1074 g_strdup (local_filename));
1076 else
1078 /* you're a dup! we don't want you */
1079 g_free (local_filename);
1080 continue;
1083 file_mime = gnome_vfs_get_mime_type_for_name (local_filename);
1085 lang_id = ianjuta_language_get_from_mime_type (lang_manager,
1086 file_mime, NULL);
1088 if (!lang_id)
1090 g_free (local_filename);
1091 continue;
1094 lang = ianjuta_language_get_name (lang_manager, lang_id, NULL);
1095 DEBUG_PRINT ("Language of %s is %s", local_filename, file_mime);
1096 /* test its existence */
1097 if (g_file_test (local_filename, G_FILE_TEST_EXISTS) == FALSE)
1099 g_free (local_filename);
1100 continue;
1103 if (!sources_array)
1104 sources_array = g_ptr_array_new ();
1106 if (!languages_array)
1107 languages_array = g_ptr_array_new ();
1109 sdb_plugin->files_count_project++;
1110 g_ptr_array_add (sources_array, local_filename);
1111 g_ptr_array_add (languages_array, g_strdup (lang));
1114 DEBUG_PRINT ("calling symbol_db_engine_add_new_files with root_dir %s",
1115 root_dir);
1117 /* connect to receive signals on single file scan complete. We'll
1118 * update a status bar notifying the user about the status
1120 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_project), "single-file-scan-end",
1121 G_CALLBACK (on_project_single_file_scan_end), plugin);
1123 symbol_db_engine_add_new_files (sdb_plugin->sdbe_project,
1124 sdb_plugin->project_opened,
1125 sources_array, languages_array, TRUE);
1127 g_hash_table_unref (check_unique_file);
1129 g_ptr_array_foreach (sources_array, (GFunc)g_free, NULL);
1130 g_ptr_array_free (sources_array, TRUE);
1132 g_ptr_array_foreach (languages_array, (GFunc)g_free, NULL);
1133 g_ptr_array_free (languages_array, TRUE);
1136 /* add a new project */
1137 static void
1138 on_project_root_added (AnjutaPlugin *plugin, const gchar *name,
1139 const GValue *value, gpointer user_data)
1141 IAnjutaProjectManager *pm;
1142 SymbolDBPlugin *sdb_plugin;
1143 const gchar *root_uri;
1145 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
1147 pm = anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin)->shell,
1148 IAnjutaProjectManager, NULL);
1150 g_free (sdb_plugin->project_root_uri);
1151 sdb_plugin->project_root_uri = NULL;
1152 root_uri = g_value_get_string (value);
1154 if (root_uri)
1156 gchar *root_dir = gnome_vfs_get_local_path_from_uri (root_uri);
1157 DEBUG_PRINT ("Symbol-DB: added project root_dir %s, name %s", root_dir,
1158 name);
1160 /* FIXME: where's the project name itself? */
1161 DEBUG_PRINT ("FIXME: where's the project name itself? ");
1162 sdb_plugin->project_opened = g_strdup (root_dir);
1164 if (root_dir)
1166 gboolean needs_sources_scan = FALSE;
1167 gboolean project_exist = FALSE;
1168 GHashTable* lang_hash;
1169 guint id;
1171 lang_hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
1172 sources_array_free);
1174 /* is it a fresh-new project? is it an imported project with
1175 * no 'new' symbol-db database but the 'old' one symbol-browser?
1177 if (symbol_db_engine_db_exists (sdb_plugin->sdbe_project,
1178 root_dir) == FALSE)
1180 DEBUG_PRINT ("Symbol-DB: project did not exist");
1181 needs_sources_scan = TRUE;
1182 project_exist = FALSE;
1184 else
1186 project_exist = TRUE;
1189 /* we'll use the same values for db_directory and project_directory */
1190 DEBUG_PRINT ("opening db %s and project_dir %s", root_dir, root_dir);
1191 if (symbol_db_engine_open_db (sdb_plugin->sdbe_project, root_dir,
1192 root_dir) == FALSE)
1193 g_error ("Symbol-DB: error in opening db");
1195 /* if project did not exist add a new project */
1196 if (project_exist == FALSE)
1198 DEBUG_PRINT ("Symbol-DB: creating new project.");
1199 symbol_db_engine_add_new_project (sdb_plugin->sdbe_project,
1200 NULL, /* still no workspace logic */
1201 sdb_plugin->project_opened);
1204 /* we need an import */
1205 if (needs_sources_scan == TRUE)
1207 DEBUG_PRINT ("Symbol-DB: importing sources...");
1208 do_import_sources (plugin, pm, root_dir);
1210 else /* no import needed. */
1212 /* we may have aborted the scan of sources ..*/
1213 GPtrArray *sources_array = NULL;
1215 sources_array =
1216 symbol_db_engine_get_files_with_zero_symbols (sdb_plugin->sdbe_project);
1218 if (sources_array != NULL && sources_array->len > 0)
1220 /* if we're importing first shut off the signal receiving.
1221 * We'll re-enable that on scan-end
1223 symbol_db_view_locals_recv_signals_from_engine (
1224 SYMBOL_DB_VIEW_LOCALS (sdb_plugin->dbv_view_tree_locals),
1225 sdb_plugin->sdbe_project, FALSE);
1227 symbol_db_view_recv_signals_from_engine (
1228 SYMBOL_DB_VIEW (sdb_plugin->dbv_view_tree),
1229 sdb_plugin->sdbe_project, FALSE);
1231 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_project),
1232 "scan-end", G_CALLBACK (on_importing_project_end), plugin);
1234 do_import_project_src_after_abort (plugin, sources_array);
1236 g_ptr_array_foreach (sources_array, (GFunc)g_free, NULL);
1237 g_ptr_array_free (sources_array, TRUE);
1240 /* Update the symbols */
1241 symbol_db_engine_update_project_symbols (sdb_plugin->sdbe_project,
1242 root_dir);
1244 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_project),
1245 _("Populating symbols' db..."));
1246 id = g_idle_add ((GSourceFunc) gtk_progress_bar_pulse,
1247 sdb_plugin->progress_bar_project);
1248 gtk_widget_show (sdb_plugin->progress_bar_project);
1250 symbol_db_view_open (SYMBOL_DB_VIEW (sdb_plugin->dbv_view_tree),
1251 sdb_plugin->sdbe_project);
1252 g_source_remove (id);
1253 gtk_widget_hide (sdb_plugin->progress_bar_project);
1255 /* root dir */
1256 sdb_plugin->project_root_dir = root_dir;
1258 g_hash_table_unref (lang_hash);
1260 /* this is uri */
1261 sdb_plugin->project_root_uri = g_strdup (root_uri);
1264 g_signal_connect (G_OBJECT (pm), "element_added",
1265 G_CALLBACK (on_project_element_added), sdb_plugin);
1266 g_signal_connect (G_OBJECT (pm), "element_removed",
1267 G_CALLBACK (on_project_element_removed), sdb_plugin);
1270 /* hide it. Default */
1271 /* system tags thing */
1272 gtk_widget_hide (sdb_plugin->progress_bar_system);
1274 GPtrArray *sys_src_array = NULL;
1276 sys_src_array =
1277 symbol_db_engine_get_files_with_zero_symbols (sdb_plugin->sdbe_globals);
1279 if (sys_src_array != NULL && sys_src_array->len > 0)
1281 do_import_system_src_after_abort (plugin, sys_src_array);
1283 g_ptr_array_foreach (sys_src_array, (GFunc)g_free, NULL);
1284 g_ptr_array_free (sys_src_array, TRUE);
1288 static void
1289 on_project_root_removed (AnjutaPlugin *plugin, const gchar *name,
1290 gpointer user_data)
1292 IAnjutaProjectManager *pm;
1293 SymbolDBPlugin *sdb_plugin;
1295 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
1296 DEBUG_PRINT ("project_root_removed ()");
1297 /* Disconnect events from project manager */
1299 /* FIXME: There should be a way to ensure that this project manager
1300 * is indeed the one that has opened the project_uri
1302 pm = anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin)->shell,
1303 IAnjutaProjectManager, NULL);
1304 g_signal_handlers_disconnect_by_func (G_OBJECT (pm),
1305 on_project_element_added,
1306 sdb_plugin);
1307 g_signal_handlers_disconnect_by_func (G_OBJECT (pm),
1308 on_project_element_removed,
1309 sdb_plugin);
1311 /* clear locals symbols and the associated cache*/
1312 symbol_db_view_locals_clear_cache (SYMBOL_DB_VIEW_LOCALS (
1313 sdb_plugin->dbv_view_tree_locals));
1315 /* clear global symbols */
1316 symbol_db_view_clear_cache (SYMBOL_DB_VIEW (sdb_plugin->dbv_view_tree));
1318 /* don't forget to close the project */
1319 symbol_db_engine_close_db (sdb_plugin->sdbe_project);
1321 g_free (sdb_plugin->project_root_uri);
1322 g_free (sdb_plugin->project_root_dir);
1323 g_free (sdb_plugin->project_opened);
1324 sdb_plugin->project_root_uri = NULL;
1325 sdb_plugin->project_root_dir = NULL;
1326 sdb_plugin->project_opened = NULL;
1329 static gboolean
1330 symbol_db_activate (AnjutaPlugin *plugin)
1332 SymbolDBPlugin *symbol_db;
1333 gchar *anjuta_cache_path;
1334 gchar *ctags_path;
1336 DEBUG_PRINT ("SymbolDBPlugin: Activating SymbolDBPlugin plugin ...");
1338 /* Initialize gda library. */
1339 gda_init ();
1341 register_stock_icons (plugin);
1343 symbol_db = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
1344 symbol_db->ui = anjuta_shell_get_ui (plugin->shell, NULL);
1345 symbol_db->prefs = anjuta_shell_get_preferences (plugin->shell, NULL);
1346 symbol_db->project_opened = NULL;
1348 ctags_path = anjuta_preferences_get (symbol_db->prefs, CTAGS_PREFS_KEY);
1350 if (ctags_path == NULL)
1352 g_warning ("ctags is not in preferences. Trying a default one %s",
1353 CTAGS_PATH);
1354 ctags_path = g_strdup (CTAGS_PATH);
1357 /* initialize the session packages to NULL. We'll store there the user
1358 * preferences for the session about global-system packages
1360 symbol_db->session_packages = NULL;
1362 /* create SymbolDBEngine(s) */
1363 symbol_db->sdbe_project = symbol_db_engine_new (ctags_path);
1365 /* the globals one too */
1366 symbol_db->sdbe_globals = symbol_db_engine_new (ctags_path);
1368 g_free (ctags_path);
1370 /* open it */
1371 anjuta_cache_path = anjuta_util_get_user_cache_file_path (".", NULL);
1372 symbol_db_engine_open_db (symbol_db->sdbe_globals,
1373 anjuta_cache_path,
1374 PROJECT_GLOBALS);
1376 g_free (anjuta_cache_path);
1378 /* create the object that'll manage the globals population */
1379 symbol_db->sdbs = symbol_db_system_new (symbol_db, symbol_db->sdbe_globals);
1381 g_signal_connect (G_OBJECT (symbol_db->sdbs), "scan-package-start",
1382 G_CALLBACK (on_system_scan_package_start), plugin);
1384 g_signal_connect (G_OBJECT (symbol_db->sdbs), "scan-package-end",
1385 G_CALLBACK (on_system_scan_package_end), plugin);
1387 g_signal_connect (G_OBJECT (symbol_db->sdbs), "single-file-scan-end",
1388 G_CALLBACK (on_system_single_file_scan_end), plugin);
1390 /* sets preferences to NULL, it'll be instantiated when required.\ */
1391 symbol_db->sdbp = NULL;
1393 /* Create widgets */
1394 symbol_db->dbv_main = gtk_vbox_new(FALSE, 5);
1395 symbol_db->dbv_notebook = gtk_notebook_new();
1396 symbol_db->progress_bar_project = gtk_progress_bar_new();
1397 gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR(symbol_db->progress_bar_project),
1398 PANGO_ELLIPSIZE_END);
1399 g_object_ref (symbol_db->progress_bar_project);
1401 symbol_db->progress_bar_system = gtk_progress_bar_new();
1402 gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR(symbol_db->progress_bar_system),
1403 PANGO_ELLIPSIZE_END);
1405 g_object_ref (symbol_db->progress_bar_system);
1407 gtk_box_pack_start (GTK_BOX (symbol_db->dbv_main), symbol_db->dbv_notebook,
1408 TRUE, TRUE, 0);
1409 gtk_box_pack_start (GTK_BOX (symbol_db->dbv_main), symbol_db->progress_bar_project,
1410 FALSE, FALSE, 0);
1411 gtk_box_pack_start (GTK_BOX (symbol_db->dbv_main), symbol_db->progress_bar_system,
1412 FALSE, FALSE, 0);
1413 gtk_widget_show_all (symbol_db->dbv_main);
1415 /* Local symbols */
1416 symbol_db->scrolled_locals = gtk_scrolled_window_new (NULL, NULL);
1417 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (symbol_db->scrolled_locals),
1418 GTK_SHADOW_IN);
1419 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (symbol_db->scrolled_locals),
1420 GTK_POLICY_AUTOMATIC,
1421 GTK_POLICY_AUTOMATIC);
1423 symbol_db->dbv_view_locals_tab_label = gtk_label_new (_("Local" ));
1424 symbol_db->dbv_view_tree_locals = symbol_db_view_locals_new ();
1425 /* activate signals receiving by default */
1426 symbol_db_view_locals_recv_signals_from_engine (
1427 SYMBOL_DB_VIEW_LOCALS (symbol_db->dbv_view_tree_locals),
1428 symbol_db->sdbe_project, TRUE);
1430 g_object_add_weak_pointer (G_OBJECT (symbol_db->dbv_view_tree_locals),
1431 (gpointer)&symbol_db->dbv_view_tree_locals);
1432 g_signal_connect (G_OBJECT (symbol_db->dbv_view_tree_locals), "row-activated",
1433 G_CALLBACK (on_local_treeview_row_activated), plugin);
1435 gtk_container_add (GTK_CONTAINER(symbol_db->scrolled_locals),
1436 symbol_db->dbv_view_tree_locals);
1439 /* Global symbols */
1440 symbol_db->scrolled_global = gtk_scrolled_window_new (NULL, NULL);
1441 gtk_scrolled_window_set_shadow_type (
1442 GTK_SCROLLED_WINDOW (symbol_db->scrolled_global),
1443 GTK_SHADOW_IN);
1444 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (symbol_db->scrolled_global),
1445 GTK_POLICY_AUTOMATIC,
1446 GTK_POLICY_AUTOMATIC);
1448 symbol_db->dbv_view_tab_label = gtk_label_new (_("Global" ));
1449 symbol_db->dbv_view_tree = symbol_db_view_new ();
1450 g_object_add_weak_pointer (G_OBJECT (symbol_db->dbv_view_tree),
1451 (gpointer)&symbol_db->dbv_view_tree);
1452 /* activate signals receiving by default */
1453 symbol_db_view_recv_signals_from_engine (
1454 SYMBOL_DB_VIEW (symbol_db->dbv_view_tree),
1455 symbol_db->sdbe_project, TRUE);
1457 g_signal_connect (G_OBJECT (symbol_db->dbv_view_tree), "row-activated",
1458 G_CALLBACK (on_global_treeview_row_activated), plugin);
1460 g_signal_connect (G_OBJECT (symbol_db->dbv_view_tree), "row-expanded",
1461 G_CALLBACK (on_global_treeview_row_expanded), plugin);
1463 g_signal_connect (G_OBJECT (symbol_db->dbv_view_tree), "row-collapsed",
1464 G_CALLBACK (on_global_treeview_row_collapsed), plugin);
1466 gtk_container_add (GTK_CONTAINER(symbol_db->scrolled_global),
1467 symbol_db->dbv_view_tree);
1469 /* Search symbols */
1470 symbol_db->dbv_view_tree_search =
1471 (GtkWidget*) symbol_db_view_search_new (symbol_db->sdbe_project);
1472 symbol_db->dbv_view_search_tab_label = gtk_label_new (_("Search" ));
1474 g_signal_connect (G_OBJECT (symbol_db->dbv_view_tree_search), "symbol-selected",
1475 G_CALLBACK (on_treesearch_symbol_selected_event),
1476 plugin);
1478 g_object_add_weak_pointer (G_OBJECT (symbol_db->dbv_view_tree_search),
1479 (gpointer)&symbol_db->dbv_view_tree_search);
1481 /* add the scrolled windows to the notebook */
1482 gtk_notebook_append_page (GTK_NOTEBOOK (symbol_db->dbv_notebook),
1483 symbol_db->scrolled_locals,
1484 symbol_db->dbv_view_locals_tab_label);
1486 gtk_notebook_append_page (GTK_NOTEBOOK (symbol_db->dbv_notebook),
1487 symbol_db->scrolled_global,
1488 symbol_db->dbv_view_tab_label);
1490 gtk_notebook_append_page (GTK_NOTEBOOK (symbol_db->dbv_notebook),
1491 symbol_db->dbv_view_tree_search,
1492 symbol_db->dbv_view_search_tab_label);
1494 gtk_widget_show_all (symbol_db->dbv_notebook);
1496 /* setting focus to the tree_view*/
1497 gtk_notebook_set_current_page (GTK_NOTEBOOK (symbol_db->dbv_notebook), 0);
1499 symbol_db->editor_watch_id =
1500 anjuta_plugin_add_watch (plugin, IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT,
1501 value_added_current_editor,
1502 value_removed_current_editor, NULL);
1503 /* Added widgets */
1504 anjuta_shell_add_widget (plugin->shell, symbol_db->dbv_main,
1505 "AnjutaSymbolDB", _("Symbols"),
1506 "symbol-db-plugin-icon",
1507 ANJUTA_SHELL_PLACEMENT_LEFT, NULL);
1509 /* set up project directory watch */
1510 symbol_db->root_watch_id = anjuta_plugin_add_watch (plugin,
1511 IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI,
1512 on_project_root_added,
1513 on_project_root_removed, NULL);
1515 /* Determine session state */
1516 g_signal_connect (plugin->shell, "load-session",
1517 G_CALLBACK (on_session_load), plugin);
1519 g_signal_connect (plugin->shell, "save-session",
1520 G_CALLBACK (on_session_save), plugin);
1522 return TRUE;
1525 static gboolean
1526 symbol_db_deactivate (AnjutaPlugin *plugin)
1528 SymbolDBPlugin *sdb_plugin;
1530 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
1532 DEBUG_PRINT ("SymbolDBPlugin: Dectivating SymbolDBPlugin plugin ...");
1533 DEBUG_PRINT ("SymbolDBPlugin: destroying engine ...");
1534 g_object_unref (sdb_plugin->sdbe_project);
1535 sdb_plugin->sdbe_project = NULL;
1537 /* this must be done *bedore* destroying sdbe_globals */
1538 g_object_unref (sdb_plugin->sdbs);
1539 sdb_plugin->sdbs = NULL;
1540 g_free (sdb_plugin->current_scanned_package);
1542 g_object_unref (sdb_plugin->sdbe_globals);
1543 sdb_plugin->sdbe_globals = NULL;
1545 g_free (sdb_plugin->project_opened);
1546 sdb_plugin->project_opened = NULL;
1548 if (sdb_plugin->session_packages)
1550 g_list_foreach (sdb_plugin->session_packages, (GFunc)g_free, NULL);
1551 g_list_free (sdb_plugin->session_packages);
1552 sdb_plugin->session_packages = NULL;
1555 /* disconnect some signals */
1556 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin->dbv_view_tree_locals),
1557 on_local_treeview_row_activated,
1558 plugin);
1560 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin->dbv_view_tree_search),
1561 on_treesearch_symbol_selected_event,
1562 plugin);
1564 /* Ensure all editor cached info are released */
1565 if (sdb_plugin->editor_connected)
1567 g_hash_table_foreach (sdb_plugin->editor_connected,
1568 on_editor_foreach_disconnect, plugin);
1569 g_hash_table_destroy (sdb_plugin->editor_connected);
1570 sdb_plugin->editor_connected = NULL;
1573 /* Remove watches */
1574 anjuta_plugin_remove_watch (plugin, sdb_plugin->root_watch_id, FALSE);
1575 anjuta_plugin_remove_watch (plugin, sdb_plugin->editor_watch_id, TRUE);
1577 /* Remove widgets: Widgets will be destroyed when dbv_main is removed */
1578 g_object_unref (sdb_plugin->progress_bar_project);
1579 g_object_unref (sdb_plugin->progress_bar_system);
1580 anjuta_shell_remove_widget (plugin->shell, sdb_plugin->dbv_main, NULL);
1582 sdb_plugin->root_watch_id = 0;
1583 sdb_plugin->editor_watch_id = 0;
1584 sdb_plugin->dbv_notebook = NULL;
1585 sdb_plugin->scrolled_global = NULL;
1586 sdb_plugin->scrolled_locals = NULL;
1587 sdb_plugin->dbv_view_tree = NULL;
1588 sdb_plugin->dbv_view_tab_label = NULL;
1589 sdb_plugin->dbv_view_tree_locals = NULL;
1590 sdb_plugin->dbv_view_locals_tab_label = NULL;
1591 sdb_plugin->dbv_view_tree_search = NULL;
1592 sdb_plugin->dbv_view_search_tab_label = NULL;
1593 sdb_plugin->progress_bar_project = NULL;
1594 sdb_plugin->progress_bar_system = NULL;
1595 return TRUE;
1598 static void
1599 symbol_db_finalize (GObject *obj)
1601 DEBUG_PRINT ("Symbol-DB finalize");
1602 /* Finalization codes here */
1603 G_OBJECT_CLASS (parent_class)->finalize (obj);
1606 static void
1607 symbol_db_dispose (GObject *obj)
1609 /* Disposition codes */
1610 G_OBJECT_CLASS (parent_class)->dispose (obj);
1613 static void
1614 symbol_db_instance_init (GObject *obj)
1616 SymbolDBPlugin *plugin = (SymbolDBPlugin*)obj;
1618 plugin->files_count_project_done = 0;
1619 plugin->files_count_project = 0;
1621 plugin->files_count_system_done = 0;
1622 plugin->files_count_system = 0;
1623 plugin->current_scanned_package = NULL;
1626 static void
1627 symbol_db_class_init (GObjectClass *klass)
1629 AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
1631 parent_class = g_type_class_peek_parent (klass);
1633 plugin_class->activate = symbol_db_activate;
1634 plugin_class->deactivate = symbol_db_deactivate;
1635 klass->finalize = symbol_db_finalize;
1636 klass->dispose = symbol_db_dispose;
1639 static IAnjutaIterable*
1640 isymbol_manager_search (IAnjutaSymbolManager *sm,
1641 IAnjutaSymbolType match_types,
1642 gboolean include_types,
1643 IAnjutaSymbolField info_fields,
1644 const gchar *match_name,
1645 gboolean partial_name_match,
1646 gboolean global_symbols_search,
1647 gboolean global_tags_search,
1648 gint results_limit,
1649 gint results_offset,
1650 GError **err)
1652 SymbolDBEngineIterator *iterator = NULL;
1653 SymbolDBPlugin *sdb_plugin;
1654 SymbolDBEngine *dbe_project;
1655 SymbolDBEngine *dbe_globals;
1656 GPtrArray *filter_array;
1657 gchar *pattern;
1658 gboolean exact_match = !partial_name_match;
1660 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (sm);
1661 dbe_project = SYMBOL_DB_ENGINE (sdb_plugin->sdbe_project);
1662 dbe_globals = SYMBOL_DB_ENGINE (sdb_plugin->sdbe_globals);
1664 if (match_types & IANJUTA_SYMBOL_TYPE_MAX)
1666 filter_array = NULL;
1668 else
1670 filter_array = symbol_db_engine_fill_type_array (match_types);
1673 if (exact_match == FALSE)
1674 pattern = g_strdup_printf ("%s%%", match_name);
1675 else
1676 pattern = g_strdup_printf ("%s", match_name);
1678 /* should we lookup for project of system tags? */
1679 /* DEBUG_PRINT ("tags scan [%s] [exact_match %d] [global %d]", pattern,
1680 exact_match, global_symbols_search); */
1681 iterator =
1682 symbol_db_engine_find_symbol_by_name_pattern_filtered (
1683 global_tags_search == FALSE ? dbe_project : dbe_globals,
1684 pattern,
1685 exact_match,
1686 filter_array,
1687 include_types,
1688 global_symbols_search,
1689 results_limit,
1690 results_offset,
1691 info_fields);
1692 g_free (pattern);
1694 if (filter_array)
1696 g_ptr_array_foreach (filter_array, (GFunc)g_free, NULL);
1697 g_ptr_array_free (filter_array, TRUE);
1699 return IANJUTA_ITERABLE (iterator);
1702 static IAnjutaIterable*
1703 isymbol_manager_get_members (IAnjutaSymbolManager *sm,
1704 IAnjutaSymbol *symbol,
1705 IAnjutaSymbolField info_fields,
1706 gboolean global_search,
1707 GError **err)
1709 SymbolDBEngineIteratorNode *node;
1710 SymbolDBPlugin *sdb_plugin;
1711 SymbolDBEngine *dbe;
1712 gint sym_id;
1713 SymbolDBEngineIterator *iterator;
1715 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (sm);
1716 dbe = SYMBOL_DB_ENGINE (sdb_plugin->sdbe_project);
1718 node = SYMBOL_DB_ENGINE_ITERATOR_NODE (symbol);
1720 sym_id = symbol_db_engine_iterator_node_get_symbol_id (node);
1722 iterator = symbol_db_engine_get_scope_members_by_symbol_id (dbe,
1723 sym_id,
1724 -1,
1726 info_fields);
1727 return IANJUTA_ITERABLE (iterator);
1730 static IAnjutaIterable*
1731 isymbol_manager_get_class_parents (IAnjutaSymbolManager *sm,
1732 IAnjutaSymbol *symbol,
1733 IAnjutaSymbolField info_fields,
1734 GError **err)
1736 SymbolDBEngineIteratorNode *node;
1737 SymbolDBPlugin *sdb_plugin;
1738 SymbolDBEngine *dbe;
1739 gint sym_id;
1740 SymbolDBEngineIterator *iterator;
1742 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (sm);
1743 dbe = SYMBOL_DB_ENGINE (sdb_plugin->sdbe_project);
1745 node = SYMBOL_DB_ENGINE_ITERATOR_NODE (symbol);
1747 sym_id = symbol_db_engine_iterator_node_get_symbol_id (node);
1749 iterator = symbol_db_engine_get_class_parents_by_symbol_id (dbe,
1750 sym_id,
1751 info_fields);
1752 return IANJUTA_ITERABLE (iterator);
1755 static void
1756 isymbol_manager_iface_init (IAnjutaSymbolManagerIface *iface)
1758 iface->search = isymbol_manager_search;
1759 iface->get_members = isymbol_manager_get_members;
1760 iface->get_class_parents = isymbol_manager_get_class_parents;
1763 static gint
1764 g_list_compare (gconstpointer a, gconstpointer b)
1766 return strcmp ((const gchar*)a, (const gchar*)b);
1769 static void
1770 on_prefs_package_add (SymbolDBPrefs *sdbp, const gchar *package,
1771 gpointer user_data)
1773 SymbolDBPlugin *sdb_plugin;
1775 g_return_if_fail (package != NULL);
1777 DEBUG_PRINT ("on_prefs_package_add");
1779 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (user_data);
1781 sdb_plugin->session_packages = g_list_prepend (sdb_plugin->session_packages,
1782 g_strdup (package));
1785 static void
1786 on_prefs_package_remove (SymbolDBPrefs *sdbp, const gchar *package,
1787 gpointer user_data)
1789 SymbolDBPlugin *sdb_plugin;
1791 g_return_if_fail (package != NULL);
1793 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (user_data);
1795 GList *item;
1796 DEBUG_PRINT ("on_prefs_package_remove");
1797 if ((item = g_list_find_custom (sdb_plugin->session_packages, package,
1798 g_list_compare)) != NULL)
1800 sdb_plugin->session_packages = g_list_remove_link (sdb_plugin->session_packages,
1801 item);
1803 /* ok, now think to the item left alone by its friends... */
1804 g_list_foreach (item, (GFunc)g_free, NULL);
1805 g_list_free (item);
1809 static void
1810 ipreferences_merge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** e)
1812 DEBUG_PRINT ("SymbolDB: ipreferences_merge");
1813 SymbolDBPlugin *sdb_plugin;
1815 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (ipref);
1817 if (sdb_plugin->sdbp == NULL)
1819 sdb_plugin->sdbp = symbol_db_prefs_new (sdb_plugin->sdbs,
1820 sdb_plugin->sdbe_project,
1821 sdb_plugin->sdbe_globals,
1822 prefs,
1823 sdb_plugin->session_packages);
1825 /* connect the signals to retrieve package modifications */
1826 g_signal_connect (G_OBJECT (sdb_plugin->sdbp), "package-add",
1827 G_CALLBACK (on_prefs_package_add),
1828 sdb_plugin);
1829 g_signal_connect (G_OBJECT (sdb_plugin->sdbp), "package-remove",
1830 G_CALLBACK (on_prefs_package_remove),
1831 sdb_plugin);
1835 static void
1836 ipreferences_unmerge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** e)
1838 SymbolDBPlugin *sdb_plugin;
1840 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (ipref);
1842 if (sdb_plugin->sdbp != NULL)
1844 g_object_unref (sdb_plugin->sdbp);
1845 sdb_plugin->sdbp = NULL;
1849 static void
1850 ipreferences_iface_init(IAnjutaPreferencesIface* iface)
1852 DEBUG_PRINT ("SymbolDB: ipreferences_iface_init");
1853 iface->merge = ipreferences_merge;
1854 iface->unmerge = ipreferences_unmerge;
1858 ANJUTA_PLUGIN_BEGIN (SymbolDBPlugin, symbol_db);
1859 ANJUTA_PLUGIN_ADD_INTERFACE (isymbol_manager, IANJUTA_TYPE_SYMBOL_MANAGER);
1860 ANJUTA_PLUGIN_ADD_INTERFACE(ipreferences, IANJUTA_TYPE_PREFERENCES);
1861 ANJUTA_PLUGIN_END;
1863 ANJUTA_SIMPLE_PLUGIN (SymbolDBPlugin, symbol_db);