language-support-cpp-java: upgraded preferences page with PkgConfigChooser.
[anjuta.git] / plugins / symbol-db / plugin.c
blob0e0141913c40e1c1bac486db29e8ba7718686721
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/interfaces/ianjuta-document-manager.h>
32 #include <libanjuta/interfaces/ianjuta-symbol-manager.h>
33 #include <libanjuta/interfaces/ianjuta-symbol.h>
34 #include <libanjuta/interfaces/ianjuta-project-manager.h>
35 #include <libanjuta/interfaces/ianjuta-file-manager.h>
36 #include <libanjuta/interfaces/ianjuta-file.h>
37 #include <libanjuta/interfaces/ianjuta-file-loader.h>
38 #include <libanjuta/interfaces/ianjuta-editor.h>
39 #include <libanjuta/interfaces/ianjuta-markable.h>
40 #include <libanjuta/interfaces/ianjuta-language.h>
41 #include <libanjuta/interfaces/ianjuta-iterable.h>
42 #include <libanjuta/interfaces/ianjuta-preferences.h>
44 #include "plugin.h"
45 #include "symbol-db-engine.h"
46 #include "symbol-db-prefs.h"
47 #include "symbol-db-views.h"
49 #define ICON_FILE "anjuta-symbol-db-plugin-48.png"
50 #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta-symbol-db-plugin.xml"
52 #define TIMEOUT_INTERVAL_SYMBOLS_UPDATE 10
53 #define TIMEOUT_SECONDS_AFTER_LAST_TIP 5
55 #define PROJECT_GLOBALS "/"
56 #define SESSION_SECTION "SymbolDB"
57 #define SESSION_KEY "SystemPackages"
59 #define ANJUTA_PIXMAP_GOTO_DECLARATION "element-interface"
60 #define ANJUTA_PIXMAP_GOTO_IMPLEMENTATION "element-method"
62 #define ANJUTA_STOCK_GOTO_DECLARATION "element-interface"
63 #define ANJUTA_STOCK_GOTO_IMPLEMENTATION "element-method"
65 static gpointer parent_class;
67 /* signals */
68 enum
70 PROJECT_IMPORT_END,
71 GLOBALS_IMPORT_END,
72 LAST_SIGNAL
75 typedef enum
77 TASK_IMPORT_PROJECT = 1,
78 TASK_IMPORT_PROJECT_AFTER_ABORT,
79 TASK_BUFFER_UPDATE,
80 TASK_ELEMENT_ADDED,
81 TASK_OFFLINE_CHANGES,
82 TASK_PROJECT_UPDATE,
83 TASK_FILE_UPDATE
84 } ProcTask;
86 static unsigned int signals[LAST_SIGNAL] = { 0 };
88 static void
89 register_stock_icons (AnjutaPlugin *plugin)
91 static gboolean registered = FALSE;
93 if (registered)
94 return;
95 registered = TRUE;
97 /* Register stock icons */
98 BEGIN_REGISTER_ICON (plugin);
99 REGISTER_ICON (ICON_FILE, "symbol-db-plugin-icon");
100 REGISTER_ICON_FULL (ANJUTA_PIXMAP_GOTO_DECLARATION, ANJUTA_STOCK_GOTO_DECLARATION);
101 REGISTER_ICON_FULL (ANJUTA_PIXMAP_GOTO_IMPLEMENTATION, ANJUTA_STOCK_GOTO_IMPLEMENTATION);
102 END_REGISTER_ICON;
105 static void
106 goto_file_line (AnjutaPlugin *plugin, const gchar *filename, gint lineno)
108 IAnjutaDocumentManager *docman;
109 GFile* file;
111 g_return_if_fail (filename != NULL);
113 DEBUG_PRINT ("going to: file %s, line %d", filename, lineno);
115 /* Go to file and line number */
116 docman = anjuta_shell_get_interface (plugin->shell, IAnjutaDocumentManager,
117 NULL);
118 file = g_file_new_for_path (filename);
119 ianjuta_document_manager_goto_file_line (docman, file, lineno, NULL);
121 g_object_unref (file);
124 /* Find an implementation (if impl == TRUE) or declaration (if impl == FALSE)
125 * from the given symbol iterator.
126 * If current_document != NULL it prefers matches from the currently open document
128 static gchar *
129 find_file_line (IAnjutaIterable *iterator, gboolean impl, const gchar *current_document,
130 gint *line)
132 gchar *path = NULL;
133 gint _line = -1;
137 const gchar *symbol_kind;
138 gboolean is_decl;
139 IAnjutaSymbol *iter_node = IANJUTA_SYMBOL (iterator);
141 if (iter_node == NULL)
143 /* not found or some error occurred */
144 break;
147 symbol_kind = ianjuta_symbol_get_string (iter_node, IANJUTA_SYMBOL_FIELD_KIND, NULL);
148 is_decl = g_strcmp0 (symbol_kind, "prototype") == 0 ||
149 g_strcmp0 (symbol_kind, "interface") == 0;
151 if (is_decl == !impl)
153 GFile *file;
154 gchar *_path;
155 file = ianjuta_symbol_get_file (iter_node, NULL);
156 /* if the path matches the current document we return immidiately */
157 _path = g_file_get_path (file);
158 g_object_unref (file);
159 if (!current_document || g_strcmp0 (_path, current_document) == 0)
161 *line = ianjuta_symbol_get_int (iter_node,
162 IANJUTA_SYMBOL_FIELD_FILE_POS,
163 NULL);
164 g_free (path);
166 return _path;
168 /* we store the first match incase there is no match against the current document */
169 else if (_line == -1)
171 path = _path;
172 _line = ianjuta_symbol_get_int (iter_node,
173 IANJUTA_SYMBOL_FIELD_FILE_POS,
174 NULL);
176 else
178 g_free (_path);
181 } while (ianjuta_iterable_next (iterator, NULL) == TRUE);
183 if (_line != -1)
184 *line = _line;
186 return path;
189 static void
190 goto_file_tag (SymbolDBPlugin *sdb_plugin, const gchar *word,
191 gboolean prefer_implementation)
193 IAnjutaIterable *iterator;
194 gchar *path = NULL;
195 gint line;
196 gint i;
197 gboolean found = FALSE;
198 SymbolDBEngine *engine;
200 for (i = 0; i < 2; i++)
202 if (i == 0)
204 engine = sdb_plugin->sdbe_project;
206 else
208 engine = sdb_plugin->sdbe_globals;
211 iterator = NULL;
212 if (symbol_db_engine_is_connected (engine))
214 iterator = ianjuta_symbol_query_search (sdb_plugin->search_query,
215 word, NULL);
218 if (iterator != NULL && ianjuta_iterable_get_length (iterator, NULL) > 0)
220 gchar *current_document = NULL;
221 /* FIXME: namespaces are not handled here, but they should. */
223 if (IANJUTA_IS_FILE (sdb_plugin->current_editor))
225 GFile *file;
227 if ((file = ianjuta_file_get_file (IANJUTA_FILE (sdb_plugin->current_editor),
228 NULL)))
230 current_document = g_file_get_path (file);
231 g_object_unref (file);
235 path = find_file_line (iterator, prefer_implementation, current_document, &line);
236 if (!path)
238 /* reset iterator */
239 ianjuta_iterable_first (iterator, NULL);
240 path = find_file_line (iterator, !prefer_implementation, current_document,
241 &line);
244 if (path)
246 goto_file_line (ANJUTA_PLUGIN (sdb_plugin), path, line);
247 g_free (path);
248 found = TRUE;
251 g_free (current_document);
254 if (iterator)
255 g_object_unref (iterator);
257 /* have we found it in the project db? */
258 if (found)
259 break;
263 static void
264 on_goto_file_tag_impl_activate (GtkAction *action, SymbolDBPlugin *sdb_plugin)
266 IAnjutaEditor *ed;
267 gchar *word;
269 if (sdb_plugin->current_editor)
271 ed = IANJUTA_EDITOR (sdb_plugin->current_editor);
272 word = ianjuta_editor_get_current_word (ed, NULL);
273 if (word)
275 goto_file_tag (sdb_plugin, word, TRUE);
276 g_free (word);
281 static void
282 on_goto_file_tag_decl_activate (GtkAction *action, SymbolDBPlugin *sdb_plugin)
284 IAnjutaEditor *ed;
285 gchar *word;
287 if (sdb_plugin->current_editor)
289 ed = IANJUTA_EDITOR (sdb_plugin->current_editor);
290 word = ianjuta_editor_get_current_word (ed, NULL);
291 if (word)
293 goto_file_tag (sdb_plugin, word, FALSE);
294 g_free (word);
299 static void
300 on_find_symbol (GtkAction *action, SymbolDBPlugin *sdb_plugin)
302 anjuta_shell_present_widget(ANJUTA_PLUGIN(sdb_plugin)->shell,
303 sdb_plugin->dbv_main, NULL);
305 gtk_notebook_set_current_page (GTK_NOTEBOOK(sdb_plugin->dbv_notebook), 2);
306 gtk_widget_grab_focus (GTK_WIDGET (sdb_plugin->search_entry));
309 static GtkActionEntry actions[] =
311 { "ActionMenuGoto", NULL, N_("_Go to"), NULL, NULL, NULL},
313 "ActionSymbolDBGotoDecl",
314 ANJUTA_STOCK_GOTO_DECLARATION,
315 N_("Tag De_claration"),
316 "<shift><control>d",
317 N_("Go to symbol declaration"),
318 G_CALLBACK (on_goto_file_tag_decl_activate)
321 "ActionSymbolDBGotoImpl",
322 ANJUTA_STOCK_GOTO_IMPLEMENTATION,
323 /* Translators: Go to the line where the tag is implemented */
324 N_("Tag _Implementation"),
325 "<control>d",
326 N_("Go to symbol definition"),
327 G_CALLBACK (on_goto_file_tag_impl_activate)
331 static GtkActionEntry actions_search[] = {
333 "ActionEditSearchFindSymbol", GTK_STOCK_FIND, N_("_Find Symbol…"),
334 "<control>l", N_("Find Symbol"),
335 G_CALLBACK (on_find_symbol)
339 static gboolean
340 on_editor_buffer_symbols_update_timeout (gpointer user_data)
342 SymbolDBPlugin *sdb_plugin;
343 IAnjutaEditor *ed;
344 gchar *current_buffer = NULL;
345 gsize buffer_size = 0;
346 gdouble seconds_elapsed;
347 GFile* file;
348 gchar * local_path;
349 GPtrArray *real_files_list;
350 GPtrArray *text_buffers;
351 GPtrArray *buffer_sizes;
352 gint i;
353 gint proc_id ;
355 g_return_val_if_fail (user_data != NULL, FALSE);
357 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (user_data);
359 if (sdb_plugin->current_editor == NULL)
360 return FALSE;
362 /* check the timer. If it's elapsed enought time since the last time the user
363 * typed in something, than proceed with updating, elsewhere don't do nothing
365 if (sdb_plugin->update_timer == NULL)
366 return TRUE;
368 seconds_elapsed = g_timer_elapsed (sdb_plugin->update_timer, NULL);
370 if (seconds_elapsed < TIMEOUT_SECONDS_AFTER_LAST_TIP)
371 return TRUE;
374 /* we won't proceed with the updating of the symbols if we didn't type in
375 anything */
376 if (sdb_plugin->need_symbols_update == FALSE)
377 return TRUE;
379 if (sdb_plugin->current_editor)
381 ed = IANJUTA_EDITOR (sdb_plugin->current_editor);
383 buffer_size = ianjuta_editor_get_length (ed, NULL);
384 current_buffer = ianjuta_editor_get_text_all (ed, NULL);
386 file = ianjuta_file_get_file (IANJUTA_FILE (ed), NULL);
388 else
389 return FALSE;
391 if (file == NULL)
392 return FALSE;
394 /* take the path reference */
395 local_path = g_file_get_path (file);
397 /* ok that's good. Let's have a last check: is the current file present
398 * on the buffer_update_files?
400 for (i = 0; i < sdb_plugin->buffer_update_files->len; i++)
402 if (g_strcmp0 (g_ptr_array_index (sdb_plugin->buffer_update_files, i),
403 local_path) == 0)
405 /* hey we found it */
406 /* something is already scanning this buffer file. Drop the procedure now. */
407 DEBUG_PRINT ("something is already scanning the file %s", local_path);
408 return FALSE;
412 real_files_list = g_ptr_array_new_with_free_func (g_free);
413 g_ptr_array_add (real_files_list, local_path);
415 text_buffers = g_ptr_array_new ();
416 g_ptr_array_add (text_buffers, current_buffer);
418 buffer_sizes = g_ptr_array_new ();
419 g_ptr_array_add (buffer_sizes, GINT_TO_POINTER (buffer_size));
422 proc_id = 0;
423 if (symbol_db_engine_is_connected (sdb_plugin->sdbe_project))
425 proc_id = symbol_db_engine_update_buffer_symbols (sdb_plugin->sdbe_project,
426 sdb_plugin->project_opened,
427 real_files_list,
428 text_buffers,
429 buffer_sizes);
432 if (proc_id > 0)
434 /* good. All is ready for a buffer scan. Add the file_scan into the arrays */
435 gchar * local_path_dup = g_strdup (local_path);
436 g_ptr_array_add (sdb_plugin->buffer_update_files, local_path_dup);
437 /* add the id too */
438 g_ptr_array_add (sdb_plugin->buffer_update_ids, GINT_TO_POINTER (proc_id));
440 /* add a task so that scan_end_manager can manage this */
441 g_tree_insert (sdb_plugin->proc_id_tree, GINT_TO_POINTER (proc_id),
442 GINT_TO_POINTER (TASK_BUFFER_UPDATE));
445 g_ptr_array_unref (real_files_list);
446 g_free (current_buffer);
447 g_object_unref (file);
449 /* no need to free local_path, it'll be automatically freed later by the buffer_update
450 * function */
452 sdb_plugin->need_symbols_update = FALSE;
454 return proc_id > 0 ? TRUE : FALSE;
457 static void
458 on_editor_buffer_symbol_update_scan_end (SymbolDBEngine *dbe, gint process_id,
459 gpointer data)
461 SymbolDBPlugin *sdb_plugin;
462 gint i;
464 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (data);
466 /* search for the proc id */
467 for (i = 0; i < sdb_plugin->buffer_update_ids->len; i++)
469 if (g_ptr_array_index (sdb_plugin->buffer_update_ids, i) == GINT_TO_POINTER (process_id))
471 gchar *str;
472 /* hey we found it */
473 /* remove both the items */
474 g_ptr_array_remove_index (sdb_plugin->buffer_update_ids, i);
476 str = (gchar*)g_ptr_array_remove_index (sdb_plugin->buffer_update_files,
481 /* was the updating of view-locals symbols blocked while we were scanning?
482 * e.g. was the editor switched? */
483 if (sdb_plugin->buffer_update_semaphore == TRUE)
485 GFile *file;
486 gchar *local_path;
487 gboolean tags_update;
488 if (!IANJUTA_IS_EDITOR (sdb_plugin->current_editor))
489 return;
491 file = ianjuta_file_get_file (IANJUTA_FILE (sdb_plugin->current_editor),
492 NULL);
494 if (file == NULL)
495 return;
497 local_path = g_file_get_path (file);
499 if (local_path == NULL)
501 g_critical ("local_path == NULL");
502 return;
505 /* add a default timeout to the updating of buffer symbols */
506 tags_update = anjuta_preferences_get_bool (sdb_plugin->prefs, BUFFER_AUTOSCAN);
508 if (tags_update)
510 sdb_plugin->buf_update_timeout_id =
511 g_timeout_add_seconds (TIMEOUT_INTERVAL_SYMBOLS_UPDATE,
512 on_editor_buffer_symbols_update_timeout,
513 sdb_plugin);
516 g_free (local_path);
517 sdb_plugin->buffer_update_semaphore = FALSE;
521 static void
522 on_editor_destroy (SymbolDBPlugin *sdb_plugin, IAnjutaEditor *editor)
524 const gchar *uri;
525 DEBUG_PRINT ("%s", "on_editor_destroy ()");
526 if (!sdb_plugin->editor_connected)
528 DEBUG_PRINT ("%s", "on_editor_destroy (): returning….");
529 return;
532 uri = g_hash_table_lookup (sdb_plugin->editor_connected, G_OBJECT (editor));
533 g_hash_table_remove (sdb_plugin->editor_connected, G_OBJECT (editor));
535 if (g_hash_table_size (sdb_plugin->editor_connected) <= 0)
537 DEBUG_PRINT ("%s", "displaying nothing…");
538 g_object_set (sdb_plugin->file_model, "file-path", NULL, NULL);
542 static void
543 on_editor_update_ui (IAnjutaEditor *editor, SymbolDBPlugin *sdb_plugin)
545 g_timer_reset (sdb_plugin->update_timer);
548 static void
549 on_char_added (IAnjutaEditor *editor, IAnjutaIterable *position, gchar ch,
550 SymbolDBPlugin *sdb_plugin)
552 g_timer_reset (sdb_plugin->update_timer);
554 /* Update when the user enters a newline */
555 if (ch == '\n')
556 sdb_plugin->need_symbols_update = TRUE;
559 static void
560 on_editor_saved (IAnjutaEditor *editor, GFile* file,
561 SymbolDBPlugin *sdb_plugin)
563 const gchar *old_uri;
564 gchar *local_filename;
565 gchar *saved_uri;
566 GPtrArray *files_array;
567 gint proc_id;
568 gint i;
570 local_filename = g_file_get_path (file);
571 /* Verify that it's local file */
572 g_return_if_fail (local_filename != NULL);
574 saved_uri = g_file_get_uri (file);
576 for (i = 0; i < sdb_plugin->buffer_update_files->len; i++)
578 if (g_strcmp0 (g_ptr_array_index (sdb_plugin->buffer_update_files, i),
579 local_filename) == 0)
581 DEBUG_PRINT ("already scanning");
582 /* something is already scanning this buffer file. Drop the procedure now. */
583 return;
587 files_array = g_ptr_array_new();
588 g_ptr_array_add (files_array, local_filename);
589 /* no need to free local_filename now */
591 if (!sdb_plugin->editor_connected)
592 return;
594 old_uri = g_hash_table_lookup (sdb_plugin->editor_connected, editor);
596 if (old_uri && strlen (old_uri) <= 0)
597 old_uri = NULL;
599 /* files_array will be freed once updating has taken place */
600 proc_id = 0;
601 if (symbol_db_engine_is_connected (sdb_plugin->sdbe_project))
603 proc_id = symbol_db_engine_update_files_symbols (sdb_plugin->sdbe_project,
604 sdb_plugin->project_root_dir, files_array, TRUE);
607 if (proc_id > 0)
609 /* add a task so that scan_end_manager can manage this */
610 g_tree_insert (sdb_plugin->proc_id_tree, GINT_TO_POINTER (proc_id),
611 GINT_TO_POINTER (TASK_FILE_UPDATE));
614 g_hash_table_insert (sdb_plugin->editor_connected, editor,
615 g_strdup (saved_uri));
617 /* if we saved it we shouldn't update a second time */
618 sdb_plugin->need_symbols_update = FALSE;
620 on_editor_update_ui (editor, sdb_plugin);
621 g_free (saved_uri);
624 static void
625 value_added_current_editor (AnjutaPlugin *plugin, const char *name,
626 const GValue *value, gpointer data)
628 gchar *uri;
629 gboolean tags_update;
630 GFile* file;
631 gchar *local_path;
632 GObject *editor;
633 SymbolDBPlugin *sdb_plugin;
635 editor = g_value_get_object (value);
636 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
637 if (sdb_plugin->session_loading)
639 return;
641 else
642 DEBUG_PRINT ("%s", "Updating symbols");
644 if (!sdb_plugin->editor_connected)
646 sdb_plugin->editor_connected = g_hash_table_new_full (g_direct_hash,
647 g_direct_equal,
648 NULL, g_free);
650 sdb_plugin->current_editor = editor;
652 if (!IANJUTA_IS_EDITOR (editor))
653 return;
655 file = ianjuta_file_get_file (IANJUTA_FILE (editor), NULL);
657 if (file == NULL)
658 return;
660 local_path = g_file_get_path (file);
661 uri = g_file_get_uri (file);
663 if (local_path == NULL)
665 g_critical ("local_path == NULL");
666 return;
669 /* we can have a weird behaviour here if we're not paying the right attention:
670 * A timeout scan could have been launched and a millisecond later the user could
671 * have switched editor: we'll be getting the symbol inserted in the previous
672 * editor into the new one's view.
674 if (sdb_plugin->buffer_update_files->len > 0)
676 sdb_plugin->buffer_update_semaphore = TRUE;
678 else
680 g_object_set (sdb_plugin->file_model, "file-path", local_path, NULL);
682 /* add a default timeout to the updating of buffer symbols */
683 tags_update = anjuta_preferences_get_bool (sdb_plugin->prefs, BUFFER_AUTOSCAN);
685 if (tags_update)
687 sdb_plugin->buf_update_timeout_id =
688 g_timeout_add_seconds (TIMEOUT_INTERVAL_SYMBOLS_UPDATE,
689 on_editor_buffer_symbols_update_timeout,
690 plugin);
694 if (g_hash_table_lookup (sdb_plugin->editor_connected, editor) == NULL)
696 g_object_weak_ref (G_OBJECT (editor),
697 (GWeakNotify) (on_editor_destroy),
698 sdb_plugin);
699 if (uri)
701 g_hash_table_insert (sdb_plugin->editor_connected, editor,
702 g_strdup (uri));
704 else
706 g_hash_table_insert (sdb_plugin->editor_connected, editor,
707 g_strdup (""));
710 g_signal_connect (G_OBJECT (editor), "saved",
711 G_CALLBACK (on_editor_saved),
712 sdb_plugin);
713 g_signal_connect (G_OBJECT (editor), "char-added",
714 G_CALLBACK (on_char_added),
715 sdb_plugin);
716 g_signal_connect (G_OBJECT(editor), "update_ui",
717 G_CALLBACK (on_editor_update_ui),
718 sdb_plugin);
720 g_free (uri);
721 g_free (local_path);
723 sdb_plugin->need_symbols_update = FALSE;
726 static void
727 on_editor_foreach_disconnect (gpointer key, gpointer value, gpointer user_data)
729 g_signal_handlers_disconnect_by_func (G_OBJECT(key),
730 G_CALLBACK (on_editor_saved),
731 user_data);
732 g_signal_handlers_disconnect_by_func (G_OBJECT(key),
733 G_CALLBACK (on_editor_update_ui),
734 user_data);
735 g_signal_handlers_disconnect_by_func (G_OBJECT(key),
736 G_CALLBACK (on_char_added),
737 user_data);
738 g_object_weak_unref (G_OBJECT(key),
739 (GWeakNotify) (on_editor_destroy),
740 user_data);
743 static void
744 value_removed_current_editor (AnjutaPlugin *plugin,
745 const char *name, gpointer data)
747 SymbolDBPlugin *sdb_plugin;
749 sdb_plugin = (SymbolDBPlugin *) plugin;
751 DEBUG_PRINT ("%s", "value_removed_current_editor ()");
752 /* let's remove the timeout for symbols refresh */
753 if (sdb_plugin->buf_update_timeout_id)
754 g_source_remove (sdb_plugin->buf_update_timeout_id);
755 sdb_plugin->buf_update_timeout_id = 0;
756 sdb_plugin->need_symbols_update = FALSE;
758 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
759 sdb_plugin->current_editor = NULL;
763 * Perform the real add to the db and also checks that no dups are inserted.
764 * Return the real number of files added.
766 static gint
767 do_add_new_files (SymbolDBPlugin *sdb_plugin, const GPtrArray *sources_array,
768 ProcTask task)
770 GPtrArray* languages_array = NULL;
771 GPtrArray* to_scan_array = NULL;
772 GHashTable* check_unique_file_hash = NULL;
773 IAnjutaLanguage* lang_manager;
774 AnjutaPlugin *plugin;
775 gint added_num;
776 gint i;
778 plugin = ANJUTA_PLUGIN (sdb_plugin);
780 /* create array of languages and the wannabe scanned files */
781 languages_array = g_ptr_array_new_with_free_func (g_free);
782 to_scan_array = g_ptr_array_new_with_free_func (g_free);
784 /* to speed the things up we must avoid the dups */
785 check_unique_file_hash = g_hash_table_new_full (g_str_hash,
786 g_str_equal, NULL, NULL);
788 lang_manager = anjuta_shell_get_interface (plugin->shell, IAnjutaLanguage,
789 NULL);
791 if (!lang_manager)
793 g_critical ("LanguageManager not found");
794 return -1;
797 for (i=0; i < sources_array->len; i++)
799 const gchar *file_mime;
800 const gchar *lang;
801 const gchar *local_filename;
802 GFile *gfile;
803 GFileInfo *gfile_info;
804 IAnjutaLanguageId lang_id;
806 if ( (local_filename = g_ptr_array_index (sources_array, i)) == NULL)
807 continue;
809 if ((gfile = g_file_new_for_path (local_filename)) == NULL)
810 continue;
812 gfile_info = g_file_query_info (gfile,
813 "standard::content-type",
814 G_FILE_QUERY_INFO_NONE,
815 NULL,
816 NULL);
817 if (gfile_info == NULL)
819 g_object_unref (gfile);
820 continue;
823 /* check if it's already present in the list. This avoids
824 * duplicates.
826 if (g_hash_table_lookup (check_unique_file_hash,
827 local_filename) == NULL)
829 g_hash_table_insert (check_unique_file_hash,
830 (gpointer)local_filename,
831 (gpointer)local_filename);
833 else
835 /* you're a dup! we don't want you */
836 continue;
839 file_mime = g_file_info_get_attribute_string (gfile_info,
840 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
842 lang_id = ianjuta_language_get_from_mime_type (lang_manager,
843 file_mime, NULL);
845 if (!lang_id)
847 g_object_unref (gfile);
848 g_object_unref (gfile_info);
849 continue;
852 lang = ianjuta_language_get_name (lang_manager, lang_id, NULL);
854 /* test its existence */
855 if (g_file_test (local_filename, G_FILE_TEST_EXISTS) == FALSE)
857 g_object_unref (gfile);
858 g_object_unref (gfile_info);
859 continue;
862 /* ok, we've just tested that the local_filename does exist.
863 * We can safely add it to the array.
865 g_ptr_array_add (languages_array, g_strdup (lang));
866 g_ptr_array_add (to_scan_array, g_strdup (local_filename));
867 g_object_unref (gfile);
868 g_object_unref (gfile_info);
871 /* last but not least check if we had some files in that GPtrArray. It that's not
872 * the case just pass over
874 if (to_scan_array->len > 0)
876 gint proc_id = symbol_db_engine_add_new_files_full_async (sdb_plugin->sdbe_project,
877 sdb_plugin->project_opened, "1.0", to_scan_array, languages_array,
878 TRUE);
880 /* insert the proc id associated within the task */
881 g_tree_insert (sdb_plugin->proc_id_tree, GINT_TO_POINTER (proc_id),
882 GINT_TO_POINTER (task));
885 /* get the real added number of files */
886 added_num = to_scan_array->len;
888 g_ptr_array_unref (languages_array);
889 g_ptr_array_unref (to_scan_array);
891 g_hash_table_destroy (check_unique_file_hash);
893 return added_num;
896 static void
897 on_project_element_added (IAnjutaProjectManager *pm, GFile *gfile,
898 SymbolDBPlugin *sdb_plugin)
900 gchar *filename;
901 gint real_added;
902 GPtrArray *files_array;
904 g_return_if_fail (sdb_plugin->project_root_uri != NULL);
905 g_return_if_fail (sdb_plugin->project_root_dir != NULL);
907 filename = g_file_get_path (gfile);
909 files_array = g_ptr_array_new_with_free_func (g_free);
910 g_ptr_array_add (files_array, filename);
912 sdb_plugin->is_adding_element = TRUE;
914 /* use a custom function to add the files to db */
915 real_added = do_add_new_files (sdb_plugin, files_array, TASK_ELEMENT_ADDED);
916 if (real_added <= 0)
918 sdb_plugin->is_adding_element = FALSE;
921 g_ptr_array_unref (files_array);
924 static void
925 on_project_element_removed (IAnjutaProjectManager *pm, GFile *gfile,
926 SymbolDBPlugin *sdb_plugin)
928 gchar *filename;
930 if (!sdb_plugin->project_root_uri)
931 return;
933 filename = g_file_get_path (gfile);
935 if (filename)
937 DEBUG_PRINT ("%s", "on_project_element_removed");
938 symbol_db_engine_remove_file (sdb_plugin->sdbe_project,
939 sdb_plugin->project_root_dir,
940 symbol_db_util_get_file_db_path (sdb_plugin->sdbe_project,
941 filename));
943 g_free (filename);
947 static void
948 on_system_scan_package_start (SymbolDBEngine *dbe, guint num_files,
949 const gchar *package, gpointer user_data)
951 SymbolDBPlugin *sdb_plugin;
952 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (user_data);
954 sdb_plugin->files_count_system_done = 0;
955 sdb_plugin->files_count_system += num_files;
958 /* show the global bar */
959 gtk_widget_show (sdb_plugin->progress_bar_system);
960 if (sdb_plugin->current_scanned_package != NULL)
961 g_free (sdb_plugin->current_scanned_package);
962 sdb_plugin->current_scanned_package = g_strdup (package);
964 DEBUG_PRINT ("********************* START [%s] with n %d files ", package, num_files);
967 static void
968 on_system_scan_package_end (SymbolDBEngine *dbe, const gchar *package,
969 gpointer user_data)
971 SymbolDBPlugin *sdb_plugin;
972 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (user_data);
974 DEBUG_PRINT ("******************** END () [%s]", package);
976 /* hide the progress bar */
977 gtk_widget_hide (sdb_plugin->progress_bar_system);
979 sdb_plugin->files_count_system_done = 0;
980 sdb_plugin->files_count_system = 0;
983 static void
984 on_system_single_file_scan_end (SymbolDBEngine *dbe, gpointer data)
986 AnjutaPlugin *plugin;
987 SymbolDBPlugin *sdb_plugin;
988 gchar *message;
989 gdouble fraction = 0;
991 plugin = ANJUTA_PLUGIN (data);
992 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
994 sdb_plugin->files_count_system_done++;
995 if (sdb_plugin->files_count_system_done >= sdb_plugin->files_count_system)
997 message = g_strdup_printf (_("%s: Generating inheritances…"),
998 sdb_plugin->current_scanned_package);
1000 else
1002 message = g_strdup_printf (_("%s: %d files scanned out of %d"),
1003 sdb_plugin->current_scanned_package,
1004 sdb_plugin->files_count_system_done,
1005 sdb_plugin->files_count_system);
1008 if (sdb_plugin->files_count_system > 0)
1010 fraction = (gdouble) sdb_plugin->files_count_system_done /
1011 (gdouble) sdb_plugin->files_count_system;
1013 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_system),
1014 fraction);
1015 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_system), message);
1017 g_free (message);
1020 static void
1021 on_project_single_file_scan_end (SymbolDBEngine *dbe, gpointer data)
1023 AnjutaPlugin *plugin;
1024 SymbolDBPlugin *sdb_plugin;
1025 gchar *message;
1026 gdouble fraction = 0;
1028 plugin = ANJUTA_PLUGIN (data);
1029 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
1031 sdb_plugin->files_count_project_done++;
1032 if (sdb_plugin->files_count_project_done >= sdb_plugin->files_count_project)
1033 message = g_strdup_printf (_("Generating inheritances…"));
1034 else
1035 message = g_strdup_printf (_("%d files scanned out of %d"),
1036 sdb_plugin->files_count_project_done, sdb_plugin->files_count_project);
1038 if (sdb_plugin->files_count_project > 0)
1040 fraction = (gdouble) sdb_plugin->files_count_project_done /
1041 (gdouble) sdb_plugin->files_count_project;
1042 if (fraction > 1.0)
1043 fraction = 1.0;
1045 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_project),
1046 fraction);
1047 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_project), message);
1048 gtk_widget_show (sdb_plugin->progress_bar_project);
1049 g_free (message);
1052 static void
1053 clear_project_progress_bar (SymbolDBEngine *dbe, gpointer data)
1055 SymbolDBPlugin *sdb_plugin;
1057 g_return_if_fail (data != NULL);
1059 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (data);
1061 /* hide the progress bar */
1062 gtk_widget_hide (sdb_plugin->progress_bar_project);
1065 static void
1066 on_check_offline_single_file_scan_end (SymbolDBEngine *dbe, gpointer data)
1068 on_project_single_file_scan_end (dbe, data);
1071 /* note the *system* word in the function */
1072 static void
1073 do_import_system_sources_after_abort (SymbolDBPlugin *sdb_plugin,
1074 const GPtrArray *sources_array)
1076 AnjutaPlugin *plugin;
1077 GPtrArray* languages_array = NULL;
1078 GPtrArray *to_scan_array = NULL;
1079 IAnjutaLanguage* lang_manager;
1080 gint i;
1082 plugin = ANJUTA_PLUGIN (sdb_plugin);
1084 lang_manager = anjuta_shell_get_interface (plugin->shell, IAnjutaLanguage,
1085 NULL);
1087 /* create array of languages */
1088 languages_array = g_ptr_array_new ();
1089 to_scan_array = g_ptr_array_new ();
1091 if (!lang_manager)
1093 g_critical ("LanguageManager not found");
1094 return;
1097 for (i=0; i < sources_array->len; i++)
1099 const gchar *file_mime;
1100 const gchar *lang;
1101 const gchar *local_filename;
1102 GFile *gfile;
1103 GFileInfo *gfile_info;
1104 IAnjutaLanguageId lang_id;
1106 local_filename = g_ptr_array_index (sources_array, i);
1108 if (local_filename == NULL)
1109 continue;
1111 gfile = g_file_new_for_path (local_filename);
1112 if (gfile == NULL)
1113 continue;
1115 gfile_info = g_file_query_info (gfile,
1116 "*",
1117 G_FILE_QUERY_INFO_NONE,
1118 NULL,
1119 NULL);
1120 if (gfile_info == NULL)
1122 g_object_unref (gfile);
1123 continue;
1126 file_mime = g_file_info_get_attribute_string (gfile_info,
1127 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
1129 lang_id = ianjuta_language_get_from_mime_type (lang_manager,
1130 file_mime, NULL);
1132 if (!lang_id)
1134 g_object_unref (gfile);
1135 g_object_unref (gfile_info);
1136 continue;
1139 lang = ianjuta_language_get_name (lang_manager, lang_id, NULL);
1141 /* test its existence */
1142 if (g_file_test (local_filename, G_FILE_TEST_EXISTS) == FALSE)
1144 g_object_unref (gfile);
1145 g_object_unref (gfile_info);
1146 continue;
1149 g_ptr_array_add (languages_array, g_strdup (lang));
1150 g_ptr_array_add (to_scan_array, g_strdup (local_filename));
1151 g_object_unref (gfile);
1152 g_object_unref (gfile_info);
1155 symbol_db_system_parse_aborted_package (sdb_plugin->sdbs,
1156 to_scan_array,
1157 languages_array);
1159 /* no need to free the GPtrArray, Huston. They'll be auto-destroyed in that
1160 * function
1164 /* we assume that sources_array has already unique elements */
1165 /* note the *project* word in the function */
1166 static void
1167 do_import_project_sources_after_abort (AnjutaPlugin *plugin,
1168 const GPtrArray *sources_array)
1170 SymbolDBPlugin *sdb_plugin;
1171 gint real_added;
1173 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
1175 sdb_plugin->is_project_importing = TRUE;
1177 /* connect to receive signals on single file scan complete. We'll
1178 * update a status bar notifying the user about the status
1180 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_project), "single-file-scan-end",
1181 G_CALLBACK (on_project_single_file_scan_end), plugin);
1183 real_added = do_add_new_files (sdb_plugin, sources_array,
1184 TASK_IMPORT_PROJECT_AFTER_ABORT);
1185 if (real_added <= 0)
1187 sdb_plugin->is_project_importing = FALSE;
1189 else
1191 sdb_plugin->files_count_project += real_added;
1195 static void
1196 do_import_project_sources (AnjutaPlugin *plugin, IAnjutaProjectManager *pm,
1197 const gchar *root_dir)
1199 SymbolDBPlugin *sdb_plugin;
1200 GList* prj_elements_list;
1201 GPtrArray* sources_array;
1202 gint i;
1203 gint real_added;
1205 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
1207 prj_elements_list = ianjuta_project_manager_get_elements (pm,
1208 ANJUTA_PROJECT_SOURCE,
1209 NULL);
1211 if (prj_elements_list == NULL)
1213 g_critical ("No sources found within this project");
1214 return;
1217 /* if we're importing first shut off the signal receiving.
1218 * We'll re-enable that on scan-end
1220 sdb_plugin->is_project_importing = TRUE;
1221 DEBUG_PRINT ("Retrieving %d gbf sources of the project…",
1222 g_list_length (prj_elements_list));
1224 /* create the storage array. The file names will be strdup'd and put here.
1225 * This is just a sort of GList -> GPtrArray conversion.
1227 sources_array = g_ptr_array_new_with_free_func (g_free);
1228 for (i=0; i < g_list_length (prj_elements_list); i++)
1230 gchar *local_filename;
1231 GFile *gfile = NULL;
1233 gfile = g_list_nth_data (prj_elements_list, i);
1235 if ((local_filename = g_file_get_path (gfile)) == NULL)
1237 continue;
1240 g_ptr_array_add (sources_array, local_filename);
1243 /* connect to receive signals on single file scan complete. We'll
1244 * update a status bar notifying the user about the status
1246 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_project), "single-file-scan-end",
1247 G_CALLBACK (on_project_single_file_scan_end), plugin);
1249 real_added = do_add_new_files (sdb_plugin, sources_array, TASK_IMPORT_PROJECT);
1250 if (real_added <= 0)
1252 sdb_plugin->is_project_importing = FALSE;
1254 sdb_plugin->files_count_project += real_added;
1257 /* free the ptr array */
1258 g_ptr_array_unref (sources_array);
1260 /* and the list of project files */
1261 g_list_foreach (prj_elements_list, (GFunc) g_object_unref, NULL);
1262 g_list_free (prj_elements_list);
1265 static void
1266 do_import_system_sources (SymbolDBPlugin *sdb_plugin)
1268 /* system's packages management */
1269 GList *item = sdb_plugin->session_packages;
1270 while (item != NULL)
1272 /* the function will take care of checking if the package is already
1273 * scanned and present on db
1275 DEBUG_PRINT ("ianjuta_project_manager_get_packages: package required: %s",
1276 (gchar*)item->data);
1277 symbol_db_system_scan_package (sdb_plugin->sdbs, item->data);
1279 item = item->next;
1282 /* the resume thing */
1283 GPtrArray *sys_src_array = NULL;
1284 sys_src_array =
1285 symbol_db_util_get_files_with_zero_symbols (sdb_plugin->sdbe_globals);
1287 if (sys_src_array != NULL && sys_src_array->len > 0)
1289 do_import_system_sources_after_abort (sdb_plugin, sys_src_array);
1291 g_ptr_array_unref (sys_src_array);
1296 * @return TRUE if a scan is in progress, FALSE elsewhere.
1298 static gboolean
1299 do_update_project_symbols (SymbolDBPlugin *sdb_plugin, const gchar *root_dir)
1301 gint proc_id;
1302 /* Update the symbols */
1303 proc_id = symbol_db_engine_update_project_symbols (sdb_plugin->sdbe_project,
1304 root_dir, FALSE);
1305 if (proc_id > 0)
1307 sdb_plugin->is_project_updating = TRUE;
1309 /* insert the proc id associated within the task */
1310 g_tree_insert (sdb_plugin->proc_id_tree, GINT_TO_POINTER (proc_id),
1311 GINT_TO_POINTER (TASK_PROJECT_UPDATE));
1312 return TRUE;
1315 return FALSE;
1319 * @return TRUE is a scan process is started, FALSE elsewhere.
1321 static gboolean
1322 do_check_offline_files_changed (SymbolDBPlugin *sdb_plugin)
1324 GList * prj_elements_list;
1325 IAnjutaProjectManager *pm;
1326 GHashTable *prj_elements_hash;
1327 GPtrArray *to_add_files = NULL;
1328 gint i;
1329 gint real_added = 0;
1331 pm = anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin)->shell,
1332 IAnjutaProjectManager, NULL);
1334 prj_elements_list = ianjuta_project_manager_get_elements (pm,
1335 ANJUTA_PROJECT_SOURCE,
1336 NULL);
1338 /* fill an hash table with all the items of the list just taken.
1339 * We won't g_strdup () the elements because they'll be freed later
1341 prj_elements_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
1342 NULL, g_free);
1344 for (i = 0; i < g_list_length (prj_elements_list); i++)
1346 GFile *gfile;
1347 gchar *filename;
1349 gfile = (GFile *)g_list_nth_data (prj_elements_list, i);
1351 if ((filename = g_file_get_path (gfile)) == NULL ||
1352 g_strcmp0 (filename, "") == 0)
1354 if (gfile)
1355 g_object_unref (gfile);
1356 continue;
1359 /* test its existence */
1360 if (g_file_query_exists (gfile, NULL) == FALSE)
1362 if (gfile)
1363 g_object_unref (gfile);
1364 continue;
1367 g_hash_table_insert (prj_elements_hash,
1368 (gpointer) symbol_db_util_get_file_db_path
1369 (sdb_plugin->sdbe_project,
1370 filename),
1371 filename);
1372 g_object_unref (gfile);
1376 /* some files may have added/removed editing Makefile.am while
1377 * Anjuta was offline. Check this case too.
1378 * FIXME: Get rid of data model here.
1380 GdaDataModel *model =
1381 symbol_db_engine_get_files_for_project (sdb_plugin->sdbe_project);
1382 GdaDataModelIter *it =
1383 gda_data_model_create_iter (model);
1385 if (it && gda_data_model_iter_move_to_row (it, 0))
1387 GPtrArray *remove_array;
1388 remove_array = g_ptr_array_new_with_free_func (g_free);
1389 do {
1390 const GValue *val = gda_data_model_iter_get_value_at (it, 0);
1391 const gchar * file = g_value_get_string (val);
1393 if (file && g_hash_table_remove (prj_elements_hash, file) == FALSE)
1394 g_ptr_array_add (remove_array, g_strdup (file));
1396 } while (gda_data_model_iter_move_next (it));
1398 symbol_db_engine_remove_files (sdb_plugin->sdbe_project,
1399 sdb_plugin->project_opened,
1400 remove_array);
1401 g_ptr_array_unref (remove_array);
1404 /* great, at this point we should have this situation:
1405 * remove array = files to remove, remaining items in the hash_table = files
1406 * to add.
1408 to_add_files = g_ptr_array_new ();
1409 if (g_hash_table_size (prj_elements_hash) > 0)
1411 gint i;
1412 GList *keys = g_hash_table_get_keys (prj_elements_hash);
1414 /* get all the nodes from the hash table and add them to the wannabe-added
1415 * array
1417 for (i = 0; i < g_hash_table_size (prj_elements_hash); i++)
1419 /*DEBUG_PRINT ("ARRAY ADD %s", (gchar*)g_list_nth_data (keys, i));*/
1420 g_ptr_array_add (to_add_files,
1421 g_hash_table_lookup (prj_elements_hash,
1422 g_list_nth_data (keys, i)));
1426 /* good. Let's go on with add of new files. */
1427 if (to_add_files->len > 0)
1429 /* block the signals spreading from engine to local-view tab */
1430 sdb_plugin->is_offline_scanning = TRUE;
1431 real_added = do_add_new_files (sdb_plugin, to_add_files,
1432 TASK_OFFLINE_CHANGES);
1434 DEBUG_PRINT ("going to do add %d files with TASK_OFFLINE_CHANGES",
1435 real_added);
1437 if (real_added <= 0)
1439 sdb_plugin->is_offline_scanning = FALSE;
1441 else {
1442 /* connect to receive signals on single file scan complete. We'll
1443 * update a status bar notifying the user about the status
1445 sdb_plugin->files_count_project += real_added;
1447 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_project), "single-file-scan-end",
1448 G_CALLBACK (on_check_offline_single_file_scan_end), ANJUTA_PLUGIN (sdb_plugin));
1452 g_object_unref (it);
1453 g_object_unref (model);
1454 g_ptr_array_unref (to_add_files);
1455 g_hash_table_destroy (prj_elements_hash);
1457 return real_added > 0 ? TRUE : FALSE;
1460 static void
1461 on_session_save (AnjutaShell *shell, AnjutaSessionPhase phase,
1462 AnjutaSession *session,
1463 SymbolDBPlugin *sdb_plugin)
1465 if (phase != ANJUTA_SESSION_PHASE_NORMAL)
1466 return;
1468 DEBUG_PRINT ("%s", "SymbolDB: session_save");
1470 anjuta_session_set_string_list (session,
1471 SESSION_SECTION,
1472 SESSION_KEY,
1473 sdb_plugin->session_packages);
1476 static void
1477 on_session_load (AnjutaShell *shell, AnjutaSessionPhase phase,
1478 AnjutaSession *session,
1479 SymbolDBPlugin *sdb_plugin)
1481 IAnjutaProjectManager *pm;
1482 pm = anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin)->shell,
1483 IAnjutaProjectManager, NULL);
1485 if (phase == ANJUTA_SESSION_PHASE_START)
1487 sdb_plugin->session_packages = anjuta_session_get_string_list (session,
1488 SESSION_SECTION,
1489 SESSION_KEY);
1491 DEBUG_PRINT ("SymbolDB: session_loading started. Getting info from %s",
1492 anjuta_session_get_session_directory (session));
1493 sdb_plugin->session_loading = TRUE;
1495 if (sdb_plugin->session_packages == NULL)
1497 /* hey, does user want to import system sources for this project? */
1498 gboolean automatic_scan = anjuta_preferences_get_bool (sdb_plugin->prefs,
1499 PROJECT_AUTOSCAN);
1501 if (automatic_scan == TRUE)
1503 sdb_plugin->session_packages = ianjuta_project_manager_get_packages (pm, NULL);
1507 /* get preferences about the parallel scan */
1508 gboolean parallel_scan = anjuta_preferences_get_bool (sdb_plugin->prefs,
1509 PARALLEL_SCAN);
1511 if (parallel_scan == TRUE &&
1512 symbol_db_engine_is_connected (sdb_plugin->sdbe_globals) == TRUE)
1514 /* we simulate a project-import-end signal received */
1515 do_import_system_sources (sdb_plugin);
1518 else if (phase == ANJUTA_SESSION_PHASE_END)
1520 IAnjutaDocumentManager* docman;
1521 sdb_plugin->session_loading = FALSE;
1522 DEBUG_PRINT ("SymbolDB: session_loading finished");
1524 /* Show the symbols for the current editor */
1525 docman = anjuta_shell_get_interface (shell, IAnjutaDocumentManager, NULL);
1526 if (docman)
1528 IAnjutaDocument* cur_doc =
1529 ianjuta_document_manager_get_current_document (docman, NULL);
1530 if (cur_doc)
1532 GValue value = {0, };
1533 g_value_init (&value, G_TYPE_OBJECT);
1534 g_value_set_object (&value, cur_doc);
1535 value_added_current_editor (ANJUTA_PLUGIN (sdb_plugin),
1536 "document_manager_current_document",
1537 &value, NULL);
1538 g_value_unset(&value);
1542 if (sdb_plugin->project_opened == NULL)
1544 gtk_widget_hide (sdb_plugin->progress_bar_project);
1545 gtk_widget_hide (sdb_plugin->progress_bar_system);
1550 /* add a new project */
1551 static void
1552 on_project_root_added (AnjutaPlugin *plugin, const gchar *name,
1553 const GValue *value, gpointer user_data)
1555 IAnjutaProjectManager *pm;
1556 SymbolDBPlugin *sdb_plugin;
1557 const gchar *root_uri;
1558 gchar *root_dir;
1559 GFile *gfile;
1561 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
1564 * The Global System symbols thing
1567 /* is the global db connected? */
1568 if (symbol_db_engine_is_connected (sdb_plugin->sdbe_globals) == FALSE)
1570 gchar *anjuta_cache_path;
1571 /* open the connection to global db */
1572 anjuta_cache_path = anjuta_util_get_user_cache_file_path (".", NULL);
1573 if (symbol_db_engine_open_db (sdb_plugin->sdbe_globals,
1574 anjuta_cache_path,
1575 PROJECT_GLOBALS) == DB_OPEN_STATUS_FATAL)
1577 g_error ("Opening global project under %s", anjuta_cache_path);
1579 g_free (anjuta_cache_path);
1581 /* unref and recreate the sdbs object */
1582 if (sdb_plugin->sdbs != NULL)
1583 g_object_unref (sdb_plugin->sdbs);
1585 sdb_plugin->sdbs = symbol_db_system_new (sdb_plugin,
1586 sdb_plugin->sdbe_globals);
1589 /* Hide the progress bar. Default system tags thing: we'll import after abort even
1590 * if the preferences says not to automatically scan the packages.
1592 gtk_widget_hide (sdb_plugin->progress_bar_system);
1594 pm = anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin)->shell,
1595 IAnjutaProjectManager, NULL);
1598 * The Project thing
1601 g_free (sdb_plugin->project_root_uri);
1602 sdb_plugin->project_root_uri = NULL;
1603 if ((root_uri = g_value_get_string (value)) == NULL)
1605 DEBUG_PRINT ("Warning, root_uri for project is NULL");
1606 return;
1610 gfile = g_file_new_for_uri (root_uri);
1612 root_dir = g_file_get_path (gfile);
1613 DEBUG_PRINT ("Symbol-DB: added project root_dir %s, name %s", root_dir,
1614 name);
1616 g_object_unref (gfile);
1618 /* FIXME: where's the project name itself? */
1619 DEBUG_PRINT ("FIXME: where's the project name itself? using %s", root_dir);
1620 sdb_plugin->project_opened = g_strdup (root_dir);
1622 if (root_dir)
1624 gboolean needs_sources_scan = FALSE;
1625 gboolean project_exist = FALSE;
1626 guint id;
1628 /* we'll use the same values for db_directory and project_directory */
1629 DEBUG_PRINT ("Opening db %s and project_dir %s", root_dir, root_dir);
1630 gint open_status = symbol_db_engine_open_db (sdb_plugin->sdbe_project, root_dir,
1631 root_dir);
1633 /* is it a fresh-new project? is it an imported project with
1634 * no 'new' symbol-db database but the 'old' one symbol-browser?
1636 switch (open_status)
1638 case DB_OPEN_STATUS_FATAL:
1639 g_error ("*** Error in opening db ***");
1640 return;
1642 case DB_OPEN_STATUS_NORMAL:
1643 project_exist = TRUE;
1644 break;
1646 case DB_OPEN_STATUS_CREATE:
1647 case DB_OPEN_STATUS_UPGRADE:
1648 needs_sources_scan = TRUE;
1649 project_exist = FALSE;
1650 break;
1652 default:
1653 break;
1656 /* if project did not exist add a new project */
1657 if (project_exist == FALSE)
1659 DEBUG_PRINT ("Creating new project.");
1660 symbol_db_engine_add_new_project (sdb_plugin->sdbe_project,
1661 NULL, /* still no workspace logic */
1662 sdb_plugin->project_opened,
1663 "1.0");
1667 * we need an initial import
1669 if (needs_sources_scan == TRUE)
1671 DEBUG_PRINT ("Importing sources.");
1672 do_import_project_sources (plugin, pm, root_dir);
1674 else
1677 * no import needed. But we may have aborted the scan of sources in
1678 * a previous session..
1680 GPtrArray *sources_array = NULL;
1681 gboolean flag_offline;
1682 gboolean flag_update;
1685 sources_array =
1686 symbol_db_util_get_files_with_zero_symbols (sdb_plugin->sdbe_project);
1688 if (sources_array != NULL && sources_array->len > 0)
1690 do_import_project_sources_after_abort (plugin, sources_array);
1691 g_ptr_array_unref (sources_array);
1694 /* check for offline changes */
1695 flag_offline = do_check_offline_files_changed (sdb_plugin);
1697 /* update any files of the project which isn't up-to-date */
1698 flag_update = do_update_project_symbols (sdb_plugin, root_dir);
1700 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_project),
1701 _("Populating symbol database…"));
1702 id = g_idle_add ((GSourceFunc) gtk_progress_bar_pulse,
1703 sdb_plugin->progress_bar_project);
1704 gtk_widget_show (sdb_plugin->progress_bar_project);
1705 g_source_remove (id);
1706 gtk_widget_hide (sdb_plugin->progress_bar_project);
1708 /* root dir */
1709 sdb_plugin->project_root_dir = root_dir;
1711 /* this is uri */
1712 sdb_plugin->project_root_uri = g_strdup (root_uri);
1714 g_signal_connect (G_OBJECT (pm), "element_added",
1715 G_CALLBACK (on_project_element_added), sdb_plugin);
1716 g_signal_connect (G_OBJECT (pm), "element_removed",
1717 G_CALLBACK (on_project_element_removed), sdb_plugin);
1720 static void
1721 on_project_root_removed (AnjutaPlugin *plugin, const gchar *name,
1722 gpointer user_data)
1724 IAnjutaProjectManager *pm;
1725 SymbolDBPlugin *sdb_plugin;
1727 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
1728 DEBUG_PRINT ("%s", "project_root_removed ()");
1729 /* Disconnect events from project manager */
1731 pm = anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin)->shell,
1732 IAnjutaProjectManager, NULL);
1733 g_signal_handlers_disconnect_by_func (G_OBJECT (pm),
1734 on_project_element_added,
1735 sdb_plugin);
1736 g_signal_handlers_disconnect_by_func (G_OBJECT (pm),
1737 on_project_element_removed,
1738 sdb_plugin);
1740 /* don't forget to close the project */
1741 symbol_db_engine_close_db (sdb_plugin->sdbe_project);
1743 /* and the globals one */
1744 symbol_db_engine_close_db (sdb_plugin->sdbe_globals);
1746 /* stop any opened scanning process */
1747 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_system), "");
1748 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin->progress_bar_project), "");
1749 gtk_widget_hide (sdb_plugin->progress_bar_system);
1750 gtk_widget_hide (sdb_plugin->progress_bar_project);
1752 sdb_plugin->files_count_system_done = 0;
1753 sdb_plugin->files_count_system = 0;
1755 sdb_plugin->files_count_project_done = 0;
1756 sdb_plugin->files_count_project = 0;
1759 g_free (sdb_plugin->project_root_uri);
1760 g_free (sdb_plugin->project_root_dir);
1761 g_free (sdb_plugin->project_opened);
1762 sdb_plugin->project_root_uri = NULL;
1763 sdb_plugin->project_root_dir = NULL;
1764 sdb_plugin->project_opened = NULL;
1767 static void
1768 on_scan_end_manager (SymbolDBEngine *dbe, gint process_id,
1769 gpointer data)
1771 SymbolDBPlugin *sdb_plugin;
1772 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (data);
1773 gint task_registered;
1775 task_registered = GPOINTER_TO_INT (g_tree_lookup (sdb_plugin->proc_id_tree,
1776 GINT_TO_POINTER (process_id)));
1777 /* hey, we haven't find anything */
1778 if (task_registered <= 0)
1780 DEBUG_PRINT ("No task found, proc id was %d", process_id);
1781 return;
1784 switch (task_registered)
1786 case TASK_IMPORT_PROJECT:
1787 case TASK_IMPORT_PROJECT_AFTER_ABORT:
1789 DEBUG_PRINT ("received TASK_IMPORT_PROJECT (AFTER_ABORT)");
1791 /* re-enable signals receiving on local-view */
1792 sdb_plugin->is_project_importing = FALSE;
1794 /* disconnect this coz it's not important after the process of importing */
1795 g_signal_handlers_disconnect_by_func (dbe, on_project_single_file_scan_end,
1796 sdb_plugin);
1798 /* get preferences about the parallel scan */
1799 gboolean parallel_scan = anjuta_preferences_get_bool (sdb_plugin->prefs,
1800 PARALLEL_SCAN);
1802 /* check the system population has a parallel fashion or not. */
1803 if (parallel_scan == FALSE)
1804 do_import_system_sources (sdb_plugin);
1806 break;
1808 case TASK_BUFFER_UPDATE:
1809 DEBUG_PRINT ("received TASK_BUFFER_UPDATE");
1810 on_editor_buffer_symbol_update_scan_end (dbe, process_id, sdb_plugin);
1811 break;
1813 case TASK_ELEMENT_ADDED:
1814 DEBUG_PRINT ("received TASK_ELEMENT_ADDED");
1815 sdb_plugin->is_adding_element = FALSE;
1816 break;
1818 case TASK_OFFLINE_CHANGES:
1819 DEBUG_PRINT ("received TASK_OFFLINE_CHANGES");
1821 /* disconnect this coz it's not important after the process of importing */
1822 g_signal_handlers_disconnect_by_func (dbe, on_check_offline_single_file_scan_end,
1823 sdb_plugin);
1825 sdb_plugin->is_offline_scanning = FALSE;
1826 break;
1828 case TASK_PROJECT_UPDATE:
1829 DEBUG_PRINT ("received TASK_PROJECT_UPDATE");
1830 sdb_plugin->is_project_updating = FALSE;
1831 break;
1833 case TASK_FILE_UPDATE:
1834 DEBUG_PRINT ("received TASK_FILE_UPDATE");
1835 break;
1837 default:
1838 DEBUG_PRINT ("Don't know what to to with task_registered %d",
1839 task_registered);
1842 /* ok, we're done. Remove the proc_id from the GTree coz we won't use it anymore */
1843 if (g_tree_remove (sdb_plugin->proc_id_tree, GINT_TO_POINTER (process_id)) == FALSE)
1844 g_warning ("Cannot remove proc_id from GTree");
1846 DEBUG_PRINT ("is_offline_scanning %d, is_project_importing %d, is_project_updating %d, "
1847 "is_adding_element %d", sdb_plugin->is_offline_scanning,
1848 sdb_plugin->is_project_importing, sdb_plugin->is_project_updating,
1849 sdb_plugin->is_adding_element);
1851 /* is the project still opened? */
1852 if (sdb_plugin->project_opened == NULL)
1854 /* just return, the project may have been closed while we were waiting for the
1855 * scanning to finish
1857 return;
1861 * perform some checks on some booleans. If they're all successfully passed
1862 * then activate the display of local view
1864 if (sdb_plugin->is_offline_scanning == FALSE &&
1865 sdb_plugin->is_project_importing == FALSE &&
1866 sdb_plugin->is_project_updating == FALSE &&
1867 sdb_plugin->is_adding_element == FALSE)
1869 sdb_plugin->files_count_project_done = 0;
1870 sdb_plugin->files_count_project = 0;
1871 clear_project_progress_bar (dbe, sdb_plugin);
1875 static void
1876 on_isymbol_manager_prj_scan_end (SymbolDBEngine *dbe,
1877 gint process_id,
1878 IAnjutaSymbolManager *sm)
1880 g_signal_emit_by_name (sm, "prj-scan-end", process_id);
1883 static void
1884 on_isymbol_manager_sys_scan_end (SymbolDBEngine *dbe,
1885 gint process_id,
1886 IAnjutaSymbolManager *sm)
1888 g_signal_emit_by_name (sm, "sys-scan-end", process_id);
1891 static gboolean
1892 symbol_db_activate (AnjutaPlugin *plugin)
1894 SymbolDBPlugin *sdb_plugin;
1895 gchar *anjuta_cache_path;
1896 gchar *ctags_path;
1897 GtkWidget *view, *label;
1899 DEBUG_PRINT ("SymbolDBPlugin: Activating SymbolDBPlugin plugin …");
1901 /* Initialize gda library. */
1902 gda_init ();
1904 register_stock_icons (plugin);
1906 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
1907 sdb_plugin->ui = anjuta_shell_get_ui (plugin->shell, NULL);
1908 sdb_plugin->prefs = anjuta_shell_get_preferences (plugin->shell, NULL);
1909 sdb_plugin->project_opened = NULL;
1911 ctags_path = NULL;
1913 /* leaving here this code. Maybe in future ctags-devs will include our patches
1914 * upstream and this can be useful again.
1916 if (ctags_path == NULL)
1918 DEBUG_PRINT ("ctags is not in preferences. Trying a default one %s",
1919 CTAGS_PATH);
1920 ctags_path = g_strdup (CTAGS_PATH);
1923 /* initialize the session packages to NULL. We'll store there the user
1924 * preferences for the session about global-system packages
1926 sdb_plugin->session_packages = NULL;
1928 sdb_plugin->buf_update_timeout_id = 0;
1929 sdb_plugin->need_symbols_update = FALSE;
1930 /* creates and start a new timer. */
1931 sdb_plugin->update_timer = g_timer_new ();
1933 /* these two arrays will maintain the same number of objects,
1934 * so that if you search, say on the first, an occurrence of a file,
1935 * you'll be able to get in O(1) the _index in the second array, where the
1936 * scan process ids are stored. This is true in the other way too.
1938 sdb_plugin->buffer_update_files = g_ptr_array_new_with_free_func (g_free);
1939 sdb_plugin->buffer_update_ids = g_ptr_array_new ();
1940 sdb_plugin->buffer_update_semaphore = FALSE;
1942 sdb_plugin->is_offline_scanning = FALSE;
1943 sdb_plugin->is_project_importing = FALSE;
1944 sdb_plugin->is_project_updating = FALSE;
1945 sdb_plugin->is_adding_element = FALSE;
1947 DEBUG_PRINT ("SymbolDBPlugin: Initializing engines with %s", ctags_path);
1948 /* create SymbolDBEngine(s) */
1949 sdb_plugin->sdbe_project = symbol_db_engine_new (ctags_path);
1950 if (sdb_plugin->sdbe_project == NULL)
1952 g_critical ("sdbe_project == NULL");
1953 return FALSE;
1956 /* the globals one too */
1957 sdb_plugin->sdbe_globals = symbol_db_engine_new (ctags_path);
1958 if (sdb_plugin->sdbe_globals == NULL)
1960 g_critical ("sdbe_globals == NULL");
1961 return FALSE;
1964 g_free (ctags_path);
1966 /* open it */
1967 anjuta_cache_path = anjuta_util_get_user_cache_file_path (".", NULL);
1968 if (symbol_db_engine_open_db (sdb_plugin->sdbe_globals,
1969 anjuta_cache_path,
1970 PROJECT_GLOBALS) == DB_OPEN_STATUS_FATAL)
1972 g_error ("Opening global project under %s", anjuta_cache_path);
1975 g_free (anjuta_cache_path);
1977 /* create the object that'll manage the globals population */
1978 sdb_plugin->sdbs = symbol_db_system_new (sdb_plugin, sdb_plugin->sdbe_globals);
1980 g_signal_connect (G_OBJECT (sdb_plugin->sdbs), "scan-package-start",
1981 G_CALLBACK (on_system_scan_package_start), plugin);
1983 g_signal_connect (G_OBJECT (sdb_plugin->sdbs), "scan-package-end",
1984 G_CALLBACK (on_system_scan_package_end), plugin);
1986 g_signal_connect (G_OBJECT (sdb_plugin->sdbs), "single-file-scan-end",
1987 G_CALLBACK (on_system_single_file_scan_end), plugin);
1989 /* beign necessary to listen to many scan-end signals, we'll build up a method
1990 * to manage them with just one signal connection
1992 sdb_plugin->proc_id_tree = g_tree_new_full ((GCompareDataFunc)&symbol_db_gtree_compare_func,
1993 NULL,
1994 NULL,
1995 NULL);
1997 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_project), "scan-end",
1998 G_CALLBACK (on_scan_end_manager), sdb_plugin);
2000 /* connect signals for interface to receive them */
2001 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_globals), "scan-end",
2002 G_CALLBACK (on_isymbol_manager_sys_scan_end), sdb_plugin);
2004 g_signal_connect (G_OBJECT (sdb_plugin->sdbe_project), "scan-end",
2005 G_CALLBACK (on_isymbol_manager_prj_scan_end), sdb_plugin);
2008 /* sets preferences to NULL, it'll be instantiated when required. */
2009 sdb_plugin->sdbp = NULL;
2011 /* Create widgets */
2012 sdb_plugin->dbv_main = gtk_vbox_new(FALSE, 5);
2013 sdb_plugin->dbv_notebook = gtk_notebook_new();
2014 gtk_notebook_set_show_border (GTK_NOTEBOOK (sdb_plugin->dbv_notebook), FALSE);
2015 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (sdb_plugin->dbv_notebook), FALSE);
2016 sdb_plugin->dbv_hbox = gtk_hbox_new (FALSE, 1);
2018 label = gtk_label_new (_("Symbols"));
2019 gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f);
2020 gtk_box_pack_start (GTK_BOX(sdb_plugin->dbv_hbox),
2021 gtk_image_new_from_stock ("symbol-db-plugin-icon",
2022 GTK_ICON_SIZE_MENU),
2023 FALSE, FALSE, 0);
2024 gtk_box_pack_start (GTK_BOX(sdb_plugin->dbv_hbox), label,
2025 FALSE, FALSE, 0);
2027 sdb_plugin->tabber = anjuta_tabber_new (GTK_NOTEBOOK (sdb_plugin->dbv_notebook));
2028 label = gtk_label_new (_("Local"));
2029 gtk_label_set_ellipsize (GTK_LABEL (label),
2030 PANGO_ELLIPSIZE_END);
2031 anjuta_tabber_add_tab (ANJUTA_TABBER (sdb_plugin->tabber),
2032 label);
2033 label = gtk_label_new (_("Global"));
2034 gtk_label_set_ellipsize (GTK_LABEL (label),
2035 PANGO_ELLIPSIZE_END);
2036 anjuta_tabber_add_tab (ANJUTA_TABBER (sdb_plugin->tabber),
2037 label);
2038 label = gtk_label_new (_("Search"));
2039 gtk_label_set_ellipsize (GTK_LABEL (label),
2040 PANGO_ELLIPSIZE_END);
2041 anjuta_tabber_add_tab (ANJUTA_TABBER (sdb_plugin->tabber),
2042 label);
2043 gtk_box_pack_end (GTK_BOX(sdb_plugin->dbv_hbox), sdb_plugin->tabber,
2044 TRUE, TRUE, 5);
2046 gtk_widget_show_all (sdb_plugin->dbv_hbox);
2048 sdb_plugin->progress_bar_project = gtk_progress_bar_new();
2049 gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR(sdb_plugin->progress_bar_project),
2050 PANGO_ELLIPSIZE_MIDDLE);
2051 g_object_ref (sdb_plugin->progress_bar_project);
2053 sdb_plugin->progress_bar_system = gtk_progress_bar_new();
2054 gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR(sdb_plugin->progress_bar_system),
2055 PANGO_ELLIPSIZE_MIDDLE);
2056 g_object_ref (sdb_plugin->progress_bar_system);
2058 gtk_box_pack_start (GTK_BOX (sdb_plugin->dbv_main), sdb_plugin->dbv_notebook,
2059 TRUE, TRUE, 0);
2060 gtk_box_pack_start (GTK_BOX (sdb_plugin->dbv_main), sdb_plugin->progress_bar_project,
2061 FALSE, FALSE, 0);
2062 gtk_box_pack_start (GTK_BOX (sdb_plugin->dbv_main), sdb_plugin->progress_bar_system,
2063 FALSE, FALSE, 0);
2064 gtk_widget_show_all (sdb_plugin->dbv_main);
2066 /* Local symbols */
2067 view = symbol_db_view_new (SYMBOL_DB_VIEW_FILE, sdb_plugin->sdbe_project,
2068 sdb_plugin);
2069 gtk_notebook_append_page (GTK_NOTEBOOK (sdb_plugin->dbv_notebook),
2070 view, gtk_label_new (_("Local")));
2071 sdb_plugin->file_model =
2072 gtk_tree_view_get_model (GTK_TREE_VIEW (gtk_bin_get_child (GTK_BIN(view))));
2074 g_object_add_weak_pointer (G_OBJECT (sdb_plugin->file_model),
2075 (gpointer)&sdb_plugin->file_model);
2077 /* Global symbols */
2078 view = symbol_db_view_new (SYMBOL_DB_VIEW_PROJECT,
2079 sdb_plugin->sdbe_project,
2080 sdb_plugin);
2081 gtk_notebook_append_page (GTK_NOTEBOOK (sdb_plugin->dbv_notebook),
2082 view, gtk_label_new (_("Global" )));
2084 /* Search symbols */
2085 view = symbol_db_view_new (SYMBOL_DB_VIEW_SEARCH,
2086 sdb_plugin->sdbe_project,
2087 sdb_plugin);
2088 sdb_plugin->search_entry = symbol_db_view_get_search_entry (view);
2089 gtk_notebook_append_page (GTK_NOTEBOOK (sdb_plugin->dbv_notebook),
2090 view, gtk_label_new (_("Search" )));
2092 gtk_widget_show_all (sdb_plugin->dbv_notebook);
2094 /* setting focus to the tree_view*/
2095 gtk_notebook_set_current_page (GTK_NOTEBOOK (sdb_plugin->dbv_notebook), 0);
2097 sdb_plugin->editor_watch_id =
2098 anjuta_plugin_add_watch (plugin, IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT,
2099 value_added_current_editor,
2100 value_removed_current_editor, NULL);
2101 /* Added widgets */
2102 anjuta_shell_add_widget_custom (plugin->shell, sdb_plugin->dbv_main,
2103 "AnjutaSymbolDB", _("Symbols"),
2104 "symbol-db-plugin-icon",
2105 sdb_plugin->dbv_hbox,
2106 ANJUTA_SHELL_PLACEMENT_LEFT, NULL);
2108 /* Add action group */
2109 sdb_plugin->popup_action_group =
2110 anjuta_ui_add_action_group_entries (sdb_plugin->ui,
2111 "ActionGroupPopupSymbolDB",
2112 _("SymbolDb popup actions"),
2113 actions,
2114 G_N_ELEMENTS (actions),
2115 GETTEXT_PACKAGE, FALSE, plugin);
2117 sdb_plugin->menu_action_group =
2118 anjuta_ui_add_action_group_entries (sdb_plugin->ui,
2119 "ActionGroupEditSearchSymbolDB",
2120 _("SymbolDb menu actions"),
2121 actions_search,
2122 G_N_ELEMENTS (actions_search),
2123 GETTEXT_PACKAGE, FALSE, plugin);
2125 /* Add UI */
2126 sdb_plugin->merge_id =
2127 anjuta_ui_merge (sdb_plugin->ui, UI_FILE);
2129 /* set up project directory watch */
2130 sdb_plugin->root_watch_id = anjuta_plugin_add_watch (plugin,
2131 IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI,
2132 on_project_root_added,
2133 on_project_root_removed, NULL);
2135 /* Determine session state */
2136 g_signal_connect (plugin->shell, "load-session",
2137 G_CALLBACK (on_session_load), plugin);
2139 g_signal_connect (plugin->shell, "save-session",
2140 G_CALLBACK (on_session_save), plugin);
2142 /* be sure to hide the progress bars in case no project has been opened. */
2143 gtk_widget_hide (sdb_plugin->progress_bar_project);
2144 gtk_widget_hide (sdb_plugin->progress_bar_system);
2146 static IAnjutaSymbolField search_fields[] =
2148 IANJUTA_SYMBOL_FIELD_KIND,
2149 IANJUTA_SYMBOL_FIELD_FILE_PATH,
2150 IANJUTA_SYMBOL_FIELD_FILE_POS
2152 sdb_plugin->search_query =
2153 ianjuta_symbol_manager_create_query (IANJUTA_SYMBOL_MANAGER (sdb_plugin),
2154 IANJUTA_SYMBOL_QUERY_SEARCH,
2155 IANJUTA_SYMBOL_QUERY_DB_PROJECT,
2156 NULL);
2157 ianjuta_symbol_query_set_fields (sdb_plugin->search_query,
2158 G_N_ELEMENTS (search_fields),
2159 search_fields, NULL);
2160 return TRUE;
2163 static gboolean
2164 symbol_db_deactivate (AnjutaPlugin *plugin)
2166 SymbolDBPlugin *sdb_plugin;
2168 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (plugin);
2170 DEBUG_PRINT ("%s", "SymbolDBPlugin: Dectivating SymbolDBPlugin plugin …");
2172 /* Unmerge UI */
2173 gtk_ui_manager_remove_ui (GTK_UI_MANAGER (sdb_plugin->ui),
2174 sdb_plugin->merge_id);
2175 gtk_ui_manager_remove_action_group (GTK_UI_MANAGER (sdb_plugin->ui),
2176 sdb_plugin->popup_action_group);
2177 gtk_ui_manager_remove_action_group (GTK_UI_MANAGER (sdb_plugin->ui),
2178 sdb_plugin->menu_action_group);
2179 g_signal_handlers_disconnect_by_func (G_OBJECT (plugin->shell),
2180 on_session_load,
2181 plugin);
2183 g_signal_handlers_disconnect_by_func (G_OBJECT (plugin->shell),
2184 on_session_save,
2185 plugin);
2187 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin->sdbs),
2188 on_system_scan_package_start,
2189 plugin);
2191 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin->sdbs),
2192 on_system_scan_package_end,
2193 plugin);
2195 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin->sdbs),
2196 on_system_single_file_scan_end,
2197 plugin);
2199 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin->sdbs),
2200 on_scan_end_manager,
2201 plugin);
2203 /* disconnect the interface ones */
2204 /* connect signals for interface to receive them */
2205 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin->sdbe_globals),
2206 G_CALLBACK (on_isymbol_manager_sys_scan_end), plugin);
2208 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin->sdbe_project),
2209 G_CALLBACK (on_isymbol_manager_prj_scan_end), plugin);
2211 if (sdb_plugin->update_timer)
2213 g_timer_destroy (sdb_plugin->update_timer);
2214 sdb_plugin->update_timer = NULL;
2217 /* destroy objects */
2218 if (sdb_plugin->sdbe_project)
2220 DEBUG_PRINT ("Destroying project engine object. ");
2221 g_object_unref (sdb_plugin->sdbe_project);
2223 sdb_plugin->sdbe_project = NULL;
2225 /* this must be done *before* destroying sdbe_globals */
2226 g_object_unref (sdb_plugin->sdbs);
2227 sdb_plugin->sdbs = NULL;
2229 g_free (sdb_plugin->current_scanned_package);
2230 sdb_plugin->current_scanned_package = NULL;
2232 DEBUG_PRINT ("Destroying global engine object. ");
2233 g_object_unref (sdb_plugin->sdbe_globals);
2234 sdb_plugin->sdbe_globals = NULL;
2236 g_free (sdb_plugin->project_opened);
2237 sdb_plugin->project_opened = NULL;
2239 if (sdb_plugin->buffer_update_files)
2241 g_ptr_array_unref (sdb_plugin->buffer_update_files);
2242 sdb_plugin->buffer_update_files = NULL;
2245 if (sdb_plugin->buffer_update_ids)
2247 g_ptr_array_unref (sdb_plugin->buffer_update_ids);
2248 sdb_plugin->buffer_update_ids = NULL;
2251 if (sdb_plugin->session_packages)
2253 g_list_foreach (sdb_plugin->session_packages, (GFunc)g_free, NULL);
2254 g_list_free (sdb_plugin->session_packages);
2255 sdb_plugin->session_packages = NULL;
2258 /* Ensure all editor cached info are released */
2259 if (sdb_plugin->editor_connected)
2261 g_hash_table_foreach (sdb_plugin->editor_connected,
2262 on_editor_foreach_disconnect, plugin);
2263 g_hash_table_destroy (sdb_plugin->editor_connected);
2264 sdb_plugin->editor_connected = NULL;
2267 // FIXME
2268 g_tree_destroy (sdb_plugin->proc_id_tree);
2270 /* Remove watches */
2271 anjuta_plugin_remove_watch (plugin, sdb_plugin->root_watch_id, FALSE);
2272 anjuta_plugin_remove_watch (plugin, sdb_plugin->editor_watch_id, TRUE);
2274 /* Remove UI */
2275 anjuta_ui_unmerge (sdb_plugin->ui, sdb_plugin->merge_id);
2277 /* Remove widgets: Widgets will be destroyed when dbv_main is removed */
2278 anjuta_shell_remove_widget (plugin->shell, sdb_plugin->dbv_main, NULL);
2280 sdb_plugin->root_watch_id = 0;
2281 sdb_plugin->editor_watch_id = 0;
2282 sdb_plugin->merge_id = 0;
2283 sdb_plugin->dbv_notebook = NULL;
2284 sdb_plugin->progress_bar_project = NULL;
2285 sdb_plugin->progress_bar_system = NULL;
2286 return TRUE;
2289 static void
2290 symbol_db_finalize (GObject *obj)
2292 DEBUG_PRINT ("Symbol-DB finalize");
2293 /* Finalization codes here */
2294 G_OBJECT_CLASS (parent_class)->finalize (obj);
2297 static void
2298 symbol_db_dispose (GObject *obj)
2300 DEBUG_PRINT ("Symbol-DB dispose");
2301 /* Disposition codes */
2302 G_OBJECT_CLASS (parent_class)->dispose (obj);
2305 static void
2306 symbol_db_instance_init (GObject *obj)
2308 SymbolDBPlugin *plugin = (SymbolDBPlugin*)obj;
2310 plugin->files_count_project_done = 0;
2311 plugin->files_count_project = 0;
2313 plugin->files_count_system_done = 0;
2314 plugin->files_count_system = 0;
2315 plugin->current_scanned_package = NULL;
2318 static void
2319 symbol_db_class_init (GObjectClass *klass)
2321 AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
2323 GObjectClass *object_class = G_OBJECT_CLASS (klass);
2324 parent_class = g_type_class_peek_parent (klass);
2326 plugin_class->activate = symbol_db_activate;
2327 plugin_class->deactivate = symbol_db_deactivate;
2328 klass->finalize = symbol_db_finalize;
2329 klass->dispose = symbol_db_dispose;
2331 signals[PROJECT_IMPORT_END]
2332 = g_signal_new ("project-import-end",
2333 G_OBJECT_CLASS_TYPE (object_class),
2334 G_SIGNAL_RUN_FIRST,
2335 G_STRUCT_OFFSET (SymbolDBPluginClass, project_import_end),
2336 NULL, NULL,
2337 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2339 signals[GLOBALS_IMPORT_END]
2340 = g_signal_new ("globals-import-end",
2341 G_OBJECT_CLASS_TYPE (object_class),
2342 G_SIGNAL_RUN_FIRST,
2343 G_STRUCT_OFFSET (SymbolDBPluginClass, globals_import_end),
2344 NULL, NULL,
2345 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2350 static void
2351 on_prefs_package_add (SymbolDBPrefs *sdbp, const gchar *package,
2352 gpointer user_data)
2354 SymbolDBPlugin *sdb_plugin;
2356 g_return_if_fail (package != NULL);
2358 DEBUG_PRINT ("%s", "on_prefs_package_add");
2360 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (user_data);
2362 sdb_plugin->session_packages = g_list_prepend (sdb_plugin->session_packages,
2363 g_strdup (package));
2366 static void
2367 on_prefs_package_remove (SymbolDBPrefs *sdbp, const gchar *package,
2368 gpointer user_data)
2370 SymbolDBPlugin *sdb_plugin;
2372 g_return_if_fail (package != NULL);
2374 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (user_data);
2376 GList *item;
2377 DEBUG_PRINT ("%s", "on_prefs_package_remove");
2378 if ((item = g_list_find_custom (sdb_plugin->session_packages, package,
2379 symbol_db_glist_compare_func)) != NULL)
2381 sdb_plugin->session_packages = g_list_remove_link (sdb_plugin->session_packages,
2382 item);
2384 /* ok, now think to the item left alone by its friends... */
2385 g_list_foreach (item, (GFunc)g_free, NULL);
2386 g_list_free (item);
2390 static void
2391 on_prefs_buffer_update_toggled (SymbolDBPrefs *sdbp, guint value,
2392 gpointer user_data)
2394 SymbolDBPlugin *sdb_plugin;
2395 DEBUG_PRINT ("on_prefs_buffer_update_toggled () %d", value);
2397 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (user_data);
2399 if (value == FALSE)
2401 if (sdb_plugin->buf_update_timeout_id)
2402 g_source_remove (sdb_plugin->buf_update_timeout_id);
2403 sdb_plugin->buf_update_timeout_id = 0;
2405 else
2407 if (sdb_plugin->buf_update_timeout_id == 0)
2408 sdb_plugin->buf_update_timeout_id =
2409 g_timeout_add_seconds (TIMEOUT_INTERVAL_SYMBOLS_UPDATE,
2410 on_editor_buffer_symbols_update_timeout,
2411 sdb_plugin);
2416 static void
2417 ipreferences_merge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** e)
2419 DEBUG_PRINT ("%s", "SymbolDB: ipreferences_merge");
2420 SymbolDBPlugin *sdb_plugin;
2422 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (ipref);
2424 if (sdb_plugin->sdbp == NULL)
2426 sdb_plugin->sdbp = symbol_db_prefs_new (sdb_plugin->sdbs,
2427 sdb_plugin->sdbe_project,
2428 sdb_plugin->sdbe_globals,
2429 prefs,
2430 sdb_plugin->session_packages);
2432 /* connect the signals to retrieve package modifications */
2433 g_signal_connect (G_OBJECT (sdb_plugin->sdbp), "package-add",
2434 G_CALLBACK (on_prefs_package_add),
2435 sdb_plugin);
2436 g_signal_connect (G_OBJECT (sdb_plugin->sdbp), "package-remove",
2437 G_CALLBACK (on_prefs_package_remove),
2438 sdb_plugin);
2439 g_signal_connect (G_OBJECT (sdb_plugin->sdbp), "buffer-update-toggled",
2440 G_CALLBACK (on_prefs_buffer_update_toggled),
2441 sdb_plugin);
2445 static void
2446 ipreferences_unmerge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** e)
2448 SymbolDBPlugin *sdb_plugin;
2450 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (ipref);
2452 if (sdb_plugin->sdbp != NULL)
2454 g_object_unref (sdb_plugin->sdbp);
2455 sdb_plugin->sdbp = NULL;
2459 static void
2460 ipreferences_iface_init(IAnjutaPreferencesIface* iface)
2462 DEBUG_PRINT ("%s", "SymbolDB: ipreferences_iface_init");
2463 iface->merge = ipreferences_merge;
2464 iface->unmerge = ipreferences_unmerge;
2467 /* IAnjutaSymbolManager implementation */
2468 static IAnjutaSymbolQuery*
2469 isymbol_manager_create_query (IAnjutaSymbolManager *isymbol_manager,
2470 IAnjutaSymbolQueryName query_name,
2471 IAnjutaSymbolQueryDb db,
2472 GError **err)
2474 SymbolDBPlugin *sdb_plugin;
2475 SymbolDBQuery *query;
2476 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager);
2478 query = symbol_db_query_new (sdb_plugin->sdbe_globals,
2479 sdb_plugin->sdbe_project, query_name, db);
2480 return IANJUTA_SYMBOL_QUERY (query);
2483 static gboolean
2484 isymbol_manager_add_package (IAnjutaSymbolManager *isymbol_manager,
2485 const gchar* pkg_name,
2486 const gchar* pkg_version,
2487 const GList* files,
2488 GError *err)
2490 SymbolDBPlugin *sdb_plugin;
2491 SymbolDBQuery *query;
2492 IAnjutaLanguage *lang_manager;
2493 GPtrArray *files_array;
2494 GList *node;
2496 sdb_plugin = ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager);
2497 lang_manager =anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin)->shell, IAnjutaLanguage,
2498 NULL);
2500 if (symbol_db_engine_add_new_project (sdb_plugin->sdbe_globals, NULL, pkg_name,
2501 pkg_version) == FALSE)
2503 return FALSE;
2506 files_array = g_ptr_array_sized_new (g_list_length (files));
2507 g_ptr_array_set_free_func (files_array, g_free);
2509 node = files;
2510 while (node != NULL)
2512 g_ptr_array_add (files_array, g_strdup (node->data));
2514 node = node->next;
2517 symbol_db_engine_add_new_files_async (sdb_plugin->sdbe_globals, lang_manager,
2518 pkg_name, pkg_version, files_array);
2520 g_ptr_array_unref (files_array);
2522 return TRUE;
2525 static gboolean
2526 isymbol_manager_activate_package (IAnjutaSymbolManager *isymbol_manager,
2527 const gchar *pkg_name,
2528 const gchar *pkg_version,
2529 GError *err)
2531 return TRUE;
2534 static gboolean
2535 isymbol_manager_deactivate_package (IAnjutaSymbolManager *isymbol_manager,
2536 const gchar *pkg_name,
2537 const gchar *pkg_version,
2538 GError *err)
2541 return TRUE;
2544 static void
2545 isymbol_manager_iface_init (IAnjutaSymbolManagerIface *iface)
2547 iface->create_query = isymbol_manager_create_query;
2548 iface->add_package = isymbol_manager_add_package;
2549 iface->activate_package = isymbol_manager_activate_package;
2550 iface->deactivate_package = isymbol_manager_deactivate_package;
2553 ANJUTA_PLUGIN_BEGIN (SymbolDBPlugin, symbol_db);
2554 ANJUTA_PLUGIN_ADD_INTERFACE (isymbol_manager, IANJUTA_TYPE_SYMBOL_MANAGER);
2555 ANJUTA_PLUGIN_ADD_INTERFACE(ipreferences, IANJUTA_TYPE_PREFERENCES);
2556 ANJUTA_PLUGIN_END;
2558 ANJUTA_SIMPLE_PLUGIN (SymbolDBPlugin, symbol_db);