From 22e8886fd1f0db96e06feaaafd8280e7e930bfb0 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 22 Oct 2021 15:25:13 +0200 Subject: [PATCH] added few docstrings --- .../publisher/widgets/border_label_widget.py | 64 +++++++++++++++---- openpype/tools/publisher/widgets/icons.py | 4 ++ openpype/tools/publisher/widgets/models.py | 55 ++++++++++++++++ openpype/tools/publisher/widgets/widgets.py | 57 ++++++++++++++++- 4 files changed, 164 insertions(+), 16 deletions(-) diff --git a/openpype/tools/publisher/widgets/border_label_widget.py b/openpype/tools/publisher/widgets/border_label_widget.py index d30ce67140..6f476fabee 100644 --- a/openpype/tools/publisher/widgets/border_label_widget.py +++ b/openpype/tools/publisher/widgets/border_label_widget.py @@ -4,6 +4,14 @@ from openpype.style import get_objected_colors class _VLineWidget(QtWidgets.QWidget): + """Widget drawing 1px wide vertical line. + + ``` │ ``` + + Line is drawn in the middle of widget. + + It is expected that parent widget will set width. + """ def __init__(self, color, left, parent): super(_VLineWidget, self).__init__(parent) self._color = color @@ -33,9 +41,21 @@ class _VLineWidget(QtWidgets.QWidget): painter.end() -class _HLineWidget(QtWidgets.QWidget): +class _HBottomLineWidget(QtWidgets.QWidget): + """Widget drawing 1px wide vertical line with side lines going upwards. + + ```└─────────────┘``` + + Corners may have curve set by radius (`set_radius`). Radius should expect + height of widget. + + Bottom line is drawed at the bottom of widget. If radius is 0 then height + of widget should be 1px. + + It is expected that parent widget will set height and radius. + """ def __init__(self, color, parent): - super(_HLineWidget, self).__init__(parent) + super(_HBottomLineWidget, self).__init__(parent) self._color = color self._radius = 0 @@ -65,9 +85,23 @@ class _HLineWidget(QtWidgets.QWidget): painter.end() -class _HCornerLineWidget(QtWidgets.QWidget): +class _HTopCornerLineWidget(QtWidgets.QWidget): + """Widget drawing 1px wide horizontal line with side line going downwards. + + ```┌───────``` + or + ```────────┐``` + + Horizontal line is drawed in the middle of widget. + + Widget represents left or right corner. Corner may have curve set by + radius (`set_radius`). Radius should expect height of widget (maximum half + height of widget). + + It is expected that parent widget will set height and radius. + """ def __init__(self, color, left_side, parent): - super(_HCornerLineWidget, self).__init__(parent) + super(_HTopCornerLineWidget, self).__init__(parent) self._left_side = left_side self._color = color self._radius = 0 @@ -112,13 +146,13 @@ class _HCornerLineWidget(QtWidgets.QWidget): class BorderedLabelWidget(QtWidgets.QFrame): """Draws borders around widget with label in the middle of top. - +------- Label --------+ - | | - | | - | CONTENT | - | | - | | - +----------------------+ + ┌─────── Label ────────┐ + │ │ + │ │ + │ CONTENT │ + │ │ + │ │ + └──────────────────────┘ """ def __init__(self, label, parent): super(BorderedLabelWidget, self).__init__(parent) @@ -128,8 +162,8 @@ class BorderedLabelWidget(QtWidgets.QFrame): if color_value: color = color_value.get_qcolor() - top_left_w = _HCornerLineWidget(color, True, self) - top_right_w = _HCornerLineWidget(color, False, self) + top_left_w = _HTopCornerLineWidget(color, True, self) + top_right_w = _HTopCornerLineWidget(color, False, self) label_widget = QtWidgets.QLabel(label, self) @@ -143,7 +177,7 @@ class BorderedLabelWidget(QtWidgets.QFrame): left_w = _VLineWidget(color, True, self) right_w = _VLineWidget(color, False, self) - bottom_w = _HLineWidget(color, self) + bottom_w = _HBottomLineWidget(color, self) center_layout = QtWidgets.QHBoxLayout() center_layout.setContentsMargins(5, 5, 5, 5) @@ -176,6 +210,7 @@ class BorderedLabelWidget(QtWidgets.QFrame): self._center_layout = center_layout def set_content_margins(self, value): + """Set margins around content.""" self._center_layout.setContentsMargins( value, value, value, value ) @@ -204,6 +239,7 @@ class BorderedLabelWidget(QtWidgets.QFrame): self._widget.update() def set_center_widget(self, widget): + """Set content widget and add it to center.""" while self._center_layout.count(): item = self._center_layout.takeAt(0) widget = item.widget() diff --git a/openpype/tools/publisher/widgets/icons.py b/openpype/tools/publisher/widgets/icons.py index b8c9d22af8..fd5c45f901 100644 --- a/openpype/tools/publisher/widgets/icons.py +++ b/openpype/tools/publisher/widgets/icons.py @@ -4,6 +4,7 @@ from Qt import QtGui def get_icon_path(icon_name=None, filename=None): + """Path to image in './images' folder.""" if icon_name is None and filename is None: return None @@ -21,6 +22,7 @@ def get_icon_path(icon_name=None, filename=None): def get_image(icon_name=None, filename=None): + """Load image from './images' as QImage.""" path = get_icon_path(icon_name, filename) if path: return QtGui.QImage(path) @@ -28,6 +30,7 @@ def get_image(icon_name=None, filename=None): def get_pixmap(icon_name=None, filename=None): + """Load image from './images' as QPixmap.""" path = get_icon_path(icon_name, filename) if path: return QtGui.QPixmap(path) @@ -35,6 +38,7 @@ def get_pixmap(icon_name=None, filename=None): def get_icon(icon_name=None, filename=None): + """Load image from './images' as QICon.""" pix = get_pixmap(icon_name, filename) if pix: return QtGui.QIcon(pix) diff --git a/openpype/tools/publisher/widgets/models.py b/openpype/tools/publisher/widgets/models.py index a783751fb0..0cfd771ef1 100644 --- a/openpype/tools/publisher/widgets/models.py +++ b/openpype/tools/publisher/widgets/models.py @@ -5,6 +5,13 @@ from Qt import QtCore, QtGui class AssetsHierarchyModel(QtGui.QStandardItemModel): + """Assets hiearrchy model. + + For selecting asset for which should beinstance created. + + Uses controller to load asset hierarchy. All asset documents are stored by + their parents. + """ def __init__(self, controller): super(AssetsHierarchyModel, self).__init__() self._controller = controller @@ -53,6 +60,19 @@ class AssetsHierarchyModel(QtGui.QStandardItemModel): class TasksModel(QtGui.QStandardItemModel): + """Tasks model. + + Task model must have set context of asset documents. + + Items in model are based on 0-infinite asset documents. Always contain + an interserction of context asset tasks. When no assets are in context + them model is empty if 2 or more are in context assets that don't have + tasks with same names then model is empty too. + + Args: + controller (PublisherController): Controller which handles creation and + publishing. + """ def __init__(self, controller): super(TasksModel, self).__init__() self._controller = controller @@ -61,11 +81,31 @@ class TasksModel(QtGui.QStandardItemModel): self._task_names_by_asset_name = {} def set_asset_names(self, asset_names): + """Set assets context.""" self._asset_names = asset_names self.reset() @staticmethod def get_intersection_of_tasks(task_names_by_asset_name): + """Calculate intersection of task names from passed data. + + Example: + ``` + # Passed `task_names_by_asset_name` + { + "asset_1": ["compositing", "animation"], + "asset_2": ["compositing", "editorial"] + } + ``` + Result: + ``` + # Set + {"compositing"} + ``` + + Args: + task_names_by_asset_name (dict): Task names in iterable by parent. + """ tasks = None for task_names in task_names_by_asset_name.values(): if tasks is None: @@ -78,12 +118,20 @@ class TasksModel(QtGui.QStandardItemModel): return tasks or set() def is_task_name_valid(self, asset_name, task_name): + """Is task name available for asset. + + Args: + asset_name (str): Name of asset where should look for task. + task_name (str): Name of task which should be available in asset's + tasks. + """ task_names = self._task_names_by_asset_name.get(asset_name) if task_names and task_name in task_names: return True return False def reset(self): + """Update model by current context.""" if not self._asset_names: self._items_by_name = {} self._task_names_by_asset_name = {} @@ -120,6 +168,13 @@ class TasksModel(QtGui.QStandardItemModel): class RecursiveSortFilterProxyModel(QtCore.QSortFilterProxyModel): + """Recursive proxy model. + + Item is not filtered if any children match the filter. + + Use case: Filtering by string - parent won't be filtered if does not match + the filter string but first checks if any children does. + """ def filterAcceptsRow(self, row, parent_index): regex = self.filterRegExp() if not regex.isEmpty(): diff --git a/openpype/tools/publisher/widgets/widgets.py b/openpype/tools/publisher/widgets/widgets.py index 8415a7a9ca..0940dcda79 100644 --- a/openpype/tools/publisher/widgets/widgets.py +++ b/openpype/tools/publisher/widgets/widgets.py @@ -32,6 +32,7 @@ class PixmapLabel(QtWidgets.QLabel): self._source_pixmap = pixmap def set_source_pixmap(self, pixmap): + """Change source image.""" self._source_pixmap = pixmap self._set_resized_pix() @@ -53,7 +54,7 @@ class PixmapLabel(QtWidgets.QLabel): class TransparentPixmapLabel(QtWidgets.QLabel): - """Label resizing to width and height of font.""" + """Transparent label resizing to width and height of font.""" def __init__(self, *args, **kwargs): super(TransparentPixmapLabel, self).__init__(*args, **kwargs) @@ -67,7 +68,11 @@ class TransparentPixmapLabel(QtWidgets.QLabel): class IconValuePixmapLabel(PixmapLabel): - """Label resizing to width and height of font.""" + """Label resizing to width and height of font. + + Handle icon parsing from creators/instances. Using of QAwesome module + of path to images. + """ fa_prefixes = ["", "fa."] default_size = 200 @@ -77,6 +82,11 @@ class IconValuePixmapLabel(PixmapLabel): super(IconValuePixmapLabel, self).__init__(source_pixmap, parent) def set_icon_def(self, icon_def): + """Set icon by it's definition name. + + Args: + icon_def (str): Name of FontAwesome icon or path to image. + """ source_pixmap = self._parse_icon_def(icon_def) self.set_source_pixmap(source_pixmap) @@ -115,6 +125,7 @@ class IconValuePixmapLabel(PixmapLabel): class ContextWarningLabel(PixmapLabel): + """Pixmap label with warning icon.""" def __init__(self, parent): pix = get_pixmap("warning") @@ -150,6 +161,18 @@ class IconButton(QtWidgets.QPushButton): class PublishIconBtn(IconButton): + """Button using alpha of source image to redraw with different color. + + Main class for buttons showed in publisher. + + TODO: + Add different states: + - normal : before publishing + - publishing : publishing is running + - validation error : validation error happened + - error : other error happened + - success : publishing finished + """ def __init__(self, pixmap_path, *args, **kwargs): super(PublishIconBtn, self).__init__(*args, **kwargs) @@ -164,9 +187,11 @@ class PublishIconBtn(IconButton): self.setIcon(self._enabled_icon) def get_enabled_icon(self): + """Enabled icon.""" return self._enabled_icon def get_disabled_icon(self): + """Disabled icon.""" if self._disabled_icon is None: pixmap = self.paint_image_with_color( self._base_image, QtCore.Qt.gray @@ -176,6 +201,14 @@ class PublishIconBtn(IconButton): @staticmethod def paint_image_with_color(image, color): + """Redraw image with single color using it's alpha. + + It is expected that input image is singlecolor image with alpha. + + Args: + image (QImage): Loaded image with alpha. + color (QColor): Color that will be used to paint image. + """ width = image.width() height = image.height() partition = 8 @@ -212,6 +245,7 @@ class PublishIconBtn(IconButton): class ResetBtn(PublishIconBtn): + """Publish reset button.""" def __init__(self, parent=None): icon_path = get_icon_path("refresh") super(ResetBtn, self).__init__(icon_path, parent) @@ -219,6 +253,7 @@ class ResetBtn(PublishIconBtn): class StopBtn(PublishIconBtn): + """Publish stop button.""" def __init__(self, parent): icon_path = get_icon_path("stop") super(StopBtn, self).__init__(icon_path, parent) @@ -226,6 +261,7 @@ class StopBtn(PublishIconBtn): class ValidateBtn(PublishIconBtn): + """Publish validate button.""" def __init__(self, parent=None): icon_path = get_icon_path("validate") super(ValidateBtn, self).__init__(icon_path, parent) @@ -233,6 +269,7 @@ class ValidateBtn(PublishIconBtn): class PublishBtn(PublishIconBtn): + """Publish start publish button.""" def __init__(self, parent=None): icon_path = get_icon_path("play") super(PublishBtn, self).__init__(icon_path, "Publish", parent) @@ -240,6 +277,7 @@ class PublishBtn(PublishIconBtn): class CreateInstanceBtn(PublishIconBtn): + """Create add button.""" def __init__(self, parent=None): icon_path = get_icon_path("add") super(CreateInstanceBtn, self).__init__(icon_path, parent) @@ -247,6 +285,7 @@ class CreateInstanceBtn(PublishIconBtn): class RemoveInstanceBtn(PublishIconBtn): + """Create remove button.""" def __init__(self, parent=None): icon_path = get_icon_path("delete") super(RemoveInstanceBtn, self).__init__(icon_path, parent) @@ -254,6 +293,7 @@ class RemoveInstanceBtn(PublishIconBtn): class ChangeViewBtn(PublishIconBtn): + """Create toggle view button.""" def __init__(self, parent=None): icon_path = get_icon_path("change_view") super(ChangeViewBtn, self).__init__(icon_path, parent) @@ -261,19 +301,32 @@ class ChangeViewBtn(PublishIconBtn): class AbstractInstanceView(QtWidgets.QWidget): + """Abstract class for instance view in creation part.""" selection_changed = QtCore.Signal() active_changed = QtCore.Signal() + # Refreshed attribute is not changed by view itself + # - widget which triggers `refresh` is changing the state + # TODO store that information in widget which cares about refreshing refreshed = False def set_refreshed(self, refreshed): + """View is refreshed with last instances. + + Views are not updated all the time. Only if are visible. + """ self.refreshed = refreshed def refresh(self): + """Refresh instances in the view from current `CreatedContext`.""" raise NotImplementedError(( "{} Method 'refresh' is not implemented." ).format(self.__class__.__name__)) def get_selected_items(self): + """Selected instances required for callbacks. + + Example: When delete button is clicked to know what should be deleted. + """ raise NotImplementedError(( "{} Method 'get_selected_items' is not implemented." ).format(self.__class__.__name__))