ayon-core/openpype/tools/utils/layouts.py
Jakub Trllo a73d19b612
Publisher: Show instances in report page (#4915)
* renamed 'validations_widget.py' to 'report_page.py'

* Implemented base logic and widgets for logs

* make one report page

* added missing imports

* added missing constants

* move and rename 'VerticallScrollArea' to 'VerticalScrollArea'

* Validation erro item have id

* use 'ReportPageWidget' in window

* change 'bg-button-hover' key to 'bg-buttons-hover' in style colors

* move publish actions widgets

* Refactored how validation error title is showed

* remove item id from validation error item but add id to group items

* remove margins from actions widget

* shrink publish frame on finished publishing

* fix dash line draw

* add missing styles

* fix dash line in thumbnail widget

* added crash widget and changed layout a little

* added infor overlay message

* export and copy report happens in main window

* fix docstrings

* added per plugin filtering for validation errors

* added implementation of 'FlowLayout'

* actions buttons are in flow layout

* fix actions order

* implemented expanding text edit widget

* expand button has some signals and properties

* description and details are separated widgets

* fix typo

* added constans to '__all__'

* parse icon def is a function

* change layout of widgets

* fix log filtering

* added state icon to instances

* fix pyside6 issues

* implemented 'ClassicExpandBtnLabel' with arrow images

* modified details separator

* added some spacing to layouts

* fix syle of description inputs and progress color

* removed unused import

* add 'is_validation_error' to errored result

* validation error has different icon in logs view

* added plugin name to ValueError if happens

* spacer before detail inputs moved out of detals widget

* fix actions visible in craash report

* ignore pyblish base classes

* filter base plugins in discovery

* use 'is' comparison instead of '__eq__'

* fix action error handling

* Fix handling of 'None' values in comparison

* formatting fix

* Report instance card have same margins as in create mode

* publish instances are grouped by family

* log messages are rstripped
2023-05-23 18:16:05 +02:00

150 lines
4.4 KiB
Python

from qtpy import QtWidgets, QtCore
class FlowLayout(QtWidgets.QLayout):
"""Layout that organize widgets by minimum size into a flow layout.
Layout is putting widget from left to right and top to bottom. When widget
can't fit a row it is added to next line. Minimum size matches widget with
biggest 'sizeHint' width and height using calculated geometry.
Content margins are part of calculations. It is possible to define
horizontal and vertical spacing.
Layout does not support stretch and spacing items.
Todos:
Unified width concept -> use width of largest item so all of them are
same. This could allow to have minimum columns option too.
"""
def __init__(self, parent=None):
super(FlowLayout, self).__init__(parent)
# spaces between each item
self._horizontal_spacing = 5
self._vertical_spacing = 5
self._items = []
def __del__(self):
while self.count():
self.takeAt(0, False)
def isEmpty(self):
for item in self._items:
if not item.isEmpty():
return False
return True
def setSpacing(self, spacing):
self._horizontal_spacing = spacing
self._vertical_spacing = spacing
self.invalidate()
def setHorizontalSpacing(self, spacing):
self._horizontal_spacing = spacing
self.invalidate()
def setVerticalSpacing(self, spacing):
self._vertical_spacing = spacing
self.invalidate()
def addItem(self, item):
self._items.append(item)
self.invalidate()
def count(self):
return len(self._items)
def itemAt(self, index):
if 0 <= index < len(self._items):
return self._items[index]
return None
def takeAt(self, index, invalidate=True):
if 0 <= index < len(self._items):
item = self._items.pop(index)
if invalidate:
self.invalidate()
return item
return None
def expandingDirections(self):
return QtCore.Qt.Orientations(QtCore.Qt.Vertical)
def hasHeightForWidth(self):
return True
def heightForWidth(self, width):
return self._setup_geometry(QtCore.QRect(0, 0, width, 0), True)
def setGeometry(self, rect):
super(FlowLayout, self).setGeometry(rect)
self._setup_geometry(rect)
def sizeHint(self):
return self.minimumSize()
def minimumSize(self):
size = QtCore.QSize(0, 0)
for item in self._items:
widget = item.widget()
if widget is not None:
parent = widget.parent()
if not widget.isVisibleTo(parent):
continue
size = size.expandedTo(item.minimumSize())
if size.width() < 1 or size.height() < 1:
return size
l_margin, t_margin, r_margin, b_margin = self.getContentsMargins()
size += QtCore.QSize(l_margin + r_margin, t_margin + b_margin)
return size
def _setup_geometry(self, rect, only_calculate=False):
h_spacing = self._horizontal_spacing
v_spacing = self._vertical_spacing
l_margin, t_margin, r_margin, b_margin = self.getContentsMargins()
left_x = rect.x() + l_margin
top_y = rect.y() + t_margin
pos_x = left_x
pos_y = top_y
row_height = 0
for item in self._items:
item_hint = item.sizeHint()
item_width = item_hint.width()
item_height = item_hint.height()
if item_width < 1 or item_height < 1:
continue
end_x = pos_x + item_width
wrap = (
row_height > 0
and (
end_x > rect.right()
or (end_x + r_margin) > rect.right()
)
)
if not wrap:
next_pos_x = end_x + h_spacing
else:
pos_x = left_x
pos_y += row_height + v_spacing
next_pos_x = pos_x + item_width + h_spacing
row_height = 0
if not only_calculate:
item.setGeometry(
QtCore.QRect(pos_x, pos_y, item_width, item_height)
)
pos_x = next_pos_x
row_height = max(row_height, item_height)
height = (pos_y - top_y) + row_height
if height > 0:
height += b_margin
return height