def testCancelAndDestroy(self): """ test that nothing goes wrong if we destroy a canvas while a job is canceling """ canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326)) canvas.setFrameStyle(0) canvas.resize(600, 400) layer = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string", "layer", "memory") # add a ton of features for i in range(5000): f = QgsFeature() f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45))) self.assertTrue(layer.dataProvider().addFeatures([f])) canvas.setLayers([layer]) canvas.setExtent(QgsRectangle(10, 30, 20, 35)) canvas.show() # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() self.assertTrue(canvas.isDrawing()) canvas.stopRendering() del canvas
def testDeferredUpdate(self): """ test that map canvas doesn't auto refresh on deferred layer update """ canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326)) canvas.setFrameStyle(0) canvas.resize(600, 400) self.assertEqual(canvas.width(), 600) self.assertEqual(canvas.height(), 400) layer = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string", "layer", "memory") canvas.setLayers([layer]) canvas.setExtent(QgsRectangle(10, 30, 20, 35)) canvas.show() # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() while canvas.isDrawing(): app.processEvents() self.assertTrue(self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas)) # add polygon to layer f = QgsFeature() f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45))) self.assertTrue(layer.dataProvider().addFeatures([f])) # deferred update - so expect that canvas will not been refreshed layer.triggerRepaint(True) timeout = time.time() + 0.1 while time.time() < timeout: # messy, but only way to check that canvas redraw doesn't occur self.assertFalse(canvas.isDrawing()) # canvas should still be empty self.assertTrue(self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas)) # refresh canvas canvas.refresh() while not canvas.isDrawing(): app.processEvents() while canvas.isDrawing(): app.processEvents() # now we expect the canvas check to fail (since they'll be a new polygon rendered over it) self.assertFalse(self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas))
def testDeferredUpdate(self): """ test that map canvas doesn't auto refresh on deferred layer update """ canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326)) canvas.setFrameStyle(0) canvas.resize(600, 400) self.assertEqual(canvas.width(), 600) self.assertEqual(canvas.height(), 400) layer = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string", "layer", "memory") canvas.setLayers([layer]) canvas.setExtent(QgsRectangle(10, 30, 20, 35)) canvas.show() # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas)) # add polygon to layer f = QgsFeature() f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45))) self.assertTrue(layer.dataProvider().addFeatures([f])) # deferred update - so expect that canvas will not been refreshed layer.triggerRepaint(True) timeout = time.time() + 0.1 while time.time() < timeout: # messy, but only way to check that canvas redraw doesn't occur self.assertFalse(canvas.isDrawing()) # canvas should still be empty self.assertTrue(self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas)) # refresh canvas canvas.refresh() canvas.waitWhileRendering() # now we expect the canvas check to fail (since they'll be a new polygon rendered over it) self.assertFalse(self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas))
def testMainAnnotationLayerRendered(self): """ test that main annotation layer is rendered above all other layers """ canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326)) canvas.setFrameStyle(0) canvas.resize(600, 400) self.assertEqual(canvas.width(), 600) self.assertEqual(canvas.height(), 400) layer = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string", "layer", "memory") sym3 = QgsFillSymbol.createSimple({'color': '#b200b2'}) layer.renderer().setSymbol(sym3) canvas.setLayers([layer]) canvas.setExtent(QgsRectangle(10, 30, 20, 35)) canvas.show() # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas)) # add polygon to layer f = QgsFeature() f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45))) self.assertTrue(layer.dataProvider().addFeatures([f])) # refresh canvas canvas.refresh() canvas.waitWhileRendering() # no annotation yet... self.assertFalse(self.canvasImageCheck('main_annotation_layer', 'main_annotation_layer', canvas)) annotation_layer = QgsProject.instance().mainAnnotationLayer() annotation_layer.setCrs(QgsCoordinateReferenceSystem(4326)) annotation_geom = QgsGeometry.fromRect(QgsRectangle(12, 30, 18, 33)) annotation = QgsAnnotationPolygonItem(annotation_geom.constGet().clone()) sym3 = QgsFillSymbol.createSimple({'color': '#ff0000', 'outline_style': 'no'}) annotation.setSymbol(sym3) annotation_layer.addItem(annotation) # refresh canvas canvas.refresh() canvas.waitWhileRendering() # annotation must be rendered over other layers self.assertTrue(self.canvasImageCheck('main_annotation_layer', 'main_annotation_layer', canvas)) annotation_layer.clear()
def test_feature_transformation(self): poly_shp = os.path.join(TEST_DATA_DIR, 'polys.shp') layer = QgsVectorLayer(poly_shp, 'Layer', 'ogr') sub_symbol = QgsFillSymbol.createSimple({ 'color': '#8888ff', 'outline_style': 'no' }) sym = QgsFillSymbol() buffer_layer = QgsGeometryGeneratorSymbolLayer.create( {'geometryModifier': 'buffer($geometry, -0.4)'}) buffer_layer.setSymbolType(QgsSymbol.Fill) buffer_layer.setSubSymbol(sub_symbol) sym.changeSymbolLayer(0, buffer_layer) layer.setRenderer(QgsSingleSymbolRenderer(sym)) canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3857')) canvas.setFrameStyle(0) canvas.resize(600, 400) self.assertEqual(canvas.width(), 600) self.assertEqual(canvas.height(), 400) canvas.setLayers([layer]) canvas.setExtent(QgsRectangle(-11960254, 4247568, -11072454, 4983088)) canvas.show() # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() feature = layer.getFeature(1) self.assertTrue(feature.isValid()) highlight = QgsHighlight(canvas, feature, layer) color = QColor(Qt.red) highlight.setColor(color) color.setAlpha(50) highlight.setFillColor(color) highlight.show() highlight.show() self.assertTrue( self.canvasImageCheck('highlight_transform', 'highlight_transform', canvas))
def testRefreshOnTimer(self): """ test that map canvas refreshes with auto refreshing layers """ canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326)) canvas.setFrameStyle(0) canvas.resize(600, 400) self.assertEqual(canvas.width(), 600) self.assertEqual(canvas.height(), 400) layer = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string", "layer", "memory") canvas.setLayers([layer]) canvas.setExtent(QgsRectangle(10, 30, 20, 35)) canvas.show() # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() self.assertTrue( self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas)) # add polygon to layer f = QgsFeature() f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45))) self.assertTrue(layer.dataProvider().addFeatures([f])) # set auto refresh on layer layer.setAutoRefreshInterval(100) layer.setAutoRefreshEnabled(True) timeout = time.time() + 1 # expect canvas to auto refresh... while not canvas.isDrawing(): app.processEvents() self.assertTrue(time.time() < timeout) while canvas.isDrawing(): app.processEvents() self.assertTrue(time.time() < timeout) # add a polygon to layer f = QgsFeature() f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45))) self.assertTrue(layer.dataProvider().addFeatures([f])) # wait for canvas auto refresh while not canvas.isDrawing(): app.processEvents() self.assertTrue(time.time() < timeout) while canvas.isDrawing(): app.processEvents() self.assertTrue(time.time() < timeout) # now canvas should look different... self.assertFalse( self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas)) # switch off auto refresh layer.setAutoRefreshEnabled(False) timeout = time.time() + 0.5 while time.time() < timeout: # messy, but only way to check that canvas redraw doesn't occur self.assertFalse(canvas.isDrawing())
def testMapTheme(self): canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326)) canvas.setFrameStyle(0) canvas.resize(600, 400) self.assertEqual(canvas.width(), 600) self.assertEqual(canvas.height(), 400) layer = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string", "layer", "memory") # add a polygon to layer f = QgsFeature() f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45))) self.assertTrue(layer.dataProvider().addFeatures([f])) # create a style sym1 = QgsFillSymbol.createSimple({'color': '#ffb200'}) renderer = QgsSingleSymbolRenderer(sym1) layer.setRenderer(renderer) canvas.setLayers([layer]) canvas.setExtent(QgsRectangle(10, 30, 20, 35)) canvas.show() # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # add some styles layer.styleManager().addStyleFromLayer('style1') sym2 = QgsFillSymbol.createSimple({'color': '#00b2ff'}) renderer2 = QgsSingleSymbolRenderer(sym2) layer.setRenderer(renderer2) layer.styleManager().addStyleFromLayer('style2') canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme2', 'theme2', canvas)) layer.styleManager().setCurrentStyle('style1') canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # ok, so all good with setting/rendering map styles # try setting canvas to a particular theme # make some themes... theme1 = QgsMapThemeCollection.MapThemeRecord() record1 = QgsMapThemeCollection.MapThemeLayerRecord(layer) record1.currentStyle = 'style1' record1.usingCurrentStyle = True theme1.setLayerRecords([record1]) theme2 = QgsMapThemeCollection.MapThemeRecord() record2 = QgsMapThemeCollection.MapThemeLayerRecord(layer) record2.currentStyle = 'style2' record2.usingCurrentStyle = True theme2.setLayerRecords([record2]) QgsProject.instance().mapThemeCollection().insert('theme1', theme1) QgsProject.instance().mapThemeCollection().insert('theme2', theme2) canvas.setTheme('theme2') canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme2', 'theme2', canvas)) canvas.setTheme('theme1') canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # add another layer layer2 = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string", "layer2", "memory") f = QgsFeature() f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45))) self.assertTrue(layer2.dataProvider().addFeatures([f])) # create a style sym1 = QgsFillSymbol.createSimple({'color': '#b2ff00'}) renderer = QgsSingleSymbolRenderer(sym1) layer2.setRenderer(renderer) # rerender canvas - should NOT show new layer canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # test again - this time refresh all layers canvas.refreshAllLayers() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # add layer 2 to theme1 record3 = QgsMapThemeCollection.MapThemeLayerRecord(layer2) theme1.setLayerRecords([record3]) QgsProject.instance().mapThemeCollection().update('theme1', theme1) canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme3', 'theme3', canvas)) # change the appearance of an active style layer2.styleManager().addStyleFromLayer('original') layer2.styleManager().addStyleFromLayer('style4') record3.currentStyle = 'style4' record3.usingCurrentStyle = True theme1.setLayerRecords([record3]) QgsProject.instance().mapThemeCollection().update('theme1', theme1) canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme3', 'theme3', canvas)) layer2.styleManager().setCurrentStyle('style4') sym3 = QgsFillSymbol.createSimple({'color': '#b200b2'}) layer2.renderer().setSymbol(sym3) canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme4', 'theme4', canvas)) # try setting layers while a theme is in place canvas.setLayers([layer]) canvas.refresh() # should be no change... setLayers should be ignored if canvas is following a theme! canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme4', 'theme4', canvas)) # setLayerStyleOverrides while theme is in place canvas.setLayerStyleOverrides({layer2.id(): 'original'}) # should be no change... setLayerStyleOverrides should be ignored if canvas is following a theme! canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme4', 'theme4', canvas)) # clear theme canvas.setTheme('') canvas.refresh() canvas.waitWhileRendering() # should be different - we should now render project layers self.assertFalse(self.canvasImageCheck('theme4', 'theme4', canvas))
def testRefreshOnTimer(self): """ test that map canvas refreshes with auto refreshing layers """ canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326)) canvas.setFrameStyle(0) canvas.resize(600, 400) self.assertEqual(canvas.width(), 600) self.assertEqual(canvas.height(), 400) layer = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string", "layer", "memory") canvas.setLayers([layer]) canvas.setExtent(QgsRectangle(10, 30, 20, 35)) canvas.show() # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas)) # add polygon to layer f = QgsFeature() f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45))) self.assertTrue(layer.dataProvider().addFeatures([f])) # set auto refresh on layer layer.setAutoRefreshInterval(100) layer.setAutoRefreshEnabled(True) timeout = time.time() + 1 # expect canvas to auto refresh... while not canvas.isDrawing(): app.processEvents() self.assertTrue(time.time() < timeout) while canvas.isDrawing(): app.processEvents() self.assertTrue(time.time() < timeout) # add a polygon to layer f = QgsFeature() f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45))) self.assertTrue(layer.dataProvider().addFeatures([f])) # wait for canvas auto refresh while not canvas.isDrawing(): app.processEvents() self.assertTrue(time.time() < timeout) while canvas.isDrawing(): app.processEvents() self.assertTrue(time.time() < timeout) # now canvas should look different... self.assertFalse(self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas)) # switch off auto refresh layer.setAutoRefreshEnabled(False) timeout = time.time() + 0.5 while time.time() < timeout: # messy, but only way to check that canvas redraw doesn't occur self.assertFalse(canvas.isDrawing())
def testMapTheme(self): canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326)) canvas.setFrameStyle(0) canvas.resize(600, 400) self.assertEqual(canvas.width(), 600) self.assertEqual(canvas.height(), 400) layer = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string", "layer", "memory") # add a polygon to layer f = QgsFeature() f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45))) self.assertTrue(layer.dataProvider().addFeatures([f])) # create a style sym1 = QgsFillSymbol.createSimple({'color': '#ffb200'}) renderer = QgsSingleSymbolRenderer(sym1) layer.setRenderer(renderer) canvas.setLayers([layer]) canvas.setExtent(QgsRectangle(10, 30, 20, 35)) canvas.show() # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # add some styles layer.styleManager().addStyleFromLayer('style1') sym2 = QgsFillSymbol.createSimple({'color': '#00b2ff'}) renderer2 = QgsSingleSymbolRenderer(sym2) layer.setRenderer(renderer2) layer.styleManager().addStyleFromLayer('style2') canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme2', 'theme2', canvas)) layer.styleManager().setCurrentStyle('style1') canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # OK, so all good with setting/rendering map styles # try setting canvas to a particular theme # make some themes... theme1 = QgsMapThemeCollection.MapThemeRecord() record1 = QgsMapThemeCollection.MapThemeLayerRecord(layer) record1.currentStyle = 'style1' record1.usingCurrentStyle = True theme1.setLayerRecords([record1]) theme2 = QgsMapThemeCollection.MapThemeRecord() record2 = QgsMapThemeCollection.MapThemeLayerRecord(layer) record2.currentStyle = 'style2' record2.usingCurrentStyle = True theme2.setLayerRecords([record2]) QgsProject.instance().mapThemeCollection().insert('theme1', theme1) QgsProject.instance().mapThemeCollection().insert('theme2', theme2) canvas.setTheme('theme2') canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme2', 'theme2', canvas)) canvas.setTheme('theme1') canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # add another layer layer2 = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string", "layer2", "memory") f = QgsFeature() f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45))) self.assertTrue(layer2.dataProvider().addFeatures([f])) # create a style sym1 = QgsFillSymbol.createSimple({'color': '#b2ff00'}) renderer = QgsSingleSymbolRenderer(sym1) layer2.setRenderer(renderer) # rerender canvas - should NOT show new layer canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # test again - this time refresh all layers canvas.refreshAllLayers() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # add layer 2 to theme1 record3 = QgsMapThemeCollection.MapThemeLayerRecord(layer2) theme1.setLayerRecords([record3]) QgsProject.instance().mapThemeCollection().update('theme1', theme1) canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme3', 'theme3', canvas)) # change the appearance of an active style layer2.styleManager().addStyleFromLayer('original') layer2.styleManager().addStyleFromLayer('style4') record3.currentStyle = 'style4' record3.usingCurrentStyle = True theme1.setLayerRecords([record3]) QgsProject.instance().mapThemeCollection().update('theme1', theme1) canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme3', 'theme3', canvas)) layer2.styleManager().setCurrentStyle('style4') sym3 = QgsFillSymbol.createSimple({'color': '#b200b2'}) layer2.renderer().setSymbol(sym3) canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme4', 'theme4', canvas)) # try setting layers while a theme is in place canvas.setLayers([layer]) canvas.refresh() # should be no change... setLayers should be ignored if canvas is following a theme! canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme4', 'theme4', canvas)) # setLayerStyleOverrides while theme is in place canvas.setLayerStyleOverrides({layer2.id(): 'original'}) # should be no change... setLayerStyleOverrides should be ignored if canvas is following a theme! canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme4', 'theme4', canvas)) # clear theme canvas.setTheme('') canvas.refresh() canvas.waitWhileRendering() # should be different - we should now render project layers self.assertFalse(self.canvasImageCheck('theme4', 'theme4', canvas))
def test_rendered_item_results_remove_outdated(self): """ Test that outdated results are removed from rendered item result caches """ canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326')) canvas.setFrameStyle(0) canvas.resize(600, 400) canvas.setCachingEnabled(True) self.assertEqual(canvas.width(), 600) self.assertEqual(canvas.height(), 400) layer = QgsAnnotationLayer( 'test', QgsAnnotationLayer.LayerOptions( QgsProject.instance().transformContext())) self.assertTrue(layer.isValid()) layer2 = QgsAnnotationLayer( 'test', QgsAnnotationLayer.LayerOptions( QgsProject.instance().transformContext())) self.assertTrue(layer2.isValid()) item = QgsAnnotationPolygonItem( QgsPolygon( QgsLineString([ QgsPoint(11.5, 13), QgsPoint(12, 13), QgsPoint(12, 13.5), QgsPoint(11.5, 13) ]))) item.setSymbol( QgsFillSymbol.createSimple({ 'color': '200,100,100', 'outline_color': 'black', 'outline_width': '2' })) item.setZIndex(1) i1_id = layer.addItem(item) item = QgsAnnotationLineItem( QgsLineString( [QgsPoint(11, 13), QgsPoint(12, 13), QgsPoint(12, 15)])) item.setZIndex(2) i2_id = layer.addItem(item) item = QgsAnnotationMarkerItem(QgsPoint(12, 13)) item.setZIndex(3) i3_id = layer2.addItem(item) layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) layer2.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) canvas.setLayers([layer, layer2]) canvas.setExtent(QgsRectangle(10, 10, 18, 18)) canvas.show() # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() results = canvas.renderedItemResults() self.assertCountEqual([i.itemId() for i in results.renderedItems()], [i1_id, i2_id, i3_id]) # now try modifying an annotation in the layer -- it will redraw, and we don't want to reuse any previously # cached rendered item results for this layer! item = QgsAnnotationPolygonItem( QgsPolygon( QgsLineString([ QgsPoint(11.5, 13), QgsPoint(12.5, 13), QgsPoint(12.5, 13.5), QgsPoint(11.5, 13) ]))) item.setZIndex(1) layer.replaceItem(i1_id, item) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() item = QgsAnnotationMarkerItem(QgsPoint(17, 18)) item.setZIndex(3) layer2.replaceItem(i3_id, item) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() results = canvas.renderedItemResults() items_in_bounds = results.renderedAnnotationItemsInBounds( QgsRectangle(10, 10, 15, 15)) self.assertCountEqual([i.itemId() for i in items_in_bounds], [i1_id, i2_id]) items_in_bounds = results.renderedAnnotationItemsInBounds( QgsRectangle(15, 15, 20, 20)) self.assertCountEqual([i.itemId() for i in items_in_bounds], [i3_id])
def test_rendered_items(self): canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326')) canvas.setFrameStyle(0) canvas.resize(600, 400) canvas.setCachingEnabled(True) self.assertEqual(canvas.width(), 600) self.assertEqual(canvas.height(), 400) layer = QgsAnnotationLayer( 'test', QgsAnnotationLayer.LayerOptions( QgsProject.instance().transformContext())) self.assertTrue(layer.isValid()) layer2 = QgsAnnotationLayer( 'test', QgsAnnotationLayer.LayerOptions( QgsProject.instance().transformContext())) self.assertTrue(layer2.isValid()) item = QgsAnnotationPolygonItem( QgsPolygon( QgsLineString([ QgsPoint(11.5, 13), QgsPoint(12, 13), QgsPoint(12, 13.5), QgsPoint(11.5, 13) ]))) item.setSymbol( QgsFillSymbol.createSimple({ 'color': '200,100,100', 'outline_color': 'black', 'outline_width': '2' })) item.setZIndex(1) i1_id = layer.addItem(item) item = QgsAnnotationLineItem( QgsLineString( [QgsPoint(11, 13), QgsPoint(12, 13), QgsPoint(12, 15)])) item.setZIndex(2) i2_id = layer.addItem(item) item = QgsAnnotationMarkerItem(QgsPoint(12, 13)) item.setZIndex(3) i3_id = layer2.addItem(item) layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) layer2.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) canvas.setLayers([layer, layer2]) canvas.setExtent(QgsRectangle(10, 10, 18, 18)) canvas.show() # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() results = canvas.renderedItemResults() self.assertCountEqual([i.itemId() for i in results.renderedItems()], [i1_id, i2_id, i3_id]) # turn off a layer -- the other layer will be rendered direct from the cached version canvas.setLayers([layer2]) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() results = canvas.renderedItemResults() # only layer2 items should be present in results -- but these MUST be present while layer2 is visible in the canvas, # even though the most recent canvas redraw used a cached version of layer2 and didn't actually have to redraw the layer self.assertEqual([i.itemId() for i in results.renderedItems()], [i3_id]) # turn layer 1 back on canvas.setLayers([layer, layer2]) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() results = canvas.renderedItemResults() # both layer1 and layer2 items should be present in results -- even though NEITHER of these layers were re-rendered, # and instead we used precached renders of both layers self.assertCountEqual([i.itemId() for i in results.renderedItems()], [i1_id, i2_id, i3_id])
class MainWindow(QMainWindow): # pylint: disable=too-many-instance-attributes # pylint: disable=too-many-statements def __init__(self, app, mapLayers, mapLayersCategory): QMainWindow.__init__(self) self.app = app self.mapLayers = mapLayers self.mapLayersCategory = mapLayersCategory self.resize(shared.windowWidth, shared.windowHeight) self.setWindowTitle(shared.progName + ": " + shared.progVer) # Set up the map canvas self.canvas = QgsMapCanvas() self.setCentralWidget(self.canvas) self.canvas.setCanvasColor(Qt.white) self.canvas.enableAntiAliasing(True) self.canvas.setCachingEnabled(True) #self.canvas.setMapUpdateInterval(1000) self.canvas.setParallelRenderingEnabled(True) self.canvas.enableMapTileRendering(True) self.canvas.setLayers(self.mapLayers) self.canvas.setExtent(shared.extentRect) self.canvas.setMagnificationFactor(shared.windowMagnification) #mapSet = self.canvas.mapSettings() #print(mapSet.flags()) # Create some actions #self.actionExit = QAction(QIcon('exit.png'), '&Exit', self) self.actionExit = QAction("&Exit", self) self.actionExit.setShortcut("Ctrl+Q") self.actionExit.setStatusTip("Exit " + shared.progName) self.actionZoomIn = QAction("Zoom in", self) self.actionZoomIn.setCheckable(True) #self.actionExit.setShortcut("Ctrl++") self.actionZoomIn.setStatusTip("Show more detail") self.actionZoomOut = QAction("Zoom out", self) self.actionZoomOut.setCheckable(True) #self.actionExit.setShortcut("Ctrl+-") self.actionZoomOut.setStatusTip("Show less detail") self.actionPan = QAction("Pan", self) self.actionPan.setCheckable(True) self.actionPan.setStatusTip("Move the map laterally") self.actionChangeBackground = QAction("Change background", self) self.actionChangeBackground.setStatusTip( "Change the raster background") if not shared.haveRasterBackground: self.actionChangeBackground.setEnabled(False) self.actionCoords = QAction("Show coordinates", self) self.actionCoords.setCheckable(True) self.actionCoords.setStatusTip("Click to show coordinates") self.actionRun = QAction("Simulate", self) self.actionRun.setStatusTip("Route flow") # Connect the actions self.actionExit.triggered.connect(app.quit) self.actionZoomIn.triggered.connect(self.zoomIn) self.actionZoomOut.triggered.connect(self.zoomOut) self.actionPan.triggered.connect(self.pan) self.actionChangeBackground.triggered.connect(self.changeBackground) self.actionCoords.triggered.connect(self.showCoords) self.actionRun.triggered.connect(self.doRun) # Create a menu bar and add menus self.menubar = self.menuBar() self.fileMenu = self.menubar.addMenu("&File") self.fileMenu.addAction(self.actionExit) self.editMenu = self.menubar.addMenu("&Edit") #self.editMenu.addAction(self.actionExit) self.viewMenu = self.menubar.addMenu("&View") self.viewMenu.addAction(self.actionZoomIn) self.viewMenu.addAction(self.actionZoomOut) self.viewMenu.addAction(self.actionPan) self.viewMenu.addAction(self.actionChangeBackground) self.viewMenu.addAction(self.actionCoords) self.runMenu = self.menubar.addMenu("&Run") self.runMenu.addAction(self.actionRun) # Create a tool bar and add some actions self.toolbar = self.addToolBar("Default") self.toolbar.setFloatable(True) self.toolbar.addAction(self.actionRun) self.toolbar.addAction(self.actionZoomIn) self.toolbar.addAction(self.actionZoomOut) self.toolbar.addAction(self.actionPan) self.toolbar.addAction(self.actionCoords) # Create some map tools self.toolPan = QgsMapToolPan(self.canvas) self.toolPan.setAction(self.actionPan) self.toolZoomIn = QgsMapToolZoom(self.canvas, False) # False = in self.toolZoomIn.setAction(self.actionZoomIn) self.toolZoomOut = QgsMapToolZoom(self.canvas, True) # True = out self.toolZoomOut.setAction(self.actionZoomOut) self.toolCoords = PointTool(self.canvas) self.toolCoords.setAction(self.actionCoords) # Put into panning mode self.pan() # Add a status bar self.statusBar = QStatusBar(self.canvas) self.setStatusBar(self.statusBar) # And put a progress indicator on the status bar self.statusBar.progress = QProgressBar(self) self.statusBar.progress.setRange(0, 100) self.statusBar.progress.setMaximumWidth(500) self.statusBar.progress.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.statusBar.addPermanentWidget(self.statusBar.progress) self.myThread = None return #====================================================================================================================== #====================================================================================================================== def doRun(self): # Delete all output features (in case we have some from a previous run) listIDs = [ feat.id() for feat in shared.outFlowMarkerPointLayer.getFeatures() ] prov = shared.outFlowMarkerPointLayer.dataProvider() prov.deleteFeatures([featID for featID in listIDs]) shared.outFlowMarkerPointLayer.updateExtents() shared.outFlowMarkerPointLayer.triggerRepaint() listIDs = [feat.id() for feat in shared.outFlowLineLayer.getFeatures()] prov = shared.outFlowLineLayer.dataProvider() prov.deleteFeatures([featID for featID in listIDs]) shared.outFlowLineLayer.updateExtents() shared.outFlowLineLayer.triggerRepaint() self.canvas.repaint() self.statusBar.progress.setValue(0) self.actionRun.setEnabled(False) # All is now ready, so run the simulation as a separate thread self.myThread = SimulationThread(self.app, self) self.myThread.refresh.connect(self.doRefresh) self.myThread.runDone.connect(self.runDone) self.canvas.freeze(True) #self.canvas.refreshAllLayers() #self.app.processEvents() self.myThread.start() print("\nThread started") return #====================================================================================================================== #====================================================================================================================== def doRefresh(self): self.canvas.freeze(False) if not self.canvas.isDrawing(): shared.outFlowMarkerPointLayer.triggerRepaint() shared.outFlowLineLayer.triggerRepaint() self.canvas.repaint() self.canvas.freeze(True) if not isinstance(shared.flowStartPoints, int): doneSoFar = (float(shared.thisStartPoint) / float(len(shared.flowStartPoints) + 1)) * 100.0 #shared.fpOut.write(doneSoFar) self.statusBar.progress.setValue(doneSoFar) return #====================================================================================================================== #====================================================================================================================== def zoomIn(self): self.canvas.freeze(False) self.canvas.setMapTool(self.toolZoomIn) return #====================================================================================================================== #====================================================================================================================== def zoomOut(self): self.canvas.freeze(False) self.canvas.setMapTool(self.toolZoomOut) return #====================================================================================================================== #====================================================================================================================== def pan(self): self.canvas.freeze(False) self.canvas.setMapTool(self.toolPan) return #====================================================================================================================== #====================================================================================================================== def showCoords(self): self.canvas.setMapTool(self.toolCoords) return #====================================================================================================================== #====================================================================================================================== def close(self): if self.myThread: self.myThread.quit() self.myThread = None return #====================================================================================================================== #====================================================================================================================== def runDone(self): self.canvas.freeze(False) shared.outFlowMarkerPointLayer.triggerRepaint() shared.outFlowLineLayer.triggerRepaint() self.canvas.repaint() print("Thread done") self.myThread.quit() #self.myThread = None self.statusBar.progress.setValue(100) #QMessageBox.information(self, "End of run", shared.progName + ": flow routed") self.statusBar.showMessage("End of run: flow routed", shared.defaultMessageDisplayTime) # To prevent subsequent re-runs # self.actionRun.setEnabled(False) return #====================================================================================================================== #====================================================================================================================== def changeBackground(self): for n in range(len(shared.rasterInputLayersCategory)): if shared.rasterInputLayersCategory[n] == INPUT_RASTER_BACKGROUND: oldOpacity = shared.rasterInputLayers[n].renderer().opacity() if oldOpacity == 0: newOpacity = shared.rasterFileOpacity[n] else: newOpacity = 0 shared.rasterInputLayers[n].renderer().setOpacity(newOpacity) #layerID = shared.rasterInputLayers[n].id() #layerTreeNode = QgsProject.instance().layerTreeRoot().findLayer(layerID) #print(layerTreeNode.dump()) #layerTreeNode.setItemVisibilityChecked(not layerTreeNode.itemVisibilityChecked()) #print(layerTreeNode.dump()) #print("*****************") #for n in range(len(self.mapLayers)): #if self.mapLayersCategory[n] == INPUT_RASTER_BACKGROUND: #self.mapLayers[n].setVisible(not self.mapLayers[n].isVisible()) #self.canvas.setLayers(self.mapLayers) self.doRefresh() return