Esempio n. 1
0
    def read(self, stream: Stream, version):
        self.texture = stream.read_object('texture')
        self.color = stream.read_object('color')
        self.transparency_color = stream.read_object('transparency color')
        self.outline = stream.read_object('outline')
        self.angle = stream.read_double('angle')
        self.size = stream.read_double('size')

        stream.read_int('raster op', expected=13)
        self.symbol_level = stream.read_int('level')
Esempio n. 2
0
    def read(self, stream: Stream, version):
        self.ramp = stream.read_object('Color ramp')
        self.fill_color = stream.read_object('fill color')

        # either an entire LineSymbol or just a LineSymbolLayer
        self.outline = stream.read_object('outline')

        self.percent = stream.read_double('percent')
        self.intervals = stream.read_uint('intervals')
        self.angle = stream.read_double('angle')

        self.type = stream.read_uint('Gradient type')
        self.symbol_level = SymbolLayer.read_symbol_level(stream)
Esempio n. 3
0
    def read(self, stream: Stream, version):
        _ = stream.read_double('unused double')
        _ = stream.read_double('unused double')

        self.line = stream.read_object('pattern line')

        # either an entire LineSymbol or just a LineSymbolLayer
        self.outline = stream.read_object('outline')

        self.angle = stream.read_double('angle')
        self.offset = stream.read_double('offset')
        self.separation = stream.read_double('separation')

        self.symbol_level = SymbolLayer.read_symbol_level(stream)
Esempio n. 4
0
    def read(self, stream: Stream, version):
        self.flip = stream.read_uchar('flip') != 0
        self.offset = stream.read_double('offset')
        self.pattern_marker = stream.read_object('pattern marker')
        self.template = stream.read_object('template')
        self.decoration = stream.read_object('decoration')

        self.symbol_level = SymbolLayer.read_symbol_level(stream)
        self.decoration_on_top = stream.read_uchar('decoration on top') != 0
        self.line_start_offset = stream.read_double('line start offset')

        self.cap = self.read_cap(stream)
        self.join = self.read_join(stream)
        self.miter_limit = stream.read_double('miter limit')
Esempio n. 5
0
    def read(self, stream: Stream, version):
        """
        Reads the decoration information
        """
        self.fixed_angle = not bool(stream.read_uchar())
        stream.log('detected {}'.format(
            'fixed angle' if self.fixed_angle else 'not fixed angle'))
        self.flip_first = bool(stream.read_uchar())
        stream.log('detected {}'.format(
            'flip first' if self.flip_first else 'no flip first'))
        self.flip_all = bool(stream.read_uchar())
        stream.log('detected {}'.format(
            'flip all' if self.flip_all else 'no flip all'))

        self.position_as_ratio = stream.read_ushort('position as ratio') != 0

        self.marker = stream.read_object('marker')

        # next bit is the number of doubles coming next
        marker_number_positions = stream.read_uint('marker positions')

        # next bit is the positions themselves -- maybe we can infer this from the number of positions
        # alone. E.g. 2 positions = 0, 1. 3 positions = 0, 0.5, 1
        for _ in range(marker_number_positions):
            self.marker_positions.append(stream.read_double())
        stream.log('marker positions are {}'.format(self.marker_positions))
Esempio n. 6
0
    def read(self, stream: Stream, version):
        self.color = stream.read_object('color')
        self.width = stream.read_double('width')

        self.line_type = self.read_line_type(stream)
        stream.log('read line type of {}'.format(self.line_type))
        self.symbol_level = SymbolLayer.read_symbol_level(stream)
Esempio n. 7
0
 def read(self, stream: Stream, version):
     has_picture = stream.read_int('has picture') != 0
     stream.read_int('unknown')
     stream.read_int('unknown')
     stream.read_int('unknown')
     stream.read_int('unknown')
     stream.read_int('unknown')
     stream.read_int('unknown')
     stream.read_int('unknown')
     stream.read_int('unknown')
     self.transparency = stream.read_double('transparency')
     self.color = stream.read_object('color')
     self.transparent_texture_color = stream.read_object('transparent texture color')
     if has_picture:
         self.picture = BmpPicture()
         self.picture.read(stream, 1)
    def read(self, stream: Stream, version):
        self.color = stream.read_object('color')
        self.size_z = stream.read_double('size z')
        self.type = stream.read_int('type', expected=(0, 1, 2, 3, 4, 5, 6))
        self.quality = stream.read_double('quality')  # 0->1

        self.symbol_level = SymbolLayer.read_symbol_level(stream)

        self.z_rotation = stream.read_double('z rotation')
        self.x_offset = stream.read_double('x offset')
        self.y_offset = stream.read_double('y offset')
        self.z_offset = stream.read_double('z offset')
        stream.read_ushort('unknown', expected=65535)

        self.dx = stream.read_double('dx')
        self.dy = stream.read_double('dy')
        self.dz = stream.read_double('dz')

        self.x_rotation = stream.read_double('x rotation')
        self.y_rotation = stream.read_double('y rotation')

        self.width = stream.read_double('width')

        self.depth_y = stream.read_double('depth y')
        self.keep_aspect_ratio = stream.read_ushort('keep aspect ratio') != 0
        self.billboard_display = stream.read_ushort('display front face') != 0
Esempio n. 9
0
    def read(self, stream: Stream, version):
        self.color = stream.read_object('color')
        self.width = stream.read_double('width')
        self.type = stream.read_int('type', expected=(0, 1, 2))
        self.quality = stream.read_double('quality')

        self.symbol_level = SymbolLayer.read_symbol_level(stream)
    def run_symbol_checks(self, path):
        """
        Checks all bin symbols against expectations
        """

        blobs = []
        for fn in os.listdir(path):
            file = os.path.join(path, fn)
            if os.path.isfile(file):
                blobs.append(file)

        for file in blobs:
            print(file)
            group, symbol_name = os.path.split(file)
            path, group = os.path.split(group)

            with open(file, 'rb') as f:
                expected_symbol = expected[group][symbol_name]
                if 'skip' in expected_symbol:
                    continue
                stream = Stream(f, debug=False)

                color = stream.read_object()

                self.assertEqual(expected_symbol['color'], color.to_dict())
Esempio n. 11
0
    def read(self, stream: Stream, version):
        self.color = stream.read_object('color')
        self.size_z = stream.read_double('size z')

        self.geometry = stream.read_object('multipatch')

        stream.read_double('unknown', expected=0)
        stream.read_double('unknown', expected=0)
        stream.read_int('unknown', expected=9)

        self.origin_x = stream.read_double('origin x')
        self.origin_y = stream.read_double('origin y')
        self.origin_z = stream.read_double('origin z')
        self.material_draping = stream.read_ushort('no material draping') == 0

        stream.read_int('unknown', expected=13)
        stream.read_int('unknown', expected=0)

        self.rotation_z = stream.read_double('rotation z')
        self.offset_x = stream.read_double('offset x')
        self.offset_y = stream.read_double('offset y')
        self.offset_z = stream.read_double('offset z')

        stream.read_ushort('unknown', expected=65535)

        self.picture = stream.read_object('picture')

        self.rotation_x = stream.read_double('rotation x')
        self.rotation_y = stream.read_double('rotation y')
        self.size_x = stream.read_double('size x')
        self.size_y = stream.read_double('size y')
        self.keep_aspect = stream.read_ushort('keep aspect') != 0

        stream.read_ushort('unknown', expected=0)
        if version == 7:
            return

        self.display_face_front = stream.read_ushort('display face front') != 0
        if version < 7:
            stream.read_int('unknown', expected=0)
            stream.read_double('unknown')
            stream.read_ushort('unknown', expected=0)
            stream.read_ushort('unknown', expected=65535)

        if version > 8:
            stream.read_ushort('unknown', expected=0)
            stream.read_int('unknown', expected=0)
Esempio n. 12
0
    def read(self, stream: Stream, version):
        self.random = bool(stream.read_int('random'))
        self.offset_x = stream.read_double('offset x')
        self.offset_y = stream.read_double('offset y')
        self.separation_x = stream.read_double('separation x')
        self.separation_y = stream.read_double('separation y')
        _ = stream.read_double('unused double')
        _ = stream.read_double('unused double')

        self.marker = stream.read_object('fill marker')

        # either an entire LineSymbol or just a LineSymbolLayer
        self.outline = stream.read_object('outline')

        self.symbol_level = SymbolLayer.read_symbol_level(stream)

        self.grid_angle = stream.read_double('grid angle')
Esempio n. 13
0
 def read_symbol(_io_stream):
     """
     Reads a symbol from the specified file
     """
     stream = Stream(_io_stream, False, tolerant=False)
     res = stream.read_object('symbol')
     assert stream.tell() == stream.end, (stream.tell, stream.end)
     return res
Esempio n. 14
0
    def read(self, stream: Stream, version):
        self.symbol_level = SymbolLayer.read_symbol_level(stream)

        _ = stream.read_object('unused color')

        number_layers = stream.read_int('layers')
        for i in range(number_layers):
            layer = stream.read_object('symbol layer {}/{}'.format(i + 1, number_layers))
            self.layers.extend([layer])

        for l in self.layers:
            l.read_enabled(stream)
        for l in self.layers:
            l.read_locked(stream)

        if version >= 2:
            for l in self.layers:
                l.read_tags(stream)
Esempio n. 15
0
 def read(self, stream: Stream, version):
     """
     Reads the decoration information
     """
     # next bit is probably number of decorations?
     count = stream.read_uint('count of decorations')
     for i in range(count):
         decoration = stream.read_object('decoration element {}/{}'.format(i, count))
         self.decorations.append(decoration)
Esempio n. 16
0
 def check_handle(self, file_handle):
     try:
         stream = Stream(file_handle)
         o = stream.read_object()
         if o is not None:
             return PersistentMatch(file_handle.tell() - 1, 1, o)
         else:
             return None
     except:  # nopep8, pylint: disable=bare-except
         pass
     return None
Esempio n. 17
0
 def check_handle(self, file_handle):
     try:
         start = file_handle.tell()
         stream = Stream(file_handle)
         color = stream.read_object()
         if issubclass(color.__class__, Color):
             return ColorMatch(start, file_handle.tell() - start, color.color_model, color)
         else:
             return None
     except:  # nopep8, pylint: disable=bare-except
         pass
     return None
Esempio n. 18
0
    def read(self, stream: Stream, version):
        self.color = stream.read_object('color')

        self.size = stream.read_double('size')
        self.width = stream.read_double('width')
        self.angle = stream.read_double('angle')
        self.style = stream.read_uint('style')
        self.symbol_level = SymbolLayer.read_symbol_level(stream)

        self.x_offset = stream.read_double('x offset')
        self.y_offset = stream.read_double('y offset')

        self.rotate_with_transform = stream.read_ushort('rotate with transform') != 0
Esempio n. 19
0
    def read(self, stream: Stream, version):
        self.color = stream.read_object('color')

        stream.read_int('raster op', expected=13)
        stream.read_int('unknown', expected=0)
        stream.read_int(
            'unknown'
        )  # expected=(0,194149600, 239970880, 324278056, 6757008) )

        self.color_ramp = stream.read_object('color ramp')

        self.invert = stream.read_ushort('invert') != 0
        self.legend_class_index = stream.read_int('legend class index')
        if 2 < version < 5:
            stream.read_int('unknown', expected=0)
            stream.read_ushort('unknown', expected=0)
        elif version >= 5:
            stream.read_ushort('unknown', expected=0)
            stream.read_int('unknown', expected=0)
            self.number_of_label = stream.read_int('number of labels')
            self.horizontal = stream.read_ushort('horizontal') != 0
            self.show_ticks = stream.read_ushort('show ticks') != 0
Esempio n. 20
0
    def read(self, stream: Stream, version):
        if version <= 4:
            self.picture = stream.read_object('picture')
        elif version == 7:
            _ = stream.read_ushort('pic version?')
            _ = stream.read_uint('picture type?')
            self.picture = stream.read_object('picture')
        elif version == 8:
            self.picture = Picture.create_from_stream(stream)

        self.color_background = stream.read_object('color bg')
        self.color_foreground = stream.read_object('color fg')
        self.color_transparent = stream.read_object('color trans')

        # either an entire LineSymbol or just a LineSymbolLayer
        self.outline = stream.read_object('outline')

        self.angle = stream.read_double('angle')
        self.scale_x = stream.read_double('scale_x')
        self.scale_y = stream.read_double('scale_y')

        self.offset_x = stream.read_double('offset x')
        self.offset_y = stream.read_double('offset y')
        self.separation_x = stream.read_double('separation x')
        self.separation_y = stream.read_double('separation y')

        stream.read(16)

        self.symbol_level = SymbolLayer.read_symbol_level(stream)

        self.swap_fb_gb = bool(stream.read_uchar('swap fgbg'))

        if version < 4:
            return

        stream.read(6)
        if 4 < version < 8:
            stream.read(4)
Esempio n. 21
0
    def read(self, stream: Stream, version):
        self.symbol_level = SymbolLayer.read_symbol_level(stream)

        # consume unused properties - MultiLayerMarkerSymbol implements IMarkerSymbol
        # so that the size/offsets/angle are required properties. But they aren't used
        # or exposed anywhere for MultiLayerMarkerSymbol
        _ = stream.read_double('unused marker size')
        _ = stream.read_double('unused marker x/y/offset or angle')
        _ = stream.read_double('unused marker x/y/offset or angle')
        _ = stream.read_double('unused marker x/y/offset or angle')
        _ = stream.read_object('unused color')

        self.halo = stream.read_int() == 1
        self.halo_size = stream.read_double('halo size')

        self.halo_symbol = stream.read_object('halo')

        # useful stuff
        number_layers = stream.read_int('layers')
        for i in range(number_layers):
            layer = stream.read_object('symbol layer {}/{}'.format(
                i + 1, number_layers))
            self.layers.extend([layer])

        for layer in self.layers:
            layer.read_enabled(stream)
        for layer in self.layers:
            layer.read_locked(stream)

        if version > 1:
            _ = stream.read_double('unknown size')
            _ = stream.read_double('unknown size')

        if version >= 3:
            for layer in self.layers:
                layer.read_tags(stream)
Esempio n. 22
0
    def read(self, stream: Stream, version):
        if version in (3, 4, 5):
            self.picture = stream.read_object('picture')
        elif version in (7, 8):
            _ = stream.read_ushort('pic version?')
            _ = stream.read_uint('picture type?')
            self.picture = stream.read_object('picture')
        elif version == 9:
            self.picture = Picture.create_from_stream(stream)

        if version < 4:
            _ = stream.read_object()
        if version <= 8:
            _ = stream.read_object()

        self.color_foreground = stream.read_object('color 1')
        self.color_background = stream.read_object('color 2')

        if version >= 9:
            self.color_transparent = stream.read_object('color 3')

        self.angle = stream.read_double('angle')
        self.size = stream.read_double('size')
        self.x_offset = stream.read_double('x offset')
        self.y_offset = stream.read_double('y offset')

        self.x_scale = stream.read_double('x scale')
        self.y_scale = stream.read_double('y scale')

        self.symbol_level = SymbolLayer.read_symbol_level(stream)
        self.swap_fb_gb = bool(stream.read_uchar('swap fgbg'))

        self.rotate_with_transform = stream.read_ushort(
            'rotate with transform') != 0

        if version < 5:
            return

        stream.read_int('unknown', expected=0)
        stream.read_ushort('unknown', expected=0)
        if version == 7:
            return

        if 5 < version <= 8:
            size = stream.read_int('unknown size')
            stream.read(size)
Esempio n. 23
0
    def read(self, stream: Stream, version):
        size = stream.read_int('size')
        # TODO - reverse engineer
        stream.read(size)

        self.crs = stream.read_object('crs')
Esempio n. 24
0
    def processAlgorithm(
            self,  # pylint: disable=missing-docstring,too-many-locals,too-many-statements
            parameters,
            context,
            feedback):
        input_file = self.parameterAsString(parameters, self.INPUT, context)
        output_file = self.parameterAsFileOutput(parameters, self.OUTPUT,
                                                 context)

        results = {}
        colors = []

        _, file_name = os.path.split(input_file)
        file_name, _ = os.path.splitext(file_name)

        feedback.pushInfo('Importing colors from {}'.format(input_file))

        try:
            raw_colors = Extractor.extract_styles(input_file, Extractor.COLORS)
        except MissingBinaryException:
            raise QgsProcessingException(  # pylint: disable=raise-missing-from
                'The MDB tools "mdb-export" utility is required to convert .style databases. Please setup a path to the MDB tools utility in the SLYR options panel.'
            )

        feedback.pushInfo('Found {} colors'.format(len(raw_colors)))

        unreadable = 0
        for index, raw_color in enumerate(raw_colors):
            feedback.setProgress(index / len(raw_colors) * 100)
            if feedback.isCanceled():
                break

            name = raw_color[Extractor.NAME]
            feedback.pushInfo('{}/{}: {}'.format(index + 1, len(raw_colors),
                                                 name))

            handle = BytesIO(raw_color[Extractor.BLOB])
            stream = Stream(handle)
            try:
                color = stream.read_object()
            except InvalidColorException:
                feedback.reportError('Error reading color {}'.format(name),
                                     False)
                unreadable += 1
                continue

            qcolor = ColorConverter.color_to_qcolor(color)
            colors.append((name, qcolor))

        results[self.COLOR_COUNT] = len(raw_colors)
        results[self.UNREADABLE_COLOR_COUNT] = unreadable

        with open(output_file, 'wt') as f:
            f.write('GIMP Palette\n')
            f.write('Name: {}\n'.format(file_name))
            f.write('Columns: 4\n')
            f.write('#\n')
            for c in colors:
                f.write('{} {} {} {}\n'.format(c[1].red(), c[1].green(),
                                               c[1].blue(), c[0]))

        results[self.OUTPUT] = output_file
        return results
Esempio n. 25
0
 def read(self, stream: Stream, version):
     stream.read_uchar('unknown', expected=0)
     self.offset = stream.read_double('offset')
     self.width = stream.read_double('width')
     self.fill_symbol = stream.read_object('fill symbol')
Esempio n. 26
0
    def processAlgorithm(
            self,  # pylint:disable=missing-docstring,too-many-locals,too-many-statements,too-many-branches
            parameters,
            context,
            feedback):
        input_file = self.parameterAsString(parameters, self.INPUT, context)
        output_file = self.parameterAsFileOutput(parameters, self.OUTPUT,
                                                 context)

        fields = QgsFields()
        fields.append(QgsField('name', QVariant.String, '', 60))
        fields.append(QgsField('warning', QVariant.String, '', 250))

        sink, dest = self.parameterAsSink(parameters, self.REPORT, context,
                                          fields)

        style = QgsStyle()
        style.createMemoryDatabase()

        results = {}

        symbol_names = set()

        def make_name_unique(name):
            """
            Ensures that the symbol name is unique (in a case insensitive way)
            """
            counter = 0
            candidate = name
            while candidate.lower() in symbol_names:
                # make name unique
                if counter == 0:
                    candidate += '_1'
                else:
                    candidate = candidate[:candidate.rfind('_') +
                                          1] + str(counter)
                counter += 1
            symbol_names.add(candidate.lower())
            return candidate

        symbols_to_extract = [
            Extractor.FILL_SYMBOLS, Extractor.LINE_SYMBOLS,
            Extractor.MARKER_SYMBOLS, Extractor.COLOR_RAMPS,
            Extractor.LINE_PATCHES, Extractor.AREA_PATCHES
        ]
        if Qgis.QGIS_VERSION_INT >= 30900:
            symbols_to_extract.extend(
                (Extractor.TEXT_SYMBOLS, Extractor.LABELS,
                 Extractor.MAPLEX_LABELS))

        type_percent = 100.0 / len(symbols_to_extract)

        results[self.LABEL_SETTINGS_COUNT] = 0
        results[self.UNREADABLE_LABEL_SETTINGS] = 0

        for type_index, symbol_type in enumerate(symbols_to_extract):
            feedback.pushInfo('Importing {} from {}'.format(
                symbol_type, input_file))

            try:
                raw_symbols = Extractor.extract_styles(input_file, symbol_type)
            except MissingBinaryException:
                raise QgsProcessingException(  # pylint: disable=raise-missing-from
                    'The MDB tools "mdb-export" utility is required to convert .style databases. Please setup a path to the MDB tools utility in the SLYR options panel.'
                )

            feedback.pushInfo('Found {} symbols of type "{}"\n\n'.format(
                len(raw_symbols), symbol_type))

            if feedback.isCanceled():
                break

            unreadable = 0
            for index, raw_symbol in enumerate(raw_symbols):
                feedback.setProgress(index / len(raw_symbols) * type_percent +
                                     type_percent * type_index)
                if feedback.isCanceled():
                    break
                name = raw_symbol[Extractor.NAME]
                tags = raw_symbol[Extractor.TAGS].split(';')
                feedback.pushInfo('{}/{}: {}'.format(index + 1,
                                                     len(raw_symbols), name))

                if symbol_type in (Extractor.AREA_PATCHES,
                                   Extractor.LINE_PATCHES,
                                   Extractor.TEXT_SYMBOLS,
                                   Extractor.MAPLEX_LABELS, Extractor.LABELS):
                    if symbol_type == Extractor.AREA_PATCHES:
                        type_string = 'area patches'
                    elif symbol_type == Extractor.LINE_PATCHES:
                        type_string = 'line patches'
                    elif symbol_type == Extractor.TEXT_SYMBOLS:
                        type_string = 'text symbols'
                    elif symbol_type == Extractor.MAPLEX_LABELS:
                        type_string = 'maplex labels'
                    elif symbol_type == Extractor.LABELS:
                        type_string = 'labels'
                    else:
                        type_string = ''

                    feedback.reportError(
                        'Converting {} is available in the licensed version of SLYR only - please see https://north-road.com/slyr/ for details'
                        .format(type_string))
                    unreadable += 1
                    continue

                unique_name = make_name_unique(name)
                if name != unique_name:
                    feedback.pushInfo(
                        'Corrected to unique name of {}'.format(unique_name))

                handle = BytesIO(raw_symbol[Extractor.BLOB])
                stream = Stream(handle)

                f = QgsFeature()
                try:
                    symbol = stream.read_object()
                except UnreadableSymbolException as e:
                    feedback.reportError(
                        'Error reading symbol {}: {}'.format(name, e), False)
                    unreadable += 1
                    if sink:
                        f.setAttributes(
                            [name, 'Error reading symbol: {}'.format(e)])
                        sink.addFeature(f)
                    continue
                except NotImplementedException as e:
                    feedback.reportError(
                        'Parsing {} is not supported: {}'.format(name, e),
                        False)
                    unreadable += 1
                    if sink:
                        f.setAttributes(
                            [name, 'Parsing not supported: {}'.format(e)])
                        sink.addFeature(f)
                    continue
                except UnsupportedVersionException as e:
                    feedback.reportError(
                        'Cannot read {} version: {}'.format(name, e), False)
                    unreadable += 1
                    if sink:
                        f.setAttributes(
                            [name, 'Version not supported: {}'.format(e)])
                        sink.addFeature(f)
                    continue
                except UnknownClsidException as e:
                    feedback.reportError(str(e), False)
                    unreadable += 1
                    if sink:
                        f.setAttributes([name, 'Unknown object: {}'.format(e)])
                        sink.addFeature(f)
                    continue
                except UnreadablePictureException as e:
                    feedback.reportError(str(e), False)
                    unreadable += 1
                    if sink:
                        f.setAttributes(
                            [name, 'Unreadable picture: {}'.format(e)])
                        sink.addFeature(f)
                    continue

                def unsupported_object_callback(msg, level=Context.WARNING):
                    if level == Context.WARNING:
                        feedback.reportError('Warning: {}'.format(msg), False)
                    elif level == Context.CRITICAL:
                        feedback.reportError(msg, False)

                    if sink:
                        f = QgsFeature()
                        f.setAttributes([name, msg])  # pylint: disable=cell-var-from-loop
                        sink.addFeature(f)

                context = Context()
                context.symbol_name = unique_name
                context.style_folder, _ = os.path.split(output_file)
                context.unsupported_object_callback = unsupported_object_callback

                try:
                    qgis_symbol = SymbolConverter.Symbol_to_QgsSymbol(
                        symbol, context)

                except NotImplementedException as e:
                    feedback.reportError(str(e), False)
                    unreadable += 1
                    if sink:
                        f.setAttributes([name, str(e)])
                        sink.addFeature(f)
                    continue
                except UnreadablePictureException as e:
                    feedback.reportError(str(e), False)
                    unreadable += 1
                    if sink:
                        f.setAttributes(
                            [name, 'Unreadable picture: {}'.format(e)])
                        sink.addFeature(f)
                    continue

                if isinstance(qgis_symbol, QgsSymbol):
                    style.addSymbol(unique_name, qgis_symbol, True)
                elif isinstance(qgis_symbol, QgsColorRamp):
                    style.addColorRamp(unique_name, qgis_symbol, True)

                if tags:
                    if isinstance(qgis_symbol, QgsSymbol):
                        assert style.tagSymbol(QgsStyle.SymbolEntity,
                                               unique_name, tags)
                    elif isinstance(qgis_symbol, QgsColorRamp):
                        assert style.tagSymbol(QgsStyle.ColorrampEntity,
                                               unique_name, tags)

            if symbol_type == Extractor.FILL_SYMBOLS:
                results[self.FILL_SYMBOL_COUNT] = len(raw_symbols)
                results[self.UNREADABLE_FILL_SYMBOLS] = unreadable
            elif symbol_type == Extractor.LINE_SYMBOLS:
                results[self.LINE_SYMBOL_COUNT] = len(raw_symbols)
                results[self.UNREADABLE_LINE_SYMBOLS] = unreadable
            elif symbol_type == Extractor.MARKER_SYMBOLS:
                results[self.MARKER_SYMBOL_COUNT] = len(raw_symbols)
                results[self.UNREADABLE_MARKER_SYMBOLS] = unreadable
            elif symbol_type == Extractor.COLOR_RAMPS:
                results[self.COLOR_RAMP_COUNT] = len(raw_symbols)
                results[self.UNREADABLE_COLOR_RAMPS] = unreadable
            elif symbol_type == Extractor.TEXT_SYMBOLS:
                results[self.TEXT_FORMAT_COUNT] = len(raw_symbols)
                results[self.UNREADABLE_TEXT_FORMATS] = unreadable
            elif symbol_type in (Extractor.MAPLEX_LABELS, Extractor.LABELS):
                results[self.LABEL_SETTINGS_COUNT] += len(raw_symbols)
                results[self.UNREADABLE_LABEL_SETTINGS] += unreadable
            elif symbol_type == Extractor.LINE_PATCHES:
                results[self.LINE_PATCH_COUNT] = len(raw_symbols)
                results[self.UNREADABLE_LINE_PATCHES] = unreadable
            elif symbol_type == Extractor.AREA_PATCHES:
                results[self.AREA_PATCH_COUNT] = len(raw_symbols)
                results[self.UNREADABLE_AREA_PATCHES] = unreadable

        style.exportXml(output_file)
        results[self.OUTPUT] = output_file
        results[self.REPORT] = dest
        return results
Esempio n. 27
0
 def read(self, stream: Stream, version):
     # first bit is either an entire LineSymbol or just a LineSymbolLayer
     self.outline = stream.read_object('outline')
     self.color = stream.read_object('color')
     self.symbol_level = SymbolLayer.read_symbol_level(stream)
     self.fill_style = stream.read_int('fill style')
Esempio n. 28
0
 def read(self, stream: Stream, version):
     self.color = stream.read_object('color')
     self.symbol_level = SymbolLayer.read_symbol_level(stream)
     stream.read_int('unknown int')
Esempio n. 29
0
 def read(self, stream: Stream, version):
     self.width = stream.read_double('width')
     self.texture_fill_symbol = stream.read_object('texture fill symbol')
     self.vertical_orientation = stream.read_uchar(
         'vertical orientation') != 0
Esempio n. 30
0
    def open_style(input_file):  # pylint: disable=too-many-locals,too-many-branches,too-many-statements
        """
        Opens a .style file
        """

        if not Extractor.is_mdb_tools_binary_available():
            bar = iface.messageBar()
            widget = bar.createMessage('SLYR', "MDB Tools utility not found")
            settings_button = QPushButton("Configure…", pressed=partial(open_settings, widget))
            widget.layout().addWidget(settings_button)
            bar.pushWidget(widget, Qgis.Critical)
            return True

        style = QgsStyle()
        style.createMemoryDatabase()

        symbol_names = set()

        def make_name_unique(name):
            """
            Ensures that the symbol name is unique (in a case insensitive way)
            """
            counter = 0
            candidate = name
            while candidate.lower() in symbol_names:
                # make name unique
                if counter == 0:
                    candidate += '_1'
                else:
                    candidate = candidate[:candidate.rfind('_') + 1] + str(counter)
                counter += 1
            symbol_names.add(candidate.lower())
            return candidate

        feedback = QgsFeedback()

        progress_dialog = QProgressDialog("Loading style database…", "Abort", 0, 100, None)
        progress_dialog.setWindowTitle("Loading Style")

        def progress_changed(progress):
            """
            Handles feedback to progress dialog bridge
            """
            progress_dialog.setValue(progress)
            iters = 0
            while QCoreApplication.hasPendingEvents() and iters < 100:
                QCoreApplication.processEvents()
                iters += 1

        feedback.progressChanged.connect(progress_changed)

        def cancel():
            """
            Slot to cancel the import
            """
            feedback.cancel()

        progress_dialog.canceled.connect(cancel)
        unreadable = []
        warnings = set()
        errors = set()

        types_to_extract = [Extractor.FILL_SYMBOLS, Extractor.LINE_SYMBOLS, Extractor.MARKER_SYMBOLS,
                            Extractor.COLOR_RAMPS,
                            Extractor.TEXT_SYMBOLS, Extractor.LABELS, Extractor.MAPLEX_LABELS, Extractor.AREA_PATCHES,
                            Extractor.LINE_PATCHES]

        type_percent = 100 / len(types_to_extract)

        for type_index, symbol_type in enumerate(types_to_extract):

            try:
                raw_symbols = Extractor.extract_styles(input_file, symbol_type)
            except MissingBinaryException:
                show_warning('MDB Tools utility not found', 'Convert style',
                             'The MDB tools "mdb-export" utility is required to convert .style databases. Please setup a path to the MDB tools utility in the SLYR options panel.',
                             level=Qgis.Critical)
                progress_dialog.deleteLater()
                return True

            if feedback.isCanceled():
                break

            for index, raw_symbol in enumerate(raw_symbols):
                feedback.setProgress(index / len(raw_symbols) * type_percent + type_percent * type_index)
                if feedback.isCanceled():
                    break
                name = raw_symbol[Extractor.NAME]
                tags = raw_symbol[Extractor.TAGS].split(';')

                if symbol_type in (
                        Extractor.AREA_PATCHES, Extractor.LINE_PATCHES, Extractor.TEXT_SYMBOLS, Extractor.MAPLEX_LABELS,
                        Extractor.LABELS):
                    if symbol_type == Extractor.AREA_PATCHES:
                        type_string = 'area patches'
                    elif symbol_type == Extractor.LINE_PATCHES:
                        type_string = 'line patches'
                    elif symbol_type == Extractor.TEXT_SYMBOLS:
                        type_string = 'text symbols'
                    elif symbol_type == Extractor.MAPLEX_LABELS:
                        type_string = 'maplex labels'
                    elif symbol_type == Extractor.LABELS:
                        type_string = 'labels'
                    else:
                        type_string = ''

                    unreadable.append('<b>{}</b>: {} conversion requires a licensed version of the SLYR plugin'.format(
                        html.escape(name), type_string))
                    continue

                unique_name = make_name_unique(name)

                handle = BytesIO(raw_symbol[Extractor.BLOB])
                stream = Stream(handle)
                stream.allow_shortcuts = False

                try:
                    symbol = stream.read_object()
                except UnreadableSymbolException as e:
                    e = 'Unreadable object: {}'.format(e)
                    unreadable.append('<b>{}</b>: {}'.format(html.escape(name), html.escape(str(e))))
                    continue
                except NotImplementedException as e:
                    unreadable.append('<b>{}</b>: {}'.format(html.escape(name), html.escape(str(e))))
                    continue
                except UnsupportedVersionException as e:
                    e = 'Unsupported version: {}'.format(e)
                    unreadable.append('<b>{}</b>: {}'.format(html.escape(name), html.escape(str(e))))
                    continue
                except UnknownClsidException as e:
                    unreadable.append('<b>{}</b>: {}'.format(html.escape(name), html.escape(str(e))))
                    continue
                except UnreadablePictureException as e:
                    unreadable.append('<b>{}</b>: {}'.format(html.escape(name), html.escape(str(e))))
                    continue

                context = Context()
                context.symbol_name = unique_name

                def unsupported_object_callback(msg, level=Context.WARNING):
                    if level == Context.WARNING:
                        warnings.add('<b>{}</b>: {}'.format(html.escape(unique_name), html.escape(msg)))
                    elif level == Context.CRITICAL:
                        errors.add('<b>{}</b>: {}'.format(html.escape(unique_name), html.escape(msg)))

                context.unsupported_object_callback = unsupported_object_callback
                # context.style_folder, _ = os.path.split(output_file)

                try:
                    qgis_symbol = SymbolConverter.Symbol_to_QgsSymbol(symbol, context)
                except NotImplementedException as e:
                    unreadable.append('<b>{}</b>: {}'.format(html.escape(name), html.escape(str(e))))
                    continue
                except UnreadablePictureException as e:
                    unreadable.append('<b>{}</b>: {}'.format(html.escape(name), html.escape(str(e))))
                    continue

                if isinstance(qgis_symbol, QgsSymbol):
                    # self.check_for_missing_fonts(qgis_symbol, feedback)
                    style.addSymbol(unique_name, qgis_symbol, True)
                elif isinstance(qgis_symbol, QgsColorRamp):
                    style.addColorRamp(unique_name, qgis_symbol, True)

                if tags:
                    if isinstance(qgis_symbol, QgsSymbol):
                        assert style.tagSymbol(QgsStyle.SymbolEntity, unique_name, tags)
                    elif isinstance(qgis_symbol, QgsColorRamp):
                        assert style.tagSymbol(QgsStyle.ColorrampEntity, unique_name, tags)
        progress_dialog.deleteLater()
        if feedback.isCanceled():
            return True

        if errors or unreadable or warnings:
            message = ''
            if unreadable:
                message = '<p>The following symbols could not be converted:</p>'
                message += '<ul>'
                for w in unreadable:
                    message += '<li>{}</li>'.format(w.replace('\n', '<br>'))
                message += '</ul>'

            if errors:
                message += '<p>The following errors were generated while converting symbols:</p>'
                message += '<ul>'
                for w in errors:
                    message += '<li>{}</li>'.format(w.replace('\n', '<br>'))
                message += '</ul>'

            if warnings:
                message += '<p>The following warnings were generated while converting symbols:</p>'
                message += '<ul>'
                for w in warnings:
                    message += '<li>{}</li>'.format(w.replace('\n', '<br>'))
                message += '</ul>'

            show_warning('style could not be completely converted', 'Convert style', message,
                         level=Qgis.Critical if (unreadable or errors) else Qgis.Warning)

        if Qgis.QGIS_VERSION_INT >= 30800:
            dlg = QgsStyleManagerDialog(style, readOnly=True)
            dlg.setFavoritesGroupVisible(False)
            dlg.setSmartGroupsVisible(False)
            fi = QFileInfo(input_file)
            dlg.setBaseStyleName(fi.baseName())
        else:
            dlg = QgsStyleManagerDialog(style)
        dlg.exec_()
        return True