From 56b8402b19dc614bfe3a4f956f64a81a11674741 Mon Sep 17 00:00:00 2001 From: Chad Vernon Date: Fri, 30 Oct 2020 09:46:07 -0700 Subject: [PATCH 1/3] Add support delegate for dpi scaling --- pyblish_lite/delegate.py | 154 +++++++++++++++++++++++++-------------- pyblish_lite/window.py | 10 +++ 2 files changed, 109 insertions(+), 55 deletions(-) diff --git a/pyblish_lite/delegate.py b/pyblish_lite/delegate.py index 7b47ffc..9f59c9f 100644 --- a/pyblish_lite/delegate.py +++ b/pyblish_lite/delegate.py @@ -45,7 +45,16 @@ } -class Item(QtWidgets.QStyledItemDelegate): +class DPIStyledItemDelegate(QtWidgets.QStyledItemDelegate): + def __init__(self, *args, **kwargs): + super(DPIStyledItemDelegate, self).__init__(*args, **kwargs) + self._dpi_scale = 1.0 + + def set_dpi_scale(self, scale): + self._dpi_scale = scale + + +class Item(DPIStyledItemDelegate): """Generic delegate for model items""" def paint(self, painter, option, index): @@ -59,7 +68,8 @@ def paint(self, painter, option, index): check_rect = QtCore.QRectF(body_rect) check_rect.setWidth(check_rect.height()) - check_rect.adjust(6, 6, -6, -6) + buffer = 6 * self._dpi_scale + check_rect.adjust(buffer, buffer, -buffer, -buffer) check_color = colors["idle"] @@ -78,27 +88,32 @@ def paint(self, painter, option, index): elif index.data(model.HasProcessed) is True: check_color = colors["ok"] + # Maintain reference to state, so we can restore it once we're done + painter.save() + painter.setFont(fonts["h4"]) metrics = painter.fontMetrics() - label_rect = QtCore.QRectF(option.rect.adjusted( - check_rect.width() + 12, 2, 0, -2)) + label_rect = QtCore.QRectF( + option.rect.adjusted( + check_rect.width() + 12 * self._dpi_scale, + 2 * self._dpi_scale, + 0, + -2 * self._dpi_scale, + ) + ) assert label_rect.width() > 0 label = index.data(model.Label) - label = metrics.elidedText(label, - QtCore.Qt.ElideRight, - label_rect.width() - 20) + label = metrics.elidedText( + label, QtCore.Qt.ElideRight, label_rect.width() - 20 * self._dpi_scale + ) font_color = colors["idle"] if not index.data(model.IsChecked): font_color = colors["inactive"] - # Maintain reference to state, so we can restore it once we're done - painter.save() - # Draw label - painter.setFont(fonts["h4"]) painter.setPen(QtGui.QPen(font_color)) painter.drawText(label_rect, label) @@ -118,8 +133,14 @@ def paint(self, painter, option, index): painter.setFont(fonts["smallAwesome"]) painter.setPen(QtGui.QPen(color)) - icon_rect = QtCore.QRectF(option.rect.adjusted( - label_rect.width() + 1, label_rect.height() / 3, 0, 0)) + icon_rect = QtCore.QRectF( + option.rect.adjusted( + label_rect.width() + 1 * self._dpi_scale, + label_rect.height() / (3 * self._dpi_scale), + 0, + 0, + ) + ) painter.drawText(icon_rect, icons["action"]) painter.restore() @@ -135,7 +156,7 @@ def paint(self, painter, option, index): painter.fillRect(check_rect, check_color) elif not index.data(model.IsIdle) and index.data(model.IsChecked): - painter.fillRect(check_rect, check_color) + painter.fillRect(check_rect, check_color) if option.state & QtWidgets.QStyle.State_MouseOver: painter.fillRect(body_rect, colors["hover"]) @@ -147,10 +168,10 @@ def paint(self, painter, option, index): painter.restore() def sizeHint(self, option, index): - return QtCore.QSize(option.rect.width(), 20) + return QtCore.QSize(option.rect.width(), 20 * self._dpi_scale) -class Artist(QtWidgets.QStyledItemDelegate): +class Artist(DPIStyledItemDelegate): """Delegate used on Artist page""" def paint(self, painter, option, index): @@ -163,30 +184,40 @@ def paint(self, painter, option, index): |_______|_____________________|___________| """ + # Maintain reference to state, so we can restore it once we're done + painter.save() # Layout - spacing = 10 - metrics = painter.fontMetrics() + spacing = 10 * self._dpi_scale - body_rect = QtCore.QRectF(option.rect).adjusted(2, 2, -8, -2) - content_rect = body_rect.adjusted(5, 5, -5, -5) + body_rect = QtCore.QRectF(option.rect).adjusted( + 2 * self._dpi_scale, + 2 * self._dpi_scale, + -8 * self._dpi_scale, + -2 * self._dpi_scale, + ) + buffer = 5 * self._dpi_scale + content_rect = body_rect.adjusted(buffer, buffer, -buffer, -buffer) toggle_rect = QtCore.QRectF(body_rect) - toggle_rect.setWidth(7) - toggle_rect.adjust(1, 1, 0, -1) + toggle_rect.setWidth(7 * self._dpi_scale) + toggle_rect.adjust( + 1 * self._dpi_scale, 1 * self._dpi_scale, 0, -1 * self._dpi_scale + ) icon_rect = QtCore.QRectF(content_rect) - icon_rect.translate(toggle_rect.width() + spacing, 3) - icon_rect.setWidth(35) - icon_rect.setHeight(35) + icon_rect.translate(toggle_rect.width() + spacing, 3 * self._dpi_scale) + icon_rect.setWidth(35 * self._dpi_scale) + icon_rect.setHeight(35 * self._dpi_scale) duration_rect = QtCore.QRectF(content_rect) duration_rect.translate(content_rect.width() - 50, 0) + label_font = fonts["h3"] + label_metrics = QtGui.QFontMetrics(label_font) label_rect = QtCore.QRectF(content_rect) - label_rect.translate(icon_rect.width() + - spacing, 0) - label_rect.setHeight(metrics.lineSpacing() + spacing) + label_rect.translate(icon_rect.width() + spacing, 0) + label_rect.setHeight(label_metrics.lineSpacing() + spacing) families_rect = QtCore.QRectF(label_rect) families_rect.translate(0, label_rect.height()) @@ -211,21 +242,20 @@ def paint(self, painter, option, index): families = ", ".join(index.data(model.Families)) # Elide - label = metrics.elidedText(label, - QtCore.Qt.ElideRight, - label_rect.width()) + label = label_metrics.elidedText( + label, QtCore.Qt.ElideRight, label_rect.width() + ) - families = metrics.elidedText(families, - QtCore.Qt.ElideRight, - label_rect.width()) + family_font = fonts["h5"] + family_metrics = QtGui.QFontMetrics(family_font) + families = family_metrics.elidedText( + families, QtCore.Qt.ElideRight, label_rect.width() + ) font_color = colors["idle"] if not index.data(model.IsChecked): font_color = colors["inactive"] - # Maintan reference to state, so we can restore it once we're done - painter.save() - # Draw background painter.fillRect(body_rect, colors["hover"]) @@ -234,11 +264,11 @@ def paint(self, painter, option, index): painter.drawText(icon_rect, icon) # Draw label - painter.setFont(fonts["h3"]) + painter.setFont(label_font) painter.drawText(label_rect, label) # Draw families - painter.setFont(fonts["h5"]) + painter.setFont(family_font) painter.setPen(QtGui.QPen(colors["inactive"])) painter.drawText(families_rect, families) @@ -253,7 +283,7 @@ def paint(self, painter, option, index): painter.fillRect(toggle_rect, check_color) elif not index.data(model.IsIdle) and index.data(model.IsChecked): - painter.fillRect(toggle_rect, check_color) + painter.fillRect(toggle_rect, check_color) if option.state & QtWidgets.QStyle.State_MouseOver: painter.fillRect(body_rect, colors["hover"]) @@ -268,18 +298,22 @@ def paint(self, painter, option, index): painter.restore() def sizeHint(self, option, index): - return QtCore.QSize(option.rect.width(), 80) + return QtCore.QSize(option.rect.width(), 80 * self._dpi_scale) -class Terminal(QtWidgets.QStyledItemDelegate): +class Terminal(DPIStyledItemDelegate): """Delegate used exclusively for the Terminal""" def paint(self, painter, option, index): """Paint text""" - icon_rect = QtCore.QRectF(option.rect).adjusted(3, 3, -3, -3) - icon_rect.setWidth(14) - icon_rect.setHeight(14) + buffer = 3 * self._dpi_scale + icon_rect = QtCore.QRectF(option.rect).adjusted( + buffer, buffer, -buffer, -buffer + ) + size = 14 * self._dpi_scale + icon_rect.setWidth(size) + icon_rect.setHeight(size) icon_color = colors["idle"] icon = icons[index.data(model.Type)] @@ -290,28 +324,38 @@ def paint(self, painter, option, index): elif index.data(model.Type) == "error": icon_color = colors["warning"] - metrics = painter.fontMetrics() - - label_rect = QtCore.QRectF(option.rect.adjusted( - icon_rect.width() + 12, 2, 0, -2)) + label_rect = QtCore.QRectF( + option.rect.adjusted( + icon_rect.width() + 12 * self._dpi_scale, + 2 * self._dpi_scale, + 0, + -2 * self._dpi_scale, + ) + ) assert label_rect.width() > 0 + label_font = fonts["h4"] + label_metrics = QtGui.QFontMetrics(label_font) label = index.data(model.Label) - label = metrics.elidedText(label, - QtCore.Qt.ElideRight, - label_rect.width() - 20) + label = label_metrics.elidedText( + label, QtCore.Qt.ElideRight, label_rect.width() - 20 * self._dpi_scale + ) font_color = colors["idle"] hover = QtGui.QPainterPath() - hover.addRect(QtCore.QRectF(option.rect).adjusted(0, 0, -1, -1)) + hover.addRect( + QtCore.QRectF(option.rect).adjusted( + 0, 0, -1 * self._dpi_scale, -1 * self._dpi_scale + ) + ) # Maintain reference to state, so we can restore it once we're done painter.save() # Draw label - painter.setFont(fonts["h4"]) + painter.setFont(label_font) painter.setPen(QtGui.QPen(font_color)) painter.drawText(label_rect, label) @@ -330,4 +374,4 @@ def paint(self, painter, option, index): painter.restore() def sizeHint(self, option, index): - return QtCore.QSize(option.rect.width(), 20) + return QtCore.QSize(option.rect.width(), 20 * self._dpi_scale) diff --git a/pyblish_lite/window.py b/pyblish_lite/window.py index af503ea..791f777 100644 --- a/pyblish_lite/window.py +++ b/pyblish_lite/window.py @@ -60,6 +60,7 @@ def __init__(self, controller, parent=None): self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.controller = controller + self._delegates = [] """General layout __________________ _____________________ @@ -114,6 +115,7 @@ def __init__(self, controller, parent=None): artist_delegate = delegate.Artist() artist_view.setItemDelegate(artist_delegate) + self._delegates.append(artist_delegate) layout = QtWidgets.QVBoxLayout(artist_page) layout.addWidget(artist_view) @@ -140,6 +142,7 @@ def __init__(self, controller, parent=None): item_delegate = delegate.Item() left_view.setItemDelegate(item_delegate) right_view.setItemDelegate(item_delegate) + self._delegates.append(item_delegate) layout = QtWidgets.QHBoxLayout(overview_page) layout.addWidget(left_view, 1) @@ -165,6 +168,7 @@ def __init__(self, controller, parent=None): terminal_delegate = delegate.Terminal() terminal_view = view.LogView() terminal_view.setItemDelegate(terminal_delegate) + self._delegates.append(terminal_delegate) layout = QtWidgets.QVBoxLayout(terminal_container) layout.addWidget(terminal_view) @@ -1062,3 +1066,9 @@ def heads_up(self, title, message, command=None): # TODO(marcus): Implement this. self.info(message) + + def paintEvent(self, event): + scale = self.windowHandle().screen().logicalDotsPerInch() / 96.0 + for delegate in self._delegates: + delegate.set_dpi_scale(scale) + super(Window, self).paintEvent(event) From b8a11c08ebe91d07cdd083581c256472c6fb1984 Mon Sep 17 00:00:00 2001 From: Chad Vernon Date: Thu, 12 Nov 2020 13:46:07 -0800 Subject: [PATCH 2/3] Fix pyblish/pyblish-lite#93 Limit scaling adjustment to Qt5 and Windows since only tested in Windows --- pyblish_lite/window.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pyblish_lite/window.py b/pyblish_lite/window.py index 791f777..da50267 100644 --- a/pyblish_lite/window.py +++ b/pyblish_lite/window.py @@ -40,11 +40,12 @@ """ from functools import partial +import os from . import delegate, model, settings, util, view from .awesome import tags as awesome -from .vendor.Qt import QtCore, QtGui, QtWidgets +from .vendor.Qt import QtCore, QtGui, QtWidgets, Qt class Window(QtWidgets.QDialog): @@ -1068,7 +1069,11 @@ def heads_up(self, title, message, command=None): self.info(message) def paintEvent(self, event): - scale = self.windowHandle().screen().logicalDotsPerInch() / 96.0 + if Qt.__qt_version__.startswith("5") and os.name == "nt": + # Only tested with Windows DPI scaling + scale = self.windowHandle().screen().logicalDotsPerInch() / 96.0 + else: + scale = 1.0 for delegate in self._delegates: delegate.set_dpi_scale(scale) super(Window, self).paintEvent(event) From 3fb2d24be19a3f7d6ce258b72ff9bcb31cd5eaff Mon Sep 17 00:00:00 2001 From: Marcus Ottosson Date: Fri, 13 Nov 2020 07:47:00 +0000 Subject: [PATCH 3/3] Update version.py --- pyblish_lite/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyblish_lite/version.py b/pyblish_lite/version.py index 663335d..ca660b2 100644 --- a/pyblish_lite/version.py +++ b/pyblish_lite/version.py @@ -1,7 +1,7 @@ VERSION_MAJOR = 0 VERSION_MINOR = 8 -VERSION_PATCH = 6 +VERSION_PATCH = 7 version_info = (VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH)