Repository: spyder-ide/spyder

Issue:
High DPI scaling messes up placement of breakpoint red circles
## The breakpoint red circle is drawn between two lines instead of on the relevant line when high DPI scaling is on.

**What steps will reproduce the problem?**

1. Use 4K or other high DPI monitor with scaling turned on (may be unnecessary, I don't have an old one to test right now?)
2. In general preferences, check "Enable high DPI scaling"
3. Restart Spyder to enable high DPI scaling
3. Place a breakpoint in a file

**What is the expected output? What do you see instead?**
The red circle should be nicely centered on the line with the intended breakpoint.  Instead the circle is drawn about half a line high and it is unclear which line it corresponds to.  Further, trying to turn it off often accidentally leads to turning another one on, but offset from the line you intended.

The breakpoint shown below is intended to be on line 8 with the command "pass", but shows up between lines 7 and 8.
![breakpoint](https://user-images.githubusercontent.com/10837851/28094703-073e769c-6653-11e7-8deb-dab800ccd57f.png)

Note, that turning off the scaling fixes the alignment, but then you are stuck with really small icons and circles.
![breakpoint2](https://user-images.githubusercontent.com/10837851/28094812-ceb264ea-6653-11e7-80d6-e45857fb7fa4.png)


**Please provide any additional information below**

## Versions and main components

* Spyder Version: 3.1.4.dev0
* Python Version: 3.6.1
* Qt Version: 5.8.0
* PyQt Version: 5.8.1
* Operating system: Windows 10


## Dependencies

jedi >=0.9.0     :  0.10.0 (OK)
matplotlib >=1.0 :  2.0.0 (OK)
nbconvert >=4.0  :  5.1.1 (OK)
numpy >=1.7      :  1.11.3 (OK)
pandas >=0.13.1  :  0.19.2 (OK)
pep8 >=0.6       :  1.7.0 (OK)
pyflakes >=0.6.0 :  1.5.0 (OK)
pygments >=2.0   :  2.2.0 (OK)
pylint >=0.25    :  1.6.5 (OK)
qtconsole >=4.2.0:  4.2.1 (OK)
rope >=0.9.4     :  0.9.4-1 (OK)
sphinx >=0.6.6   :  1.5.2 (OK)
sympy >=0.7.3    :  1.0 (OK)




Discussion:
As I'm looking at this more, I noticed that it also happens for things like the orange exclamation triangle for code analysis issues.
Thanks for reporting. We'll at this one after we release Spyder 3.2

Resolving patch:
diff --git a/spyder/widgets/sourcecode/codeeditor.py b/spyder/widgets/sourcecode/codeeditor.py
--- a/spyder/widgets/sourcecode/codeeditor.py
+++ b/spyder/widgets/sourcecode/codeeditor.py
@@ -27,7 +27,7 @@
 import time
 
 # Third party imports
-from qtpy import is_pyqt46
+from qtpy import is_pyqt46, QT_VERSION
 from qtpy.compat import to_qvariant
 from qtpy.QtCore import QRect, QRegExp, QSize, Qt, QTimer, Signal, Slot
 from qtpy.QtGui import (QBrush, QColor, QCursor, QFont, QIntValidator,
@@ -52,6 +52,7 @@
 from spyder.utils import syntaxhighlighters as sh
 from spyder.utils import encoding, sourcecode
 from spyder.utils.dochelpers import getobj
+from spyder.utils.programs import check_version
 from spyder.utils.qthelpers import add_actions, create_action, mimedata2url
 from spyder.utils.sourcecode import ALL_LANGUAGES, CELL_LANGUAGES
 from spyder.widgets.editortools import PythonCFM
@@ -68,6 +69,7 @@
 # For debugging purpose:
 LOG_FILENAME = get_conf_path('codeeditor.log')
 DEBUG_EDITOR = DEBUG >= 3
+QT55_VERSION = check_version(QT_VERSION, "5.5", ">=")
 
 
 def is_letter_or_number(char):
@@ -1179,7 +1181,12 @@ def linenumberarea_paint_event(self, event):
         active_line_number = active_block.blockNumber() + 1
 
         def draw_pixmap(ytop, pixmap):
-            painter.drawPixmap(0, ytop + (font_height-pixmap.height()) / 2,
+            if not QT55_VERSION:
+                pixmap_height = pixmap.height()
+            else:
+                # scale pixmap height to device independent pixels
+                pixmap_height = pixmap.height() / pixmap.devicePixelRatio()
+            painter.drawPixmap(0, ytop + (font_height-pixmap_height) / 2,
                                pixmap)
 
         for top, line_number, block in self.visible_blocks:


Test patch: