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_add_delete_symbols(self): style = QgsStyle() style.createMemoryDatabase() model = QgsStyleModel(style) self.assertEqual(model.rowCount(), 0) symbol = createMarkerSymbol() self.assertTrue(style.addSymbol('a', symbol, True)) self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'a') symbol = createMarkerSymbol() self.assertTrue(style.addSymbol('c', symbol, True)) self.assertEqual(model.rowCount(), 2) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'a') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'c') symbol = createMarkerSymbol() self.assertTrue(style.addSymbol('b', symbol, 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), 'b') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'c') symbol = createMarkerSymbol() self.assertTrue(style.addSymbol('1', symbol, True)) self.assertEqual(model.rowCount(), 4) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), '1') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'a') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'b') self.assertEqual(model.data(model.index(3, 0), Qt.DisplayRole), 'c') self.assertFalse(style.removeSymbol('xxxx')) self.assertEqual(model.rowCount(), 4) self.assertTrue(style.removeSymbol('b')) self.assertEqual(model.rowCount(), 3) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), '1') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'a') self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole), 'c') self.assertTrue(style.removeSymbol('1')) self.assertEqual(model.rowCount(), 2) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'a') self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole), 'c') self.assertTrue(style.removeSymbol('c')) self.assertEqual(model.rowCount(), 1) self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 'a') self.assertTrue(style.removeSymbol('a')) self.assertEqual(model.rowCount(), 0)
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 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 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 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)) model = QgsStyleModel(style) self.assertEqual(model.rowCount(), 2) for i in range(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.setProperty('icon_sizes', [QSize(24, 24), 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.setProperty('icon_sizes', [QSize(100, 90), QSize(200, 180)]) icon = model.data(model.index(i, 0), Qt.DecorationRole) self.assertEqual( icon.availableSizes(), [QSize(24, 24), QSize(100, 90), QSize(200, 180)]) 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(125, 112)) self.assertEqual(icon.actualSize(QSize(225, 225)), QSize(200, 180)) model.setProperty('icon_sizes', None)
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_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 testMatchToSymbols(self): """ Test QgsCategorizedSymbolRender.matchToSymbols """ renderer = QgsCategorizedSymbolRenderer() renderer.setClassAttribute('x') symbol_a = createMarkerSymbol() symbol_a.setColor(QColor(255, 0, 0)) renderer.addCategory(QgsRendererCategory('a', symbol_a, 'a')) symbol_b = createMarkerSymbol() symbol_b.setColor(QColor(0, 255, 0)) renderer.addCategory(QgsRendererCategory('b', symbol_b, 'b')) symbol_c = createMarkerSymbol() symbol_c.setColor(QColor(0, 0, 255)) renderer.addCategory(QgsRendererCategory('c ', symbol_c, 'c')) matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols( None, QgsSymbol.Marker) self.assertEqual(matched, 0) style = QgsStyle() symbol_a = createMarkerSymbol() symbol_a.setColor(QColor(255, 10, 10)) self.assertTrue(style.addSymbol('a', symbol_a)) symbol_B = createMarkerSymbol() symbol_B.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('B ', symbol_B)) symbol_b = createFillSymbol() symbol_b.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('b', symbol_b)) symbol_C = createLineSymbol() symbol_C.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('C', symbol_C)) symbol_C = createMarkerSymbol() symbol_C.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol(' ----c/- ', symbol_C)) # non-matching symbol type matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols( style, QgsSymbol.Line) self.assertEqual(matched, 0) self.assertEqual(unmatched_cats, ['a', 'b', 'c ']) self.assertEqual(unmatched_symbols, [' ----c/- ', 'B ', 'C', 'a', 'b']) # exact match matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols( style, QgsSymbol.Marker) self.assertEqual(matched, 1) self.assertEqual(unmatched_cats, ['b', 'c ']) self.assertEqual(unmatched_symbols, [' ----c/- ', 'B ', 'C', 'b']) # make sure symbol was applied context = QgsRenderContext() renderer.startRender(context, QgsFields()) symbol, ok = renderer.symbolForValue2('a') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#ff0a0a') renderer.stopRender(context) # case insensitive match matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols( style, QgsSymbol.Marker, False) self.assertEqual(matched, 2) self.assertEqual(unmatched_cats, ['c ']) self.assertEqual(unmatched_symbols, [' ----c/- ', 'C', 'b']) # make sure symbols were applied context = QgsRenderContext() renderer.startRender(context, QgsFields()) symbol, ok = renderer.symbolForValue2('a') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#ff0a0a') symbol, ok = renderer.symbolForValue2('b') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#0aff0a') renderer.stopRender(context) # case insensitive match matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols( style, QgsSymbol.Marker, False) self.assertEqual(matched, 2) self.assertEqual(unmatched_cats, ['c ']) self.assertEqual(unmatched_symbols, [' ----c/- ', 'C', 'b']) # make sure symbols were applied context = QgsRenderContext() renderer.startRender(context, QgsFields()) symbol, ok = renderer.symbolForValue2('a') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#ff0a0a') symbol, ok = renderer.symbolForValue2('b') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#0aff0a') renderer.stopRender(context) # tolerant match matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols( style, QgsSymbol.Marker, True, True) self.assertEqual(matched, 2) self.assertEqual(unmatched_cats, ['b']) self.assertEqual(unmatched_symbols, ['B ', 'C', 'b']) # make sure symbols were applied context = QgsRenderContext() renderer.startRender(context, QgsFields()) symbol, ok = renderer.symbolForValue2('a') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#ff0a0a') symbol, ok = renderer.symbolForValue2('c ') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#0aff0a') renderer.stopRender(context) # tolerant match, case insensitive matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols( style, QgsSymbol.Marker, False, True) self.assertEqual(matched, 3) self.assertFalse(unmatched_cats) self.assertEqual(unmatched_symbols, ['C', 'b']) # make sure symbols were applied context = QgsRenderContext() renderer.startRender(context, QgsFields()) symbol, ok = renderer.symbolForValue2('a') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#ff0a0a') symbol, ok = renderer.symbolForValue2('b') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#0aff0a') symbol, ok = renderer.symbolForValue2('c ') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#0aff0a') renderer.stopRender(context)
def processAlgorithm( self, # pylint:disable=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(original_name): """ Ensures that the symbol name is unique (in a case-insensitive way) """ counter = 0 candidate = original_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)) 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: feat = QgsFeature() feat.setAttributes([name, msg]) # pylint: disable=cell-var-from-loop sink.addFeature(feat) context = Context() context.symbol_name = unique_name context.style_folder, _ = os.path.split(output_file) context.unsupported_object_callback = unsupported_object_callback if symbol_type in (Extractor.AREA_PATCHES, Extractor.LINE_PATCHES): feedback.reportError( '{}: Legend patch conversion requires the licensed version of SLYR' .format(name), False) unreadable += 1 if sink: f.setAttributes( [name, 'Unreadable legend patch: {}'.format(name)]) sink.addFeature(f) continue 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) elif isinstance(qgis_symbol, QgsTextFormat): if Qgis.QGIS_VERSION_INT >= 30900: style.addTextFormat(unique_name, qgis_symbol, True) elif isinstance(qgis_symbol, QgsPalLayerSettings): if Qgis.QGIS_VERSION_INT >= 30900: style.addLabelSettings(unique_name, qgis_symbol, True) elif Qgis.QGIS_VERSION_INT >= 31300: if isinstance(qgis_symbol, QgsLegendPatchShape): style.addLegendPatchShape(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) elif isinstance(qgis_symbol, QgsTextFormat) and hasattr( QgsStyle, 'TextFormatEntity'): assert style.tagSymbol(QgsStyle.TextFormatEntity, unique_name, tags) elif isinstance(qgis_symbol, QgsPalLayerSettings) and hasattr( QgsStyle, 'LabelSettingsEntity'): assert style.tagSymbol(QgsStyle.LabelSettingsEntity, unique_name, tags) elif Qgis.QGIS_VERSION_INT >= 31300: if isinstance(qgis_symbol, QgsLegendPatchShape): assert style.tagSymbol( QgsStyle.LegendPatchShapeEntity, 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_style_with_symbols(self): 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)) model = QgsStyleModel(style) self.assertEqual(model.rowCount(), 5) self.assertEqual(model.columnCount(), 2) self.assertEqual(model.headerData(0, Qt.Horizontal), 'Name') self.assertEqual(model.headerData(1, Qt.Horizontal), 'Tags') 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()) self.assertFalse(model.flags(model.index(-1, 0)) & Qt.ItemIsEditable) self.assertFalse(model.flags(model.index(5, 0)) & Qt.ItemIsEditable) self.assertFalse(model.flags(model.index(0, 1)) & Qt.ItemIsEditable) self.assertTrue(model.flags(model.index(0, 0)) & Qt.ItemIsEditable) 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.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)
if not args.destination: args.destination = '/home/nyall/Styles/GEO_Surface___Solid_Shades.xml' styles = [(args.file, Extractor.FILL_SYMBOLS)] style = QgsStyle() for (fill_style_db, symbol_type) in styles: print('{}:{}'.format(fill_style_db, symbol_type)) raw_symbols = Extractor.extract_styles(fill_style_db, symbol_type) print('Found {} symbols of type "{}"\n\n'.format(len(raw_symbols), symbol_type)) for index, raw_symbol in enumerate(raw_symbols): name = raw_symbol[Extractor.NAME] # print('{}/{}: {}'.format(index + 1, len(raw_symbols),name)) handle = BytesIO(raw_symbol[Extractor.BLOB]) try: symbol = read_symbol(file_handle=handle) except UnreadableSymbolException: print('Error reading symbol {}'.format(name)) continue qgis_symbol = FillSymbol_to_QgsFillSymbol(symbol) style.addSymbol(name, qgis_symbol) style.exportXml(args.destination)
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
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 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 processAlgorithm(self, parameters, context, feedback): # pylint: disable=missing-docstring,too-many-locals,too-many-statements input_file = self.parameterAsString(parameters, self.INPUT, context) output_file = self.parameterAsFileOutput(parameters, self.OUTPUT, context) mdbtools_folder = ProcessingConfig.getSetting('MDB_PATH') style = QgsStyle() 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)): 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] 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 try: qgis_symbol = Symbol_to_QgsSymbol(symbol) except NotImplementedException as e: feedback.reportError(str(e)) unreadable += 1 continue style.addSymbol(unique_name, qgis_symbol) 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 style.exportXml(output_file) results[self.OUTPUT] = output_file 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=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) style = QgsStyle() style.createMemoryDatabase() warnings = set() def unsupported_object_callback(msg, level=Context.WARNING): if msg in warnings: return warnings.add(msg) if level == Context.WARNING: feedback.reportError('Warning: {}'.format(msg), False) elif level == Context.CRITICAL: feedback.reportError(msg, False) context = Context() context.unsupported_object_callback = unsupported_object_callback if Qgis.QGIS_VERSION_INT < 30600: context.invalid_layer_resolver = GuiUtils.get_valid_mime_uri # context.style_folder, _ = os.path.split(output_file) with open(input_file, 'rb') as f: stream = Stream(f, False, force_layer=True, offset=0) try: obj = stream.read_object() except RequiresLicenseException as e: raise QgsProcessingException( '{} - please see https://north-road.com/slyr/ for details'. format(e)) from e except UnknownClsidException as e: feedback.reportError(str(e), fatalError=True) return {} except UnreadableSymbolException as e: feedback.reportError('Unreadable object: {}'.format(e), fatalError=True) return {} except NotImplementedException as e: feedback.reportError(str(e), fatalError=True) return {} except UnicodeDecodeError as e: feedback.reportError('Unreadable object: {}'.format(e), fatalError=True) return {} if not LayerConverter.is_layer(obj) and not isinstance( obj, GroupLayer): feedback.reportError('Objects of type {} are not supported'.format( obj.__class__.__name__), fatalError=False) return {} symbol_names = set() def make_name_unique(original_name): """ Ensures that the symbol name is unique (in a case-insensitive way) """ counter = 0 candidate = original_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 layers = LayerConverter.unique_layer_name_map(obj) for name, layer in layers.items(): feedback.pushInfo('Extracting symbols from {}'.format(name)) symbols = VectorRendererConverter.extract_symbols_from_renderer( layer, context, default_name=name, base_name=name if len(layers) > 1 else '') for k, v in symbols.items(): unique_name = make_name_unique(k) if k != unique_name: feedback.pushInfo( 'Corrected to unique name of {}'.format(unique_name)) if isinstance(v, QgsSymbol): style.addSymbol(unique_name, v, True) elif isinstance(v, QgsColorRamp): style.addColorRamp(unique_name, v, True) elif isinstance(v, QgsTextFormat): if Qgis.QGIS_VERSION_INT >= 30900: style.addTextFormat(unique_name, v, True) style.exportXml(output_file) return {self.OUTPUT: output_file}
def test_style_with_symbols(self): 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)) model = QgsStyleModel(style) self.assertEqual(model.rowCount(), 5) self.assertEqual(model.columnCount(), 2) self.assertEqual(model.headerData(0, Qt.Horizontal), 'Name') self.assertEqual(model.headerData(1, Qt.Horizontal), 'Tags') 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()) self.assertFalse(model.flags(model.index(-1, 0)) & Qt.ItemIsEditable) self.assertFalse(model.flags(model.index(5, 0)) & Qt.ItemIsEditable) self.assertFalse(model.flags(model.index(0, 1)) & Qt.ItemIsEditable) self.assertTrue(model.flags(model.index(0, 0)) & Qt.ItemIsEditable) 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.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)
def testMatchToSymbols(self): """ Test QgsCategorizedSymbolRender.matchToSymbols """ renderer = QgsCategorizedSymbolRenderer() renderer.setClassAttribute('x') symbol_a = createMarkerSymbol() symbol_a.setColor(QColor(255, 0, 0)) renderer.addCategory(QgsRendererCategory('a', symbol_a, 'a')) symbol_b = createMarkerSymbol() symbol_b.setColor(QColor(0, 255, 0)) renderer.addCategory(QgsRendererCategory('b', symbol_b, 'b')) symbol_c = createMarkerSymbol() symbol_c.setColor(QColor(0, 0, 255)) renderer.addCategory(QgsRendererCategory('c ', symbol_c, 'c')) matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols(None, QgsSymbol.Marker) self.assertEqual(matched, 0) style = QgsStyle() symbol_a = createMarkerSymbol() symbol_a.setColor(QColor(255, 10, 10)) self.assertTrue(style.addSymbol('a', symbol_a)) symbol_B = createMarkerSymbol() symbol_B.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('B ', symbol_B)) symbol_b = createFillSymbol() symbol_b.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('b', symbol_b)) symbol_C = createLineSymbol() symbol_C.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('C', symbol_C)) symbol_C = createMarkerSymbol() symbol_C.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol(' ----c/- ', symbol_C)) # non-matching symbol type matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols(style, QgsSymbol.Line) self.assertEqual(matched, 0) self.assertEqual(unmatched_cats, ['a', 'b', 'c ']) self.assertEqual(unmatched_symbols, [' ----c/- ', 'B ', 'C', 'a', 'b']) # exact match matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols(style, QgsSymbol.Marker) self.assertEqual(matched, 1) self.assertEqual(unmatched_cats, ['b', 'c ']) self.assertEqual(unmatched_symbols, [' ----c/- ', 'B ', 'C', 'b']) # make sure symbol was applied context = QgsRenderContext() renderer.startRender(context, QgsFields()) symbol, ok = renderer.symbolForValue2('a') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#ff0a0a') renderer.stopRender(context) # case insensitive match matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols(style, QgsSymbol.Marker, False) self.assertEqual(matched, 2) self.assertEqual(unmatched_cats, ['c ']) self.assertEqual(unmatched_symbols, [' ----c/- ', 'C', 'b']) # make sure symbols were applied context = QgsRenderContext() renderer.startRender(context, QgsFields()) symbol, ok = renderer.symbolForValue2('a') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#ff0a0a') symbol, ok = renderer.symbolForValue2('b') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#0aff0a') renderer.stopRender(context) # case insensitive match matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols(style, QgsSymbol.Marker, False) self.assertEqual(matched, 2) self.assertEqual(unmatched_cats, ['c ']) self.assertEqual(unmatched_symbols, [' ----c/- ', 'C', 'b']) # make sure symbols were applied context = QgsRenderContext() renderer.startRender(context, QgsFields()) symbol, ok = renderer.symbolForValue2('a') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#ff0a0a') symbol, ok = renderer.symbolForValue2('b') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#0aff0a') renderer.stopRender(context) # tolerant match matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols(style, QgsSymbol.Marker, True, True) self.assertEqual(matched, 2) self.assertEqual(unmatched_cats, ['b']) self.assertEqual(unmatched_symbols, ['B ', 'C', 'b']) # make sure symbols were applied context = QgsRenderContext() renderer.startRender(context, QgsFields()) symbol, ok = renderer.symbolForValue2('a') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#ff0a0a') symbol, ok = renderer.symbolForValue2('c ') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#0aff0a') renderer.stopRender(context) # tolerant match, case insensitive matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols(style, QgsSymbol.Marker, False, True) self.assertEqual(matched, 3) self.assertFalse(unmatched_cats) self.assertEqual(unmatched_symbols, ['C', 'b']) # make sure symbols were applied context = QgsRenderContext() renderer.startRender(context, QgsFields()) symbol, ok = renderer.symbolForValue2('a') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#ff0a0a') symbol, ok = renderer.symbolForValue2('b') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#0aff0a') symbol, ok = renderer.symbolForValue2('c ') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#0aff0a') renderer.stopRender(context)
def run(self): """ Start the library generation """ patched_xml = ['S_01_081_0017', 'S_01_081_0018', 'S_14_145_0015', 'S_05_019_0001', 'L_19_006_0008', 'L_25_116_0001', 'S_11_042_0013', 'L_21_105_0002', 'L_21_107_0010', 'L_22_092_0003', 'L_22_092_0008', 'L_22_092_0009', 'L_22_092_0010', 'L_22_092_0011', 'L_22_092_0012', 'P_31_159_0002', 'S_01_081_0010', 'S_01_089_0016', 'S_05_017_0008', 'S_10_041_0004', 'S_13_046_0012', 'S_13_046_0018', 'S_14_048_0008', 'S_18_071_0001', 'P_28_157_0001', 'P_32_160_0001', 'P_33_161_0001'] # Symbols for which it exists a manually modified svg patched_svg = ['P_26_120_0015', 'P_33_172_0001', 'P_26_122_0007', 'P_26_124_0004_1', 'L_20_099_0006', 'L_20_099_0007', 'L_20_099_0009', 'L_20_099_0011', 'P_28_157_0001', 'P_32_160_0001', 'P_33_161_0001'] blobs = [] style = QgsStyle() context = Context() context.units = QgsUnitTypes.RenderMillimeters context.relative_paths = True context.picture_folder = os.path.join( self.output_directory, 'svg') context.convert_fonts = True context.force_svg_instead_of_raster = True context.parameterise_svg = False context.embed_pictures = False a = QApplication([]) for fn in os.listdir(self.bin_directory): file = os.path.join(self.bin_directory, fn) if os.path.isfile(file): blobs.append(file) symbol_name = os.path.splitext(fn)[0] with open(file, 'rb') as f: context.symbol_name = symbol_name symbol = read_symbol(f, debug=False) qgis_symbol = Symbol_to_QgsSymbol(symbol, context) if symbol_name in patched_xml: xml_file = os.path.join( self.patched_xml_directory, symbol_name + '.xml') style.importXml(xml_file) print("Patch symbol {} with {}".format( symbol_name, xml_file)) continue style.addSymbol(symbol_name, qgis_symbol) style.exportXml( os.path.join(self.output_directory, 'libreria.xml')) for svg in patched_svg: svg_src = os.path.join(self.patched_svg_directory, svg + '.svg') svg_dest = os.path.join( self.output_directory, 'svg', svg + '.svg') copyfile(svg_src, svg_dest) print("Patch svg {} with {}".format(svg_dest, svg_src))