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_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_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
def colorize_svg( src: Union[str, Path, IO[bytes]], dst: Union[None, str, Path, BinaryIO]=None, *, selected: bool=False, app: Optional[QApplication]=None, ) -> bytes: """Inject colors into a breeze-style SVG. :param src: A file object or path to read SVG data from. :param dst: A file object or path to write SVG data to. :param selected: Use selection colors? :param app: Currently running QApplication. Uses QApplication.instance() by default. :return: Returns the SVG as binary data. """ if app is None: app = QApplication.instance() sheet = get_sheet(selected, app) if hasattr(src, 'read'): raw = src.read() else: path = Path(src) with gzip.open(str(path)) if path.suffix == '.svgz' else path.open('rb') as f: raw = f.read() processed = QByteArray() reader = QXmlStreamReader(raw) writer = QXmlStreamWriter(processed) while not reader.atEnd(): if ( reader.readNext() == QXmlStreamReader.StartElement and reader.qualifiedName() == 'style' and reader.attributes().value('id') == 'current-color-scheme' ): writer.writeStartElement('style') writer.writeAttributes(reader.attributes()) writer.writeCharacters(sheet) writer.writeEndElement() while reader.tokenType() != QXmlStreamReader.EndElement: reader.readNext() elif reader.tokenType() != QXmlStreamReader.Invalid: writer.writeCurrentToken(reader) processed = bytes(processed) if hasattr(dst, 'write'): dst.write(processed) elif dst is not None: with Path(dst).open('wb'): dst.write(processed) return processed