From b53326b38c85d3c64db444a978b06c65bd23fde7 Mon Sep 17 00:00:00 2001 From: Vanuan Date: Wed, 29 Jul 2020 05:41:42 +0300 Subject: [PATCH] High DPI support: Scale Draft cursor to device pixel ratio --- src/Mod/Draft/draftguitools/gui_snapper.py | 53 +++++++++++++++++----- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/src/Mod/Draft/draftguitools/gui_snapper.py b/src/Mod/Draft/draftguitools/gui_snapper.py index 702e6ff19e..a480cda1f4 100644 --- a/src/Mod/Draft/draftguitools/gui_snapper.py +++ b/src/Mod/Draft/draftguitools/gui_snapper.py @@ -1111,6 +1111,44 @@ class Snapper: if self.dim2.Distance: self.dim2.on() + def get_cursor_size(self): + # TODO Unfortunately, there's no way to get the cursor size in Qt + # Either provide platform-specific implementation or make it a user preference + # This should be in device-independent pixels + return 32 + + def device_pixel_ratio(self): + device_pixel_ratio = 1 + mw = Gui.getMainWindow() + for w in mw.findChild(QtGui.QMdiArea).findChildren(QtGui.QWidget): + if w.metaObject().className() == "SIM::Coin3D::Quarter::QuarterWidget": + device_pixel_ratio = w.devicePixelRatio() + return device_pixel_ratio + + def get_cursor_with_tail(self, base_icon_name, tail_icon_name=None): + base_icon = QtGui.QPixmap(base_icon_name) + device_pixel_ratio = self.device_pixel_ratio() + full_icon_size = self.get_cursor_size() + new_icon_width = full_icon_size * device_pixel_ratio + new_icon_height = 0.75 * full_icon_size * device_pixel_ratio + new_icon = QtGui.QPixmap(new_icon_width, new_icon_height) + new_icon.fill(QtCore.Qt.transparent) + qp = QtGui.QPainter() + qp.begin(new_icon) + base_icon = base_icon.scaledToWidth(0.5 * full_icon_size * device_pixel_ratio) + qp.drawPixmap(0, 0, base_icon) + if tail_icon_name: + tail_icon_width = 0.5 * full_icon_size * device_pixel_ratio + tail_icon_x = 0.5 * full_icon_size * device_pixel_ratio + tail_icon_y = 0.25 * full_icon_size * device_pixel_ratio + tail_pixmap = QtGui.QPixmap(tail_icon_name).scaledToWidth(tail_icon_width) + qp.drawPixmap(QtCore.QPoint(tail_icon_x, tail_icon_y), tail_pixmap) + qp.end() + cur_hot_x = 0.25 * full_icon_size * device_pixel_ratio + cur_hot_y = 0.25 * full_icon_size * device_pixel_ratio + new_icon.setDevicePixelRatio(device_pixel_ratio) + cur = QtGui.QCursor(new_icon, cur_hot_x, cur_hot_y) + return cur def setCursor(self, mode=None): """Set or reset the cursor to the given mode or resets.""" @@ -1128,24 +1166,17 @@ class Snapper: self.cursorMode = None else: if mode != self.cursorMode: - baseicon = QtGui.QPixmap(":/icons/Draft_Cursor.svg") - newicon = QtGui.QPixmap(32, 24) - newicon.fill(QtCore.Qt.transparent) - qp = QtGui.QPainter() - qp.begin(newicon) - qp.drawPixmap(0, 0, baseicon) + base_icon_name = ":/icons/Draft_Cursor.svg" + tail_icon_name = None if not (mode == 'passive'): - tp = QtGui.QPixmap(self.cursors[mode]).scaledToWidth(16) - qp.drawPixmap(QtCore.QPoint(16, 8), tp) - qp.end() - cur = QtGui.QCursor(newicon, 8, 8) + tail_icon_name = self.cursors[mode] + cur = self.get_cursor_with_tail(base_icon_name, tail_icon_name) mw = Gui.getMainWindow() for w in mw.findChild(QtGui.QMdiArea).findChildren(QtGui.QWidget): if w.metaObject().className() == "SIM::Coin3D::Quarter::QuarterWidget": w.setCursor(cur) self.cursorMode = mode - def restack(self): """Lower the grid tracker so it doesn't obscure other objects.""" if self.grid: