1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
3 * anjuta-profile-manager.c
4 * Copyright (C) Naba Kumar <naba@gnome.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * SECTION:anjuta-profile-manager
23 * @short_description: Managers a stack of plugins profiles
24 * @see_also: #AnjutaPluginManager, #AnjutaProfile
25 * @stability: Unstable
26 * @include: libanjuta/anjuta-profile-manager.h
28 * Anjuta uses up to three profiles. A system profile which contains mandatory
29 * plugins which are never unloaded. A user profile is used when no project is
30 * loaded and a project profile when one is loaded.
31 * If a second project is loaded, it is loaded in another instance of Anjuta.
32 * When a project is closed, Anjuta goes back to the user profile.
34 * The profile manager can be in a frozen state where you can push or
35 * pop a profile from the stack without triggering a change of the profile.
40 #include <libanjuta/anjuta-debug.h>
41 #include <libanjuta/anjuta-marshal.h>
42 #include "anjuta-profile-manager.h"
58 struct _AnjutaProfileManagerPriv
60 AnjutaPluginManager
*plugin_manager
;
63 /* Pending queue. Profiles are queued until freeze count becomes 0 */
64 GList
*profiles_queue
;
66 /* Freeze count. Pending profiles are loaded when it reaches 0 */
70 static GObjectClass
* parent_class
= NULL
;
71 static guint profile_manager_signals
[LAST_SIGNAL
] = { 0 };
74 anjuta_profile_manager_init (AnjutaProfileManager
*object
)
76 object
->priv
= g_new0 (AnjutaProfileManagerPriv
, 1);
80 anjuta_profile_manager_finalize (GObject
*object
)
82 AnjutaProfileManagerPriv
*priv
= ANJUTA_PROFILE_MANAGER (object
)->priv
;
85 g_list_free_full (priv
->profiles
, g_object_unref
);
87 if (priv
->profiles_queue
)
88 g_list_free_full (priv
->profiles_queue
, g_object_unref
);
91 G_OBJECT_CLASS (parent_class
)->finalize (object
);
95 anjuta_profile_manager_set_property (GObject
*object
, guint prop_id
,
96 const GValue
*value
, GParamSpec
*pspec
)
98 AnjutaProfileManagerPriv
*priv
;
99 g_return_if_fail (ANJUTA_IS_PROFILE_MANAGER (object
));
100 priv
= ANJUTA_PROFILE_MANAGER (object
)->priv
;
104 case PROP_PLUGIN_MANAGER
:
105 g_return_if_fail (ANJUTA_IS_PLUGIN_MANAGER (g_value_get_object (value
)));
106 priv
->plugin_manager
= g_value_get_object (value
);
109 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
115 anjuta_profile_manager_get_property (GObject
*object
, guint prop_id
,
116 GValue
*value
, GParamSpec
*pspec
)
118 AnjutaProfileManagerPriv
*priv
;
119 g_return_if_fail (ANJUTA_IS_PROFILE_MANAGER (object
));
120 priv
= ANJUTA_PROFILE_MANAGER (object
)->priv
;
124 case PROP_PLUGIN_MANAGER
:
125 g_value_set_object (value
, priv
->plugin_manager
);
128 g_value_set_pointer (value
, priv
->profiles
);
131 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
137 anjuta_profile_manager_class_init (AnjutaProfileManagerClass
*klass
)
139 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
140 parent_class
= G_OBJECT_CLASS (g_type_class_peek_parent (klass
));
142 object_class
->finalize
= anjuta_profile_manager_finalize
;
143 object_class
->set_property
= anjuta_profile_manager_set_property
;
144 object_class
->get_property
= anjuta_profile_manager_get_property
;
146 g_object_class_install_property (object_class
,
148 g_param_spec_object ("plugin-manager",
150 "The plugin manager to use for profile plugins",
151 ANJUTA_TYPE_PLUGIN_MANAGER
,
156 * AnjutaProfileManager::profile-pushed:
157 * @profile_manager: a #AnjutaProfileManager object.
158 * @profile: the new #AnjutaProfile added.
160 * Emitted when a profile is added in the stack. If the profile manager is
161 * not frozen, the current profile will be unloaded and the new one
164 profile_manager_signals
[PROFILE_PUSHED
] =
165 g_signal_new ("profile-pushed",
166 G_OBJECT_CLASS_TYPE (klass
),
168 G_STRUCT_OFFSET (AnjutaProfileManagerClass
,
171 anjuta_cclosure_marshal_VOID__OBJECT
,
173 ANJUTA_TYPE_PROFILE
);
176 * AnjutaProfileManager::profile-popped:
177 * @profile_manager: a #AnjutaProfileManager object.
178 * @profile: the current removed #AnjutaProfile.
180 * Emitted when a profile is removed from the stack. If the profile manager
181 * is not frozen, the current profile will be unloaded and the previous one
184 profile_manager_signals
[PROFILE_POPPED
] =
185 g_signal_new ("profile-popped",
186 G_OBJECT_CLASS_TYPE (klass
),
188 G_STRUCT_OFFSET (AnjutaProfileManagerClass
,
191 anjuta_cclosure_marshal_VOID__OBJECT
,
193 ANJUTA_TYPE_PROFILE
);
198 anjuta_profile_manager_get_type (void)
200 static GType our_type
= 0;
204 static const GTypeInfo our_info
=
206 sizeof (AnjutaProfileManagerClass
), /* class_size */
207 (GBaseInitFunc
) NULL
, /* base_init */
208 (GBaseFinalizeFunc
) NULL
, /* base_finalize */
209 (GClassInitFunc
) anjuta_profile_manager_class_init
, /* class_init */
210 (GClassFinalizeFunc
) NULL
, /* class_finalize */
211 NULL
/* class_data */,
212 sizeof (AnjutaProfileManager
), /* instance_size */
214 (GInstanceInitFunc
) anjuta_profile_manager_init
, /* instance_init */
215 NULL
/* value_table */
218 our_type
= g_type_register_static (G_TYPE_OBJECT
, "AnjutaProfileManager",
226 * anjuta_profile_manager_new:
227 * @plugin_manager: the #AnjutaPluginManager used by all profiles.
229 * Create a new profile manager.
231 * Return value: the new #AnjutaProfileManager object.
233 AnjutaProfileManager
*
234 anjuta_profile_manager_new (AnjutaPluginManager
*plugin_manager
)
238 obj
= g_object_new (ANJUTA_TYPE_PROFILE_MANAGER
, "plugin-manager",
239 plugin_manager
, NULL
);
240 return ANJUTA_PROFILE_MANAGER (obj
);
244 anjuta_profile_manager_load_profiles (AnjutaProfileManager
*profile_manager
, GError
**error
)
246 AnjutaProfileManagerPriv
*priv
;
247 gboolean loaded
= FALSE
;
249 priv
= profile_manager
->priv
;
251 /* If there is no freeze load profile now */
252 while ((priv
->freeze_count
<= 0) && (priv
->profiles_queue
!= NULL
))
254 AnjutaProfile
*previous_profile
= NULL
;
257 /* We need to load each profile one by one because a "system" profile
258 * contains plugins which are never unloaded. */
260 previous_profile
= priv
->profiles
->data
;
261 node
= g_list_last (priv
->profiles_queue
);
262 priv
->profiles_queue
= g_list_remove_link (priv
->profiles_queue
, node
);
263 priv
->profiles
= g_list_concat (node
, priv
->profiles
);
265 /* Load profile. Note that loading a profile can trigger the load of
266 * additional profile. Typically loading the default profile will
267 * trigger the load of the last project profile. */
268 if (previous_profile
!= NULL
) anjuta_profile_unload (previous_profile
, NULL
);
269 loaded
= anjuta_profile_load (ANJUTA_PROFILE (node
->data
), error
);
276 anjuta_profile_manager_queue_profile (AnjutaProfileManager
*profile_manager
,
277 AnjutaProfile
*profile
,
280 AnjutaProfileManagerPriv
*priv
;
282 priv
= profile_manager
->priv
;
284 priv
->profiles_queue
= g_list_prepend (priv
->profiles_queue
, profile
);
286 /* If there is no freeze load profile now */
287 return anjuta_profile_manager_load_profiles (profile_manager
, error
);
291 * anjuta_profile_manager_push:
292 * @profile_manager: the #AnjutaProfileManager object.
293 * @profile: the new #AnjutaProfile.
294 * @error: error propagation and reporting.
296 * Add a new profile at the top of the profile manager stack. If the profile
297 * manager is not frozen, this new profile will be loaded immediatly and
298 * become the current profile.
300 * Return value: %TRUE on success, %FALSE otherwise.
303 anjuta_profile_manager_push (AnjutaProfileManager
*profile_manager
,
304 AnjutaProfile
*profile
, GError
**error
)
306 g_return_val_if_fail (ANJUTA_IS_PROFILE_MANAGER (profile_manager
), FALSE
);
308 /* Emit profile push signal */
309 g_signal_emit_by_name (profile_manager
, "profile-pushed",
312 return anjuta_profile_manager_queue_profile (profile_manager
, profile
,
317 * anjuta_profile_manager_pop:
318 * @profile_manager: the #AnjutaProfileManager object.
319 * @profile: the #AnjutaProfile to remove.
320 * @error: error propagation and reporting.
322 * Remove a profile from the profile manager stack. If the manager is not
323 * frozen, only the current profile can be removed. It will be unloaded and
324 * the previous profile will be loaded.
325 * If the manager is frozen, the current profile or the last pushed profile
328 * Return value: %TRUE on success, %FALSE otherwise.
331 anjuta_profile_manager_pop (AnjutaProfileManager
*profile_manager
,
332 AnjutaProfile
*profile
, GError
**error
)
334 AnjutaProfileManagerPriv
*priv
;
336 g_return_val_if_fail (ANJUTA_IS_PROFILE_MANAGER (profile_manager
), FALSE
);
337 priv
= profile_manager
->priv
;
339 /* First check in the queue */
340 if (priv
->profiles_queue
)
342 g_return_val_if_fail (priv
->profiles_queue
->data
== profile
, FALSE
);
343 priv
->profiles_queue
= g_list_remove (priv
->profiles_queue
, profile
);
345 g_signal_emit_by_name (profile_manager
, "profile-popped",
348 g_object_unref (profile
);
352 /* Then check in the current stack */
355 g_return_val_if_fail (priv
->profiles
->data
== profile
, FALSE
);
356 priv
->profiles
= g_list_remove (priv
->profiles
, profile
);
358 g_signal_emit_by_name (profile_manager
, "profile-popped",
361 /* Restore the next profile in the stack */
362 anjuta_profile_unload (profile
, NULL
);
363 g_object_unref (profile
);
366 return anjuta_profile_load (ANJUTA_PROFILE (priv
->profiles
->data
), error
);
375 * anjuta_profile_manager_freeze:
376 * @profile_manager: the #AnjutaProfileManager object.
378 * Freeze the plugin manager. In this state, plugins can be added and removed
379 * from the stack without triggering any change in the current profile. It is
380 * possible to freeze the manager several times but it will be back in its normal
381 * state only after as much call of anjuta_profile_manager_thaw().
384 anjuta_profile_manager_freeze (AnjutaProfileManager
*profile_manager
)
386 AnjutaProfileManagerPriv
*priv
;
387 g_return_if_fail (ANJUTA_IS_PROFILE_MANAGER (profile_manager
));
389 priv
= profile_manager
->priv
;
390 priv
->freeze_count
++;
394 * anjuta_profile_manager_thaw:
395 * @profile_manager: the #AnjutaProfileManager object.
396 * @error: error propagation and reporting.
398 * Put back the plugin manager in its normal mode after calling
399 * anjuta_profile_manager_freeze(). It will load a new profile if one has been
400 * added while the manager was frozen.
402 * Return value: %TRUE on success, %FALSE otherwise.
405 anjuta_profile_manager_thaw (AnjutaProfileManager
*profile_manager
,
408 AnjutaProfileManagerPriv
*priv
;
409 g_return_val_if_fail (ANJUTA_IS_PROFILE_MANAGER (profile_manager
), FALSE
);
411 priv
= profile_manager
->priv
;
413 if (priv
->freeze_count
> 0)
414 priv
->freeze_count
--;
416 return anjuta_profile_manager_load_profiles (profile_manager
, error
);
420 * anjuta_profile_manager_get_current :
421 * @profile_manager: A #AnjutaProfileManager object.
423 * Return the current profile.
425 * Return value: (transfer none) (allow-none): a #AnjutaProfile object or %NULL
426 * if the profile stack is empty.
429 anjuta_profile_manager_get_current (AnjutaProfileManager
*profile_manager
)
431 g_return_val_if_fail (ANJUTA_IS_PROFILE_MANAGER (profile_manager
), NULL
);
433 if (profile_manager
->priv
->profiles_queue
)
434 return ANJUTA_PROFILE (profile_manager
->priv
->profiles_queue
->data
);
435 else if (profile_manager
->priv
->profiles
)
436 return ANJUTA_PROFILE (profile_manager
->priv
->profiles
->data
);
442 * anjuta_profile_manager_close:
443 * @profile_manager: A #AnjutaProfileManager object.
445 * Close the #AnjutaProfileManager causing "descoped" to be emitted and
446 * all queued and previous profiles to be released. This function is to be used
447 * when destroying an Anjuta instance.
450 anjuta_profile_manager_close (AnjutaProfileManager
*profile_manager
)
452 AnjutaProfileManagerPriv
*priv
;
454 g_return_if_fail (ANJUTA_IS_PROFILE_MANAGER (profile_manager
));
456 priv
= profile_manager
->priv
;
460 AnjutaProfile
*profile
= ANJUTA_PROFILE (priv
->profiles
->data
);
462 /* Emit "descoped" so that other parts of anjuta can store
463 * information about the currently loaded profile. */
464 anjuta_profile_unload (profile
, NULL
);
466 g_list_free_full (priv
->profiles
, g_object_unref
);
467 priv
->profiles
= NULL
;
470 if (priv
->profiles_queue
)
472 g_list_free_full (priv
->profiles
, g_object_unref
);
473 priv
->profiles_queue
= NULL
;