Skip to content

Porting Orange2 widgets to Orange3

Aleš Erjavec edited this page Nov 2, 2015 · 11 revisions
Package/Module reorganization

The import names for OWWidget and supporting GUI building library were reorganized

  • Orange.OrangeWidgets.OWWidget -> Orange.widgets.widget

  • Orange.OrangeWidgets.OWBaseWidget -> Orange.widgets.widget (The OWBaseWidget and OWWidget are merged into a single class)

  • Orange.OrangeWidgets.OWGUI -> Orange.widgets.gui (the contents and interface remain compatible;)

  • Orange.OrangeWidgets.OWColorPalette -> Orange.widgets.utils.colorpalette

  • Orange.OrangeWidgets.OWContexts -> Orange.widgets.settings The context handlers have seen substantial changes.

  • There is no longer any Orange.OrangeWidgets.OWGraph we are using pyqtgraph for all ploting

Defining widget meta description

The widget meta data descriptions (name, desciption, icon, ...) are moved into the OWWidget's class namespace. E.g. in Orange2 the widget meta definitions would look like

"""
<name>Widget</name>
<description>An awesome widget</description>
...
"""

or

NAME = "Widget"
DESCRIPTION = "An awesome widget"
ICON = "icon/someicon.svg"

defined at the module level namespace

In Orange 3 this is changed to

class OWAwesome(OWWidget):
    # Widget's descriptive name
    name = "Widget"
    # A short widget description
    description = "An awesome widget"
    # An icon resource file path for this widget
    # (a path relative to the module where this widget is defined)
    icon = "icons/someicon.svg"
    # Priority within a category
    priority = 0

    # A list of input definitions (here an input named "Bar" taking a
    # value of type `object`, and specifying that a method "set_foo" is
    # the one to receive the input)
    inputs = [("Foo", object, "set_foo")]

    # A list of output definitions (here on output named "Bar"
    # of type object)
    outputs = [("Bar", object)]

    ...

    def set_foo(self, foo):
        """Set the foo widget input"""
        ...
Widget initialization

The OWWidget.__init__ method no longer takes any parameters. The signalManager and title are no longer passed to the __init__, while the parameters specifying the requested GUI layout, ... are (again) defined in the widget's class namespace. E.g. what was once in Orange2

class FooWidget(OWWidget):
    def __init__(self, parent=None, signalManager=None, title="blabla"):
        OWWidget.__init__(self, parent, signalManager, title, wantMainArea=False, ...)

is now changed to

class FooWidget(OWWidget):
    name = "Foo"
    # Do not want the default layout with the main area.
    want_main_area = False
    def __init__(self):
        super().__init__()
Settings

How settings are defined has changed. In Orange2 the settings (widget members) were specified by a class variable settingsList containing a list of member names to store.

class FooWidget(OWWidget):
    settingsList = ["bar"]
    def __init__(self, *args, *kwargs)
         OWWidget.__init__(self, *args, **kwargs)
         # initialize the 'members' to the defaults
         self.bar = 2
         # load/restore the saved state; bar member would be modified here
         self.loadSettings()

In Orange3 the same is accomplished by defining/initializing the settings in the class namespace using the Orange.widget.settings.Setting 'descriptor'

from Orange.widgets.settings import Setting
class FooWidget(OWWidget):
    name = "Foo"
    # Initialize bar and mark it as a persistent setting (i.e. it will be restored
    # from a previous session or a saved workflow)
    bar = Setting(2)
    def __init__(self):
        super().__init__()
        # note that there is no self.loadSettings() or equivalent the `bar` member was
        # already restored and is ready for use.
Context dependent settings

In Orange2

class FooWidget(OWWidget):
    contextHandlers = {"": DomainContextHandler("", ["bar"])}
    ...
    def set_foo(self, foo):
        self.closeContext("")
        ...
        self.openContext("", foo)

in Orange3:

from Orange.widgets.settings import Setting, ContextSetting, DomainContextHandler
class FooWidget(OWWidget):
    name = "Foo"
    # note: the Domain context handler no longer takes a list of member
    # names as a parameter. Context dependent members are defined by
    # `ContextSetting` 'descriptor'
    settingsHandler = DomainContextHandler()
    # Initialize bar and mark it as a context dependent setting 
    bar = ContextSetting(2)
    # Regular non context dependent setting.
    regular_setting = Setting(42)

   ...
    def set_foo(self, foo):
        self.closeContext()
        ...
        self.openContext(foo)

Specifying multiple context handlers is no longer possible, therefore the close/openContext no longer take the contextName as the first parameter.

Add-on package metadata (setup.py)

For add-ons to be displayed in Orange3's Add-on Manager dialog they must include a "orange3 add-on" keyword in their package metadata (i.e. the keywords parameter of the setup function). See orange3-example-addon's setup.py