def __init__(self, name, parent): super(SnapshotsView, self).__init__(parent) self._pixmap = None self._name = name self._scene = QtGui.QGraphicsScene(parent) self.setGeometry(QtCore.QRect(0, 0, parent.width(), parent.height())) self._scale_factor = 1.15 css_frame = """ /*background: #000; border-top: 2px solid #000; border-left: 2px solid #000; border-right: 2px solid #000; border-top-left-radius: 4px; border-top-right-radius: 4px;*/ """ self.setStyleSheet(css_frame) self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self._item = QtGui.QGraphicsPixmapItem() self._scene.addItem(self._item) self._drawings = [] image_pen_px = QtGui.QPixmap(':ftrack/image/integration/pencil') image_pen_px.setMask(image_pen_px.mask()) self._image_pen_cursor = QtGui.QCursor(image_pen_px) self._pen_color = QtCore.Qt.red self._drawing_mode = False self._pencil_pressed = False self._position_mouse = None self.setBackgroundBrush( QtGui.QBrush(QtCore.Qt.black, QtCore.Qt.SolidPattern)) self.setScene(self._scene)
def _bounding_boxes(self, comment, width, padding_left, padding_top): padding_left_box = padding_left - self._padding_comment width_comment = width - padding_left width_comment -= (self._padding_item["right"] + self._padding_content["right"]) if width_comment < 0: width_comment = 0 width_adjust = - \ self._padding_comment if width_comment >= self._padding_comment else 0 r_comment = QtCore.QRect(padding_left, padding_top, width_comment, 50) r_comment_text = r_comment.adjusted(self._padding_comment, self._padding_comment, width_adjust, -self._padding_comment) bounding_text = self._fm_desc.boundingRect(r_comment_text, self._comment_flags, comment) r_comment.setHeight(bounding_text.height() + self._padding_comment * 2) r_comment_text.setHeight(bounding_text.height()) return (r_comment, r_comment_text)
def paint(self, painter, option, index): ''' Override the tree widget draw widget function. ''' rect = option.rect tree_widget = self.parent() model = tree_widget.model() item = index.model().itemFromIndex(index) line = item.script_line.clean_line line_number = item.line_number is_title = item.script_line.has_children() is_comment = item.script_line.is_comment() color_value = self._color_default_value if item.script_line.is_comment(): font = self._font_comment color_default = self._color_comment highlight_value = False elif item.script_line.is_layer_addition(): font = self._font_default color_default = self._color_layer_addition highlight_value = False elif (item.script_line.stack_pushed() != None or item.script_line.stack_set() != None): font = self._font_default color_default = self._color_stacked_pushed color_value = self._color_stacked_pushed_value highlight_value = True elif item.script_line.has_children(): font = self._font_has_children color_default = self._color_has_children highlight_value = True else: font = self._font_default color_default = self._color_default highlight_value = True font.setPixelSize(tree_widget.font_size) # Get the size of the text according to the chosen font fm = QtGui.QFontMetrics(font) # Separate the line in a list of tuple (text, color) to draw the text if item.script_line.has_children( ) and not tree_widget.isExpanded(index): to_write = [(line + "...}", color_default)] else: to_write = [(line, color_default)] if highlight_value: # Try to highlight the name and the value(s) if possible tuple_split = item.script_line.clean_line.split(" ", 1) if len(tuple_split) > 1: if tuple_split[-1].strip() not in ["{", "{...}"]: to_write = [(tuple_split[0], color_default), (tuple_split[-1], color_value)] # Set line number indentation font_line_number = self._font_default font_line_number.setPixelSize(tree_widget.font_size) fm_line_number = QtGui.QFontMetrics(font_line_number) self.line_numbers_indent = fm_line_number.width( str(model.total_line_number)) # Draw the line number if the option has been set painter.setPen( QtGui.QPen(self._color_line_number, 1, QtCore.Qt.SolidLine)) painter.setFont(font_line_number) painter.drawText(5, rect.top() + 15, str(item.line_number)) interval_left = rect.left() + 15 + self.line_numbers_indent # Draw the filter if we need one if tree_widget.filter != None: self._color_selection.setAlpha(70) elements = re.findall(tree_widget.filter, line, re.IGNORECASE) tmp_line = line interval_rect = interval_left for element in elements: prefix, tmp_line = tmp_line.split(element, 1) interval_rect += fm.width(prefix) width = fm.width(element) rect_selection = QtCore.QRect(interval_rect, rect.y(), width, rect.height()) painter.setBrush(self._color_selection) painter.setPen( QtGui.QPen(self._color_selection, 2, QtCore.Qt.SolidLine)) painter.drawRect(rect_selection) interval_rect += width # Draw the text for tuple_to_write in to_write: text, color = tuple_to_write pen = QtGui.QPen(color, 1, QtCore.Qt.SolidLine) painter.setPen(QtGui.QPen(color, 1, QtCore.Qt.SolidLine)) painter.setFont(font) painter.drawText(interval_left, rect.top() + 15, text) interval_left += fm.width(text) + 5
def paint(self, painter, option, index): painter.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing) padding_left = option.rect.left( ) + self._padding_item["left"] + self._padding_content["left"] padding_right = self._padding_item["right"] + self._padding_content[ "right"] padding_top = option.rect.top() + self._padding_item["top"] is_btn = index.data(TreeItem.is_button_role) if is_btn: text_btn = "show more versions..." padding_top += self._fm_desc.height() padding_left_btn = option.rect.width() - option.rect.width() * 0.5 padding_left_btn -= self._fm_desc.width(text_btn) * 0.5 self._button_rect = QtCore.QRect(option.rect.left(), 0, option.rect.width(), option.rect.height()) self.draw_button(painter, text_btn, padding_left_btn, padding_top, index) else: asset_type = index.data(TreeItem.asset_type_role) name = index.data(TreeItem.name_role) version_nb = index.data(TreeItem.version_nb_role) publisher = index.data(TreeItem.publisher_role) date = index.data(TreeItem.date_role) is_edited = index.data(TreeItem.is_edited_role) comment = index.data(TreeItem.comment_role) locked = index.data(TreeItem.is_locked_role) thumbnail = index.data(TreeItem.thumbnail_role) locations = index.data(TreeItem.location_role) available = index.data(TreeItem.is_available_role) main_color = QtGui.QColor() main_color.setNamedColor('#333') legend_color = QtGui.QColor() legend_color.setNamedColor(self._view.asset_color(asset_type)) # Get status if self._is_top_asset_version(index): if available is None: background = self._background_regenerated elif available: background = self._background else: background = self._background_not_available background_comment = self._background_comment size_thumbnail = self._thumnbail_size else: if available is None: background = self._background_regenerated elif available: background = self._background.lighter(111) else: background = self._background_child_not_available background_comment = self._background_comment.lighter(111) size_thumbnail = self._thumnbail_child_size background_comment = main_color background = QtGui.QColor() background.setNamedColor('#222') # Draw background if option.state & QtGui.QStyle.State_Selected: painter.setPen( QtGui.QPen(QtCore.Qt.lightGray, 2, QtCore.Qt.SolidLine)) else: painter.setPen(QtGui.QPen(background, 0, QtCore.Qt.SolidLine)) painter.setBrush(background) adjusted_rect = option.rect.adjusted( self._padding_item["left"], self._padding_item["top"], -self._padding_item["right"], -self._padding_item["top"] - self._padding_item["bottom"]) painter.drawRoundedRect(adjusted_rect, 3, 3) # Draw type type_indicator_rect = QtCore.QRect(adjusted_rect.left() + 3, adjusted_rect.top() + 3, self._type_indicator_width - 6, adjusted_rect.height() - 6) painter.setPen(QtGui.QPen(legend_color, 0, QtCore.Qt.SolidLine)) painter.setBrush(legend_color) # painter.drawRoundedRect(type_indicator_rect, 3, 3) padding_left += self._type_indicator_width padding_top += self._padding_content["top"] # Draw thumbnail if necessary if self._show_thumbnail: if thumbnail is None: pixmap = QtGui.QImage(self._thumnbail_default) else: pixmap = QtGui.QImage(thumbnail) pixmap_scaled = pixmap.scaled(size_thumbnail, QtCore.Qt.KeepAspectRatio) thumbnail_rect = QtCore.QRect(padding_left, padding_top, pixmap_scaled.width(), pixmap_scaled.height()) painter.setPen( QtGui.QPen(self._background.darker(190), 0.5, QtCore.Qt.SolidLine)) painter.setBrushOrigin(padding_left, padding_top) painter.setBrush(pixmap_scaled) painter.drawRoundedRect(thumbnail_rect, 3, 3) # If it's a top asset, we draw the legend if self._is_top_asset_version(index): padding_top_rect = padding_top + thumbnail_rect.height( ) - self._fm_desc.height() type_rect = QtCore.QRect( padding_left, padding_top_rect - 6, self._fm_desc.width(asset_type) + 10, self._fm_desc.height() + 6) painter.setBrush(legend_color) painter.drawRoundedRect(type_rect, 3, 3) if legend_color.lightness() < 127.5: legend_text_color = legend_color.lighter(190) else: legend_text_color = legend_color.darker(190) painter.setPen( QtGui.QPen(legend_text_color, 0, QtCore.Qt.SolidLine)) padding_top_legend = padding_top + thumbnail_rect.height( ) - 6 painter.drawText(padding_left + 2, padding_top_legend, asset_type) padding_left += size_thumbnail.width() + 10 # Draw version number if self._is_top_asset_version(index): color_number = self._name_color else: color_number = self._name_color.darker(130) painter.setPen(QtGui.QPen(color_number, 1, QtCore.Qt.SolidLine)) painter.setFont(self._font_name) version_nb_str = "v%02d" % version_nb painter.drawText( option.rect.right() - padding_right - self._fm_name.width(version_nb_str), padding_top + self._fm_name.height(), version_nb_str) # Draw name asset if necessary if self._is_top_asset_version(index): padding_top += self._fm_name.height() painter.drawText(padding_left, padding_top, name) padding_top += self._inter_text # If publisher is None, that means that the asset is being # regenerated if publisher != None: # Draw publisher painter.setPen( QtGui.QPen(self._desc_color, 1, QtCore.Qt.SolidLine)) painter.setFont(self._font_desc) label = "published by " if not is_edited else "edited by " padding_top += self._fm_desc.height() painter.drawText(padding_left, padding_top, label + publisher.getName()) # Draw Date painter.setPen( QtGui.QPen(self._owner_color, 1, QtCore.Qt.SolidLine)) padding_top += self._fm_desc.height() + self._inter_text self.draw_date(painter, date, padding_left, padding_top, index) self._date_rect = QtCore.QRect( padding_left, padding_top - self._fm_desc.height() - option.rect.top(), option.rect.width() - padding_left - 10, self._fm_desc.height() + 10) # # Draw Location if necessary # if not available: # locations_info = "Locations: " # if len(locations) > 0: # locations_info += ", ".join(locations) # else: # locations_info += "Hmmm... nowhere?" # painter.setPen( # QtGui.QPen(QtCore.Qt.red, 1, QtCore.Qt.SolidLine)) # padding_top += self._fm_desc.height() + self._inter_text # painter.drawText(padding_left, padding_top, locations_info) # Draw comment painter.setPen( QtGui.QPen(background_comment, 0, QtCore.Qt.SolidLine)) painter.setBrush(background_comment) padding_top += self._inter_text * 2 r_comment, r_comment_text = self._bounding_boxes( comment, option.rect.width(), padding_left, padding_top) painter.drawRoundedRect(r_comment, 3, 3) painter.setPen( QtGui.QPen(self._comment_color, 1, QtCore.Qt.SolidLine)) painter.drawText(r_comment_text, self._comment_flags, comment) else: # Draw loading asset... painter.setPen( QtGui.QPen(self._desc_color, 1, QtCore.Qt.SolidLine)) painter.setFont(self._font_desc) padding_top += self._fm_desc.height() painter.drawText(padding_left, padding_top, "Loading...") # Get the width to update the sizeHint self._width = option.rect.width()
def editorEvent(self, event, model, option, index): asset_version = index.data(QtCore.Qt.DisplayRole) btn_role = index.data(QtCore.Qt.UserRole) # Set rects rect_btn = QtCore.QRect() if (self._button_rect is not None and (btn_role or asset_version.get('version') > 1)): rect_btn = self._button_rect.translated(0, option.rect.top()) rect_date = QtCore.QRect() if self._date_rect is not None: rect_date = self._date_rect.translated(0, option.rect.top()) # Set events if event.type() == QtCore.QEvent.Type.MouseMove: self._current_index = index if ((event.pos().y() >= rect_date.top() and event.pos().y() <= rect_date.bottom()) and (event.pos().x() >= rect_date.left() and event.pos().x() <= rect_date.right())): model.setData(index, self._hover_state["date_hover"], QtCore.Qt.DecorationRole) elif ((btn_role or asset_version.get('version') > 1) and (event.pos().y() >= rect_btn.top() and event.pos().y() <= rect_btn.bottom()) and (event.pos().x() >= rect_btn.left() and event.pos().x() <= rect_btn.right())): model.setData(index, self._hover_state["btn_hover"], QtCore.Qt.DecorationRole) else: model.setData(index, self._hover_state["no_hover"], QtCore.Qt.DecorationRole) elif event.type() == QtCore.QEvent.Type.MouseButtonPress: if ((btn_role or asset_version.get('version') > 1) and (event.pos().y() >= rect_btn.top() and event.pos().y() <= rect_btn.bottom()) and (event.pos().x() >= rect_btn.left() and event.pos().x() <= rect_btn.right())): model.setData(index, self._hover_state["btn_pressed"], QtCore.Qt.DecorationRole) if btn_role: self._view.toggle_show_more_versions(index) else: self._view.toggle_show_versions(index) else: model.setData(index, self._hover_state["no_hover"], QtCore.Qt.DecorationRole) elif event.type() == QtCore.QEvent.Type.MouseButtonRelease: if ((btn_role or asset_version.get('version') > 1) and (event.pos().y() >= rect_btn.top() and event.pos().y() <= rect_btn.bottom()) and (event.pos().x() >= rect_btn.left() and event.pos().x() <= rect_btn.right())): model.setData(index, self._hover_state["btn_hover"], QtCore.Qt.DecorationRole) else: model.setData(index, self._hover_state["no_hover"], QtCore.Qt.DecorationRole) return super(TreeDelegateStyle, self).editorEvent(event, model, option, index)
def paintEvent(self, event): painter = QtGui.QPainter(self) painter.setRenderHint(QtGui.QPainter.Antialiasing) # Design the graph width_graph = self.width() - (self._pad_left + self._pad_right) height_graph = self.height() - (self._pad_top + self._pad_bottom) rect = QtCore.QRect( self._pad_left, self._pad_top, width_graph, height_graph) painter.fillRect(self.rect(), self._color_back_2) painter.fillRect(rect, self._color_back_1) # Sort graphs to draw the highlighted one at the end unhighlight_graphs = [ p for p in self._points.keys() if p != self._highlight_graph] all_graphs_type = unhighlight_graphs + [self._highlight_graph] # Collect the axis values to draw it at the end... pts_legend_Y = dict() pts_legend_X = dict() versions = range(self._version_number) width_interval = 1 if len( versions) == 1 else 1 / float(len(versions) - 1) for i in versions: pts_legend_X[i] = self._pad_left + width_graph * i * width_interval # collect the highlighted point to get the tool-tips.. points_h = dict() # Get the highlighted point hover_point = None # Draw each graph... for type_graph in all_graphs_type: if self._points[type_graph] == None: continue points_tuples = [] highlighted = type_graph == self._highlight_graph for i in sorted(pts_legend_X.keys(), reverse=True): hover = False try: graph_point = self._points[type_graph][i] except IndexError: pass else: padding = self._pad_top + height_graph relative_position = height_graph * self.raise_level * 0.1 ypos = padding - relative_position * \ graph_point.normalized_value pt = (pts_legend_X[i], ypos) points_tuples.append(pt) pts_legend_Y[graph_point.value] = ypos if highlighted: points_h[pt] = graph_point if self._cursor != None and hover_point == None: inter_points = width_interval * width_graph * 0.5 if (self._cursor[0] > pts_legend_X[i] - inter_points and self._cursor[0] < pts_legend_X[i] + inter_points): hover_point = (pts_legend_X[i], ypos) hover = True # Draw vertical lines of the graph (and horizontal if # necessary) color = self._color_dot_lines_hover if hover else self._color_dot_lines painter.setPen( QtGui.QPen(QtGui.QColor(color), 1, QtCore.Qt.DotLine)) line_tuples = [(pts_legend_X[i], self._pad_top), (pts_legend_X[i], self.height() - self._pad_bottom)] line_polys = QtGui.QPolygonF( map(lambda p: QtCore.QPointF(*p), line_tuples)) painter.drawPolyline(line_polys) if hover: line_H = [(self._pad_left, hover_point[1]), (self._pad_left + width_graph, hover_point[1])] line_H_polys = QtGui.QPolygonF( map(lambda p: QtCore.QPointF(*p), line_H)) painter.drawPolyline(line_H_polys) # Draw the lines of the graph width_line = 3 if highlighted else 2 color = self._points_colors[ type_graph] if highlighted else self._points_colors[type_graph].darker(110) painter.setPen(QtGui.QPen(QtGui.QColor(color), width_line)) points_polys = QtGui.QPolygonF( map(lambda p: QtCore.QPointF(*p), points_tuples)) painter.drawPolyline(points_polys) # Draw points for point_tuple in points_tuples: painter.drawEllipse( QtCore.QRectF(point_tuple[0] - 2, point_tuple[1] - 2, 4, 4)) # Draw highlighted graph points... if hover_point != None and self._highlight_graph in self._points_colors.keys(): x_pos, y_pos = hover_point color = self._points_colors[self._highlight_graph].lighter(160) painter.setBrush(QtGui.QBrush(color)) painter.setPen(QtGui.QPen(QtGui.QColor(QtCore.Qt.black), 1)) painter.drawEllipse(QtCore.QRectF(x_pos - 5, y_pos - 5, 10, 10)) painter.setPen(QtGui.QPen(QtGui.QColor(self._color_axis_text), 2)) # Draw X Axis buf_X = 0 for version_nb in sorted(pts_legend_X.keys(), reverse=True): version_str = "v%d" % (version_nb + 1) version_position_X = pts_legend_X[ version_nb] - len(version_str) * 5 if buf_X == 0 or buf_X - version_position_X > 40: pt_legend_X = QtCore.QPointF(version_position_X, self._pad_top + height_graph + 15) painter.drawText(pt_legend_X, version_str) buf_X = version_position_X # Draw Y Axis buf_Y = 0 for value_Y in sorted(pts_legend_Y.keys(), reverse=True): if buf_Y == 0 or pts_legend_Y[value_Y] - buf_Y > 15: value_str = str(value_Y) pt_legend_Y = QtCore.QPointF(self._pad_left - len(value_str) * 15, pts_legend_Y[value_Y] + 10) bounding_rect = QtCore.QRect(0, pts_legend_Y[value_Y] - 4, self._pad_left - 15, pts_legend_Y[value_Y] + 10) painter.drawText( bounding_rect, QtCore.Qt.AlignRight, value_str) buf_Y = pts_legend_Y[value_Y] if hover_point != None: td = QtGui.QTextDocument() td.setHtml(points_h[hover_point].tooltip) width_tooltip = 180 td.setTextWidth(width_tooltip) height_tooltip = td.size().height() pos_topleft = QtCore.QPoint( self._cursor[0] + 5, self._cursor[1] + 5) if pos_topleft.x() + width_tooltip > self.width() - self._pad_right - 10: pos_topleft.setX( self.width() - self._pad_right - width_tooltip - 10) if pos_topleft.y() + height_tooltip > self.height() - self._pad_bottom - 10: pos_topleft.setY( self.height() - self._pad_bottom - height_tooltip - 10) painter.setOpacity(0.6) rect = QtCore.QRect(pos_topleft.x(), pos_topleft.y(), width_tooltip + 20, height_tooltip + 20) painter.fillRect(rect, self._color_tooltip) painter.setOpacity(1.0) painter.translate(pos_topleft.x() + 10, pos_topleft.y() + 10) ctx = QtGui.QAbstractTextDocumentLayout.PaintContext() ctx.clip = QtCore.QRect(0, 0, width_tooltip, height_tooltip) td.documentLayout().draw(painter, ctx) # Place the buttons pad_left = 5 pos_bottom = self.height() - 25 for button_name in ["tracked", "in_tree", "enabled", "total"]: if self._buttons[button_name] != None: width_btn = self._buttons[button_name].width() self._buttons[button_name].move( self.width() - width_btn - pad_left, pos_bottom) pad_left += width_btn + 5 if self._highlight_graph == button_name: btn_css = "background:%s; color:#FFF; border:none; border-radius:3px;" % self._points_colors[ button_name].name() else: btn_css = "background:#444; color:#FFF; border:none; border-radius:3px;" self._buttons[button_name].setStyleSheet(btn_css) # Raise the curve at the first display.... if self.raise_level < 10: self.raise_level += 1 time.sleep(0.000015) self.update()