1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19 
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 
25 module peas.Engine;
26 
27 private import glib.ConstructionException;
28 private import glib.ListG;
29 private import glib.Str;
30 private import gobject.ObjectG;
31 private import gobject.Signals;
32 public  import gtkc.gdktypes;
33 private import peas.PluginInfo;
34 private import peasc.peas;
35 public  import peasc.peastypes;
36 private import std.algorithm;
37 
38 
39 /**
40  * The #PeasEngine structure contains only private data and should only be
41  * accessed using the provided API.
42  */
43 public class Engine : ObjectG
44 {
45 	/** the main Gtk struct */
46 	protected PeasEngine* peasEngine;
47 
48 	/** Get the main Gtk struct */
49 	public PeasEngine* getEngineStruct()
50 	{
51 		return peasEngine;
52 	}
53 
54 	/** the main Gtk struct as a void* */
55 	protected override void* getStruct()
56 	{
57 		return cast(void*)peasEngine;
58 	}
59 
60 	protected override void setStruct(GObject* obj)
61 	{
62 		peasEngine = cast(PeasEngine*)obj;
63 		super.setStruct(obj);
64 	}
65 
66 	/**
67 	 * Sets our main struct and passes it to the parent class.
68 	 */
69 	public this (PeasEngine* peasEngine, bool ownedRef = false)
70 	{
71 		this.peasEngine = peasEngine;
72 		super(cast(GObject*)peasEngine, ownedRef);
73 	}
74 
75 	/**
76 	 * Return a new instance of Engine.
77 	 * If no default Engine has been instantiated yet,
78 	 * the first call of this function will set the default
79 	 * engine as the new instance of Engine.
80 	 *
81 	 * Params:
82 	 *     global = Weather to return a global plugin loader
83 	 *
84 	 * Return: a new instance of Engine.
85 	 *
86 	 * Throws: ConstructionException GTK+ fails to create the object.
87 	 */
88 	public this(bool global = true)
89 	{
90 		PeasEngine* p;
91 		
92 		if (global)
93 			p = peas_engine_new();
94 		else
95 			p = peas_engine_new_with_nonglobal_loaders();
96 		
97 		if(p is null)
98 		{
99 			throw new ConstructionException("null returned by new");
100 		}
101 		
102 		this(p, true);
103 	}
104 
105 	/**
106 	 */
107 
108 	/** */
109 	public static GType getType()
110 	{
111 		return peas_engine_get_type();
112 	}
113 
114 	/**
115 	 * Return the existing instance of #PeasEngine or a subclass of it.
116 	 * If no #PeasEngine subclass has been instantiated yet, the first call
117 	 * of this function will return a new instance of #PeasEngine.
118 	 *
119 	 * Note: this function should never be used when multiple threads are
120 	 * using libpeas API as it is not thread-safe.
121 	 *
122 	 * Return: the existing instance of #PeasEngine.
123 	 */
124 	public static Engine getDefault()
125 	{
126 		auto p = peas_engine_get_default();
127 		
128 		if(p is null)
129 		{
130 			return null;
131 		}
132 		
133 		return ObjectG.getDObject!(Engine)(cast(PeasEngine*) p);
134 	}
135 
136 	/**
137 	 * This function appends a search path to the list of paths where to
138 	 * look for plugins.
139 	 *
140 	 * A so-called "search path" actually consists of both a
141 	 * module directory (where the shared libraries or language modules
142 	 * lie) and a data directory (where the plugin data is).
143 	 *
144 	 * The plugin will be able to use a correct data dir depending on
145 	 * where it is installed, hence allowing to keep the plugin agnostic
146 	 * when it comes to installation location: the same plugin can be
147 	 * installed either in the system path or in the user's home directory,
148 	 * without taking other special care than using
149 	 * peas_plugin_info_get_data_dir() when looking for its data files.
150 	 *
151 	 * If @data_dir is %NULL, then it is set to the same value as
152 	 * @module_dir.
153 	 *
154 	 * Params:
155 	 *     moduleDir = the plugin module directory.
156 	 *     dataDir = the plugin data directory.
157 	 */
158 	public void addSearchPath(string moduleDir, string dataDir)
159 	{
160 		peas_engine_add_search_path(peasEngine, Str.toStringz(moduleDir), Str.toStringz(dataDir));
161 	}
162 
163 	/**
164 	 * If the plugin identified by @info implements the @extension_type interface,
165 	 * then this function will return a new instance of this implementation,
166 	 * wrapped in a new #PeasExtension instance. Otherwise, it will return %NULL.
167 	 *
168 	 * See peas_engine_create_extension() for more information.
169 	 *
170 	 * Params:
171 	 *     info = A loaded #PeasPluginInfo.
172 	 *     extensionType = The implemented extension #GType.
173 	 *     firstProperty = the name of the first property.
174 	 *     varArgs = the value of the first property, followed optionally by more
175 	 *         name/value pairs, followed by %NULL.
176 	 *
177 	 * Return: a new instance of #PeasExtension wrapping
178 	 *     the @extension_type instance, or %NULL.
179 	 */
180 	public PeasExtension* createExtensionValist(PluginInfo info, GType extensionType, string firstProperty, void* varArgs)
181 	{
182 		return peas_engine_create_extension_valist(peasEngine, (info is null) ? null : info.getPluginInfoStruct(), extensionType, Str.toStringz(firstProperty), varArgs);
183 	}
184 
185 	/**
186 	 * If the plugin identified by @info implements the @extension_type interface,
187 	 * then this function will return a new instance of this implementation,
188 	 * wrapped in a new #PeasExtension instance. Otherwise, it will return %NULL.
189 	 *
190 	 * See peas_engine_create_extension() for more information.
191 	 *
192 	 * Params:
193 	 *     info = A loaded #PeasPluginInfo.
194 	 *     extensionType = The implemented extension #GType.
195 	 *     nParameters = the length of the @parameters array.
196 	 *     parameters = an array of #GParameter.
197 	 *
198 	 * Return: a new instance of #PeasExtension wrapping
199 	 *     the @extension_type instance, or %NULL.
200 	 */
201 	public PeasExtension* createExtensionv(PluginInfo info, GType extensionType, GParameter[] parameters)
202 	{
203 		return peas_engine_create_extensionv(peasEngine, (info is null) ? null : info.getPluginInfoStruct(), extensionType, cast(uint)parameters.length, parameters.ptr);
204 	}
205 
206 	/**
207 	 * Enable a loader, enables a loader for plugins.
208 	 * The C plugin loader is always enabled. The other plugin
209 	 * loaders are: lua5.1, python and python3.
210 	 *
211 	 * For instance, the following code will enable Python 2 plugins
212 	 * to be loaded:
213 	 * |[
214 	 * peas_engine_enable_loader (engine, "python");
215 	 * ]|
216 	 *
217 	 * Note: plugin loaders used to be shared across #PeasEngines so enabling
218 	 * a loader on one #PeasEngine would enable it on all #PeasEngines.
219 	 * This behavior has been kept to avoid breaking applications,
220 	 * however a warning has been added to help applications transition.
221 	 *
222 	 * Params:
223 	 *     loaderName = The name of the loader to enable.
224 	 */
225 	public void enableLoader(string loaderName)
226 	{
227 		peas_engine_enable_loader(peasEngine, Str.toStringz(loaderName));
228 	}
229 
230 	/**
231 	 * This function triggers garbage collection on all the loaders currently
232 	 * owned by the #PeasEngine.  This can be used to force the loaders to destroy
233 	 * managed objects that still hold references to objects that are about to
234 	 * disappear.
235 	 */
236 	public void garbageCollect()
237 	{
238 		peas_engine_garbage_collect(peasEngine);
239 	}
240 
241 	/**
242 	 * Returns the list of the names of all the loaded plugins, or an array
243 	 * containing a single %NULL element if there is no plugin currently loaded.
244 	 *
245 	 * Please note that the returned array is a newly allocated one: you will need
246 	 * to free it using g_strfreev().
247 	 *
248 	 * Return: A newly-allocated
249 	 *     %NULL-terminated array of strings.
250 	 */
251 	public string[] getLoadedPlugins()
252 	{
253 		auto retStr = peas_engine_get_loaded_plugins(peasEngine);
254 		
255 		scope(exit) Str.freeStringArray(retStr);
256 		return Str.toStringArray(retStr);
257 	}
258 
259 	/**
260 	 * Gets the #PeasPluginInfo corresponding with @plugin_name,
261 	 * or %NULL if @plugin_name was not found.
262 	 *
263 	 * Params:
264 	 *     pluginName = A plugin name.
265 	 *
266 	 * Return: the #PeasPluginInfo corresponding with
267 	 *     a given plugin module name.
268 	 */
269 	public PluginInfo getPluginInfo(string pluginName)
270 	{
271 		auto p = peas_engine_get_plugin_info(peasEngine, Str.toStringz(pluginName));
272 		
273 		if(p is null)
274 		{
275 			return null;
276 		}
277 		
278 		return ObjectG.getDObject!(PluginInfo)(cast(PeasPluginInfo*) p);
279 	}
280 
281 	/**
282 	 * Returns the list of #PeasPluginInfo known to the engine.
283 	 *
284 	 * Return: a #GList of
285 	 *     #PeasPluginInfo. Note that the list belongs to the engine and should
286 	 *     not be freed.
287 	 */
288 	public ListG getPluginList()
289 	{
290 		auto p = peas_engine_get_plugin_list(peasEngine);
291 		
292 		if(p is null)
293 		{
294 			return null;
295 		}
296 		
297 		return new ListG(cast(GList*) p);
298 	}
299 
300 	/**
301 	 * Loads the plugin corresponding to @info if it's not currently loaded.
302 	 * Emits the "load-plugin" signal; loading the plugin
303 	 * actually occurs in the default signal handler.
304 	 *
305 	 * Params:
306 	 *     info = A #PeasPluginInfo.
307 	 *
308 	 * Return: whether the plugin has been successfully loaded.
309 	 */
310 	public bool loadPlugin(PluginInfo info)
311 	{
312 		return peas_engine_load_plugin(peasEngine, (info is null) ? null : info.getPluginInfoStruct()) != 0;
313 	}
314 
315 	/**
316 	 * This function prepends a search path to the list of paths where to
317 	 * look for plugins.
318 	 *
319 	 * See Also: peas_engine_add_search_path()
320 	 *
321 	 * Params:
322 	 *     moduleDir = the plugin module directory.
323 	 *     dataDir = the plugin data directory.
324 	 *
325 	 * Since: 1.6
326 	 */
327 	public void prependSearchPath(string moduleDir, string dataDir)
328 	{
329 		peas_engine_prepend_search_path(peasEngine, Str.toStringz(moduleDir), Str.toStringz(dataDir));
330 	}
331 
332 	/**
333 	 * Returns if @info provides an extension for @extension_type.
334 	 * If the @info is not loaded than %FALSE will always be returned.
335 	 *
336 	 * Params:
337 	 *     info = A #PeasPluginInfo.
338 	 *     extensionType = The extension #GType.
339 	 *
340 	 * Return: if @info provides an extension for @extension_type.
341 	 */
342 	public bool providesExtension(PluginInfo info, GType extensionType)
343 	{
344 		return peas_engine_provides_extension(peasEngine, (info is null) ? null : info.getPluginInfoStruct(), extensionType) != 0;
345 	}
346 
347 	/**
348 	 * Rescan all the registered directories to find new or updated plugins.
349 	 *
350 	 * Calling this function will make the newly installed plugin infos
351 	 * be loaded by the engine, so the new plugins can be used without
352 	 * restarting the application.
353 	 */
354 	public void rescanPlugins()
355 	{
356 		peas_engine_rescan_plugins(peasEngine);
357 	}
358 
359 	/**
360 	 * Sets the list of loaded plugins for @engine. When this function is called,
361 	 * the #PeasEngine will load all the plugins whose names are in @plugin_names,
362 	 * and ensures all other active plugins are unloaded.
363 	 *
364 	 * If @plugin_names is %NULL, all plugins will be unloaded.
365 	 *
366 	 * Params:
367 	 *     pluginNames = A %NULL-terminated
368 	 *         array of plugin names, or %NULL.
369 	 */
370 	public void setLoadedPlugins(string[] pluginNames)
371 	{
372 		peas_engine_set_loaded_plugins(peasEngine, Str.toStringzArray(pluginNames));
373 	}
374 
375 	/**
376 	 * Unloads the plugin corresponding to @info.
377 	 * Emits the "unload-plugin" signal; unloading the plugin
378 	 * actually occurs in the default signal handler.
379 	 *
380 	 * Params:
381 	 *     info = A #PeasPluginInfo.
382 	 *
383 	 * Return: whether the plugin has been successfully unloaded.
384 	 */
385 	public bool unloadPlugin(PluginInfo info)
386 	{
387 		return peas_engine_unload_plugin(peasEngine, (info is null) ? null : info.getPluginInfoStruct()) != 0;
388 	}
389 
390 	protected class OnLoadPluginDelegateWrapper
391 	{
392 		void delegate(PluginInfo, Engine) dlg;
393 		gulong handlerId;
394 		ConnectFlags flags;
395 		this(void delegate(PluginInfo, Engine) dlg, gulong handlerId, ConnectFlags flags)
396 		{
397 			this.dlg = dlg;
398 			this.handlerId = handlerId;
399 			this.flags = flags;
400 		}
401 	}
402 	protected OnLoadPluginDelegateWrapper[] onLoadPluginListeners;
403 
404 	/**
405 	 * The load-plugin signal is emitted when a plugin is being loaded.
406 	 *
407 	 * The plugin is being loaded in the default handler. Hence, if you want to
408 	 * perform some action before the plugin is loaded, you should use
409 	 * g_signal_connect(), but if you want to perform some action *after* the
410 	 * plugin is loaded (the most common case), you should use
411 	 * g_signal_connect_after().
412 	 *
413 	 * Params:
414 	 *     info = A #PeasPluginInfo.
415 	 */
416 	gulong addOnLoadPlugin(void delegate(PluginInfo, Engine) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
417 	{
418 		onLoadPluginListeners ~= new OnLoadPluginDelegateWrapper(dlg, 0, connectFlags);
419 		onLoadPluginListeners[onLoadPluginListeners.length - 1].handlerId = Signals.connectData(
420 			this,
421 			"load-plugin",
422 			cast(GCallback)&callBackLoadPlugin,
423 			cast(void*)onLoadPluginListeners[onLoadPluginListeners.length - 1],
424 			cast(GClosureNotify)&callBackLoadPluginDestroy,
425 			connectFlags);
426 		return onLoadPluginListeners[onLoadPluginListeners.length - 1].handlerId;
427 	}
428 	
429 	extern(C) static void callBackLoadPlugin(PeasEngine* engineStruct, PeasPluginInfo* info,OnLoadPluginDelegateWrapper wrapper)
430 	{
431 		wrapper.dlg(ObjectG.getDObject!(PluginInfo)(info), wrapper.outer);
432 	}
433 	
434 	extern(C) static void callBackLoadPluginDestroy(OnLoadPluginDelegateWrapper wrapper, GClosure* closure)
435 	{
436 		wrapper.outer.internalRemoveOnLoadPlugin(wrapper);
437 	}
438 
439 	protected void internalRemoveOnLoadPlugin(OnLoadPluginDelegateWrapper source)
440 	{
441 		foreach(index, wrapper; onLoadPluginListeners)
442 		{
443 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
444 			{
445 				onLoadPluginListeners[index] = null;
446 				onLoadPluginListeners = std.algorithm.remove(onLoadPluginListeners, index);
447 				break;
448 			}
449 		}
450 	}
451 	
452 
453 	protected class OnUnloadPluginDelegateWrapper
454 	{
455 		void delegate(PluginInfo, Engine) dlg;
456 		gulong handlerId;
457 		ConnectFlags flags;
458 		this(void delegate(PluginInfo, Engine) dlg, gulong handlerId, ConnectFlags flags)
459 		{
460 			this.dlg = dlg;
461 			this.handlerId = handlerId;
462 			this.flags = flags;
463 		}
464 	}
465 	protected OnUnloadPluginDelegateWrapper[] onUnloadPluginListeners;
466 
467 	/**
468 	 * The unload-plugin signal is emitted when a plugin is being unloaded.
469 	 *
470 	 * The plugin is being unloaded in the default handler. Hence, if you want
471 	 * to perform some action before the plugin is unloaded (the most common
472 	 * case), you should use g_signal_connect(), but if you want to perform some
473 	 * action after the plugin is unloaded (the most common case), you should
474 	 * use g_signal_connect_after().
475 	 *
476 	 * Params:
477 	 *     info = A #PeasPluginInfo.
478 	 */
479 	gulong addOnUnloadPlugin(void delegate(PluginInfo, Engine) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
480 	{
481 		onUnloadPluginListeners ~= new OnUnloadPluginDelegateWrapper(dlg, 0, connectFlags);
482 		onUnloadPluginListeners[onUnloadPluginListeners.length - 1].handlerId = Signals.connectData(
483 			this,
484 			"unload-plugin",
485 			cast(GCallback)&callBackUnloadPlugin,
486 			cast(void*)onUnloadPluginListeners[onUnloadPluginListeners.length - 1],
487 			cast(GClosureNotify)&callBackUnloadPluginDestroy,
488 			connectFlags);
489 		return onUnloadPluginListeners[onUnloadPluginListeners.length - 1].handlerId;
490 	}
491 	
492 	extern(C) static void callBackUnloadPlugin(PeasEngine* engineStruct, PeasPluginInfo* info,OnUnloadPluginDelegateWrapper wrapper)
493 	{
494 		wrapper.dlg(ObjectG.getDObject!(PluginInfo)(info), wrapper.outer);
495 	}
496 	
497 	extern(C) static void callBackUnloadPluginDestroy(OnUnloadPluginDelegateWrapper wrapper, GClosure* closure)
498 	{
499 		wrapper.outer.internalRemoveOnUnloadPlugin(wrapper);
500 	}
501 
502 	protected void internalRemoveOnUnloadPlugin(OnUnloadPluginDelegateWrapper source)
503 	{
504 		foreach(index, wrapper; onUnloadPluginListeners)
505 		{
506 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
507 			{
508 				onUnloadPluginListeners[index] = null;
509 				onUnloadPluginListeners = std.algorithm.remove(onUnloadPluginListeners, index);
510 				break;
511 			}
512 		}
513 	}
514 	
515 }