symbol-db: Update symbol database on editor changes without saving
[anjuta.git] / plugins / symbol-db / plugin.c
blob3ad0979b8e6ad2f09bd8c52c4f32ff0ab68adae9
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 <gio/gio.h>
27 #include <libanjuta/anjuta-shell.h>
28 #include <libanjuta/anjuta-debug.h>
29 #include <libanjuta/anjuta-utils.h>
30 #include <libanjuta/anjuta-tabber.h>
31 #include <libanjuta/anjuta-project.h>
32 #include <libanjuta/interfaces/ianjuta-document-manager.h>
33 #include <libanjuta/interfaces/ianjuta-symbol-manager.h>
34 #include <libanjuta/interfaces/ianjuta-symbol.h>
35 #include <libanjuta/interfaces/ianjuta-project-manager.h>
36 #include <libanjuta/interfaces/ianjuta-project.h>
37 #include <libanjuta/interfaces/ianjuta-file-manager.h>
38 #include <libanjuta/interfaces/ianjuta-file.h>
39 #include <libanjuta/interfaces/ianjuta-file-loader.h>
40 #include <libanjuta/interfaces/ianjuta-editor.h>
41 #include <libanjuta/interfaces/ianjuta-markable.h>
42 #include <libanjuta/interfaces/ianjuta-language.h>
43 #include <libanjuta/interfaces/ianjuta-iterable.h>
44 #include <libanjuta/interfaces/ianjuta-preferences.h>
46 #include "plugin.h"
47 #include "symbol-db-engine.h"
48 #include "symbol-db-views.h"
50 #define ICON_FILE "anjuta-symbol-db-plugin-48.png"
51 #define UI_FILE PACKAGE_DATA_DIR\
52 "/ui/anjuta-symbol-db-plugin.xml"
54 #define BUILDER_FILE PACKAGE_DATA_DIR\
55 "/glade/anjuta-symbol-db.ui"
56 #define BUILDER_ROOT "symbol_prefs"
57 #define ICON_FILE "anjuta-symbol-db-plugin-48.png"
58 #define BUFFER_UPDATE "symboldb-buffer-update"
59 #define PARALLEL_SCAN "symboldb-parallel-scan"
60 #define PREFS_BUFFER_UPDATE "preferences_toggle:bool:1:1:symboldb-buffer-update"
61 #define PREFS_PARALLEL_SCAN "preferences_toggle:bool:1:1:symboldb-parallel-scan"
63 #define TIMEOUT_INTERVAL_SYMBOLS_UPDATE 10
64 #define TIMEOUT_SECONDS_AFTER_LAST_TIP 5
66 #define PROJECT_GLOBALS "/"
67 #define SESSION_SECTION "SymbolDB"
68 #define SESSION_KEY "SystemPackages"
69 #define PROJECT_ROOT_NAME_DEFAULT "localprj"
71 #define ANJUTA_PIXMAP_GOTO_DECLARATION "element-interface"
72 #define ANJUTA_PIXMAP_GOTO_IMPLEMENTATION "element-method"
74 #define ANJUTA_STOCK_GOTO_DECLARATION "element-interface"
75 #define ANJUTA_STOCK_GOTO_IMPLEMENTATION "element-method"
77 #define PREF_SCHEMA "org.gnome.anjuta.symbol-db"
81 static gpointer parent_class;
83 /* signals */
84 enum
86 PROJECT_IMPORT_END,
87 GLOBALS_IMPORT_END,
88 LAST_SIGNAL
91 typedef enum
93 TASK_IMPORT_PROJECT = 1,
94 TASK_IMPORT_PROJECT_AFTER_ABORT,
95 TASK_BUFFER_UPDATE,
96 TASK_ELEMENT_ADDED,
97 TASK_OFFLINE_CHANGES,
98 TASK_PROJECT_UPDATE,
99 TASK_FILE_UPDATE
100 } ProcTask;
102 static unsigned int signals[LAST_SIGNAL] = { 0 };
104 static void
105 register_stock_icons (AnjutaPlugin *plugin)
107 static gboolean registered = FALSE;
109 if (registered)
110 return;
111 registered = TRUE;
113 /* Register stock icons */
114 BEGIN_REGISTER_ICON (plugin);
115 REGISTER_ICON (ICON_FILE, "symbol-db-plugin-icon");
116 REGISTER_ICON_FULL (ANJUTA_PIXMAP_GOTO_DECLARATION, ANJUTA_STOCK_GOTO_DECLARATION);
117 REGISTER_ICON_FULL (ANJUTA_PIXMAP_GOTO_IMPLEMENTATION, ANJUTA_STOCK_GOTO_IMPLEMENTATION);
118 END_REGISTER_ICON;
121 static void
122 goto_file_line (AnjutaPlugin *plugin, const gchar *filename, gint lineno)
124 IAnjutaDocumentManager *docman;
125 GFile* file;
127 g_return_if_fail (filename != NULL);
129 DEBUG_PRINT ("going to: file %s, line %d", filename, lineno);
131 /* Go to file and line number */
132 docman = anjuta_shell_get_interface (plugin->shell, IAnjutaDocumentManager,
133 NULL);
134 file = g_file_new_for_path (filename);
135 ianjuta_document_manager_goto_file_line (docman, file, lineno, NULL);
137 g_object_unref (file);
140 /* Find an implementation (if impl == TRUE) or declaration (if impl == FALSE)
141 * from the given symbol iterator.
142 * If current_document != NULL it prefers matches from the currently open document
144 static gchar *
145 find_file_line (IAnjutaIterable *iterator, gboolean impl, const gchar *current_document,
146 gint *line)
148 gchar *path = NULL;
149 gint _line = -1;
153 const gchar *symbol_kind;
154 gboolean is_decl;
155 IAnjutaSymbol *iter_node = IANJUTA_SYMBOL (iterator);
157 if (iter_node == NULL)
159 /* not found or some error occurred */
160 break;
163 symbol_kind = ianjuta_symbol_get_string (iter_node, IANJUTA_SYMBOL_FIELD_KIND, NULL);
164 is_decl = g_strcmp0 (symbol_kind, "prototype") == 0 ||
165 g_strcmp0 (symbol_kind, "interface") == 0;
167 if (is_decl == !impl)
169 GFile *file;
170 gchar *_path;
171 file = ianjuta_symbol_get_file (iter_node, NULL);
172 /* if the path matches the current document we return immidiately */
173 _path = g_file_get_path (file);
174 g_object_unref (file);
175 if (!current_document || g_strcmp0 (_path, current_document) == 0)
177 *line = ianjuta_symbol_get_int (iter_node,
178 IANJUTA_SYMBOL_FIELD_FILE_POS,
179 NULL);
180 g_free (path);
182 return _path;
184 /* we store the first match incase there is no match against the current document */
185 else if (_line == -1)
187 path = _path;
188 _line = ianjuta_symbol_get_int (iter_node,
189 IANJUTA_SYMBOL_FIELD_FILE_POS,
190 NULL);
192 else
194 g_free (_path);
197 } while (ianjuta_iterable_next (iterator, NULL) == TRUE);
199 if (_line != -1)
200 *line = _line;
202 return path;
205 static void
206 goto_file_tag (SymbolDBPlugin *sdb_plugin, const gchar *word,
207 gboolean prefer_implementation)
209 IAnjutaIterable *iterator;
210 gchar *path = NULL;
211 gint line;
212 gint i;
213 gboolean found = FALSE;
214 SymbolDBEngine *engine;
216 for (i = 0; i < 2; i++)
218 if (i == 0)
220 engine = sdb_plugin->sdbe_project;
222 else
224 engine = sdb_plugin->sdbe_globals;
227 iterator = NULL;
228 if (symbol_db_engine_is_connected (engine))
230 iterator = ianjuta_symbol_query_search (sdb_plugin->search_query,
231 word, NULL);
234 if (iterator != NULL && ianjuta_iterable_get_length (iterator, NULL) > 0)
236 gchar *current_document = NULL;
237 /* FIXME: namespaces are not handled here, but they should. */
239 if (IANJUTA_IS_FILE (sdb_plugin->current_editor))
241 GFile *file;
243 if ((file = ianjuta_file_get_file (IANJUTA_FILE (sdb_plugin->current_editor),
244 NULL)))
246 current_document = g_file_get_path (file);
247 g_object_unref (file);
251 path = find_file_line (iterator, prefer_implementation, current_document, &line);
252 if (!path)
254 /* reset iterator */
255 ianjuta_iterable_first (iterator, NULL);
256 path = find_file_line (iterator, !prefer_implementation, current_document,
257 &line);
260 if (path)
262 goto_file_line (ANJUTA_PLUGIN (sdb_plugin), path, line);
263 g_free (path);
264 found = TRUE;
267 g_free (current_document);
270 if (iterator)
271 g_object_unref (iterator);
273 /* have we found it in the project db? */
274 if (found)
275 break;
279 static void
280 on_goto_file_tag_impl_activate (GtkAction *action, SymbolDBPlugin *sdb_plugin)
282 IAnjutaEditor *ed;
283 gchar *word;
285 if (sdb_plugin->current_editor)
287 ed = IANJUTA_EDITOR (sdb_plugin->current_editor);
288 word = ianjuta_editor_get_current_word (ed, NULL);
289 if (word)
291 goto_file_tag (sdb_plugin, word, TRUE);
292 g_free (word);
297 static void
298 on_goto_file_tag_decl_activate (GtkAction *action, SymbolDBPlugin *sdb_plugin)
300 IAnjutaEditor *ed;
301 gchar *word;
303 if (sdb_plugin->current_editor)
305 ed = IANJUTA_EDITOR (sdb_plugin->current_editor);
306 word = ianjuta_editor_get_current_word (ed, NULL);
307 if (word)
309 goto_file_tag (sdb_plugin, word, FALSE);
310 g_free (word);
315 static void
316 on_find_symbol (GtkAction *action, SymbolDBPlugin *sdb_plugin)
318 anjuta_shell_present_widget(ANJUTA_PLUGIN(sdb_plugin)->shell,
319 sdb_plugin->dbv_main, NULL);
321 gtk_notebook_set_current_page (GTK_NOTEBOOK(sdb_plugin->dbv_notebook), 2);
322 gtk_widget_grab_focus (GTK_WIDGET (sdb_plugin->search_entry));
325 static GtkActionEntry actions[] =
327 { "ActionMenuGoto", NULL, N_("_Go to"), NULL, NULL, NULL},
329 "ActionSymbolDBGotoDecl",
330 ANJUTA_STOCK_GOTO_DECLARATION,
331 N_("Tag De_claration"),
332 "<shift><control>d",
333 N_("Go to symbol declaration"),
334 G_CALLBACK (on_goto_file_tag_decl_activate)
337 "ActionSymbolDBGotoImpl",
338 ANJUTA_STOCK_GOTO_IMPLEMENTATION,
339 /* Translators: Go to the line where the tag is implemented */
340 N_("Tag _Implementation"),
341 "<control>d",
342 N_("Go to symbol definition"),
343 G_CALLBACK (on_goto_file_tag_impl_activate)
347 static GtkActionEntry actions_search[] = {
349 "ActionEditSearchFindSymbol", GTK_STOCK_FIND, N_("_Find Symbol…"),
350 "<control>l", N_("Find Symbol"),
351 G_CALLBACK (on_find_symbol)
355 static gboolean
356 editor_buffer_symbols_update (IAnjutaEditor *editor, SymbolDBPlugin *sdb_plugin)
358 gchar *current_buffer = NULL;
359 gsize buffer_size = 0;
360 GFile* file;
361 gchar * local_path;
362 GPtrArray *real_files_list;
363 GPtrArray *text_buffers;
364 GPtrArray *buffer_sizes;
365 gint i;
366 gint proc_id ;
368 /* we won't proceed with the updating of the symbols if we didn't type in
369 anything */
371 if (sdb_plugin->need_symbols_update == FALSE)
372 return FALSE;
374 if (editor)
376 buffer_size = ianjuta_editor_get_length (editor, NULL);
377 current_buffer = ianjuta_editor_get_text_all (editor, NULL);
379 file = ianjuta_file_get_file (IANJUTA_FILE (editor), NULL);
381 else
382 return FALSE;
384 if (file == NULL)
385 return FALSE;
387 /* take the path reference */
388 local_path = g_file_get_path (file);
390 /* ok that's good. Let's have a last check: is the current file present
391 * on the buffer_update_files?
393 for (i = 0; i < sdb_plugin->buffer_update_files->len; i++)
395 if (g_strcmp0 (g_ptr_array_index (sdb_plugin->buffer_update_files, i),
396 local_path) == 0)
398 /* hey we found it */
399 /* something is already scanning this buffer file. Drop the procedure now. */
400 DEBUG_PRINT ("something is already scanning the file %s", local_path);
401 return FALSE;
405 real_files_list = g_ptr_array_new_with_free_func (g_free);
406 g_ptr_array_add (real_files_list, local_path);
408 text_buffers = g_ptr_array_new ();
409 g_ptr_array_add (text_buffers, current_buffer);
411 buffer_sizes = g_ptr_array_new ();
412 g_ptr_array_add (buffer_sizes, GINT_TO_POINTER (buffer_size));
415 proc_id = 0;
416 if (symbol_db_engine_is_connected (sdb_plugin->sdbe_project))
418 proc_id = symbol_db_engine_update_buffer_symbols (sdb_plugin->sdbe_project,
419 sdb_plugin->project_opened,
420 real_files_list,
421 text_buffers,
422 buffer_sizes);
425 if (proc_id > 0)
427 /* good. All is ready for a buffer scan. Add the file_scan into the arrays */
428 gchar * local_path_dup = g_strdup (local_path);
429 g_ptr_array_add (sdb_plugin->buffer_update_files, local_path_dup);
430 /* add the id too */
431 g_ptr_array_add (sdb_plugin->buffer_update_ids, GINT_TO_POINTER (proc_id));
433 /* add a task so that scan_end_manager can manage this */
434 g_tree_insert (sdb_plugin->proc_id_tree, GINT_TO_POINTER (proc_id),
435 GINT_TO_POINTER (TASK_BUFFER_UPDATE));
437 if(sdb_plugin->editors){
438 g_hash_table_insert(sdb_plugin->editors, GINT_TO_POINTER (proc_id), editor);
442 g_ptr_array_unref (real_files_list);
443 g_free (current_buffer);
444 g_object_unref (file);
446 /* no need to free local_path, it'll be automatically freed later by the buffer_update
447 * function */
449 if(sdb_plugin->buffer_update_files->len > 0)
450 sdb_plugin->need_symbols_update = TRUE;
452 return !sdb_plugin->need_symbols_update;
454 static gboolean
455 on_editor_buffer_symbols_update_timeout (gpointer user_data)
457 SymbolDBPlugin *sdb_plugin;
458 gdouble seconds_elapsed;
460 g_return_val_if_fail (user_data != NULL, FALSE);
462 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (user_data);
463 if (sdb_plugin->current_editor == NULL)
464 return FALSE;
466 /* check the timer. If it's elapsed enought time since the last time the user
467 * typed in something, than proceed with updating, elsewhere don't do nothing
469 if (sdb_plugin->update_timer == NULL)
470 return TRUE;
472 seconds_elapsed = g_timer_elapsed (sdb_plugin->update_timer, NULL);
474 if (seconds_elapsed < TIMEOUT_SECONDS_AFTER_LAST_TIP)
475 return TRUE;
477 return editor_buffer_symbols_update (IANJUTA_EDITOR (sdb_plugin->current_editor),
478 sdb_plugin);
481 static void
482 on_editor_buffer_symbol_update_scan_end (SymbolDBEngine *dbe, gint process_id,
483 gpointer data)
485 SymbolDBPlugin *sdb_plugin;
486 gint i;
488 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (data);
490 /* search for the proc id */
491 for (i = 0; i < sdb_plugin->buffer_update_ids->len; i++)
493 if (g_ptr_array_index (sdb_plugin->buffer_update_ids, i) == GINT_TO_POINTER (process_id))
495 /* hey we found it */
496 /* remove both the items */
497 g_ptr_array_remove_index (sdb_plugin->buffer_update_ids, i);
499 g_ptr_array_remove_index (sdb_plugin->buffer_update_files, i);
501 /* no need to free the string coz the g_ptr_array is built with
502 * g_ptr_array_new_with_free_func (g_free)
507 IAnjutaEditor *editor = g_hash_table_lookup(sdb_plugin->editors, GINT_TO_POINTER (process_id));
508 g_hash_table_remove(sdb_plugin->editors, GINT_TO_POINTER (process_id));
510 if (!editor)
511 return;
513 /* was the updating of view-locals symbols blocked while we were scanning?
514 * e.g. was the editor switched? */
515 if (sdb_plugin->buffer_update_semaphore == TRUE)
517 GFile *file;
518 gchar *local_path;
519 gboolean tags_update;
520 if (!IANJUTA_IS_EDITOR (editor))
521 return;
523 file = ianjuta_file_get_file (IANJUTA_FILE (editor),
524 NULL);
526 if (file == NULL)
527 return;
529 local_path = g_file_get_path (file);
531 if (local_path == NULL)
533 g_critical ("local_path == NULL");
534 return;
537 /* add a default timeout to the updating of buffer symbols */
538 tags_update = g_settings_get_boolean (sdb_plugin->settings, BUFFER_UPDATE);
540 if (tags_update)
542 sdb_plugin->buf_update_timeout_id =
543 g_timeout_add_seconds (TIMEOUT_INTERVAL_SYMBOLS_UPDATE,
544 on_editor_buffer_symbols_update_timeout,
545 sdb_plugin);
548 g_free (local_path);
549 sdb_plugin->buffer_update_semaphore = FALSE;
553 static void
554 on_editor_destroy (SymbolDBPlugin *sdb_plugin, IAnjutaEditor *editor)
556 if (!sdb_plugin->editor_connected)
558 DEBUG_PRINT ("%s", "on_editor_destroy (): returning….");
559 return;
562 g_hash_table_remove (sdb_plugin->editor_connected, G_OBJECT (editor));
564 if (g_hash_table_size (sdb_plugin->editor_connected) <= 0)
566 DEBUG_PRINT ("%s", "displaying nothing…");
567 if (sdb_plugin->file_model)
568 g_object_set (sdb_plugin->file_model, "file-path", NULL, NULL);
572 static void
573 on_editor_update_ui (IAnjutaEditor *editor, SymbolDBPlugin *sdb_plugin)
575 g_timer_reset (sdb_plugin->update_timer);
578 static void
579 on_code_added (IAnjutaEditor *editor, IAnjutaIterable *position, gchar *code,
580 SymbolDBPlugin *sdb_plugin)
582 IAnjutaEditor *old_editor = sdb_plugin->current_editor;
583 sdb_plugin->current_editor = editor;
584 sdb_plugin->need_symbols_update = TRUE;
585 editor_buffer_symbols_update (editor, sdb_plugin);
586 sdb_plugin->current_editor = old_editor;
589 static void
590 on_char_added (IAnjutaEditor *editor, IAnjutaIterable *position, gchar ch,
591 SymbolDBPlugin *sdb_plugin)
593 g_timer_reset (sdb_plugin->update_timer);
595 /* Update when the user enters a newline */
596 if (ch == '\n')
597 sdb_plugin->need_symbols_update = TRUE;
600 static void
601 on_editor_saved (IAnjutaEditor *editor, GFile* file,
602 SymbolDBPlugin *sdb_plugin)
604 const gchar *old_uri;
605 gchar *local_filename;
606 gchar *saved_uri;
607 GPtrArray *files_array;
608 gint proc_id;
609 gint i;
611 local_filename = g_file_get_path (file);
612 /* Verify that it's local file */
613 g_return_if_fail (local_filename != NULL);
615 saved_uri = g_file_get_uri (file);
617 for (i = 0; i < sdb_plugin->buffer_update_files->len; i++)
619 if (g_strcmp0 (g_ptr_array_index (sdb_plugin->buffer_update_files, i),
620 local_filename) == 0)
622 DEBUG_PRINT ("already scanning");
623 /* something is already scanning this buffer file. Drop the procedure now. */
624 return;
628 files_array = g_ptr_array_new();
629 g_ptr_array_add (files_array, local_filename);
630 /* no need to free local_filename now */
632 if (!sdb_plugin->editor_connected)
633 return;
635 old_uri = g_hash_table_lookup (sdb_plugin->editor_connected, editor);
637 if (old_uri && strlen (old_uri) <= 0)
638 old_uri = NULL;
640 /* files_array will be freed once updating has taken place */
641 proc_id = 0;
642 if (symbol_db_engine_is_connected (sdb_plugin->sdbe_project))
644 proc_id = symbol_db_engine_update_files_symbols (sdb_plugin->sdbe_project,
645 sdb_plugin->project_root_dir, files_array, TRUE);
648 if (proc_id > 0)
650 /* add a task so that scan_end_manager can manage this */
651 g_tree_insert (sdb_plugin->proc_id_tree, GINT_TO_POINTER (proc_id),
652 GINT_TO_POINTER (TASK_FILE_UPDATE));
655 g_hash_table_insert (sdb_plugin->editor_connected, editor,
656 g_strdup (saved_uri));
658 /* if we saved it we shouldn't update a second time */
659 sdb_plugin->need_symbols_update = FALSE;
661 on_editor_update_ui (editor, sdb_plugin);
662 g_free (saved_uri);
665 static void
666 value_added_current_editor (AnjutaPlugin *plugin, const char *name,
667 const GValue *value, gpointer data)
669 gchar *uri;
670 gboolean tags_update;
671 GFile* file;
672 gchar *local_path;
673 GObject *editor;
674 SymbolDBPlugin *sdb_plugin;
676 editor = g_value_get_object (value);
677 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
678 if (sdb_plugin->session_loading)
680 return;
682 else
683 DEBUG_PRINT ("%s", "Updating symbols");
685 if (!sdb_plugin->editor_connected)
687 sdb_plugin->editor_connected = g_hash_table_new_full (g_direct_hash,
688 g_direct_equal,
689 NULL, g_free);
691 sdb_plugin->current_editor = editor;
693 if (!sdb_plugin->editors)
695 sdb_plugin->editors = g_hash_table_new (NULL, NULL);
698 if (!IANJUTA_IS_EDITOR (editor))
699 return;
701 file = ianjuta_file_get_file (IANJUTA_FILE (editor), NULL);
703 if (file == NULL)
704 return;
706 local_path = g_file_get_path (file);
707 uri = g_file_get_uri (file);
709 if (local_path == NULL)
711 g_critical ("local_path == NULL");
712 return;
715 /* we can have a weird behaviour here if we're not paying the right attention:
716 * A timeout scan could have been launched and a millisecond later the user could
717 * have switched editor: we'll be getting the symbol inserted in the previous
718 * editor into the new one's view.
720 if (sdb_plugin->buffer_update_files->len > 0)
722 sdb_plugin->buffer_update_semaphore = TRUE;
724 else
726 g_object_set (sdb_plugin->file_model, "file-path", local_path, NULL);
728 /* add a default timeout to the updating of buffer symbols */
729 tags_update = g_settings_get_boolean (sdb_plugin->settings, BUFFER_UPDATE);
732 if (tags_update)
734 sdb_plugin->buf_update_timeout_id =
735 g_timeout_add_seconds (TIMEOUT_INTERVAL_SYMBOLS_UPDATE,
736 on_editor_buffer_symbols_update_timeout,
737 plugin);
741 if (g_hash_table_lookup (sdb_plugin->editor_connected, editor) == NULL)
743 g_object_weak_ref (G_OBJECT (editor),
744 (GWeakNotify) (on_editor_destroy),
745 sdb_plugin);
746 if (uri)
748 g_hash_table_insert (sdb_plugin->editor_connected, editor,
749 g_strdup (uri));
751 else
753 g_hash_table_insert (sdb_plugin->editor_connected, editor,
754 g_strdup (""));
757 g_signal_connect (G_OBJECT (editor), "saved",
758 G_CALLBACK (on_editor_saved),
759 sdb_plugin);
760 g_signal_connect (G_OBJECT (editor), "char-added",
761 G_CALLBACK (on_char_added),
762 sdb_plugin);
763 g_signal_connect (G_OBJECT (editor), "code-changed",
764 G_CALLBACK (on_code_added),
765 sdb_plugin);
766 g_signal_connect (G_OBJECT(editor), "update_ui",
767 G_CALLBACK (on_editor_update_ui),
768 sdb_plugin);
770 g_free (uri);
771 g_free (local_path);
773 sdb_plugin->need_symbols_update = FALSE;
776 static void
777 on_editor_foreach_disconnect (gpointer key, gpointer value, gpointer user_data)
779 g_signal_handlers_disconnect_by_func (G_OBJECT(key),
780 G_CALLBACK (on_editor_saved),
781 user_data);
782 g_signal_handlers_disconnect_by_func (G_OBJECT(key),
783 G_CALLBACK (on_editor_update_ui),
784 user_data);
785 g_signal_handlers_disconnect_by_func (G_OBJECT(key),
786 G_CALLBACK (on_char_added),
787 user_data);
788 g_signal_handlers_disconnect_by_func (G_OBJECT(key),
789 G_CALLBACK (on_code_added),
790 user_data);
791 g_object_weak_unref (G_OBJECT(key),
792 (GWeakNotify) (on_editor_destroy),
793 user_data);
796 static gboolean
797 same_editor (gpointer key, gpointer value, gpointer user_data)
799 return value == user_data;
802 static void
803 value_removed_current_editor (AnjutaPlugin *plugin,
804 const char *name, gpointer data)
806 SymbolDBPlugin *sdb_plugin;
808 sdb_plugin = (SymbolDBPlugin *) plugin;
810 DEBUG_PRINT ("%s", "value_removed_current_editor ()");
811 /* let's remove the timeout for symbols refresh */
812 if (sdb_plugin->buf_update_timeout_id)
813 g_source_remove (sdb_plugin->buf_update_timeout_id);
814 sdb_plugin->buf_update_timeout_id = 0;
815 sdb_plugin->need_symbols_update = FALSE;
817 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
820 /* Remove editor from list of editors */
821 if(sdb_plugin->editors)
822 g_hash_table_foreach_remove (sdb_plugin->editors, same_editor, sdb_plugin->current_editor);
824 sdb_plugin->current_editor = NULL;
828 * Perform the real add to the db and also checks that no dups are inserted.
829 * Return the real number of files added or -1 on error.
831 static gint
832 do_add_new_files (SymbolDBPlugin *sdb_plugin, const GPtrArray *sources_array,
833 ProcTask task)
835 GPtrArray* languages_array = NULL;
836 GPtrArray* to_scan_array = NULL;
837 GHashTable* check_unique_file_hash = NULL;
838 IAnjutaLanguage* lang_manager;
839 AnjutaPlugin *plugin;
840 gint added_num;
841 gint i;
842 gint proc_id;
844 plugin = ANJUTA_PLUGIN (sdb_plugin);
846 /* create array of languages and the wannabe scanned files */
847 languages_array = g_ptr_array_new_with_free_func (g_free);
848 to_scan_array = g_ptr_array_new_with_free_func (g_free);
850 /* to speed the things up we must avoid the dups */
851 check_unique_file_hash = g_hash_table_new_full (g_str_hash,
852 g_str_equal, NULL, NULL);
854 lang_manager = anjuta_shell_get_interface (plugin->shell, IAnjutaLanguage,
855 NULL);
857 if (!lang_manager)
859 g_critical ("LanguageManager not found");
860 return -1;
863 for (i=0; i < sources_array->len; i++)
865 const gchar *file_mime;
866 const gchar *lang;
867 const gchar *local_filename;
868 GFile *gfile;
869 GFileInfo *gfile_info;
870 IAnjutaLanguageId lang_id;
872 if ( (local_filename = g_ptr_array_index (sources_array, i)) == NULL)
873 continue;
875 if ((gfile = g_file_new_for_path (local_filename)) == NULL)
876 continue;
878 gfile_info = g_file_query_info (gfile,
879 "standard::content-type",
880 G_FILE_QUERY_INFO_NONE,
881 NULL,
882 NULL);
883 if (gfile_info == NULL)
885 g_object_unref (gfile);
886 continue;
889 /* check if it's already present in the list. This avoids
890 * duplicates.
892 if (g_hash_table_lookup (check_unique_file_hash,
893 local_filename) == NULL)
895 g_hash_table_insert (check_unique_file_hash,
896 (gpointer)local_filename,
897 (gpointer)local_filename);
899 else
901 /* you're a dup! we don't want you */
902 continue;
905 file_mime = g_file_info_get_attribute_string (gfile_info,
906 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
908 lang_id = ianjuta_language_get_from_mime_type (lang_manager,
909 file_mime, NULL);
911 if (!lang_id)
913 g_object_unref (gfile);
914 g_object_unref (gfile_info);
915 continue;
918 lang = ianjuta_language_get_name (lang_manager, lang_id, NULL);
920 /* test its existence */
921 if (g_file_test (local_filename, G_FILE_TEST_EXISTS) == FALSE)
923 g_object_unref (gfile);
924 g_object_unref (gfile_info);
925 continue;
928 /* ok, we've just tested that the local_filename does exist.
929 * We can safely add it to the array.
931 g_ptr_array_add (languages_array, g_strdup (lang));
932 g_ptr_array_add (to_scan_array, g_strdup (local_filename));
933 g_object_unref (gfile);
934 g_object_unref (gfile_info);
937 /* last but not least check if we had some files in that GPtrArray. It that's not
938 * the case just pass over
940 proc_id = 0;
941 if (to_scan_array->len > 0)
943 proc_id = symbol_db_engine_add_new_files_full_async (sdb_plugin->sdbe_project,
944 sdb_plugin->project_opened, "1.0", to_scan_array, languages_array,
945 TRUE);
948 if (proc_id > 0)
950 /* insert the proc id associated within the task */
951 g_tree_insert (sdb_plugin->proc_id_tree, GINT_TO_POINTER (proc_id),
952 GINT_TO_POINTER (task));
955 /* get the real added number of files */
956 added_num = to_scan_array->len;
958 g_ptr_array_unref (languages_array);
959 g_ptr_array_unref (to_scan_array);
961 g_hash_table_destroy (check_unique_file_hash);
963 return proc_id > 0 ? added_num : -1;
966 static void
967 on_project_element_added (IAnjutaProjectManager *pm, GFile *gfile,
968 SymbolDBPlugin *sdb_plugin)
970 gchar *filename;
971 gint real_added;
972 GPtrArray *files_array;
974 g_return_if_fail (sdb_plugin->project_root_uri != NULL);
975 g_return_if_fail (sdb_plugin->project_root_dir != NULL);
977 filename = g_file_get_path (gfile);
979 files_array = g_ptr_array_new_with_free_func (g_free);
980 g_ptr_array_add (files_array, filename);
982 sdb_plugin->is_adding_element = TRUE;
984 /* use a custom function to add the files to db */
985 real_added = do_add_new_files (sdb_plugin, files_array, TASK_ELEMENT_ADDED);
986 if (real_added <= 0)
988 sdb_plugin->is_adding_element = FALSE;
991 g_ptr_array_unref (files_array);
994 static void
995 on_project_element_removed (IAnjutaProjectManager *pm, GFile *gfile,
996 SymbolDBPlugin *sdb_plugin)
998 gchar *filename;
1000 if (!sdb_plugin->project_root_uri)
1001 return;
1003 filename = g_file_get_path (gfile);
1005 if (filename)
1007 DEBUG_PRINT ("%s", "on_project_element_removed");
1008 symbol_db_engine_remove_file (sdb_plugin->sdbe_project,
1009 sdb_plugin->project_root_dir,
1010 symbol_db_util_get_file_db_path (sdb_plugin->sdbe_project,
1011 filename));
1013 g_free (filename);
1017 static void
1018 on_system_scan_package_start (SymbolDBEngine *dbe, guint num_files,
1019 const gchar *package, gpointer user_data)
1021 SymbolDBPlugin *sdb_plugin;
1022 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (user_data);
1024 sdb_plugin->files_count_system_done = 0;
1025 sdb_plugin->files_count_system += num_files;
1028 /* show the global bar */
1029 gtk_widget_show (sdb_plugin->progress_bar_system);
1030 if (sdb_plugin->current_scanned_package != NULL)
1031 g_free (sdb_plugin->current_scanned_package);
1032 sdb_plugin->current_scanned_package = g_strdup (package);
1034 DEBUG_PRINT ("********************* START [%s] with n %d files ", package, num_files);
1037 static void
1038 on_system_scan_package_end (SymbolDBEngine *dbe, const gchar *package,
1039 gpointer user_data)
1041 SymbolDBPlugin *sdb_plugin;
1042 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (user_data);
1044 DEBUG_PRINT ("******************** END () [%s]", package);
1046 /* hide the progress bar */
1047 gtk_widget_hide (sdb_plugin->progress_bar_system);
1049 sdb_plugin->files_count_system_done = 0;
1050 sdb_plugin->files_count_system = 0;
1053 static void
1054 on_system_single_file_scan_end (SymbolDBEngine *dbe, gpointer data)
1056 AnjutaPlugin *plugin;
1057 SymbolDBPlugin *sdb_plugin;
1058 gchar *message;
1059 gdouble fraction = 0;
1061 plugin = ANJUTA_PLUGIN (data);
1062 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
1064 sdb_plugin->files_count_system_done++;
1065 if (sdb_plugin->files_count_system_done >= sdb_plugin->files_count_system)
1067 message = g_strdup_printf (_("%s: Generating inheritances…"),
1068 sdb_plugin->current_scanned_package);
1070 else
1072 /* Translators: %s is the name of a system library */
1073 message = g_strdup_printf (ngettext ("%s: %d file scanned out of %d", "%s: %d files scanned out of %d", sdb_plugin->files_count_system_done),
1074 sdb_plugin->current_scanned_package,
1075 sdb_plugin->files_count_system_done,
1076 sdb_plugin->files_count_system);
1079 if (sdb_plugin->files_count_system > 0)
1081 fraction = (gdouble) sdb_plugin->files_count_system_done /
1082 (gdouble) sdb_plugin->files_count_system;
1084 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_system),
1085 fraction);
1086 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_system), message);
1088 g_free (message);
1091 static void
1092 on_project_single_file_scan_end (SymbolDBEngine *dbe, gpointer data)
1094 AnjutaPlugin *plugin;
1095 SymbolDBPlugin *sdb_plugin;
1096 gchar *message;
1097 gdouble fraction = 0;
1099 plugin = ANJUTA_PLUGIN (data);
1100 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
1102 sdb_plugin->files_count_project_done++;
1103 if (sdb_plugin->files_count_project_done >= sdb_plugin->files_count_project)
1104 message = g_strdup_printf (_("Generating inheritances…"));
1105 else
1106 message = g_strdup_printf (ngettext ("%d file scanned out of %d", "%d files scanned out of %d", sdb_plugin->files_count_project_done),
1107 sdb_plugin->files_count_project_done, sdb_plugin->files_count_project);
1109 if (sdb_plugin->files_count_project > 0)
1111 fraction = (gdouble) sdb_plugin->files_count_project_done /
1112 (gdouble) sdb_plugin->files_count_project;
1113 if (fraction > 1.0)
1114 fraction = 1.0;
1116 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_project),
1117 fraction);
1118 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_project), message);
1119 gtk_widget_show (sdb_plugin->progress_bar_project);
1120 g_free (message);
1123 static void
1124 clear_project_progress_bar (SymbolDBEngine *dbe, gpointer data)
1126 SymbolDBPlugin *sdb_plugin;
1128 g_return_if_fail (data != NULL);
1130 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (data);
1132 /* hide the progress bar */
1133 gtk_widget_hide (sdb_plugin->progress_bar_project);
1136 static void
1137 on_check_offline_single_file_scan_end (SymbolDBEngine *dbe, gpointer data)
1139 on_project_single_file_scan_end (dbe, data);
1142 /* note the *system* word in the function */
1143 static void
1144 do_import_system_sources_after_abort (SymbolDBPlugin *sdb_plugin,
1145 const GPtrArray *sources_array)
1147 AnjutaPlugin *plugin;
1148 GPtrArray* languages_array = NULL;
1149 GPtrArray *to_scan_array = NULL;
1150 IAnjutaLanguage* lang_manager;
1151 gint i;
1153 plugin = ANJUTA_PLUGIN (sdb_plugin);
1155 lang_manager = anjuta_shell_get_interface (plugin->shell, IAnjutaLanguage,
1156 NULL);
1158 /* create array of languages */
1159 languages_array = g_ptr_array_new_with_free_func (g_free);
1160 to_scan_array = g_ptr_array_new_with_free_func (g_free);
1162 if (!lang_manager)
1164 g_critical ("LanguageManager not found");
1165 return;
1168 for (i=0; i < sources_array->len; i++)
1170 const gchar *file_mime;
1171 const gchar *lang;
1172 const gchar *local_filename;
1173 GFile *gfile;
1174 GFileInfo *gfile_info;
1175 IAnjutaLanguageId lang_id;
1177 local_filename = g_ptr_array_index (sources_array, i);
1179 if (local_filename == NULL)
1180 continue;
1182 gfile = g_file_new_for_path (local_filename);
1183 if (gfile == NULL)
1184 continue;
1186 gfile_info = g_file_query_info (gfile,
1187 "*",
1188 G_FILE_QUERY_INFO_NONE,
1189 NULL,
1190 NULL);
1191 if (gfile_info == NULL)
1193 g_object_unref (gfile);
1194 continue;
1197 file_mime = g_file_info_get_attribute_string (gfile_info,
1198 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
1200 lang_id = ianjuta_language_get_from_mime_type (lang_manager,
1201 file_mime, NULL);
1203 if (!lang_id)
1205 g_object_unref (gfile);
1206 g_object_unref (gfile_info);
1207 continue;
1210 lang = ianjuta_language_get_name (lang_manager, lang_id, NULL);
1212 /* test its existence */
1213 if (g_file_test (local_filename, G_FILE_TEST_EXISTS) == FALSE)
1215 g_object_unref (gfile);
1216 g_object_unref (gfile_info);
1217 continue;
1220 g_ptr_array_add (languages_array, g_strdup (lang));
1221 g_ptr_array_add (to_scan_array, g_strdup (local_filename));
1222 g_object_unref (gfile);
1223 g_object_unref (gfile_info);
1226 /* FIXME HERE currently disabled */
1227 #if 0
1228 symbol_db_system_parse_aborted_package (sdb_plugin->sdbs,
1229 to_scan_array,
1230 languages_array);
1231 #endif
1233 g_ptr_array_unref(to_scan_array);
1234 g_ptr_array_unref(languages_array);
1237 /* we assume that sources_array has already unique elements */
1238 /* note the *project* word in the function */
1239 static void
1240 do_import_project_sources_after_abort (SymbolDBPlugin *sdb_plugin,
1241 const GPtrArray *sources_array)
1243 gint real_added;
1245 sdb_plugin->is_project_importing = TRUE;
1247 /* connect to receive signals on single file scan complete. We'll
1248 * update a status bar notifying the user about the status
1250 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_project), "single-file-scan-end",
1251 G_CALLBACK (on_project_single_file_scan_end), sdb_plugin);
1253 real_added = do_add_new_files (sdb_plugin, sources_array,
1254 TASK_IMPORT_PROJECT_AFTER_ABORT);
1255 if (real_added <= 0)
1257 sdb_plugin->is_project_importing = FALSE;
1259 else
1261 sdb_plugin->files_count_project += real_added;
1265 static void
1266 do_import_project_sources (SymbolDBPlugin *sdb_plugin, IAnjutaProjectManager *pm,
1267 const gchar *root_dir)
1269 GList* prj_elements_list;
1270 GPtrArray* sources_array;
1271 gint i;
1272 gint real_added;
1274 prj_elements_list = ianjuta_project_manager_get_elements (pm,
1275 ANJUTA_PROJECT_SOURCE | ANJUTA_PROJECT_PROJECT,
1276 NULL);
1278 if (prj_elements_list == NULL)
1280 g_warning ("No sources found within this project");
1281 return;
1284 /* if we're importing first shut off the signal receiving.
1285 * We'll re-enable that on scan-end
1287 sdb_plugin->is_project_importing = TRUE;
1288 DEBUG_PRINT ("Retrieving %d gbf sources of the project…",
1289 g_list_length (prj_elements_list));
1291 /* create the storage array. The file names will be strdup'd and put here.
1292 * This is just a sort of GList -> GPtrArray conversion.
1294 sources_array = g_ptr_array_new_with_free_func (g_free);
1295 for (i=0; i < g_list_length (prj_elements_list); i++)
1297 gchar *local_filename;
1298 GFile *gfile = NULL;
1300 gfile = g_list_nth_data (prj_elements_list, i);
1302 if ((local_filename = g_file_get_path (gfile)) == NULL)
1304 continue;
1307 g_ptr_array_add (sources_array, local_filename);
1310 /* connect to receive signals on single file scan complete. We'll
1311 * update a status bar notifying the user about the status
1313 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_project), "single-file-scan-end",
1314 G_CALLBACK (on_project_single_file_scan_end), sdb_plugin);
1316 real_added = do_add_new_files (sdb_plugin, sources_array, TASK_IMPORT_PROJECT);
1317 if (real_added <= 0)
1319 sdb_plugin->is_project_importing = FALSE;
1321 sdb_plugin->files_count_project += real_added;
1324 /* free the ptr array */
1325 g_ptr_array_unref (sources_array);
1327 /* and the list of project files */
1328 g_list_foreach (prj_elements_list, (GFunc) g_object_unref, NULL);
1329 g_list_free (prj_elements_list);
1333 * This function will call do_import_project_sources_after_abort ().
1334 * The list of files for sysstem packages enqueued on the first scan aren't
1335 * persisted on session for later retrieval. So we can only rely
1336 * on fixing the zero-symbols file.
1338 static void
1339 do_import_system_sources (SymbolDBPlugin *sdb_plugin)
1341 /* the resume thing */
1342 GPtrArray *sys_src_array = NULL;
1343 sys_src_array =
1344 symbol_db_util_get_files_with_zero_symbols (sdb_plugin->sdbe_globals);
1346 if (sys_src_array != NULL && sys_src_array->len > 0)
1348 do_import_system_sources_after_abort (sdb_plugin, sys_src_array);
1350 g_ptr_array_unref (sys_src_array);
1355 * @return TRUE if a scan is in progress, FALSE elsewhere.
1357 static gboolean
1358 do_update_project_symbols (SymbolDBPlugin *sdb_plugin, const gchar *root_dir)
1360 gint proc_id;
1361 /* Update the symbols */
1362 proc_id = symbol_db_engine_update_project_symbols (sdb_plugin->sdbe_project,
1363 root_dir, FALSE);
1364 if (proc_id > 0)
1366 sdb_plugin->is_project_updating = TRUE;
1368 /* insert the proc id associated within the task */
1369 g_tree_insert (sdb_plugin->proc_id_tree, GINT_TO_POINTER (proc_id),
1370 GINT_TO_POINTER (TASK_PROJECT_UPDATE));
1371 return TRUE;
1374 return FALSE;
1378 * do_check_offline_files_changed:
1379 * @sdb_plugin: self
1381 * Returns: TRUE if a scan process is started, FALSE elsewhere.
1383 static gboolean
1384 do_check_offline_files_changed (SymbolDBPlugin *sdb_plugin)
1386 GList * prj_elements_list;
1387 GList *node;
1388 IAnjutaProjectManager *pm;
1389 GHashTable *prj_elements_hash;
1390 GPtrArray *to_add_files = NULL;
1391 gint real_added = 0;
1393 pm = anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin)->shell,
1394 IAnjutaProjectManager, NULL);
1396 prj_elements_list = ianjuta_project_manager_get_elements (pm,
1397 ANJUTA_PROJECT_SOURCE | ANJUTA_PROJECT_PROJECT,
1398 NULL);
1400 /* fill an hash table with all the items of the list just taken.
1401 * We won't g_strdup () the elements because they'll be freed later
1403 prj_elements_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
1404 NULL, g_free);
1406 for (node = prj_elements_list; node != NULL; node = g_list_next (node))
1408 GFile *gfile;
1409 gchar *filename;
1410 const gchar *db_path;
1412 gfile = node->data;
1413 if (!gfile)
1414 continue;
1416 if ((filename = g_file_get_path (gfile)) == NULL ||
1417 !strlen (filename))
1419 g_object_unref (gfile);
1421 continue;
1424 /* test its existence */
1425 if (g_file_query_exists (gfile, NULL) == FALSE)
1427 g_object_unref (gfile);
1429 continue;
1432 /* Use g_hash_table_replace instead of g_hash_table_insert because the key
1433 * and the value use the same block of memory, both must be changed at
1434 * the same time. */
1435 db_path = symbol_db_util_get_file_db_path (sdb_plugin->sdbe_project,
1436 filename);
1438 if (db_path)
1439 g_hash_table_replace (prj_elements_hash,
1440 (gchar *)db_path,
1441 (gchar *)filename);
1442 g_object_unref (gfile);
1445 g_list_free(prj_elements_list);
1447 /* some files may have added/removed editing Makefile.am while
1448 * Anjuta was offline. Check this case too.
1449 * FIXME: Get rid of data model here.
1451 GdaDataModel *model =
1452 symbol_db_engine_get_files_for_project (sdb_plugin->sdbe_project);
1453 GdaDataModelIter *it =
1454 gda_data_model_create_iter (model);
1456 if (it && gda_data_model_iter_move_to_row (it, 0))
1458 GPtrArray *remove_array;
1459 remove_array = g_ptr_array_new_with_free_func (g_free);
1460 do {
1461 const GValue *val = gda_data_model_iter_get_value_at (it, 0);
1462 const gchar * file = g_value_get_string (val);
1464 if (file && g_hash_table_remove (prj_elements_hash, file) == FALSE)
1465 g_ptr_array_add (remove_array, g_strdup (file));
1467 } while (gda_data_model_iter_move_next (it));
1469 symbol_db_engine_remove_files (sdb_plugin->sdbe_project,
1470 sdb_plugin->project_opened,
1471 remove_array);
1472 g_ptr_array_unref (remove_array);
1475 /* great, at this point we should have this situation:
1476 * remove array = files to remove, remaining items in the hash_table = files
1477 * to add.
1479 to_add_files = g_ptr_array_new ();
1480 if (g_hash_table_size (prj_elements_hash) > 0)
1482 gint i;
1483 GList *keys = g_hash_table_get_keys (prj_elements_hash);
1485 /* get all the nodes from the hash table and add them to the wannabe-added
1486 * array
1488 for (i = 0; i < g_hash_table_size (prj_elements_hash); i++)
1490 /*DEBUG_PRINT ("ARRAY ADD %s", (gchar*)g_list_nth_data (keys, i));*/
1491 g_ptr_array_add (to_add_files,
1492 g_hash_table_lookup (prj_elements_hash,
1493 g_list_nth_data (keys, i)));
1497 /* good. Let's go on with add of new files. */
1498 if (to_add_files->len > 0)
1500 /* block the signals spreading from engine to local-view tab */
1501 sdb_plugin->is_offline_scanning = TRUE;
1502 real_added = do_add_new_files (sdb_plugin, to_add_files,
1503 TASK_OFFLINE_CHANGES);
1505 DEBUG_PRINT ("going to do add %d files with TASK_OFFLINE_CHANGES",
1506 real_added);
1508 if (real_added <= 0)
1510 sdb_plugin->is_offline_scanning = FALSE;
1512 else {
1513 /* connect to receive signals on single file scan complete. We'll
1514 * update a status bar notifying the user about the status
1516 sdb_plugin->files_count_project += real_added;
1518 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_project), "single-file-scan-end",
1519 G_CALLBACK (on_check_offline_single_file_scan_end), ANJUTA_PLUGIN (sdb_plugin));
1523 /*if (it != NULL) g_object_unref (it);*/
1524 g_object_unref (it);
1525 g_object_unref (model);
1526 g_ptr_array_unref (to_add_files);
1527 g_hash_table_destroy (prj_elements_hash);
1529 return real_added > 0 ? TRUE : FALSE;
1532 static void
1533 on_session_save (AnjutaShell *shell, AnjutaSessionPhase phase,
1534 AnjutaSession *session,
1535 SymbolDBPlugin *sdb_plugin)
1537 if (phase != ANJUTA_SESSION_PHASE_NORMAL)
1538 return;
1540 DEBUG_PRINT ("%s", "SymbolDB: session_save");
1543 static void
1544 on_session_load (AnjutaShell *shell, AnjutaSessionPhase phase,
1545 AnjutaSession *session,
1546 SymbolDBPlugin *sdb_plugin)
1548 if (phase == ANJUTA_SESSION_PHASE_START)
1550 DEBUG_PRINT ("SymbolDB: session_loading started. Getting info from %s",
1551 anjuta_session_get_session_directory (session));
1552 sdb_plugin->session_loading = TRUE;
1554 /* get preferences about the parallel scan */
1555 gboolean parallel_scan = g_settings_get_boolean (sdb_plugin->settings,
1556 PARALLEL_SCAN);
1558 if (parallel_scan == TRUE &&
1559 symbol_db_engine_is_connected (sdb_plugin->sdbe_globals) == TRUE)
1561 /* we simulate a project-import-end signal received */
1562 do_import_system_sources (sdb_plugin);
1565 else if (phase == ANJUTA_SESSION_PHASE_END)
1567 IAnjutaDocumentManager* docman;
1568 sdb_plugin->session_loading = FALSE;
1569 DEBUG_PRINT ("SymbolDB: session_loading finished");
1571 /* Show the symbols for the current editor */
1572 docman = anjuta_shell_get_interface (shell, IAnjutaDocumentManager, NULL);
1573 if (docman)
1575 IAnjutaDocument* cur_doc =
1576 ianjuta_document_manager_get_current_document (docman, NULL);
1577 if (cur_doc)
1579 GValue value = {0, };
1580 g_value_init (&value, G_TYPE_OBJECT);
1581 g_value_set_object (&value, cur_doc);
1582 value_added_current_editor (ANJUTA_PLUGIN (sdb_plugin),
1583 "document_manager_current_document",
1584 &value, NULL);
1585 g_value_unset(&value);
1589 if (sdb_plugin->project_opened == NULL)
1591 gtk_widget_hide (sdb_plugin->progress_bar_project);
1592 gtk_widget_hide (sdb_plugin->progress_bar_system);
1597 static void
1598 on_project_loaded (IAnjutaProjectManager *pm, GError *error,
1599 SymbolDBPlugin *sdb_plugin)
1601 g_return_if_fail (sdb_plugin->project_root_uri != NULL);
1602 g_return_if_fail (sdb_plugin->project_root_dir != NULL);
1604 /* Malformed project abort */
1605 if (error != NULL) return;
1608 * we need an initial import
1610 if (sdb_plugin->needs_sources_scan == TRUE)
1612 DEBUG_PRINT ("Importing sources.");
1613 do_import_project_sources (sdb_plugin, pm, sdb_plugin->project_root_dir);
1615 else
1618 * no import needed. But we may have aborted the scan of sources in
1619 * a previous session..
1621 GPtrArray *sources_array = NULL;
1623 DEBUG_PRINT ("Checking for files with zero symbols.");
1624 sources_array =
1625 symbol_db_util_get_files_with_zero_symbols (sdb_plugin->sdbe_project);
1627 if (sources_array != NULL && sources_array->len > 0)
1629 DEBUG_PRINT ("Importing files after abort.");
1630 do_import_project_sources_after_abort (sdb_plugin, sources_array);
1632 g_ptr_array_unref (sources_array);
1635 DEBUG_PRINT ("Checking for offline changes.");
1636 /* check for offline changes */
1637 if (do_check_offline_files_changed (sdb_plugin) == FALSE)
1639 DEBUG_PRINT ("no changes. Skipping.");
1642 DEBUG_PRINT ("Updating project symbols.");
1643 /* update any files of the project which isn't up-to-date */
1644 if (do_update_project_symbols (sdb_plugin, sdb_plugin->project_opened) == FALSE)
1646 DEBUG_PRINT ("no changes. Skipping.");
1651 /* add a new project */
1652 static void
1653 on_project_root_added (AnjutaPlugin *plugin, const gchar *name,
1654 const GValue *value, gpointer user_data)
1656 SymbolDBPlugin *sdb_plugin;
1657 const gchar *root_uri;
1658 gchar *root_dir;
1659 GFile *gfile;
1661 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
1664 * The Global System symbols thing
1667 /* is the global db connected? */
1668 if (symbol_db_engine_is_connected (sdb_plugin->sdbe_globals) == FALSE)
1670 gchar *anjuta_cache_path;
1671 /* open the connection to global db */
1672 anjuta_cache_path = anjuta_util_get_user_cache_file_path (".", NULL);
1673 if (symbol_db_engine_open_db (sdb_plugin->sdbe_globals,
1674 anjuta_cache_path,
1675 PROJECT_GLOBALS) == DB_OPEN_STATUS_FATAL)
1677 g_error ("Opening global project under %s", anjuta_cache_path);
1679 g_free (anjuta_cache_path);
1681 /* unref and recreate the sdbs object */
1682 if (sdb_plugin->sdbs != NULL)
1683 g_object_unref (sdb_plugin->sdbs);
1685 sdb_plugin->sdbs = symbol_db_system_new (sdb_plugin,
1686 sdb_plugin->sdbe_globals);
1689 /* Hide the progress bar. Default system tags thing: we'll import after abort even
1690 * if the preferences says not to automatically scan the packages.
1692 gtk_widget_hide (sdb_plugin->progress_bar_system);
1696 * The Project thing
1699 g_free (sdb_plugin->project_root_uri);
1700 sdb_plugin->project_root_uri = NULL;
1701 if ((root_uri = g_value_get_string (value)) == NULL)
1703 DEBUG_PRINT ("Warning, root_uri for project is NULL");
1704 return;
1708 gfile = g_file_new_for_uri (root_uri);
1710 root_dir = g_file_get_path (gfile);
1711 DEBUG_PRINT ("Symbol-DB: added project root_dir %s, name %s", root_dir,
1712 name);
1714 g_object_unref (gfile);
1716 /* let the project be something like "." to avoid problems when renaming the
1717 * project dir */
1718 sdb_plugin->project_opened = g_strdup (PROJECT_ROOT_NAME_DEFAULT);
1720 if (root_dir)
1722 gboolean project_exist = FALSE;
1723 guint id;
1725 /* we'll use the same values for db_directory and project_directory */
1726 DEBUG_PRINT ("Opening db %s and project_dir %s", root_dir, root_dir);
1727 gint open_status = symbol_db_engine_open_db (sdb_plugin->sdbe_project, root_dir,
1728 root_dir);
1730 /* is it a fresh-new project? is it an imported project with
1731 * no 'new' symbol-db database but the 'old' one symbol-browser?
1733 sdb_plugin->needs_sources_scan = FALSE;
1734 switch (open_status)
1736 case DB_OPEN_STATUS_FATAL:
1737 g_warning ("*** Error in opening db ***");
1738 return;
1740 case DB_OPEN_STATUS_NORMAL:
1741 project_exist = TRUE;
1742 break;
1744 case DB_OPEN_STATUS_CREATE:
1745 case DB_OPEN_STATUS_UPGRADE:
1746 sdb_plugin->needs_sources_scan = TRUE;
1747 project_exist = FALSE;
1748 break;
1750 default:
1751 break;
1754 /* if project did not exist add a new project */
1755 if (project_exist == FALSE)
1757 DEBUG_PRINT ("Creating new project.");
1758 symbol_db_engine_add_new_project (sdb_plugin->sdbe_project,
1759 NULL, /* still no workspace logic */
1760 sdb_plugin->project_opened,
1761 "1.0");
1764 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_project),
1765 _("Populating symbol database…"));
1766 id = g_idle_add ((GSourceFunc) gtk_progress_bar_pulse,
1767 sdb_plugin->progress_bar_project);
1768 gtk_widget_show (sdb_plugin->progress_bar_project);
1769 g_source_remove (id);
1770 gtk_widget_hide (sdb_plugin->progress_bar_project);
1772 /* root dir */
1773 sdb_plugin->project_root_dir = root_dir;
1775 /* this is uri */
1776 sdb_plugin->project_root_uri = g_strdup (root_uri);
1779 static void
1780 on_project_root_removed (AnjutaPlugin *plugin, const gchar *name,
1781 gpointer user_data)
1783 IAnjutaProjectManager *pm;
1784 SymbolDBPlugin *sdb_plugin;
1786 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
1787 DEBUG_PRINT ("%s", "project_root_removed ()");
1788 /* Disconnect events from project manager */
1790 pm = anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin)->shell,
1791 IAnjutaProjectManager, NULL);
1792 g_signal_handlers_disconnect_by_func (G_OBJECT (pm),
1793 on_project_element_added,
1794 sdb_plugin);
1795 g_signal_handlers_disconnect_by_func (G_OBJECT (pm),
1796 on_project_element_removed,
1797 sdb_plugin);
1799 /* don't forget to close the project */
1800 symbol_db_engine_close_db (sdb_plugin->sdbe_project);
1802 /* and the globals one */
1803 symbol_db_engine_close_db (sdb_plugin->sdbe_globals);
1805 /* stop any opened scanning process */
1806 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_system), "");
1807 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_project), "");
1808 gtk_widget_hide (sdb_plugin->progress_bar_system);
1809 gtk_widget_hide (sdb_plugin->progress_bar_project);
1811 sdb_plugin->files_count_system_done = 0;
1812 sdb_plugin->files_count_system = 0;
1814 sdb_plugin->files_count_project_done = 0;
1815 sdb_plugin->files_count_project = 0;
1818 g_free (sdb_plugin->project_root_uri);
1819 g_free (sdb_plugin->project_root_dir);
1820 g_free (sdb_plugin->project_opened);
1821 sdb_plugin->project_root_uri = NULL;
1822 sdb_plugin->project_root_dir = NULL;
1823 sdb_plugin->project_opened = NULL;
1826 static void
1827 on_scan_end_manager (SymbolDBEngine *dbe, gint process_id,
1828 gpointer data)
1830 SymbolDBPlugin *sdb_plugin;
1831 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (data);
1832 gint task_registered;
1834 task_registered = GPOINTER_TO_INT (g_tree_lookup (sdb_plugin->proc_id_tree,
1835 GINT_TO_POINTER (process_id)));
1836 /* hey, we haven't find anything */
1837 if (task_registered <= 0)
1839 DEBUG_PRINT ("No task found, proc id was %d", process_id);
1840 return;
1843 switch (task_registered)
1845 case TASK_IMPORT_PROJECT:
1846 case TASK_IMPORT_PROJECT_AFTER_ABORT:
1848 DEBUG_PRINT ("received TASK_IMPORT_PROJECT (AFTER_ABORT)");
1850 /* re-enable signals receiving on local-view */
1851 sdb_plugin->is_project_importing = FALSE;
1853 /* disconnect this coz it's not important after the process of importing */
1854 g_signal_handlers_disconnect_by_func (dbe, on_project_single_file_scan_end,
1855 sdb_plugin);
1857 /* get preferences about the parallel scan */
1858 gboolean parallel_scan = g_settings_get_boolean (sdb_plugin->settings,
1859 PARALLEL_SCAN);
1862 /* check the system population has a parallel fashion or not. */
1863 if (parallel_scan == FALSE)
1864 do_import_system_sources (sdb_plugin);
1866 break;
1868 case TASK_BUFFER_UPDATE:
1869 DEBUG_PRINT ("received TASK_BUFFER_UPDATE");
1870 on_editor_buffer_symbol_update_scan_end (dbe, process_id, sdb_plugin);
1871 break;
1873 case TASK_ELEMENT_ADDED:
1874 DEBUG_PRINT ("received TASK_ELEMENT_ADDED");
1875 sdb_plugin->is_adding_element = FALSE;
1876 break;
1878 case TASK_OFFLINE_CHANGES:
1879 DEBUG_PRINT ("received TASK_OFFLINE_CHANGES");
1881 /* disconnect this coz it's not important after the process of importing */
1882 g_signal_handlers_disconnect_by_func (dbe, on_check_offline_single_file_scan_end,
1883 sdb_plugin);
1885 sdb_plugin->is_offline_scanning = FALSE;
1886 break;
1888 case TASK_PROJECT_UPDATE:
1889 DEBUG_PRINT ("received TASK_PROJECT_UPDATE");
1890 sdb_plugin->is_project_updating = FALSE;
1891 break;
1893 case TASK_FILE_UPDATE:
1894 DEBUG_PRINT ("received TASK_FILE_UPDATE");
1895 break;
1897 default:
1898 DEBUG_PRINT ("Don't know what to to with task_registered %d",
1899 task_registered);
1902 /* ok, we're done. Remove the proc_id from the GTree coz we won't use it anymore */
1903 if (g_tree_remove (sdb_plugin->proc_id_tree, GINT_TO_POINTER (process_id)) == FALSE)
1904 g_warning ("Cannot remove proc_id from GTree");
1906 DEBUG_PRINT ("is_offline_scanning %d, is_project_importing %d, is_project_updating %d, "
1907 "is_adding_element %d", sdb_plugin->is_offline_scanning,
1908 sdb_plugin->is_project_importing, sdb_plugin->is_project_updating,
1909 sdb_plugin->is_adding_element);
1911 /* is the project still opened? */
1912 if (sdb_plugin->project_opened == NULL)
1914 /* just return, the project may have been closed while we were waiting for the
1915 * scanning to finish
1917 return;
1921 * perform some checks on some booleans. If they're all successfully passed
1922 * then activate the display of local view
1924 if (sdb_plugin->is_offline_scanning == FALSE &&
1925 sdb_plugin->is_project_importing == FALSE &&
1926 sdb_plugin->is_project_updating == FALSE &&
1927 sdb_plugin->is_adding_element == FALSE)
1929 sdb_plugin->files_count_project_done = 0;
1930 sdb_plugin->files_count_project = 0;
1931 clear_project_progress_bar (dbe, sdb_plugin);
1935 static void
1936 on_isymbol_manager_prj_scan_end (SymbolDBEngine *dbe,
1937 gint process_id,
1938 IAnjutaSymbolManager *sm)
1940 g_signal_emit_by_name (sm, "prj-scan-end", process_id);
1943 static void
1944 on_isymbol_manager_sys_scan_begin (SymbolDBEngine *dbe, gint process_id,
1945 SymbolDBPlugin *sdb_plugin)
1947 sdb_plugin->current_pkg_scanned = g_async_queue_pop (sdb_plugin->global_scan_aqueue);
1949 if (sdb_plugin->current_pkg_scanned == NULL)
1950 return;
1952 DEBUG_PRINT ("==%d==>\n"
1953 "begin %s", process_id, sdb_plugin->current_pkg_scanned->package_name);
1954 gtk_widget_show (sdb_plugin->progress_bar_system);
1957 static void
1958 on_isymbol_manager_sys_single_scan_end (SymbolDBEngine *dbe, SymbolDBPlugin *sdb_plugin)
1960 PackageScanData *pkg_scan;
1962 /* ignore signals when scan-end has already been received */
1963 if (sdb_plugin->current_pkg_scanned == NULL)
1965 return;
1968 pkg_scan = sdb_plugin->current_pkg_scanned;
1969 pkg_scan->files_done++;
1971 gtk_widget_show (sdb_plugin->progress_bar_system);
1972 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_system),
1973 (gdouble)pkg_scan->files_done /
1974 (gdouble)pkg_scan->files_length);
1977 static void
1978 on_isymbol_manager_sys_scan_end (SymbolDBEngine *dbe,
1979 gint process_id,
1980 SymbolDBPlugin *sdb_plugin)
1982 IAnjutaSymbolManager *sm;
1983 PackageScanData *pkg_scan;
1985 g_return_if_fail (sdb_plugin->current_pkg_scanned != NULL);
1987 DEBUG_PRINT ("<==%d==\nscan end %s. Queue now is %d",
1988 process_id,
1989 sdb_plugin->current_pkg_scanned->package_name,
1990 g_async_queue_length (sdb_plugin->global_scan_aqueue));
1992 sm = anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin)->shell,
1993 IAnjutaSymbolManager, NULL);
1995 g_signal_emit_by_name (sm, "sys-scan-end", process_id);
1997 pkg_scan = sdb_plugin->current_pkg_scanned;
1998 g_free (pkg_scan->package_name);
1999 g_free (pkg_scan->package_version);
2000 g_free (pkg_scan);
2002 sdb_plugin->current_pkg_scanned = NULL;
2004 gtk_widget_hide (sdb_plugin->progress_bar_system);
2007 static gboolean
2008 symbol_db_activate (AnjutaPlugin *plugin)
2010 IAnjutaProjectManager *pm;
2011 SymbolDBPlugin *sdb_plugin;
2012 gchar *anjuta_cache_path;
2013 gchar *ctags_path;
2014 GtkWidget *view, *label;
2016 DEBUG_PRINT ("SymbolDBPlugin: Activating SymbolDBPlugin plugin …");
2018 /* Initialize gda library. */
2019 gda_init ();
2021 register_stock_icons (plugin);
2023 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
2024 sdb_plugin->ui = anjuta_shell_get_ui (plugin->shell, NULL);
2025 sdb_plugin->project_opened = NULL;
2027 pm = anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin)->shell,
2028 IAnjutaProjectManager, NULL);
2030 ctags_path = NULL;
2032 /* leaving here this code. Maybe in future ctags-devs will include our patches
2033 * upstream and this can be useful again.
2035 if (ctags_path == NULL)
2037 DEBUG_PRINT ("ctags is not in preferences. Trying a default one %s",
2038 CTAGS_PATH);
2039 ctags_path = g_strdup (CTAGS_PATH);
2042 sdb_plugin->buf_update_timeout_id = 0;
2043 sdb_plugin->need_symbols_update = FALSE;
2044 /* creates and start a new timer. */
2045 sdb_plugin->update_timer = g_timer_new ();
2047 /* these two arrays will maintain the same number of objects,
2048 * so that if you search, say on the first, an occurrence of a file,
2049 * you'll be able to get in O(1) the _index in the second array, where the
2050 * scan process ids are stored. This is true in the other way too.
2052 sdb_plugin->buffer_update_files = g_ptr_array_new_with_free_func (g_free);
2053 sdb_plugin->buffer_update_ids = g_ptr_array_new ();
2054 sdb_plugin->buffer_update_semaphore = FALSE;
2056 sdb_plugin->is_offline_scanning = FALSE;
2057 sdb_plugin->is_project_importing = FALSE;
2058 sdb_plugin->is_project_updating = FALSE;
2059 sdb_plugin->is_adding_element = FALSE;
2061 DEBUG_PRINT ("SymbolDBPlugin: Initializing engines with %s", ctags_path);
2062 /* create SymbolDBEngine(s) */
2063 sdb_plugin->sdbe_project = symbol_db_engine_new (ctags_path);
2064 if (sdb_plugin->sdbe_project == NULL)
2066 g_critical ("sdbe_project == NULL");
2067 return FALSE;
2070 /* the globals one too */
2071 sdb_plugin->sdbe_globals = symbol_db_engine_new (ctags_path);
2072 if (sdb_plugin->sdbe_globals == NULL)
2074 g_critical ("sdbe_globals == NULL");
2075 return FALSE;
2078 g_free (ctags_path);
2080 /* open it */
2081 anjuta_cache_path = anjuta_util_get_user_cache_file_path (".", NULL);
2082 if (symbol_db_engine_open_db (sdb_plugin->sdbe_globals,
2083 anjuta_cache_path,
2084 PROJECT_GLOBALS) == DB_OPEN_STATUS_FATAL)
2086 g_error ("Opening global project under %s", anjuta_cache_path);
2089 g_free (anjuta_cache_path);
2091 sdb_plugin->global_scan_aqueue = g_async_queue_new ();
2092 /* create the object that'll manage the globals population */
2093 sdb_plugin->sdbs = symbol_db_system_new (sdb_plugin, sdb_plugin->sdbe_globals);
2094 #if 0
2095 g_signal_connect (G_OBJECT (sdb_plugin->sdbs), "scan-package-start",
2096 G_CALLBACK (on_system_scan_package_start), plugin);
2098 g_signal_connect (G_OBJECT (sdb_plugin->sdbs), "scan-package-end",
2099 G_CALLBACK (on_system_scan_package_end), plugin);
2101 g_signal_connect (G_OBJECT (sdb_plugin->sdbs), "single-file-scan-end",
2102 G_CALLBACK (on_system_single_file_scan_end), plugin);
2103 #endif
2104 /* beign necessary to listen to many scan-end signals, we'll build up a method
2105 * to manage them with just one signal connection
2107 sdb_plugin->proc_id_tree = g_tree_new_full ((GCompareDataFunc)&symbol_db_gtree_compare_func,
2108 NULL,
2109 NULL,
2110 NULL);
2112 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_project), "scan-end",
2113 G_CALLBACK (on_scan_end_manager), sdb_plugin);
2115 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_project), "scan-end",
2116 G_CALLBACK (on_isymbol_manager_prj_scan_end), sdb_plugin);
2118 /* connect signals for interface to receive them */
2119 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_globals), "single-file-scan-end",
2120 G_CALLBACK (on_isymbol_manager_sys_single_scan_end), sdb_plugin);
2122 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_globals), "scan-end",
2123 G_CALLBACK (on_isymbol_manager_sys_scan_end), sdb_plugin);
2125 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_globals), "scan-begin",
2126 G_CALLBACK (on_isymbol_manager_sys_scan_begin), sdb_plugin);
2130 /* connect signals for project loading and element adding */
2131 g_signal_connect (G_OBJECT (pm), "element-added",
2132 G_CALLBACK (on_project_element_added), sdb_plugin);
2133 g_signal_connect (G_OBJECT (pm), "element-removed",
2134 G_CALLBACK (on_project_element_removed), sdb_plugin);
2135 g_signal_connect (G_OBJECT (pm), "project-loaded",
2136 G_CALLBACK (on_project_loaded), sdb_plugin);
2138 /* Create widgets */
2139 sdb_plugin->dbv_main = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
2140 sdb_plugin->dbv_notebook = gtk_notebook_new();
2141 gtk_notebook_set_show_border (GTK_NOTEBOOK (sdb_plugin->dbv_notebook), FALSE);
2142 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (sdb_plugin->dbv_notebook), FALSE);
2143 sdb_plugin->dbv_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1);
2145 label = gtk_label_new (_("Symbols"));
2146 gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f);
2147 gtk_box_pack_start (GTK_BOX(sdb_plugin->dbv_hbox),
2148 gtk_image_new_from_stock ("symbol-db-plugin-icon",
2149 GTK_ICON_SIZE_MENU),
2150 FALSE, FALSE, 0);
2151 gtk_box_pack_start (GTK_BOX(sdb_plugin->dbv_hbox), label,
2152 FALSE, FALSE, 0);
2154 sdb_plugin->tabber = anjuta_tabber_new (GTK_NOTEBOOK (sdb_plugin->dbv_notebook));
2155 label = gtk_label_new (_("File"));
2156 gtk_label_set_ellipsize (GTK_LABEL (label),
2157 PANGO_ELLIPSIZE_END);
2158 anjuta_tabber_add_tab (ANJUTA_TABBER (sdb_plugin->tabber),
2159 label);
2160 label = gtk_label_new (_("Project"));
2161 gtk_label_set_ellipsize (GTK_LABEL (label),
2162 PANGO_ELLIPSIZE_END);
2163 anjuta_tabber_add_tab (ANJUTA_TABBER (sdb_plugin->tabber),
2164 label);
2165 label = gtk_label_new (_("Search"));
2166 gtk_label_set_ellipsize (GTK_LABEL (label),
2167 PANGO_ELLIPSIZE_END);
2168 anjuta_tabber_add_tab (ANJUTA_TABBER (sdb_plugin->tabber),
2169 label);
2170 gtk_box_pack_end (GTK_BOX(sdb_plugin->dbv_hbox), sdb_plugin->tabber,
2171 TRUE, TRUE, 5);
2173 gtk_widget_show_all (sdb_plugin->dbv_hbox);
2175 sdb_plugin->progress_bar_project = gtk_progress_bar_new();
2176 gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR(sdb_plugin->progress_bar_project),
2177 PANGO_ELLIPSIZE_MIDDLE);
2178 g_object_ref (sdb_plugin->progress_bar_project);
2180 sdb_plugin->progress_bar_system = gtk_progress_bar_new();
2181 gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR(sdb_plugin->progress_bar_system),
2182 PANGO_ELLIPSIZE_MIDDLE);
2183 g_object_ref (sdb_plugin->progress_bar_system);
2185 gtk_box_pack_start (GTK_BOX (sdb_plugin->dbv_main), sdb_plugin->dbv_notebook,
2186 TRUE, TRUE, 0);
2187 gtk_box_pack_start (GTK_BOX (sdb_plugin->dbv_main), sdb_plugin->progress_bar_project,
2188 FALSE, FALSE, 0);
2189 gtk_box_pack_start (GTK_BOX (sdb_plugin->dbv_main), sdb_plugin->progress_bar_system,
2190 FALSE, FALSE, 0);
2191 gtk_widget_show_all (sdb_plugin->dbv_main);
2193 /* Local symbols */
2194 view = symbol_db_view_new (SYMBOL_DB_VIEW_FILE, sdb_plugin->sdbe_project,
2195 sdb_plugin);
2196 gtk_notebook_append_page (GTK_NOTEBOOK (sdb_plugin->dbv_notebook),
2197 view, gtk_label_new (_("Local")));
2198 sdb_plugin->file_model =
2199 gtk_tree_view_get_model (GTK_TREE_VIEW (gtk_bin_get_child (GTK_BIN(view))));
2201 g_object_add_weak_pointer (G_OBJECT (sdb_plugin->file_model),
2202 (gpointer)&sdb_plugin->file_model);
2204 /* Global symbols */
2205 view = symbol_db_view_new (SYMBOL_DB_VIEW_PROJECT,
2206 sdb_plugin->sdbe_project,
2207 sdb_plugin);
2208 gtk_notebook_append_page (GTK_NOTEBOOK (sdb_plugin->dbv_notebook),
2209 view, gtk_label_new (_("Global" )));
2211 /* Search symbols */
2212 view = symbol_db_view_new (SYMBOL_DB_VIEW_SEARCH,
2213 sdb_plugin->sdbe_project,
2214 sdb_plugin);
2215 sdb_plugin->search_entry = symbol_db_view_get_search_entry (view);
2216 gtk_notebook_append_page (GTK_NOTEBOOK (sdb_plugin->dbv_notebook),
2217 view, gtk_label_new (_("Search" )));
2219 gtk_widget_show_all (sdb_plugin->dbv_notebook);
2221 /* setting focus to the tree_view*/
2222 gtk_notebook_set_current_page (GTK_NOTEBOOK (sdb_plugin->dbv_notebook), 0);
2224 sdb_plugin->editor_watch_id =
2225 anjuta_plugin_add_watch (plugin, IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT,
2226 value_added_current_editor,
2227 value_removed_current_editor, NULL);
2228 /* Added widgets */
2229 anjuta_shell_add_widget_custom (plugin->shell, sdb_plugin->dbv_main,
2230 "AnjutaSymbolDB", _("Symbols"),
2231 "symbol-db-plugin-icon",
2232 sdb_plugin->dbv_hbox,
2233 ANJUTA_SHELL_PLACEMENT_LEFT, NULL);
2235 /* Add action group */
2236 sdb_plugin->popup_action_group =
2237 anjuta_ui_add_action_group_entries (sdb_plugin->ui,
2238 "ActionGroupPopupSymbolDB",
2239 _("SymbolDb popup actions"),
2240 actions,
2241 G_N_ELEMENTS (actions),
2242 GETTEXT_PACKAGE, FALSE, plugin);
2244 sdb_plugin->menu_action_group =
2245 anjuta_ui_add_action_group_entries (sdb_plugin->ui,
2246 "ActionGroupEditSearchSymbolDB",
2247 _("SymbolDb menu actions"),
2248 actions_search,
2249 G_N_ELEMENTS (actions_search),
2250 GETTEXT_PACKAGE, FALSE, plugin);
2252 /* Add UI */
2253 sdb_plugin->merge_id =
2254 anjuta_ui_merge (sdb_plugin->ui, UI_FILE);
2256 /* set up project directory watch */
2257 sdb_plugin->root_watch_id = anjuta_plugin_add_watch (plugin,
2258 IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI,
2259 on_project_root_added,
2260 on_project_root_removed, NULL);
2262 /* Determine session state */
2263 g_signal_connect (plugin->shell, "load-session",
2264 G_CALLBACK (on_session_load), plugin);
2266 g_signal_connect (plugin->shell, "save-session",
2267 G_CALLBACK (on_session_save), plugin);
2269 /* be sure to hide the progress bars in case no project has been opened. */
2270 gtk_widget_hide (sdb_plugin->progress_bar_project);
2271 gtk_widget_hide (sdb_plugin->progress_bar_system);
2273 static IAnjutaSymbolField search_fields[] =
2275 IANJUTA_SYMBOL_FIELD_KIND,
2276 IANJUTA_SYMBOL_FIELD_FILE_PATH,
2277 IANJUTA_SYMBOL_FIELD_FILE_POS
2279 sdb_plugin->search_query =
2280 ianjuta_symbol_manager_create_query (IANJUTA_SYMBOL_MANAGER (sdb_plugin),
2281 IANJUTA_SYMBOL_QUERY_SEARCH,
2282 IANJUTA_SYMBOL_QUERY_DB_PROJECT,
2283 NULL);
2284 ianjuta_symbol_query_set_fields (sdb_plugin->search_query,
2285 G_N_ELEMENTS (search_fields),
2286 search_fields, NULL);
2287 return TRUE;
2290 static gboolean
2291 symbol_db_deactivate (AnjutaPlugin *plugin)
2293 SymbolDBPlugin *sdb_plugin;
2294 IAnjutaProjectManager *pm;
2296 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
2298 pm = anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin)->shell,
2299 IAnjutaProjectManager, NULL);
2303 DEBUG_PRINT ("%s", "SymbolDBPlugin: Dectivating SymbolDBPlugin plugin …");
2305 /* Unmerge UI */
2306 gtk_ui_manager_remove_ui (GTK_UI_MANAGER (sdb_plugin->ui),
2307 sdb_plugin->merge_id);
2308 gtk_ui_manager_remove_action_group (GTK_UI_MANAGER (sdb_plugin->ui),
2309 sdb_plugin->popup_action_group);
2310 gtk_ui_manager_remove_action_group (GTK_UI_MANAGER (sdb_plugin->ui),
2311 sdb_plugin->menu_action_group);
2312 g_signal_handlers_disconnect_by_func (G_OBJECT (plugin->shell),
2313 on_session_load,
2314 plugin);
2316 g_signal_handlers_disconnect_by_func (G_OBJECT (plugin->shell),
2317 on_session_save,
2318 plugin);
2320 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin->sdbs),
2321 on_system_scan_package_start,
2322 plugin);
2324 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin->sdbs),
2325 on_system_scan_package_end,
2326 plugin);
2328 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin->sdbs),
2329 on_system_single_file_scan_end,
2330 plugin);
2332 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin->sdbs),
2333 on_scan_end_manager,
2334 plugin);
2336 /* disconnect the interface ones */
2337 /* connect signals for interface to receive them */
2338 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin->sdbe_globals),
2339 G_CALLBACK (on_isymbol_manager_sys_scan_end), plugin);
2341 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin->sdbe_project),
2342 G_CALLBACK (on_isymbol_manager_prj_scan_end), plugin);
2344 g_signal_handlers_disconnect_by_func (G_OBJECT (pm),
2345 G_CALLBACK (on_project_element_added), plugin);
2347 g_signal_handlers_disconnect_by_func (G_OBJECT (pm),
2348 G_CALLBACK (on_project_element_removed), plugin);
2350 g_signal_handlers_disconnect_by_func (G_OBJECT (pm),
2351 G_CALLBACK (on_project_loaded), plugin);
2353 if (sdb_plugin->buf_update_timeout_id)
2355 g_source_remove (sdb_plugin->buf_update_timeout_id);
2356 sdb_plugin->buf_update_timeout_id = 0;
2358 if (sdb_plugin->update_timer)
2360 g_timer_destroy (sdb_plugin->update_timer);
2361 sdb_plugin->update_timer = NULL;
2364 /* destroy search query */
2365 if (sdb_plugin->search_query)
2367 g_object_unref (sdb_plugin->search_query);
2369 sdb_plugin->search_query = NULL;
2371 /* destroy objects */
2372 if (sdb_plugin->sdbe_project)
2374 DEBUG_PRINT ("Destroying project engine object. ");
2375 g_object_unref (sdb_plugin->sdbe_project);
2377 sdb_plugin->sdbe_project = NULL;
2379 PackageScanData *pkg_scan_data;
2380 while ((pkg_scan_data = g_async_queue_try_pop (sdb_plugin->global_scan_aqueue)) != NULL)
2382 g_free (pkg_scan_data->package_name);
2383 g_free (pkg_scan_data->package_version);
2384 g_free (pkg_scan_data);
2387 g_async_queue_unref (sdb_plugin->global_scan_aqueue);
2388 sdb_plugin->global_scan_aqueue = NULL;
2390 /* this must be done *before* destroying sdbe_globals */
2391 g_object_unref (sdb_plugin->sdbs);
2392 sdb_plugin->sdbs = NULL;
2394 g_free (sdb_plugin->current_scanned_package);
2395 sdb_plugin->current_scanned_package = NULL;
2397 DEBUG_PRINT ("Destroying global engine object. ");
2398 g_object_unref (sdb_plugin->sdbe_globals);
2399 sdb_plugin->sdbe_globals = NULL;
2401 g_free (sdb_plugin->project_opened);
2402 sdb_plugin->project_opened = NULL;
2404 if (sdb_plugin->buffer_update_files)
2406 g_ptr_array_unref (sdb_plugin->buffer_update_files);
2407 sdb_plugin->buffer_update_files = NULL;
2410 if (sdb_plugin->buffer_update_ids)
2412 g_ptr_array_unref (sdb_plugin->buffer_update_ids);
2413 sdb_plugin->buffer_update_ids = NULL;
2416 /* Ensure all editor cached info are released */
2417 if (sdb_plugin->editor_connected)
2419 g_hash_table_foreach (sdb_plugin->editor_connected,
2420 on_editor_foreach_disconnect, plugin);
2421 g_hash_table_destroy (sdb_plugin->editor_connected);
2422 sdb_plugin->editor_connected = NULL;
2423 g_hash_table_destroy (sdb_plugin->editors);
2424 sdb_plugin->editors = NULL;
2427 // FIXME
2428 g_tree_destroy (sdb_plugin->proc_id_tree);
2430 /* Remove watches */
2431 anjuta_plugin_remove_watch (plugin, sdb_plugin->root_watch_id, FALSE);
2432 anjuta_plugin_remove_watch (plugin, sdb_plugin->editor_watch_id, TRUE);
2434 /* Remove UI */
2435 anjuta_ui_unmerge (sdb_plugin->ui, sdb_plugin->merge_id);
2437 /* Remove widgets: Widgets will be destroyed when dbv_main is removed */
2438 anjuta_shell_remove_widget (plugin->shell, sdb_plugin->dbv_main, NULL);
2440 sdb_plugin->root_watch_id = 0;
2441 sdb_plugin->editor_watch_id = 0;
2442 sdb_plugin->merge_id = 0;
2443 sdb_plugin->dbv_notebook = NULL;
2444 sdb_plugin->progress_bar_project = NULL;
2445 sdb_plugin->progress_bar_system = NULL;
2446 return TRUE;
2449 static void
2450 symbol_db_finalize (GObject *obj)
2452 DEBUG_PRINT ("Symbol-DB finalize");
2453 /* Finalization codes here */
2454 G_OBJECT_CLASS (parent_class)->finalize (obj);
2457 static void
2458 symbol_db_dispose (GObject *obj)
2460 SymbolDBPlugin *plugin = (SymbolDBPlugin*)obj;
2461 DEBUG_PRINT ("Symbol-DB dispose");
2462 /* Disposition codes */
2463 g_object_unref (plugin->settings);
2466 G_OBJECT_CLASS (parent_class)->dispose (obj);
2469 static void
2470 symbol_db_instance_init (GObject *obj)
2472 SymbolDBPlugin *plugin = (SymbolDBPlugin*)obj;
2474 plugin->files_count_project_done = 0;
2475 plugin->files_count_project = 0;
2477 plugin->files_count_system_done = 0;
2478 plugin->files_count_system = 0;
2479 plugin->current_scanned_package = NULL;
2480 plugin->settings = g_settings_new (PREF_SCHEMA);
2483 static void
2484 symbol_db_class_init (GObjectClass *klass)
2486 AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
2488 GObjectClass *object_class = G_OBJECT_CLASS (klass);
2489 parent_class = g_type_class_peek_parent (klass);
2491 plugin_class->activate = symbol_db_activate;
2492 plugin_class->deactivate = symbol_db_deactivate;
2493 klass->finalize = symbol_db_finalize;
2494 klass->dispose = symbol_db_dispose;
2496 signals[PROJECT_IMPORT_END]
2497 = g_signal_new ("project-import-end",
2498 G_OBJECT_CLASS_TYPE (object_class),
2499 G_SIGNAL_RUN_FIRST,
2500 G_STRUCT_OFFSET (SymbolDBPluginClass, project_import_end),
2501 NULL, NULL,
2502 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2504 signals[GLOBALS_IMPORT_END]
2505 = g_signal_new ("globals-import-end",
2506 G_OBJECT_CLASS_TYPE (object_class),
2507 G_SIGNAL_RUN_FIRST,
2508 G_STRUCT_OFFSET (SymbolDBPluginClass, globals_import_end),
2509 NULL, NULL,
2510 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2513 static void
2514 on_prefs_buffer_update_toggled (GtkToggleButton* button,
2515 gpointer user_data)
2517 SymbolDBPlugin *sdb_plugin;
2518 gboolean sensitive;
2520 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (user_data);
2522 sensitive = gtk_toggle_button_get_active (button);
2524 DEBUG_PRINT ("on_prefs_buffer_update_toggled () %d", sensitive);
2526 if (sensitive == FALSE)
2528 if (sdb_plugin->buf_update_timeout_id)
2529 g_source_remove (sdb_plugin->buf_update_timeout_id);
2530 sdb_plugin->buf_update_timeout_id = 0;
2532 else
2534 if (sdb_plugin->buf_update_timeout_id == 0)
2535 sdb_plugin->buf_update_timeout_id =
2536 g_timeout_add_seconds (TIMEOUT_INTERVAL_SYMBOLS_UPDATE,
2537 on_editor_buffer_symbols_update_timeout,
2538 sdb_plugin);
2542 static void
2543 ipreferences_merge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** e)
2545 DEBUG_PRINT ("%s", "SymbolDB: ipreferences_merge");
2546 SymbolDBPlugin *sdb_plugin;
2547 GtkWidget *buf_up_widget;
2548 GError* error = NULL;
2550 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (ipref);
2552 if (sdb_plugin->prefs_bxml == NULL)
2554 /* Create the preferences page */
2555 sdb_plugin->prefs_bxml = gtk_builder_new ();
2556 if (!gtk_builder_add_from_file (sdb_plugin->prefs_bxml, BUILDER_FILE, &error))
2558 g_warning ("Couldn't load builder file: %s", error->message);
2559 g_error_free(error);
2563 anjuta_preferences_add_from_builder (prefs,
2564 sdb_plugin->prefs_bxml,
2565 sdb_plugin->settings,
2566 BUILDER_ROOT,
2567 _("Symbol Database"),
2568 ICON_FILE);
2570 buf_up_widget = GTK_WIDGET (gtk_builder_get_object (sdb_plugin->prefs_bxml,
2571 PREFS_BUFFER_UPDATE));
2573 g_signal_connect (buf_up_widget, "toggled",
2574 G_CALLBACK (on_prefs_buffer_update_toggled),
2575 sdb_plugin);
2578 static void
2579 ipreferences_unmerge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** e)
2581 SymbolDBPlugin *sdb_plugin;
2583 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (ipref);
2585 anjuta_preferences_remove_page(prefs, _("Symbol Database"));
2586 g_object_unref (sdb_plugin->prefs_bxml);
2587 sdb_plugin->prefs_bxml = NULL;
2590 static void
2591 ipreferences_iface_init(IAnjutaPreferencesIface* iface)
2593 DEBUG_PRINT ("%s", "SymbolDB: ipreferences_iface_init");
2594 iface->merge = ipreferences_merge;
2595 iface->unmerge = ipreferences_unmerge;
2598 /* IAnjutaSymbolManager implementation */
2599 static IAnjutaSymbolQuery*
2600 isymbol_manager_create_query (IAnjutaSymbolManager *isymbol_manager,
2601 IAnjutaSymbolQueryName query_name,
2602 IAnjutaSymbolQueryDb db,
2603 GError **err)
2605 SymbolDBPlugin *sdb_plugin;
2606 SymbolDBQuery *query;
2608 g_return_val_if_fail (isymbol_manager != NULL, NULL);
2610 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager);
2612 query = symbol_db_query_new (sdb_plugin->sdbe_globals,
2613 sdb_plugin->sdbe_project,
2614 query_name,
2616 db == IANJUTA_SYMBOL_QUERY_DB_PROJECT ?
2617 NULL : /* FIXME */ NULL);
2618 return IANJUTA_SYMBOL_QUERY (query);
2621 static gboolean
2622 isymbol_manager_add_package (IAnjutaSymbolManager *isymbol_manager,
2623 const gchar* pkg_name,
2624 const gchar* pkg_version,
2625 GList* files,
2626 GError **err)
2628 SymbolDBPlugin *sdb_plugin;
2629 IAnjutaLanguage *lang_manager;
2630 GPtrArray *files_array;
2631 PackageScanData *pkg_scan_data;
2634 g_return_val_if_fail (isymbol_manager != NULL, FALSE);
2636 /* DEBUG */
2637 GList *node;
2638 node = files;
2639 while (node != NULL)
2641 node = node->next;
2644 /* FIXME: pkg_version comes with \n at the end. This should be avoided */
2645 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager);
2646 lang_manager = anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin)->shell, IAnjutaLanguage,
2647 NULL);
2649 if (symbol_db_engine_add_new_project (sdb_plugin->sdbe_globals, NULL, pkg_name,
2650 pkg_version) == FALSE)
2652 return FALSE;
2655 files_array = anjuta_util_convert_string_list_to_array (files);
2657 pkg_scan_data = g_new0 (PackageScanData, 1);
2659 g_async_queue_push (sdb_plugin->global_scan_aqueue, pkg_scan_data);
2660 pkg_scan_data->files_length = g_list_length (files);
2661 pkg_scan_data->package_name = g_strdup (pkg_name);
2662 pkg_scan_data->package_version = g_strdup (pkg_version);
2664 pkg_scan_data->proc_id = symbol_db_engine_add_new_files_async (sdb_plugin->sdbe_globals, lang_manager,
2665 pkg_name, pkg_version, files_array);
2667 g_ptr_array_unref (files_array);
2669 return TRUE;
2672 /* FIXME: do this thread safe */
2673 static gboolean
2674 isymbol_manager_activate_package (IAnjutaSymbolManager *isymbol_manager,
2675 const gchar *pkg_name,
2676 const gchar *pkg_version,
2677 GError **err)
2679 SymbolDBPlugin *sdb_plugin;
2681 g_return_val_if_fail (isymbol_manager != NULL, FALSE);
2683 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager);
2685 if (symbol_db_engine_project_exists (sdb_plugin->sdbe_globals, pkg_name,
2686 pkg_version) == TRUE)
2688 /* FIXME: Activate package in database */
2689 DEBUG_PRINT ("STUB");
2690 return TRUE;
2693 /* user should add a package before activating it. */
2694 return FALSE;
2697 static void
2698 isymbol_manager_deactivate_package (IAnjutaSymbolManager *isymbol_manager,
2699 const gchar *pkg_name,
2700 const gchar *pkg_version,
2701 GError **err)
2703 SymbolDBPlugin *sdb_plugin;
2705 g_return_if_fail (isymbol_manager != NULL);
2707 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager);
2709 if (symbol_db_engine_project_exists (sdb_plugin->sdbe_globals, pkg_name,
2710 pkg_version) == TRUE)
2712 DEBUG_PRINT ("STUB");
2713 /* FIXME: deactivate package in database */
2717 static void
2718 isymbol_manager_deactivate_all (IAnjutaSymbolManager *isymbol_manager,
2719 GError **err)
2721 #if 0
2722 SymbolDBPlugin *sdb_plugin;
2724 g_return_if_fail (isymbol_manager != NULL);
2726 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager);
2727 #endif
2728 /* FIXME: deactivate all packages in database */
2729 DEBUG_PRINT ("STUB");
2732 static void
2733 isymbol_manager_iface_init (IAnjutaSymbolManagerIface *iface)
2735 iface->create_query = isymbol_manager_create_query;
2736 iface->activate_package = isymbol_manager_activate_package;
2737 iface->deactivate_package = isymbol_manager_deactivate_package;
2738 iface->deactivate_all = isymbol_manager_deactivate_all;
2739 iface->add_package = isymbol_manager_add_package;
2742 ANJUTA_PLUGIN_BEGIN (SymbolDBPlugin, symbol_db);
2743 ANJUTA_PLUGIN_ADD_INTERFACE (isymbol_manager, IANJUTA_TYPE_SYMBOL_MANAGER);
2744 ANJUTA_PLUGIN_ADD_INTERFACE(ipreferences, IANJUTA_TYPE_PREFERENCES);
2745 ANJUTA_PLUGIN_END;
2747 ANJUTA_SIMPLE_PLUGIN (SymbolDBPlugin, symbol_db);