def restore_child_nodes(self, stream: QXmlStreamReader,
                            testing: bool) -> Tuple[bool, Optional[QWidget]]:
        '''
        Restore state of child nodes.

        Parameters
        ----------
        stream : QXmlStreamReader
        created_widget : QWidget
        testing : bool

        Returns
        -------
        value : bool
        widget : QWidget
        '''
        result = True
        widget = None
        while stream.readNextStartElement():
            if stream.name() == "Splitter":
                result, widget = self.restore_splitter(stream, testing)
            elif stream.name() == "Area":
                result, widget = self.restore_dock_area(stream, testing)
            else:
                stream.skipCurrentElement()
            logger.debug('restored child node %s: %s', stream.name(), widget)

        return result, widget
    def restore_dock_area(self, stream: QXmlStreamReader,
                          testing: bool) -> Tuple[bool, QWidget]:
        '''
        Restores a dock area.

        Parameters
        ----------
        stream : QXmlStreamReader
        created_widget : QWidget
        testing : bool

        Returns
        -------
        value : bool
        widget : QWidget
        '''
        tabs = int(stream.attributes().value("Tabs"))
        current_dock_widget = stream.attributes().value("Current")
        logger.debug('Restore NodeDockArea Tabs: %s current: %s', tabs,
                     current_dock_widget)
        dock_area = None
        if not testing:
            dock_area = DockAreaWidget(self.dock_manager, self.public)

        while stream.readNextStartElement():
            if stream.name() != "Widget":
                continue

            object_name = stream.attributes().value("Name")
            if not object_name:
                return False, None

            closed = bool(int(stream.attributes().value("Closed")))

            stream.skipCurrentElement()
            dock_widget = self.dock_manager.find_dock_widget(object_name)
            if dock_widget and dock_area:
                logger.debug('Dock Widget found - parent %s',
                             dock_widget.parent())
                # We hide the DockArea here to prevent the short display (the flashing)
                # of the dock areas during application startup
                dock_area.hide()
                dock_area.add_dock_widget(dock_widget)
                dock_widget.set_toggle_view_action_checked(not closed)
                dock_widget.set_closed_state(closed)
                dock_widget.setProperty("closed", closed)
                dock_widget.setProperty("dirty", False)

        if testing:
            return True, None

        if not dock_area.dock_widgets_count():
            dock_area.deleteLater()
            dock_area = None
        else:
            dock_area.setProperty("currentDockWidget", current_dock_widget)
            self.append_dock_areas(dock_area)

        return True, dock_area
    def restore_splitter(self, stream: QXmlStreamReader,
                         testing: bool) -> Tuple[bool, Optional[QWidget]]:
        '''
        Restores a splitter.

        Parameters
        ----------
        stream : QXmlStreamReader
        created_widget : QWidget
        testing : bool

        Returns
        -------
        value : bool
        widget : QWidget
        '''
        orientation_str = stream.attributes().value("Orientation")
        if orientation_str.startswith("-"):
            orientation = Qt.Horizontal
        elif orientation_str.startswith("|"):
            orientation = Qt.Vertical
        else:
            return False, None

        widget_count = int(stream.attributes().value("Count"))
        if not widget_count:
            return False, None

        logger.debug('Restore NodeSplitter Orientation: %s  WidgetCount: %s',
                     orientation, widget_count)

        splitter = (None if testing else self.new_splitter(orientation))
        visible = False
        sizes = []

        while stream.readNextStartElement():
            child_node = None
            if stream.name() == "Splitter":
                result, child_node = self.restore_splitter(stream, testing)
                if not result:
                    return False, None
            elif stream.name() == "Area":
                result, child_node = self.restore_dock_area(stream, testing)
                if not result:
                    return False, None
            elif stream.name() == "Sizes":
                s_sizes = stream.readElementText().strip()
                sizes = [int(sz) for sz in s_sizes.split(' ')]
                logger.debug('Sizes: %s (from s_sizes: %s)', sizes, s_sizes)
            else:
                stream.skipCurrentElement()

            if splitter is not None and child_node is not None:
                logger.debug('ChildNode isVisible %s isVisibleTo %s',
                             child_node.isVisible(),
                             child_node.isVisibleTo(splitter))
                splitter.addWidget(child_node)
                visible |= child_node.isVisibleTo(splitter)

        if len(sizes) != widget_count:
            return False, None

        if testing:
            splitter = None
        else:
            if not splitter.count():
                splitter.deleteLater()
                splitter = None
            else:
                splitter.setSizes(sizes)
                splitter.setVisible(visible)

        return True, splitter