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
)
465 sdb_plugin
->buf_update_timeout_id
= 0;
469 /* check the timer. If it's elapsed enought time since the last time the user
470 * typed in something, than proceed with updating, elsewhere don't do nothing
472 if (sdb_plugin
->update_timer
== NULL
)
475 seconds_elapsed
= g_timer_elapsed (sdb_plugin
->update_timer
, NULL
);
477 if (seconds_elapsed
< TIMEOUT_SECONDS_AFTER_LAST_TIP
)
480 editor_buffer_symbols_update (IANJUTA_EDITOR (sdb_plugin
->current_editor
),
487 on_editor_buffer_symbol_update_scan_end (SymbolDBEngine
*dbe
, gint process_id
,
490 SymbolDBPlugin
*sdb_plugin
;
493 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (data
);
495 /* search for the proc id */
496 for (i
= 0; i
< sdb_plugin
->buffer_update_ids
->len
; i
++)
498 if (g_ptr_array_index (sdb_plugin
->buffer_update_ids
, i
) == GINT_TO_POINTER (process_id
))
500 /* hey we found it */
501 /* remove both the items */
502 g_ptr_array_remove_index (sdb_plugin
->buffer_update_ids
, i
);
504 g_ptr_array_remove_index (sdb_plugin
->buffer_update_files
, i
);
506 /* no need to free the string coz the g_ptr_array is built with
507 * g_ptr_array_new_with_free_func (g_free)
512 IAnjutaEditor
*editor
= g_hash_table_lookup(sdb_plugin
->editors
, GINT_TO_POINTER (process_id
));
513 g_hash_table_remove(sdb_plugin
->editors
, GINT_TO_POINTER (process_id
));
518 /* was the updating of view-locals symbols blocked while we were scanning?
519 * e.g. was the editor switched? */
520 if (sdb_plugin
->buffer_update_semaphore
== TRUE
)
524 gboolean tags_update
;
525 if (!IANJUTA_IS_EDITOR (editor
))
528 file
= ianjuta_file_get_file (IANJUTA_FILE (editor
),
534 local_path
= g_file_get_path (file
);
536 if (local_path
== NULL
)
538 g_critical ("local_path == NULL");
542 /* add a default timeout to the updating of buffer symbols */
543 tags_update
= g_settings_get_boolean (sdb_plugin
->settings
, BUFFER_UPDATE
);
547 sdb_plugin
->buf_update_timeout_id
=
548 g_timeout_add_seconds (TIMEOUT_INTERVAL_SYMBOLS_UPDATE
,
549 on_editor_buffer_symbols_update_timeout
,
554 sdb_plugin
->buffer_update_semaphore
= FALSE
;
559 on_editor_destroy (SymbolDBPlugin
*sdb_plugin
, IAnjutaEditor
*editor
)
561 if (!sdb_plugin
->editor_connected
)
563 DEBUG_PRINT ("%s", "on_editor_destroy (): returning….");
567 g_hash_table_remove (sdb_plugin
->editor_connected
, G_OBJECT (editor
));
569 if (g_hash_table_size (sdb_plugin
->editor_connected
) <= 0)
571 DEBUG_PRINT ("%s", "displaying nothing…");
572 if (sdb_plugin
->file_model
)
573 g_object_set (sdb_plugin
->file_model
, "file-path", NULL
, NULL
);
578 on_editor_update_ui (IAnjutaEditor
*editor
, SymbolDBPlugin
*sdb_plugin
)
580 g_timer_reset (sdb_plugin
->update_timer
);
584 on_code_added (IAnjutaEditor
*editor
, IAnjutaIterable
*position
, gchar
*code
,
585 SymbolDBPlugin
*sdb_plugin
)
587 IAnjutaEditor
*old_editor
= sdb_plugin
->current_editor
;
588 sdb_plugin
->current_editor
= editor
;
589 sdb_plugin
->need_symbols_update
= TRUE
;
590 editor_buffer_symbols_update (editor
, sdb_plugin
);
591 sdb_plugin
->current_editor
= old_editor
;
595 on_char_added (IAnjutaEditor
*editor
, IAnjutaIterable
*position
, gchar ch
,
596 SymbolDBPlugin
*sdb_plugin
)
598 g_timer_reset (sdb_plugin
->update_timer
);
600 /* Update when the user enters a newline */
602 sdb_plugin
->need_symbols_update
= TRUE
;
606 on_editor_saved (IAnjutaEditor
*editor
, GFile
* file
,
607 SymbolDBPlugin
*sdb_plugin
)
609 const gchar
*old_uri
;
610 gchar
*local_filename
;
612 GPtrArray
*files_array
;
616 local_filename
= g_file_get_path (file
);
617 /* Verify that it's local file */
618 g_return_if_fail (local_filename
!= NULL
);
620 saved_uri
= g_file_get_uri (file
);
622 for (i
= 0; i
< sdb_plugin
->buffer_update_files
->len
; i
++)
624 if (g_strcmp0 (g_ptr_array_index (sdb_plugin
->buffer_update_files
, i
),
625 local_filename
) == 0)
627 DEBUG_PRINT ("already scanning");
628 /* something is already scanning this buffer file. Drop the procedure now. */
633 files_array
= g_ptr_array_new();
634 g_ptr_array_add (files_array
, local_filename
);
635 /* no need to free local_filename now */
637 if (!sdb_plugin
->editor_connected
)
640 old_uri
= g_hash_table_lookup (sdb_plugin
->editor_connected
, editor
);
642 if (old_uri
&& strlen (old_uri
) <= 0)
645 /* files_array will be freed once updating has taken place */
647 if (symbol_db_engine_is_connected (sdb_plugin
->sdbe_project
))
649 proc_id
= symbol_db_engine_update_files_symbols (sdb_plugin
->sdbe_project
,
650 sdb_plugin
->project_root_dir
, files_array
, TRUE
);
655 /* add a task so that scan_end_manager can manage this */
656 g_tree_insert (sdb_plugin
->proc_id_tree
, GINT_TO_POINTER (proc_id
),
657 GINT_TO_POINTER (TASK_FILE_UPDATE
));
660 g_hash_table_insert (sdb_plugin
->editor_connected
, editor
,
661 g_strdup (saved_uri
));
663 /* if we saved it we shouldn't update a second time */
664 sdb_plugin
->need_symbols_update
= FALSE
;
666 on_editor_update_ui (editor
, sdb_plugin
);
671 value_added_current_editor (AnjutaPlugin
*plugin
, const char *name
,
672 const GValue
*value
, gpointer data
)
675 gboolean tags_update
;
679 SymbolDBPlugin
*sdb_plugin
;
681 editor
= g_value_get_object (value
);
682 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
683 if (sdb_plugin
->session_loading
)
688 DEBUG_PRINT ("%s", "Updating symbols");
690 if (!sdb_plugin
->editor_connected
)
692 sdb_plugin
->editor_connected
= g_hash_table_new_full (g_direct_hash
,
696 sdb_plugin
->current_editor
= editor
;
698 if (!sdb_plugin
->editors
)
700 sdb_plugin
->editors
= g_hash_table_new (NULL
, NULL
);
703 if (!IANJUTA_IS_EDITOR (editor
))
706 file
= ianjuta_file_get_file (IANJUTA_FILE (editor
), NULL
);
711 local_path
= g_file_get_path (file
);
712 uri
= g_file_get_uri (file
);
714 if (local_path
== NULL
)
716 g_critical ("local_path == NULL");
720 /* we can have a weird behaviour here if we're not paying the right attention:
721 * A timeout scan could have been launched and a millisecond later the user could
722 * have switched editor: we'll be getting the symbol inserted in the previous
723 * editor into the new one's view.
725 if (sdb_plugin
->buffer_update_files
->len
> 0)
727 sdb_plugin
->buffer_update_semaphore
= TRUE
;
731 g_object_set (sdb_plugin
->file_model
, "file-path", local_path
, NULL
);
733 /* add a default timeout to the updating of buffer symbols */
734 tags_update
= g_settings_get_boolean (sdb_plugin
->settings
, BUFFER_UPDATE
);
739 sdb_plugin
->buf_update_timeout_id
=
740 g_timeout_add_seconds (TIMEOUT_INTERVAL_SYMBOLS_UPDATE
,
741 on_editor_buffer_symbols_update_timeout
,
746 if (g_hash_table_lookup (sdb_plugin
->editor_connected
, editor
) == NULL
)
748 g_object_weak_ref (G_OBJECT (editor
),
749 (GWeakNotify
) (on_editor_destroy
),
753 g_hash_table_insert (sdb_plugin
->editor_connected
, editor
,
758 g_hash_table_insert (sdb_plugin
->editor_connected
, editor
,
762 g_signal_connect (G_OBJECT (editor
), "saved",
763 G_CALLBACK (on_editor_saved
),
765 g_signal_connect (G_OBJECT (editor
), "char-added",
766 G_CALLBACK (on_char_added
),
768 g_signal_connect (G_OBJECT (editor
), "code-changed",
769 G_CALLBACK (on_code_added
),
771 g_signal_connect (G_OBJECT(editor
), "update_ui",
772 G_CALLBACK (on_editor_update_ui
),
778 sdb_plugin
->need_symbols_update
= FALSE
;
782 on_editor_foreach_disconnect (gpointer key
, gpointer value
, gpointer user_data
)
784 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
785 G_CALLBACK (on_editor_saved
),
787 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
788 G_CALLBACK (on_editor_update_ui
),
790 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
791 G_CALLBACK (on_char_added
),
793 g_signal_handlers_disconnect_by_func (G_OBJECT(key
),
794 G_CALLBACK (on_code_added
),
796 g_object_weak_unref (G_OBJECT(key
),
797 (GWeakNotify
) (on_editor_destroy
),
802 same_editor (gpointer key
, gpointer value
, gpointer user_data
)
804 return value
== user_data
;
808 value_removed_current_editor (AnjutaPlugin
*plugin
,
809 const char *name
, gpointer data
)
811 SymbolDBPlugin
*sdb_plugin
;
813 sdb_plugin
= (SymbolDBPlugin
*) plugin
;
815 DEBUG_PRINT ("%s", "value_removed_current_editor ()");
816 /* let's remove the timeout for symbols refresh */
817 if (sdb_plugin
->buf_update_timeout_id
)
818 g_source_remove (sdb_plugin
->buf_update_timeout_id
);
819 sdb_plugin
->buf_update_timeout_id
= 0;
820 sdb_plugin
->need_symbols_update
= FALSE
;
822 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
825 /* Remove editor from list of editors */
826 if(sdb_plugin
->editors
)
827 g_hash_table_foreach_remove (sdb_plugin
->editors
, same_editor
, sdb_plugin
->current_editor
);
829 sdb_plugin
->current_editor
= NULL
;
833 * Perform the real add to the db and also checks that no dups are inserted.
834 * Return the real number of files added or -1 on error.
837 do_add_new_files (SymbolDBPlugin
*sdb_plugin
, const GPtrArray
*sources_array
,
840 GPtrArray
* languages_array
= NULL
;
841 GPtrArray
* to_scan_array
= NULL
;
842 GHashTable
* check_unique_file_hash
= NULL
;
843 IAnjutaLanguage
* lang_manager
;
844 AnjutaPlugin
*plugin
;
849 plugin
= ANJUTA_PLUGIN (sdb_plugin
);
851 /* create array of languages and the wannabe scanned files */
852 languages_array
= g_ptr_array_new_with_free_func (g_free
);
853 to_scan_array
= g_ptr_array_new_with_free_func (g_free
);
855 /* to speed the things up we must avoid the dups */
856 check_unique_file_hash
= g_hash_table_new_full (g_str_hash
,
857 g_str_equal
, NULL
, NULL
);
859 lang_manager
= anjuta_shell_get_interface (plugin
->shell
, IAnjutaLanguage
,
864 g_critical ("LanguageManager not found");
868 for (i
=0; i
< sources_array
->len
; i
++)
870 const gchar
*file_mime
;
872 const gchar
*local_filename
;
874 GFileInfo
*gfile_info
;
875 IAnjutaLanguageId lang_id
;
877 if ( (local_filename
= g_ptr_array_index (sources_array
, i
)) == NULL
)
880 if ((gfile
= g_file_new_for_path (local_filename
)) == NULL
)
883 gfile_info
= g_file_query_info (gfile
,
884 "standard::content-type",
885 G_FILE_QUERY_INFO_NONE
,
888 if (gfile_info
== NULL
)
890 g_object_unref (gfile
);
894 /* check if it's already present in the list. This avoids
897 if (g_hash_table_lookup (check_unique_file_hash
,
898 local_filename
) == NULL
)
900 g_hash_table_insert (check_unique_file_hash
,
901 (gpointer
)local_filename
,
902 (gpointer
)local_filename
);
906 /* you're a dup! we don't want you */
910 file_mime
= g_file_info_get_attribute_string (gfile_info
,
911 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE
);
913 lang_id
= ianjuta_language_get_from_mime_type (lang_manager
,
918 g_object_unref (gfile
);
919 g_object_unref (gfile_info
);
923 lang
= ianjuta_language_get_name (lang_manager
, lang_id
, NULL
);
925 /* test its existence */
926 if (g_file_test (local_filename
, G_FILE_TEST_EXISTS
) == FALSE
)
928 g_object_unref (gfile
);
929 g_object_unref (gfile_info
);
933 /* ok, we've just tested that the local_filename does exist.
934 * We can safely add it to the array.
936 g_ptr_array_add (languages_array
, g_strdup (lang
));
937 g_ptr_array_add (to_scan_array
, g_strdup (local_filename
));
938 g_object_unref (gfile
);
939 g_object_unref (gfile_info
);
942 /* last but not least check if we had some files in that GPtrArray. It that's not
943 * the case just pass over
946 if (to_scan_array
->len
> 0)
948 proc_id
= symbol_db_engine_add_new_files_full_async (sdb_plugin
->sdbe_project
,
949 sdb_plugin
->project_opened
, "1.0", to_scan_array
, languages_array
,
955 /* insert the proc id associated within the task */
956 g_tree_insert (sdb_plugin
->proc_id_tree
, GINT_TO_POINTER (proc_id
),
957 GINT_TO_POINTER (task
));
960 /* get the real added number of files */
961 added_num
= to_scan_array
->len
;
963 g_ptr_array_unref (languages_array
);
964 g_ptr_array_unref (to_scan_array
);
966 g_hash_table_destroy (check_unique_file_hash
);
968 return proc_id
> 0 ? added_num
: -1;
972 on_project_element_added (IAnjutaProjectManager
*pm
, GFile
*gfile
,
973 SymbolDBPlugin
*sdb_plugin
)
977 GPtrArray
*files_array
;
979 g_return_if_fail (sdb_plugin
->project_root_uri
!= NULL
);
980 g_return_if_fail (sdb_plugin
->project_root_dir
!= NULL
);
982 filename
= g_file_get_path (gfile
);
984 files_array
= g_ptr_array_new_with_free_func (g_free
);
985 g_ptr_array_add (files_array
, filename
);
987 sdb_plugin
->is_adding_element
= TRUE
;
989 /* use a custom function to add the files to db */
990 real_added
= do_add_new_files (sdb_plugin
, files_array
, TASK_ELEMENT_ADDED
);
993 sdb_plugin
->is_adding_element
= FALSE
;
996 g_ptr_array_unref (files_array
);
1000 on_project_element_removed (IAnjutaProjectManager
*pm
, GFile
*gfile
,
1001 SymbolDBPlugin
*sdb_plugin
)
1005 if (!sdb_plugin
->project_root_uri
)
1008 filename
= g_file_get_path (gfile
);
1012 DEBUG_PRINT ("%s", "on_project_element_removed");
1013 symbol_db_engine_remove_file (sdb_plugin
->sdbe_project
,
1014 sdb_plugin
->project_root_dir
,
1015 symbol_db_util_get_file_db_path (sdb_plugin
->sdbe_project
,
1023 on_system_scan_package_start (SymbolDBEngine
*dbe
, guint num_files
,
1024 const gchar
*package
, gpointer user_data
)
1026 SymbolDBPlugin
*sdb_plugin
;
1027 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (user_data
);
1029 sdb_plugin
->files_count_system_done
= 0;
1030 sdb_plugin
->files_count_system
+= num_files
;
1033 /* show the global bar */
1034 gtk_widget_show (sdb_plugin
->progress_bar_system
);
1035 if (sdb_plugin
->current_scanned_package
!= NULL
)
1036 g_free (sdb_plugin
->current_scanned_package
);
1037 sdb_plugin
->current_scanned_package
= g_strdup (package
);
1039 DEBUG_PRINT ("********************* START [%s] with n %d files ", package
, num_files
);
1043 on_system_scan_package_end (SymbolDBEngine
*dbe
, const gchar
*package
,
1046 SymbolDBPlugin
*sdb_plugin
;
1047 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (user_data
);
1049 DEBUG_PRINT ("******************** END () [%s]", package
);
1051 /* hide the progress bar */
1052 gtk_widget_hide (sdb_plugin
->progress_bar_system
);
1054 sdb_plugin
->files_count_system_done
= 0;
1055 sdb_plugin
->files_count_system
= 0;
1059 on_system_single_file_scan_end (SymbolDBEngine
*dbe
, gpointer data
)
1061 AnjutaPlugin
*plugin
;
1062 SymbolDBPlugin
*sdb_plugin
;
1064 gdouble fraction
= 0;
1066 plugin
= ANJUTA_PLUGIN (data
);
1067 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
1069 sdb_plugin
->files_count_system_done
++;
1070 if (sdb_plugin
->files_count_system_done
>= sdb_plugin
->files_count_system
)
1072 message
= g_strdup_printf (_("%s: Generating inheritances…"),
1073 sdb_plugin
->current_scanned_package
);
1077 /* Translators: %s is the name of a system library */
1078 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
),
1079 sdb_plugin
->current_scanned_package
,
1080 sdb_plugin
->files_count_system_done
,
1081 sdb_plugin
->files_count_system
);
1084 if (sdb_plugin
->files_count_system
> 0)
1086 fraction
= (gdouble
) sdb_plugin
->files_count_system_done
/
1087 (gdouble
) sdb_plugin
->files_count_system
;
1089 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_system
),
1091 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_system
), message
);
1097 on_project_single_file_scan_end (SymbolDBEngine
*dbe
, gpointer data
)
1099 AnjutaPlugin
*plugin
;
1100 SymbolDBPlugin
*sdb_plugin
;
1102 gdouble fraction
= 0;
1104 plugin
= ANJUTA_PLUGIN (data
);
1105 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
1107 sdb_plugin
->files_count_project_done
++;
1108 if (sdb_plugin
->files_count_project_done
>= sdb_plugin
->files_count_project
)
1109 message
= g_strdup_printf (_("Generating inheritances…"));
1111 message
= g_strdup_printf (ngettext ("%d file scanned out of %d", "%d files scanned out of %d", sdb_plugin
->files_count_project_done
),
1112 sdb_plugin
->files_count_project_done
, sdb_plugin
->files_count_project
);
1114 if (sdb_plugin
->files_count_project
> 0)
1116 fraction
= (gdouble
) sdb_plugin
->files_count_project_done
/
1117 (gdouble
) sdb_plugin
->files_count_project
;
1121 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_project
),
1123 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_project
), message
);
1124 gtk_widget_show (sdb_plugin
->progress_bar_project
);
1129 clear_project_progress_bar (SymbolDBEngine
*dbe
, gpointer data
)
1131 SymbolDBPlugin
*sdb_plugin
;
1133 g_return_if_fail (data
!= NULL
);
1135 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (data
);
1137 /* hide the progress bar */
1138 gtk_widget_hide (sdb_plugin
->progress_bar_project
);
1142 on_check_offline_single_file_scan_end (SymbolDBEngine
*dbe
, gpointer data
)
1144 on_project_single_file_scan_end (dbe
, data
);
1147 /* note the *system* word in the function */
1149 do_import_system_sources_after_abort (SymbolDBPlugin
*sdb_plugin
,
1150 const GPtrArray
*sources_array
)
1152 AnjutaPlugin
*plugin
;
1153 GPtrArray
* languages_array
= NULL
;
1154 GPtrArray
*to_scan_array
= NULL
;
1155 IAnjutaLanguage
* lang_manager
;
1158 plugin
= ANJUTA_PLUGIN (sdb_plugin
);
1160 lang_manager
= anjuta_shell_get_interface (plugin
->shell
, IAnjutaLanguage
,
1163 /* create array of languages */
1164 languages_array
= g_ptr_array_new_with_free_func (g_free
);
1165 to_scan_array
= g_ptr_array_new_with_free_func (g_free
);
1169 g_critical ("LanguageManager not found");
1173 for (i
=0; i
< sources_array
->len
; i
++)
1175 const gchar
*file_mime
;
1177 const gchar
*local_filename
;
1179 GFileInfo
*gfile_info
;
1180 IAnjutaLanguageId lang_id
;
1182 local_filename
= g_ptr_array_index (sources_array
, i
);
1184 if (local_filename
== NULL
)
1187 gfile
= g_file_new_for_path (local_filename
);
1191 gfile_info
= g_file_query_info (gfile
,
1193 G_FILE_QUERY_INFO_NONE
,
1196 if (gfile_info
== NULL
)
1198 g_object_unref (gfile
);
1202 file_mime
= g_file_info_get_attribute_string (gfile_info
,
1203 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE
);
1205 lang_id
= ianjuta_language_get_from_mime_type (lang_manager
,
1210 g_object_unref (gfile
);
1211 g_object_unref (gfile_info
);
1215 lang
= ianjuta_language_get_name (lang_manager
, lang_id
, NULL
);
1217 /* test its existence */
1218 if (g_file_test (local_filename
, G_FILE_TEST_EXISTS
) == FALSE
)
1220 g_object_unref (gfile
);
1221 g_object_unref (gfile_info
);
1225 g_ptr_array_add (languages_array
, g_strdup (lang
));
1226 g_ptr_array_add (to_scan_array
, g_strdup (local_filename
));
1227 g_object_unref (gfile
);
1228 g_object_unref (gfile_info
);
1231 /* FIXME HERE currently disabled */
1233 symbol_db_system_parse_aborted_package (sdb_plugin
->sdbs
,
1238 g_ptr_array_unref(to_scan_array
);
1239 g_ptr_array_unref(languages_array
);
1242 /* we assume that sources_array has already unique elements */
1243 /* note the *project* word in the function */
1245 do_import_project_sources_after_abort (SymbolDBPlugin
*sdb_plugin
,
1246 const GPtrArray
*sources_array
)
1250 sdb_plugin
->is_project_importing
= TRUE
;
1252 /* connect to receive signals on single file scan complete. We'll
1253 * update a status bar notifying the user about the status
1255 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_project
), "single-file-scan-end",
1256 G_CALLBACK (on_project_single_file_scan_end
), sdb_plugin
);
1258 real_added
= do_add_new_files (sdb_plugin
, sources_array
,
1259 TASK_IMPORT_PROJECT_AFTER_ABORT
);
1260 if (real_added
<= 0)
1262 sdb_plugin
->is_project_importing
= FALSE
;
1266 sdb_plugin
->files_count_project
+= real_added
;
1271 do_import_project_sources (SymbolDBPlugin
*sdb_plugin
, IAnjutaProjectManager
*pm
,
1272 const gchar
*root_dir
)
1274 GList
* prj_elements_list
;
1275 GPtrArray
* sources_array
;
1279 prj_elements_list
= ianjuta_project_manager_get_elements (pm
,
1280 ANJUTA_PROJECT_SOURCE
| ANJUTA_PROJECT_PROJECT
,
1283 if (prj_elements_list
== NULL
)
1285 g_warning ("No sources found within this project");
1289 /* if we're importing first shut off the signal receiving.
1290 * We'll re-enable that on scan-end
1292 sdb_plugin
->is_project_importing
= TRUE
;
1293 DEBUG_PRINT ("Retrieving %d gbf sources of the project…",
1294 g_list_length (prj_elements_list
));
1296 /* create the storage array. The file names will be strdup'd and put here.
1297 * This is just a sort of GList -> GPtrArray conversion.
1299 sources_array
= g_ptr_array_new_with_free_func (g_free
);
1300 for (i
=0; i
< g_list_length (prj_elements_list
); i
++)
1302 gchar
*local_filename
;
1303 GFile
*gfile
= NULL
;
1305 gfile
= g_list_nth_data (prj_elements_list
, i
);
1307 if ((local_filename
= g_file_get_path (gfile
)) == NULL
)
1312 g_ptr_array_add (sources_array
, local_filename
);
1315 /* connect to receive signals on single file scan complete. We'll
1316 * update a status bar notifying the user about the status
1318 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_project
), "single-file-scan-end",
1319 G_CALLBACK (on_project_single_file_scan_end
), sdb_plugin
);
1321 real_added
= do_add_new_files (sdb_plugin
, sources_array
, TASK_IMPORT_PROJECT
);
1322 if (real_added
<= 0)
1324 sdb_plugin
->is_project_importing
= FALSE
;
1326 sdb_plugin
->files_count_project
+= real_added
;
1329 /* free the ptr array */
1330 g_ptr_array_unref (sources_array
);
1332 /* and the list of project files */
1333 g_list_foreach (prj_elements_list
, (GFunc
) g_object_unref
, NULL
);
1334 g_list_free (prj_elements_list
);
1338 * This function will call do_import_project_sources_after_abort ().
1339 * The list of files for sysstem packages enqueued on the first scan aren't
1340 * persisted on session for later retrieval. So we can only rely
1341 * on fixing the zero-symbols file.
1344 do_import_system_sources (SymbolDBPlugin
*sdb_plugin
)
1346 /* the resume thing */
1347 GPtrArray
*sys_src_array
= NULL
;
1349 symbol_db_util_get_files_with_zero_symbols (sdb_plugin
->sdbe_globals
);
1351 if (sys_src_array
!= NULL
&& sys_src_array
->len
> 0)
1353 do_import_system_sources_after_abort (sdb_plugin
, sys_src_array
);
1355 g_ptr_array_unref (sys_src_array
);
1360 * @return TRUE if a scan is in progress, FALSE elsewhere.
1363 do_update_project_symbols (SymbolDBPlugin
*sdb_plugin
, const gchar
*root_dir
)
1366 /* Update the symbols */
1367 proc_id
= symbol_db_engine_update_project_symbols (sdb_plugin
->sdbe_project
,
1371 sdb_plugin
->is_project_updating
= TRUE
;
1373 /* insert the proc id associated within the task */
1374 g_tree_insert (sdb_plugin
->proc_id_tree
, GINT_TO_POINTER (proc_id
),
1375 GINT_TO_POINTER (TASK_PROJECT_UPDATE
));
1383 * do_check_offline_files_changed:
1386 * Returns: TRUE if a scan process is started, FALSE elsewhere.
1389 do_check_offline_files_changed (SymbolDBPlugin
*sdb_plugin
)
1391 GList
* prj_elements_list
;
1393 IAnjutaProjectManager
*pm
;
1394 GHashTable
*prj_elements_hash
;
1395 GPtrArray
*to_add_files
= NULL
;
1396 gint real_added
= 0;
1398 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
,
1399 IAnjutaProjectManager
, NULL
);
1401 prj_elements_list
= ianjuta_project_manager_get_elements (pm
,
1402 ANJUTA_PROJECT_SOURCE
| ANJUTA_PROJECT_PROJECT
,
1405 /* fill an hash table with all the items of the list just taken.
1406 * We won't g_strdup () the elements because they'll be freed later
1408 prj_elements_hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
,
1411 for (node
= prj_elements_list
; node
!= NULL
; node
= g_list_next (node
))
1415 const gchar
*db_path
;
1421 if ((filename
= g_file_get_path (gfile
)) == NULL
||
1424 g_object_unref (gfile
);
1429 /* test its existence */
1430 if (g_file_query_exists (gfile
, NULL
) == FALSE
)
1432 g_object_unref (gfile
);
1437 /* Use g_hash_table_replace instead of g_hash_table_insert because the key
1438 * and the value use the same block of memory, both must be changed at
1440 db_path
= symbol_db_util_get_file_db_path (sdb_plugin
->sdbe_project
,
1444 g_hash_table_replace (prj_elements_hash
,
1447 g_object_unref (gfile
);
1450 g_list_free(prj_elements_list
);
1452 /* some files may have added/removed editing Makefile.am while
1453 * Anjuta was offline. Check this case too.
1454 * FIXME: Get rid of data model here.
1456 GdaDataModel
*model
=
1457 symbol_db_engine_get_files_for_project (sdb_plugin
->sdbe_project
);
1458 GdaDataModelIter
*it
=
1459 gda_data_model_create_iter (model
);
1461 if (it
&& gda_data_model_iter_move_to_row (it
, 0))
1463 GPtrArray
*remove_array
;
1464 remove_array
= g_ptr_array_new_with_free_func (g_free
);
1466 const GValue
*val
= gda_data_model_iter_get_value_at (it
, 0);
1467 const gchar
* file
= g_value_get_string (val
);
1469 if (file
&& g_hash_table_remove (prj_elements_hash
, file
) == FALSE
)
1470 g_ptr_array_add (remove_array
, g_strdup (file
));
1472 } while (gda_data_model_iter_move_next (it
));
1474 symbol_db_engine_remove_files (sdb_plugin
->sdbe_project
,
1475 sdb_plugin
->project_opened
,
1477 g_ptr_array_unref (remove_array
);
1480 /* great, at this point we should have this situation:
1481 * remove array = files to remove, remaining items in the hash_table = files
1484 to_add_files
= g_ptr_array_new ();
1485 if (g_hash_table_size (prj_elements_hash
) > 0)
1488 GList
*keys
= g_hash_table_get_keys (prj_elements_hash
);
1490 /* get all the nodes from the hash table and add them to the wannabe-added
1493 for (i
= 0; i
< g_hash_table_size (prj_elements_hash
); i
++)
1495 /*DEBUG_PRINT ("ARRAY ADD %s", (gchar*)g_list_nth_data (keys, i));*/
1496 g_ptr_array_add (to_add_files
,
1497 g_hash_table_lookup (prj_elements_hash
,
1498 g_list_nth_data (keys
, i
)));
1502 /* good. Let's go on with add of new files. */
1503 if (to_add_files
->len
> 0)
1505 /* block the signals spreading from engine to local-view tab */
1506 sdb_plugin
->is_offline_scanning
= TRUE
;
1507 real_added
= do_add_new_files (sdb_plugin
, to_add_files
,
1508 TASK_OFFLINE_CHANGES
);
1510 DEBUG_PRINT ("going to do add %d files with TASK_OFFLINE_CHANGES",
1513 if (real_added
<= 0)
1515 sdb_plugin
->is_offline_scanning
= FALSE
;
1518 /* connect to receive signals on single file scan complete. We'll
1519 * update a status bar notifying the user about the status
1521 sdb_plugin
->files_count_project
+= real_added
;
1523 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_project
), "single-file-scan-end",
1524 G_CALLBACK (on_check_offline_single_file_scan_end
), ANJUTA_PLUGIN (sdb_plugin
));
1528 /*if (it != NULL) g_object_unref (it);*/
1529 g_object_unref (it
);
1530 g_object_unref (model
);
1531 g_ptr_array_unref (to_add_files
);
1532 g_hash_table_destroy (prj_elements_hash
);
1534 return real_added
> 0 ? TRUE
: FALSE
;
1538 on_session_save (AnjutaShell
*shell
, AnjutaSessionPhase phase
,
1539 AnjutaSession
*session
,
1540 SymbolDBPlugin
*sdb_plugin
)
1542 if (phase
!= ANJUTA_SESSION_PHASE_NORMAL
)
1545 DEBUG_PRINT ("%s", "SymbolDB: session_save");
1549 on_session_load (AnjutaShell
*shell
, AnjutaSessionPhase phase
,
1550 AnjutaSession
*session
,
1551 SymbolDBPlugin
*sdb_plugin
)
1553 if (phase
== ANJUTA_SESSION_PHASE_START
)
1555 DEBUG_PRINT ("SymbolDB: session_loading started. Getting info from %s",
1556 anjuta_session_get_session_directory (session
));
1557 sdb_plugin
->session_loading
= TRUE
;
1559 /* get preferences about the parallel scan */
1560 gboolean parallel_scan
= g_settings_get_boolean (sdb_plugin
->settings
,
1563 if (parallel_scan
== TRUE
&&
1564 symbol_db_engine_is_connected (sdb_plugin
->sdbe_globals
) == TRUE
)
1566 /* we simulate a project-import-end signal received */
1567 do_import_system_sources (sdb_plugin
);
1570 else if (phase
== ANJUTA_SESSION_PHASE_END
)
1572 IAnjutaDocumentManager
* docman
;
1573 sdb_plugin
->session_loading
= FALSE
;
1574 DEBUG_PRINT ("SymbolDB: session_loading finished");
1576 /* Show the symbols for the current editor */
1577 docman
= anjuta_shell_get_interface (shell
, IAnjutaDocumentManager
, NULL
);
1580 IAnjutaDocument
* cur_doc
=
1581 ianjuta_document_manager_get_current_document (docman
, NULL
);
1584 GValue value
= {0, };
1585 g_value_init (&value
, G_TYPE_OBJECT
);
1586 g_value_set_object (&value
, cur_doc
);
1587 value_added_current_editor (ANJUTA_PLUGIN (sdb_plugin
),
1588 "document_manager_current_document",
1590 g_value_unset(&value
);
1594 if (sdb_plugin
->project_opened
== NULL
)
1596 gtk_widget_hide (sdb_plugin
->progress_bar_project
);
1597 gtk_widget_hide (sdb_plugin
->progress_bar_system
);
1603 on_project_loaded (IAnjutaProjectManager
*pm
, GError
*error
,
1604 SymbolDBPlugin
*sdb_plugin
)
1606 g_return_if_fail (sdb_plugin
->project_root_uri
!= NULL
);
1607 g_return_if_fail (sdb_plugin
->project_root_dir
!= NULL
);
1609 /* Malformed project abort */
1610 if (error
!= NULL
) return;
1613 * we need an initial import
1615 if (sdb_plugin
->needs_sources_scan
== TRUE
)
1617 DEBUG_PRINT ("Importing sources.");
1618 do_import_project_sources (sdb_plugin
, pm
, sdb_plugin
->project_root_dir
);
1623 * no import needed. But we may have aborted the scan of sources in
1624 * a previous session..
1626 GPtrArray
*sources_array
= NULL
;
1628 DEBUG_PRINT ("Checking for files with zero symbols.");
1630 symbol_db_util_get_files_with_zero_symbols (sdb_plugin
->sdbe_project
);
1632 if (sources_array
!= NULL
&& sources_array
->len
> 0)
1634 DEBUG_PRINT ("Importing files after abort.");
1635 do_import_project_sources_after_abort (sdb_plugin
, sources_array
);
1637 g_ptr_array_unref (sources_array
);
1640 DEBUG_PRINT ("Checking for offline changes.");
1641 /* check for offline changes */
1642 if (do_check_offline_files_changed (sdb_plugin
) == FALSE
)
1644 DEBUG_PRINT ("no changes. Skipping.");
1647 DEBUG_PRINT ("Updating project symbols.");
1648 /* update any files of the project which isn't up-to-date */
1649 if (do_update_project_symbols (sdb_plugin
, sdb_plugin
->project_opened
) == FALSE
)
1651 DEBUG_PRINT ("no changes. Skipping.");
1656 /* add a new project */
1658 on_project_root_added (AnjutaPlugin
*plugin
, const gchar
*name
,
1659 const GValue
*value
, gpointer user_data
)
1661 SymbolDBPlugin
*sdb_plugin
;
1662 const gchar
*root_uri
;
1665 GError
*error
= NULL
;
1667 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
1670 * The Global System symbols thing
1673 /* is the global db connected? */
1674 if (symbol_db_engine_is_connected (sdb_plugin
->sdbe_globals
) == FALSE
)
1676 gchar
*anjuta_cache_path
;
1677 /* open the connection to global db */
1678 anjuta_cache_path
= anjuta_util_get_user_cache_file_path (".", NULL
);
1679 if (symbol_db_engine_open_db (sdb_plugin
->sdbe_globals
,
1682 &error
) == DB_OPEN_STATUS_FATAL
)
1684 g_error ("Opening global project under %s: %s", anjuta_cache_path
, error
->message
);
1686 g_free (anjuta_cache_path
);
1688 /* unref and recreate the sdbs object */
1689 if (sdb_plugin
->sdbs
!= NULL
)
1690 g_object_unref (sdb_plugin
->sdbs
);
1692 sdb_plugin
->sdbs
= symbol_db_system_new (sdb_plugin
,
1693 sdb_plugin
->sdbe_globals
);
1696 /* Hide the progress bar. Default system tags thing: we'll import after abort even
1697 * if the preferences says not to automatically scan the packages.
1699 gtk_widget_hide (sdb_plugin
->progress_bar_system
);
1706 g_free (sdb_plugin
->project_root_uri
);
1707 sdb_plugin
->project_root_uri
= NULL
;
1708 if ((root_uri
= g_value_get_string (value
)) == NULL
)
1710 DEBUG_PRINT ("Warning, root_uri for project is NULL");
1715 gfile
= g_file_new_for_uri (root_uri
);
1717 root_dir
= g_file_get_path (gfile
);
1718 DEBUG_PRINT ("Symbol-DB: added project root_dir %s, name %s", root_dir
,
1721 g_object_unref (gfile
);
1723 /* let the project be something like "." to avoid problems when renaming the
1725 sdb_plugin
->project_opened
= g_strdup (PROJECT_ROOT_NAME_DEFAULT
);
1729 gboolean project_exist
= FALSE
;
1732 /* we'll use the same values for db_directory and project_directory */
1733 DEBUG_PRINT ("Opening db %s and project_dir %s", root_dir
, root_dir
);
1734 gint open_status
= symbol_db_engine_open_db (sdb_plugin
->sdbe_project
, root_dir
,
1737 /* is it a fresh-new project? is it an imported project with
1738 * no 'new' symbol-db database but the 'old' one symbol-browser?
1740 sdb_plugin
->needs_sources_scan
= FALSE
;
1741 switch (open_status
)
1743 case DB_OPEN_STATUS_FATAL
:
1744 g_warning ("*** Error in opening db: %s***", error
->message
);
1747 case DB_OPEN_STATUS_NORMAL
:
1748 project_exist
= TRUE
;
1751 case DB_OPEN_STATUS_CREATE
:
1752 case DB_OPEN_STATUS_UPGRADE
:
1753 sdb_plugin
->needs_sources_scan
= TRUE
;
1754 project_exist
= FALSE
;
1761 /* if project did not exist add a new project */
1762 if (project_exist
== FALSE
)
1764 DEBUG_PRINT ("Creating new project.");
1765 symbol_db_engine_add_new_project (sdb_plugin
->sdbe_project
,
1766 NULL
, /* still no workspace logic */
1767 sdb_plugin
->project_opened
,
1771 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_project
),
1772 _("Populating symbol database…"));
1773 id
= g_idle_add ((GSourceFunc
) gtk_progress_bar_pulse
,
1774 sdb_plugin
->progress_bar_project
);
1775 gtk_widget_show (sdb_plugin
->progress_bar_project
);
1776 g_source_remove (id
);
1777 gtk_widget_hide (sdb_plugin
->progress_bar_project
);
1780 sdb_plugin
->project_root_dir
= root_dir
;
1783 sdb_plugin
->project_root_uri
= g_strdup (root_uri
);
1787 on_project_root_removed (AnjutaPlugin
*plugin
, const gchar
*name
,
1790 IAnjutaProjectManager
*pm
;
1791 SymbolDBPlugin
*sdb_plugin
;
1793 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
1794 DEBUG_PRINT ("%s", "project_root_removed ()");
1795 /* Disconnect events from project manager */
1797 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
,
1798 IAnjutaProjectManager
, NULL
);
1799 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
1800 on_project_element_added
,
1802 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
1803 on_project_element_removed
,
1806 /* don't forget to close the project */
1807 symbol_db_engine_close_db (sdb_plugin
->sdbe_project
);
1809 /* and the globals one */
1810 symbol_db_engine_close_db (sdb_plugin
->sdbe_globals
);
1812 /* stop any opened scanning process */
1813 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_system
), "");
1814 gtk_progress_bar_set_text (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_project
), "");
1815 gtk_widget_hide (sdb_plugin
->progress_bar_system
);
1816 gtk_widget_hide (sdb_plugin
->progress_bar_project
);
1818 sdb_plugin
->files_count_system_done
= 0;
1819 sdb_plugin
->files_count_system
= 0;
1821 sdb_plugin
->files_count_project_done
= 0;
1822 sdb_plugin
->files_count_project
= 0;
1825 g_free (sdb_plugin
->project_root_uri
);
1826 g_free (sdb_plugin
->project_root_dir
);
1827 g_free (sdb_plugin
->project_opened
);
1828 sdb_plugin
->project_root_uri
= NULL
;
1829 sdb_plugin
->project_root_dir
= NULL
;
1830 sdb_plugin
->project_opened
= NULL
;
1834 on_scan_end_manager (SymbolDBEngine
*dbe
, gint process_id
,
1837 SymbolDBPlugin
*sdb_plugin
;
1838 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (data
);
1839 gint task_registered
;
1841 task_registered
= GPOINTER_TO_INT (g_tree_lookup (sdb_plugin
->proc_id_tree
,
1842 GINT_TO_POINTER (process_id
)));
1843 /* hey, we haven't find anything */
1844 if (task_registered
<= 0)
1846 DEBUG_PRINT ("No task found, proc id was %d", process_id
);
1850 switch (task_registered
)
1852 case TASK_IMPORT_PROJECT
:
1853 case TASK_IMPORT_PROJECT_AFTER_ABORT
:
1855 DEBUG_PRINT ("received TASK_IMPORT_PROJECT (AFTER_ABORT)");
1857 /* re-enable signals receiving on local-view */
1858 sdb_plugin
->is_project_importing
= FALSE
;
1860 /* disconnect this coz it's not important after the process of importing */
1861 g_signal_handlers_disconnect_by_func (dbe
, on_project_single_file_scan_end
,
1864 /* get preferences about the parallel scan */
1865 gboolean parallel_scan
= g_settings_get_boolean (sdb_plugin
->settings
,
1869 /* check the system population has a parallel fashion or not. */
1870 if (parallel_scan
== FALSE
)
1871 do_import_system_sources (sdb_plugin
);
1875 case TASK_BUFFER_UPDATE
:
1876 DEBUG_PRINT ("received TASK_BUFFER_UPDATE");
1877 on_editor_buffer_symbol_update_scan_end (dbe
, process_id
, sdb_plugin
);
1880 case TASK_ELEMENT_ADDED
:
1881 DEBUG_PRINT ("received TASK_ELEMENT_ADDED");
1882 sdb_plugin
->is_adding_element
= FALSE
;
1885 case TASK_OFFLINE_CHANGES
:
1886 DEBUG_PRINT ("received TASK_OFFLINE_CHANGES");
1888 /* disconnect this coz it's not important after the process of importing */
1889 g_signal_handlers_disconnect_by_func (dbe
, on_check_offline_single_file_scan_end
,
1892 sdb_plugin
->is_offline_scanning
= FALSE
;
1895 case TASK_PROJECT_UPDATE
:
1896 DEBUG_PRINT ("received TASK_PROJECT_UPDATE");
1897 sdb_plugin
->is_project_updating
= FALSE
;
1900 case TASK_FILE_UPDATE
:
1901 DEBUG_PRINT ("received TASK_FILE_UPDATE");
1905 DEBUG_PRINT ("Don't know what to to with task_registered %d",
1909 /* ok, we're done. Remove the proc_id from the GTree coz we won't use it anymore */
1910 if (g_tree_remove (sdb_plugin
->proc_id_tree
, GINT_TO_POINTER (process_id
)) == FALSE
)
1911 g_warning ("Cannot remove proc_id from GTree");
1913 DEBUG_PRINT ("is_offline_scanning %d, is_project_importing %d, is_project_updating %d, "
1914 "is_adding_element %d", sdb_plugin
->is_offline_scanning
,
1915 sdb_plugin
->is_project_importing
, sdb_plugin
->is_project_updating
,
1916 sdb_plugin
->is_adding_element
);
1918 /* is the project still opened? */
1919 if (sdb_plugin
->project_opened
== NULL
)
1921 /* just return, the project may have been closed while we were waiting for the
1922 * scanning to finish
1928 * perform some checks on some booleans. If they're all successfully passed
1929 * then activate the display of local view
1931 if (sdb_plugin
->is_offline_scanning
== FALSE
&&
1932 sdb_plugin
->is_project_importing
== FALSE
&&
1933 sdb_plugin
->is_project_updating
== FALSE
&&
1934 sdb_plugin
->is_adding_element
== FALSE
)
1936 sdb_plugin
->files_count_project_done
= 0;
1937 sdb_plugin
->files_count_project
= 0;
1938 clear_project_progress_bar (dbe
, sdb_plugin
);
1943 on_isymbol_manager_prj_scan_end (SymbolDBEngine
*dbe
,
1945 IAnjutaSymbolManager
*sm
)
1947 g_signal_emit_by_name (sm
, "prj-scan-end", process_id
);
1951 on_isymbol_manager_sys_scan_begin (SymbolDBEngine
*dbe
, gint process_id
,
1952 SymbolDBPlugin
*sdb_plugin
)
1954 sdb_plugin
->current_pkg_scanned
= g_async_queue_pop (sdb_plugin
->global_scan_aqueue
);
1956 if (sdb_plugin
->current_pkg_scanned
== NULL
)
1959 DEBUG_PRINT ("==%d==>\n"
1960 "begin %s", process_id
, sdb_plugin
->current_pkg_scanned
->package_name
);
1961 gtk_widget_show (sdb_plugin
->progress_bar_system
);
1965 on_isymbol_manager_sys_single_scan_end (SymbolDBEngine
*dbe
, SymbolDBPlugin
*sdb_plugin
)
1967 PackageScanData
*pkg_scan
;
1969 /* ignore signals when scan-end has already been received */
1970 if (sdb_plugin
->current_pkg_scanned
== NULL
)
1975 pkg_scan
= sdb_plugin
->current_pkg_scanned
;
1976 pkg_scan
->files_done
++;
1978 gtk_widget_show (sdb_plugin
->progress_bar_system
);
1979 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (sdb_plugin
->progress_bar_system
),
1980 (gdouble
)pkg_scan
->files_done
/
1981 (gdouble
)pkg_scan
->files_length
);
1985 on_isymbol_manager_sys_scan_end (SymbolDBEngine
*dbe
,
1987 SymbolDBPlugin
*sdb_plugin
)
1989 IAnjutaSymbolManager
*sm
;
1990 PackageScanData
*pkg_scan
;
1992 g_return_if_fail (sdb_plugin
->current_pkg_scanned
!= NULL
);
1994 DEBUG_PRINT ("<==%d==\nscan end %s. Queue now is %d",
1996 sdb_plugin
->current_pkg_scanned
->package_name
,
1997 g_async_queue_length (sdb_plugin
->global_scan_aqueue
));
1999 sm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
,
2000 IAnjutaSymbolManager
, NULL
);
2002 g_signal_emit_by_name (sm
, "sys-scan-end", process_id
);
2004 pkg_scan
= sdb_plugin
->current_pkg_scanned
;
2005 g_free (pkg_scan
->package_name
);
2006 g_free (pkg_scan
->package_version
);
2009 sdb_plugin
->current_pkg_scanned
= NULL
;
2011 gtk_widget_hide (sdb_plugin
->progress_bar_system
);
2015 symbol_db_activate (AnjutaPlugin
*plugin
)
2017 IAnjutaProjectManager
*pm
;
2018 SymbolDBPlugin
*sdb_plugin
;
2019 gchar
*anjuta_cache_path
;
2021 GtkWidget
*view
, *label
;
2022 GError
*error
= NULL
;
2024 DEBUG_PRINT ("SymbolDBPlugin: Activating SymbolDBPlugin plugin …");
2026 /* Initialize gda library. */
2029 register_stock_icons (plugin
);
2031 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
2032 sdb_plugin
->ui
= anjuta_shell_get_ui (plugin
->shell
, NULL
);
2033 sdb_plugin
->project_opened
= NULL
;
2035 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
,
2036 IAnjutaProjectManager
, NULL
);
2040 /* leaving here this code. Maybe in future ctags-devs will include our patches
2041 * upstream and this can be useful again.
2043 if (ctags_path
== NULL
)
2045 DEBUG_PRINT ("ctags is not in preferences. Trying a default one %s",
2047 ctags_path
= g_strdup (CTAGS_PATH
);
2050 sdb_plugin
->buf_update_timeout_id
= 0;
2051 sdb_plugin
->need_symbols_update
= FALSE
;
2052 /* creates and start a new timer. */
2053 sdb_plugin
->update_timer
= g_timer_new ();
2055 /* these two arrays will maintain the same number of objects,
2056 * so that if you search, say on the first, an occurrence of a file,
2057 * you'll be able to get in O(1) the _index in the second array, where the
2058 * scan process ids are stored. This is true in the other way too.
2060 sdb_plugin
->buffer_update_files
= g_ptr_array_new_with_free_func (g_free
);
2061 sdb_plugin
->buffer_update_ids
= g_ptr_array_new ();
2062 sdb_plugin
->buffer_update_semaphore
= FALSE
;
2064 sdb_plugin
->is_offline_scanning
= FALSE
;
2065 sdb_plugin
->is_project_importing
= FALSE
;
2066 sdb_plugin
->is_project_updating
= FALSE
;
2067 sdb_plugin
->is_adding_element
= FALSE
;
2069 DEBUG_PRINT ("SymbolDBPlugin: Initializing engines with %s", ctags_path
);
2070 /* create SymbolDBEngine(s) */
2071 sdb_plugin
->sdbe_project
= symbol_db_engine_new (ctags_path
);
2072 if (sdb_plugin
->sdbe_project
== NULL
)
2074 g_critical ("sdbe_project == NULL");
2078 /* the globals one too */
2079 sdb_plugin
->sdbe_globals
= symbol_db_engine_new (ctags_path
);
2080 if (sdb_plugin
->sdbe_globals
== NULL
)
2082 g_critical ("sdbe_globals == NULL");
2086 g_free (ctags_path
);
2089 anjuta_cache_path
= anjuta_util_get_user_cache_file_path (".", NULL
);
2090 if (symbol_db_engine_open_db (sdb_plugin
->sdbe_globals
,
2093 &error
) == DB_OPEN_STATUS_FATAL
)
2095 g_error ("Opening global project under %s: %s", anjuta_cache_path
, error
->message
);
2098 g_free (anjuta_cache_path
);
2100 sdb_plugin
->global_scan_aqueue
= g_async_queue_new ();
2101 /* create the object that'll manage the globals population */
2102 sdb_plugin
->sdbs
= symbol_db_system_new (sdb_plugin
, sdb_plugin
->sdbe_globals
);
2104 g_signal_connect (G_OBJECT (sdb_plugin
->sdbs
), "scan-package-start",
2105 G_CALLBACK (on_system_scan_package_start
), plugin
);
2107 g_signal_connect (G_OBJECT (sdb_plugin
->sdbs
), "scan-package-end",
2108 G_CALLBACK (on_system_scan_package_end
), plugin
);
2110 g_signal_connect (G_OBJECT (sdb_plugin
->sdbs
), "single-file-scan-end",
2111 G_CALLBACK (on_system_single_file_scan_end
), plugin
);
2113 /* beign necessary to listen to many scan-end signals, we'll build up a method
2114 * to manage them with just one signal connection
2116 sdb_plugin
->proc_id_tree
= g_tree_new_full ((GCompareDataFunc
)&symbol_db_gtree_compare_func
,
2121 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_project
), "scan-end",
2122 G_CALLBACK (on_scan_end_manager
), sdb_plugin
);
2124 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_project
), "scan-end",
2125 G_CALLBACK (on_isymbol_manager_prj_scan_end
), sdb_plugin
);
2127 /* connect signals for interface to receive them */
2128 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_globals
), "single-file-scan-end",
2129 G_CALLBACK (on_isymbol_manager_sys_single_scan_end
), sdb_plugin
);
2131 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_globals
), "scan-end",
2132 G_CALLBACK (on_isymbol_manager_sys_scan_end
), sdb_plugin
);
2134 g_signal_connect (G_OBJECT (sdb_plugin
->sdbe_globals
), "scan-begin",
2135 G_CALLBACK (on_isymbol_manager_sys_scan_begin
), sdb_plugin
);
2139 /* connect signals for project loading and element adding */
2140 g_signal_connect (G_OBJECT (pm
), "element-added",
2141 G_CALLBACK (on_project_element_added
), sdb_plugin
);
2142 g_signal_connect (G_OBJECT (pm
), "element-removed",
2143 G_CALLBACK (on_project_element_removed
), sdb_plugin
);
2144 g_signal_connect (G_OBJECT (pm
), "project-loaded",
2145 G_CALLBACK (on_project_loaded
), sdb_plugin
);
2147 /* Create widgets */
2148 sdb_plugin
->dbv_main
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 5);
2149 sdb_plugin
->dbv_notebook
= gtk_notebook_new();
2150 gtk_notebook_set_show_border (GTK_NOTEBOOK (sdb_plugin
->dbv_notebook
), FALSE
);
2151 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (sdb_plugin
->dbv_notebook
), FALSE
);
2152 sdb_plugin
->dbv_hbox
= gtk_box_new (GTK_ORIENTATION_HORIZONTAL
, 1);
2154 label
= gtk_label_new (_("Symbols"));
2155 gtk_misc_set_alignment (GTK_MISC (label
), 0.0f
, 0.5f
);
2156 gtk_box_pack_start (GTK_BOX(sdb_plugin
->dbv_hbox
),
2157 gtk_image_new_from_stock ("symbol-db-plugin-icon",
2158 GTK_ICON_SIZE_MENU
),
2160 gtk_box_pack_start (GTK_BOX(sdb_plugin
->dbv_hbox
), label
,
2163 sdb_plugin
->tabber
= anjuta_tabber_new (GTK_NOTEBOOK (sdb_plugin
->dbv_notebook
));
2164 label
= gtk_label_new (_("File"));
2165 gtk_label_set_ellipsize (GTK_LABEL (label
),
2166 PANGO_ELLIPSIZE_END
);
2167 anjuta_tabber_add_tab (ANJUTA_TABBER (sdb_plugin
->tabber
),
2169 label
= gtk_label_new (_("Project"));
2170 gtk_label_set_ellipsize (GTK_LABEL (label
),
2171 PANGO_ELLIPSIZE_END
);
2172 anjuta_tabber_add_tab (ANJUTA_TABBER (sdb_plugin
->tabber
),
2174 label
= gtk_label_new (_("Search"));
2175 gtk_label_set_ellipsize (GTK_LABEL (label
),
2176 PANGO_ELLIPSIZE_END
);
2177 anjuta_tabber_add_tab (ANJUTA_TABBER (sdb_plugin
->tabber
),
2179 gtk_box_pack_end (GTK_BOX(sdb_plugin
->dbv_hbox
), sdb_plugin
->tabber
,
2182 gtk_widget_show_all (sdb_plugin
->dbv_hbox
);
2184 sdb_plugin
->progress_bar_project
= gtk_progress_bar_new();
2185 gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR(sdb_plugin
->progress_bar_project
),
2186 PANGO_ELLIPSIZE_MIDDLE
);
2187 g_object_ref (sdb_plugin
->progress_bar_project
);
2189 sdb_plugin
->progress_bar_system
= gtk_progress_bar_new();
2190 gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR(sdb_plugin
->progress_bar_system
),
2191 PANGO_ELLIPSIZE_MIDDLE
);
2192 g_object_ref (sdb_plugin
->progress_bar_system
);
2194 gtk_box_pack_start (GTK_BOX (sdb_plugin
->dbv_main
), sdb_plugin
->dbv_notebook
,
2196 gtk_box_pack_start (GTK_BOX (sdb_plugin
->dbv_main
), sdb_plugin
->progress_bar_project
,
2198 gtk_box_pack_start (GTK_BOX (sdb_plugin
->dbv_main
), sdb_plugin
->progress_bar_system
,
2200 gtk_widget_show_all (sdb_plugin
->dbv_main
);
2203 view
= symbol_db_view_new (SYMBOL_DB_VIEW_FILE
, sdb_plugin
->sdbe_project
,
2205 gtk_notebook_append_page (GTK_NOTEBOOK (sdb_plugin
->dbv_notebook
),
2206 view
, gtk_label_new (_("Local")));
2207 sdb_plugin
->file_model
=
2208 gtk_tree_view_get_model (GTK_TREE_VIEW (gtk_bin_get_child (GTK_BIN(view
))));
2210 g_object_add_weak_pointer (G_OBJECT (sdb_plugin
->file_model
),
2211 (gpointer
)&sdb_plugin
->file_model
);
2213 /* Global symbols */
2214 view
= symbol_db_view_new (SYMBOL_DB_VIEW_PROJECT
,
2215 sdb_plugin
->sdbe_project
,
2217 gtk_notebook_append_page (GTK_NOTEBOOK (sdb_plugin
->dbv_notebook
),
2218 view
, gtk_label_new (_("Global" )));
2220 /* Search symbols */
2221 view
= symbol_db_view_new (SYMBOL_DB_VIEW_SEARCH
,
2222 sdb_plugin
->sdbe_project
,
2224 sdb_plugin
->search_entry
= symbol_db_view_get_search_entry (view
);
2225 gtk_notebook_append_page (GTK_NOTEBOOK (sdb_plugin
->dbv_notebook
),
2226 view
, gtk_label_new (_("Search" )));
2228 gtk_widget_show_all (sdb_plugin
->dbv_notebook
);
2230 /* setting focus to the tree_view*/
2231 gtk_notebook_set_current_page (GTK_NOTEBOOK (sdb_plugin
->dbv_notebook
), 0);
2233 sdb_plugin
->editor_watch_id
=
2234 anjuta_plugin_add_watch (plugin
, IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT
,
2235 value_added_current_editor
,
2236 value_removed_current_editor
, NULL
);
2238 anjuta_shell_add_widget_custom (plugin
->shell
, sdb_plugin
->dbv_main
,
2239 "AnjutaSymbolDB", _("Symbols"),
2240 "symbol-db-plugin-icon",
2241 sdb_plugin
->dbv_hbox
,
2242 ANJUTA_SHELL_PLACEMENT_LEFT
, NULL
);
2244 /* Add action group */
2245 sdb_plugin
->popup_action_group
=
2246 anjuta_ui_add_action_group_entries (sdb_plugin
->ui
,
2247 "ActionGroupPopupSymbolDB",
2248 _("SymbolDb popup actions"),
2250 G_N_ELEMENTS (actions
),
2251 GETTEXT_PACKAGE
, FALSE
, plugin
);
2253 sdb_plugin
->menu_action_group
=
2254 anjuta_ui_add_action_group_entries (sdb_plugin
->ui
,
2255 "ActionGroupEditSearchSymbolDB",
2256 _("SymbolDb menu actions"),
2258 G_N_ELEMENTS (actions_search
),
2259 GETTEXT_PACKAGE
, FALSE
, plugin
);
2262 sdb_plugin
->merge_id
=
2263 anjuta_ui_merge (sdb_plugin
->ui
, UI_FILE
);
2265 /* set up project directory watch */
2266 sdb_plugin
->root_watch_id
= anjuta_plugin_add_watch (plugin
,
2267 IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI
,
2268 on_project_root_added
,
2269 on_project_root_removed
, NULL
);
2271 /* Determine session state */
2272 g_signal_connect (plugin
->shell
, "load-session",
2273 G_CALLBACK (on_session_load
), plugin
);
2275 g_signal_connect (plugin
->shell
, "save-session",
2276 G_CALLBACK (on_session_save
), plugin
);
2278 /* be sure to hide the progress bars in case no project has been opened. */
2279 gtk_widget_hide (sdb_plugin
->progress_bar_project
);
2280 gtk_widget_hide (sdb_plugin
->progress_bar_system
);
2282 static IAnjutaSymbolField search_fields
[] =
2284 IANJUTA_SYMBOL_FIELD_KIND
,
2285 IANJUTA_SYMBOL_FIELD_FILE_PATH
,
2286 IANJUTA_SYMBOL_FIELD_FILE_POS
2288 sdb_plugin
->search_query
=
2289 ianjuta_symbol_manager_create_query (IANJUTA_SYMBOL_MANAGER (sdb_plugin
),
2290 IANJUTA_SYMBOL_QUERY_SEARCH
,
2291 IANJUTA_SYMBOL_QUERY_DB_PROJECT
,
2293 ianjuta_symbol_query_set_fields (sdb_plugin
->search_query
,
2294 G_N_ELEMENTS (search_fields
),
2295 search_fields
, NULL
);
2300 symbol_db_deactivate (AnjutaPlugin
*plugin
)
2302 SymbolDBPlugin
*sdb_plugin
;
2303 IAnjutaProjectManager
*pm
;
2305 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (plugin
);
2307 pm
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
,
2308 IAnjutaProjectManager
, NULL
);
2312 DEBUG_PRINT ("%s", "SymbolDBPlugin: Dectivating SymbolDBPlugin plugin …");
2315 gtk_ui_manager_remove_ui (GTK_UI_MANAGER (sdb_plugin
->ui
),
2316 sdb_plugin
->merge_id
);
2317 gtk_ui_manager_remove_action_group (GTK_UI_MANAGER (sdb_plugin
->ui
),
2318 sdb_plugin
->popup_action_group
);
2319 gtk_ui_manager_remove_action_group (GTK_UI_MANAGER (sdb_plugin
->ui
),
2320 sdb_plugin
->menu_action_group
);
2321 g_signal_handlers_disconnect_by_func (G_OBJECT (plugin
->shell
),
2325 g_signal_handlers_disconnect_by_func (G_OBJECT (plugin
->shell
),
2329 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->sdbs
),
2330 on_system_scan_package_start
,
2333 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->sdbs
),
2334 on_system_scan_package_end
,
2337 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->sdbs
),
2338 on_system_single_file_scan_end
,
2341 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->sdbs
),
2342 on_scan_end_manager
,
2345 /* disconnect the interface ones */
2346 /* connect signals for interface to receive them */
2347 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->sdbe_globals
),
2348 G_CALLBACK (on_isymbol_manager_sys_scan_end
), plugin
);
2350 g_signal_handlers_disconnect_by_func (G_OBJECT (sdb_plugin
->sdbe_project
),
2351 G_CALLBACK (on_isymbol_manager_prj_scan_end
), plugin
);
2353 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
2354 G_CALLBACK (on_project_element_added
), plugin
);
2356 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
2357 G_CALLBACK (on_project_element_removed
), plugin
);
2359 g_signal_handlers_disconnect_by_func (G_OBJECT (pm
),
2360 G_CALLBACK (on_project_loaded
), plugin
);
2362 if (sdb_plugin
->buf_update_timeout_id
)
2364 g_source_remove (sdb_plugin
->buf_update_timeout_id
);
2365 sdb_plugin
->buf_update_timeout_id
= 0;
2367 if (sdb_plugin
->update_timer
)
2369 g_timer_destroy (sdb_plugin
->update_timer
);
2370 sdb_plugin
->update_timer
= NULL
;
2373 /* destroy search query */
2374 if (sdb_plugin
->search_query
)
2376 g_object_unref (sdb_plugin
->search_query
);
2378 sdb_plugin
->search_query
= NULL
;
2380 /* destroy objects */
2381 if (sdb_plugin
->sdbe_project
)
2383 DEBUG_PRINT ("Destroying project engine object. ");
2384 g_object_unref (sdb_plugin
->sdbe_project
);
2386 sdb_plugin
->sdbe_project
= NULL
;
2388 PackageScanData
*pkg_scan_data
;
2389 while ((pkg_scan_data
= g_async_queue_try_pop (sdb_plugin
->global_scan_aqueue
)) != NULL
)
2391 g_free (pkg_scan_data
->package_name
);
2392 g_free (pkg_scan_data
->package_version
);
2393 g_free (pkg_scan_data
);
2396 g_async_queue_unref (sdb_plugin
->global_scan_aqueue
);
2397 sdb_plugin
->global_scan_aqueue
= NULL
;
2399 /* this must be done *before* destroying sdbe_globals */
2400 g_object_unref (sdb_plugin
->sdbs
);
2401 sdb_plugin
->sdbs
= NULL
;
2403 g_free (sdb_plugin
->current_scanned_package
);
2404 sdb_plugin
->current_scanned_package
= NULL
;
2406 DEBUG_PRINT ("Destroying global engine object. ");
2407 g_object_unref (sdb_plugin
->sdbe_globals
);
2408 sdb_plugin
->sdbe_globals
= NULL
;
2410 g_free (sdb_plugin
->project_opened
);
2411 sdb_plugin
->project_opened
= NULL
;
2413 if (sdb_plugin
->buffer_update_files
)
2415 g_ptr_array_unref (sdb_plugin
->buffer_update_files
);
2416 sdb_plugin
->buffer_update_files
= NULL
;
2419 if (sdb_plugin
->buffer_update_ids
)
2421 g_ptr_array_unref (sdb_plugin
->buffer_update_ids
);
2422 sdb_plugin
->buffer_update_ids
= NULL
;
2425 /* Ensure all editor cached info are released */
2426 if (sdb_plugin
->editor_connected
)
2428 g_hash_table_foreach (sdb_plugin
->editor_connected
,
2429 on_editor_foreach_disconnect
, plugin
);
2430 g_hash_table_destroy (sdb_plugin
->editor_connected
);
2431 sdb_plugin
->editor_connected
= NULL
;
2432 g_hash_table_destroy (sdb_plugin
->editors
);
2433 sdb_plugin
->editors
= NULL
;
2437 g_tree_destroy (sdb_plugin
->proc_id_tree
);
2439 /* Remove watches */
2440 anjuta_plugin_remove_watch (plugin
, sdb_plugin
->root_watch_id
, FALSE
);
2441 anjuta_plugin_remove_watch (plugin
, sdb_plugin
->editor_watch_id
, TRUE
);
2444 anjuta_ui_unmerge (sdb_plugin
->ui
, sdb_plugin
->merge_id
);
2446 /* Remove widgets: Widgets will be destroyed when dbv_main is removed */
2447 anjuta_shell_remove_widget (plugin
->shell
, sdb_plugin
->dbv_main
, NULL
);
2449 sdb_plugin
->root_watch_id
= 0;
2450 sdb_plugin
->editor_watch_id
= 0;
2451 sdb_plugin
->merge_id
= 0;
2452 sdb_plugin
->dbv_notebook
= NULL
;
2453 sdb_plugin
->progress_bar_project
= NULL
;
2454 sdb_plugin
->progress_bar_system
= NULL
;
2459 symbol_db_finalize (GObject
*obj
)
2461 DEBUG_PRINT ("Symbol-DB finalize");
2462 /* Finalization codes here */
2463 G_OBJECT_CLASS (parent_class
)->finalize (obj
);
2467 symbol_db_dispose (GObject
*obj
)
2469 SymbolDBPlugin
*plugin
= (SymbolDBPlugin
*)obj
;
2470 DEBUG_PRINT ("Symbol-DB dispose");
2471 /* Disposition codes */
2472 if (plugin
->settings
!= NULL
)
2474 g_object_unref (plugin
->settings
);
2475 plugin
->settings
= NULL
;
2478 if (plugin
->file_model
!= NULL
)
2480 g_object_remove_weak_pointer (G_OBJECT (plugin
->file_model
),
2481 (gpointer
)&plugin
->file_model
);
2482 plugin
->file_model
= NULL
;
2485 G_OBJECT_CLASS (parent_class
)->dispose (obj
);
2489 symbol_db_instance_init (GObject
*obj
)
2491 SymbolDBPlugin
*plugin
= (SymbolDBPlugin
*)obj
;
2493 plugin
->files_count_project_done
= 0;
2494 plugin
->files_count_project
= 0;
2496 plugin
->files_count_system_done
= 0;
2497 plugin
->files_count_system
= 0;
2498 plugin
->current_scanned_package
= NULL
;
2499 plugin
->settings
= g_settings_new (PREF_SCHEMA
);
2503 symbol_db_class_init (GObjectClass
*klass
)
2505 AnjutaPluginClass
*plugin_class
= ANJUTA_PLUGIN_CLASS (klass
);
2507 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
2508 parent_class
= g_type_class_peek_parent (klass
);
2510 plugin_class
->activate
= symbol_db_activate
;
2511 plugin_class
->deactivate
= symbol_db_deactivate
;
2512 klass
->finalize
= symbol_db_finalize
;
2513 klass
->dispose
= symbol_db_dispose
;
2515 signals
[PROJECT_IMPORT_END
]
2516 = g_signal_new ("project-import-end",
2517 G_OBJECT_CLASS_TYPE (object_class
),
2519 G_STRUCT_OFFSET (SymbolDBPluginClass
, project_import_end
),
2521 g_cclosure_marshal_VOID__VOID
, G_TYPE_NONE
, 0);
2523 signals
[GLOBALS_IMPORT_END
]
2524 = g_signal_new ("globals-import-end",
2525 G_OBJECT_CLASS_TYPE (object_class
),
2527 G_STRUCT_OFFSET (SymbolDBPluginClass
, globals_import_end
),
2529 g_cclosure_marshal_VOID__VOID
, G_TYPE_NONE
, 0);
2533 on_prefs_buffer_update_toggled (GtkToggleButton
* button
,
2536 SymbolDBPlugin
*sdb_plugin
;
2539 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (user_data
);
2541 sensitive
= gtk_toggle_button_get_active (button
);
2543 DEBUG_PRINT ("on_prefs_buffer_update_toggled () %d", sensitive
);
2545 if (sensitive
== FALSE
)
2547 if (sdb_plugin
->buf_update_timeout_id
)
2548 g_source_remove (sdb_plugin
->buf_update_timeout_id
);
2549 sdb_plugin
->buf_update_timeout_id
= 0;
2553 if (sdb_plugin
->buf_update_timeout_id
== 0)
2554 sdb_plugin
->buf_update_timeout_id
=
2555 g_timeout_add_seconds (TIMEOUT_INTERVAL_SYMBOLS_UPDATE
,
2556 on_editor_buffer_symbols_update_timeout
,
2562 ipreferences_merge(IAnjutaPreferences
* ipref
, AnjutaPreferences
* prefs
, GError
** e
)
2564 DEBUG_PRINT ("%s", "SymbolDB: ipreferences_merge");
2565 SymbolDBPlugin
*sdb_plugin
;
2566 GtkWidget
*buf_up_widget
;
2567 GError
* error
= NULL
;
2569 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (ipref
);
2571 if (sdb_plugin
->prefs_bxml
== NULL
)
2573 /* Create the preferences page */
2574 sdb_plugin
->prefs_bxml
= gtk_builder_new ();
2575 if (!gtk_builder_add_from_file (sdb_plugin
->prefs_bxml
, BUILDER_FILE
, &error
))
2577 g_warning ("Couldn't load builder file: %s", error
->message
);
2578 g_error_free(error
);
2582 anjuta_preferences_add_from_builder (prefs
,
2583 sdb_plugin
->prefs_bxml
,
2584 sdb_plugin
->settings
,
2586 _("Symbol Database"),
2589 buf_up_widget
= GTK_WIDGET (gtk_builder_get_object (sdb_plugin
->prefs_bxml
,
2590 PREFS_BUFFER_UPDATE
));
2592 g_signal_connect (buf_up_widget
, "toggled",
2593 G_CALLBACK (on_prefs_buffer_update_toggled
),
2598 ipreferences_unmerge(IAnjutaPreferences
* ipref
, AnjutaPreferences
* prefs
, GError
** e
)
2600 SymbolDBPlugin
*sdb_plugin
;
2602 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (ipref
);
2604 anjuta_preferences_remove_page(prefs
, _("Symbol Database"));
2605 g_object_unref (sdb_plugin
->prefs_bxml
);
2606 sdb_plugin
->prefs_bxml
= NULL
;
2610 ipreferences_iface_init(IAnjutaPreferencesIface
* iface
)
2612 DEBUG_PRINT ("%s", "SymbolDB: ipreferences_iface_init");
2613 iface
->merge
= ipreferences_merge
;
2614 iface
->unmerge
= ipreferences_unmerge
;
2617 /* IAnjutaSymbolManager implementation */
2618 static IAnjutaSymbolQuery
*
2619 isymbol_manager_create_query (IAnjutaSymbolManager
*isymbol_manager
,
2620 IAnjutaSymbolQueryName query_name
,
2621 IAnjutaSymbolQueryDb db
,
2624 SymbolDBPlugin
*sdb_plugin
;
2625 SymbolDBQuery
*query
;
2627 g_return_val_if_fail (isymbol_manager
!= NULL
, NULL
);
2629 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager
);
2631 query
= symbol_db_query_new (sdb_plugin
->sdbe_globals
,
2632 sdb_plugin
->sdbe_project
,
2635 db
== IANJUTA_SYMBOL_QUERY_DB_PROJECT
?
2636 NULL
: /* FIXME */ NULL
);
2637 return IANJUTA_SYMBOL_QUERY (query
);
2641 isymbol_manager_add_package (IAnjutaSymbolManager
*isymbol_manager
,
2642 const gchar
* pkg_name
,
2643 const gchar
* pkg_version
,
2647 SymbolDBPlugin
*sdb_plugin
;
2648 IAnjutaLanguage
*lang_manager
;
2649 GPtrArray
*files_array
;
2650 PackageScanData
*pkg_scan_data
;
2653 g_return_val_if_fail (isymbol_manager
!= NULL
, FALSE
);
2658 while (node
!= NULL
)
2663 /* FIXME: pkg_version comes with \n at the end. This should be avoided */
2664 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager
);
2665 lang_manager
= anjuta_shell_get_interface (ANJUTA_PLUGIN (sdb_plugin
)->shell
, IAnjutaLanguage
,
2668 if (symbol_db_engine_add_new_project (sdb_plugin
->sdbe_globals
, NULL
, pkg_name
,
2669 pkg_version
) == FALSE
)
2674 files_array
= anjuta_util_convert_string_list_to_array (files
);
2676 pkg_scan_data
= g_new0 (PackageScanData
, 1);
2678 g_async_queue_push (sdb_plugin
->global_scan_aqueue
, pkg_scan_data
);
2679 pkg_scan_data
->files_length
= g_list_length (files
);
2680 pkg_scan_data
->package_name
= g_strdup (pkg_name
);
2681 pkg_scan_data
->package_version
= g_strdup (pkg_version
);
2683 pkg_scan_data
->proc_id
= symbol_db_engine_add_new_files_async (sdb_plugin
->sdbe_globals
, lang_manager
,
2684 pkg_name
, pkg_version
, files_array
);
2686 g_ptr_array_unref (files_array
);
2691 /* FIXME: do this thread safe */
2693 isymbol_manager_activate_package (IAnjutaSymbolManager
*isymbol_manager
,
2694 const gchar
*pkg_name
,
2695 const gchar
*pkg_version
,
2698 SymbolDBPlugin
*sdb_plugin
;
2700 g_return_val_if_fail (isymbol_manager
!= NULL
, FALSE
);
2702 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager
);
2704 if (symbol_db_engine_project_exists (sdb_plugin
->sdbe_globals
, pkg_name
,
2705 pkg_version
) == TRUE
)
2707 /* FIXME: Activate package in database */
2708 DEBUG_PRINT ("STUB");
2712 /* user should add a package before activating it. */
2717 isymbol_manager_deactivate_package (IAnjutaSymbolManager
*isymbol_manager
,
2718 const gchar
*pkg_name
,
2719 const gchar
*pkg_version
,
2722 SymbolDBPlugin
*sdb_plugin
;
2724 g_return_if_fail (isymbol_manager
!= NULL
);
2726 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager
);
2728 if (symbol_db_engine_project_exists (sdb_plugin
->sdbe_globals
, pkg_name
,
2729 pkg_version
) == TRUE
)
2731 DEBUG_PRINT ("STUB");
2732 /* FIXME: deactivate package in database */
2737 isymbol_manager_deactivate_all (IAnjutaSymbolManager
*isymbol_manager
,
2741 SymbolDBPlugin
*sdb_plugin
;
2743 g_return_if_fail (isymbol_manager
!= NULL
);
2745 sdb_plugin
= ANJUTA_PLUGIN_SYMBOL_DB (isymbol_manager
);
2747 /* FIXME: deactivate all packages in database */
2748 DEBUG_PRINT ("STUB");
2752 isymbol_manager_iface_init (IAnjutaSymbolManagerIface
*iface
)
2754 iface
->create_query
= isymbol_manager_create_query
;
2755 iface
->activate_package
= isymbol_manager_activate_package
;
2756 iface
->deactivate_package
= isymbol_manager_deactivate_package
;
2757 iface
->deactivate_all
= isymbol_manager_deactivate_all
;
2758 iface
->add_package
= isymbol_manager_add_package
;
2761 ANJUTA_PLUGIN_BEGIN (SymbolDBPlugin
, symbol_db
);
2762 ANJUTA_PLUGIN_ADD_INTERFACE (isymbol_manager
, IANJUTA_TYPE_SYMBOL_MANAGER
);
2763 ANJUTA_PLUGIN_ADD_INTERFACE(ipreferences
, IANJUTA_TYPE_PREFERENCES
);
2766 ANJUTA_SIMPLE_PLUGIN (SymbolDBPlugin
, symbol_db
);