1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Johannes Schmid 2011 <jhs@Obelix>
6 * anjuta is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * anjuta is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "cpp-packages.h"
23 #include <libanjuta/interfaces/ianjuta-project-manager.h>
24 #include <libanjuta/interfaces/ianjuta-symbol-manager.h>
25 #include <libanjuta/anjuta-pkg-config.h>
26 #include <libanjuta/anjuta-pkg-scanner.h>
27 #include <libanjuta/anjuta-debug.h>
28 #include <libanjuta/anjuta-preferences.h>
30 #define PREF_PROJECT_PACKAGES "load-project-packages"
31 #define PREF_USER_PACKAGES "user-packages"
32 #define PREF_LIBC "load-libc"
34 #define PROJECT_LOADED "__cpp_packages_loaded"
35 #define USER_LOADED "__cpp_user_packages_loaded"
38 * Standard files of the C library (according to
39 * https://secure.wikimedia.org/wikipedia/en/wiki/C_standard_library)
41 const gchar
* libc_files
[] =
71 * Standard location of libc on UNIX systems
73 #define LIBC_LOCATION "/usr/include"
74 #define LIBC_VERSION "C99"
90 pkg_data_compare (gpointer data1
, gpointer pkg2
)
92 PackageData
* pkg_data1
= data1
;
94 return strcmp (pkg_data1
->pkg
, (const gchar
*) pkg2
);
98 pkg_data_free (PackageData
* data
)
101 g_free (data
->version
);
106 G_DEFINE_TYPE (CppPackages
, cpp_packages
, G_TYPE_OBJECT
);
109 cpp_packages_activate_package (IAnjutaSymbolManager
* sm
, const gchar
* pkg
,
110 GList
** packages_to_add
)
112 gchar
* name
= g_strdup (pkg
);
116 /* Clean package name */
117 for (c
= name
; *c
!= '\0'; c
++)
119 if (g_ascii_isspace (*c
))
126 version
= anjuta_pkg_config_get_version (name
);
130 return *packages_to_add
;
133 /* Only query each package once */
134 if (g_list_find_custom (*packages_to_add
,
135 name
, (GCompareFunc
) pkg_data_compare
))
136 return *packages_to_add
;
137 if (!ianjuta_symbol_manager_activate_package (sm
, name
, version
, NULL
))
139 GList
* deps
= anjuta_pkg_config_list_dependencies (name
, NULL
);
141 PackageData
* data
= g_new0 (PackageData
, 1);
142 for (dep
= deps
; dep
!= NULL
; dep
= g_list_next (dep
))
144 cpp_packages_activate_package (sm
, dep
->data
, packages_to_add
);
146 anjuta_util_glist_strings_free (deps
);
147 data
->pkg
= g_strdup (name
);
148 data
->version
= g_strdup (version
);
149 *packages_to_add
= g_list_prepend (*packages_to_add
,
153 return *packages_to_add
;
157 on_package_ready (AnjutaCommand
* command
,
159 IAnjutaSymbolManager
* sm
)
161 AnjutaPkgScanner
* scanner
= ANJUTA_PKG_SCANNER (command
);
162 if (g_list_length (anjuta_pkg_scanner_get_files (scanner
)))
164 ianjuta_symbol_manager_add_package (sm
,
165 anjuta_pkg_scanner_get_package (scanner
),
166 anjuta_pkg_scanner_get_version (scanner
),
167 anjuta_pkg_scanner_get_files (scanner
),
173 on_queue_finished (AnjutaCommandQueue
* queue
, CppPackages
* packages
)
175 g_object_unref (queue
);
176 packages
->loading
= FALSE
;
177 g_object_unref (packages
);
181 cpp_packages_activate_libc (CppPackages
* packages
)
183 IAnjutaSymbolManager
* sm
=
184 anjuta_shell_get_interface (anjuta_plugin_get_shell (ANJUTA_PLUGIN(packages
->plugin
)),
185 IAnjutaSymbolManager
, NULL
);
187 if (!ianjuta_symbol_manager_activate_package (sm
, LIBC
, LIBC_VERSION
, NULL
))
189 /* Create file list*/
192 for (file
= libc_files
; *file
!= NULL
; file
++)
194 gchar
* real_file
= g_build_filename (LIBC_LOCATION
, *file
, NULL
);
195 if (g_file_test (real_file
, G_FILE_TEST_EXISTS
))
196 files
= g_list_append (files
, real_file
);
202 ianjuta_symbol_manager_add_package (sm
,
207 anjuta_util_glist_strings_free (files
);
212 on_load_libc (GSettings
* settings
,
214 CppPackages
* packages
)
217 g_settings_get_boolean (ANJUTA_PLUGIN_CPP_JAVA(packages
->plugin
)->settings
,
221 cpp_packages_activate_libc (packages
);
225 IAnjutaSymbolManager
* sm
=
226 anjuta_shell_get_interface (anjuta_plugin_get_shell (ANJUTA_PLUGIN(packages
->plugin
)),
227 IAnjutaSymbolManager
, NULL
);
228 ianjuta_symbol_manager_deactivate_package (sm
, LIBC
, LIBC_VERSION
, NULL
);
233 cpp_packages_load_real (CppPackages
* packages
, GError
* error
, IAnjutaProjectManager
* pm
)
235 IAnjutaSymbolManager
* sm
=
236 anjuta_shell_get_interface (anjuta_plugin_get_shell (ANJUTA_PLUGIN(packages
->plugin
)),
237 IAnjutaSymbolManager
, NULL
);
240 GList
* packages_to_add
= NULL
;
245 ianjuta_symbol_manager_deactivate_all (sm
, NULL
);
246 pkgs
= ianjuta_project_manager_get_packages (pm
, NULL
);
247 for (pkg
= pkgs
; pkg
!= NULL
; pkg
= g_list_next (pkg
))
249 cpp_packages_activate_package (sm
, pkg
->data
, &packages_to_add
);
254 packages
->loading
= TRUE
;
255 packages
->queue
= anjuta_command_queue_new (ANJUTA_COMMAND_QUEUE_EXECUTE_MANUAL
);
256 for (pkg
= packages_to_add
; pkg
!= NULL
; pkg
= g_list_next (pkg
))
258 PackageData
* pkg_data
= pkg
->data
;
259 AnjutaCommand
* command
=
260 anjuta_pkg_scanner_new (pkg_data
->pkg
, pkg_data
->version
);
261 g_signal_connect (command
, "command-finished",
262 G_CALLBACK (on_package_ready
), sm
);
263 anjuta_command_queue_push (packages
->queue
, command
);
265 g_list_foreach (packages_to_add
, (GFunc
) pkg_data_free
, NULL
);
266 g_list_free (packages_to_add
);
268 g_signal_connect (packages
->queue
, "finished", G_CALLBACK (on_queue_finished
), packages
);
269 /* Make sure the pointer is valid when the queue finishes */
270 g_object_ref (packages
);
271 anjuta_command_queue_start (packages
->queue
);
276 cpp_packages_load_user (CppPackages
* packages
, gboolean force
)
278 CppJavaPlugin
* plugin
= ANJUTA_PLUGIN_CPP_JAVA(packages
->plugin
);
279 AnjutaShell
* shell
= anjuta_plugin_get_shell (ANJUTA_PLUGIN (plugin
));
280 IAnjutaSymbolManager
* sm
=
281 anjuta_shell_get_interface (shell
, IAnjutaSymbolManager
, NULL
);
282 gboolean loaded
= GPOINTER_TO_INT (g_object_get_data (G_OBJECT (shell
),
285 if (!loaded
|| force
)
287 gchar
* packages_str
= g_settings_get_string (plugin
->settings
,
289 GStrv pkgs
= g_strsplit (packages_str
, ";", -1);
291 GList
* packages_to_add
= NULL
;
294 ianjuta_symbol_manager_deactivate_all (sm
, NULL
);
296 for (package
= pkgs
; *package
!= NULL
; package
++)
298 cpp_packages_activate_package (sm
, *package
, &packages_to_add
);
301 g_free (packages_str
);
305 packages
->loading
= TRUE
;
306 packages
->queue
= anjuta_command_queue_new (ANJUTA_COMMAND_QUEUE_EXECUTE_MANUAL
);
307 for (pkg
= packages_to_add
; pkg
!= NULL
; pkg
= g_list_next (pkg
))
309 PackageData
* pkg_data
= pkg
->data
;
310 AnjutaCommand
* command
=
311 anjuta_pkg_scanner_new (pkg_data
->pkg
, pkg_data
->version
);
312 g_signal_connect (command
, "command-finished",
313 G_CALLBACK (on_package_ready
), sm
);
314 anjuta_command_queue_push (packages
->queue
, command
);
316 g_list_foreach (packages_to_add
, (GFunc
) pkg_data_free
, NULL
);
317 g_list_free (packages_to_add
);
319 g_object_set_data (G_OBJECT (shell
),
320 USER_LOADED
, GINT_TO_POINTER (TRUE
));
322 g_signal_connect (packages
->queue
, "finished", G_CALLBACK (on_queue_finished
), packages
);
323 /* Make sure the pointer is valid when the queue finishes */
324 g_object_ref (packages
);
325 anjuta_command_queue_start (packages
->queue
);
331 cpp_packages_idle_load_user (CppPackages
* packages
)
333 if (packages
->loading
)
336 cpp_packages_load (packages
, TRUE
);
337 packages
->idle_id
= 0;
338 g_object_unref (packages
);
344 cpp_packages_load (CppPackages
* packages
, gboolean force
)
346 CppJavaPlugin
* plugin
= ANJUTA_PLUGIN_CPP_JAVA(packages
->plugin
);
348 if (g_settings_get_boolean (plugin
->settings
,
349 PREF_PROJECT_PACKAGES
))
351 IAnjutaProjectManager
* pm
=
352 anjuta_shell_get_interface (packages
->plugin
->shell
, IAnjutaProjectManager
, NULL
);
353 IAnjutaProject
* project
;
355 g_signal_connect_swapped (pm
, "project-loaded", G_CALLBACK (cpp_packages_load_real
), packages
);
357 project
= ianjuta_project_manager_get_current_project (pm
, NULL
);
358 /* Only load the packages if necessary */
359 if (project
&& ianjuta_project_is_loaded (project
, NULL
))
361 gboolean loaded
= GPOINTER_TO_INT (g_object_get_data (G_OBJECT (project
),
363 if (!loaded
&& !packages
->loading
)
365 cpp_packages_load_real (packages
, NULL
, pm
);
366 g_object_set_data (G_OBJECT (project
), PROJECT_LOADED
, GINT_TO_POINTER (TRUE
));
372 if (packages
->loading
)
374 if (!packages
->idle_id
)
376 packages
->idle_id
= g_idle_add ((GSourceFunc
)cpp_packages_idle_load_user
, packages
);
377 g_object_ref (packages
);
383 cpp_packages_load_user (packages
, force
);
387 g_signal_connect (plugin
->settings
, "changed::PREF_LIBC",
388 G_CALLBACK (on_load_libc
), packages
);
389 on_load_libc (plugin
->settings
,
395 cpp_packages_init (CppPackages
*packages
)
397 packages
->loading
= FALSE
;
398 packages
->idle_id
= 0;
402 cpp_packages_finalize (GObject
* object
)
404 CppPackages
*packages
= CPP_PACKAGES (object
);
405 AnjutaShell
* shell
= packages
->plugin
->shell
;
409 IAnjutaProjectManager
* pm
=
410 anjuta_shell_get_interface (shell
, IAnjutaProjectManager
, NULL
);
413 g_signal_handlers_disconnect_by_func (pm
, cpp_packages_load_real
, packages
);
416 G_OBJECT_CLASS (cpp_packages_parent_class
)->finalize (object
);
420 cpp_packages_set_property (GObject
*object
, guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
422 CppPackages
* packages
;
424 g_return_if_fail (CPP_IS_PACKAGES (object
));
426 packages
= CPP_PACKAGES (object
);
431 packages
->plugin
= ANJUTA_PLUGIN (g_value_get_object (value
));
434 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
440 cpp_packages_get_property (GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
442 CppPackages
* packages
;
444 g_return_if_fail (CPP_IS_PACKAGES (object
));
446 packages
= CPP_PACKAGES (object
);
451 g_value_set_object (value
, G_OBJECT (packages
->plugin
));
454 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
460 cpp_packages_class_init (CppPackagesClass
*klass
)
462 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
464 object_class
->finalize
= cpp_packages_finalize
;
465 object_class
->set_property
= cpp_packages_set_property
;
466 object_class
->get_property
= cpp_packages_get_property
;
468 g_object_class_install_property (object_class
,
470 g_param_spec_object ("plugin",
474 G_PARAM_WRITABLE
| G_PARAM_CONSTRUCT_ONLY
));
478 cpp_packages_new (AnjutaPlugin
* plugin
)
481 g_object_new (CPP_TYPE_PACKAGES
,
484 return CPP_PACKAGES (object
);