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