Skip to content

Commit

Permalink
Merge pull request #112 from chadmv/dpi-scaling
Browse files Browse the repository at this point in the history
Add delegate support for dpi scaling Fix #93
  • Loading branch information
mottosso authored Nov 13, 2020
2 parents 7c5d0ee + 3fb2d24 commit 5f8eacf
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 57 deletions.
154 changes: 99 additions & 55 deletions pyblish_lite/delegate.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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"]

Expand All @@ -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)

Expand All @@ -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()
Expand All @@ -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"])
Expand All @@ -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):
Expand All @@ -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())
Expand All @@ -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"])

Expand All @@ -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)

Expand All @@ -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"])
Expand All @@ -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)]
Expand All @@ -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)

Expand All @@ -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)
2 changes: 1 addition & 1 deletion pyblish_lite/version.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

VERSION_MAJOR = 0
VERSION_MINOR = 8
VERSION_PATCH = 6
VERSION_PATCH = 7


version_info = (VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH)
Expand Down
17 changes: 16 additions & 1 deletion pyblish_lite/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -60,6 +61,7 @@ def __init__(self, controller, parent=None):
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

self.controller = controller
self._delegates = []

"""General layout
__________________ _____________________
Expand Down Expand Up @@ -114,6 +116,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)
Expand All @@ -140,6 +143,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)
Expand All @@ -165,6 +169,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)
Expand Down Expand Up @@ -1062,3 +1067,13 @@ def heads_up(self, title, message, command=None):

# TODO(marcus): Implement this.
self.info(message)

def paintEvent(self, event):
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)

0 comments on commit 5f8eacf

Please sign in to comment.