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 }