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 }