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