def test_tags_changed(self): style = QgsStyle() style.createMemoryDatabase() model = QgsStyleModel(style) symbol = createMarkerSymbol() self.assertTrue(style.addSymbol('a', symbol, True)) symbol = createMarkerSymbol() self.assertTrue(style.addSymbol('c', symbol, True)) ramp_a = QgsLimitedRandomColorRamp(5) self.assertTrue(style.addColorRamp('ramp a', ramp_a, True)) symbol_B = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('ramp c', symbol_B, True)) self.assertFalse(model.data(model.index(0, 1), Qt.DisplayRole)) self.assertFalse(model.data(model.index(1, 1), Qt.DisplayRole)) self.assertFalse(model.data(model.index(2, 1), Qt.DisplayRole)) self.assertFalse(model.data(model.index(3, 1), Qt.DisplayRole)) style.tagSymbol(QgsStyle.SymbolEntity, 'a', ['t1', 't2']) self.assertEqual(model.data(model.index(0, 1), Qt.DisplayRole), 't1, t2') self.assertFalse(model.data(model.index(1, 1), Qt.DisplayRole)) self.assertFalse(model.data(model.index(2, 1), Qt.DisplayRole)) self.assertFalse(model.data(model.index(3, 1), Qt.DisplayRole)) style.tagSymbol(QgsStyle.SymbolEntity, 'a', ['t3']) self.assertEqual(model.data(model.index(0, 1), Qt.DisplayRole), 't1, t2, t3') self.assertFalse(model.data(model.index(1, 1), Qt.DisplayRole)) self.assertFalse(model.data(model.index(2, 1), Qt.DisplayRole)) self.assertFalse(model.data(model.index(3, 1), Qt.DisplayRole)) style.tagSymbol(QgsStyle.ColorrampEntity, 'ramp a', ['t1', 't2']) self.assertEqual(model.data(model.index(0, 1), Qt.DisplayRole), 't1, t2, t3') self.assertFalse(model.data(model.index(1, 1), Qt.DisplayRole)) self.assertEqual(model.data(model.index(2, 1), Qt.DisplayRole), 't1, t2') self.assertFalse(model.data(model.index(3, 1), Qt.DisplayRole)) style.tagSymbol(QgsStyle.ColorrampEntity, 'ramp c', ['t3']) self.assertEqual(model.data(model.index(0, 1), Qt.DisplayRole), 't1, t2, t3') self.assertFalse(model.data(model.index(1, 1), Qt.DisplayRole)) self.assertEqual(model.data(model.index(2, 1), Qt.DisplayRole), 't1, t2') self.assertEqual(model.data(model.index(3, 1), Qt.DisplayRole), 't3') style.tagSymbol(QgsStyle.SymbolEntity, 'c', ['t4']) self.assertEqual(model.data(model.index(0, 1), Qt.DisplayRole), 't1, t2, t3') self.assertEqual(model.data(model.index(1, 1), Qt.DisplayRole), 't4') self.assertEqual(model.data(model.index(2, 1), Qt.DisplayRole), 't1, t2') self.assertEqual(model.data(model.index(3, 1), Qt.DisplayRole), 't3') style.detagSymbol(QgsStyle.SymbolEntity, 'c', ['t4']) self.assertEqual(model.data(model.index(0, 1), Qt.DisplayRole), 't1, t2, t3') self.assertFalse(model.data(model.index(1, 1), Qt.DisplayRole)) self.assertEqual(model.data(model.index(2, 1), Qt.DisplayRole), 't1, t2') self.assertEqual(model.data(model.index(3, 1), Qt.DisplayRole), 't3') style.detagSymbol(QgsStyle.ColorrampEntity, 'ramp a', ['t1']) self.assertEqual(model.data(model.index(0, 1), Qt.DisplayRole), 't1, t2, t3') self.assertFalse(model.data(model.index(1, 1), Qt.DisplayRole)) self.assertEqual(model.data(model.index(2, 1), Qt.DisplayRole), 't2') self.assertEqual(model.data(model.index(3, 1), Qt.DisplayRole), 't3')
def test_style_with_ramps(self): style = QgsStyle() style.createMemoryDatabase() # style with only ramps ramp_a = QgsLimitedRandomColorRamp(5) self.assertTrue(style.addColorRamp('a', ramp_a, True)) style.tagSymbol(QgsStyle.ColorrampEntity, 'a', ['tag 1', 'tag 2']) symbol_B = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('B ', symbol_B, True)) symbol_b = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('b', symbol_b, True)) symbol_C = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('C', symbol_C, True)) style.tagSymbol(QgsStyle.ColorrampEntity, 'C', ['tag 3']) symbol_C = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp(' ----c/- ', symbol_C, True)) model = QgsStyleModel(style) self.assertEqual(model.rowCount(), 5) self.assertEqual(model.columnCount(), 2) self.assertTrue(model.index(0, 0).isValid()) self.assertFalse(model.index(10, 0).isValid()) self.assertFalse(model.index(0, 10).isValid()) self.assertFalse(model.parent(model.index(0, 0)).isValid()) for role in (Qt.DisplayRole, Qt.EditRole): self.assertIsNone(model.data(model.index(-1, 0), role)) self.assertIsNone(model.data(model.index(-1, 1), role)) self.assertEqual(model.data(model.index(0, 0), role), ' ----c/- ') self.assertFalse(model.data(model.index(0, 1), role)) self.assertIsNone(model.data(model.index(0, 2), role)) self.assertIsNone(model.data(model.index(0, -1), role)) self.assertEqual(model.data(model.index(1, 0), role), 'B ') self.assertFalse(model.data(model.index(1, 1), role)) self.assertEqual(model.data(model.index(2, 0), role), 'C') self.assertEqual(model.data(model.index(2, 1), role), 'tag 3') self.assertEqual(model.data(model.index(3, 0), role), 'a') self.assertEqual(model.data(model.index(3, 1), role), 'tag 1, tag 2') self.assertEqual(model.data(model.index(4, 0), role), 'b') self.assertFalse(model.data(model.index(4, 1), role)) self.assertIsNone(model.data(model.index(5, 0), role)) self.assertIsNone(model.data(model.index(5, 1), role)) # decorations self.assertIsNone(model.data(model.index(-1, 0), Qt.DecorationRole)) self.assertIsNone(model.data(model.index(0, 1), Qt.DecorationRole)) self.assertIsNone(model.data(model.index(5, 0), Qt.DecorationRole)) self.assertFalse(model.data(model.index(0, 0), Qt.DecorationRole).isNull()) self.assertEqual(model.data(model.index(0, 0), QgsStyleModel.TypeRole), QgsStyle.ColorrampEntity) self.assertEqual(model.data(model.index(1, 0), QgsStyleModel.TypeRole), QgsStyle.ColorrampEntity) self.assertEqual(model.data(model.index(4, 0), QgsStyleModel.TypeRole), QgsStyle.ColorrampEntity)
def testSetData(self): """ Test model set data """ style = QgsStyle() style.createMemoryDatabase() symbol_a = createMarkerSymbol() symbol_a.setColor(QColor(255, 10, 10)) self.assertTrue(style.addSymbol('a', symbol_a, True)) ramp_a = QgsLimitedRandomColorRamp(5) self.assertTrue(style.addColorRamp('ramp a', ramp_a, True)) model = QgsStyleModel(style) self.assertEqual(model.rowCount(), 2) self.assertEqual(style.symbolNames(), ['a']) self.assertFalse(model.setData(QModelIndex(), 'b', Qt.EditRole)) self.assertFalse(model.setData(model.index(0, 1), 'b', Qt.EditRole)) self.assertTrue(model.setData(model.index(0, 0), 'new symbol name', Qt.EditRole)) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'new symbol name') self.assertEqual(style.symbolNames(), ['new symbol name']) self.assertTrue(model.setData(model.index(1, 0), 'ramp new name', Qt.EditRole)) self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'ramp new name') self.assertEqual(style.colorRampNames(), ['ramp new name'])
def test_add_remove_ramps(self): style = QgsStyle() style.createMemoryDatabase() model = QgsStyleModel(style) symbol = createMarkerSymbol() self.assertTrue(style.addSymbol('a', symbol, True)) symbol = createMarkerSymbol() self.assertTrue(style.addSymbol('c', symbol, True)) self.assertEqual(model.rowCount(), 2) ramp_a = QgsLimitedRandomColorRamp(5) self.assertTrue(style.addColorRamp('ramp a', ramp_a, True)) self.assertEqual(model.rowCount(), 3) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'a') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'c') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'ramp a') symbol_B = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('ramp c', symbol_B, True)) self.assertEqual(model.rowCount(), 4) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'a') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'c') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'ramp a') self.assertEqual(model.data(model.index(3, 0), Qt.DisplayRole), 'ramp c') symbol_b = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('ramp b', symbol_b, True)) self.assertEqual(model.rowCount(), 5) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'a') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'c') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'ramp a') self.assertEqual(model.data(model.index(3, 0), Qt.DisplayRole), 'ramp b') self.assertEqual(model.data(model.index(4, 0), Qt.DisplayRole), 'ramp c') self.assertTrue(style.removeColorRamp('ramp a')) self.assertEqual(model.rowCount(), 4) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'a') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'c') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'ramp b') self.assertEqual(model.data(model.index(3, 0), Qt.DisplayRole), 'ramp c')
def testIconSize(self): """ Test that model has responsive icon sizes for decorations """ style = QgsStyle() style.createMemoryDatabase() symbol_a = createMarkerSymbol() symbol_a.setColor(QColor(255, 10, 10)) self.assertTrue(style.addSymbol('a', symbol_a, True)) ramp_a = QgsLimitedRandomColorRamp(5) self.assertTrue(style.addColorRamp('ramp a', ramp_a, True)) for i in range(2): model = QgsStyleModel(style) self.assertEqual(model.rowCount(), 2) icon = model.data(model.index(i, 0), Qt.DecorationRole) # by default, only 24x24 icon self.assertEqual(icon.availableSizes(), [QSize(24, 24)]) self.assertEqual(icon.actualSize(QSize(10, 10)), QSize(10, 10)) self.assertEqual(icon.actualSize(QSize(24, 24)), QSize(24, 24)) self.assertEqual(icon.actualSize(QSize(90, 90)), QSize(24, 24)) model.addDesiredIconSize(QSize(24, 24)) model.addDesiredIconSize(QSize(100, 90)) icon = model.data(model.index(i, 0), Qt.DecorationRole) self.assertEqual(icon.availableSizes(), [QSize(24, 24), QSize(100, 90)]) self.assertEqual(icon.actualSize(QSize(10, 10)), QSize(10, 10)) self.assertEqual(icon.actualSize(QSize(24, 24)), QSize(24, 24)) self.assertEqual(icon.actualSize(QSize(25, 25)), QSize(25, 22)) self.assertEqual(icon.actualSize(QSize(90, 90)), QSize(90, 81)) self.assertEqual(icon.actualSize(QSize(125, 125)), QSize(100, 90)) model = QgsStyleModel(style) model.addDesiredIconSize(QSize(100, 90)) model.addDesiredIconSize(QSize(200, 180)) icon = model.data(model.index(i, 0), Qt.DecorationRole) self.assertEqual(icon.availableSizes(), [QSize(100, 90), QSize(200, 180)]) self.assertEqual(icon.actualSize(QSize(24, 24)), QSize(24, 21)) self.assertEqual(icon.actualSize(QSize(25, 25)), QSize(25, 22)) self.assertEqual(icon.actualSize(QSize(90, 90)), QSize(90, 81)) self.assertEqual(icon.actualSize(QSize(125, 125)), QSize(125, 112)) self.assertEqual(icon.actualSize(QSize(225, 225)), QSize(200, 180))
def test_filter_proxy(self): style = QgsStyle() style.createMemoryDatabase() symbol_a = createMarkerSymbol() symbol_a.setColor(QColor(255, 10, 10)) self.assertTrue(style.addSymbol('a', symbol_a, True)) style.tagSymbol(QgsStyle.SymbolEntity, 'a', ['tag 1', 'tag 2']) symbol_B = createMarkerSymbol() symbol_B.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('BB', symbol_B, True)) symbol_b = createFillSymbol() symbol_b.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('b', symbol_b, True)) symbol_C = createLineSymbol() symbol_C.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('C', symbol_C, True)) style.tagSymbol(QgsStyle.SymbolEntity, 'C', ['tag 3']) symbol_C = createMarkerSymbol() symbol_C.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('another', symbol_C, True)) ramp_a = QgsLimitedRandomColorRamp(5) self.assertTrue(style.addColorRamp('ramp a', ramp_a, True)) style.tagSymbol(QgsStyle.ColorrampEntity, 'ramp a', ['tag 1', 'tag 2']) symbol_B = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('ramp BB', symbol_B, True)) symbol_b = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('ramp c', symbol_b, True)) model = QgsStyleProxyModel(style) self.assertEqual(model.rowCount(), 8) # filter string model.setFilterString('xx') self.assertEqual(model.filterString(), 'xx') self.assertEqual(model.rowCount(), 0) model.setFilterString('b') self.assertEqual(model.rowCount(), 3) self.assertEqual(model.data(model.index(0, 0)), 'b') self.assertEqual(model.data(model.index(1, 0)), 'BB') self.assertEqual(model.data(model.index(2, 0)), 'ramp BB') model.setFilterString('bb') self.assertEqual(model.rowCount(), 2) self.assertEqual(model.data(model.index(0, 0)), 'BB') self.assertEqual(model.data(model.index(1, 0)), 'ramp BB') model.setFilterString('tag 1') self.assertEqual(model.rowCount(), 2) self.assertEqual(model.data(model.index(0, 0)), 'a') self.assertEqual(model.data(model.index(1, 0)), 'ramp a') model.setFilterString('TAG 1') self.assertEqual(model.rowCount(), 2) self.assertEqual(model.data(model.index(0, 0)), 'a') self.assertEqual(model.data(model.index(1, 0)), 'ramp a') model.setFilterString('ram b') self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0)), 'ramp BB') model.setFilterString('ta ram') # match ta -> "tag 1", ram -> "ramp a" self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0)), 'ramp a') model.setFilterString('') self.assertEqual(model.rowCount(), 8) # entity type model.setEntityFilter(QgsStyle.SymbolEntity) self.assertEqual(model.rowCount(), 8) model.setEntityFilter(QgsStyle.ColorrampEntity) self.assertEqual(model.rowCount(), 8) model.setEntityFilterEnabled(True) self.assertEqual(model.rowCount(), 3) self.assertEqual(model.data(model.index(0, 0)), 'ramp a') self.assertEqual(model.data(model.index(1, 0)), 'ramp BB') self.assertEqual(model.data(model.index(2, 0)), 'ramp c') model.setFilterString('BB') self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0)), 'ramp BB') model.setFilterString('') model.setEntityFilter(QgsStyle.SymbolEntity) self.assertEqual(model.rowCount(), 5) self.assertEqual(model.data(model.index(0, 0)), 'a') self.assertEqual(model.data(model.index(1, 0)), 'another') self.assertEqual(model.data(model.index(2, 0)), 'b') self.assertEqual(model.data(model.index(3, 0)), 'BB') self.assertEqual(model.data(model.index(4, 0)), 'C') model.setFilterString('ot') self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0)), 'another') model.setFilterString('') model.setEntityFilterEnabled(False) self.assertEqual(model.rowCount(), 8) # symbol type filter model.setSymbolType(QgsSymbol.Line) self.assertEqual(model.rowCount(), 8) model.setSymbolType(QgsSymbol.Marker) self.assertEqual(model.rowCount(), 8) model.setSymbolTypeFilterEnabled(True) self.assertEqual(model.rowCount(), 6) self.assertEqual(model.data(model.index(0, 0)), 'a') self.assertEqual(model.data(model.index(1, 0)), 'another') self.assertEqual(model.data(model.index(2, 0)), 'BB') self.assertEqual(model.data(model.index(3, 0)), 'ramp a') self.assertEqual(model.data(model.index(4, 0)), 'ramp BB') model.setEntityFilterEnabled(True) self.assertEqual(model.rowCount(), 3) self.assertEqual(model.data(model.index(0, 0)), 'a') self.assertEqual(model.data(model.index(1, 0)), 'another') self.assertEqual(model.data(model.index(2, 0)), 'BB') model.setFilterString('oth') self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0)), 'another') model.setEntityFilterEnabled(False) self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0)), 'another') model.setEntityFilterEnabled(True) model.setFilterString('') model.setSymbolType(QgsSymbol.Line) self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0)), 'C') model.setSymbolType(QgsSymbol.Fill) self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0)), 'b') model.setSymbolTypeFilterEnabled(False) model.setEntityFilterEnabled(False) self.assertEqual(model.rowCount(), 8) # tag filter self.assertEqual(model.tagId(), -1) tag_1_id = style.tagId('tag 1') tag_3_id = style.tagId('tag 3') model.setTagId(tag_1_id) self.assertEqual(model.tagId(), tag_1_id) self.assertEqual(model.rowCount(), 2) self.assertEqual(model.data(model.index(0, 0)), 'a') self.assertEqual(model.data(model.index(1, 0)), 'ramp a') model.setEntityFilterEnabled(True) model.setEntityFilter(QgsStyle.ColorrampEntity) self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0)), 'ramp a') model.setEntityFilterEnabled(False) model.setFilterString('ra') self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0)), 'ramp a') model.setEntityFilterEnabled(False) model.setFilterString('') model.setTagId(-1) self.assertEqual(model.rowCount(), 8) model.setTagId(tag_3_id) self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0)), 'C') style.tagSymbol(QgsStyle.ColorrampEntity, 'ramp c', ['tag 3']) self.assertEqual(model.rowCount(), 2) self.assertEqual(model.data(model.index(0, 0)), 'C') self.assertEqual(model.data(model.index(1, 0)), 'ramp c') style.detagSymbol(QgsStyle.ColorrampEntity, 'ramp c') self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0)), 'C') model.setTagId(-1) self.assertEqual(model.rowCount(), 8) # favorite filter style.addFavorite(QgsStyle.ColorrampEntity, 'ramp c') style.addFavorite(QgsStyle.SymbolEntity, 'another') self.assertEqual(model.favoritesOnly(), False) model.setFavoritesOnly(True) self.assertEqual(model.favoritesOnly(), True) self.assertEqual(model.rowCount(), 2) self.assertEqual(model.data(model.index(0, 0)), 'another') self.assertEqual(model.data(model.index(1, 0)), 'ramp c') model.setEntityFilterEnabled(True) model.setEntityFilter(QgsStyle.ColorrampEntity) self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0)), 'ramp c') model.setEntityFilterEnabled(False) model.setFilterString('er') self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0)), 'another') model.setEntityFilterEnabled(False) model.setFilterString('') self.assertEqual(model.rowCount(), 2) style.addFavorite(QgsStyle.ColorrampEntity, 'ramp a') self.assertEqual(model.rowCount(), 3) self.assertEqual(model.data(model.index(0, 0)), 'another') self.assertEqual(model.data(model.index(1, 0)), 'ramp a') self.assertEqual(model.data(model.index(2, 0)), 'ramp c') style.removeFavorite(QgsStyle.ColorrampEntity, 'ramp a') self.assertEqual(model.rowCount(), 2) self.assertEqual(model.data(model.index(0, 0)), 'another') self.assertEqual(model.data(model.index(1, 0)), 'ramp c') style.addFavorite(QgsStyle.SymbolEntity, 'BB') self.assertEqual(model.rowCount(), 3) self.assertEqual(model.data(model.index(0, 0)), 'another') self.assertEqual(model.data(model.index(1, 0)), 'BB') self.assertEqual(model.data(model.index(2, 0)), 'ramp c') style.removeFavorite(QgsStyle.SymbolEntity, 'another') self.assertEqual(model.rowCount(), 2) self.assertEqual(model.data(model.index(0, 0)), 'BB') self.assertEqual(model.data(model.index(1, 0)), 'ramp c') model.setFavoritesOnly(False) self.assertEqual(model.rowCount(), 8) # smart group filter style.addSmartgroup('smart', 'AND', ['tag 3'], [], ['c'], []) self.assertEqual(model.smartGroupId(), -1) model.setSmartGroupId(1) self.assertEqual(model.smartGroupId(), 1) self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0)), 'C') style.addSmartgroup('smart', 'OR', ['tag 3'], [], ['c'], []) model.setSmartGroupId(2) self.assertEqual(model.rowCount(), 2) self.assertEqual(model.data(model.index(0, 0)), 'C') self.assertEqual(model.data(model.index(1, 0)), 'ramp c') style.tagSymbol(QgsStyle.SymbolEntity, 'a', ['tag 3']) self.assertEqual(model.rowCount(), 3) self.assertEqual(model.data(model.index(0, 0)), 'a') self.assertEqual(model.data(model.index(1, 0)), 'C') self.assertEqual(model.data(model.index(2, 0)), 'ramp c') style.renameColorRamp('ramp c', 'x') self.assertEqual(model.rowCount(), 2) self.assertEqual(model.data(model.index(0, 0)), 'a') self.assertEqual(model.data(model.index(1, 0)), 'C') model.setSmartGroupId(-1) self.assertEqual(model.rowCount(), 8)
def test_renamed(self): style = QgsStyle() style.createMemoryDatabase() model = QgsStyleModel(style) symbol = createMarkerSymbol() self.assertTrue(style.addSymbol('a', symbol, True)) symbol = createMarkerSymbol() self.assertTrue(style.addSymbol('c', symbol, True)) ramp_a = QgsLimitedRandomColorRamp(5) self.assertTrue(style.addColorRamp('ramp a', ramp_a, True)) symbol_B = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('ramp c', symbol_B, True)) self.assertEqual(model.rowCount(), 4) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'a') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'c') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'ramp a') self.assertEqual(model.data(model.index(3, 0), Qt.DisplayRole), 'ramp c') self.assertTrue(style.renameSymbol('a', 'b')) self.assertEqual(model.rowCount(), 4) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'b') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'c') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'ramp a') self.assertEqual(model.data(model.index(3, 0), Qt.DisplayRole), 'ramp c') self.assertTrue(style.renameSymbol('b', 'd')) self.assertEqual(model.rowCount(), 4) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'c') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'd') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'ramp a') self.assertEqual(model.data(model.index(3, 0), Qt.DisplayRole), 'ramp c') self.assertTrue(style.renameSymbol('d', 'e')) self.assertEqual(model.rowCount(), 4) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'c') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'e') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'ramp a') self.assertEqual(model.data(model.index(3, 0), Qt.DisplayRole), 'ramp c') self.assertTrue(style.renameSymbol('c', 'f')) self.assertEqual(model.rowCount(), 4) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'e') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'f') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'ramp a') self.assertEqual(model.data(model.index(3, 0), Qt.DisplayRole), 'ramp c') self.assertTrue(style.renameColorRamp('ramp a', 'ramp b')) self.assertEqual(model.rowCount(), 4) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'e') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'f') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'ramp b') self.assertEqual(model.data(model.index(3, 0), Qt.DisplayRole), 'ramp c') self.assertTrue(style.renameColorRamp('ramp b', 'ramp d')) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'e') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'f') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'ramp c') self.assertEqual(model.data(model.index(3, 0), Qt.DisplayRole), 'ramp d') self.assertTrue(style.renameColorRamp('ramp d', 'ramp e')) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'e') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'f') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'ramp c') self.assertEqual(model.data(model.index(3, 0), Qt.DisplayRole), 'ramp e') self.assertTrue(style.renameColorRamp('ramp c', 'ramp f')) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'e') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'f') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'ramp e') self.assertEqual(model.data(model.index(3, 0), Qt.DisplayRole), 'ramp f')
def test_mixed_style(self): """ Test style with both symbols and ramps """ style = QgsStyle() style.createMemoryDatabase() # style with only symbols symbol_a = createMarkerSymbol() symbol_a.setColor(QColor(255, 10, 10)) self.assertTrue(style.addSymbol('a', symbol_a, True)) style.tagSymbol(QgsStyle.SymbolEntity, 'a', ['tag 1', 'tag 2']) symbol_B = createMarkerSymbol() symbol_B.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('B ', symbol_B, True)) symbol_b = createFillSymbol() symbol_b.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('b', symbol_b, True)) symbol_C = createLineSymbol() symbol_C.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('C', symbol_C, True)) style.tagSymbol(QgsStyle.SymbolEntity, 'C', ['tag 3']) symbol_C = createMarkerSymbol() symbol_C.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol(' ----c/- ', symbol_C, True)) ramp_a = QgsLimitedRandomColorRamp(5) self.assertTrue(style.addColorRamp('ramp a', ramp_a, True)) style.tagSymbol(QgsStyle.ColorrampEntity, 'ramp a', ['tag 1', 'tag 2']) symbol_B = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('ramp B ', symbol_B, True)) symbol_b = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('ramp c', symbol_b, True)) model = QgsStyleModel(style) self.assertEqual(model.rowCount(), 8) self.assertEqual(model.columnCount(), 2) self.assertTrue(model.index(0, 0).isValid()) self.assertFalse(model.index(10, 0).isValid()) self.assertFalse(model.index(0, 10).isValid()) self.assertFalse(model.parent(model.index(0, 0)).isValid()) for role in (Qt.DisplayRole, Qt.EditRole): self.assertIsNone(model.data(model.index(-1, 0), role)) self.assertIsNone(model.data(model.index(-1, 1), role)) self.assertEqual(model.data(model.index(0, 0), role), ' ----c/- ') self.assertFalse(model.data(model.index(0, 1), role)) self.assertIsNone(model.data(model.index(0, 2), role)) self.assertIsNone(model.data(model.index(0, -1), role)) self.assertEqual(model.data(model.index(1, 0), role), 'B ') self.assertFalse(model.data(model.index(1, 1), role)) self.assertEqual(model.data(model.index(2, 0), role), 'C') self.assertEqual(model.data(model.index(2, 1), role), 'tag 3') self.assertEqual(model.data(model.index(3, 0), role), 'a') self.assertEqual(model.data(model.index(3, 1), role), 'tag 1, tag 2') self.assertEqual(model.data(model.index(4, 0), role), 'b') self.assertFalse(model.data(model.index(4, 1), role)) self.assertEqual(model.data(model.index(5, 0), role), 'ramp B ') self.assertFalse(model.data(model.index(5, 1), role)) self.assertEqual(model.data(model.index(6, 0), role), 'ramp a') self.assertEqual(model.data(model.index(6, 1), role), 'tag 1, tag 2') self.assertEqual(model.data(model.index(7, 0), role), 'ramp c') self.assertFalse(model.data(model.index(7, 1), role)) self.assertIsNone(model.data(model.index(8, 0), role)) self.assertIsNone(model.data(model.index(8, 1), role)) # decorations self.assertIsNone(model.data(model.index(-1, 0), Qt.DecorationRole)) self.assertIsNone(model.data(model.index(0, 1), Qt.DecorationRole)) self.assertIsNone(model.data(model.index(8, 0), Qt.DecorationRole)) self.assertFalse(model.data(model.index(0, 0), Qt.DecorationRole).isNull()) self.assertFalse(model.data(model.index(5, 0), Qt.DecorationRole).isNull()) self.assertEqual(model.data(model.index(0, 0), QgsStyleModel.TypeRole), QgsStyle.SymbolEntity) self.assertEqual(model.data(model.index(1, 0), QgsStyleModel.TypeRole), QgsStyle.SymbolEntity) self.assertEqual(model.data(model.index(4, 0), QgsStyleModel.TypeRole), QgsStyle.SymbolEntity) self.assertEqual(model.data(model.index(5, 0), QgsStyleModel.TypeRole), QgsStyle.ColorrampEntity) self.assertEqual(model.data(model.index(6, 0), QgsStyleModel.TypeRole), QgsStyle.ColorrampEntity) self.assertEqual(model.data(model.index(7, 0), QgsStyleModel.TypeRole), QgsStyle.ColorrampEntity)
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
def test_mixed_style(self): """ Test style with both symbols and ramps """ style = QgsStyle() style.createMemoryDatabase() # style with only symbols symbol_a = createMarkerSymbol() symbol_a.setColor(QColor(255, 10, 10)) self.assertTrue(style.addSymbol('a', symbol_a, True)) style.tagSymbol(QgsStyle.SymbolEntity, 'a', ['tag 1', 'tag 2']) symbol_B = createMarkerSymbol() symbol_B.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('B ', symbol_B, True)) symbol_b = createFillSymbol() symbol_b.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('b', symbol_b, True)) symbol_C = createLineSymbol() symbol_C.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('C', symbol_C, True)) style.tagSymbol(QgsStyle.SymbolEntity, 'C', ['tag 3']) symbol_C = createMarkerSymbol() symbol_C.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol(' ----c/- ', symbol_C, True)) ramp_a = QgsLimitedRandomColorRamp(5) self.assertTrue(style.addColorRamp('ramp a', ramp_a, True)) style.tagSymbol(QgsStyle.ColorrampEntity, 'ramp a', ['tag 1', 'tag 2']) symbol_B = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('ramp B ', symbol_B, True)) symbol_b = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('ramp c', symbol_b, True)) model = QgsStyleModel(style) self.assertEqual(model.rowCount(), 8) self.assertEqual(model.columnCount(), 2) self.assertTrue(model.index(0, 0).isValid()) self.assertFalse(model.index(10, 0).isValid()) self.assertFalse(model.index(0, 10).isValid()) self.assertFalse(model.parent(model.index(0, 0)).isValid()) for role in (Qt.DisplayRole, Qt.EditRole): self.assertIsNone(model.data(model.index(-1, 0), role)) self.assertIsNone(model.data(model.index(-1, 1), role)) self.assertEqual(model.data(model.index(0, 0), role), ' ----c/- ') self.assertFalse(model.data(model.index(0, 1), role)) self.assertIsNone(model.data(model.index(0, 2), role)) self.assertIsNone(model.data(model.index(0, -1), role)) self.assertEqual(model.data(model.index(1, 0), role), 'B ') self.assertFalse(model.data(model.index(1, 1), role)) self.assertEqual(model.data(model.index(2, 0), role), 'C') self.assertEqual(model.data(model.index(2, 1), role), 'tag 3') self.assertEqual(model.data(model.index(3, 0), role), 'a') self.assertEqual(model.data(model.index(3, 1), role), 'tag 1, tag 2') self.assertEqual(model.data(model.index(4, 0), role), 'b') self.assertFalse(model.data(model.index(4, 1), role)) self.assertEqual(model.data(model.index(5, 0), role), 'ramp B ') self.assertFalse(model.data(model.index(5, 1), role)) self.assertEqual(model.data(model.index(6, 0), role), 'ramp a') self.assertEqual(model.data(model.index(6, 1), role), 'tag 1, tag 2') self.assertEqual(model.data(model.index(7, 0), role), 'ramp c') self.assertFalse(model.data(model.index(7, 1), role)) self.assertIsNone(model.data(model.index(8, 0), role)) self.assertIsNone(model.data(model.index(8, 1), role)) # decorations self.assertIsNone(model.data(model.index(-1, 0), Qt.DecorationRole)) self.assertIsNone(model.data(model.index(0, 1), Qt.DecorationRole)) self.assertIsNone(model.data(model.index(8, 0), Qt.DecorationRole)) self.assertFalse( model.data(model.index(0, 0), Qt.DecorationRole).isNull()) self.assertFalse( model.data(model.index(5, 0), Qt.DecorationRole).isNull()) self.assertEqual(model.data(model.index(0, 0), QgsStyleModel.TypeRole), QgsStyle.SymbolEntity) self.assertEqual(model.data(model.index(1, 0), QgsStyleModel.TypeRole), QgsStyle.SymbolEntity) self.assertEqual(model.data(model.index(4, 0), QgsStyleModel.TypeRole), QgsStyle.SymbolEntity) self.assertEqual(model.data(model.index(5, 0), QgsStyleModel.TypeRole), QgsStyle.ColorrampEntity) self.assertEqual(model.data(model.index(6, 0), QgsStyleModel.TypeRole), QgsStyle.ColorrampEntity) self.assertEqual(model.data(model.index(7, 0), QgsStyleModel.TypeRole), QgsStyle.ColorrampEntity)
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) embed_pictures = self.parameterAsBool(parameters, self.EMBED_PICTURES, context) convert_fonts = self.parameterAsBool(parameters, self.CONVERT_FONTS, context) parameterize = self.parameterAsBool(parameters, self.PARAMETERIZE, context) units = self.parameterAsEnum(parameters, self.UNITS, context) force_svg = self.parameterAsBool(parameters, self.FORCE_SVG, context) relative_paths = self.parameterAsBool(parameters, self.RELATIVE_PATHS, context) picture_folder = self.parameterAsString(parameters, self.PICTURE_FOLDER, context) if not picture_folder: picture_folder, _ = os.path.split(output_file) mdbtools_folder = ProcessingConfig.getSetting('MDB_PATH') 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 for type_index, symbol_type in enumerate( (Extractor.FILL_SYMBOLS, Extractor.LINE_SYMBOLS, Extractor.MARKER_SYMBOLS, Extractor.COLOR_RAMPS)): feedback.pushInfo('Importing {} from {}'.format(symbol_type, input_file)) raw_symbols = Extractor.extract_styles(input_file, symbol_type, mdbtools_path=mdbtools_folder) 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) * 33.3 + 33.3 * 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)) 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)) 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)) 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)) unreadable += 1 if sink: f.setAttributes([name, 'Version not supported: {}'.format(e)]) sink.addFeature(f) continue except UnknownGuidException as e: feedback.reportError(str(e)) unreadable += 1 if sink: f.setAttributes([name, 'Unknown object: {}'.format(e)]) sink.addFeature(f) continue except UnreadablePictureException as e: feedback.reportError(str(e)) unreadable += 1 if sink: f.setAttributes([name, 'Unreadable picture: {}'.format(e)]) sink.addFeature(f) continue self.check_for_unsupported_property(name, symbol, feedback, sink) context = Context() context.symbol_name = unique_name context.picture_folder = picture_folder context.embed_pictures = embed_pictures context.convert_fonts = convert_fonts context.parameterise_svg = parameterize context.force_svg_instead_of_raster = force_svg context.relative_paths = relative_paths context.style_folder, _ = os.path.split(output_file) context.units = QgsUnitTypes.RenderPoints if units == 0 else QgsUnitTypes.RenderMillimeters try: qgis_symbol = Symbol_to_QgsSymbol(symbol, context) except NotImplementedException as e: feedback.reportError(str(e)) unreadable += 1 if sink: f.setAttributes([name, str(e)]) sink.addFeature(f) 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) 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 style.exportXml(output_file) results[self.OUTPUT] = output_file results[self.REPORT] = dest return results
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(): message_bar = iface.messageBar() widget = message_bar.createMessage('SLYR', "MDB Tools utility not found") settings_button = QPushButton("Configure…", pressed=partial( open_settings, widget)) widget.layout().addWidget(settings_button) message_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), # pylint: disable=cell-var-from-loop html.escape(msg))) elif level == Context.CRITICAL: errors.add('<b>{}</b>: {}'.format( html.escape(unique_name), # pylint: disable=cell-var-from-loop 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
def test_style_with_ramps(self): style = QgsStyle() style.createMemoryDatabase() # style with only ramps ramp_a = QgsLimitedRandomColorRamp(5) self.assertTrue(style.addColorRamp('a', ramp_a, True)) style.tagSymbol(QgsStyle.ColorrampEntity, 'a', ['tag 1', 'tag 2']) symbol_B = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('B ', symbol_B, True)) symbol_b = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('b', symbol_b, True)) symbol_C = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp('C', symbol_C, True)) style.tagSymbol(QgsStyle.ColorrampEntity, 'C', ['tag 3']) symbol_C = QgsLimitedRandomColorRamp() self.assertTrue(style.addColorRamp(' ----c/- ', symbol_C, True)) model = QgsStyleModel(style) self.assertEqual(model.rowCount(), 5) self.assertEqual(model.columnCount(), 2) self.assertTrue(model.index(0, 0).isValid()) self.assertFalse(model.index(10, 0).isValid()) self.assertFalse(model.index(0, 10).isValid()) self.assertFalse(model.parent(model.index(0, 0)).isValid()) for role in (Qt.DisplayRole, Qt.EditRole): self.assertIsNone(model.data(model.index(-1, 0), role)) self.assertIsNone(model.data(model.index(-1, 1), role)) self.assertEqual(model.data(model.index(0, 0), role), ' ----c/- ') self.assertFalse(model.data(model.index(0, 1), role)) self.assertIsNone(model.data(model.index(0, 2), role)) self.assertIsNone(model.data(model.index(0, -1), role)) self.assertEqual(model.data(model.index(1, 0), role), 'B ') self.assertFalse(model.data(model.index(1, 1), role)) self.assertEqual(model.data(model.index(2, 0), role), 'C') self.assertEqual(model.data(model.index(2, 1), role), 'tag 3') self.assertEqual(model.data(model.index(3, 0), role), 'a') self.assertEqual(model.data(model.index(3, 1), role), 'tag 1, tag 2') self.assertEqual(model.data(model.index(4, 0), role), 'b') self.assertFalse(model.data(model.index(4, 1), role)) self.assertIsNone(model.data(model.index(5, 0), role)) self.assertIsNone(model.data(model.index(5, 1), role)) # decorations self.assertIsNone(model.data(model.index(-1, 0), Qt.DecorationRole)) self.assertIsNone(model.data(model.index(0, 1), Qt.DecorationRole)) self.assertIsNone(model.data(model.index(5, 0), Qt.DecorationRole)) self.assertFalse( model.data(model.index(0, 0), Qt.DecorationRole).isNull()) self.assertEqual(model.data(model.index(0, 0), QgsStyleModel.TypeRole), QgsStyle.ColorrampEntity) self.assertEqual(model.data(model.index(1, 0), QgsStyleModel.TypeRole), QgsStyle.ColorrampEntity) self.assertEqual(model.data(model.index(4, 0), QgsStyleModel.TypeRole), QgsStyle.ColorrampEntity)
def processAlgorithm(self, parameters, context, feedback): # pylint: disable=missing-docstring,too-many-locals,too-many-statements,too-many-branches input_file = self.parameterAsString(parameters, self.INPUT, context) output_file = self.parameterAsFileOutput(parameters, self.OUTPUT, context) mdbtools_folder = ProcessingConfig.getSetting('MDB_PATH') 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 for type_index, symbol_type in enumerate( (Extractor.FILL_SYMBOLS, Extractor.LINE_SYMBOLS, Extractor.MARKER_SYMBOLS, Extractor.COLOR_RAMPS)): feedback.pushInfo('Importing {} from {}'.format( symbol_type, input_file)) raw_symbols = Extractor.extract_styles( input_file, symbol_type, mdbtools_path=mdbtools_folder) 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) * 33.3 + 33.3 * 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)) 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) try: symbol = stream.read_object() except UnreadableSymbolException as e: feedback.reportError('Error reading symbol {}: {}'.format( name, e)) unreadable += 1 continue except NotImplementedException as e: feedback.reportError( 'Parsing {} is not supported: {}'.format(name, e)) unreadable += 1 continue except UnsupportedVersionException as e: feedback.reportError('Cannot read {} version: {}'.format( name, e)) unreadable += 1 continue except UnknownGuidException as e: feedback.reportError(str(e)) unreadable += 1 continue self.check_for_unsupported_property(symbol, feedback) try: qgis_symbol = Symbol_to_QgsSymbol(symbol) except NotImplementedException as e: feedback.reportError(str(e)) unreadable += 1 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) 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 style.exportXml(output_file) results[self.OUTPUT] = output_file return results