We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
an issue on ViewBox.mapToView
Hi, I do love pyqtgraph, it really save my life, but there is a little problem in it. 

At first start of pg.GraphicsWindow, it seems that ViewBox return (0, 0) size by ViewBox.rect() method, which lead to ViewBox.updateMatrix get 0 size of bound and so that functions.invertQTransform fail.

one of the ways to work around it is mannually resize the Window by setFixedSize() or adjustSize().

For example, I post the cross hair example of pyqtgraph below for illustration. 
### Short description
<!-- This should summarize the issue. -->
GraphicsWindow.addPlot doesn't initialize correct ViewBox size, which lead to exception when use ViewBox.mapToView.
My tricky is just resize GraphicsWindow by adjustSize() method, and it does work.

### Code to reproduce

```
"""
Demonstrates some customized mouse interaction by drawing a crosshair that follows
the mouse.
"""

#import initExample ## Add path to library (just for examples; you do not need this)
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph.Point import Point



#generate layout
app = QtGui.QApplication([])
#app = QtGui.QApplication()
#win = pg.GraphicsLayoutWidget(show=True)
#win = pg.GraphicsLayoutWidget(show=True, parent=None)

win = pg.GraphicsWindow()    # Using GraphicsWindow so can I run the file on PyCharm
win.setWindowTitle('pyqtgraph example: crosshair')

label = pg.LabelItem(justify='right')
win.addItem(label)

p1 = win.addPlot(row=1, col=0)
p2 = win.addPlot(row=2, col=0)

region = pg.LinearRegionItem()
region.setZValue(10)
#Add the LinearRegionItem to the ViewBox, but tell the ViewBox to exclude this
#item when doing auto-range calculations.

p2.addItem(region, ignoreBounds=True)

#pg.dbg()
'''
Set whether automatic range uses only visible data when determining the range to show.
'''
#p1.setAutoVisible(x=False, y=False)


#create numpy arrays
#make the numbers large to show that the xrange shows data from 10000 to all the way 0
data1 = 10000 + 15000 * pg.gaussianFilter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000)
data2 = 15000 + 15000 * pg.gaussianFilter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000)

p1.plot(data1, pen="r")
p1.plot(data2, pen="g")

p2.plot(data1, pen="w")

'''*********The Issue*********'''
#win.adjustSize()    # my trick, please decomment the line and the program would work out

print(p1.getViewBox().size())               # ->PyQt5.QtCore.QSizeF()
print(p1.getViewBox().viewPixelSize())      # exception raised due to empty viewBox size
'''*********The Issue*********'''

def update():
    region.setZValue(10)
    minX, maxX = region.getRegion()
    p1.setXRange(minX, maxX, padding=0)


region.sigRegionChanged.connect(update)

def updateRegion(window, viewRange):
    rgn = viewRange[0]
    region.setRegion(rgn)


p1.sigRangeChanged.connect(updateRegion)



region.setRegion([1000, 2000])

#cross hair
vLine = pg.InfiniteLine(angle=90, movable=False)
hLine = pg.InfiniteLine(angle=0, movable=False)
p1.addItem(vLine, ignoreBounds=True)
p1.addItem(hLine, ignoreBounds=True)


vb = p1.vb




def mouseMoved(evt):
    #print(evt)

    pos = evt[0]  #using signal proxy turns original arguments into a tuple
    print(pos)

    if p1.sceneBoundingRect().contains(pos):
        mousePoint = vb.mapSceneToView(pos)
        print(mousePoint)
        index = int(mousePoint.x())
        if index > 0 and index < len(data1):
            label.setText("<span style='font-size: 12pt'>x=%0.1f,   <span style='color: red'>y1=%0.1f</span>,   <span style='color: green'>y2=%0.1f</span>" % (mousePoint.x(), data1[index], data2[index]))
        vLine.setPos(mousePoint.x())
        hLine.setPos(mousePoint.y())



proxy = pg.SignalProxy(p1.scene().sigMouseMoved, rateLimit=60, slot=mouseMoved)
#p1.scene().sigMouseMoved.connect(mouseMoved)

##Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()
```

### Expected behavior
p1.getViewBox().viewPixelSize() should work

### Real behavior
but it raises an exception

```
Traceback (most recent call last):
  File "C:/Users/Lee King Batchelor/Desktop/PythonExcel4Securities/pyqtgraph/CrossHair.py", line 86, in <module>
    print(p1.getViewBox().viewPixelSize())      # exception raised due to empty viewBox size
  File "C:\Anaconda3\envs\pyqtgraph\lib\site-packages\pyqtgraph\graphicsItems\ViewBox\ViewBox.py", line 1176, in viewPixelSize
    o = self.mapToView(Point(0,0))
  File "C:\Anaconda3\envs\pyqtgraph\lib\site-packages\pyqtgraph\graphicsItems\ViewBox\ViewBox.py", line 1142, in mapToView
    m = fn.invertQTransform(self.childTransform())
  File "C:\Anaconda3\envs\pyqtgraph\lib\site-packages\pyqtgraph\functions.py", line 2199, in invertQTransform
    inv = numpy.linalg.inv(arr)
  File "<__array_function__ internals>", line 6, in inv
  File "C:\Anaconda3\envs\pyqtgraph\lib\site-packages\numpy\linalg\linalg.py", line 547, in inv
    ainv = _umath_linalg.inv(a, signature=signature, extobj=extobj)
  File "C:\Anaconda3\envs\pyqtgraph\lib\site-packages\numpy\linalg\linalg.py", line 97, in _raise_linalgerror_singular
    raise LinAlgError("Singular matrix")
numpy.linalg.LinAlgError: Singular matrix
```

### Tested environment(s)

 * PyQtGraph version: 0.1 and 0.11 dev0
 * Qt Python binding:PyQt5.9.2 and PySide2 5.13.1
 * Python version: 3.7
 * NumPy version: 1.8.1
 * Operating system: Win 10
 * Installation method: pip and system package
### Additional context


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pyqtgraph/graphicsItems/GraphicsLayout.py`
Content:
```
1 from ..Qt import QtGui, QtCore
2 from .. import functions as fn
3 from .GraphicsWidget import GraphicsWidget
4 ## Must be imported at the end to avoid cyclic-dependency hell:
5 from .ViewBox import ViewBox
6 from .PlotItem import PlotItem
7 from .LabelItem import LabelItem
8 
9 __all__ = ['GraphicsLayout']
10 class GraphicsLayout(GraphicsWidget):
11     """
12     Used for laying out GraphicsWidgets in a grid.
13     This is usually created automatically as part of a :class:`GraphicsWindow <pyqtgraph.GraphicsWindow>` or :class:`GraphicsLayoutWidget <pyqtgraph.GraphicsLayoutWidget>`.
14     """
15 
16 
17     def __init__(self, parent=None, border=None):
18         GraphicsWidget.__init__(self, parent)
19         if border is True:
20             border = (100,100,100)
21         self.border = border
22         self.layout = QtGui.QGraphicsGridLayout()
23         self.setLayout(self.layout)
24         self.items = {}  ## item: [(row, col), (row, col), ...]  lists all cells occupied by the item
25         self.rows = {}   ## row: {col1: item1, col2: item2, ...}    maps cell location to item
26         self.itemBorders = {}  ## {item1: QtGui.QGraphicsRectItem, ...} border rects
27         self.currentRow = 0
28         self.currentCol = 0
29         self.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding))
30     
31     #def resizeEvent(self, ev):
32         #ret = GraphicsWidget.resizeEvent(self, ev)
33         #print self.pos(), self.mapToDevice(self.rect().topLeft())
34         #return ret
35 
36     def setBorder(self, *args, **kwds):
37         """
38         Set the pen used to draw border between cells.
39         
40         See :func:`mkPen <pyqtgraph.mkPen>` for arguments.        
41         """
42         self.border = fn.mkPen(*args, **kwds)
43 
44         for borderRect in self.itemBorders.values():
45             borderRect.setPen(self.border)
46 
47     def nextRow(self):
48         """Advance to next row for automatic item placement"""
49         self.currentRow += 1
50         self.currentCol = -1
51         self.nextColumn()
52         
53     def nextColumn(self):
54         """Advance to next available column
55         (generally only for internal use--called by addItem)"""
56         self.currentCol += 1
57         while self.getItem(self.currentRow, self.currentCol) is not None:
58             self.currentCol += 1
59         
60     def nextCol(self, *args, **kargs):
61         """Alias of nextColumn"""
62         return self.nextColumn(*args, **kargs)
63         
64     def addPlot(self, row=None, col=None, rowspan=1, colspan=1, **kargs):
65         """
66         Create a PlotItem and place it in the next available cell (or in the cell specified)
67         All extra keyword arguments are passed to :func:`PlotItem.__init__ <pyqtgraph.PlotItem.__init__>`
68         Returns the created item.
69         """
70         plot = PlotItem(**kargs)
71         self.addItem(plot, row, col, rowspan, colspan)
72         return plot
73         
74     def addViewBox(self, row=None, col=None, rowspan=1, colspan=1, **kargs):
75         """
76         Create a ViewBox and place it in the next available cell (or in the cell specified)
77         All extra keyword arguments are passed to :func:`ViewBox.__init__ <pyqtgraph.ViewBox.__init__>`
78         Returns the created item.
79         """
80         vb = ViewBox(**kargs)
81         self.addItem(vb, row, col, rowspan, colspan)
82         return vb
83         
84     def addLabel(self, text=' ', row=None, col=None, rowspan=1, colspan=1, **kargs):
85         """
86         Create a LabelItem with *text* and place it in the next available cell (or in the cell specified)
87         All extra keyword arguments are passed to :func:`LabelItem.__init__ <pyqtgraph.LabelItem.__init__>`
88         Returns the created item.
89         
90         To create a vertical label, use *angle* = -90.
91         """
92         text = LabelItem(text, **kargs)
93         self.addItem(text, row, col, rowspan, colspan)
94         return text
95         
96     def addLayout(self, row=None, col=None, rowspan=1, colspan=1, **kargs):
97         """
98         Create an empty GraphicsLayout and place it in the next available cell (or in the cell specified)
99         All extra keyword arguments are passed to :func:`GraphicsLayout.__init__ <pyqtgraph.GraphicsLayout.__init__>`
100         Returns the created item.
101         """
102         layout = GraphicsLayout(**kargs)
103         self.addItem(layout, row, col, rowspan, colspan)
104         return layout
105         
106     def addItem(self, item, row=None, col=None, rowspan=1, colspan=1):
107         """
108         Add an item to the layout and place it in the next available cell (or in the cell specified).
109         The item must be an instance of a QGraphicsWidget subclass.
110         """
111         if row is None:
112             row = self.currentRow
113         if col is None:
114             col = self.currentCol
115             
116         self.items[item] = []
117         for i in range(rowspan):
118             for j in range(colspan):
119                 row2 = row + i
120                 col2 = col + j
121                 if row2 not in self.rows:
122                     self.rows[row2] = {}
123                 self.rows[row2][col2] = item
124                 self.items[item].append((row2, col2))
125 
126         borderRect = QtGui.QGraphicsRectItem()
127 
128         borderRect.setParentItem(self)
129         borderRect.setZValue(1e3)
130         borderRect.setPen(fn.mkPen(self.border))
131 
132         self.itemBorders[item] = borderRect
133 
134         item.geometryChanged.connect(self._updateItemBorder)
135 
136         self.layout.addItem(item, row, col, rowspan, colspan)
137         self.nextColumn()
138 
139     def getItem(self, row, col):
140         """Return the item in (*row*, *col*). If the cell is empty, return None."""
141         return self.rows.get(row, {}).get(col, None)
142 
143     def boundingRect(self):
144         return self.rect()
145 
146     def itemIndex(self, item):
147         for i in range(self.layout.count()):
148             if self.layout.itemAt(i).graphicsItem() is item:
149                 return i
150         raise Exception("Could not determine index of item " + str(item))
151     
152     def removeItem(self, item):
153         """Remove *item* from the layout."""
154         ind = self.itemIndex(item)
155         self.layout.removeAt(ind)
156         self.scene().removeItem(item)
157         
158         for r, c in self.items[item]:
159             del self.rows[r][c]
160         del self.items[item]
161 
162         item.geometryChanged.disconnect(self._updateItemBorder)
163         del self.itemBorders[item]
164 
165         self.update()
166     
167     def clear(self):
168         for i in list(self.items.keys()):
169             self.removeItem(i)
170         self.currentRow = 0
171         self.currentCol = 0
172 
173     def setContentsMargins(self, *args):
174         # Wrap calls to layout. This should happen automatically, but there
175         # seems to be a Qt bug:
176         # http://stackoverflow.com/questions/27092164/margins-in-pyqtgraphs-graphicslayout
177         self.layout.setContentsMargins(*args)
178 
179     def setSpacing(self, *args):
180         self.layout.setSpacing(*args)
181 
182     def _updateItemBorder(self):
183         if self.border is None:
184             return
185 
186         item = self.sender()
187         if item is None:
188             return
189 
190         r = item.mapRectToParent(item.boundingRect())
191         self.itemBorders[item].setRect(r)
192
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pyqtgraph/graphicsItems/GraphicsLayout.py b/pyqtgraph/graphicsItems/GraphicsLayout.py
--- a/pyqtgraph/graphicsItems/GraphicsLayout.py
+++ b/pyqtgraph/graphicsItems/GraphicsLayout.py
@@ -134,6 +134,9 @@
         item.geometryChanged.connect(self._updateItemBorder)
 
         self.layout.addItem(item, row, col, rowspan, colspan)
+        self.layout.activate() # Update layout, recalculating bounds.
+                               # Allows some PyQtGraph features to also work without Qt event loop.
+        
         self.nextColumn()
 
     def getItem(self, row, col):

{"golden_diff": "diff --git a/pyqtgraph/graphicsItems/GraphicsLayout.py b/pyqtgraph/graphicsItems/GraphicsLayout.py\n--- a/pyqtgraph/graphicsItems/GraphicsLayout.py\n+++ b/pyqtgraph/graphicsItems/GraphicsLayout.py\n@@ -134,6 +134,9 @@\n         item.geometryChanged.connect(self._updateItemBorder)\n \n         self.layout.addItem(item, row, col, rowspan, colspan)\n+        self.layout.activate() # Update layout, recalculating bounds.\n+                               # Allows some PyQtGraph features to also work without Qt event loop.\n+        \n         self.nextColumn()\n \n     def getItem(self, row, col):\n", "issue": "an issue on ViewBox.mapToView\nHi, I do love pyqtgraph, it really save my life, but there is a little problem in it. \r\n\r\nAt first start of pg.GraphicsWindow, it seems that ViewBox return (0, 0) size by ViewBox.rect() method, which lead to ViewBox.updateMatrix get 0 size of bound and so that functions.invertQTransform fail.\r\n\r\none of the ways to work around it is mannually resize the Window by setFixedSize() or adjustSize().\r\n\r\nFor example, I post the cross hair example of pyqtgraph below for illustration. \r\n### Short description\r\n<!-- This should summarize the issue. -->\r\nGraphicsWindow.addPlot doesn't initialize correct ViewBox size, which lead to exception when use ViewBox.mapToView.\r\nMy tricky is just resize GraphicsWindow by adjustSize() method, and it does work.\r\n\r\n### Code to reproduce\r\n\r\n```\r\n\"\"\"\r\nDemonstrates some customized mouse interaction by drawing a crosshair that follows\r\nthe mouse.\r\n\"\"\"\r\n\r\n#import initExample ## Add path to library (just for examples; you do not need this)\r\nimport numpy as np\r\nimport pyqtgraph as pg\r\nfrom pyqtgraph.Qt import QtGui, QtCore\r\nfrom pyqtgraph.Point import Point\r\n\r\n\r\n\r\n#generate layout\r\napp = QtGui.QApplication([])\r\n#app = QtGui.QApplication()\r\n#win = pg.GraphicsLayoutWidget(show=True)\r\n#win = pg.GraphicsLayoutWidget(show=True, parent=None)\r\n\r\nwin = pg.GraphicsWindow()    # Using GraphicsWindow so can I run the file on PyCharm\r\nwin.setWindowTitle('pyqtgraph example: crosshair')\r\n\r\nlabel = pg.LabelItem(justify='right')\r\nwin.addItem(label)\r\n\r\np1 = win.addPlot(row=1, col=0)\r\np2 = win.addPlot(row=2, col=0)\r\n\r\nregion = pg.LinearRegionItem()\r\nregion.setZValue(10)\r\n#Add the LinearRegionItem to the ViewBox, but tell the ViewBox to exclude this\r\n#item when doing auto-range calculations.\r\n\r\np2.addItem(region, ignoreBounds=True)\r\n\r\n#pg.dbg()\r\n'''\r\nSet whether automatic range uses only visible data when determining the range to show.\r\n'''\r\n#p1.setAutoVisible(x=False, y=False)\r\n\r\n\r\n#create numpy arrays\r\n#make the numbers large to show that the xrange shows data from 10000 to all the way 0\r\ndata1 = 10000 + 15000 * pg.gaussianFilter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000)\r\ndata2 = 15000 + 15000 * pg.gaussianFilter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000)\r\n\r\np1.plot(data1, pen=\"r\")\r\np1.plot(data2, pen=\"g\")\r\n\r\np2.plot(data1, pen=\"w\")\r\n\r\n'''*********The Issue*********'''\r\n#win.adjustSize()    # my trick, please decomment the line and the program would work out\r\n\r\nprint(p1.getViewBox().size())               # ->PyQt5.QtCore.QSizeF()\r\nprint(p1.getViewBox().viewPixelSize())      # exception raised due to empty viewBox size\r\n'''*********The Issue*********'''\r\n\r\ndef update():\r\n    region.setZValue(10)\r\n    minX, maxX = region.getRegion()\r\n    p1.setXRange(minX, maxX, padding=0)\r\n\r\n\r\nregion.sigRegionChanged.connect(update)\r\n\r\ndef updateRegion(window, viewRange):\r\n    rgn = viewRange[0]\r\n    region.setRegion(rgn)\r\n\r\n\r\np1.sigRangeChanged.connect(updateRegion)\r\n\r\n\r\n\r\nregion.setRegion([1000, 2000])\r\n\r\n#cross hair\r\nvLine = pg.InfiniteLine(angle=90, movable=False)\r\nhLine = pg.InfiniteLine(angle=0, movable=False)\r\np1.addItem(vLine, ignoreBounds=True)\r\np1.addItem(hLine, ignoreBounds=True)\r\n\r\n\r\nvb = p1.vb\r\n\r\n\r\n\r\n\r\ndef mouseMoved(evt):\r\n    #print(evt)\r\n\r\n    pos = evt[0]  #using signal proxy turns original arguments into a tuple\r\n    print(pos)\r\n\r\n    if p1.sceneBoundingRect().contains(pos):\r\n        mousePoint = vb.mapSceneToView(pos)\r\n        print(mousePoint)\r\n        index = int(mousePoint.x())\r\n        if index > 0 and index < len(data1):\r\n            label.setText(\"<span style='font-size: 12pt'>x=%0.1f,   <span style='color: red'>y1=%0.1f</span>,   <span style='color: green'>y2=%0.1f</span>\" % (mousePoint.x(), data1[index], data2[index]))\r\n        vLine.setPos(mousePoint.x())\r\n        hLine.setPos(mousePoint.y())\r\n\r\n\r\n\r\nproxy = pg.SignalProxy(p1.scene().sigMouseMoved, rateLimit=60, slot=mouseMoved)\r\n#p1.scene().sigMouseMoved.connect(mouseMoved)\r\n\r\n##Start Qt event loop unless running in interactive mode or using pyside.\r\nif __name__ == '__main__':\r\n    import sys\r\n    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):\r\n        QtGui.QApplication.instance().exec_()\r\n```\r\n\r\n### Expected behavior\r\np1.getViewBox().viewPixelSize() should work\r\n\r\n### Real behavior\r\nbut it raises an exception\r\n\r\n```\r\nTraceback (most recent call last):\r\n  File \"C:/Users/Lee King Batchelor/Desktop/PythonExcel4Securities/pyqtgraph/CrossHair.py\", line 86, in <module>\r\n    print(p1.getViewBox().viewPixelSize())      # exception raised due to empty viewBox size\r\n  File \"C:\\Anaconda3\\envs\\pyqtgraph\\lib\\site-packages\\pyqtgraph\\graphicsItems\\ViewBox\\ViewBox.py\", line 1176, in viewPixelSize\r\n    o = self.mapToView(Point(0,0))\r\n  File \"C:\\Anaconda3\\envs\\pyqtgraph\\lib\\site-packages\\pyqtgraph\\graphicsItems\\ViewBox\\ViewBox.py\", line 1142, in mapToView\r\n    m = fn.invertQTransform(self.childTransform())\r\n  File \"C:\\Anaconda3\\envs\\pyqtgraph\\lib\\site-packages\\pyqtgraph\\functions.py\", line 2199, in invertQTransform\r\n    inv = numpy.linalg.inv(arr)\r\n  File \"<__array_function__ internals>\", line 6, in inv\r\n  File \"C:\\Anaconda3\\envs\\pyqtgraph\\lib\\site-packages\\numpy\\linalg\\linalg.py\", line 547, in inv\r\n    ainv = _umath_linalg.inv(a, signature=signature, extobj=extobj)\r\n  File \"C:\\Anaconda3\\envs\\pyqtgraph\\lib\\site-packages\\numpy\\linalg\\linalg.py\", line 97, in _raise_linalgerror_singular\r\n    raise LinAlgError(\"Singular matrix\")\r\nnumpy.linalg.LinAlgError: Singular matrix\r\n```\r\n\r\n### Tested environment(s)\r\n\r\n * PyQtGraph version: 0.1 and 0.11 dev0\r\n * Qt Python binding:PyQt5.9.2 and PySide2 5.13.1\r\n * Python version: 3.7\r\n * NumPy version: 1.8.1\r\n * Operating system: Win 10\r\n * Installation method: pip and system package\r\n### Additional context\r\n\n", "before_files": [{"content": "from ..Qt import QtGui, QtCore\nfrom .. import functions as fn\nfrom .GraphicsWidget import GraphicsWidget\n## Must be imported at the end to avoid cyclic-dependency hell:\nfrom .ViewBox import ViewBox\nfrom .PlotItem import PlotItem\nfrom .LabelItem import LabelItem\n\n__all__ = ['GraphicsLayout']\nclass GraphicsLayout(GraphicsWidget):\n    \"\"\"\n    Used for laying out GraphicsWidgets in a grid.\n    This is usually created automatically as part of a :class:`GraphicsWindow <pyqtgraph.GraphicsWindow>` or :class:`GraphicsLayoutWidget <pyqtgraph.GraphicsLayoutWidget>`.\n    \"\"\"\n\n\n    def __init__(self, parent=None, border=None):\n        GraphicsWidget.__init__(self, parent)\n        if border is True:\n            border = (100,100,100)\n        self.border = border\n        self.layout = QtGui.QGraphicsGridLayout()\n        self.setLayout(self.layout)\n        self.items = {}  ## item: [(row, col), (row, col), ...]  lists all cells occupied by the item\n        self.rows = {}   ## row: {col1: item1, col2: item2, ...}    maps cell location to item\n        self.itemBorders = {}  ## {item1: QtGui.QGraphicsRectItem, ...} border rects\n        self.currentRow = 0\n        self.currentCol = 0\n        self.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding))\n    \n    #def resizeEvent(self, ev):\n        #ret = GraphicsWidget.resizeEvent(self, ev)\n        #print self.pos(), self.mapToDevice(self.rect().topLeft())\n        #return ret\n\n    def setBorder(self, *args, **kwds):\n        \"\"\"\n        Set the pen used to draw border between cells.\n        \n        See :func:`mkPen <pyqtgraph.mkPen>` for arguments.        \n        \"\"\"\n        self.border = fn.mkPen(*args, **kwds)\n\n        for borderRect in self.itemBorders.values():\n            borderRect.setPen(self.border)\n\n    def nextRow(self):\n        \"\"\"Advance to next row for automatic item placement\"\"\"\n        self.currentRow += 1\n        self.currentCol = -1\n        self.nextColumn()\n        \n    def nextColumn(self):\n        \"\"\"Advance to next available column\n        (generally only for internal use--called by addItem)\"\"\"\n        self.currentCol += 1\n        while self.getItem(self.currentRow, self.currentCol) is not None:\n            self.currentCol += 1\n        \n    def nextCol(self, *args, **kargs):\n        \"\"\"Alias of nextColumn\"\"\"\n        return self.nextColumn(*args, **kargs)\n        \n    def addPlot(self, row=None, col=None, rowspan=1, colspan=1, **kargs):\n        \"\"\"\n        Create a PlotItem and place it in the next available cell (or in the cell specified)\n        All extra keyword arguments are passed to :func:`PlotItem.__init__ <pyqtgraph.PlotItem.__init__>`\n        Returns the created item.\n        \"\"\"\n        plot = PlotItem(**kargs)\n        self.addItem(plot, row, col, rowspan, colspan)\n        return plot\n        \n    def addViewBox(self, row=None, col=None, rowspan=1, colspan=1, **kargs):\n        \"\"\"\n        Create a ViewBox and place it in the next available cell (or in the cell specified)\n        All extra keyword arguments are passed to :func:`ViewBox.__init__ <pyqtgraph.ViewBox.__init__>`\n        Returns the created item.\n        \"\"\"\n        vb = ViewBox(**kargs)\n        self.addItem(vb, row, col, rowspan, colspan)\n        return vb\n        \n    def addLabel(self, text=' ', row=None, col=None, rowspan=1, colspan=1, **kargs):\n        \"\"\"\n        Create a LabelItem with *text* and place it in the next available cell (or in the cell specified)\n        All extra keyword arguments are passed to :func:`LabelItem.__init__ <pyqtgraph.LabelItem.__init__>`\n        Returns the created item.\n        \n        To create a vertical label, use *angle* = -90.\n        \"\"\"\n        text = LabelItem(text, **kargs)\n        self.addItem(text, row, col, rowspan, colspan)\n        return text\n        \n    def addLayout(self, row=None, col=None, rowspan=1, colspan=1, **kargs):\n        \"\"\"\n        Create an empty GraphicsLayout and place it in the next available cell (or in the cell specified)\n        All extra keyword arguments are passed to :func:`GraphicsLayout.__init__ <pyqtgraph.GraphicsLayout.__init__>`\n        Returns the created item.\n        \"\"\"\n        layout = GraphicsLayout(**kargs)\n        self.addItem(layout, row, col, rowspan, colspan)\n        return layout\n        \n    def addItem(self, item, row=None, col=None, rowspan=1, colspan=1):\n        \"\"\"\n        Add an item to the layout and place it in the next available cell (or in the cell specified).\n        The item must be an instance of a QGraphicsWidget subclass.\n        \"\"\"\n        if row is None:\n            row = self.currentRow\n        if col is None:\n            col = self.currentCol\n            \n        self.items[item] = []\n        for i in range(rowspan):\n            for j in range(colspan):\n                row2 = row + i\n                col2 = col + j\n                if row2 not in self.rows:\n                    self.rows[row2] = {}\n                self.rows[row2][col2] = item\n                self.items[item].append((row2, col2))\n\n        borderRect = QtGui.QGraphicsRectItem()\n\n        borderRect.setParentItem(self)\n        borderRect.setZValue(1e3)\n        borderRect.setPen(fn.mkPen(self.border))\n\n        self.itemBorders[item] = borderRect\n\n        item.geometryChanged.connect(self._updateItemBorder)\n\n        self.layout.addItem(item, row, col, rowspan, colspan)\n        self.nextColumn()\n\n    def getItem(self, row, col):\n        \"\"\"Return the item in (*row*, *col*). If the cell is empty, return None.\"\"\"\n        return self.rows.get(row, {}).get(col, None)\n\n    def boundingRect(self):\n        return self.rect()\n\n    def itemIndex(self, item):\n        for i in range(self.layout.count()):\n            if self.layout.itemAt(i).graphicsItem() is item:\n                return i\n        raise Exception(\"Could not determine index of item \" + str(item))\n    \n    def removeItem(self, item):\n        \"\"\"Remove *item* from the layout.\"\"\"\n        ind = self.itemIndex(item)\n        self.layout.removeAt(ind)\n        self.scene().removeItem(item)\n        \n        for r, c in self.items[item]:\n            del self.rows[r][c]\n        del self.items[item]\n\n        item.geometryChanged.disconnect(self._updateItemBorder)\n        del self.itemBorders[item]\n\n        self.update()\n    \n    def clear(self):\n        for i in list(self.items.keys()):\n            self.removeItem(i)\n        self.currentRow = 0\n        self.currentCol = 0\n\n    def setContentsMargins(self, *args):\n        # Wrap calls to layout. This should happen automatically, but there\n        # seems to be a Qt bug:\n        # http://stackoverflow.com/questions/27092164/margins-in-pyqtgraphs-graphicslayout\n        self.layout.setContentsMargins(*args)\n\n    def setSpacing(self, *args):\n        self.layout.setSpacing(*args)\n\n    def _updateItemBorder(self):\n        if self.border is None:\n            return\n\n        item = self.sender()\n        if item is None:\n            return\n\n        r = item.mapRectToParent(item.boundingRect())\n        self.itemBorders[item].setRect(r)\n", "path": "pyqtgraph/graphicsItems/GraphicsLayout.py"}], "after_files": [{"content": "from ..Qt import QtGui, QtCore\nfrom .. import functions as fn\nfrom .GraphicsWidget import GraphicsWidget\n## Must be imported at the end to avoid cyclic-dependency hell:\nfrom .ViewBox import ViewBox\nfrom .PlotItem import PlotItem\nfrom .LabelItem import LabelItem\n\n__all__ = ['GraphicsLayout']\nclass GraphicsLayout(GraphicsWidget):\n    \"\"\"\n    Used for laying out GraphicsWidgets in a grid.\n    This is usually created automatically as part of a :class:`GraphicsWindow <pyqtgraph.GraphicsWindow>` or :class:`GraphicsLayoutWidget <pyqtgraph.GraphicsLayoutWidget>`.\n    \"\"\"\n\n\n    def __init__(self, parent=None, border=None):\n        GraphicsWidget.__init__(self, parent)\n        if border is True:\n            border = (100,100,100)\n        self.border = border\n        self.layout = QtGui.QGraphicsGridLayout()\n        self.setLayout(self.layout)\n        self.items = {}  ## item: [(row, col), (row, col), ...]  lists all cells occupied by the item\n        self.rows = {}   ## row: {col1: item1, col2: item2, ...}    maps cell location to item\n        self.itemBorders = {}  ## {item1: QtGui.QGraphicsRectItem, ...} border rects\n        self.currentRow = 0\n        self.currentCol = 0\n        self.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding))\n    \n    #def resizeEvent(self, ev):\n        #ret = GraphicsWidget.resizeEvent(self, ev)\n        #print self.pos(), self.mapToDevice(self.rect().topLeft())\n        #return ret\n\n    def setBorder(self, *args, **kwds):\n        \"\"\"\n        Set the pen used to draw border between cells.\n        \n        See :func:`mkPen <pyqtgraph.mkPen>` for arguments.        \n        \"\"\"\n        self.border = fn.mkPen(*args, **kwds)\n\n        for borderRect in self.itemBorders.values():\n            borderRect.setPen(self.border)\n\n    def nextRow(self):\n        \"\"\"Advance to next row for automatic item placement\"\"\"\n        self.currentRow += 1\n        self.currentCol = -1\n        self.nextColumn()\n        \n    def nextColumn(self):\n        \"\"\"Advance to next available column\n        (generally only for internal use--called by addItem)\"\"\"\n        self.currentCol += 1\n        while self.getItem(self.currentRow, self.currentCol) is not None:\n            self.currentCol += 1\n        \n    def nextCol(self, *args, **kargs):\n        \"\"\"Alias of nextColumn\"\"\"\n        return self.nextColumn(*args, **kargs)\n        \n    def addPlot(self, row=None, col=None, rowspan=1, colspan=1, **kargs):\n        \"\"\"\n        Create a PlotItem and place it in the next available cell (or in the cell specified)\n        All extra keyword arguments are passed to :func:`PlotItem.__init__ <pyqtgraph.PlotItem.__init__>`\n        Returns the created item.\n        \"\"\"\n        plot = PlotItem(**kargs)\n        self.addItem(plot, row, col, rowspan, colspan)\n        return plot\n        \n    def addViewBox(self, row=None, col=None, rowspan=1, colspan=1, **kargs):\n        \"\"\"\n        Create a ViewBox and place it in the next available cell (or in the cell specified)\n        All extra keyword arguments are passed to :func:`ViewBox.__init__ <pyqtgraph.ViewBox.__init__>`\n        Returns the created item.\n        \"\"\"\n        vb = ViewBox(**kargs)\n        self.addItem(vb, row, col, rowspan, colspan)\n        return vb\n        \n    def addLabel(self, text=' ', row=None, col=None, rowspan=1, colspan=1, **kargs):\n        \"\"\"\n        Create a LabelItem with *text* and place it in the next available cell (or in the cell specified)\n        All extra keyword arguments are passed to :func:`LabelItem.__init__ <pyqtgraph.LabelItem.__init__>`\n        Returns the created item.\n        \n        To create a vertical label, use *angle* = -90.\n        \"\"\"\n        text = LabelItem(text, **kargs)\n        self.addItem(text, row, col, rowspan, colspan)\n        return text\n        \n    def addLayout(self, row=None, col=None, rowspan=1, colspan=1, **kargs):\n        \"\"\"\n        Create an empty GraphicsLayout and place it in the next available cell (or in the cell specified)\n        All extra keyword arguments are passed to :func:`GraphicsLayout.__init__ <pyqtgraph.GraphicsLayout.__init__>`\n        Returns the created item.\n        \"\"\"\n        layout = GraphicsLayout(**kargs)\n        self.addItem(layout, row, col, rowspan, colspan)\n        return layout\n        \n    def addItem(self, item, row=None, col=None, rowspan=1, colspan=1):\n        \"\"\"\n        Add an item to the layout and place it in the next available cell (or in the cell specified).\n        The item must be an instance of a QGraphicsWidget subclass.\n        \"\"\"\n        if row is None:\n            row = self.currentRow\n        if col is None:\n            col = self.currentCol\n            \n        self.items[item] = []\n        for i in range(rowspan):\n            for j in range(colspan):\n                row2 = row + i\n                col2 = col + j\n                if row2 not in self.rows:\n                    self.rows[row2] = {}\n                self.rows[row2][col2] = item\n                self.items[item].append((row2, col2))\n\n        borderRect = QtGui.QGraphicsRectItem()\n\n        borderRect.setParentItem(self)\n        borderRect.setZValue(1e3)\n        borderRect.setPen(fn.mkPen(self.border))\n\n        self.itemBorders[item] = borderRect\n\n        item.geometryChanged.connect(self._updateItemBorder)\n\n        self.layout.addItem(item, row, col, rowspan, colspan)\n        self.layout.activate() # Update layout, recalculating bounds.\n                               # Allows some PyQtGraph features to also work without Qt event loop.\n        \n        self.nextColumn()\n\n    def getItem(self, row, col):\n        \"\"\"Return the item in (*row*, *col*). If the cell is empty, return None.\"\"\"\n        return self.rows.get(row, {}).get(col, None)\n\n    def boundingRect(self):\n        return self.rect()\n\n    def itemIndex(self, item):\n        for i in range(self.layout.count()):\n            if self.layout.itemAt(i).graphicsItem() is item:\n                return i\n        raise Exception(\"Could not determine index of item \" + str(item))\n    \n    def removeItem(self, item):\n        \"\"\"Remove *item* from the layout.\"\"\"\n        ind = self.itemIndex(item)\n        self.layout.removeAt(ind)\n        self.scene().removeItem(item)\n        \n        for r, c in self.items[item]:\n            del self.rows[r][c]\n        del self.items[item]\n\n        item.geometryChanged.disconnect(self._updateItemBorder)\n        del self.itemBorders[item]\n\n        self.update()\n    \n    def clear(self):\n        for i in list(self.items.keys()):\n            self.removeItem(i)\n        self.currentRow = 0\n        self.currentCol = 0\n\n    def setContentsMargins(self, *args):\n        # Wrap calls to layout. This should happen automatically, but there\n        # seems to be a Qt bug:\n        # http://stackoverflow.com/questions/27092164/margins-in-pyqtgraphs-graphicslayout\n        self.layout.setContentsMargins(*args)\n\n    def setSpacing(self, *args):\n        self.layout.setSpacing(*args)\n\n    def _updateItemBorder(self):\n        if self.border is None:\n            return\n\n        item = self.sender()\n        if item is None:\n            return\n\n        r = item.mapRectToParent(item.boundingRect())\n        self.itemBorders[item].setRect(r)\n", "path": "pyqtgraph/graphicsItems/GraphicsLayout.py"}]}