from openalea.core.control import Control
from openalea.core.control.manager import ControlContainer
from openalea.core.service.interface import interface_name
from openalea.core.service.plugin import plugins
from openalea.vpltk.qt import QtGui
from openalea.oalab.utils import ModalDialog
import weakref
"""
**preferred**: specify explicitly the name of the Qt control widget you want to use
**shape**: if None, tries to return a widget.
If shape is a string, returns widget corresponding to this shape.
If it's a list, search widget for first shape. If no widgets found, search for second shape and so on.
"""
[docs]def discover_qt_controls():
return plugins('oalab.plugin', criteria=dict(implement='IWidgetSelector'))
[docs]def qt_editor_class(iname, shape=None, preferred=None):
iname = interface_name(iname)
# Get all widget plugin for "iname" interface
widget_plugins = qt_widget_plugins(iname)
# If preferred widget(s) is/are specified, try to find it
if isinstance(preferred, str):
preferred_widgets = [preferred]
else:
preferred_widgets = preferred
if preferred_widgets:
for preferred in preferred_widgets:
# Load widget specified with control
for plugin in widget_plugins:
if preferred == plugin.name:
widget_class = plugin.implementation
return widget_class
# No preferred widget specified or preferred widget not found.
# We try to find a widget corresponding to shapes
if shape is None:
shapes = ['hline', 'large', 'small']
elif isinstance(shape, str):
shapes = [shape]
else:
shapes = list(shape)
for shape in shapes:
for plugin in widget_plugins:
if shape in plugin.edit_shape or 'responsive' in plugin.edit_shape:
widget_class = plugin.implementation
widget_class.shape = shape
return widget_class
return None
[docs]def qt_dialog(control=None, **kwds):
"""
You can pass control factory arguments:
- name: Control name
- interface: Control interface
- value: Control value
You can also pass qt_editor factory arguments
- shape: widget shape
- preferred: preferred widget
"""
autoapply = kwds.get('autoapply', False)
if control is None:
control = Control(**kwds)
widget = qt_editor(control, **kwds)
widget.autoapply(control, autoapply)
dialog = ModalDialog(widget)
if dialog.exec_() == QtGui.QDialog.Accepted:
return widget.value()
else:
return None
[docs]def qt_editor(control, shape=None, preferred=None, **kwds):
if preferred is None and control.widget:
preferred = control.widget
widget_class = qt_editor_class(control.interface, shape, preferred)
# TODO: FIX THIS HACK
if hasattr(widget_class, 'shape'):
shape = widget_class.shape
if widget_class:
widget = None
if issubclass(widget_class, QtGui.QWidget):
widget = widget_class()
else:
widget = widget_class.edit(control, shape)
if widget is not None:
widget.set(control)
# widget.show()
return widget
[docs]def qt_container(container, **kwargs):
widget = QtGui.QWidget()
layout = QtGui.QFormLayout(widget)
widget.editor = {}
widget.control = {}
for control in container.controls():
editor = qt_editor(control, 'hline')
if editor:
widget.editor[control] = weakref.ref(editor)
widget.control[control.name] = control
layout.addRow(control.label, editor)
return widget
[docs]def qt_viewer(control, shape=None):
pass
[docs]def qt_painter(control, shape=None, preferred=None):
cname = control.interface.__class__.__name__
widget_plugins = qt_widget_plugins(cname)
widget_class = None
if preferred:
# Load widget specified with control
for plugin in widget_plugins:
if preferred == plugin.name and plugin.paint:
widget_class = plugin.implementation
return widget_class.paint(control, shape)
# Load first editor
for plugin in widget_plugins:
if plugin.paint:
widget_class = plugin.implementation
return widget_class.paint(control, shape)
[docs]def edit(control):
import sys
if 'PyQt4.QtGui' in sys.modules or 'PySide.QtGui' in sys.modules:
from openalea.vpltk.qt import QtGui
if QtGui.QApplication.instance():
if isinstance(control, Control):
return qt_editor(control)
elif isinstance(control, ControlContainer):
return qt_container(control)
else:
raise NotImplementedError, 'Only Qt editors are supported'