def _context_menu_button_rect(self, option, index): anchor = option.rect.bottomRight() margins = QMargins(3, 3, 3, 3) rect = QRect(0, 0, 30, 30) rect.moveBottomRight(anchor) self._context_menu_button_rects[index] = rect return rect.marginsRemoved(margins)
def sizeHint(self, option, index): msg = index.model().data(index, Qt.DisplayRole) field = QRect(option.rect) field.setWidth(variables.window_width - variables.WINDOW_PADDING) field = field.marginsRemoved(variables.TEXT_PADDING) doc = QTextDocument(msg.text) doc.setDocumentMargin(0) opt = QTextOption() opt.setWrapMode(opt.WrapAtWordBoundaryOrAnywhere) doc.setDefaultTextOption(opt) doc.setDefaultFont(variables.font) if msg.user == variables.USER_ME: doc.setTextWidth(field.size().width() - 20 - 50) else: doc.setTextWidth(field.size().width() - 20) field.setHeight(int(doc.size().height())) field.setWidth(int(doc.idealWidth())) field = field.marginsAdded(variables.TEXT_PADDING) return QSize(0, field.size().height())
def paint(self, painter, option, index): msg = index.model().data(index, Qt.DisplayRole) field = QRect(option.rect) field = field.marginsRemoved(variables.TEXT_PADDING) doc = QTextDocument(msg.text) doc.setDocumentMargin(0) opt = QTextOption() opt.setWrapMode(opt.WrapAtWordBoundaryOrAnywhere) doc.setDefaultTextOption(opt) doc.setDefaultFont(variables.font) if msg.user == variables.USER_ME: doc.setTextWidth(field.size().width() - 20 - 50) else: doc.setTextWidth(field.size().width() - 20) field.setHeight(int(doc.size().height())) field.setWidth(int(doc.idealWidth())) field = field.marginsAdded(variables.TEXT_PADDING) line_height = QFontMetrics(variables.font).lineSpacing( ) + variables.TEXT_PADDING.bottom() - variables.BUBBLE_PADDING.bottom( ) + variables.TEXT_PADDING.top() - variables.BUBBLE_PADDING.top() if msg.user == variables.USER_ME: rect = QRect(option.rect.right() - field.size().width() - 20, option.rect.top(), field.size().width(), field.size().height()) else: rect = QRect(20, option.rect.top(), field.size().width(), field.size().height()) bubblerect = rect.marginsRemoved(variables.BUBBLE_PADDING) textrect = rect.marginsRemoved(variables.TEXT_PADDING) if msg.user == variables.USER_ME: p1 = bubblerect.topRight() p2 = bubblerect.bottomLeft() + QPoint(-36, -int(line_height / 2)) else: p1 = bubblerect.topLeft() painter.setRenderHint(QPainter.Antialiasing) painter.setPen(Qt.NoPen) color = QColor(variables.BUBBLE_COLORS[msg.user]) painter.setBrush(color) painter.drawRoundedRect(bubblerect, 10, 10) painter.drawPolygon(p1 + QPoint(-20, 0), p1 + QPoint(20, 0), p1 + QPoint(0, 15)) if msg.user == variables.USER_ME: if msg.status == variables.STATUS_UNREAD: painter.setPen(Qt.NoPen) painter.setBrush(QColor(variables.STATUS_COLOR)) painter.drawEllipse(p2, 7, 7) elif msg.status == variables.STATUS_UNDELIVERED: pen = QPen(QColor(variables.STATUS_COLOR)) pen.setWidth(2) painter.setPen(pen) painter.setBrush(Qt.NoBrush) painter.drawEllipse(p2, 7, 7) painter.drawLine(p2, p2 + QPoint(0, -5)) painter.drawLine(p2, p2 + QPoint(3, 0)) painter.setPen(Qt.gray) painter.setFont(variables.font) painter.translate(textrect.x(), textrect.y()) textrectf = QRectF(textrect) textrectf.moveTo(0, 0) doc.drawContents(painter, textrectf) painter.translate(-textrect.x(), -textrect.y())
def paint(self, painter, option, index): dlg = index.model().data(index, Qt.DisplayRole) painter.setRenderHint(QPainter.Antialiasing) color = QColor(Qt.white) if option.state & QStyle.State_MouseOver: color = QColor(variables.HIGHLIGHT_COLOR) painter.setPen(QPen(color)) painter.setBrush(QBrush(color)) painter.drawRect(option.rect) painter.setPen(Qt.black) painter.setBrush(Qt.NoBrush) painter.drawLine(option.rect.bottomLeft(), option.rect.bottomRight()) doc = QTextDocument(dlg.ip) doc.setDocumentMargin(0) doc.setDefaultFont(variables.font) textrect = QRect(option.rect) textrect = textrect.marginsRemoved(variables.IP_PADDING) textrect.setHeight(int(doc.size().height())) textrect.setWidth(int(doc.size().width())) offset = textrect.marginsAdded(variables.IP_PADDING).height() painter.setPen(Qt.black) painter.setFont(variables.font) painter.translate(textrect.x(), textrect.y()) textrectf = QRectF(textrect) textrectf.moveTo(0, 0) doc.drawContents(painter, textrectf) painter.translate(-textrect.x(), -textrect.y()) string = "" if dlg.user == variables.USER_ME: string += "You: " print(dlg.msg) string += dlg.msg fm = QFontMetrics(variables.font_small) textrect = QRect(option.rect) textrect.moveTop(textrect.y() + offset) textrect = textrect.marginsRemoved(variables.MSG_PADDING) textrect.setHeight(fm.lineSpacing()) spainter = QStylePainter(painter.device(), QWidget()) spainter.setRenderHint(QPainter.Antialiasing) if fm.horizontalAdvance(string) > textrect.width(): fade = QLinearGradient(variables.MSG_PADDING.left() + textrect.width()* 0.9, 0, variables.MSG_PADDING.left() + textrect.width(), 0) fade.setSpread(QGradient.PadSpread) fade.setColorAt(0, Qt.darkGray) fade.setColorAt(1, color) pal = QPalette() pal.setBrush(QPalette.Text, QBrush(fade)) spainter.setFont(variables.font_small) spainter.drawItemText(textrect, Qt.TextSingleLine, pal, True, string, QPalette.Text) else: spainter.setPen(Qt.darkGray) spainter.setFont(variables.font_small) spainter.drawText(textrect, Qt.TextSingleLine, string) p1 = textrect.bottomRight() + QPoint(36, -int(textrect.height() / 2)) if dlg.status == variables.STATUS_UNREAD: spainter.setPen(Qt.NoPen) spainter.setBrush(QColor(variables.STATUS_COLOR)) spainter.drawEllipse(p1, 7, 7) elif dlg.status == variables.STATUS_UNDELIVERED: pen = QPen(QColor(variables.STATUS_COLOR)) pen.setWidth(2) spainter.setPen(pen) spainter.setBrush(Qt.NoBrush) spainter.drawEllipse(p1, 7, 7) spainter.drawLine(p1, p1 + QPoint(0, -5)) spainter.drawLine(p1, p1 + QPoint(3, 0)) elif dlg.status == variables.STATUS_NEW: pen = QPen(QColor(variables.STATUS_NEW_COLOR)) pen.setWidth(5) spainter.setPen(pen) spainter.setBrush(Qt.NoBrush) spainter.drawEllipse(p1, 7, 7) #painter.translate(-textrect.x(), -textrect.y()) '''doc = QTextDocument(str)
class FileItemRenderer: def __init__(self, item): self.fileinfo = item.fileinfo self.icon = item.icon self.thumbnail = item._get_thumbnail() self._item_style = item.file_view._mode._item_style self.level_of_detail = item.file_view._mode._level_of_detail self.style = item.file_view._style self.zoom_index = item.file_view._mode._zoom_index self.tile_rect = item.tile_rect self.hovering = item.hovering self.animation_timer = item.animation_timer self.new = item._new self.crop_thumbnails = item.file_view._crop_thumbnails self.is_selected = item.isSelected() self.is_cursor = item.file_view._cursor_item == item self.thumbnail_rect: QRect = QRect(0, 0, item.tile_rect.width(), item.tile_rect.width()) def render(self, painter: QPainter) -> None: if self._item_style == FileItemStyle.SMALLICON: self.paint_smallicon_view(painter) elif self._item_style == FileItemStyle.DETAIL: self.paint_detail_view(painter) else: self.paint(painter) if self.is_selected: painter.save() painter.setCompositionMode(QPainter.CompositionMode_SourceOver) painter.setOpacity(0.5) painter.fillRect(self.tile_rect, QColor(127, 192, 255)) painter.setCompositionMode(QPainter.CompositionMode_SourceOver) painter.setOpacity(1.0) painter.setPen(QColor(96, 127, 255)) painter.setBrush(Qt.NoBrush) painter.drawRect(self.tile_rect) painter.restore() if self.is_cursor: painter.setOpacity(1.0) painter.setPen(QColor(0, 0, 0)) painter.setBrush(QColor(255, 255, 255, 96)) painter.drawRect(self.tile_rect) def paint_smallicon_view(self, painter: QPainter) -> None: self.thumbnail_rect = QRect(0, 0, self.tile_rect.height(), self.tile_rect.height()) font = self.style.font fm = self.style.fm painter.setFont(font) self.paint_thumbnail(painter) if self.zoom_index in [0, 1]: text_option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) text_rect = QRect( QPoint(self.tile_rect.height() + 4, 0), QPoint(self.tile_rect.width(), self.tile_rect.height())) text = self.fileinfo.basename() text = fm.elidedText(text, Qt.ElideRight, text_rect.width()) painter.drawText(QRectF(text_rect), text, text_option) elif self.zoom_index in [2]: text_rect = QRect( QPoint(self.tile_rect.height() + 4, 0), QPoint(self.tile_rect.width() - 80, self.tile_rect.height())) text = self.fileinfo.basename() text = fm.elidedText(text, Qt.ElideRight, text_rect.width()) text_option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) painter.drawText(QRectF(text_rect), text, text_option) text_rect = QRect( QPoint(self.tile_rect.width() - 80, 0), QPoint(self.tile_rect.width(), self.tile_rect.height())) text = bytefmt.humanize(self.fileinfo.size()) text = fm.elidedText(text, Qt.ElideRight, text_rect.width()) text_option = QTextOption(Qt.AlignRight | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) painter.setPen(QColor(96, 96, 96)) painter.drawText(QRectF(text_rect), text, text_option) else: top_left_text, top_right_text, bottom_left_text, bottom_right = self.make_text( ) row1_rect = QRect( QPoint(self.tile_rect.left() + self.tile_rect.height() + 8, self.tile_rect.top()), QPoint(self.tile_rect.right() - 8, self.tile_rect.top() + self.tile_rect.height() / 2)) row2_rect = QRect( QPoint(self.tile_rect.left() + self.tile_rect.height() + 8, self.tile_rect.top() + self.tile_rect.height() / 2), QPoint(self.tile_rect.right() - 8, self.tile_rect.bottom())) # row 1 text_rect = QRect( QPoint(row1_rect.left(), row1_rect.top()), QPoint(row1_rect.right() - 80, row1_rect.bottom())) text = self.fileinfo.basename() text = fm.elidedText(text, Qt.ElideRight, text_rect.width()) text_option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) painter.drawText(QRectF(text_rect), text, text_option) text_rect = QRect(QPoint(row1_rect.left() - 80, row1_rect.top()), QPoint(row1_rect.right(), row1_rect.bottom())) text = bytefmt.humanize(self.fileinfo.size()) text = fm.elidedText(text, Qt.ElideRight, text_rect.width()) text_option = QTextOption(Qt.AlignRight | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) painter.setPen(QColor(96, 96, 96)) painter.drawText(QRectF(text_rect), text, text_option) # row 2 text_rect = QRect( QPoint(row2_rect.left(), row2_rect.top()), QPoint(row2_rect.right() - 80, row2_rect.bottom())) text = bottom_left_text text = fm.elidedText(text, Qt.ElideRight, text_rect.width()) text_option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) painter.drawText(QRectF(text_rect), text, text_option) text_rect = QRect(QPoint(row2_rect.left() - 80, row2_rect.top()), QPoint(row2_rect.right(), row2_rect.bottom())) text = top_left_text text = fm.elidedText(text, Qt.ElideRight, text_rect.width()) text_option = QTextOption(Qt.AlignRight | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) painter.setPen(QColor(96, 96, 96)) painter.drawText(QRectF(text_rect), text, text_option) def paint_detail_view(self, painter: QPainter) -> None: self.thumbnail_rect = QRect(0, 0, self.tile_rect.height(), self.tile_rect.height()) self.paint_thumbnail(painter) lst = ( [self.fileinfo.basename(), bytefmt.humanize(self.fileinfo.size())] + list(self.make_text())) text_option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) total_width = self.tile_rect.width() - self.thumbnail_rect.width() - 8 widths = [60, 10, 10, 10, 10, 10] x = self.thumbnail_rect.width() + 4 for idx, text in enumerate(lst[:-1]): if idx != 0: text_option.setAlignment(Qt.AlignRight | Qt.AlignVCenter) width = total_width * (widths[idx] / 100) painter.drawText(QRectF(x, 0, width, self.tile_rect.height()), text, text_option) x += width def paint(self, painter: QPainter) -> None: self.paint_text_items(painter) self.paint_thumbnail(painter) if self.hovering and self.animation_timer is None: if not self.fileinfo.isdir() and not self.fileinfo.is_archive(): painter.setCompositionMode(QPainter.CompositionMode_Overlay) painter.setOpacity(0.75) self.paint_thumbnail(painter) painter.setOpacity(1.0) painter.setCompositionMode(QPainter.CompositionMode_SourceOver) if self.level_of_detail > 1: self.paint_metadata(painter) self.paint_overlay(painter) def paint_text_items(self, painter: QPainter) -> None: # text items if self.level_of_detail > 0: self.paint_text_item(painter, 0, self.fileinfo.basename()) if self.level_of_detail > 2: painter.setPen(QColor(96, 96, 96)) self.paint_text_item(painter, 1, bytefmt.humanize(self.fileinfo.size())) if self.level_of_detail > 3: dt = datetime.fromtimestamp(self.fileinfo.mtime()) painter.setPen(QColor(96, 96, 96)) self.paint_text_item(painter, 2, dt.strftime("%F %T")) def paint_text_item(self, painter: QPainter, row: int, text: str) -> None: font = self.style.font fm = self.style.fm tmp = text target_width = self.tile_rect.width() if fm.width(tmp) > target_width: while fm.width(tmp + "…") > target_width: tmp = tmp[0:-1] if tmp != text: text = tmp + "…" painter.setFont(font) k = [0, 1, 1, 2, 3][self.level_of_detail] painter.drawText(self.tile_rect.width() / 2 - fm.width(text) / 2, self.tile_rect.height() - 2 + 16 * row - 16 * k + 14, text) def paint_thumbnail(self, painter: QPainter) -> None: thumbnail = self.thumbnail if thumbnail.status == ThumbnailStatus.INITIAL: self.paint_icon(painter, self.icon) elif thumbnail.status == ThumbnailStatus.LOADING: self.paint_icon(painter, self.icon) elif thumbnail.status == ThumbnailStatus.THUMBNAIL_UNAVAILABLE: self.paint_icon(painter, self.icon) elif thumbnail.status == ThumbnailStatus.THUMBNAIL_ERROR: self.paint_icon(painter, self.icon) elif thumbnail.status == ThumbnailStatus.THUMBNAIL_READY: pixmap = thumbnail.get_pixmap() assert pixmap is not None if not self.crop_thumbnails: rect = make_scaled_rect(pixmap.width(), pixmap.height(), self.thumbnail_rect.width(), self.thumbnail_rect.width()) painter.drawPixmap(rect, pixmap) else: srcrect = make_cropped_rect(pixmap.width(), pixmap.height(), self.thumbnail_rect.width(), self.thumbnail_rect.width()) painter.drawPixmap(self.thumbnail_rect, pixmap, srcrect) if (self.fileinfo.is_archive() or self.fileinfo.isdir()) and not self.hovering: self.paint_icon(painter, self.icon) def make_text(self): metadata = self.fileinfo.metadata() top_left_text = "" top_right_text = "" bottom_left_text = "" bottom_right_text = "" if 'duration' in metadata: hours, minutes, seconds = split_duration(metadata['duration']) top_left_text = "{:d}:{:02d}:{:02d}".format( hours, minutes, seconds) if 'pages' in metadata: top_left_text = "{:d} pages".format(metadata['pages']) if 'file_count' in metadata: top_left_text = "{:d} files".format(metadata['file_count']) if 'framerate' in metadata: top_right_text = "{:g}fps".format(metadata['framerate']) if 'width' in metadata and 'height' in metadata: bottom_left_text = "{}x{}".format(metadata['width'], metadata['height']) return (top_left_text, top_right_text, bottom_left_text, bottom_right_text) def paint_metadata(self, painter: QPainter) -> None: font = self.style.font fm = self.style.fm painter.setFont(font) if self.new: painter.drawPixmap(QRect(2, 2, 24, 24), self.style.shared_pixmaps.new) if "type" in self.fileinfo.metadata() and self.fileinfo.metadata( )["type"] == "error": painter.drawPixmap(QRect(2, 2, 24, 24), self.style.shared_pixmaps.error) top_left_text, top_right_text, bottom_left_text, bottom_right = self.make_text( ) if top_left_text: w = fm.width(top_left_text) painter.setPen(Qt.NoPen) painter.setBrush(QColor(255, 255, 255, 160)) painter.drawRect(0, 0, w + 4, 16) painter.setPen(QColor(0, 0, 0)) painter.drawText(2, 12, top_left_text) if top_right_text: w = fm.width(top_right_text) painter.setPen(Qt.NoPen) painter.setBrush(QColor(255, 255, 255, 160)) painter.drawRect(self.thumbnail_rect.width() - w - 4, 0, w + 4, 16) painter.setPen(QColor(0, 0, 0)) painter.drawText(self.thumbnail_rect.width() - w - 2, 12, top_right_text) if bottom_left_text: w = fm.width(bottom_left_text) painter.setPen(Qt.NoPen) painter.setBrush(QColor(255, 255, 255, 160)) painter.drawRect(0, self.thumbnail_rect.height() - 16, w + 4, 16) painter.setPen(QColor(0, 0, 0)) painter.drawText(2, self.thumbnail_rect.height() - 4, bottom_left_text) if self.fileinfo.is_video(): painter.setOpacity(0.5) # painter.setCompositionMode(QPainter.CompositionMode_Plus) painter.drawPixmap( QRect(self.thumbnail_rect.width() - 24 - 2, self.thumbnail_rect.height() - 24 - 2, 24, 24), self.style.shared_pixmaps.video) painter.setOpacity(1.0) elif self.fileinfo.is_image(): painter.setOpacity(0.5) # painter.setCompositionMode(QPainter.CompositionMode_Plus) painter.drawPixmap( QRect(self.thumbnail_rect.width() - 24 - 2, self.thumbnail_rect.height() - 24 - 2, 24, 24), self.style.shared_pixmaps.image) painter.setOpacity(1.0) def paint_overlay(self, painter: QPainter) -> None: if self.fileinfo.have_access() is False: painter.setOpacity(0.5) m = int(self.thumbnail_rect.width() * 0.125) painter.drawPixmap( self.thumbnail_rect.marginsRemoved(QMargins(m, m, m, m)), self.style.shared_pixmaps.locked) painter.setOpacity(1.0) thumbnail = self.thumbnail if thumbnail.status == ThumbnailStatus.LOADING or thumbnail.status == ThumbnailStatus.INITIAL: painter.setOpacity(0.5) painter.drawPixmap( QRect(self.thumbnail_rect.width() - 32, 2, 32, 32), self.style.shared_pixmaps.loading) painter.setOpacity(1.0) elif thumbnail.status == ThumbnailStatus.THUMBNAIL_ERROR: self.paint_icon(painter, self.style.shared_icons.image_error) def paint_tiny_icon(self, painter: QPainter, icon: QIcon) -> None: painter.setOpacity(0.5) icon.paint(painter, QRect(self.tile_rect.width() - 48, 0, 48, 48)) def paint_icon(self, painter: QPainter, icon: QIcon) -> None: if self._item_style == FileItemStyle.ICON: rect = make_unscaled_rect(self.thumbnail_rect.width() * 3 // 4, self.thumbnail_rect.width() * 3 // 4, self.thumbnail_rect.width(), self.thumbnail_rect.height()) else: rect = make_unscaled_rect(self.thumbnail_rect.width(), self.thumbnail_rect.height(), self.thumbnail_rect.width(), self.thumbnail_rect.height()) if self.fileinfo.isdir() or self.fileinfo.is_archive(): scalable = self.style.shared_scalable( self.thumbnail_rect.width(), self.thumbnail_rect.height(), ) pixmap = scalable.load_icon_icon(icon, outline=True) painter.fillRect(self.thumbnail_rect, QBrush(QColor(255, 255, 255, 160))) painter.drawPixmap(0, 0, pixmap) else: icon.paint(painter, rect)
class FileItemRenderer: def __init__(self, item): self.fileinfo = item.fileinfo self.icon = item.icon self.thumbnail = item._get_thumbnail() self._item_style = item.file_view._mode._item_style self.level_of_detail = item.file_view._mode._level_of_detail self.style = item.file_view._style self.zoom_index = item.file_view._mode._zoom_index self.tile_rect = item.tile_rect self.hovering = item.hovering self.animation_timer = item.animation_timer self.new = item._new self.crop_thumbnails = item.file_view._crop_thumbnails self.is_selected = item.isSelected() self.is_cursor = item.file_view._cursor_item == item self.thumbnail_rect: QRect = QRect(0, 0, item.tile_rect.width(), item.tile_rect.width()) def render(self, painter: QPainter) -> None: if self._item_style == FileItemStyle.SMALLICON: self.paint_smallicon_view(painter) elif self._item_style == FileItemStyle.DETAIL: self.paint_detail_view(painter) else: self.paint(painter) if self.is_selected: painter.save() painter.setCompositionMode(QPainter.CompositionMode_SourceOver) painter.setOpacity(0.5) painter.fillRect(self.tile_rect, QColor(127, 192, 255)) painter.setCompositionMode(QPainter.CompositionMode_SourceOver) painter.setOpacity(1.0) painter.setPen(QColor(96, 127, 255)) painter.setBrush(Qt.NoBrush) painter.drawRect(self.tile_rect) painter.restore() if self.is_cursor: painter.setOpacity(1.0) painter.setPen(QColor(0, 0, 0)) painter.setBrush(QColor(255, 255, 255, 96)) painter.drawRect(self.tile_rect) def paint_smallicon_view(self, painter: QPainter) -> None: self.thumbnail_rect = QRect(0, 0, self.tile_rect.height(), self.tile_rect.height()) font = self.style.font fm = self.style.fm painter.setFont(font) self.paint_thumbnail(painter) if self.zoom_index in [0, 1]: text_option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) text_rect = QRect(QPoint(self.tile_rect.height() + 4, 0), QPoint(self.tile_rect.width(), self.tile_rect.height())) text = self.fileinfo.basename() text = fm.elidedText(text, Qt.ElideRight, text_rect.width()) painter.drawText(QRectF(text_rect), text, text_option) elif self.zoom_index in [2]: text_rect = QRect(QPoint(self.tile_rect.height() + 4, 0), QPoint(self.tile_rect.width() - 80, self.tile_rect.height())) text = self.fileinfo.basename() text = fm.elidedText(text, Qt.ElideRight, text_rect.width()) text_option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) painter.drawText(QRectF(text_rect), text, text_option) text_rect = QRect(QPoint(self.tile_rect.width() - 80, 0), QPoint(self.tile_rect.width(), self.tile_rect.height())) text = bytefmt.humanize(self.fileinfo.size()) text = fm.elidedText(text, Qt.ElideRight, text_rect.width()) text_option = QTextOption(Qt.AlignRight | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) painter.setPen(QColor(96, 96, 96)) painter.drawText(QRectF(text_rect), text, text_option) else: top_left_text, top_right_text, bottom_left_text, bottom_right = self.make_text() row1_rect = QRect(QPoint(self.tile_rect.left() + self.tile_rect.height() + 8, self.tile_rect.top()), QPoint(self.tile_rect.right() - 8, self.tile_rect.top() + self.tile_rect.height() / 2)) row2_rect = QRect(QPoint(self.tile_rect.left() + self.tile_rect.height() + 8, self.tile_rect.top() + self.tile_rect.height() / 2), QPoint(self.tile_rect.right() - 8, self.tile_rect.bottom())) # row 1 text_rect = QRect(QPoint(row1_rect.left(), row1_rect.top()), QPoint(row1_rect.right() - 80, row1_rect.bottom())) text = self.fileinfo.basename() text = fm.elidedText(text, Qt.ElideRight, text_rect.width()) text_option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) painter.drawText(QRectF(text_rect), text, text_option) text_rect = QRect(QPoint(row1_rect.left() - 80, row1_rect.top()), QPoint(row1_rect.right(), row1_rect.bottom())) text = bytefmt.humanize(self.fileinfo.size()) text = fm.elidedText(text, Qt.ElideRight, text_rect.width()) text_option = QTextOption(Qt.AlignRight | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) painter.setPen(QColor(96, 96, 96)) painter.drawText(QRectF(text_rect), text, text_option) # row 2 text_rect = QRect(QPoint(row2_rect.left(), row2_rect.top()), QPoint(row2_rect.right() - 80, row2_rect.bottom())) text = bottom_left_text text = fm.elidedText(text, Qt.ElideRight, text_rect.width()) text_option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) painter.drawText(QRectF(text_rect), text, text_option) text_rect = QRect(QPoint(row2_rect.left() - 80, row2_rect.top()), QPoint(row2_rect.right(), row2_rect.bottom())) text = top_left_text text = fm.elidedText(text, Qt.ElideRight, text_rect.width()) text_option = QTextOption(Qt.AlignRight | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) painter.setPen(QColor(96, 96, 96)) painter.drawText(QRectF(text_rect), text, text_option) def paint_detail_view(self, painter: QPainter) -> None: self.thumbnail_rect = QRect(0, 0, self.tile_rect.height(), self.tile_rect.height()) self.paint_thumbnail(painter) lst = ([self.fileinfo.basename(), bytefmt.humanize(self.fileinfo.size())] + list(self.make_text())) text_option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter) text_option.setWrapMode(QTextOption.NoWrap) total_width = self.tile_rect.width() - self.thumbnail_rect.width() - 8 widths = [60, 10, 10, 10, 10, 10] x = self.thumbnail_rect.width() + 4 for idx, text in enumerate(lst[:-1]): if idx != 0: text_option.setAlignment(Qt.AlignRight | Qt.AlignVCenter) width = total_width * (widths[idx] / 100) painter.drawText(QRectF(x, 0, width, self.tile_rect.height()), text, text_option) x += width def paint(self, painter: QPainter) -> None: self.paint_text_items(painter) self.paint_thumbnail(painter) if self.hovering and self.animation_timer is None: if not self.fileinfo.isdir() and not self.fileinfo.is_archive(): painter.setCompositionMode(QPainter.CompositionMode_Overlay) painter.setOpacity(0.75) self.paint_thumbnail(painter) painter.setOpacity(1.0) painter.setCompositionMode(QPainter.CompositionMode_SourceOver) if self.level_of_detail > 1: self.paint_metadata(painter) self.paint_overlay(painter) def paint_text_items(self, painter: QPainter) -> None: # text items if self.level_of_detail > 0: self.paint_text_item(painter, 0, self.fileinfo.basename()) if self.level_of_detail > 2: painter.setPen(QColor(96, 96, 96)) self.paint_text_item(painter, 1, bytefmt.humanize(self.fileinfo.size())) if self.level_of_detail > 3: dt = datetime.fromtimestamp(self.fileinfo.mtime()) painter.setPen(QColor(96, 96, 96)) self.paint_text_item(painter, 2, dt.strftime("%F %T")) def paint_text_item(self, painter: QPainter, row: int, text: str) -> None: font = self.style.font fm = self.style.fm tmp = text target_width = self.tile_rect.width() if fm.width(tmp) > target_width: while fm.width(tmp + "…") > target_width: tmp = tmp[0:-1] if tmp != text: text = tmp + "…" painter.setFont(font) k = [0, 1, 1, 2, 3][self.level_of_detail] painter.drawText(self.tile_rect.width() / 2 - fm.width(text) / 2, self.tile_rect.height() - 2 + 16 * row - 16 * k + 14, text) def paint_thumbnail(self, painter: QPainter) -> None: thumbnail = self.thumbnail if thumbnail.status == ThumbnailStatus.INITIAL: self.paint_icon(painter, self.icon) elif thumbnail.status == ThumbnailStatus.LOADING: self.paint_icon(painter, self.icon) elif thumbnail.status == ThumbnailStatus.THUMBNAIL_UNAVAILABLE: self.paint_icon(painter, self.icon) elif thumbnail.status == ThumbnailStatus.THUMBNAIL_ERROR: self.paint_icon(painter, self.icon) elif thumbnail.status == ThumbnailStatus.THUMBNAIL_READY: pixmap = thumbnail.get_pixmap() assert pixmap is not None if not self.crop_thumbnails: rect = make_scaled_rect(pixmap.width(), pixmap.height(), self.thumbnail_rect.width(), self.thumbnail_rect.width()) painter.drawPixmap(rect, pixmap) else: srcrect = make_cropped_rect(pixmap.width(), pixmap.height(), self.thumbnail_rect.width(), self.thumbnail_rect.width()) painter.drawPixmap(self.thumbnail_rect, pixmap, srcrect) if (self.fileinfo.is_archive() or self.fileinfo.isdir()) and not self.hovering: self.paint_icon(painter, self.icon) def make_text(self): metadata = self.fileinfo.metadata() top_left_text = "" top_right_text = "" bottom_left_text = "" bottom_right_text = "" if 'duration' in metadata: hours, minutes, seconds = split_duration(metadata['duration']) top_left_text = "{:d}:{:02d}:{:02d}".format(hours, minutes, seconds) if 'pages' in metadata: top_left_text = "{:d} pages".format(metadata['pages']) if 'file_count' in metadata: top_left_text = "{:d} files".format(metadata['file_count']) if 'framerate' in metadata: top_right_text = "{:g}fps".format(metadata['framerate']) if 'width' in metadata and 'height' in metadata: bottom_left_text = "{}x{}".format(metadata['width'], metadata['height']) return (top_left_text, top_right_text, bottom_left_text, bottom_right_text) def paint_metadata(self, painter: QPainter) -> None: font = self.style.font fm = self.style.fm painter.setFont(font) if self.new: painter.drawPixmap(QRect(2, 2, 24, 24), self.style.shared_pixmaps.new) if "type" in self.fileinfo.metadata() and self.fileinfo.metadata()["type"] == "error": painter.drawPixmap(QRect(2, 2, 24, 24), self.style.shared_pixmaps.error) top_left_text, top_right_text, bottom_left_text, bottom_right = self.make_text() if top_left_text: w = fm.width(top_left_text) painter.setPen(Qt.NoPen) painter.setBrush(QColor(255, 255, 255, 160)) painter.drawRect(0, 0, w + 4, 16) painter.setPen(QColor(0, 0, 0)) painter.drawText(2, 12, top_left_text) if top_right_text: w = fm.width(top_right_text) painter.setPen(Qt.NoPen) painter.setBrush(QColor(255, 255, 255, 160)) painter.drawRect(self.thumbnail_rect.width() - w - 4, 0, w + 4, 16) painter.setPen(QColor(0, 0, 0)) painter.drawText(self.thumbnail_rect.width() - w - 2, 12, top_right_text) if bottom_left_text: w = fm.width(bottom_left_text) painter.setPen(Qt.NoPen) painter.setBrush(QColor(255, 255, 255, 160)) painter.drawRect(0, self.thumbnail_rect.height() - 16, w + 4, 16) painter.setPen(QColor(0, 0, 0)) painter.drawText(2, self.thumbnail_rect.height() - 4, bottom_left_text) if self.fileinfo.is_video(): painter.setOpacity(0.5) # painter.setCompositionMode(QPainter.CompositionMode_Plus) painter.drawPixmap(QRect(self.thumbnail_rect.width() - 24 - 2, self.thumbnail_rect.height() - 24 - 2, 24, 24), self.style.shared_pixmaps.video) painter.setOpacity(1.0) elif self.fileinfo.is_image(): painter.setOpacity(0.5) # painter.setCompositionMode(QPainter.CompositionMode_Plus) painter.drawPixmap(QRect(self.thumbnail_rect.width() - 24 - 2, self.thumbnail_rect.height() - 24 - 2, 24, 24), self.style.shared_pixmaps.image) painter.setOpacity(1.0) def paint_overlay(self, painter: QPainter) -> None: if self.fileinfo.have_access() is False: painter.setOpacity(0.5) m = int(self.thumbnail_rect.width() * 0.125) painter.drawPixmap(self.thumbnail_rect.marginsRemoved(QMargins(m, m, m, m)), self.style.shared_pixmaps.locked) painter.setOpacity(1.0) thumbnail = self.thumbnail if thumbnail.status == ThumbnailStatus.LOADING or thumbnail.status == ThumbnailStatus.INITIAL: painter.setOpacity(0.5) painter.drawPixmap(QRect(self.thumbnail_rect.width() - 32, 2, 32, 32), self.style.shared_pixmaps.loading) painter.setOpacity(1.0) elif thumbnail.status == ThumbnailStatus.THUMBNAIL_ERROR: self.paint_icon(painter, self.style.shared_icons.image_error) def paint_tiny_icon(self, painter: QPainter, icon: QIcon) -> None: painter.setOpacity(0.5) icon.paint(painter, QRect(self.tile_rect.width() - 48, 0, 48, 48)) def paint_icon(self, painter: QPainter, icon: QIcon) -> None: if self._item_style == FileItemStyle.ICON: rect = make_unscaled_rect(self.thumbnail_rect.width() * 3 // 4, self.thumbnail_rect.width() * 3 // 4, self.thumbnail_rect.width(), self.thumbnail_rect.height()) else: rect = make_unscaled_rect(self.thumbnail_rect.width(), self.thumbnail_rect.height(), self.thumbnail_rect.width(), self.thumbnail_rect.height()) if self.fileinfo.isdir() or self.fileinfo.is_archive(): scalable = self.style.shared_scalable(self.thumbnail_rect.width(), self.thumbnail_rect.height(),) pixmap = scalable.load_icon_icon(icon, outline=True) painter.fillRect(self.thumbnail_rect, QBrush(QColor(255, 255, 255, 160))) painter.drawPixmap(0, 0, pixmap) else: icon.paint(painter, rect)