Make behavior configurable when a reloaded dock is missing.
+ other bugfixes
This commit is contained in:
parent
dd672c41b6
commit
b6f9516678
@ -17,16 +17,20 @@ class Container(object):
|
|||||||
|
|
||||||
def containerChanged(self, c):
|
def containerChanged(self, c):
|
||||||
self._container = c
|
self._container = c
|
||||||
|
if c is None:
|
||||||
|
self.area = None
|
||||||
|
else:
|
||||||
|
self.area = c.area
|
||||||
|
|
||||||
def type(self):
|
def type(self):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def insert(self, new, pos=None, neighbor=None):
|
def insert(self, new, pos=None, neighbor=None):
|
||||||
# remove from existing parent first
|
|
||||||
new.setParent(None)
|
|
||||||
|
|
||||||
if not isinstance(new, list):
|
if not isinstance(new, list):
|
||||||
new = [new]
|
new = [new]
|
||||||
|
for n in new:
|
||||||
|
# remove from existing parent first
|
||||||
|
n.setParent(None)
|
||||||
if neighbor is None:
|
if neighbor is None:
|
||||||
if pos == 'before':
|
if pos == 'before':
|
||||||
index = 0
|
index = 0
|
||||||
@ -40,34 +44,37 @@ class Container(object):
|
|||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
for n in new:
|
for n in new:
|
||||||
#print "change container", n, " -> ", self
|
|
||||||
n.containerChanged(self)
|
|
||||||
#print "insert", n, " -> ", self, index
|
#print "insert", n, " -> ", self, index
|
||||||
self._insertItem(n, index)
|
self._insertItem(n, index)
|
||||||
|
#print "change container", n, " -> ", self
|
||||||
|
n.containerChanged(self)
|
||||||
index += 1
|
index += 1
|
||||||
n.sigStretchChanged.connect(self.childStretchChanged)
|
n.sigStretchChanged.connect(self.childStretchChanged)
|
||||||
#print "child added", self
|
#print "child added", self
|
||||||
self.updateStretch()
|
self.updateStretch()
|
||||||
|
|
||||||
def apoptose(self, propagate=True):
|
def apoptose(self, propagate=True):
|
||||||
##if there is only one (or zero) item in this container, disappear.
|
# if there is only one (or zero) item in this container, disappear.
|
||||||
|
# if propagate is True, then also attempt to apoptose parent containers.
|
||||||
cont = self._container
|
cont = self._container
|
||||||
c = self.count()
|
c = self.count()
|
||||||
if c > 1:
|
if c > 1:
|
||||||
return
|
return
|
||||||
if self.count() == 1: ## if there is one item, give it to the parent container (unless this is the top)
|
if c == 1: ## if there is one item, give it to the parent container (unless this is the top)
|
||||||
if self is self.area.topContainer:
|
ch = self.widget(0)
|
||||||
|
if (self.area is not None and self is self.area.topContainer and not isinstance(ch, Container)) or self.container() is None:
|
||||||
return
|
return
|
||||||
self.container().insert(self.widget(0), 'before', self)
|
self.container().insert(ch, 'before', self)
|
||||||
#print "apoptose:", self
|
#print "apoptose:", self
|
||||||
self.close()
|
self.close()
|
||||||
if propagate and cont is not None:
|
if propagate and cont is not None:
|
||||||
cont.apoptose()
|
cont.apoptose()
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.area = None
|
|
||||||
self._container = None
|
|
||||||
self.setParent(None)
|
self.setParent(None)
|
||||||
|
if self.area is not None and self.area.topContainer is self:
|
||||||
|
self.area.topContainer = None
|
||||||
|
self.containerChanged(None)
|
||||||
|
|
||||||
def childEvent(self, ev):
|
def childEvent(self, ev):
|
||||||
ch = ev.child()
|
ch = ev.child()
|
||||||
@ -92,7 +99,6 @@ class Container(object):
|
|||||||
###Set the stretch values for this container to reflect its contents
|
###Set the stretch values for this container to reflect its contents
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def stretch(self):
|
def stretch(self):
|
||||||
"""Return the stretch factors for this container"""
|
"""Return the stretch factors for this container"""
|
||||||
return self._stretch
|
return self._stretch
|
||||||
|
@ -36,6 +36,7 @@ class Dock(QtGui.QWidget, DockDrop):
|
|||||||
self.widgetArea.setLayout(self.layout)
|
self.widgetArea.setLayout(self.layout)
|
||||||
self.widgetArea.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
self.widgetArea.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
||||||
self.widgets = []
|
self.widgets = []
|
||||||
|
self._container = None
|
||||||
self.currentRow = 0
|
self.currentRow = 0
|
||||||
#self.titlePos = 'top'
|
#self.titlePos = 'top'
|
||||||
self.raiseOverlay()
|
self.raiseOverlay()
|
||||||
@ -187,9 +188,6 @@ class Dock(QtGui.QWidget, DockDrop):
|
|||||||
def name(self):
|
def name(self):
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
def container(self):
|
|
||||||
return self._container
|
|
||||||
|
|
||||||
def addWidget(self, widget, row=None, col=0, rowspan=1, colspan=1):
|
def addWidget(self, widget, row=None, col=0, rowspan=1, colspan=1):
|
||||||
"""
|
"""
|
||||||
Add a new widget to the interior of this Dock.
|
Add a new widget to the interior of this Dock.
|
||||||
@ -202,7 +200,6 @@ class Dock(QtGui.QWidget, DockDrop):
|
|||||||
self.layout.addWidget(widget, row, col, rowspan, colspan)
|
self.layout.addWidget(widget, row, col, rowspan, colspan)
|
||||||
self.raiseOverlay()
|
self.raiseOverlay()
|
||||||
|
|
||||||
|
|
||||||
def startDrag(self):
|
def startDrag(self):
|
||||||
self.drag = QtGui.QDrag(self)
|
self.drag = QtGui.QDrag(self)
|
||||||
mime = QtCore.QMimeData()
|
mime = QtCore.QMimeData()
|
||||||
@ -216,21 +213,30 @@ class Dock(QtGui.QWidget, DockDrop):
|
|||||||
def float(self):
|
def float(self):
|
||||||
self.area.floatDock(self)
|
self.area.floatDock(self)
|
||||||
|
|
||||||
|
def container(self):
|
||||||
|
return self._container
|
||||||
|
|
||||||
def containerChanged(self, c):
|
def containerChanged(self, c):
|
||||||
|
if self._container is not None:
|
||||||
|
# ask old container to close itself if it is no longer needed
|
||||||
|
self._container.apoptose()
|
||||||
#print self.name(), "container changed"
|
#print self.name(), "container changed"
|
||||||
self._container = c
|
self._container = c
|
||||||
if c.type() != 'tab':
|
if c is None:
|
||||||
self.moveLabel = True
|
self.area = None
|
||||||
self.label.setDim(False)
|
|
||||||
else:
|
else:
|
||||||
self.moveLabel = False
|
self.area = c.area
|
||||||
|
if c.type() != 'tab':
|
||||||
self.setOrientation(force=True)
|
self.moveLabel = True
|
||||||
|
self.label.setDim(False)
|
||||||
|
else:
|
||||||
|
self.moveLabel = False
|
||||||
|
|
||||||
|
self.setOrientation(force=True)
|
||||||
|
|
||||||
def raiseDock(self):
|
def raiseDock(self):
|
||||||
"""If this Dock is stacked underneath others, raise it to the top."""
|
"""If this Dock is stacked underneath others, raise it to the top."""
|
||||||
self.container().raiseDock(self)
|
self.container().raiseDock(self)
|
||||||
|
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""Remove this dock from the DockArea it lives inside."""
|
"""Remove this dock from the DockArea it lives inside."""
|
||||||
|
@ -61,6 +61,8 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
|
|||||||
if isinstance(relativeTo, basestring):
|
if isinstance(relativeTo, basestring):
|
||||||
relativeTo = self.docks[relativeTo]
|
relativeTo = self.docks[relativeTo]
|
||||||
container = self.getContainer(relativeTo)
|
container = self.getContainer(relativeTo)
|
||||||
|
if container is None:
|
||||||
|
raise TypeError("Dock %s is not contained in a DockArea; cannot add another dock relative to it." % relativeTo)
|
||||||
neighbor = relativeTo
|
neighbor = relativeTo
|
||||||
|
|
||||||
## what container type do we need?
|
## what container type do we need?
|
||||||
@ -98,7 +100,6 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
|
|||||||
#print "request insert", dock, insertPos, neighbor
|
#print "request insert", dock, insertPos, neighbor
|
||||||
old = dock.container()
|
old = dock.container()
|
||||||
container.insert(dock, insertPos, neighbor)
|
container.insert(dock, insertPos, neighbor)
|
||||||
dock.area = self
|
|
||||||
self.docks[dock.name()] = dock
|
self.docks[dock.name()] = dock
|
||||||
if old is not None:
|
if old is not None:
|
||||||
old.apoptose()
|
old.apoptose()
|
||||||
@ -142,23 +143,19 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
|
|||||||
|
|
||||||
def insert(self, new, pos=None, neighbor=None):
|
def insert(self, new, pos=None, neighbor=None):
|
||||||
if self.topContainer is not None:
|
if self.topContainer is not None:
|
||||||
|
# Adding new top-level container; addContainer() should
|
||||||
|
# take care of giving the old top container a new home.
|
||||||
self.topContainer.containerChanged(None)
|
self.topContainer.containerChanged(None)
|
||||||
self.layout.addWidget(new)
|
self.layout.addWidget(new)
|
||||||
|
new.containerChanged(self)
|
||||||
self.topContainer = new
|
self.topContainer = new
|
||||||
#print self, "set top:", new
|
|
||||||
new._container = self
|
|
||||||
self.raiseOverlay()
|
self.raiseOverlay()
|
||||||
#print "Insert top:", new
|
|
||||||
|
|
||||||
def count(self):
|
def count(self):
|
||||||
if self.topContainer is None:
|
if self.topContainer is None:
|
||||||
return 0
|
return 0
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
#def paintEvent(self, ev):
|
|
||||||
#self.drawDockOverlay()
|
|
||||||
|
|
||||||
def resizeEvent(self, ev):
|
def resizeEvent(self, ev):
|
||||||
self.resizeOverlay(self.size())
|
self.resizeOverlay(self.size())
|
||||||
|
|
||||||
@ -180,7 +177,6 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
|
|||||||
area.win.resize(dock.size())
|
area.win.resize(dock.size())
|
||||||
area.moveDock(dock, 'top', None)
|
area.moveDock(dock, 'top', None)
|
||||||
|
|
||||||
|
|
||||||
def removeTempArea(self, area):
|
def removeTempArea(self, area):
|
||||||
self.tempAreas.remove(area)
|
self.tempAreas.remove(area)
|
||||||
#print "close window", area.window()
|
#print "close window", area.window()
|
||||||
@ -212,14 +208,16 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
|
|||||||
childs.append(self.childState(obj.widget(i)))
|
childs.append(self.childState(obj.widget(i)))
|
||||||
return (obj.type(), childs, obj.saveState())
|
return (obj.type(), childs, obj.saveState())
|
||||||
|
|
||||||
|
def restoreState(self, state, missing='error'):
|
||||||
def restoreState(self, state):
|
|
||||||
"""
|
"""
|
||||||
Restore Dock configuration as generated by saveState.
|
Restore Dock configuration as generated by saveState.
|
||||||
|
|
||||||
Note that this function does not create any Docks--it will only
|
This function does not create any Docks--it will only
|
||||||
restore the arrangement of an existing set of Docks.
|
restore the arrangement of an existing set of Docks.
|
||||||
|
|
||||||
|
By default, docks that are described in *state* but do not exist
|
||||||
|
in the dock area will cause an exception to be raised. This behavior
|
||||||
|
can be changed by setting *missing* to 'ignore' or 'create'.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
## 1) make dict of all docks and list of existing containers
|
## 1) make dict of all docks and list of existing containers
|
||||||
@ -229,17 +227,20 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
|
|||||||
|
|
||||||
## 2) create container structure, move docks into new containers
|
## 2) create container structure, move docks into new containers
|
||||||
if state['main'] is not None:
|
if state['main'] is not None:
|
||||||
self.buildFromState(state['main'], docks, self)
|
self.buildFromState(state['main'], docks, self, missing=missing)
|
||||||
|
|
||||||
## 3) create floating areas, populate
|
## 3) create floating areas, populate
|
||||||
for s in state['float']:
|
for s in state['float']:
|
||||||
a = self.addTempArea()
|
a = self.addTempArea()
|
||||||
a.buildFromState(s[0]['main'], docks, a)
|
a.buildFromState(s[0]['main'], docks, a, missing=missing)
|
||||||
a.win.setGeometry(*s[1])
|
a.win.setGeometry(*s[1])
|
||||||
|
a.apoptose() # ask temp area to close itself if it is empty
|
||||||
|
|
||||||
## 4) Add any remaining docks to the bottom
|
## 4) Add any remaining docks to a float
|
||||||
for d in docks.values():
|
for d in docks.values():
|
||||||
self.moveDock(d, 'below', None)
|
a = self.addTempArea()
|
||||||
|
a.addDock(d, 'below')
|
||||||
|
# self.moveDock(d, 'below', None)
|
||||||
|
|
||||||
#print "\nKill old containers:"
|
#print "\nKill old containers:"
|
||||||
## 5) kill old containers
|
## 5) kill old containers
|
||||||
@ -248,8 +249,7 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
|
|||||||
for a in oldTemps:
|
for a in oldTemps:
|
||||||
a.apoptose()
|
a.apoptose()
|
||||||
|
|
||||||
|
def buildFromState(self, state, docks, root, depth=0, missing='error'):
|
||||||
def buildFromState(self, state, docks, root, depth=0):
|
|
||||||
typ, contents, state = state
|
typ, contents, state = state
|
||||||
pfx = " " * depth
|
pfx = " " * depth
|
||||||
if typ == 'dock':
|
if typ == 'dock':
|
||||||
@ -257,7 +257,15 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
|
|||||||
obj = docks[contents]
|
obj = docks[contents]
|
||||||
del docks[contents]
|
del docks[contents]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise Exception('Cannot restore dock state; no dock with name "%s"' % contents)
|
if missing == 'error':
|
||||||
|
raise Exception('Cannot restore dock state; no dock with name "%s"' % contents)
|
||||||
|
elif missing == 'create':
|
||||||
|
obj = Dock(name=contents)
|
||||||
|
elif missing == 'ignore':
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
raise ValueError('"missing" argument must be one of "error", "create", or "ignore".')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
obj = self.makeContainer(typ)
|
obj = self.makeContainer(typ)
|
||||||
|
|
||||||
@ -266,10 +274,11 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
|
|||||||
|
|
||||||
if typ != 'dock':
|
if typ != 'dock':
|
||||||
for o in contents:
|
for o in contents:
|
||||||
self.buildFromState(o, docks, obj, depth+1)
|
self.buildFromState(o, docks, obj, depth+1, missing=missing)
|
||||||
|
# remove this container if possible. (there are valid situations when a restore will
|
||||||
|
# generate empty containers, such as when using missing='ignore')
|
||||||
obj.apoptose(propagate=False)
|
obj.apoptose(propagate=False)
|
||||||
obj.restoreState(state) ## this has to be done later?
|
obj.restoreState(state) ## this has to be done later?
|
||||||
|
|
||||||
|
|
||||||
def findAll(self, obj=None, c=None, d=None):
|
def findAll(self, obj=None, c=None, d=None):
|
||||||
if obj is None:
|
if obj is None:
|
||||||
@ -295,14 +304,15 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
|
|||||||
d.update(d2)
|
d.update(d2)
|
||||||
return (c, d)
|
return (c, d)
|
||||||
|
|
||||||
def apoptose(self):
|
def apoptose(self, propagate=True):
|
||||||
|
# remove top container if possible, close this area if it is temporary.
|
||||||
#print "apoptose area:", self.temporary, self.topContainer, self.topContainer.count()
|
#print "apoptose area:", self.temporary, self.topContainer, self.topContainer.count()
|
||||||
if self.topContainer.count() == 0:
|
if self.topContainer is None or self.topContainer.count() == 0:
|
||||||
self.topContainer = None
|
self.topContainer = None
|
||||||
if self.temporary:
|
if self.temporary:
|
||||||
self.home.removeTempArea(self)
|
self.home.removeTempArea(self)
|
||||||
#self.close()
|
#self.close()
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
docks = self.findAll()[1]
|
docks = self.findAll()[1]
|
||||||
for dock in docks.values():
|
for dock in docks.values():
|
||||||
@ -322,12 +332,38 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
|
|||||||
def dropEvent(self, *args):
|
def dropEvent(self, *args):
|
||||||
DockDrop.dropEvent(self, *args)
|
DockDrop.dropEvent(self, *args)
|
||||||
|
|
||||||
|
def printState(self, state=None, name='Main'):
|
||||||
|
# for debugging
|
||||||
|
if state is None:
|
||||||
|
state = self.saveState()
|
||||||
|
print("=== %s dock area ===" % name)
|
||||||
|
if state['main'] is None:
|
||||||
|
print(" (empty)")
|
||||||
|
else:
|
||||||
|
self._printAreaState(state['main'])
|
||||||
|
for i, float in enumerate(state['float']):
|
||||||
|
self.printState(float[0], name='float %d' % i)
|
||||||
|
|
||||||
class TempAreaWindow(QtGui.QMainWindow):
|
def _printAreaState(self, area, indent=0):
|
||||||
|
if area[0] == 'dock':
|
||||||
|
print(" " * indent + area[0] + " " + str(area[1:]))
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
print(" " * indent + area[0])
|
||||||
|
for ch in area[1]:
|
||||||
|
self._printAreaState(ch, indent+1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TempAreaWindow(QtGui.QWidget):
|
||||||
def __init__(self, area, **kwargs):
|
def __init__(self, area, **kwargs):
|
||||||
QtGui.QMainWindow.__init__(self, **kwargs)
|
QtGui.QWidget.__init__(self, **kwargs)
|
||||||
self.setCentralWidget(area)
|
self.layout = QtGui.QGridLayout()
|
||||||
|
self.setLayout(self.layout)
|
||||||
|
self.layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.dockarea = area
|
||||||
|
self.layout.addWidget(area)
|
||||||
|
|
||||||
def closeEvent(self, *args, **kwargs):
|
def closeEvent(self, *args):
|
||||||
self.centralWidget().clear()
|
self.dockarea.clear()
|
||||||
QtGui.QMainWindow.closeEvent(self, *args, **kwargs)
|
QtGui.QWidget.closeEvent(self, *args)
|
||||||
|
184
pyqtgraph/dockarea/tests/test_dockarea.py
Normal file
184
pyqtgraph/dockarea/tests/test_dockarea.py
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import pyqtgraph as pg
|
||||||
|
from collections import OrderedDict
|
||||||
|
pg.mkQApp()
|
||||||
|
|
||||||
|
import pyqtgraph.dockarea as da
|
||||||
|
|
||||||
|
def test_dockarea():
|
||||||
|
a = da.DockArea()
|
||||||
|
d1 = da.Dock("dock 1")
|
||||||
|
a.addDock(d1, 'left')
|
||||||
|
|
||||||
|
assert a.topContainer is d1.container()
|
||||||
|
assert d1.container().container() is a
|
||||||
|
assert d1.area is a
|
||||||
|
assert a.topContainer.widget(0) is d1
|
||||||
|
|
||||||
|
d2 = da.Dock("dock 2")
|
||||||
|
a.addDock(d2, 'right')
|
||||||
|
|
||||||
|
assert a.topContainer is d1.container()
|
||||||
|
assert a.topContainer is d2.container()
|
||||||
|
assert d1.container().container() is a
|
||||||
|
assert d2.container().container() is a
|
||||||
|
assert d2.area is a
|
||||||
|
assert a.topContainer.widget(0) is d1
|
||||||
|
assert a.topContainer.widget(1) is d2
|
||||||
|
|
||||||
|
d3 = da.Dock("dock 3")
|
||||||
|
a.addDock(d3, 'bottom')
|
||||||
|
|
||||||
|
assert a.topContainer is d3.container()
|
||||||
|
assert d2.container().container() is d3.container()
|
||||||
|
assert d1.container().container() is d3.container()
|
||||||
|
assert d1.container().container().container() is a
|
||||||
|
assert d2.container().container().container() is a
|
||||||
|
assert d3.container().container() is a
|
||||||
|
assert d3.area is a
|
||||||
|
assert d2.area is a
|
||||||
|
assert a.topContainer.widget(0) is d1.container()
|
||||||
|
assert a.topContainer.widget(1) is d3
|
||||||
|
|
||||||
|
d4 = da.Dock("dock 4")
|
||||||
|
a.addDock(d4, 'below', d3)
|
||||||
|
|
||||||
|
assert d4.container().type() == 'tab'
|
||||||
|
assert d4.container() is d3.container()
|
||||||
|
assert d3.container().container() is d2.container().container()
|
||||||
|
assert d4.area is a
|
||||||
|
a.printState()
|
||||||
|
|
||||||
|
# layout now looks like:
|
||||||
|
# vcontainer
|
||||||
|
# hcontainer
|
||||||
|
# dock 1
|
||||||
|
# dock 2
|
||||||
|
# tcontainer
|
||||||
|
# dock 3
|
||||||
|
# dock 4
|
||||||
|
|
||||||
|
# test save/restore state
|
||||||
|
state = a.saveState()
|
||||||
|
a2 = da.DockArea()
|
||||||
|
# default behavior is to raise exception if docks are missing
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
a2.restoreState(state)
|
||||||
|
|
||||||
|
# test restore with ignore missing
|
||||||
|
a2.restoreState(state, missing='ignore')
|
||||||
|
assert a2.topContainer is None
|
||||||
|
|
||||||
|
# test restore with auto-create
|
||||||
|
a2.restoreState(state, missing='create')
|
||||||
|
assert a2.saveState() == state
|
||||||
|
a2.printState()
|
||||||
|
|
||||||
|
# double-check that state actually matches the output of saveState()
|
||||||
|
c1 = a2.topContainer
|
||||||
|
assert c1.type() == 'vertical'
|
||||||
|
c2 = c1.widget(0)
|
||||||
|
c3 = c1.widget(1)
|
||||||
|
assert c2.type() == 'horizontal'
|
||||||
|
assert c2.widget(0).name() == 'dock 1'
|
||||||
|
assert c2.widget(1).name() == 'dock 2'
|
||||||
|
assert c3.type() == 'tab'
|
||||||
|
assert c3.widget(0).name() == 'dock 3'
|
||||||
|
assert c3.widget(1).name() == 'dock 4'
|
||||||
|
|
||||||
|
# test restore with docks already present
|
||||||
|
a3 = da.DockArea()
|
||||||
|
a3docks = []
|
||||||
|
for i in range(1, 5):
|
||||||
|
dock = da.Dock('dock %d' % i)
|
||||||
|
a3docks.append(dock)
|
||||||
|
a3.addDock(dock, 'right')
|
||||||
|
a3.restoreState(state)
|
||||||
|
assert a3.saveState() == state
|
||||||
|
|
||||||
|
# test restore with extra docks present
|
||||||
|
a3 = da.DockArea()
|
||||||
|
a3docks = []
|
||||||
|
for i in [1, 2, 5, 4, 3]:
|
||||||
|
dock = da.Dock('dock %d' % i)
|
||||||
|
a3docks.append(dock)
|
||||||
|
a3.addDock(dock, 'left')
|
||||||
|
a3.restoreState(state)
|
||||||
|
a3.printState()
|
||||||
|
|
||||||
|
|
||||||
|
# test a more complex restore
|
||||||
|
a4 = da.DockArea()
|
||||||
|
state1 = {'float': [], 'main':
|
||||||
|
('horizontal', [
|
||||||
|
('vertical', [
|
||||||
|
('horizontal', [
|
||||||
|
('tab', [
|
||||||
|
('dock', 'dock1', {}),
|
||||||
|
('dock', 'dock2', {}),
|
||||||
|
('dock', 'dock3', {}),
|
||||||
|
('dock', 'dock4', {})
|
||||||
|
], {'index': 1}),
|
||||||
|
('vertical', [
|
||||||
|
('dock', 'dock5', {}),
|
||||||
|
('horizontal', [
|
||||||
|
('dock', 'dock6', {}),
|
||||||
|
('dock', 'dock7', {})
|
||||||
|
], {'sizes': [184, 363]})
|
||||||
|
], {'sizes': [355, 120]})
|
||||||
|
], {'sizes': [9, 552]})
|
||||||
|
], {'sizes': [480]}),
|
||||||
|
('dock', 'dock8', {})
|
||||||
|
], {'sizes': [566, 69]})
|
||||||
|
}
|
||||||
|
|
||||||
|
state2 = {'float': [], 'main':
|
||||||
|
('horizontal', [
|
||||||
|
('vertical', [
|
||||||
|
('horizontal', [
|
||||||
|
('dock', 'dock2', {}),
|
||||||
|
('vertical', [
|
||||||
|
('dock', 'dock5', {}),
|
||||||
|
('horizontal', [
|
||||||
|
('dock', 'dock6', {}),
|
||||||
|
('dock', 'dock7', {})
|
||||||
|
], {'sizes': [492, 485]})
|
||||||
|
], {'sizes': [936, 0]})
|
||||||
|
], {'sizes': [172, 982]})
|
||||||
|
], {'sizes': [941]}),
|
||||||
|
('vertical', [
|
||||||
|
('dock', 'dock8', {}),
|
||||||
|
('dock', 'dock4', {}),
|
||||||
|
('dock', 'dock1', {})
|
||||||
|
], {'sizes': [681, 225, 25]})
|
||||||
|
], {'sizes': [1159, 116]})}
|
||||||
|
|
||||||
|
a4.restoreState(state1, missing='create')
|
||||||
|
a4.restoreState(state2, missing='ignore')
|
||||||
|
a4.printState()
|
||||||
|
|
||||||
|
c, d = a4.findAll()
|
||||||
|
assert d['dock3'].area is not a4
|
||||||
|
assert d['dock1'].container() is d['dock4'].container() is d['dock8'].container()
|
||||||
|
assert d['dock6'].container() is d['dock7'].container()
|
||||||
|
assert a4 is d['dock2'].area is d['dock2'].container().container().container()
|
||||||
|
assert a4 is d['dock5'].area is d['dock5'].container().container().container().container()
|
||||||
|
|
||||||
|
# States should be the same with two exceptions:
|
||||||
|
# dock3 is in a float because it does not appear in state2
|
||||||
|
# a superfluous vertical splitter in state2 has been removed
|
||||||
|
state4 = a4.saveState()
|
||||||
|
state4['main'][1][0] = state4['main'][1][0][1][0]
|
||||||
|
assert clean_state(state4['main']) == clean_state(state2['main'])
|
||||||
|
|
||||||
|
|
||||||
|
def clean_state(state):
|
||||||
|
# return state dict with sizes removed
|
||||||
|
ch = [clean_state(x) for x in state[1]] if isinstance(state[1], list) else state[1]
|
||||||
|
state = (state[0], ch, {})
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_dockarea()
|
Loading…
x
Reference in New Issue
Block a user