Repository: pyqtgraph/pyqtgraph

Issue:
GradientLegend broken in y-inverted viewbox
### Short description
If GradientLegend is placed in a ViewBox with inverted Y axis, the text is flipped vertically. If the y-axis is not inverted, then the text is upright but the rest of the item is upside-down. This changed was introduced in [5fa3901c0](https://github.com/pyqtgraph/pyqtgraph/commit/5fa3901c00f4ffb9cc9951d7cac4af02fb56a497). Prior to that, a similar issue was present, but only for viewboxes that were _not_ inverted (apparently this had only ever been used in y-inverted views, which is common when working with images).


### Code to reproduce
```
import pyqtgraph as pg
p1 = pg.plot(title='inverted')
l1 = pg.GradientLegend([25, 300], [-20, -30])
l1.pen = pg.mkPen(color='w', width=1, cosmetic=True)
p1.addItem(l1)
p1.invertY()
p2 = pg.plot(title='normal')
l2 = pg.GradientLegend([25, 300], [-20, -30])
l2.pen = pg.mkPen(color='w', width=1, cosmetic=True)
p2.addItem(l2)
```

### Expected behavior
item placement and visual appearance should be the same regardless of whether `p.invertY()` is called. The legend item should appear in the upper-right, and the max value (red) should be at the top.



Discussion:

Resolving patch:
diff --git a/pyqtgraph/colormap.py b/pyqtgraph/colormap.py
--- a/pyqtgraph/colormap.py
+++ b/pyqtgraph/colormap.py
@@ -104,7 +104,6 @@ def _getFromFile(name):
         else:
             csv_mode = False
         for line in fh:
-            name = None
             line = line.strip()
             if len(line) == 0: continue # empty line
             if line[0] == ';': continue # comment
diff --git a/pyqtgraph/graphicsItems/GradientLegend.py b/pyqtgraph/graphicsItems/GradientLegend.py
--- a/pyqtgraph/graphicsItems/GradientLegend.py
+++ b/pyqtgraph/graphicsItems/GradientLegend.py
@@ -15,17 +15,25 @@ def __init__(self, size, offset):
         self.offset = offset
         UIGraphicsItem.__init__(self)
         self.setAcceptedMouseButtons(QtCore.Qt.MouseButton.NoButton)
-        self.brush = QtGui.QBrush(QtGui.QColor(200,0,0))
+        self.brush = QtGui.QBrush(QtGui.QColor(255,255,255,100)) # background color
         self.pen = QtGui.QPen(QtGui.QColor(0,0,0))
+        self.textPen = QtGui.QPen(QtGui.QColor(0,0,0))
         self.labels = {'max': 1, 'min': 0}
         self.gradient = QtGui.QLinearGradient()
         self.gradient.setColorAt(0, QtGui.QColor(0,0,0))
         self.gradient.setColorAt(1, QtGui.QColor(255,0,0))
+        self.setZValue(100) # draw on top of ordinary plots
         
     def setGradient(self, g):
         self.gradient = g
         self.update()
         
+    def setColorMap(self, colormap):
+        """
+        Set displayed gradient from a :class:`~pyqtgraph.ColorMap` object.
+        """
+        self.gradient = colormap.getGradient()
+        
     def setIntColorScale(self, minVal, maxVal, *args, **kargs):
         colors = [fn.intColor(i, maxVal-minVal, *args, **kargs) for i in range(minVal, maxVal)]
         g = QtGui.QLinearGradient()
@@ -45,14 +53,15 @@ def setLabels(self, l):
         
     def paint(self, p, opt, widget):
         UIGraphicsItem.paint(self, p, opt, widget)
-        rect = self.boundingRect()   ## Boundaries of visible area in scene coords.
-        unit = self.pixelSize()       ## Size of one view pixel in scene coords.
-        if unit[0] is None:  
+
+        view = self.getViewBox()
+        if view is None:
             return
+        p.save() # save painter state before we change transformation
+        trans = view.sceneTransform()
+        p.setTransform( trans ) # draw in ViewBox pixel coordinates
+        rect = view.rect()
         
-        ## Have to scale painter so that text and gradients are correct size and not upside down
-        p.scale(unit[0], -unit[1])
-
         ## determine max width of all labels
         labelWidth = 0
         labelHeight = 0
@@ -63,10 +72,10 @@ def paint(self, p, opt, widget):
             
         textPadding = 2  # in px
         
-        xR = rect.right()  / unit[0]
-        xL = rect.left()   / unit[0]
-        yB = -(rect.top()    / unit[1])
-        yT = -(rect.bottom() / unit[1])
+        xR = rect.right()
+        xL = rect.left()
+        yT = rect.top()
+        yB = rect.bottom()
         
         # coordinates describe edges of text and bar, additional margins will be added for background
         if self.offset[0] < 0:
@@ -87,7 +96,7 @@ def paint(self, p, opt, widget):
 
         ## Draw background
         p.setPen(self.pen)
-        p.setBrush(QtGui.QBrush(QtGui.QColor(255,255,255,100)))
+        p.setBrush(self.brush) # background color        
         rect = QtCore.QRectF(
             QtCore.QPointF(x1 - textPadding, y1-labelHeight/2 - textPadding), # extra left/top padding 
             QtCore.QPointF(x3 + textPadding, y2+labelHeight/2 + textPadding)  # extra bottom/right padding
@@ -95,20 +104,22 @@ def paint(self, p, opt, widget):
         p.drawRect(rect)
 
         ## Draw color bar
-        self.gradient.setStart(0, y1)
-        self.gradient.setFinalStop(0, y2)
+        self.gradient.setStart(0, y2) 
+        self.gradient.setFinalStop(0, y1)
         p.setBrush(self.gradient)
         rect = QtCore.QRectF(
-            QtCore.QPointF(x1, y1), 
+            QtCore.QPointF(x1, y1),
             QtCore.QPointF(x2, y2)
         )
         p.drawRect(rect)
 
         ## draw labels
-        p.setPen(QtGui.QPen(QtGui.QColor(0,0,0)))
+        p.setPen(self.textPen)
         tx = x2 + 2 * textPadding # margin between bar and text
         lh = labelHeight
         lw = labelWidth
         for k in self.labels:
-            y = y1 + self.labels[k] * (y2-y1)
+            y = y2 - self.labels[k] * (y2-y1)
             p.drawText(QtCore.QRectF(tx, y - lh/2, lw, lh), QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignVCenter, str(k))
+
+        p.restore() # restore QPainter transform to original state


Test patch: