def __init__(self, icon_label, status_label, progress_bar): """ :param parent: The model parent. :type parent: :class:`~PySide.QtGui.QObject` """ super(ProgressHandler, self).__init__() self._icon_label = icon_label self._status_label = status_label self._progress_bar = progress_bar self._icon_lookup = { self.PHASE_LOAD: QtGui.QPixmap(":/tk_multi_publish2/status_load.png"), self.PHASE_VALIDATE: QtGui.QPixmap(":/tk_multi_publish2/status_validate.png"), self.PHASE_PUBLISH: QtGui.QPixmap(":/tk_multi_publish2/status_publish.png"), self.PHASE_FINALIZE: QtGui.QPixmap(":/tk_multi_publish2/status_success.png"), } self._icon_warning = QtGui.QPixmap( ":/tk_multi_publish2/status_warning.png") self._icon_error = QtGui.QPixmap( ":/tk_multi_publish2/status_error.png") # These colors come from the HIG. self._debug_brush = QtGui.QBrush(QtGui.QColor("#88BC47")) # green self._warning_brush = QtGui.QBrush(QtGui.QColor("#F9A332")) # orange self._error_brush = QtGui.QBrush(QtGui.QColor("#EC494A")) # red # parent our progress widget overlay self._progress_details = ProgressDetailsWidget( self._progress_bar.parent()) self._progress_details.copy_to_clipboard_clicked.connect( self._copy_log_to_clipboard) # clicking on the log toggles the logging window self._status_label.clicked.connect(self._progress_details.toggle) # store all log messages in a list self._log_messages = [] self._current_indent = 0 # set up our log dispatch self._log_wrapper = PublishLogWrapper(self) self._logging_parent_item = None # none means root self._current_phase = None
def create_round_thumbnail(image): """ Create a 200 px wide circle thumbnail :param image: QImage representing a thumbnail :returns: Round QPixmap """ CANVAS_SIZE = 200 # get the 512 base image base_image = QtGui.QPixmap(CANVAS_SIZE, CANVAS_SIZE) base_image.fill(QtCore.Qt.transparent) # now attempt to load the image # pixmap will be a null pixmap if load fails thumb = QtGui.QPixmap.fromImage(image) if not thumb.isNull(): # scale it down to fit inside a frame of maximum 512x512 thumb_scaled = thumb.scaled(CANVAS_SIZE, CANVAS_SIZE, QtCore.Qt.KeepAspectRatioByExpanding, QtCore.Qt.SmoothTransformation) # now composite the thumbnail on top of the base image # bottom align it to make it look nice thumb_img = thumb_scaled.toImage() brush = QtGui.QBrush(thumb_img) painter = QtGui.QPainter(base_image) painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setBrush(brush) painter.drawEllipse(0, 0, CANVAS_SIZE, CANVAS_SIZE) painter.end() return base_image
def paintEvent(self, event): """ Render the UI. """ if self._mode == self.MODE_OFF: return painter = QtGui.QPainter() painter.begin(self) try: # set up semi transparent backdrop painter.setRenderHint(QtGui.QPainter.Antialiasing) overlay_color = QtGui.QColor(30, 30, 30, 100) painter.setBrush( QtGui.QBrush(overlay_color)) painter.setPen(QtGui.QPen(overlay_color)) painter.drawRect(0, 0, painter.device().width(), painter.device().height()) # show the spinner painter.translate((painter.device().width() / 2) - 10, (painter.device().height() / 2) - 10) pen = QtGui.QPen(QtGui.QColor(self._bundle.style_constants["SG_HIGHLIGHT_COLOR"])) pen.setWidth(1) painter.setPen(pen) r = QtCore.QRectF(0.0, 0.0, 20.0, 20.0) start_angle = (0 + self._spin_angle) * 4 * 16 span_angle = 340 * 16 painter.drawArc(r, start_angle, span_angle) finally: painter.end()
def _get_default_thumbnail(self, sg_entity): """ Get the default icon for the specified entity. :param sg_entity: A Shotgun entity dictionary for the entity to get the icon for. :returns: A QIcon for the entity if available. For Step entities, a swatch representing the step colour is returned. If no icon is available for the entity type then the default icon is returned """ if sg_entity.get("type") == "Step": # special case handling for steps to return a colour swatch: step_id = sg_entity.get("id") if step_id != None: # get the colour from the cache: if step_id not in ShotgunEntityModel._SG_STEP_COLOURS: ShotgunEntityModel._SG_STEP_COLOURS[step_id] = None # refresh cache: bundle = sgtk.platform.current_bundle() try: sg_steps = bundle.shotgun.find("Step", [], ["color"]) for sg_step in sg_steps: colour = None try: colour = tuple([ int(c) for c in sg_step.get("color").split(",") ]) except: pass ShotgunEntityModel._SG_STEP_COLOURS[ sg_step["id"]] = colour except: pass colour = ShotgunEntityModel._SG_STEP_COLOURS[step_id] if colour and isinstance(colour, tuple) and len(colour) == 3: # get the icon for this colour from the cache: if colour not in self._step_swatch_icons: # build icon and add to cache: pm = QtGui.QPixmap(16, 16) pm.fill(QtCore.Qt.transparent) painter = QtGui.QPainter(pm) try: painter.setBrush( QtGui.QBrush( QtGui.QColor(colour[0], colour[1], colour[2]))) painter.setPen(QtCore.Qt.black) painter.drawRect(2, 2, 12, 12) finally: painter.end() self._step_swatch_icons[colour] = QtGui.QIcon(pm) # return the icon: return self._step_swatch_icons[colour] # just return the entity icon or the default icon if there is no entity icon: return self.get_entity_icon( sg_entity.get("type")) or self._default_icon
def create_overlayed_user_publish_thumbnail(publish_pixmap, user_pixmap): """ Creates a sqaure 75x75 thumbnail with an optional overlayed pixmap. """ # create a 100x100 base image base_image = QtGui.QPixmap(75, 75) base_image.fill(QtCore.Qt.transparent) painter = QtGui.QPainter(base_image) painter.setRenderHint(QtGui.QPainter.Antialiasing) # scale down the thumb if not publish_pixmap.isNull(): thumb_scaled = publish_pixmap.scaled( 75, 75, QtCore.Qt.KeepAspectRatioByExpanding, QtCore.Qt.SmoothTransformation) # now composite the thumbnail on top of the base image # bottom align it to make it look nice thumb_img = thumb_scaled.toImage() brush = QtGui.QBrush(thumb_img) painter.save() painter.setBrush(brush) painter.setPen(QtGui.QPen(QtCore.Qt.NoPen)) painter.drawRect(0, 0, 75, 75) painter.restore() if user_pixmap and not user_pixmap.isNull(): # overlay the user picture on top of the thumbnail user_scaled = user_pixmap.scaled( 30, 30, QtCore.Qt.KeepAspectRatioByExpanding, QtCore.Qt.SmoothTransformation) user_img = user_scaled.toImage() user_brush = QtGui.QBrush(user_img) painter.save() painter.translate(42, 42) painter.setBrush(user_brush) painter.setPen(QtGui.QPen(QtCore.Qt.NoPen)) painter.drawRect(0, 0, 30, 30) painter.restore() painter.end() return base_image
def create_overlayed_publish_thumbnail(image): """ Given a shotgun thumbnail, create a publish icon with the thumbnail composited onto a centered otherwise empty canvas. This will return a 512x400 pixmap object. :param image: QImage containing a thumbnail :returns: QPixmap with a 512x400 px image """ CANVAS_WIDTH = 512 CANVAS_HEIGHT = 400 CORNER_RADIUS = 10 # get the 512 base image base_image = QtGui.QPixmap(CANVAS_WIDTH, CANVAS_HEIGHT) base_image.fill(QtCore.Qt.transparent) # now attempt to load the image # pixmap will be a null pixmap if load fails thumb = QtGui.QPixmap.fromImage(image) if not thumb.isNull(): # scale it down to fit inside a frame of maximum 512x512 thumb_scaled = thumb.scaled(CANVAS_WIDTH, CANVAS_HEIGHT, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) # now composite the thumbnail on top of the base image # bottom align it to make it look nice thumb_img = thumb_scaled.toImage() brush = QtGui.QBrush(thumb_img) painter = QtGui.QPainter(base_image) painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setBrush(brush) # figure out the offsets in order to center the thumb height_difference = CANVAS_HEIGHT - thumb_scaled.height() width_difference = CANVAS_WIDTH - thumb_scaled.width() # center it horizontally inlay_offset_w = (width_difference / 2) + (CORNER_RADIUS / 2) # center it vertically inlay_offset_h = (height_difference / 2) + (CORNER_RADIUS / 2) # note how we have to compensate for the corner radius painter.translate(inlay_offset_w, inlay_offset_h) painter.drawRoundedRect(0, 0, thumb_scaled.width() - CORNER_RADIUS, thumb_scaled.height() - CORNER_RADIUS, CORNER_RADIUS, CORNER_RADIUS) painter.end() return base_image
def create_rectangular_thumbnail(thumb): """ Scale a given pixmap down to a given resolution :param thumb: pixmap to scale :returns: scaled thumbnail """ # TODO: this would be great to add to the qtwidgets framework CANVAS_WIDTH = 48 CANVAS_HEIGHT = 38 if thumb.isNull(): # to be safe, if thumb is null, use the empty/default thumbnail thumb = QtGui.QPixmap( ":/tk_framework_qtwidgets.global_search_widget/no_thumbnail.png" ) # get the 512 base image base_image = QtGui.QPixmap(CANVAS_WIDTH, CANVAS_HEIGHT) base_image.fill(QtCore.Qt.transparent) # scale it down to fit inside a frame of maximum 512x400 thumb_scaled = thumb.scaled( CANVAS_WIDTH, CANVAS_HEIGHT, QtCore.Qt.KeepAspectRatioByExpanding, QtCore.Qt.SmoothTransformation, ) # now composite the thumbnail on top of the base image # bottom align it to make it look nice thumb_img = thumb_scaled.toImage() brush = QtGui.QBrush(thumb_img) painter = QtGui.QPainter(base_image) painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setBrush(brush) # figure out the offset height wise in order to center the thumb height_difference = CANVAS_HEIGHT - thumb_scaled.height() width_difference = CANVAS_WIDTH - thumb_scaled.width() # center it with wise inlay_offset_w = width_difference / 2 # bottom height wise # inlay_offset_h = height_difference+CORNER_RADIUS inlay_offset_h = height_difference / 2 # note how we have to compensate for the corner radius painter.translate(inlay_offset_w, inlay_offset_h) painter.drawRect(0, 0, thumb_scaled.width(), thumb_scaled.height()) painter.end() return base_image
def clear_highlight(self): original_format = QtGui.QTextCharFormat() original_format.setBackground( QtGui.QBrush(QtGui.QColor(0, 0, 0), QtCore.Qt.NoBrush) ) cursor = self.__logs.textCursor() cursor.select(QtGui.QTextCursor.Document) cursor.mergeCharFormat(original_format) cursor.clearSelection() self.__logs.setTextCursor(cursor)
def highlight_current_line(self): """Highlight the current line of the input widget.""" extra_selection = QtGui.QTextEdit.ExtraSelection() extra_selection.format.setBackground( QtGui.QBrush(self._current_line_color())) extra_selection.format.setProperty( QtGui.QTextFormat.FullWidthSelection, True) extra_selection.cursor = self.textCursor() extra_selection.cursor.clearSelection() self.setExtraSelections([extra_selection])
def create_rectangular_512x400_thumbnail(image): """ Given a QImage shotgun thumbnail, create a rectangular icon with the thumbnail composited onto a centered otherwise empty canvas. This will return a 512x400 pixmap object. :param image: QImage source image :returns: QPixmap rectangular thumbnail on a 512x400 rect backdrop """ CANVAS_WIDTH = 512 CANVAS_HEIGHT = 400 CORNER_RADIUS = 10 # get the 512 base image base_image = QtGui.QPixmap(CANVAS_WIDTH, CANVAS_HEIGHT) base_image.fill(QtCore.Qt.transparent) # now attempt to load the image # pixmap will be a null pixmap if load fails thumb = QtGui.QPixmap.fromImage(image) if not thumb.isNull(): # scale it down to fit inside a frame of maximum 512x512 thumb_scaled = thumb.scaled( CANVAS_WIDTH, CANVAS_HEIGHT, QtCore.Qt.KeepAspectRatioByExpanding, QtCore.Qt.SmoothTransformation, ) # now composite the thumbnail on top of the base image # bottom align it to make it look nice thumb_img = thumb_scaled.toImage() brush = QtGui.QBrush(thumb_img) painter = QtGui.QPainter(base_image) painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setBrush(brush) painter.setPen(QtGui.QPen()) painter.drawRoundedRect( 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, CORNER_RADIUS, CORNER_RADIUS ) painter.end() return base_image
def __create_rounded_rect_thumbnail(image, canvas_width, canvas_height, radius): """ Given a qimage shotgun thumbnail, create a publish icon with the thumbnail composited onto a centered otherwise empty canvas. The thumbnail will be taking up all the space in the image. :param image: QImage to load thumbnail from :param canvas_width: Width of image to generate, in pixels :param canvas_height: Heiht of image to generate, in pixels :param radius: Corner radius of image to generate, in pixels :returns: QPixmap object """ # get the base image base_image = QtGui.QPixmap(canvas_width, canvas_height) base_image.fill(QtCore.Qt.transparent) # now attempt to load the image # pixmap will be a null pixmap if load fails thumb = QtGui.QPixmap.fromImage(image) if not thumb.isNull(): # scale it down to fit inside a frame thumb_scaled = thumb.scaled( canvas_width, canvas_height, QtCore.Qt.KeepAspectRatioByExpanding, QtCore.Qt.SmoothTransformation, ) # now composite the thumbnail on top of the base image # bottom align it to make it look nice thumb_img = thumb_scaled.toImage() brush = QtGui.QBrush(thumb_img) painter = QtGui.QPainter(base_image) painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setBrush(brush) painter.setPen(QtGui.QPen()) painter.drawRoundedRect(0, 0, canvas_width, canvas_height, radius, radius) painter.end() return base_image
def __format_thumbnail(self, pixmap_obj): """ Given a screengrab, create a thumbnail object, scaled to 96x75 px and with a subtle rounded frame. :param pixmap_obj: input screenshot :returns: 96x75px pixmap """ CANVAS_WIDTH = 96 CANVAS_HEIGHT = 75 CORNER_RADIUS = 6 # get the 512 base image base_image = QtGui.QPixmap(CANVAS_WIDTH, CANVAS_HEIGHT) base_image.fill(QtCore.Qt.transparent) # scale it down to fit inside a frame of maximum 512x512 thumb_scaled = pixmap_obj.scaled(CANVAS_WIDTH, CANVAS_HEIGHT, QtCore.Qt.KeepAspectRatioByExpanding, QtCore.Qt.SmoothTransformation) # now composite the thumbnail on top of the base image # bottom align it to make it look nice thumb_img = thumb_scaled.toImage() brush = QtGui.QBrush(thumb_img) painter = QtGui.QPainter(base_image) painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setBrush(brush) pen = QtGui.QPen(QtGui.QColor("#2C93E2")) pen.setWidth(3) painter.setPen(pen) # note how we have to compensate for the corner radius painter.drawRoundedRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, CORNER_RADIUS, CORNER_RADIUS) painter.end() return base_image
def paintEvent(self, paint_event): """ Paints the line plain text editor and adds a placeholder on bottom right corner when multiple values are detected. """ # If the box does not have focus, draw <multiple values> placeholder when self._show_placeholder is true, even if the widget has text if not self.hasFocus() and self._show_placeholder == True: p = QtGui.QPainter(self.viewport()) # right placeholder note in blue col = QtGui.QColor(24,167,227) # blue p.setPen(QtGui.QPen(col)) p.setBrush(QtGui.QBrush(col)) p.drawText(self.rect(),QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft, self._placeholder_text) else: QtGui.QPlainTextEdit.paintEvent(self, paint_event)
def paintEvent(self, event): """ Render the UI. """ if self._mode == self.MODE_OFF: return painter = QtGui.QPainter() painter.begin(self) try: # set up semi transparent backdrop painter.setRenderHint(QtGui.QPainter.Antialiasing) overlay_color = QtGui.QColor(30, 30, 30, 160) painter.setBrush( QtGui.QBrush(overlay_color)) painter.setPen(QtGui.QPen(overlay_color)) painter.drawRect(0, 0, painter.device().width(), painter.device().height()) finally: painter.end()
def paintEvent(self, paint_event): """ Paints the line plain text editor and adds a placeholder on bottom right corner when multiple values are detected. """ # If the box does not have focus, draw <multiple values> placeholder when self._show_placeholder is true, even if the widget has text if not self.hasFocus() and self._show_multiple_values is True: p = QtGui.QPainter(self.viewport()) # right placeholder note in blue col = QtGui.QColor(self._highlight) # blue p.setPen(QtGui.QPen(col)) p.setBrush(QtGui.QBrush(col)) p.drawText( self.rect(), QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft, self._multiple_values_text, ) else: super(PublishDescriptionEditBase, self).paintEvent(paint_event)
def find_all(self, pattern, logs): highlight_format = QtGui.QTextCharFormat() highlight_format.setBackground( QtGui.QBrush(QtGui.QColor(80, 80, 80)) ) regex = QtCore.QRegExp(pattern, QtCore.Qt.CaseInsensitive) matches = [] pos = 0 index = regex.indexIn(logs, pos) count = 0 while (index != -1): count += 1 matched_length = regex.matchedLength() # append start index and length of last matched string # length could be different matches.append((index, matched_length)) # select the matched text and apply the desired format self.highlight_one(index, matched_length, highlight_format) # Move to the next match pos = index + matched_length index = regex.indexIn(logs, pos) return matches
def paintEvent(self, event): """ Override the Qt method. Highlight the background color on mouse hover. """ super(ChoicesFilterItemWidget, self).paintEvent(event) option = QtGui.QStyleOption() option.initFrom(self) painter = QtGui.QPainter() painter.begin(self) try: if option.state & QtGui.QStyle.State_MouseOver: painter.setRenderHint(QtGui.QPainter.Antialiasing) hover_color = option.palette.highlight().color() painter.setBrush(QtGui.QBrush(hover_color)) painter.setPen(QtGui.QPen(hover_color)) painter.drawRect( 0, 0, painter.device().width(), painter.device().height() ) finally: painter.end()
def create_overlayed_folder_thumbnail(image): """ Given a shotgun thumbnail, create a folder icon with the thumbnail composited on top. This will return a 512x400 pixmap object. :param image: QImage containing a thumbnail :returns: QPixmap with a 512x400 px image """ # folder icon size CANVAS_WIDTH = 512 CANVAS_HEIGHT = 400 # corner radius when we draw CORNER_RADIUS = 10 # maximum sized canvas we can draw on *inside* the # folder icon graphic MAX_THUMB_WIDTH = 460 MAX_THUMB_HEIGHT = 280 # looks like there are some pyside related memory issues here relating to # referencing a resource and then operating on it. Just to be sure, make # make a full copy of the resource before starting to manipulate. base_image = QtGui.QPixmap(":/res/folder_512x400.png") # now attempt to load the image # pixmap will be a null pixmap if load fails thumb = QtGui.QPixmap.fromImage(image) if not thumb.isNull(): thumb_scaled = thumb.scaled(MAX_THUMB_WIDTH, MAX_THUMB_HEIGHT, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) # now composite the thumbnail thumb_img = thumb_scaled.toImage() brush = QtGui.QBrush(thumb_img) painter = QtGui.QPainter(base_image) painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setBrush(brush) # figure out the offset height wise in order to center the thumb height_difference = CANVAS_HEIGHT - thumb_scaled.height() width_difference = CANVAS_WIDTH - thumb_scaled.width() inlay_offset_w = (width_difference / 2) + (CORNER_RADIUS / 2) # add a 30 px offset here to push the image off center to # fit nicely inside the folder icon inlay_offset_h = (height_difference / 2) + (CORNER_RADIUS / 2) + 30 # note how we have to compensate for the corner radius painter.translate(inlay_offset_w, inlay_offset_h) painter.drawRoundedRect(0, 0, thumb_scaled.width() - CORNER_RADIUS, thumb_scaled.height() - CORNER_RADIUS, CORNER_RADIUS, CORNER_RADIUS) painter.end() return base_image
def create_round_512x400_note_thumbnail(image, client=False, unread=False): """ Given a QImage shotgun thumbnail, create a round icon with the thumbnail composited onto a centered otherwise empty canvas. This will return a 512x400 pixmap object. :param image: QImage source image :param client: indicates that this is a client note :param unread: indicates that this is an unread note :returns: QPixmap circular thumbnail, 380px wide, on a 512x400 rect backdrop """ CANVAS_WIDTH = 512 CANVAS_HEIGHT = 400 CIRCLE_SIZE = 380 # get the 512 base image base_image = QtGui.QPixmap(CANVAS_WIDTH, CANVAS_HEIGHT) base_image.fill(QtCore.Qt.transparent) # now attempt to load the image # pixmap will be a null pixmap if load fails thumb = QtGui.QPixmap.fromImage(image) if not thumb.isNull(): # scale it to fill a 400x400 square thumb_scaled = thumb.scaled( CIRCLE_SIZE, CIRCLE_SIZE, QtCore.Qt.KeepAspectRatioByExpanding, QtCore.Qt.SmoothTransformation, ) # now composite the thumbnail on top of the base image # bottom align it to make it look nice thumb_img = thumb_scaled.toImage() brush = QtGui.QBrush(thumb_img) painter = QtGui.QPainter(base_image) painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setBrush(brush) # figure out the offset height wise in order to center the thumb # center it inlay_offset_h = (CANVAS_HEIGHT - CIRCLE_SIZE) / 2 inlay_offset_w = (CANVAS_WIDTH - CIRCLE_SIZE) / 2 # note how we have to compensate for the corner radius painter.translate(inlay_offset_w, inlay_offset_h) painter.drawEllipse(0, 0, CIRCLE_SIZE, CIRCLE_SIZE) if unread: UNREAD_NOTE_INDICATOR = QtGui.QPixmap( ":/tk_multi_infopanel/unread_indicator.png" ) painter.drawPixmap(-10, -10, UNREAD_NOTE_INDICATOR) painter.translate(0, 250) if client: CLIENT_NOTE_INDICATOR = QtGui.QPixmap( ":/tk_multi_infopanel/client_note_indicator.png" ) painter.drawPixmap(0, 0, CLIENT_NOTE_INDICATOR) painter.end() return base_image