Input and output channels are defined anywhere within the
__init__
function of a main widget class. The definition
is used when running a widget, but also when registering your widget
within Orange Canvas. Channel definitions are optional, depending on
what your widget does.
self.outputs
should thus be a list of tuples, within
each the first element is a name of the channel, and the second the
type of the tokens that will be passed through. Token types are class
names; most often these are some Orange classes, but they can also be
anything you may define as class in Python.
Widgets send the data by using self.send
call,
like:
Parameters of send
are channel name and a token to be
send (e.g., a variable that holds the data to be send through the
channel).
When tokens are send around, the signaling mechanism annotates
them with a pointer to an object that sent the toke (e.g., a widget
id). Additionally, this annotation can be coupled with some name
passed to send
, in case you have a widget that can send
few tokens one after the other and you would like to enable a receiving widget
recognize these are different tokens (and not updates of the same
one):
An example of the simplest definition of an input channel is:
Again, self.inputs
is a list of tuples, where the
elements are the name of the channel, followed by a channel type and a
Python function that will be called with any token received. For the
channel defined above, a corresponding receiving function would be of
the type (we would most often define it within the widget class
defintion, hence self
for the first attribute):
Any time our widget would receive a token, receiveData
would be called. Notice there would be no way of knowing anything
about the sender of the token, hence widget would most often replace
the previously received token with the new one, and forget about the
old one.
Widgets can often clear their output by sending a None
as a token. Also, upon deletion of some widget, this is the way that
Orange Canvas would inform all directly connected downstream widgets
about deletion. Similar, when channels connecting two widgets are
deleted, Orange Canvas would automatically send None
to
the receiving widget. Make sure your widget handles None
tokens appropriately!
There are cases when widget would like to know about the origin of a token. Say, you would like to input several learners to the evaluation widget, how would this distinguish between the learners of different origins? Remember (from above) that tokens are actually passed around with IDs (pointers to widgets that sent them). To declare a widget is interested about these IDs, one needs to define an input channel in the following way:
where the last argument refers if we have a "single token channel" (last argument should be 1, default) or a "multitoken" one (0 as a fourth element of the list holding channel definition). For the above declared channel, the receiving function should include an extra argument for the ID, like:
Widgets such as OWTestLearners
and alike use such
schema.
Finally, we may have input channels of the same type. If a widget would declare input channels like:
and we connect this widget in Orange Canvas to a sending widget that has a single orange.ExampleTable output channel, Canvas would bring up Set Channels dialog. There, a sending widget's channel would be connected to both receiving channels. As we would often prefer to connect to a single (default) channel instead (still allowing user of Orange Canvas to set up a different schema manually), we set all the channels to which we do not want an automatic connection into a "minor mode". We do this by the using the fifth element in the channel definition list, like: