1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Massimo Cora' 2007-2008 <maxcvs@email.it>
6 * plugin.c is free software.
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
13 * plugin.c is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with plugin.c. If not, write to:
20 * The Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301, USA.
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>
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"/ui/anjuta-symbol-db-plugin.xml"
53 #define BUILDER_FILE PACKAGE_DATA_DIR"/glade/anjuta-symbol-db.ui"
54 #define BUILDER_ROOT "symbol_prefs"
55 #define ICON_FILE "anjuta-symbol-db-plugin-48.png"
56 #define BUFFER_UPDATE "symboldb-buffer-update"
57 #define PARALLEL_SCAN "symboldb-parallel-scan"
58 #define PREFS_BUFFER_UPDATE "preferences_toggle:bool:1:1:symboldb-buffer-update"
59 #define PREFS_PARALLEL_SCAN "preferences_toggle:bool:1:1:symboldb-parallel-scan"
61 #define TIMEOUT_INTERVAL_SYMBOLS_UPDATE 10
62 #define TIMEOUT_SECONDS_AFTER_LAST_TIP 5
64 #define PROJECT_GLOBALS "/"
65 #define SESSION_SECTION "SymbolDB"
66 #define SESSION_KEY "SystemPackages"
68 #define ANJUTA_PIXMAP_GOTO_DECLARATION "element-interface"
69 #define ANJUTA_PIXMAP_GOTO_IMPLEMENTATION "element-method"
71 #define ANJUTA_STOCK_GOTO_DECLARATION "element-interface"
72 #define ANJUTA_STOCK_GOTO_IMPLEMENTATION "element-method"
74 #define PREF_SCHEMA "org.gnome.anjuta.symbol-db"
76 static gpointer parent_class
;
88 TASK_IMPORT_PROJECT
= 1,
89 TASK_IMPORT_PROJECT_AFTER_ABORT
,
97 static unsigned int signals
[LAST_SIGNAL
] = { 0 };
100 register_stock_icons (AnjutaPlugin
*plugin
)
102 static gboolean registered
= FALSE
;
108 /* Register stock icons */
109 BEGIN_REGISTER_ICON (plugin
);
110 REGISTER_ICON (ICON_FILE
, "symbol-db-plugin-icon");
111 REGISTER_ICON_FULL (ANJUTA_PIXMAP_GOTO_DECLARATION
, ANJUTA_STOCK_GOTO_DECLARATION
);
112 REGISTER_ICON_FULL (ANJUTA_PIXMAP_GOTO_IMPLEMENTATION
, ANJUTA_STOCK_GOTO_IMPLEMENTATION
);
117 goto_file_line (AnjutaPlugin
*plugin
, const gchar
*filename
, gint lineno
)
119 IAnjutaDocumentManager
*docman
;
122 g_return_if_fail (filename
!= NULL
);
124 DEBUG_PRINT ("going to: file %s, line %d", filename
, lineno
);
126 /* Go to file and line number */
127 docman
= anjuta_shell_get_interface (plugin
->shell
, IAnjutaDocumentManager
,
129 file
= g_file_new_for_path (filename
);
130 ianjuta_document_manager_goto_file_line (docman
, file
, lineno
, NULL
);
132 g_object_unref (file
);
135 /* Find an implementation (if impl == TRUE) or declaration (if impl == FALSE)
136 * from the given symbol iterator.
137 * If current_document != NULL it prefers matches from the currently open document
140 find_file_line (IAnjutaIterable
*iterator
, gboolean impl
, const gchar
*current_document
,
148 const gchar
*symbol_kind
;
150 IAnjutaSymbol
*iter_node
= IANJUTA_SYMBOL (iterator
);
152 if (iter_node
== NULL
)
154 /* not found or some error occurred */
158 symbol_kind
= ianjuta_symbol_get_string (iter_node
, IANJUTA_SYMBOL_FIELD_KIND
, NULL
);
159 is_decl
= g_strcmp0 (symbol_kind
, "prototype") == 0 ||
160 g_strcmp0 (symbol_kind
, "interface") == 0;
162 if (is_decl
== !impl
)
166 file
= ianjuta_symbol_get_file (iter_node
, NULL
);
167 /* if the path matches the current document we return immidiately */
168 _path
= g_file_get_path (file
);
169 g_object_unref (file
);
170 if (!current_document
|| g_strcmp0 (_path
, current_document
) == 0)
172 *line
= ianjuta_symbol_get_int (iter_node
,
173 IANJUTA_SYMBOL_FIELD_FILE_POS
,
179 /* we store the first match incase there is no match against the current document */
180 else if (_line
== -1)
183 _line
= ianjuta_symbol_get_int (iter_node
,
184 IANJUTA_SYMBOL_FIELD_FILE_POS
,
192 } while (ianjuta_iterable_next (iterator
, NULL
) == TRUE
);
201 goto_file_tag (SymbolDBPlugin
*sdb_plugin
, const gchar
*word
,
202 gboolean prefer_implementation
)
204 IAnjutaIterable
*iterator
;
208 gboolean found
= FALSE
;
209 SymbolDBEngine
*engine
;
211 for (i
= 0; i
< 2; i
++)
215 engine
= sdb_plugin
->sdbe_project
;
219 engine
= sdb_plugin
->sdbe_globals
;
223 if (symbol_db_engine_is_connected (engine
))
225 iterator
= ianjuta_symbol_query_search (sdb_plugin
->search_query
,
229 if (iterator
!= NULL
&& ianjuta_iterable_get_length (iterator
, NULL
) > 0)
231 gchar
*current_document
= NULL
;
232 /* FIXME: namespaces are not handled here, but they should. */
234 if (IANJUTA_IS_FILE (sdb_plugin
->current_editor
))
238 if ((file
= ianjuta_file_get_file (IANJUTA_FILE (sdb_plugin
->current_editor
),
241 current_document
= g_file_get_path (file
);
242 g_object_unref (file
);
246 path
= find_file_line (iterator
, prefer_implementation
, current_document
, &line
);
250 ianjuta_iterable_first (iterator
, NULL
);
251 path
= find_file_line (iterator
, !prefer_implementation
, current_document
,
257 goto_file_line (ANJUTA_PLUGIN (sdb_plugin
), path
, line
);
262 g_free (current_document
);
266 g_object_unref (iterator
);
268 /* have we found it in the project db? */
275 on_goto_file_tag_impl_activate (GtkAction
*action
, SymbolDBPlugin
*sdb_plugin
)
280 if (sdb_plugin
->current_editor
)
282 ed
= IANJUTA_EDITOR (sdb_plugin
->current_editor
);
283 word
= ianjuta_editor_get_current_word (ed
, NULL
);
286 goto_file_tag (sdb_plugin
, word
, TRUE
);
293 on_goto_file_tag_decl_activate (GtkAction
*action
, SymbolDBPlugin
*sdb_plugin
)
298 if (sdb_plugin
->current_editor
)
300 ed
= IANJUTA_EDITOR (sdb_plugin
->current_editor
);
301 word
= ianjuta_editor_get_current_word (ed
, NULL
);
304 goto_file_tag (sdb_plugin
, word
, FALSE
);
311 on_find_symbol (GtkAction
*action
, SymbolDBPlugin
*sdb_plugin
)
313 anjuta_shell_present_widget(ANJUTA_PLUGIN(sdb_plugin
)->shell
,
314 sdb_plugin
->dbv_main
, NULL
);
316 gtk_notebook_set_current_page (GTK_NOTEBOOK(sdb_plugin
->dbv_notebook
), 2);
317 gtk_widget_grab_focus (GTK_WIDGET (sdb_plugin
->search_entry
));
320 static GtkActionEntry actions
[] =
322 { "ActionMenuGoto", NULL
, N_("_Go to"), NULL
, NULL
, NULL
},
324 "ActionSymbolDBGotoDecl",
325 ANJUTA_STOCK_GOTO_DECLARATION
,
326 N_("Tag De_claration"),
328 N_("Go to symbol declaration"),
329 G_CALLBACK (on_goto_file_tag_decl_activate
)
332 "ActionSymbolDBGotoImpl",
333 ANJUTA_STOCK_GOTO_IMPLEMENTATION
,
334 /* Translators: Go to the line where the tag is implemented */
335 N_("Tag _Implementation"),
337 N_("Go to symbol definition"),
338 G_CALLBACK (on_goto_file_tag_impl_activate
)
342 static GtkActionEntry actions_search
[] = {
344 "ActionEditSearchFindSymbol", GTK_STOCK_FIND
, N_("_Find Symbol…"),
345 "<control>l", N_("Find Symbol"),
346 G_CALLBACK (on_find_symbol
)
351 editor_buffer_symbols_update (IAnjutaEditor
*editor
, SymbolDBPlugin
*sdb_plugin
)
353 gchar
*current_buffer
= NULL
;
354 gsize buffer_size
= 0;
357 GPtrArray
*real_files_list
;
358 GPtrArray
*text_buffers
;
359 GPtrArray
*buffer_sizes
;
363 /* we won't proceed with the updating of the symbols if we didn't type in
365 if (sdb_plugin
->need_symbols_update
== FALSE
)
370 buffer_size
= ianjuta_editor_get_length (editor
, NULL
);
371 current_buffer
= ianjuta_editor_get_text_all (editor
, NULL
);
373 file
= ianjuta_file_get_file (IANJUTA_FILE (editor
), NULL
);
381 /* take the path reference */
382 local_path
= g_file_get_path (file
);
384 /* ok that's good. Let's have a last check: is the current file present
385 * on the buffer_update_files?
387 for (i
= 0; i
< sdb_plugin
->buffer_update_files
->len
; i
++)
389 if (g_strcmp0 (g_ptr_array_index (sdb_plugin
->buffer_update_files
, i
),
392 /* hey we found it */
393 /* something is already scanning this buffer file. Drop the procedure now. */
394 DEBUG_PRINT ("something is already scanning the file %s", local_path
);
399 real_files_list
= g_ptr_array_new_with_free_func (g_free
);
400 g_ptr_array_add (real_files_list
, local_path
);
402 text_buffers
= g_ptr_array_new ();
403 g_ptr_array_add (text_buffers
, current_buffer
);
405 buffer_sizes
= g_ptr_array_new ();
406 g_ptr_array_add (buffer_sizes
, GINT_TO_POINTER (buffer_size
));
410 if (symbol_db_engine_is_connected (sdb_plugin
->sdbe_project
))
412 proc_id
= symbol_db_engine_update_buffer_symbols (sdb_plugin
->sdbe_project
,
413 sdb_plugin
->project_opened
,
421 /* good. All is ready for a buffer scan. Add the file_scan into the arrays */
422 gchar
* local_path_dup
= g_strdup (local_path
);
423 g_ptr_array_add (sdb_plugin
->buffer_update_files
, local_path_dup
);
425 g_ptr_array_add (sdb_plugin
->buffer_update_ids
, GINT_TO_POINTER (proc_id
));
427 /* add a task so that scan_end_manager can manage this */
428 g_tree_insert (sdb_plugin
->proc_id_tree
, GINT_TO_POINTER (proc_id
),
429 GINT_TO_POINTER (TASK_BUFFER_UPDATE
));
432 g_ptr_array_unref (real_files_list
);
433 g_free (current_buffer
);
434 g_object_unref (file
);
436 /* no need to free local_path, it'll be automatically freed later by the buffer_update
439 sdb_plugin
->need_symbols_update
= FALSE
;
441 return proc_id
> 0 ? TRUE
: FALSE
;
444 on_editor_buffer_symbols_update_timeout (gpointer user_data
)
446 SymbolDBPlugin
*sdb_plugin
;
447 gdouble seconds_elapsed
;
449 g_return_val_if_fail (user_data
!= NULL
, FALSE
);
451 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (user_data
);
453 if (sdb_plugin
->current_editor
== NULL
)
456 /* check the timer. If it's elapsed enought time since the last time the user
457 * typed in something, than proceed with updating, elsewhere don't do nothing
459 if (sdb_plugin
->update_timer
== NULL
)
462 seconds_elapsed
= g_timer_elapsed (sdb_plugin
->update_timer
, NULL
);
464 if (seconds_elapsed
< TIMEOUT_SECONDS_AFTER_LAST_TIP
)
467 return editor_buffer_symbols_update (IANJUTA_EDITOR (sdb_plugin
->current_editor
),
472 on_editor_buffer_symbol_update_scan_end (SymbolDBEngine
*dbe
, gint process_id
,
475 SymbolDBPlugin
*sdb_plugin
;
478 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (data
);
480 /* search for the proc id */
481 for (i
= 0; i
< sdb_plugin
->buffer_update_ids
->len
; i
++)
483 if (g_ptr_array_index (sdb_plugin
->buffer_update_ids
, i
) == GINT_TO_POINTER (process_id
))
485 /* hey we found it */
486 /* remove both the items */
487 g_ptr_array_remove_index (sdb_plugin
->buffer_update_ids
, i
);
489 g_ptr_array_remove_index (sdb_plugin
->buffer_update_files
, i
);
491 /* no need to free the string coz the g_ptr_array is built with
492 * g_ptr_array_new_with_free_func (g_free)
497 /* was the updating of view-locals symbols blocked while we were scanning?
498 * e.g. was the editor switched? */
499 if (sdb_plugin
->buffer_update_semaphore
== TRUE
)
503 gboolean tags_update
;
504 if (!IANJUTA_IS_EDITOR (sdb_plugin
->current_editor
))
507 file
= ianjuta_file_get_file (IANJUTA_FILE (sdb_plugin
->current_editor
),
513 local_path
= g_file_get_path (file
);
515 if (local_path
== NULL
)
517 g_critical ("local_path == NULL");
521 /* add a default timeout to the updating of buffer symbols */
522 tags_update
= g_settings_get_boolean (sdb_plugin
->settings
, BUFFER_UPDATE
);
526 sdb_plugin
->buf_update_timeout_id
=
527 g_timeout_add_seconds (TIMEOUT_INTERVAL_SYMBOLS_UPDATE
,
528 on_editor_buffer_symbols_update_timeout
,
533 sdb_plugin
->buffer_update_semaphore
= FALSE
;
538 on_editor_destroy (SymbolDBPlugin
*sdb_plugin
, IAnjutaEditor
*editor
)
540 if (!sdb_plugin
->editor_connected
)
542 DEBUG_PRINT ("%s", "on_editor_destroy (): returning….");
546 g_hash_table_remove (sdb_plugin
->editor_connected
, G_OBJECT (editor
));
548 if (g_hash_table_size (sdb_plugin
->editor_connected
) <= 0)
550 DEBUG_PRINT ("%s", "displaying nothing…");
551 if (sdb_plugin
->file_model
)
552 g_object_set (sdb_plugin
->file_model
, "file-path", NULL
, NULL
);
557 on_editor_update_ui (IAnjutaEditor
*editor
, SymbolDBPlugin
*sdb_plugin
)
559 g_timer_reset (sdb_plugin
->update_timer
);
563 on_code_added (IAnjutaEditor
*editor
, IAnjutaIterable
*position
, gchar
*code
,
564 SymbolDBPlugin
*sdb_plugin
)
566 sdb_plugin
->need_symbols_update
= TRUE
;
567 editor_buffer_symbols_update (editor
, sdb_plugin
);
571 on_char_added (IAnjutaEditor
*editor
, IAnjutaIterable
*position
, gchar ch
,
572 SymbolDBPlugin
*sdb_plugin
)
574 g_timer_reset (sdb_plugin
->update_timer
);
576 /* Update when the user enters a newline */
578 sdb_plugin
->need_symbols_update
= TRUE
;
582 on_editor_saved (IAnjutaEditor
*editor
, GFile
* file
,
583 SymbolDBPlugin
*sdb_plugin
)
585 const gchar
*old_uri
;
586 gchar
*local_filename
;
588 GPtrArray
*files_array
;
592 local_filename
= g_file_get_path (file
);
593 /* Verify that it's local file */
594 g_return_if_fail (local_filename
!= NULL
);
596 saved_uri
= g_file_get_uri (file
);
598 for (i
= 0; i
< sdb_plugin
->buffer_update_files
->len
; i
++)
600 if (g_strcmp0 (g_ptr_array_index (sdb_plugin
->buffer_update_files
, i
),
601 local_filename
) == 0)
603 DEBUG_PRINT ("already scanning");
604 /* something is already scanning this buffer file. Drop the procedure now. */
609 files_array
= g_ptr_array_new();
610 g_ptr_array_add (files_array
, local_filename
);
611 /* no need to free local_filename now */
613 if (!sdb_plugin
->editor_connected
)
616 old_uri
= g_hash_table_lookup (sdb_plugin
->editor_connected
, editor
);
618 if (old_uri
&& strlen (old_uri
) <= 0)
621 /* files_array will be freed once updating has taken place */
623 if (symbol_db_engine_is_connected (sdb_plugin
->sdbe_project
))
625 proc_id
= symbol_db_engine_update_files_symbols (sdb_plugin
->sdbe_project
,
626 sdb_plugin
->project_root_dir
, files_array
, TRUE
);
631 /* add a task so that scan_end_manager can manage this */
632 g_tree_insert (sdb_plugin
->proc_id_tree
, GINT_TO_POINTER (proc_id
),
633 GINT_TO_POINTER (TASK_FILE_UPDATE
));
636 g_hash_table_insert (sdb_plugin
->editor_connected
, editor
,
637 g_strdup (saved_uri
));
639 /* if we saved it we shouldn't update a second time */
640 sdb_plugin
->need_symbols_update
= FALSE
;
642 on_editor_update_ui (editor
, sdb_plugin
);
647 value_added_current_editor (AnjutaPlugin
*plugin
, const char *name
,
648 const GValue
*value
, gpointer data
)
651 gboolean tags_update
;
655 SymbolDBPlugin
*sdb_plugin
;
657 editor
= g_value_get_object (value
);
658 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
659 if (sdb_plugin
->session_loading
)
664 DEBUG_PRINT ("%s", "Updating symbols");
666 if (!sdb_plugin
->editor_connected
)
668 sdb_plugin
->editor_connected
= g_hash_table_new_full (g_direct_hash
,
672 sdb_plugin
->current_editor
= editor
;
674 if (!IANJUTA_IS_EDITOR (editor
))
677 file
= ianjuta_file_get_file (IANJUTA_FILE (editor
), NULL
);
682 local_path
= g_file_get_path (file
);
683 uri
= g_file_get_uri (file
);
685 if (local_path
== NULL
)
687 g_critical ("local_path == NULL");
691 /* we can have a weird behaviour here if we're not paying the right attention:
692 * A timeout scan could have been launched and a millisecond later the user could
693 * have switched editor: we'll be getting the symbol inserted in the previous
694 * editor into the new one's view.
696 if (sdb_plugin
->buffer_update_files
->len
> 0)
698 sdb_plugin
->buffer_update_semaphore
= TRUE
;
702 g_object_set (sdb_plugin
->file_model
, "file-path", local_path
, NULL
);
704 /* add a default timeout to the updating of buffer symbols */
705 tags_update
= g_settings_get_boolean (sdb_plugin
->settings
, BUFFER_UPDATE
);
710 sdb_plugin
->buf_update_timeout_id
=
711 g_timeout_add_seconds (TIMEOUT_INTERVAL_SYMBOLS_UPDATE
,
712 on_editor_buffer_symbols_update_timeout
,
717 if (g_hash_table_lookup (sdb_plugin
->editor_connected
, editor
) == NULL
)
719 g_object_weak_ref (G_OBJECT (editor
),
720 (GWeakNotify
) (on_editor_destroy
),
724 g_hash_table_insert (sdb_plugin
->editor_connected
, editor
,
729 g_hash_table_insert (sdb_plugin
->editor_connected
, editor
,
733 g_signal_connect (G_OBJECT (editor
), "saved",
734 G_CALLBACK (on_editor_saved
),
736 g_signal_connect (G_OBJECT (editor
), "char-added",
737 G_CALLBACK (on_char_added
),
739 g_signal_connect (G_OBJECT (editor
), "code-added",
740 G_CALLBACK (on_code_added
),
742 g_signal_connect (G_OBJECT(editor
), "update_ui",
743 G_CALLBACK (on_editor_update_ui
),
749 sdb_plugin
->need_symbols_update
= FALSE
;
753 on_editor_foreach_disconnect (gpointer key
, gpointer value
, gpointer user_data
)
755 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
756 G_CALLBACK (on_editor_saved
),
758 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
759 G_CALLBACK (on_editor_update_ui
),
761 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
762 G_CALLBACK (on_char_added
),
764 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
765 G_CALLBACK (on_code_added
),
767 g_object_weak_unref (G_OBJECT(key
),
768 (GWeakNotify
) (on_editor_destroy
),
773 value_removed_current_editor (AnjutaPlugin
*plugin
,
774 const char *name
, gpointer data
)
776 SymbolDBPlugin
*sdb_plugin
;
778 sdb_plugin
= (SymbolDBPlugin
*) plugin
;
780 DEBUG_PRINT ("%s", "value_removed_current_editor ()");
781 /* let's remove the timeout for symbols refresh */
782 if (sdb_plugin
->buf_update_timeout_id
)
783 g_source_remove (sdb_plugin
->buf_update_timeout_id
);
784 sdb_plugin
->buf_update_timeout_id
= 0;
785 sdb_plugin
->need_symbols_update
= FALSE
;
787 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
788 sdb_plugin
->current_editor
= NULL
;
792 * Perform the real add to the db and also checks that no dups are inserted.
793 * Return the real number of files added or -1 on error.
796 do_add_new_files (SymbolDBPlugin
*sdb_plugin
, const GPtrArray
*sources_array
,
799 GPtrArray
* languages_array
= NULL
;
800 GPtrArray
* to_scan_array
= NULL
;
801 GHashTable
* check_unique_file_hash
= NULL
;
802 IAnjutaLanguage
* lang_manager
;
803 AnjutaPlugin
*plugin
;
808 plugin
= ANJUTA_PLUGIN (sdb_plugin
);
810 /* create array of languages and the wannabe scanned files */
811 languages_array
= g_ptr_array_new_with_free_func (g_free
);
812 to_scan_array
= g_ptr_array_new_with_free_func (g_free
);
814 /* to speed the things up we must avoid the dups */
815 check_unique_file_hash
= g_hash_table_new_full (g_str_hash
,
816 g_str_equal
, NULL
, NULL
);
818 lang_manager
= anjuta_shell_get_interface (plugin
->shell
, IAnjutaLanguage
,
823 g_critical ("LanguageManager not found");
827 for (i
=0; i
< sources_array
->len
; i
++)
829 const gchar
*file_mime
;
831 const gchar
*local_filename
;
833 GFileInfo
*gfile_info
;
834 IAnjutaLanguageId lang_id
;
836 if ( (local_filename
= g_ptr_array_index (sources_array
, i
)) == NULL
)
839 if ((gfile
= g_file_new_for_path (local_filename
)) == NULL
)
842 gfile_info
= g_file_query_info (gfile
,
843 "standard::content-type",
844 G_FILE_QUERY_INFO_NONE
,
847 if (gfile_info
== NULL
)
849 g_object_unref (gfile
);
853 /* check if it's already present in the list. This avoids
856 if (g_hash_table_lookup (check_unique_file_hash
,
857 local_filename
) == NULL
)
859 g_hash_table_insert (check_unique_file_hash
,
860 (gpointer
)local_filename
,
861 (gpointer
)local_filename
);
865 /* you're a dup! we don't want you */
869 file_mime
= g_file_info_get_attribute_string (gfile_info
,
870 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE
);
872 lang_id
= ianjuta_language_get_from_mime_type (lang_manager
,
877 g_object_unref (gfile
);
878 g_object_unref (gfile_info
);
882 lang
= ianjuta_language_get_name (lang_manager
, lang_id
, NULL
);
884 /* test its existence */
885 if (g_file_test (local_filename
, G_FILE_TEST_EXISTS
) == FALSE
)
887 g_object_unref (gfile
);
888 g_object_unref (gfile_info
);
892 /* ok, we've just tested that the local_filename does exist.
893 * We can safely add it to the array.
895 g_ptr_array_add (languages_array
, g_strdup (lang
));
896 g_ptr_array_add (to_scan_array
, g_strdup (local_filename
));
897 g_object_unref (gfile
);
898 g_object_unref (gfile_info
);
901 /* last but not least check if we had some files in that GPtrArray. It that's not
902 * the case just pass over
905 if (to_scan_array
->len
> 0)
907 proc_id
= symbol_db_engine_add_new_files_full_async (sdb_plugin
->sdbe_project
,
908 sdb_plugin
->project_opened
, "1.0", to_scan_array
, languages_array
,
914 /* insert the proc id associated within the task */
915 g_tree_insert (sdb_plugin
->proc_id_tree
, GINT_TO_POINTER (proc_id
),
916 GINT_TO_POINTER (task
));
919 /* get the real added number of files */
920 added_num
= to_scan_array
->len
;
922 g_ptr_array_unref (languages_array
);
923 g_ptr_array_unref (to_scan_array
);
925 g_hash_table_destroy (check_unique_file_hash
);
927 return proc_id
> 0 ? added_num
: -1;
931 on_project_element_added (IAnjutaProjectManager
*pm
, GFile
*gfile
,
932 SymbolDBPlugin
*sdb_plugin
)
936 GPtrArray
*files_array
;
938 g_return_if_fail (sdb_plugin
->project_root_uri
!= NULL
);
939 g_return_if_fail (sdb_plugin
->project_root_dir
!= NULL
);
941 filename
= g_file_get_path (gfile
);
943 files_array
= g_ptr_array_new_with_free_func (g_free
);
944 g_ptr_array_add (files_array
, filename
);
946 sdb_plugin
->is_adding_element
= TRUE
;
948 /* use a custom function to add the files to db */
949 real_added
= do_add_new_files (sdb_plugin
, files_array
, TASK_ELEMENT_ADDED
);
952 sdb_plugin
->is_adding_element
= FALSE
;
955 g_ptr_array_unref (files_array
);
959 on_project_element_removed (IAnjutaProjectManager
*pm
, GFile
*gfile
,
960 SymbolDBPlugin
*sdb_plugin
)
964 if (!sdb_plugin
->project_root_uri
)
967 filename
= g_file_get_path (gfile
);
971 DEBUG_PRINT ("%s", "on_project_element_removed");
972 symbol_db_engine_remove_file (sdb_plugin
->sdbe_project
,
973 sdb_plugin
->project_root_dir
,
974 symbol_db_util_get_file_db_path (sdb_plugin
->sdbe_project
,
982 on_system_scan_package_start (SymbolDBEngine
*dbe
, guint num_files
,
983 const gchar
*package
, gpointer user_data
)
985 SymbolDBPlugin
*sdb_plugin
;
986 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (user_data
);
988 sdb_plugin
->files_count_system_done
= 0;
989 sdb_plugin
->files_count_system
+= num_files
;
992 /* show the global bar */
993 gtk_widget_show (sdb_plugin
->progress_bar_system
);
994 if (sdb_plugin
->current_scanned_package
!= NULL
)
995 g_free (sdb_plugin
->current_scanned_package
);
996 sdb_plugin
->current_scanned_package
= g_strdup (package
);
998 DEBUG_PRINT ("********************* START [%s] with n %d files ", package
, num_files
);
1002 on_system_scan_package_end (SymbolDBEngine
*dbe
, const gchar
*package
,
1005 SymbolDBPlugin
*sdb_plugin
;
1006 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (user_data
);
1008 DEBUG_PRINT ("******************** END () [%s]", package
);
1010 /* hide the progress bar */
1011 gtk_widget_hide (sdb_plugin
->progress_bar_system
);
1013 sdb_plugin
->files_count_system_done
= 0;
1014 sdb_plugin
->files_count_system
= 0;
1018 on_system_single_file_scan_end (SymbolDBEngine
*dbe
, gpointer data
)
1020 AnjutaPlugin
*plugin
;
1021 SymbolDBPlugin
*sdb_plugin
;
1023 gdouble fraction
= 0;
1025 plugin
= ANJUTA_PLUGIN (data
);
1026 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
1028 sdb_plugin
->files_count_system_done
++;
1029 if (sdb_plugin
->files_count_system_done
>= sdb_plugin
->files_count_system
)
1031 message
= g_strdup_printf (_("%s: Generating inheritances…"),
1032 sdb_plugin
->current_scanned_package
);
1036 /* Translators: %s is the name of a system library */
1037 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
),
1038 sdb_plugin
->current_scanned_package
,
1039 sdb_plugin
->files_count_system_done
,
1040 sdb_plugin
->files_count_system
);
1043 if (sdb_plugin
->files_count_system
> 0)
1045 fraction
= (gdouble
) sdb_plugin
->files_count_system_done
/
1046 (gdouble
) sdb_plugin
->files_count_system
;
1048 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_system
),
1050 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_system
), message
);
1056 on_project_single_file_scan_end (SymbolDBEngine
*dbe
, gpointer data
)
1058 AnjutaPlugin
*plugin
;
1059 SymbolDBPlugin
*sdb_plugin
;
1061 gdouble fraction
= 0;
1063 plugin
= ANJUTA_PLUGIN (data
);
1064 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
1066 sdb_plugin
->files_count_project_done
++;
1067 if (sdb_plugin
->files_count_project_done
>= sdb_plugin
->files_count_project
)
1068 message
= g_strdup_printf (_("Generating inheritances…"));
1070 message
= g_strdup_printf (ngettext ("%d file scanned out of %d", "%d files scanned out of %d", sdb_plugin
->files_count_project_done
),
1071 sdb_plugin
->files_count_project_done
, sdb_plugin
->files_count_project
);
1073 if (sdb_plugin
->files_count_project
> 0)
1075 fraction
= (gdouble
) sdb_plugin
->files_count_project_done
/
1076 (gdouble
) sdb_plugin
->files_count_project
;
1080 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_project
),
1082 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_project
), message
);
1083 gtk_widget_show (sdb_plugin
->progress_bar_project
);
1088 clear_project_progress_bar (SymbolDBEngine
*dbe
, gpointer data
)
1090 SymbolDBPlugin
*sdb_plugin
;
1092 g_return_if_fail (data
!= NULL
);
1094 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (data
);
1096 /* hide the progress bar */
1097 gtk_widget_hide (sdb_plugin
->progress_bar_project
);
1101 on_check_offline_single_file_scan_end (SymbolDBEngine
*dbe
, gpointer data
)
1103 on_project_single_file_scan_end (dbe
, data
);
1106 /* note the *system* word in the function */
1108 do_import_system_sources_after_abort (SymbolDBPlugin
*sdb_plugin
,
1109 const GPtrArray
*sources_array
)
1111 AnjutaPlugin
*plugin
;
1112 GPtrArray
* languages_array
= NULL
;
1113 GPtrArray
*to_scan_array
= NULL
;
1114 IAnjutaLanguage
* lang_manager
;
1117 plugin
= ANJUTA_PLUGIN (sdb_plugin
);
1119 lang_manager
= anjuta_shell_get_interface (plugin
->shell
, IAnjutaLanguage
,
1122 /* create array of languages */
1123 languages_array
= g_ptr_array_new ();
1124 to_scan_array
= g_ptr_array_new ();
1128 g_critical ("LanguageManager not found");
1132 for (i
=0; i
< sources_array
->len
; i
++)
1134 const gchar
*file_mime
;
1136 const gchar
*local_filename
;
1138 GFileInfo
*gfile_info
;
1139 IAnjutaLanguageId lang_id
;
1141 local_filename
= g_ptr_array_index (sources_array
, i
);
1143 if (local_filename
== NULL
)
1146 gfile
= g_file_new_for_path (local_filename
);
1150 gfile_info
= g_file_query_info (gfile
,
1152 G_FILE_QUERY_INFO_NONE
,
1155 if (gfile_info
== NULL
)
1157 g_object_unref (gfile
);
1161 file_mime
= g_file_info_get_attribute_string (gfile_info
,
1162 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE
);
1164 lang_id
= ianjuta_language_get_from_mime_type (lang_manager
,
1169 g_object_unref (gfile
);
1170 g_object_unref (gfile_info
);
1174 lang
= ianjuta_language_get_name (lang_manager
, lang_id
, NULL
);
1176 /* test its existence */
1177 if (g_file_test (local_filename
, G_FILE_TEST_EXISTS
) == FALSE
)
1179 g_object_unref (gfile
);
1180 g_object_unref (gfile_info
);
1184 g_ptr_array_add (languages_array
, g_strdup (lang
));
1185 g_ptr_array_add (to_scan_array
, g_strdup (local_filename
));
1186 g_object_unref (gfile
);
1187 g_object_unref (gfile_info
);
1190 /* FIXME HERE currently disabled */
1192 symbol_db_system_parse_aborted_package (sdb_plugin
->sdbs
,
1196 /* no need to free the GPtrArray, Huston. They'll be auto-destroyed in that
1201 /* we assume that sources_array has already unique elements */
1202 /* note the *project* word in the function */
1204 do_import_project_sources_after_abort (SymbolDBPlugin
*sdb_plugin
,
1205 const GPtrArray
*sources_array
)
1209 sdb_plugin
->is_project_importing
= TRUE
;
1211 /* connect to receive signals on single file scan complete. We'll
1212 * update a status bar notifying the user about the status
1214 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_project
), "single-file-scan-end",
1215 G_CALLBACK (on_project_single_file_scan_end
), sdb_plugin
);
1217 real_added
= do_add_new_files (sdb_plugin
, sources_array
,
1218 TASK_IMPORT_PROJECT_AFTER_ABORT
);
1219 if (real_added
<= 0)
1221 sdb_plugin
->is_project_importing
= FALSE
;
1225 sdb_plugin
->files_count_project
+= real_added
;
1230 do_import_project_sources (SymbolDBPlugin
*sdb_plugin
, IAnjutaProjectManager
*pm
,
1231 const gchar
*root_dir
)
1233 GList
* prj_elements_list
;
1234 GPtrArray
* sources_array
;
1238 prj_elements_list
= ianjuta_project_manager_get_elements (pm
,
1239 ANJUTA_PROJECT_SOURCE
| ANJUTA_PROJECT_PROJECT
,
1242 if (prj_elements_list
== NULL
)
1244 g_warning ("No sources found within this project");
1248 /* if we're importing first shut off the signal receiving.
1249 * We'll re-enable that on scan-end
1251 sdb_plugin
->is_project_importing
= TRUE
;
1252 DEBUG_PRINT ("Retrieving %d gbf sources of the project…",
1253 g_list_length (prj_elements_list
));
1255 /* create the storage array. The file names will be strdup'd and put here.
1256 * This is just a sort of GList -> GPtrArray conversion.
1258 sources_array
= g_ptr_array_new_with_free_func (g_free
);
1259 for (i
=0; i
< g_list_length (prj_elements_list
); i
++)
1261 gchar
*local_filename
;
1262 GFile
*gfile
= NULL
;
1264 gfile
= g_list_nth_data (prj_elements_list
, i
);
1266 if ((local_filename
= g_file_get_path (gfile
)) == NULL
)
1271 g_ptr_array_add (sources_array
, local_filename
);
1274 /* connect to receive signals on single file scan complete. We'll
1275 * update a status bar notifying the user about the status
1277 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_project
), "single-file-scan-end",
1278 G_CALLBACK (on_project_single_file_scan_end
), sdb_plugin
);
1280 real_added
= do_add_new_files (sdb_plugin
, sources_array
, TASK_IMPORT_PROJECT
);
1281 if (real_added
<= 0)
1283 sdb_plugin
->is_project_importing
= FALSE
;
1285 sdb_plugin
->files_count_project
+= real_added
;
1288 /* free the ptr array */
1289 g_ptr_array_unref (sources_array
);
1291 /* and the list of project files */
1292 g_list_foreach (prj_elements_list
, (GFunc
) g_object_unref
, NULL
);
1293 g_list_free (prj_elements_list
);
1297 * This function will call do_import_project_sources_after_abort ().
1298 * The list of files for sysstem packages enqueued on the first scan aren't
1299 * persisted on session for later retrieval. So we can only rely
1300 * on fixing the zero-symbols file.
1303 do_import_system_sources (SymbolDBPlugin
*sdb_plugin
)
1305 /* the resume thing */
1306 GPtrArray
*sys_src_array
= NULL
;
1308 symbol_db_util_get_files_with_zero_symbols (sdb_plugin
->sdbe_globals
);
1310 if (sys_src_array
!= NULL
&& sys_src_array
->len
> 0)
1312 do_import_system_sources_after_abort (sdb_plugin
, sys_src_array
);
1314 g_ptr_array_unref (sys_src_array
);
1319 * @return TRUE if a scan is in progress, FALSE elsewhere.
1322 do_update_project_symbols (SymbolDBPlugin
*sdb_plugin
, const gchar
*root_dir
)
1325 /* Update the symbols */
1326 proc_id
= symbol_db_engine_update_project_symbols (sdb_plugin
->sdbe_project
,
1330 sdb_plugin
->is_project_updating
= TRUE
;
1332 /* insert the proc id associated within the task */
1333 g_tree_insert (sdb_plugin
->proc_id_tree
, GINT_TO_POINTER (proc_id
),
1334 GINT_TO_POINTER (TASK_PROJECT_UPDATE
));
1342 * do_check_offline_files_changed:
1345 * Returns: TRUE if a scan process is started, FALSE elsewhere.
1348 do_check_offline_files_changed (SymbolDBPlugin
*sdb_plugin
)
1350 GList
* prj_elements_list
;
1352 IAnjutaProjectManager
*pm
;
1353 GHashTable
*prj_elements_hash
;
1354 GPtrArray
*to_add_files
= NULL
;
1355 gint real_added
= 0;
1357 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
,
1358 IAnjutaProjectManager
, NULL
);
1360 prj_elements_list
= ianjuta_project_manager_get_elements (pm
,
1361 ANJUTA_PROJECT_SOURCE
| ANJUTA_PROJECT_PROJECT
,
1364 /* fill an hash table with all the items of the list just taken.
1365 * We won't g_strdup () the elements because they'll be freed later
1367 prj_elements_hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
,
1370 node
= prj_elements_list
;
1371 while (node
!= NULL
)
1378 if ((filename
= g_file_get_path (gfile
)) == NULL
||
1379 g_strcmp0 (filename
, "") == 0)
1382 g_object_unref (gfile
);
1384 node
= g_list_next (node
);
1388 /* test its existence */
1389 if (g_file_query_exists (gfile
, NULL
) == FALSE
)
1392 g_object_unref (gfile
);
1394 node
= g_list_next (node
);
1398 /* Use g_hash_table_replace instead of g_hash_table_insert because the key
1399 * and the value use the same block of memory, both must be changed at
1401 g_hash_table_replace (prj_elements_hash
,
1402 (gpointer
) symbol_db_util_get_file_db_path
1403 (sdb_plugin
->sdbe_project
,
1406 g_object_unref (gfile
);
1408 node
= g_list_next (node
);
1412 /* some files may have added/removed editing Makefile.am while
1413 * Anjuta was offline. Check this case too.
1414 * FIXME: Get rid of data model here.
1416 GdaDataModel
*model
=
1417 symbol_db_engine_get_files_for_project (sdb_plugin
->sdbe_project
);
1418 GdaDataModelIter
*it
=
1419 gda_data_model_create_iter (model
);
1421 if (it
&& gda_data_model_iter_move_to_row (it
, 0))
1423 GPtrArray
*remove_array
;
1424 remove_array
= g_ptr_array_new_with_free_func (g_free
);
1426 const GValue
*val
= gda_data_model_iter_get_value_at (it
, 0);
1427 const gchar
* file
= g_value_get_string (val
);
1429 if (file
&& g_hash_table_remove (prj_elements_hash
, file
) == FALSE
)
1430 g_ptr_array_add (remove_array
, g_strdup (file
));
1432 } while (gda_data_model_iter_move_next (it
));
1434 symbol_db_engine_remove_files (sdb_plugin
->sdbe_project
,
1435 sdb_plugin
->project_opened
,
1437 g_ptr_array_unref (remove_array
);
1440 /* great, at this point we should have this situation:
1441 * remove array = files to remove, remaining items in the hash_table = files
1444 to_add_files
= g_ptr_array_new ();
1445 if (g_hash_table_size (prj_elements_hash
) > 0)
1448 GList
*keys
= g_hash_table_get_keys (prj_elements_hash
);
1450 /* get all the nodes from the hash table and add them to the wannabe-added
1453 for (i
= 0; i
< g_hash_table_size (prj_elements_hash
); i
++)
1455 /*DEBUG_PRINT ("ARRAY ADD %s", (gchar*)g_list_nth_data (keys, i));*/
1456 g_ptr_array_add (to_add_files
,
1457 g_hash_table_lookup (prj_elements_hash
,
1458 g_list_nth_data (keys
, i
)));
1462 /* good. Let's go on with add of new files. */
1463 if (to_add_files
->len
> 0)
1465 /* block the signals spreading from engine to local-view tab */
1466 sdb_plugin
->is_offline_scanning
= TRUE
;
1467 real_added
= do_add_new_files (sdb_plugin
, to_add_files
,
1468 TASK_OFFLINE_CHANGES
);
1470 DEBUG_PRINT ("going to do add %d files with TASK_OFFLINE_CHANGES",
1473 if (real_added
<= 0)
1475 sdb_plugin
->is_offline_scanning
= FALSE
;
1478 /* connect to receive signals on single file scan complete. We'll
1479 * update a status bar notifying the user about the status
1481 sdb_plugin
->files_count_project
+= real_added
;
1483 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_project
), "single-file-scan-end",
1484 G_CALLBACK (on_check_offline_single_file_scan_end
), ANJUTA_PLUGIN (sdb_plugin
));
1488 /*if (it != NULL) g_object_unref (it);*/
1489 g_object_unref (it
);
1490 g_object_unref (model
);
1491 g_ptr_array_unref (to_add_files
);
1492 g_hash_table_destroy (prj_elements_hash
);
1494 return real_added
> 0 ? TRUE
: FALSE
;
1498 on_session_save (AnjutaShell
*shell
, AnjutaSessionPhase phase
,
1499 AnjutaSession
*session
,
1500 SymbolDBPlugin
*sdb_plugin
)
1502 if (phase
!= ANJUTA_SESSION_PHASE_NORMAL
)
1505 DEBUG_PRINT ("%s", "SymbolDB: session_save");
1509 on_session_load (AnjutaShell
*shell
, AnjutaSessionPhase phase
,
1510 AnjutaSession
*session
,
1511 SymbolDBPlugin
*sdb_plugin
)
1513 if (phase
== ANJUTA_SESSION_PHASE_START
)
1515 DEBUG_PRINT ("SymbolDB: session_loading started. Getting info from %s",
1516 anjuta_session_get_session_directory (session
));
1517 sdb_plugin
->session_loading
= TRUE
;
1519 /* get preferences about the parallel scan */
1520 gboolean parallel_scan
= g_settings_get_boolean (sdb_plugin
->settings
,
1523 if (parallel_scan
== TRUE
&&
1524 symbol_db_engine_is_connected (sdb_plugin
->sdbe_globals
) == TRUE
)
1526 /* we simulate a project-import-end signal received */
1527 do_import_system_sources (sdb_plugin
);
1530 else if (phase
== ANJUTA_SESSION_PHASE_END
)
1532 IAnjutaDocumentManager
* docman
;
1533 sdb_plugin
->session_loading
= FALSE
;
1534 DEBUG_PRINT ("SymbolDB: session_loading finished");
1536 /* Show the symbols for the current editor */
1537 docman
= anjuta_shell_get_interface (shell
, IAnjutaDocumentManager
, NULL
);
1540 IAnjutaDocument
* cur_doc
=
1541 ianjuta_document_manager_get_current_document (docman
, NULL
);
1544 GValue value
= {0, };
1545 g_value_init (&value
, G_TYPE_OBJECT
);
1546 g_value_set_object (&value
, cur_doc
);
1547 value_added_current_editor (ANJUTA_PLUGIN (sdb_plugin
),
1548 "document_manager_current_document",
1550 g_value_unset(&value
);
1554 if (sdb_plugin
->project_opened
== NULL
)
1556 gtk_widget_hide (sdb_plugin
->progress_bar_project
);
1557 gtk_widget_hide (sdb_plugin
->progress_bar_system
);
1563 on_project_loaded (IAnjutaProjectManager
*pm
, GError
*error
,
1564 SymbolDBPlugin
*sdb_plugin
)
1566 g_return_if_fail (sdb_plugin
->project_root_uri
!= NULL
);
1567 g_return_if_fail (sdb_plugin
->project_root_dir
!= NULL
);
1569 /* Malformed project abort */
1570 if (error
!= NULL
) return;
1573 * we need an initial import
1575 if (sdb_plugin
->needs_sources_scan
== TRUE
)
1577 DEBUG_PRINT ("Importing sources.");
1578 do_import_project_sources (sdb_plugin
, pm
, sdb_plugin
->project_root_dir
);
1583 * no import needed. But we may have aborted the scan of sources in
1584 * a previous session..
1586 GPtrArray
*sources_array
= NULL
;
1588 DEBUG_PRINT ("Checking for files with zero symbols.");
1590 symbol_db_util_get_files_with_zero_symbols (sdb_plugin
->sdbe_project
);
1592 if (sources_array
!= NULL
&& sources_array
->len
> 0)
1594 DEBUG_PRINT ("Importing files after abort.");
1595 do_import_project_sources_after_abort (sdb_plugin
, sources_array
);
1597 g_ptr_array_unref (sources_array
);
1600 DEBUG_PRINT ("Checking for offline changes.");
1601 /* check for offline changes */
1602 if (do_check_offline_files_changed (sdb_plugin
) == FALSE
)
1604 DEBUG_PRINT ("no changes. Skipping.");
1607 DEBUG_PRINT ("Updating project symbols.");
1608 /* update any files of the project which isn't up-to-date */
1609 if (do_update_project_symbols (sdb_plugin
, sdb_plugin
->project_opened
) == FALSE
)
1611 DEBUG_PRINT ("no changes. Skipping.");
1616 /* add a new project */
1618 on_project_root_added (AnjutaPlugin
*plugin
, const gchar
*name
,
1619 const GValue
*value
, gpointer user_data
)
1621 IAnjutaProjectManager
*pm
;
1622 SymbolDBPlugin
*sdb_plugin
;
1623 const gchar
*root_uri
;
1626 IAnjutaProject
*project
;
1627 AnjutaProjectNode
*root
;
1628 const gchar
*root_name
;
1630 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
1633 * The Global System symbols thing
1636 /* is the global db connected? */
1637 if (symbol_db_engine_is_connected (sdb_plugin
->sdbe_globals
) == FALSE
)
1639 gchar
*anjuta_cache_path
;
1640 /* open the connection to global db */
1641 anjuta_cache_path
= anjuta_util_get_user_cache_file_path (".", NULL
);
1642 if (symbol_db_engine_open_db (sdb_plugin
->sdbe_globals
,
1644 PROJECT_GLOBALS
) == DB_OPEN_STATUS_FATAL
)
1646 g_error ("Opening global project under %s", anjuta_cache_path
);
1648 g_free (anjuta_cache_path
);
1650 /* unref and recreate the sdbs object */
1651 if (sdb_plugin
->sdbs
!= NULL
)
1652 g_object_unref (sdb_plugin
->sdbs
);
1654 sdb_plugin
->sdbs
= symbol_db_system_new (sdb_plugin
,
1655 sdb_plugin
->sdbe_globals
);
1658 /* Hide the progress bar. Default system tags thing: we'll import after abort even
1659 * if the preferences says not to automatically scan the packages.
1661 gtk_widget_hide (sdb_plugin
->progress_bar_system
);
1663 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
,
1664 IAnjutaProjectManager
, NULL
);
1671 g_free (sdb_plugin
->project_root_uri
);
1672 sdb_plugin
->project_root_uri
= NULL
;
1673 if ((root_uri
= g_value_get_string (value
)) == NULL
)
1675 DEBUG_PRINT ("Warning, root_uri for project is NULL");
1680 gfile
= g_file_new_for_uri (root_uri
);
1682 root_dir
= g_file_get_path (gfile
);
1683 DEBUG_PRINT ("Symbol-DB: added project root_dir %s, name %s", root_dir
,
1686 g_object_unref (gfile
);
1688 project
= ianjuta_project_manager_get_current_project (pm
, NULL
);
1689 root
= ianjuta_project_get_root (project
, NULL
);
1690 root_name
= anjuta_project_node_get_name (root
);
1692 sdb_plugin
->project_opened
= g_strdup (root_name
);
1696 gboolean project_exist
= FALSE
;
1699 /* we'll use the same values for db_directory and project_directory */
1700 DEBUG_PRINT ("Opening db %s and project_dir %s", root_dir
, root_dir
);
1701 gint open_status
= symbol_db_engine_open_db (sdb_plugin
->sdbe_project
, root_dir
,
1704 /* is it a fresh-new project? is it an imported project with
1705 * no 'new' symbol-db database but the 'old' one symbol-browser?
1707 sdb_plugin
->needs_sources_scan
= FALSE
;
1708 switch (open_status
)
1710 case DB_OPEN_STATUS_FATAL
:
1711 g_warning ("*** Error in opening db ***");
1714 case DB_OPEN_STATUS_NORMAL
:
1715 project_exist
= TRUE
;
1718 case DB_OPEN_STATUS_CREATE
:
1719 case DB_OPEN_STATUS_UPGRADE
:
1720 sdb_plugin
->needs_sources_scan
= TRUE
;
1721 project_exist
= FALSE
;
1728 /* if project did not exist add a new project */
1729 if (project_exist
== FALSE
)
1731 DEBUG_PRINT ("Creating new project.");
1732 symbol_db_engine_add_new_project (sdb_plugin
->sdbe_project
,
1733 NULL
, /* still no workspace logic */
1734 sdb_plugin
->project_opened
,
1738 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_project
),
1739 _("Populating symbol database…"));
1740 id
= g_idle_add ((GSourceFunc
) gtk_progress_bar_pulse
,
1741 sdb_plugin
->progress_bar_project
);
1742 gtk_widget_show (sdb_plugin
->progress_bar_project
);
1743 g_source_remove (id
);
1744 gtk_widget_hide (sdb_plugin
->progress_bar_project
);
1747 sdb_plugin
->project_root_dir
= root_dir
;
1750 sdb_plugin
->project_root_uri
= g_strdup (root_uri
);
1754 on_project_root_removed (AnjutaPlugin
*plugin
, const gchar
*name
,
1757 IAnjutaProjectManager
*pm
;
1758 SymbolDBPlugin
*sdb_plugin
;
1760 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
1761 DEBUG_PRINT ("%s", "project_root_removed ()");
1762 /* Disconnect events from project manager */
1764 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
,
1765 IAnjutaProjectManager
, NULL
);
1766 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
1767 on_project_element_added
,
1769 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
1770 on_project_element_removed
,
1773 /* don't forget to close the project */
1774 symbol_db_engine_close_db (sdb_plugin
->sdbe_project
);
1776 /* and the globals one */
1777 symbol_db_engine_close_db (sdb_plugin
->sdbe_globals
);
1779 /* stop any opened scanning process */
1780 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_system
), "");
1781 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_project
), "");
1782 gtk_widget_hide (sdb_plugin
->progress_bar_system
);
1783 gtk_widget_hide (sdb_plugin
->progress_bar_project
);
1785 sdb_plugin
->files_count_system_done
= 0;
1786 sdb_plugin
->files_count_system
= 0;
1788 sdb_plugin
->files_count_project_done
= 0;
1789 sdb_plugin
->files_count_project
= 0;
1792 g_free (sdb_plugin
->project_root_uri
);
1793 g_free (sdb_plugin
->project_root_dir
);
1794 g_free (sdb_plugin
->project_opened
);
1795 sdb_plugin
->project_root_uri
= NULL
;
1796 sdb_plugin
->project_root_dir
= NULL
;
1797 sdb_plugin
->project_opened
= NULL
;
1801 on_scan_end_manager (SymbolDBEngine
*dbe
, gint process_id
,
1804 SymbolDBPlugin
*sdb_plugin
;
1805 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (data
);
1806 gint task_registered
;
1808 task_registered
= GPOINTER_TO_INT (g_tree_lookup (sdb_plugin
->proc_id_tree
,
1809 GINT_TO_POINTER (process_id
)));
1810 /* hey, we haven't find anything */
1811 if (task_registered
<= 0)
1813 DEBUG_PRINT ("No task found, proc id was %d", process_id
);
1817 switch (task_registered
)
1819 case TASK_IMPORT_PROJECT
:
1820 case TASK_IMPORT_PROJECT_AFTER_ABORT
:
1822 DEBUG_PRINT ("received TASK_IMPORT_PROJECT (AFTER_ABORT)");
1824 /* re-enable signals receiving on local-view */
1825 sdb_plugin
->is_project_importing
= FALSE
;
1827 /* disconnect this coz it's not important after the process of importing */
1828 g_signal_handlers_disconnect_by_func (dbe
, on_project_single_file_scan_end
,
1831 /* get preferences about the parallel scan */
1832 gboolean parallel_scan
= g_settings_get_boolean (sdb_plugin
->settings
,
1836 /* check the system population has a parallel fashion or not. */
1837 if (parallel_scan
== FALSE
)
1838 do_import_system_sources (sdb_plugin
);
1842 case TASK_BUFFER_UPDATE
:
1843 DEBUG_PRINT ("received TASK_BUFFER_UPDATE");
1844 on_editor_buffer_symbol_update_scan_end (dbe
, process_id
, sdb_plugin
);
1847 case TASK_ELEMENT_ADDED
:
1848 DEBUG_PRINT ("received TASK_ELEMENT_ADDED");
1849 sdb_plugin
->is_adding_element
= FALSE
;
1852 case TASK_OFFLINE_CHANGES
:
1853 DEBUG_PRINT ("received TASK_OFFLINE_CHANGES");
1855 /* disconnect this coz it's not important after the process of importing */
1856 g_signal_handlers_disconnect_by_func (dbe
, on_check_offline_single_file_scan_end
,
1859 sdb_plugin
->is_offline_scanning
= FALSE
;
1862 case TASK_PROJECT_UPDATE
:
1863 DEBUG_PRINT ("received TASK_PROJECT_UPDATE");
1864 sdb_plugin
->is_project_updating
= FALSE
;
1867 case TASK_FILE_UPDATE
:
1868 DEBUG_PRINT ("received TASK_FILE_UPDATE");
1872 DEBUG_PRINT ("Don't know what to to with task_registered %d",
1876 /* ok, we're done. Remove the proc_id from the GTree coz we won't use it anymore */
1877 if (g_tree_remove (sdb_plugin
->proc_id_tree
, GINT_TO_POINTER (process_id
)) == FALSE
)
1878 g_warning ("Cannot remove proc_id from GTree");
1880 DEBUG_PRINT ("is_offline_scanning %d, is_project_importing %d, is_project_updating %d, "
1881 "is_adding_element %d", sdb_plugin
->is_offline_scanning
,
1882 sdb_plugin
->is_project_importing
, sdb_plugin
->is_project_updating
,
1883 sdb_plugin
->is_adding_element
);
1885 /* is the project still opened? */
1886 if (sdb_plugin
->project_opened
== NULL
)
1888 /* just return, the project may have been closed while we were waiting for the
1889 * scanning to finish
1895 * perform some checks on some booleans. If they're all successfully passed
1896 * then activate the display of local view
1898 if (sdb_plugin
->is_offline_scanning
== FALSE
&&
1899 sdb_plugin
->is_project_importing
== FALSE
&&
1900 sdb_plugin
->is_project_updating
== FALSE
&&
1901 sdb_plugin
->is_adding_element
== FALSE
)
1903 sdb_plugin
->files_count_project_done
= 0;
1904 sdb_plugin
->files_count_project
= 0;
1905 clear_project_progress_bar (dbe
, sdb_plugin
);
1910 on_isymbol_manager_prj_scan_end (SymbolDBEngine
*dbe
,
1912 IAnjutaSymbolManager
*sm
)
1914 g_signal_emit_by_name (sm
, "prj-scan-end", process_id
);
1918 on_isymbol_manager_sys_scan_begin (SymbolDBEngine
*dbe
, gint process_id
,
1919 SymbolDBPlugin
*sdb_plugin
)
1921 sdb_plugin
->current_pkg_scanned
= g_async_queue_pop (sdb_plugin
->global_scan_aqueue
);
1923 if (sdb_plugin
->current_pkg_scanned
== NULL
)
1926 DEBUG_PRINT ("==%d==>\n"
1927 "begin %s", process_id
, sdb_plugin
->current_pkg_scanned
->package_name
);
1928 gtk_widget_show (sdb_plugin
->progress_bar_system
);
1932 on_isymbol_manager_sys_single_scan_end (SymbolDBEngine
*dbe
, SymbolDBPlugin
*sdb_plugin
)
1934 PackageScanData
*pkg_scan
;
1936 /* ignore signals when scan-end has already been received */
1937 if (sdb_plugin
->current_pkg_scanned
== NULL
)
1942 pkg_scan
= sdb_plugin
->current_pkg_scanned
;
1943 pkg_scan
->files_done
++;
1945 gtk_widget_show (sdb_plugin
->progress_bar_system
);
1946 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_system
),
1947 (gdouble
)pkg_scan
->files_done
/
1948 (gdouble
)pkg_scan
->files_length
);
1952 on_isymbol_manager_sys_scan_end (SymbolDBEngine
*dbe
,
1954 SymbolDBPlugin
*sdb_plugin
)
1956 IAnjutaSymbolManager
*sm
;
1957 PackageScanData
*pkg_scan
;
1959 g_return_if_fail (sdb_plugin
->current_pkg_scanned
!= NULL
);
1961 DEBUG_PRINT ("<==%d==\nscan end %s. Queue now is %d",
1963 sdb_plugin
->current_pkg_scanned
->package_name
,
1964 g_async_queue_length (sdb_plugin
->global_scan_aqueue
));
1966 sm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
,
1967 IAnjutaSymbolManager
, NULL
);
1969 g_signal_emit_by_name (sm
, "sys-scan-end", process_id
);
1971 pkg_scan
= sdb_plugin
->current_pkg_scanned
;
1972 g_free (pkg_scan
->package_name
);
1973 g_free (pkg_scan
->package_version
);
1976 sdb_plugin
->current_pkg_scanned
= NULL
;
1978 gtk_widget_hide (sdb_plugin
->progress_bar_system
);
1982 symbol_db_activate (AnjutaPlugin
*plugin
)
1984 IAnjutaProjectManager
*pm
;
1985 SymbolDBPlugin
*sdb_plugin
;
1986 gchar
*anjuta_cache_path
;
1988 GtkWidget
*view
, *label
;
1990 DEBUG_PRINT ("SymbolDBPlugin: Activating SymbolDBPlugin plugin …");
1992 /* Initialize gda library. */
1995 register_stock_icons (plugin
);
1997 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
1998 sdb_plugin
->ui
= anjuta_shell_get_ui (plugin
->shell
, NULL
);
1999 sdb_plugin
->project_opened
= NULL
;
2001 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
,
2002 IAnjutaProjectManager
, NULL
);
2006 /* leaving here this code. Maybe in future ctags-devs will include our patches
2007 * upstream and this can be useful again.
2009 if (ctags_path
== NULL
)
2011 DEBUG_PRINT ("ctags is not in preferences. Trying a default one %s",
2013 ctags_path
= g_strdup (CTAGS_PATH
);
2016 sdb_plugin
->buf_update_timeout_id
= 0;
2017 sdb_plugin
->need_symbols_update
= FALSE
;
2018 /* creates and start a new timer. */
2019 sdb_plugin
->update_timer
= g_timer_new ();
2021 /* these two arrays will maintain the same number of objects,
2022 * so that if you search, say on the first, an occurrence of a file,
2023 * you'll be able to get in O(1) the _index in the second array, where the
2024 * scan process ids are stored. This is true in the other way too.
2026 sdb_plugin
->buffer_update_files
= g_ptr_array_new_with_free_func (g_free
);
2027 sdb_plugin
->buffer_update_ids
= g_ptr_array_new ();
2028 sdb_plugin
->buffer_update_semaphore
= FALSE
;
2030 sdb_plugin
->is_offline_scanning
= FALSE
;
2031 sdb_plugin
->is_project_importing
= FALSE
;
2032 sdb_plugin
->is_project_updating
= FALSE
;
2033 sdb_plugin
->is_adding_element
= FALSE
;
2035 DEBUG_PRINT ("SymbolDBPlugin: Initializing engines with %s", ctags_path
);
2036 /* create SymbolDBEngine(s) */
2037 sdb_plugin
->sdbe_project
= symbol_db_engine_new (ctags_path
);
2038 if (sdb_plugin
->sdbe_project
== NULL
)
2040 g_critical ("sdbe_project == NULL");
2044 /* the globals one too */
2045 sdb_plugin
->sdbe_globals
= symbol_db_engine_new (ctags_path
);
2046 if (sdb_plugin
->sdbe_globals
== NULL
)
2048 g_critical ("sdbe_globals == NULL");
2052 g_free (ctags_path
);
2055 anjuta_cache_path
= anjuta_util_get_user_cache_file_path (".", NULL
);
2056 if (symbol_db_engine_open_db (sdb_plugin
->sdbe_globals
,
2058 PROJECT_GLOBALS
) == DB_OPEN_STATUS_FATAL
)
2060 g_error ("Opening global project under %s", anjuta_cache_path
);
2063 g_free (anjuta_cache_path
);
2065 sdb_plugin
->global_scan_aqueue
= g_async_queue_new ();
2066 /* create the object that'll manage the globals population */
2067 sdb_plugin
->sdbs
= symbol_db_system_new (sdb_plugin
, sdb_plugin
->sdbe_globals
);
2069 g_signal_connect (G_OBJECT (sdb_plugin
->sdbs
), "scan-package-start",
2070 G_CALLBACK (on_system_scan_package_start
), plugin
);
2072 g_signal_connect (G_OBJECT (sdb_plugin
->sdbs
), "scan-package-end",
2073 G_CALLBACK (on_system_scan_package_end
), plugin
);
2075 g_signal_connect (G_OBJECT (sdb_plugin
->sdbs
), "single-file-scan-end",
2076 G_CALLBACK (on_system_single_file_scan_end
), plugin
);
2078 /* beign necessary to listen to many scan-end signals, we'll build up a method
2079 * to manage them with just one signal connection
2081 sdb_plugin
->proc_id_tree
= g_tree_new_full ((GCompareDataFunc
)&symbol_db_gtree_compare_func
,
2086 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_project
), "scan-end",
2087 G_CALLBACK (on_scan_end_manager
), sdb_plugin
);
2089 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_project
), "scan-end",
2090 G_CALLBACK (on_isymbol_manager_prj_scan_end
), sdb_plugin
);
2092 /* connect signals for interface to receive them */
2093 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_globals
), "single-file-scan-end",
2094 G_CALLBACK (on_isymbol_manager_sys_single_scan_end
), sdb_plugin
);
2096 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_globals
), "scan-end",
2097 G_CALLBACK (on_isymbol_manager_sys_scan_end
), sdb_plugin
);
2099 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_globals
), "scan-begin",
2100 G_CALLBACK (on_isymbol_manager_sys_scan_begin
), sdb_plugin
);
2104 /* connect signals for project loading and element adding */
2105 g_signal_connect (G_OBJECT (pm
), "element-added",
2106 G_CALLBACK (on_project_element_added
), sdb_plugin
);
2107 g_signal_connect (G_OBJECT (pm
), "element-removed",
2108 G_CALLBACK (on_project_element_removed
), sdb_plugin
);
2109 g_signal_connect (G_OBJECT (pm
), "project-loaded",
2110 G_CALLBACK (on_project_loaded
), sdb_plugin
);
2112 /* Create widgets */
2113 sdb_plugin
->dbv_main
= gtk_vbox_new(FALSE
, 5);
2114 sdb_plugin
->dbv_notebook
= gtk_notebook_new();
2115 gtk_notebook_set_show_border (GTK_NOTEBOOK (sdb_plugin
->dbv_notebook
), FALSE
);
2116 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (sdb_plugin
->dbv_notebook
), FALSE
);
2117 sdb_plugin
->dbv_hbox
= gtk_hbox_new (FALSE
, 1);
2119 label
= gtk_label_new (_("Symbols"));
2120 gtk_misc_set_alignment (GTK_MISC (label
), 0.0f
, 0.5f
);
2121 gtk_box_pack_start (GTK_BOX(sdb_plugin
->dbv_hbox
),
2122 gtk_image_new_from_stock ("symbol-db-plugin-icon",
2123 GTK_ICON_SIZE_MENU
),
2125 gtk_box_pack_start (GTK_BOX(sdb_plugin
->dbv_hbox
), label
,
2128 sdb_plugin
->tabber
= anjuta_tabber_new (GTK_NOTEBOOK (sdb_plugin
->dbv_notebook
));
2129 label
= gtk_label_new (_("File"));
2130 gtk_label_set_ellipsize (GTK_LABEL (label
),
2131 PANGO_ELLIPSIZE_END
);
2132 anjuta_tabber_add_tab (ANJUTA_TABBER (sdb_plugin
->tabber
),
2134 label
= gtk_label_new (_("Project"));
2135 gtk_label_set_ellipsize (GTK_LABEL (label
),
2136 PANGO_ELLIPSIZE_END
);
2137 anjuta_tabber_add_tab (ANJUTA_TABBER (sdb_plugin
->tabber
),
2139 label
= gtk_label_new (_("Search"));
2140 gtk_label_set_ellipsize (GTK_LABEL (label
),
2141 PANGO_ELLIPSIZE_END
);
2142 anjuta_tabber_add_tab (ANJUTA_TABBER (sdb_plugin
->tabber
),
2144 gtk_box_pack_end (GTK_BOX(sdb_plugin
->dbv_hbox
), sdb_plugin
->tabber
,
2147 gtk_widget_show_all (sdb_plugin
->dbv_hbox
);
2149 sdb_plugin
->progress_bar_project
= gtk_progress_bar_new();
2150 gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR(sdb_plugin
->progress_bar_project
),
2151 PANGO_ELLIPSIZE_MIDDLE
);
2152 g_object_ref (sdb_plugin
->progress_bar_project
);
2154 sdb_plugin
->progress_bar_system
= gtk_progress_bar_new();
2155 gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR(sdb_plugin
->progress_bar_system
),
2156 PANGO_ELLIPSIZE_MIDDLE
);
2157 g_object_ref (sdb_plugin
->progress_bar_system
);
2159 gtk_box_pack_start (GTK_BOX (sdb_plugin
->dbv_main
), sdb_plugin
->dbv_notebook
,
2161 gtk_box_pack_start (GTK_BOX (sdb_plugin
->dbv_main
), sdb_plugin
->progress_bar_project
,
2163 gtk_box_pack_start (GTK_BOX (sdb_plugin
->dbv_main
), sdb_plugin
->progress_bar_system
,
2165 gtk_widget_show_all (sdb_plugin
->dbv_main
);
2168 view
= symbol_db_view_new (SYMBOL_DB_VIEW_FILE
, sdb_plugin
->sdbe_project
,
2170 gtk_notebook_append_page (GTK_NOTEBOOK (sdb_plugin
->dbv_notebook
),
2171 view
, gtk_label_new (_("Local")));
2172 sdb_plugin
->file_model
=
2173 gtk_tree_view_get_model (GTK_TREE_VIEW (gtk_bin_get_child (GTK_BIN(view
))));
2175 g_object_add_weak_pointer (G_OBJECT (sdb_plugin
->file_model
),
2176 (gpointer
)&sdb_plugin
->file_model
);
2178 /* Global symbols */
2179 view
= symbol_db_view_new (SYMBOL_DB_VIEW_PROJECT
,
2180 sdb_plugin
->sdbe_project
,
2182 gtk_notebook_append_page (GTK_NOTEBOOK (sdb_plugin
->dbv_notebook
),
2183 view
, gtk_label_new (_("Global" )));
2185 /* Search symbols */
2186 view
= symbol_db_view_new (SYMBOL_DB_VIEW_SEARCH
,
2187 sdb_plugin
->sdbe_project
,
2189 sdb_plugin
->search_entry
= symbol_db_view_get_search_entry (view
);
2190 gtk_notebook_append_page (GTK_NOTEBOOK (sdb_plugin
->dbv_notebook
),
2191 view
, gtk_label_new (_("Search" )));
2193 gtk_widget_show_all (sdb_plugin
->dbv_notebook
);
2195 /* setting focus to the tree_view*/
2196 gtk_notebook_set_current_page (GTK_NOTEBOOK (sdb_plugin
->dbv_notebook
), 0);
2198 sdb_plugin
->editor_watch_id
=
2199 anjuta_plugin_add_watch (plugin
, IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT
,
2200 value_added_current_editor
,
2201 value_removed_current_editor
, NULL
);
2203 anjuta_shell_add_widget_custom (plugin
->shell
, sdb_plugin
->dbv_main
,
2204 "AnjutaSymbolDB", _("Symbols"),
2205 "symbol-db-plugin-icon",
2206 sdb_plugin
->dbv_hbox
,
2207 ANJUTA_SHELL_PLACEMENT_LEFT
, NULL
);
2209 /* Add action group */
2210 sdb_plugin
->popup_action_group
=
2211 anjuta_ui_add_action_group_entries (sdb_plugin
->ui
,
2212 "ActionGroupPopupSymbolDB",
2213 _("SymbolDb popup actions"),
2215 G_N_ELEMENTS (actions
),
2216 GETTEXT_PACKAGE
, FALSE
, plugin
);
2218 sdb_plugin
->menu_action_group
=
2219 anjuta_ui_add_action_group_entries (sdb_plugin
->ui
,
2220 "ActionGroupEditSearchSymbolDB",
2221 _("SymbolDb menu actions"),
2223 G_N_ELEMENTS (actions_search
),
2224 GETTEXT_PACKAGE
, FALSE
, plugin
);
2227 sdb_plugin
->merge_id
=
2228 anjuta_ui_merge (sdb_plugin
->ui
, UI_FILE
);
2230 /* set up project directory watch */
2231 sdb_plugin
->root_watch_id
= anjuta_plugin_add_watch (plugin
,
2232 IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI
,
2233 on_project_root_added
,
2234 on_project_root_removed
, NULL
);
2236 /* Determine session state */
2237 g_signal_connect (plugin
->shell
, "load-session",
2238 G_CALLBACK (on_session_load
), plugin
);
2240 g_signal_connect (plugin
->shell
, "save-session",
2241 G_CALLBACK (on_session_save
), plugin
);
2243 /* be sure to hide the progress bars in case no project has been opened. */
2244 gtk_widget_hide (sdb_plugin
->progress_bar_project
);
2245 gtk_widget_hide (sdb_plugin
->progress_bar_system
);
2247 static IAnjutaSymbolField search_fields
[] =
2249 IANJUTA_SYMBOL_FIELD_KIND
,
2250 IANJUTA_SYMBOL_FIELD_FILE_PATH
,
2251 IANJUTA_SYMBOL_FIELD_FILE_POS
2253 sdb_plugin
->search_query
=
2254 ianjuta_symbol_manager_create_query (IANJUTA_SYMBOL_MANAGER (sdb_plugin
),
2255 IANJUTA_SYMBOL_QUERY_SEARCH
,
2256 IANJUTA_SYMBOL_QUERY_DB_PROJECT
,
2258 ianjuta_symbol_query_set_fields (sdb_plugin
->search_query
,
2259 G_N_ELEMENTS (search_fields
),
2260 search_fields
, NULL
);
2265 symbol_db_deactivate (AnjutaPlugin
*plugin
)
2267 SymbolDBPlugin
*sdb_plugin
;
2268 IAnjutaProjectManager
*pm
;
2270 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
2272 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
,
2273 IAnjutaProjectManager
, NULL
);
2277 DEBUG_PRINT ("%s", "SymbolDBPlugin: Dectivating SymbolDBPlugin plugin …");
2280 gtk_ui_manager_remove_ui (GTK_UI_MANAGER (sdb_plugin
->ui
),
2281 sdb_plugin
->merge_id
);
2282 gtk_ui_manager_remove_action_group (GTK_UI_MANAGER (sdb_plugin
->ui
),
2283 sdb_plugin
->popup_action_group
);
2284 gtk_ui_manager_remove_action_group (GTK_UI_MANAGER (sdb_plugin
->ui
),
2285 sdb_plugin
->menu_action_group
);
2286 g_signal_handlers_disconnect_by_func (G_OBJECT (plugin
->shell
),
2290 g_signal_handlers_disconnect_by_func (G_OBJECT (plugin
->shell
),
2294 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->sdbs
),
2295 on_system_scan_package_start
,
2298 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->sdbs
),
2299 on_system_scan_package_end
,
2302 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->sdbs
),
2303 on_system_single_file_scan_end
,
2306 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->sdbs
),
2307 on_scan_end_manager
,
2310 /* disconnect the interface ones */
2311 /* connect signals for interface to receive them */
2312 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->sdbe_globals
),
2313 G_CALLBACK (on_isymbol_manager_sys_scan_end
), plugin
);
2315 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->sdbe_project
),
2316 G_CALLBACK (on_isymbol_manager_prj_scan_end
), plugin
);
2318 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
2319 G_CALLBACK (on_project_element_added
), plugin
);
2321 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
2322 G_CALLBACK (on_project_element_removed
), plugin
);
2324 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
2325 G_CALLBACK (on_project_loaded
), plugin
);
2327 if (sdb_plugin
->update_timer
)
2329 g_timer_destroy (sdb_plugin
->update_timer
);
2330 sdb_plugin
->update_timer
= NULL
;
2333 /* destroy search query */
2334 if (sdb_plugin
->search_query
)
2336 g_object_unref (sdb_plugin
->search_query
);
2338 sdb_plugin
->search_query
= NULL
;
2340 /* destroy objects */
2341 if (sdb_plugin
->sdbe_project
)
2343 DEBUG_PRINT ("Destroying project engine object. ");
2344 g_object_unref (sdb_plugin
->sdbe_project
);
2346 sdb_plugin
->sdbe_project
= NULL
;
2348 PackageScanData
*pkg_scan_data
;
2349 while ((pkg_scan_data
= g_async_queue_try_pop (sdb_plugin
->global_scan_aqueue
)) != NULL
)
2351 g_free (pkg_scan_data
->package_name
);
2352 g_free (pkg_scan_data
->package_version
);
2353 g_free (pkg_scan_data
);
2356 g_async_queue_unref (sdb_plugin
->global_scan_aqueue
);
2357 sdb_plugin
->global_scan_aqueue
= NULL
;
2359 /* this must be done *before* destroying sdbe_globals */
2360 g_object_unref (sdb_plugin
->sdbs
);
2361 sdb_plugin
->sdbs
= NULL
;
2363 g_free (sdb_plugin
->current_scanned_package
);
2364 sdb_plugin
->current_scanned_package
= NULL
;
2366 DEBUG_PRINT ("Destroying global engine object. ");
2367 g_object_unref (sdb_plugin
->sdbe_globals
);
2368 sdb_plugin
->sdbe_globals
= NULL
;
2370 g_free (sdb_plugin
->project_opened
);
2371 sdb_plugin
->project_opened
= NULL
;
2373 if (sdb_plugin
->buffer_update_files
)
2375 g_ptr_array_unref (sdb_plugin
->buffer_update_files
);
2376 sdb_plugin
->buffer_update_files
= NULL
;
2379 if (sdb_plugin
->buffer_update_ids
)
2381 g_ptr_array_unref (sdb_plugin
->buffer_update_ids
);
2382 sdb_plugin
->buffer_update_ids
= NULL
;
2385 /* Ensure all editor cached info are released */
2386 if (sdb_plugin
->editor_connected
)
2388 g_hash_table_foreach (sdb_plugin
->editor_connected
,
2389 on_editor_foreach_disconnect
, plugin
);
2390 g_hash_table_destroy (sdb_plugin
->editor_connected
);
2391 sdb_plugin
->editor_connected
= NULL
;
2395 g_tree_destroy (sdb_plugin
->proc_id_tree
);
2397 /* Remove watches */
2398 anjuta_plugin_remove_watch (plugin
, sdb_plugin
->root_watch_id
, FALSE
);
2399 anjuta_plugin_remove_watch (plugin
, sdb_plugin
->editor_watch_id
, TRUE
);
2402 anjuta_ui_unmerge (sdb_plugin
->ui
, sdb_plugin
->merge_id
);
2404 /* Remove widgets: Widgets will be destroyed when dbv_main is removed */
2405 anjuta_shell_remove_widget (plugin
->shell
, sdb_plugin
->dbv_main
, NULL
);
2407 sdb_plugin
->root_watch_id
= 0;
2408 sdb_plugin
->editor_watch_id
= 0;
2409 sdb_plugin
->merge_id
= 0;
2410 sdb_plugin
->dbv_notebook
= NULL
;
2411 sdb_plugin
->progress_bar_project
= NULL
;
2412 sdb_plugin
->progress_bar_system
= NULL
;
2417 symbol_db_finalize (GObject
*obj
)
2419 DEBUG_PRINT ("Symbol-DB finalize");
2420 /* Finalization codes here */
2421 G_OBJECT_CLASS (parent_class
)->finalize (obj
);
2425 symbol_db_dispose (GObject
*obj
)
2427 SymbolDBPlugin
*plugin
= (SymbolDBPlugin
*)obj
;
2428 DEBUG_PRINT ("Symbol-DB dispose");
2429 /* Disposition codes */
2430 g_object_unref (plugin
->settings
);
2433 G_OBJECT_CLASS (parent_class
)->dispose (obj
);
2437 symbol_db_instance_init (GObject
*obj
)
2439 SymbolDBPlugin
*plugin
= (SymbolDBPlugin
*)obj
;
2441 plugin
->files_count_project_done
= 0;
2442 plugin
->files_count_project
= 0;
2444 plugin
->files_count_system_done
= 0;
2445 plugin
->files_count_system
= 0;
2446 plugin
->current_scanned_package
= NULL
;
2447 plugin
->settings
= g_settings_new (PREF_SCHEMA
);
2451 symbol_db_class_init (GObjectClass
*klass
)
2453 AnjutaPluginClass
*plugin_class
= ANJUTA_PLUGIN_CLASS (klass
);
2455 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
2456 parent_class
= g_type_class_peek_parent (klass
);
2458 plugin_class
->activate
= symbol_db_activate
;
2459 plugin_class
->deactivate
= symbol_db_deactivate
;
2460 klass
->finalize
= symbol_db_finalize
;
2461 klass
->dispose
= symbol_db_dispose
;
2463 signals
[PROJECT_IMPORT_END
]
2464 = g_signal_new ("project-import-end",
2465 G_OBJECT_CLASS_TYPE (object_class
),
2467 G_STRUCT_OFFSET (SymbolDBPluginClass
, project_import_end
),
2469 g_cclosure_marshal_VOID__VOID
, G_TYPE_NONE
, 0);
2471 signals
[GLOBALS_IMPORT_END
]
2472 = g_signal_new ("globals-import-end",
2473 G_OBJECT_CLASS_TYPE (object_class
),
2475 G_STRUCT_OFFSET (SymbolDBPluginClass
, globals_import_end
),
2477 g_cclosure_marshal_VOID__VOID
, G_TYPE_NONE
, 0);
2481 on_prefs_buffer_update_toggled (GtkToggleButton
* button
,
2484 SymbolDBPlugin
*sdb_plugin
;
2487 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (user_data
);
2489 sensitive
= gtk_toggle_button_get_active (button
);
2491 DEBUG_PRINT ("on_prefs_buffer_update_toggled () %d", sensitive
);
2493 if (sensitive
== FALSE
)
2495 if (sdb_plugin
->buf_update_timeout_id
)
2496 g_source_remove (sdb_plugin
->buf_update_timeout_id
);
2497 sdb_plugin
->buf_update_timeout_id
= 0;
2501 if (sdb_plugin
->buf_update_timeout_id
== 0)
2502 sdb_plugin
->buf_update_timeout_id
=
2503 g_timeout_add_seconds (TIMEOUT_INTERVAL_SYMBOLS_UPDATE
,
2504 on_editor_buffer_symbols_update_timeout
,
2510 ipreferences_merge(IAnjutaPreferences
* ipref
, AnjutaPreferences
* prefs
, GError
** e
)
2512 DEBUG_PRINT ("%s", "SymbolDB: ipreferences_merge");
2513 SymbolDBPlugin
*sdb_plugin
;
2514 GtkWidget
*buf_up_widget
;
2515 GError
* error
= NULL
;
2517 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (ipref
);
2519 if (sdb_plugin
->prefs_bxml
== NULL
)
2521 /* Create the preferences page */
2522 sdb_plugin
->prefs_bxml
= gtk_builder_new ();
2523 if (!gtk_builder_add_from_file (sdb_plugin
->prefs_bxml
, BUILDER_FILE
, &error
))
2525 g_warning ("Couldn't load builder file: %s", error
->message
);
2526 g_error_free(error
);
2530 anjuta_preferences_add_from_builder (prefs
,
2531 sdb_plugin
->prefs_bxml
,
2532 sdb_plugin
->settings
,
2534 _("Symbol Database"),
2537 buf_up_widget
= GTK_WIDGET (gtk_builder_get_object (sdb_plugin
->prefs_bxml
,
2538 PREFS_BUFFER_UPDATE
));
2540 g_signal_connect (buf_up_widget
, "toggled",
2541 G_CALLBACK (on_prefs_buffer_update_toggled
),
2546 ipreferences_unmerge(IAnjutaPreferences
* ipref
, AnjutaPreferences
* prefs
, GError
** e
)
2548 SymbolDBPlugin
*sdb_plugin
;
2550 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (ipref
);
2552 anjuta_preferences_remove_page(prefs
, _("Symbol Database"));
2553 g_object_unref (sdb_plugin
->prefs_bxml
);
2554 sdb_plugin
->prefs_bxml
= NULL
;
2558 ipreferences_iface_init(IAnjutaPreferencesIface
* iface
)
2560 DEBUG_PRINT ("%s", "SymbolDB: ipreferences_iface_init");
2561 iface
->merge
= ipreferences_merge
;
2562 iface
->unmerge
= ipreferences_unmerge
;
2565 /* IAnjutaSymbolManager implementation */
2566 static IAnjutaSymbolQuery
*
2567 isymbol_manager_create_query (IAnjutaSymbolManager
*isymbol_manager
,
2568 IAnjutaSymbolQueryName query_name
,
2569 IAnjutaSymbolQueryDb db
,
2572 SymbolDBPlugin
*sdb_plugin
;
2573 SymbolDBQuery
*query
;
2575 g_return_val_if_fail (isymbol_manager
!= NULL
, NULL
);
2577 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager
);
2579 query
= symbol_db_query_new (sdb_plugin
->sdbe_globals
,
2580 sdb_plugin
->sdbe_project
,
2583 db
== IANJUTA_SYMBOL_QUERY_DB_PROJECT
?
2584 NULL
: /* FIXME */ NULL
);
2585 return IANJUTA_SYMBOL_QUERY (query
);
2589 isymbol_manager_add_package (IAnjutaSymbolManager
*isymbol_manager
,
2590 const gchar
* pkg_name
,
2591 const gchar
* pkg_version
,
2595 SymbolDBPlugin
*sdb_plugin
;
2596 IAnjutaLanguage
*lang_manager
;
2597 GPtrArray
*files_array
;
2598 PackageScanData
*pkg_scan_data
;
2601 g_return_val_if_fail (isymbol_manager
!= NULL
, FALSE
);
2606 while (node
!= NULL
)
2611 /* FIXME: pkg_version comes with \n at the end. This should be avoided */
2612 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager
);
2613 lang_manager
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
, IAnjutaLanguage
,
2616 if (symbol_db_engine_add_new_project (sdb_plugin
->sdbe_globals
, NULL
, pkg_name
,
2617 pkg_version
) == FALSE
)
2622 files_array
= anjuta_util_convert_string_list_to_array (files
);
2624 pkg_scan_data
= g_new0 (PackageScanData
, 1);
2626 g_async_queue_push (sdb_plugin
->global_scan_aqueue
, pkg_scan_data
);
2627 pkg_scan_data
->files_length
= g_list_length (files
);
2628 pkg_scan_data
->package_name
= g_strdup (pkg_name
);
2629 pkg_scan_data
->package_version
= g_strdup (pkg_version
);
2631 pkg_scan_data
->proc_id
= symbol_db_engine_add_new_files_async (sdb_plugin
->sdbe_globals
, lang_manager
,
2632 pkg_name
, pkg_version
, files_array
);
2634 g_ptr_array_unref (files_array
);
2639 /* FIXME: do this thread safe */
2641 isymbol_manager_activate_package (IAnjutaSymbolManager
*isymbol_manager
,
2642 const gchar
*pkg_name
,
2643 const gchar
*pkg_version
,
2646 SymbolDBPlugin
*sdb_plugin
;
2648 g_return_val_if_fail (isymbol_manager
!= NULL
, FALSE
);
2650 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager
);
2652 if (symbol_db_engine_project_exists (sdb_plugin
->sdbe_globals
, pkg_name
,
2653 pkg_version
) == TRUE
)
2655 /* FIXME: Activate package in database */
2656 DEBUG_PRINT ("STUB");
2660 /* user should add a package before activating it. */
2665 isymbol_manager_deactivate_package (IAnjutaSymbolManager
*isymbol_manager
,
2666 const gchar
*pkg_name
,
2667 const gchar
*pkg_version
,
2670 SymbolDBPlugin
*sdb_plugin
;
2672 g_return_if_fail (isymbol_manager
!= NULL
);
2674 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager
);
2676 if (symbol_db_engine_project_exists (sdb_plugin
->sdbe_globals
, pkg_name
,
2677 pkg_version
) == TRUE
)
2679 DEBUG_PRINT ("STUB");
2680 /* FIXME: deactivate package in database */
2685 isymbol_manager_deactivate_all (IAnjutaSymbolManager
*isymbol_manager
,
2689 SymbolDBPlugin
*sdb_plugin
;
2691 g_return_if_fail (isymbol_manager
!= NULL
);
2693 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager
);
2695 /* FIXME: deactivate all packages in database */
2696 DEBUG_PRINT ("STUB");
2700 isymbol_manager_iface_init (IAnjutaSymbolManagerIface
*iface
)
2702 iface
->create_query
= isymbol_manager_create_query
;
2703 iface
->activate_package
= isymbol_manager_activate_package
;
2704 iface
->deactivate_package
= isymbol_manager_deactivate_package
;
2705 iface
->deactivate_all
= isymbol_manager_deactivate_all
;
2706 iface
->add_package
= isymbol_manager_add_package
;
2709 ANJUTA_PLUGIN_BEGIN (SymbolDBPlugin
, symbol_db
);
2710 ANJUTA_PLUGIN_ADD_INTERFACE (isymbol_manager
, IANJUTA_TYPE_SYMBOL_MANAGER
);
2711 ANJUTA_PLUGIN_ADD_INTERFACE(ipreferences
, IANJUTA_TYPE_PREFERENCES
);
2714 ANJUTA_SIMPLE_PLUGIN (SymbolDBPlugin
, symbol_db
);