Пример #1
0
    def restore_state_from_xml(self, state: QByteArray, version: int,
                               testing: bool) -> bool:
        '''
        Restores the state

        Parameters
        ----------
        state : QByteArray
        version : int
        testing : bool

        Returns
        -------
        value : bool
        '''
        if state.isEmpty():
            return False

        stream = QXmlStreamReader(state)
        stream.readNextStartElement()
        if stream.name() != "QtAdvancedDockingSystem":
            return False

        v = stream.attributes().value("Version")
        if int(v) != version:
            return False

        result = True
        dock_containers = stream.attributes().value("Containers")
        logger.debug('dock_containers %s', dock_containers)
        dock_container_count = 0
        while stream.readNextStartElement():
            if stream.name() == "Container":
                result = self.restore_container(dock_container_count,
                                                stream,
                                                testing=testing)
                if not result:
                    break
                dock_container_count += 1

        if testing or not dock_container_count:
            return result

        # Delete remaining empty floating widgets
        floating_widget_index = dock_container_count - 1
        delete_count = len(self.floating_widgets) - floating_widget_index

        for i in range(delete_count):
            to_remove = self.floating_widgets[floating_widget_index + i]
            self.public.remove_dock_container(to_remove.dock_container())
            to_remove.deleteLater()

        return result
    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
    def restore_state(self,
                      stream: QXmlStreamReader,
                      testing: bool = False) -> bool:
        '''
        Restores the state from given stream.

        Parameters
        ----------
        stream : QXmlStreamReader
        testing : bool
            If Testing is true, the function only parses the data from the
            given stream but does not restore anything. You can use this check
            for faulty files before you start restoring the state

        Returns
        -------
        value : bool
        '''
        is_floating = bool(int(stream.attributes().value("Floating")))
        logger.debug('Restore DockContainerWidget Floating %s', is_floating)

        if not testing:
            self.d._visible_dock_area_count = -1

            # invalidate the dock area count and clear the area cache
            self.d.dock_areas.clear()
            self.d.last_added_area_cache.clear()

        if is_floating:
            logger.debug('Restore floating widget')
            if not stream.readNextStartElement(
            ) or stream.name() != "Geometry":
                return False

            geometry_string = stream.readElementText(
                QXmlStreamReader.ErrorOnUnexpectedElement)

            geometry = QByteArray.fromHex(geometry_string)
            if geometry.isEmpty():
                return False

            if not testing:
                floating_widget = self.floating_widget()
                floating_widget.restoreGeometry(geometry)

        res, new_root_splitter = self.d.restore_child_nodes(stream, testing)
        if not res:
            return False

        if testing:
            return True

        # If the root splitter is empty, rostoreChildNodes returns a 0 pointer
        # and we need to create a new empty root splitter
        if not new_root_splitter:
            new_root_splitter = self.d.new_splitter(Qt.Horizontal)

        self.d.layout.replaceWidget(self.d.root_splitter, new_root_splitter)
        old_root = self.d.root_splitter
        self.d.root_splitter = new_root_splitter
        old_root.deleteLater()
        return True