"""
Contains helpers for creating layouts.
Copyright Schrodinger, LLC. All rights reserved.
"""
#- Imports -------------------------------------------------------------------
from schrodinger.Qt import QtWidgets
#- Globals -------------------------------------------------------------------
STRETCH = 0
ROW_SPAN = 1
COL_SPAN = 2
#- Functions -----------------------------------------------------------------
def _add_to_layout(obj, layout, *args, **kwargs):
"""
Cycles through adding to a layout. First it tries to add the
`obj` as a widget, then as an item and finally as a layout.
"""
try:
layout.addWidget(obj, *args, **kwargs)
except TypeError:
try:
layout.addItem(obj, *args, **kwargs)
except TypeError:
# If an error occurs here let QT raise the error
layout.addLayout(obj, *args, **kwargs)
def _apply_box_settings(layout, objects, margins=None, spacing=5):
"""
Private function to apply common settings to a `QtWidgets.QHBoxLayout`
or `QtWidgets.QVBoxLayout` object.
:param objects: Objects (widget, item, layout) to add
:type objects: mixed (list or single object)
:param stretch: Whether or not to add a stretch to the end of the layout
:type stretch: bool
:param margins: Margins used in `QtWidgets.QHBoxLayout.setContentsMargins`
:type margins: tuple
"""
if not isinstance(objects, (list, tuple)):
objects = [objects]
margins = margins or (-1, -1, -1, -1)
layout.setSpacing(spacing)
layout.setContentsMargins(*margins)
for obj in objects:
if obj == STRETCH:
layout.addStretch()
else:
_add_to_layout(obj, layout)
return layout
[docs]def vbox(objects, margins=None, spacing=5):
"""
Function used to create a `QtWidgets.QVBoxLayout` object.
:param objects: Objects (widget, item, layout) to add
:type objects: mixed (list or single object)
:param margins: Margins used in `QtWidgets.QHBoxLayout.setContentsMargins`
:type margins: tuple
"""
layout = QtWidgets.QVBoxLayout()
hbox_layout = _apply_box_settings(layout, objects, margins, spacing)
return hbox_layout
[docs]def hbox(objects, margins=None, spacing=5):
"""
Function used to create a `QtWidgets.QHBoxLayout` object.
:param objects: Objects (widget, item, layout) to add
:type objects: mixed (list or single object)
:param margins: Margins used in `QtWidgets.QHBoxLayout.setContentsMargins`
:type margins: tuple
"""
layout = QtWidgets.QHBoxLayout()
hbox_layout = _apply_box_settings(layout, objects, margins, spacing)
return hbox_layout
[docs]def grid(objects, stretch=False, margins=None, hspace=5, vspace=5):
"""
Function used to create a `QtWidgets.QGridLayout` object. The `objects`
is a list of objects that will populate the grid. The grid's row
count will equal the length of `objects` and it's column count will
equal the length of the row with the most items. If you want to skip
a column, set it to `None`, and if you want a column to span multiple
columns add a `schrodinger.application.bioluminate.layout.ROW_SPAN`
to all the preceding columns you want it to occupy.
Example::
`objects = [
[ layout.ROW_SPAN, layout.ROW_SPAN, label, None, line_edit],
[ double_spinner, push_button, line_edit ]
]
grid = layout.grid(objects)
`
The above will return a grid layout like::
--------------------------------------------------------------
| label | | line_edit |
-------------------------------------------------------------
| double_spinner | push_button | line_edit | | |
--------------------------------------------------------------
:param objects: Objects (widget, item, or layout) to add to a single
`QtWidgets.QGridLayout`
:type objects: list of lists
"""
margins = margins or (-1, -1, -1, -1)
grid_layout = QtWidgets.QGridLayout()
# Set the columns up so that blank columns still take space up.
# This keeps the layout much cleaner if objects are dynamic
col_lens = [len(a) for a in objects]
#for i in range(0,max(col_lens)):
# grid_layout.setColumnMinimumWidth(i, 50)
grid_layout.setHorizontalSpacing(hspace)
grid_layout.setVerticalSpacing(vspace)
grid_layout.setContentsMargins(*margins)
for i, row in enumerate(objects):
row_span = 1
# We do not support column spans yet but we still need to add
# the variable for when we call _add_to_layout
col_span = 1
for j, wid in enumerate(row):
if wid is None:
continue
if wid == ROW_SPAN:
row_span += 1
continue
j -= (row_span - 1)
_add_to_layout(wid, grid_layout, i, j, row_span, col_span)
row_span = 1
col_span = 1
return grid_layout