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 peas.c.functions;
34 public  import peas.c.types;
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,
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 	 * Since libpeas 1.22, @extension_type can be an Abstract #GType
170 	 * and not just an Interface #GType.
171 	 *
172 	 * See peas_engine_create_extension() for more information.
173 	 *
174 	 * Params:
175 	 *     info = A loaded #PeasPluginInfo.
176 	 *     extensionType = The implemented extension #GType.
177 	 *     firstProperty = the name of the first property.
178 	 *     varArgs = the value of the first property, followed optionally by more
179 	 *         name/value pairs, followed by %NULL.
180 	 *
181 	 * Returns: a new instance of #PeasExtension wrapping
182 	 *     the @extension_type instance, or %NULL.
183 	 */
184 	public PeasExtension* createExtensionValist(PluginInfo info, GType extensionType, string firstProperty, void* varArgs)
185 	{
186 		return peas_engine_create_extension_valist(peasEngine, (info is null) ? null : info.getPluginInfoStruct(), extensionType, Str.toStringz(firstProperty), varArgs);
187 	}
188 
189 	/**
190 	 * If the plugin identified by @info implements the @extension_type,
191 	 * then this function will return a new instance of this implementation,
192 	 * wrapped in a new #PeasExtension instance. Otherwise, it will return %NULL.
193 	 *
194 	 * Since libpeas 1.22, @extension_type can be an Abstract #GType
195 	 * and not just an Interface #GType.
196 	 *
197 	 * See peas_engine_create_extension() for more information.
198 	 *
199 	 * Params:
200 	 *     info = A loaded #PeasPluginInfo.
201 	 *     extensionType = The implemented extension #GType.
202 	 *     parameters = an array of #GParameter.
203 	 *
204 	 * Returns: a new instance of #PeasExtension wrapping
205 	 *     the @extension_type instance, or %NULL.
206 	 */
207 	public PeasExtension* createExtensionv(PluginInfo info, GType extensionType, GParameter[] parameters)
208 	{
209 		return peas_engine_create_extensionv(peasEngine, (info is null) ? null : info.getPluginInfoStruct(), extensionType, cast(uint)parameters.length, parameters.ptr);
210 	}
211 
212 	/**
213 	 * Enable a loader, enables a loader for plugins.
214 	 * The C plugin loader is always enabled. The other plugin
215 	 * loaders are: lua5.1, python and python3.
216 	 *
217 	 * For instance, the following code will enable Python 2 plugins
218 	 * to be loaded:
219 	 * |[
220 	 * peas_engine_enable_loader (engine, "python");
221 	 * ]|
222 	 *
223 	 * Note: plugin loaders used to be shared across #PeasEngines so enabling
224 	 * a loader on one #PeasEngine would enable it on all #PeasEngines.
225 	 * This behavior has been kept to avoid breaking applications,
226 	 * however a warning has been added to help applications transition.
227 	 *
228 	 * Params:
229 	 *     loaderName = The name of the loader to enable.
230 	 */
231 	public void enableLoader(string loaderName)
232 	{
233 		peas_engine_enable_loader(peasEngine, Str.toStringz(loaderName));
234 	}
235 
236 	/**
237 	 * This function triggers garbage collection on all the loaders currently
238 	 * owned by the #PeasEngine.  This can be used to force the loaders to destroy
239 	 * managed objects that still hold references to objects that are about to
240 	 * disappear.
241 	 */
242 	public void garbageCollect()
243 	{
244 		peas_engine_garbage_collect(peasEngine);
245 	}
246 
247 	/**
248 	 * Returns the list of the names of all the loaded plugins, or an array
249 	 * containing a single %NULL element if there is no plugin currently loaded.
250 	 *
251 	 * Please note that the returned array is a newly allocated one: you will need
252 	 * to free it using g_strfreev().
253 	 *
254 	 * Returns: A newly-allocated
255 	 *     %NULL-terminated array of strings.
256 	 */
257 	public string[] getLoadedPlugins()
258 	{
259 		auto retStr = peas_engine_get_loaded_plugins(peasEngine);
260 
261 		scope(exit) Str.freeStringArray(retStr);
262 		return Str.toStringArray(retStr);
263 	}
264 
265 	/**
266 	 * Gets the #PeasPluginInfo corresponding with @plugin_name,
267 	 * or %NULL if @plugin_name was not found.
268 	 *
269 	 * Params:
270 	 *     pluginName = A plugin name.
271 	 *
272 	 * Returns: the #PeasPluginInfo corresponding with
273 	 *     a given plugin module name.
274 	 */
275 	public PluginInfo getPluginInfo(string pluginName)
276 	{
277 		auto p = peas_engine_get_plugin_info(peasEngine, Str.toStringz(pluginName));
278 
279 		if(p is null)
280 		{
281 			return null;
282 		}
283 
284 		return ObjectG.getDObject!(PluginInfo)(cast(PeasPluginInfo*) p);
285 	}
286 
287 	/**
288 	 * Returns the list of #PeasPluginInfo known to the engine.
289 	 *
290 	 * Returns: a #GList of
291 	 *     #PeasPluginInfo. Note that the list belongs to the engine and should
292 	 *     not be freed.
293 	 */
294 	public ListG getPluginList()
295 	{
296 		auto p = peas_engine_get_plugin_list(peasEngine);
297 
298 		if(p is null)
299 		{
300 			return null;
301 		}
302 
303 		return new ListG(cast(GList*) p);
304 	}
305 
306 	/**
307 	 * Loads the plugin corresponding to @info if it's not currently loaded.
308 	 * Emits the "load-plugin" signal; loading the plugin
309 	 * actually occurs in the default signal handler.
310 	 *
311 	 * Params:
312 	 *     info = A #PeasPluginInfo.
313 	 *
314 	 * Returns: whether the plugin has been successfully loaded.
315 	 */
316 	public bool loadPlugin(PluginInfo info)
317 	{
318 		return peas_engine_load_plugin(peasEngine, (info is null) ? null : info.getPluginInfoStruct()) != 0;
319 	}
320 
321 	/**
322 	 * This function prepends a search path to the list of paths where to
323 	 * look for plugins.
324 	 *
325 	 * See Also: peas_engine_add_search_path()
326 	 *
327 	 * Params:
328 	 *     moduleDir = the plugin module directory.
329 	 *     dataDir = the plugin data directory.
330 	 *
331 	 * Since: 1.6
332 	 */
333 	public void prependSearchPath(string moduleDir, string dataDir)
334 	{
335 		peas_engine_prepend_search_path(peasEngine, Str.toStringz(moduleDir), Str.toStringz(dataDir));
336 	}
337 
338 	/**
339 	 * Returns if @info provides an extension for @extension_type.
340 	 * If the @info is not loaded than %FALSE will always be returned.
341 	 *
342 	 * Since libpeas 1.22, @extension_type can be an Abstract #GType
343 	 * and not just an Interface #GType.
344 	 *
345 	 * Params:
346 	 *     info = A #PeasPluginInfo.
347 	 *     extensionType = The extension #GType.
348 	 *
349 	 * Returns: if @info provides an extension for @extension_type.
350 	 */
351 	public bool providesExtension(PluginInfo info, GType extensionType)
352 	{
353 		return peas_engine_provides_extension(peasEngine, (info is null) ? null : info.getPluginInfoStruct(), extensionType) != 0;
354 	}
355 
356 	/**
357 	 * Rescan all the registered directories to find new or updated plugins.
358 	 *
359 	 * Calling this function will make the newly installed plugin infos
360 	 * be loaded by the engine, so the new plugins can be used without
361 	 * restarting the application.
362 	 */
363 	public void rescanPlugins()
364 	{
365 		peas_engine_rescan_plugins(peasEngine);
366 	}
367 
368 	/**
369 	 * Sets the list of loaded plugins for @engine. When this function is called,
370 	 * the #PeasEngine will load all the plugins whose names are in @plugin_names,
371 	 * and ensures all other active plugins are unloaded.
372 	 *
373 	 * If @plugin_names is %NULL, all plugins will be unloaded.
374 	 *
375 	 * Params:
376 	 *     pluginNames = A %NULL-terminated
377 	 *         array of plugin names, or %NULL.
378 	 */
379 	public void setLoadedPlugins(string[] pluginNames)
380 	{
381 		peas_engine_set_loaded_plugins(peasEngine, Str.toStringzArray(pluginNames));
382 	}
383 
384 	/**
385 	 * Unloads the plugin corresponding to @info.
386 	 * Emits the "unload-plugin" signal; unloading the plugin
387 	 * actually occurs in the default signal handler.
388 	 *
389 	 * Params:
390 	 *     info = A #PeasPluginInfo.
391 	 *
392 	 * Returns: whether the plugin has been successfully unloaded.
393 	 */
394 	public bool unloadPlugin(PluginInfo info)
395 	{
396 		return peas_engine_unload_plugin(peasEngine, (info is null) ? null : info.getPluginInfoStruct()) != 0;
397 	}
398 
399 	protected class OnLoadPluginDelegateWrapper
400 	{
401 		void delegate(PluginInfo, Engine) dlg;
402 		gulong handlerId;
403 
404 		this(void delegate(PluginInfo, Engine) dlg)
405 		{
406 			this.dlg = dlg;
407 			onLoadPluginListeners ~= this;
408 		}
409 
410 		void remove(OnLoadPluginDelegateWrapper source)
411 		{
412 			foreach(index, wrapper; onLoadPluginListeners)
413 			{
414 				if (wrapper.handlerId == source.handlerId)
415 				{
416 					onLoadPluginListeners[index] = null;
417 					onLoadPluginListeners = std.algorithm.remove(onLoadPluginListeners, index);
418 					break;
419 				}
420 			}
421 		}
422 	}
423 	OnLoadPluginDelegateWrapper[] onLoadPluginListeners;
424 
425 	/**
426 	 * The load-plugin signal is emitted when a plugin is being loaded.
427 	 *
428 	 * The plugin is being loaded in the default handler. Hence, if you want to
429 	 * perform some action before the plugin is loaded, you should use
430 	 * g_signal_connect(), but if you want to perform some action *after* the
431 	 * plugin is loaded (the most common case), you should use
432 	 * g_signal_connect_after().
433 	 *
434 	 * Params:
435 	 *     info = A #PeasPluginInfo.
436 	 */
437 	gulong addOnLoadPlugin(void delegate(PluginInfo, Engine) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
438 	{
439 		auto wrapper = new OnLoadPluginDelegateWrapper(dlg);
440 		wrapper.handlerId = Signals.connectData(
441 			this,
442 			"load-plugin",
443 			cast(GCallback)&callBackLoadPlugin,
444 			cast(void*)wrapper,
445 			cast(GClosureNotify)&callBackLoadPluginDestroy,
446 			connectFlags);
447 		return wrapper.handlerId;
448 	}
449 
450 	extern(C) static void callBackLoadPlugin(PeasEngine* engineStruct, PeasPluginInfo* info, OnLoadPluginDelegateWrapper wrapper)
451 	{
452 		wrapper.dlg(ObjectG.getDObject!(PluginInfo)(info), wrapper.outer);
453 	}
454 
455 	extern(C) static void callBackLoadPluginDestroy(OnLoadPluginDelegateWrapper wrapper, GClosure* closure)
456 	{
457 		wrapper.remove(wrapper);
458 	}
459 
460 	protected class OnUnloadPluginDelegateWrapper
461 	{
462 		void delegate(PluginInfo, Engine) dlg;
463 		gulong handlerId;
464 
465 		this(void delegate(PluginInfo, Engine) dlg)
466 		{
467 			this.dlg = dlg;
468 			onUnloadPluginListeners ~= this;
469 		}
470 
471 		void remove(OnUnloadPluginDelegateWrapper source)
472 		{
473 			foreach(index, wrapper; onUnloadPluginListeners)
474 			{
475 				if (wrapper.handlerId == source.handlerId)
476 				{
477 					onUnloadPluginListeners[index] = null;
478 					onUnloadPluginListeners = std.algorithm.remove(onUnloadPluginListeners, index);
479 					break;
480 				}
481 			}
482 		}
483 	}
484 	OnUnloadPluginDelegateWrapper[] onUnloadPluginListeners;
485 
486 	/**
487 	 * The unload-plugin signal is emitted when a plugin is being unloaded.
488 	 *
489 	 * The plugin is being unloaded in the default handler. Hence, if you want
490 	 * to perform some action before the plugin is unloaded (the most common
491 	 * case), you should use g_signal_connect(), but if you want to perform some
492 	 * action after the plugin is unloaded (the most common case), you should
493 	 * use g_signal_connect_after().
494 	 *
495 	 * Params:
496 	 *     info = A #PeasPluginInfo.
497 	 */
498 	gulong addOnUnloadPlugin(void delegate(PluginInfo, Engine) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
499 	{
500 		auto wrapper = new OnUnloadPluginDelegateWrapper(dlg);
501 		wrapper.handlerId = Signals.connectData(
502 			this,
503 			"unload-plugin",
504 			cast(GCallback)&callBackUnloadPlugin,
505 			cast(void*)wrapper,
506 			cast(GClosureNotify)&callBackUnloadPluginDestroy,
507 			connectFlags);
508 		return wrapper.handlerId;
509 	}
510 
511 	extern(C) static void callBackUnloadPlugin(PeasEngine* engineStruct, PeasPluginInfo* info, OnUnloadPluginDelegateWrapper wrapper)
512 	{
513 		wrapper.dlg(ObjectG.getDObject!(PluginInfo)(info), wrapper.outer);
514 	}
515 
516 	extern(C) static void callBackUnloadPluginDestroy(OnUnloadPluginDelegateWrapper wrapper, GClosure* closure)
517 	{
518 		wrapper.remove(wrapper);
519 	}
520 }