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