When setting parameters on modules, some value types provide a custom widget. For example, VTK allows setting color properties by using color chooser widgets. These are defined on a per-constant basis, and they are set at module registration time, so you can define your own widgets for constants. This file describes how to do just that. -------------------------------------------------------------------------------- Creating a new constant To create a widget for your own module, you first need to make sure your module subclasses from Constant, the base class for all constant values in VisTrails. If you don't know how to create user-defined modules, please check the documentation for that first. A user-defined constant is a module that should respect a few additional requirements. These are documented in the docstring for Constant, in core/modules/basic_modules.py, and reproduced here for completeness. When implementing your own constant, You have to adhere to the following interface: Implement the following methods: translate_to_python(x): Given a string, translate_to_python must return a python value that will be the value seen by the execution modules. For example, translate_to_python called on a float parameter with value '3.15' will return float('3.15'). translate_to_string(): Return a string representation of the current constant, which will eventually be passed to translate_to_python. validate(v): return True if given python value is a plausible value for the constant. It should be implemented such that validate(translate_to_python(x)) == True for all valid x A constant must also expose its default value, through the field default_value. There are fields you are not allowed to use in your constant classes. These are: 'id', 'interpreter', 'logging' and 'change_parameter' -------------------------------------------------------------------------------- GUI widgets Now that we have a constant class, we need to create a widget that allows the custom values to be set. This can be any PyQt widget, provided that you respect the following requirements: 1) Your class should always inherit from core.modules.constant_configuration.ConstantMixin, a class mixin that provides you with some necessary infrastructure. 2) Your constructor should expect an instance of core.vistrail.module_param.ModuleParam and the widget's Qt parent. The fields you are probably going to use from ModuleParam are 'type', 'identifier', 'namespace' and 'strValue'. The first three are used to specify the actual type of the class, and 'strValue' is a string representation of the value itself, typically obtained by a call to translate_to_string() as described above. A typical declaration of the constructor then would be class MyOwnConstant(SomeQtWidget, ConstantMixin): def __init__(self, param, parent=None): SomeQtWidget.__init__(self, parent) ConstantMixin.__init__(self) 3) You should implement a "contents()" method that returns a string representation of the value encoded by the GUI in its current state. 4) Every time a change in the GUI state should be passed to VisTrails, you should call update_parent(). Every time this is called a new version is created, so make sure you have a reasonable granularity. -------------------------------------------------------------------------------- Constants during execution To make writing your own modules more convenient, VisTrails provides a certain amount of transparent conversion for some constants. Consider this example. A VisTrails pipeline contains a Float module with value 3.0 connected to port "port1" on a downstream module "Foo" whose compute method is as follows: class Foo(Module): ... def compute(self): ... x = self.getInputFromPort("port1") In this case, x will be a basic Python value of type 'float', _not_ a module of type Float. This automatic conversion happens for only a few classes: Boolean, Integer, Null, Float, and String. These get translated to the expected python types (Null becomes None). Note, however, that this translation does _not_ happen for any other constant, so if you need programmatic access to a constant in your code, you should distinguish between these cases. -------------------------------------------------------------------------------- Gotchas, what to watch out for: If your custom widget is generating errors with tracebacks similar to: File "/home/cscheid/vistrails/trunk/vistrails/core/modules/constant_configuration.py", line 43, in update_parent if newContents != self._last_contents: AttributeError:_last_contents It probably means you forgot to call the constructor to ConstantWidgetMixin. --------------------------------------------------------------------------------