class MainWindow(QtGui.QMainWindow): def __init__(self): QtGui.QMainWindow.__init__(self) self.canvas = QgsMapCanvas() self.canvas.setCanvasColor(QtGui.QColor(255, 255, 255)) self.canvas.enableAntiAliasing(True) def create_layer(self, data): display_name = 'some-layer' uri = 'Point?crs=epsg:4326&index=yes&uuid=%s' % uuid.uuid4() vlayer = QgsVectorLayer(uri, display_name, 'memory') QgsMapLayerRegistry.instance().addMapLayer(vlayer) provider = vlayer.dataProvider() vlayer.startEditing() provider.addAttributes([ QgsField('population_density', QtCore.QVariant.Double), ]) features = [] for x, y, density in data: feat = QgsFeature() geom = QgsGeometry.fromPoint(QgsPoint(x, y)) feat.setGeometry(geom) feat.setAttributes([density]) features.append(feat) provider.addFeatures(features) vlayer.commitChanges() vlayer.updateExtents() self.canvas.setExtent(vlayer.extent()) vlayer.triggerRepaint()
class RenderWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.setupUi() self.layer = None self.marker = Marker(self.canvas) def setupUi(self): gridLayout = QGridLayout(self) gridLayout.setContentsMargins(0, 0, 0, 0) self.canvas = QgsMapCanvas() self.canvas.setCanvasColor(QColor(255, 255, 255)) self.canvas.setStyleSheet("border: 0px;") settings = QSettings() self.canvas.enableAntiAliasing(settings.value("/qgis/enable_anti_aliasing", False, type=bool)) self.setMinimumSize(15, 15) # mouse action pan and zoom self.pan_zoom_tool = PanAndZoomPointTool(self) self.canvas.setMapTool(self.pan_zoom_tool) gridLayout.addWidget(self.canvas) def render_layer(self, layer): with block_signals_to(self): # set the CRS of the canvas view based on sampling layer sampling_crs = self.parent_view.sampling_layer.crs() self.canvas.setDestinationCrs(sampling_crs) # set the sampling over the layer to view self.canvas.setLayers([self.parent_view.sampling_layer, layer]) # set init extent from other view if any is activated else set layer extent from AcATaMa.gui.classification_dialog import ClassificationDialog others_view = [(view_widget.render_widget.canvas.extent(), view_widget.current_scale_factor) for view_widget in ClassificationDialog.view_widgets if not view_widget.render_widget.canvas.extent().isEmpty()] if others_view: extent, scale = others_view[0] extent.scale(1 / scale) self.set_extents_and_scalefactor(extent) elif ClassificationDialog.current_sample: ClassificationDialog.current_sample.fit_to( self.parent_view, ClassificationDialog.instance.radiusFitToSample.value()) self.canvas.refresh() self.layer = layer # show marker if ClassificationDialog.current_sample: self.marker.show(ClassificationDialog.current_sample) def set_extents_and_scalefactor(self, extent): with block_signals_to(self.canvas): self.canvas.setExtent(extent) self.canvas.zoomByFactor(self.parent_view.scaleFactor.value()) if self.marker.marker: self.marker.marker.updatePosition() def layer_style_editor(self): style_editor_dlg = StyleEditorDialog(self.layer, self.canvas, self.parent_view) if style_editor_dlg.exec_(): style_editor_dlg.apply()
class ViewerWnd( QMainWindow ): def __init__( self, app, dictOpts ): QMainWindow.__init__( self ) self.setWindowTitle( "PostGIS Layer Viewer - v.1.6.1" ) self.setTabPosition( Qt.BottomDockWidgetArea, QTabWidget.North ) self.canvas = QgsMapCanvas() self.canvas.setCanvasColor( Qt.white ) self.canvas.useImageToRender( True ) self.canvas.enableAntiAliasing( True ) self.setCentralWidget( self.canvas ) actionZoomIn = QAction( QIcon( imgs_dir + "mActionZoomIn.png" ), QString( "Zoom in" ), self ) actionZoomOut = QAction( QIcon( imgs_dir + "mActionZoomOut.png" ), QString( "Zoom out" ), self ) actionPan = QAction( QIcon( imgs_dir + "mActionPan.png" ), QString( "Pan" ), self ) actionZoomFullExtent = QAction( QIcon( imgs_dir + "mActionZoomFullExtent.png" ), QString( "Zoom full" ), self ) actionZoomIn.setCheckable( True ) actionZoomOut.setCheckable( True ) actionPan.setCheckable( True ) self.connect(actionZoomIn, SIGNAL( "triggered()" ), self.zoomIn ) self.connect(actionZoomOut, SIGNAL( "triggered()" ), self.zoomOut ) self.connect(actionPan, SIGNAL( "triggered()" ), self.pan ) self.connect(actionZoomFullExtent, SIGNAL( "triggered()" ), self.zoomFullExtent ) self.actionGroup = QActionGroup( self ) self.actionGroup.addAction( actionPan ) self.actionGroup.addAction( actionZoomIn ) self.actionGroup.addAction( actionZoomOut ) # Create the toolbar self.toolbar = self.addToolBar( "Map tools" ) self.toolbar.addAction( actionPan ) self.toolbar.addAction( actionZoomIn ) self.toolbar.addAction( actionZoomOut ) self.toolbar.addAction( actionZoomFullExtent ) # Create the map tools self.toolPan = QgsMapToolPan( self.canvas ) self.toolPan.setAction( actionPan ) self.toolZoomIn = QgsMapToolZoom( self.canvas, False ) # false = in self.toolZoomIn.setAction( actionZoomIn ) self.toolZoomOut = QgsMapToolZoom( self.canvas, True ) # true = out self.toolZoomOut.setAction( actionZoomOut ) # Create the statusbar self.statusbar = QStatusBar( self ) self.statusbar.setObjectName( "statusbar" ) self.setStatusBar( self.statusbar ) self.lblXY = QLabel() self.lblXY.setFrameStyle( QFrame.Box ) self.lblXY.setMinimumWidth( 170 ) self.lblXY.setAlignment( Qt.AlignCenter ) self.statusbar.setSizeGripEnabled( False ) self.statusbar.addPermanentWidget( self.lblXY, 0 ) self.lblScale = QLabel() self.lblScale.setFrameStyle( QFrame.StyledPanel ) self.lblScale.setMinimumWidth( 140 ) self.statusbar.addPermanentWidget( self.lblScale, 0 ) self.createLegendWidget() # Create the legend widget self.connect( app, SIGNAL( "loadPgLayer" ), self.loadLayer ) self.connect( self.canvas, SIGNAL( "scaleChanged(double)" ), self.changeScale ) self.connect( self.canvas, SIGNAL( "xyCoordinates(const QgsPoint&)" ), self.updateXY ) self.pan() # Default self.plugins = Plugins( self, self.canvas, dictOpts['-h'], dictOpts['-p'], dictOpts['-d'], dictOpts['-U'], dictOpts['-W'] ) self.createAboutWidget() self.layerSRID = '-1' self.loadLayer( dictOpts ) def zoomIn( self ): self.canvas.setMapTool( self.toolZoomIn ) def zoomOut( self ): self.canvas.setMapTool( self.toolZoomOut ) def pan( self ): self.canvas.setMapTool( self.toolPan ) def zoomFullExtent( self ): self.canvas.zoomToFullExtent() def about( self ): pass def createLegendWidget( self ): """ Create the map legend widget and associate it to the canvas """ self.legend = Legend( self ) self.legend.setCanvas( self.canvas ) self.legend.setObjectName( "theMapLegend" ) self.LegendDock = QDockWidget( "Layers", self ) self.LegendDock.setObjectName( "legend" ) self.LegendDock.setTitleBarWidget( QWidget() ) self.LegendDock.setWidget( self.legend ) self.LegendDock.setContentsMargins ( 0, 0, 0, 0 ) self.addDockWidget( Qt.BottomDockWidgetArea, self.LegendDock ) def createAboutWidget( self ): self.AboutDock = QDockWidget( "About", self ) self.AboutDock.setObjectName( "about" ) self.AboutDock.setTitleBarWidget( QWidget() ) self.AboutDock.setContentsMargins( 0, 0, 0, 0 ) self.tabifyDockWidget( self.LegendDock, self.AboutDock ) self.LegendDock.raise_() # legendDock at the top from PyQt4.QtCore import QRect from PyQt4.QtGui import QSizePolicy, QGridLayout, QFont font = QFont() font.setFamily("Sans Serif") font.setPointSize(8.7) self.AboutWidget = QWidget() self.AboutWidget.setFont( font ) self.AboutWidget.setObjectName("AboutWidget") self.AboutDock.setWidget( self.AboutWidget ) self.labelAbout = QLabel( self.AboutWidget ) self.labelAbout.setAlignment(Qt.AlignCenter) self.labelAbout.setWordWrap(True) self.gridLayout = QGridLayout(self.AboutWidget) self.gridLayout.setContentsMargins(0, 0, 0, 0) self.gridLayout.setObjectName("gridLayout") self.gridLayout.addWidget(self.labelAbout, 0, 1, 1, 1) self.labelAbout.setTextInteractionFlags(Qt.LinksAccessibleByMouse|Qt.LinksAccessibleByKeyboard|Qt.TextSelectableByKeyboard|Qt.TextSelectableByMouse) self.labelAbout.setOpenExternalLinks( True ) self.labelAbout.setText("<html><head/><body><a href=\"http://geotux.tuxfamily.org/index.php/en/geo-blogs/item/293-consola-sql-para-plugin-pgadmin-postgis-viewer\">PostGIS Layer Viewer</a> v.1.6.1 (2015.02.24)<br \><br \>" \ "Copyright (c) 2010 Ivan Mincik,<br \>[email protected]<br \>" \ u"Copyright (c) 2011-2015 Germán Carrillo,<br \>[email protected]<br \><br \>" \ "<i>Licensed under the terms of GNU GPL v.2.0</i><br \><br \>" \ "Based on PyQGIS. Plugin Fast SQL Layer by Pablo T. Carreira.</body></html>" ) def loadLayer( self, dictOpts ): print 'I: Loading the layer...' self.layerSRID = dictOpts[ 'srid' ] # To access the SRID when querying layer properties if not self.isActiveWindow(): self.activateWindow() self.raise_() if dictOpts['type'] == 'vector': # QGIS connection uri = QgsDataSourceURI() uri.setConnection( dictOpts['-h'], dictOpts['-p'], dictOpts['-d'], dictOpts['-U'], dictOpts['-W'] ) uri.setDataSource( dictOpts['-s'], dictOpts['-t'], dictOpts['-g'] ) layer = QgsVectorLayer( uri.uri(), dictOpts['-s'] + '.' + dictOpts['-t'], "postgres" ) elif dictOpts['type'] == 'raster': connString = "PG: dbname=%s host=%s user=%s password=%s port=%s mode=2 " \ "schema=%s column=%s table=%s" % ( dictOpts['-d'], dictOpts['-h'], dictOpts['-U'], dictOpts['-W'], dictOpts['-p'], dictOpts['-s'], dictOpts['col'], dictOpts['-t'] ) layer = QgsRasterLayer( connString, dictOpts['-s'] + '.' + dictOpts['-t'] ) if layer.isValid(): layer.setContrastEnhancement( QgsContrastEnhancement.StretchToMinimumMaximum ) self.addLayer( layer, self.layerSRID ) def addLayer( self, layer, srid='-1' ): if layer.isValid(): # Only in case that srid != -1, read the layer SRS properties, otherwise don't since it will return 4326 if srid != '-1': self.layerSRID = layer.crs().description() + ' (' + str( layer.crs().postgisSrid() ) + ')' else: self.layerSRID = 'Unknown SRS (-1)' if self.canvas.layerCount() == 0: self.canvas.setExtent( layer.extent() ) if srid != '-1': print 'I: Map SRS (EPSG): %s' % self.layerSRID self.canvas.setMapUnits( layer.crs().mapUnits() ) else: print 'I: Unknown Reference System' self.canvas.setMapUnits( 0 ) # 0: QGis.Meters return QgsMapLayerRegistry.instance().addMapLayer( layer ) return False def activeLayer( self ): """ Returns the active layer in the layer list widget """ return self.legend.activeLayer() def getLayerProperties( self, l ): """ Create a layer-properties string (l:layer)""" print 'I: Generating layer properties...' if l.type() == 0: # Vector wkbType = ["WKBUnknown","WKBPoint","WKBLineString","WKBPolygon", "WKBMultiPoint","WKBMultiLineString","WKBMultiPolygon", "WKBNoGeometry","WKBPoint25D","WKBLineString25D","WKBPolygon25D", "WKBMultiPoint25D","WKBMultiLineString25D","WKBMultiPolygon25D"] properties = "Source: %s\n" \ "Geometry type: %s\n" \ "Number of features: %s\n" \ "Number of fields: %s\n" \ "SRS (EPSG): %s\n" \ "Extent: %s " \ % ( l.source(), wkbType[l.wkbType()], l.featureCount(), l.dataProvider().fields().count(), self.layerSRID, l.extent().toString() ) elif l.type() == 1: # Raster rType = [ "GrayOrUndefined (single band)", "Palette (single band)", "Multiband", "ColorLayer" ] properties = "Source: %s\n" \ "Raster type: %s\n" \ "Width-Height (pixels): %sx%s\n" \ "Bands: %s\n" \ "SRS (EPSG): %s\n" \ "Extent: %s" \ % ( l.source(), rType[l.rasterType()], l.width(), l.height(), l.bandCount(), self.layerSRID, l.extent().toString() ) self.layerSRID = '-1' # Initialize the srid return properties def changeScale( self, scale ): self.lblScale.setText( "Scale 1:" + formatNumber( scale ) ) def updateXY( self, p ): if self.canvas.mapUnits() == 2: # Degrees self.lblXY.setText( formatToDegrees( p.x() ) + " | " \ + formatToDegrees( p.y() ) ) else: # Unidad lineal self.lblXY.setText( formatNumber( p.x() ) + " | " \ + formatNumber( p.y() ) + "" )
class GeometryDiffViewerDialog(QDialog): def __init__(self, geoms, crs, parent = None): super(GeometryDiffViewerDialog, self).__init__(parent) self.geoms = geoms self.crs = crs self.initGui() def initGui(self): layout = QVBoxLayout() self.tab = QTabWidget() self.table = QTableView() self.setLayout(layout) self.canvas = QgsMapCanvas() self.canvas.setCanvasColor(Qt.white) settings = QSettings() self.canvas.enableAntiAliasing(settings.value("/qgis/enable_anti_aliasing", False, type = bool)) self.canvas.useImageToRender(settings.value("/qgis/use_qimage_to_render", False, type = bool)) self.canvas.mapSettings().setDestinationCrs(self.crs) action = settings.value("/qgis/wheel_action", 0, type = float) zoomFactor = settings.value("/qgis/zoom_factor", 2, type = float) self.canvas.setWheelAction(QgsMapCanvas.WheelAction(action), zoomFactor) self.panTool = QgsMapToolPan(self.canvas) self.canvas.setMapTool(self.panTool) execute(self.createLayers) model = GeomDiffTableModel(self.data) self.table.setModel(model) self.table.resizeColumnsToContents() self.table.resizeRowsToContents() self.tab.addTab(self.canvas, "Map view") self.tab.addTab(self.table, "Table view") layout.addWidget(self.tab) self.resize(600, 500) self.setWindowTitle("Geometry comparison") def createLayers(self): textGeometries = [] for geom in self.geoms: text = geom.exportToWkt() valid = " -1234567890.," text = "".join([c for c in text if c in valid]) textGeometries.append(text.split(",")) lines = difflib.Differ().compare(textGeometries[0], textGeometries[1]) self.data = [] for line in lines: if line.startswith("+"): self.data.append([None, line[2:]]) if line.startswith("-"): self.data.append([line[2:], None]) if line.startswith(" "): self.data.append([line[2:], line[2:]]) types = [("LineString", lineBeforeStyle, lineAfterStyle), ("Polygon", polygonBeforeStyle, polygonAfterStyle)] layers = [] extent = self.geoms[0].boundingBox() for i, geom in enumerate(self.geoms): geomtype = types[int(geom.type() - 1)][0] style = types[int(geom.type() - 1)][i + 1] layer = loadLayerNoCrsDialog(geomtype + "?crs=" + self.crs.authid(), "layer", "memory") pr = layer.dataProvider() feat = QgsFeature() feat.setGeometry(geom) pr.addFeatures([feat]) layer.loadNamedStyle(style) layer.updateExtents() layers.append(layer) QgsMapLayerRegistry.instance().addMapLayer(layer, False) extent.combineExtentWith(geom.boundingBox()) layer = loadLayerNoCrsDialog("Point?crs=%s&field=changetype:string" % self.crs.authid(), "points", "memory") pr = layer.dataProvider() feats = [] for coords in self.data: coord = coords[0] or coords[1] feat = QgsFeature() x, y = coord.strip().split(" ") x, y = (float(x), float(y)) pt = QgsGeometry.fromPoint(QgsPoint(x, y)) feat.setGeometry(pt) if coords[0] is None: changetype = "A" elif coords[1] is None: changetype = "R" else: changetype = "U" feat.setAttributes([changetype]) feats.append(feat) pr.addFeatures(feats) layer.loadNamedStyle(pointsStyle) QgsMapLayerRegistry.instance().addMapLayer(layer, False) layers.append(layer) self.mapLayers = [QgsMapCanvasLayer(lay) for lay in layers] self.canvas.setLayerSet(self.mapLayers) self.canvas.setExtent(extent) self.canvas.refresh() def reject(self): QDialog.reject(self)
class WidgetResult(Ui_widgetResult, QWidget): """ Widget (Panel) for result review """ ''' buffer around clicked point for point in polygon query ''' SEARCH_BUFFER = 20.0 ''' supported export formats ''' EXPORT_FORMATS = { get_ui_string("app.extension.shapefile"):ExportTypes.Shapefile, #get_ui_string("app.extension.kml"):ExportTypes.KML, #get_ui_string("app.extension.nrml"):ExportTypes.NRML, get_ui_string("app.extension.csv"):ExportTypes.CSV, }; ''' enumeration of Layer to be previewed ''' EXPOSURE, SURVEY, POP_GRID, FOOTPRINT, ZONES = range(5); ''' name for Layer to be previewed ''' LAYER_NAMES = [ get_ui_string("widget.result.layer.exposure"), get_ui_string("widget.result.layer.survey"), get_ui_string("widget.result.layer.popgrid"), get_ui_string("widget.result.layer.footprint"), get_ui_string("widget.result.layer.zones"), ]; LAYER_STYLES = [ '<!DOCTYPE renderer><renderer-v2 symbollevels="0" type="singleSymbol"><symbols><symbol outputUnit="MM" alpha="1" type="fill" name="0"><layer pass="******" class="SimpleLine" locked="0"><prop k="capstyle" v="square"/><prop k="color" v="0,0,0,255"/><prop k="customdash" v="5;2"/><prop k="joinstyle" v="bevel"/><prop k="offset" v="0"/><prop k="penstyle" v="solid"/><prop k="use_custom_dash" v="0"/><prop k="width" v="0.26"/></layer></symbol></symbols><rotation field=""/><sizescale field=""/></renderer-v2>', '<!DOCTYPE renderer><renderer-v2 symbollevels="0" type="singleSymbol"><symbols><symbol outputUnit="MM" alpha="1" type="marker" name="0"><layer pass="******" class="SimpleMarker" locked="0"><prop k="angle" v="0"/><prop k="color" v="0,0,255,255"/><prop k="color_border" v="0,0,255,255"/><prop k="name" v="circle"/><prop k="offset" v="0,0"/><prop k="size" v="2"/></layer></symbol></symbols><rotation field=""/><sizescale field=""/></renderer-v2>', '<!DOCTYPE renderer><renderer-v2 symbollevels="0" type="singleSymbol"><symbols><symbol outputUnit="MM" alpha="1" type="marker" name="0"><layer pass="******" class="SimpleMarker" locked="0"><prop k="angle" v="0"/><prop k="color" v="0,255,0,255"/><prop k="color_border" v="0,255,0,255"/><prop k="name" v="rectangle"/><prop k="offset" v="0,0"/><prop k="size" v="4"/></layer></symbol></symbols><rotation field=""/><sizescale field=""/></renderer-v2>', '<!DOCTYPE renderer><renderer-v2 symbollevels="0" type="singleSymbol"><symbols><symbol outputUnit="MM" alpha="1" type="fill" name="0"><layer pass="******" class="SimpleFill" locked="0"><prop k="color" v="170,250,170,255"/><prop k="color_border" v="0,0,0,255"/><prop k="offset" v="0,0"/><prop k="style" v="solid"/><prop k="style_border" v="solid"/><prop k="width_border" v="0.26"/></layer></symbol></symbols><rotation field=""/><sizescale field=""/></renderer-v2>', '<!DOCTYPE renderer><renderer-v2 symbollevels="0" type="singleSymbol"><symbols><symbol outputUnit="MM" alpha="1" type="fill" name="0"><layer pass="******" class="SimpleFill" locked="0"><prop k="color" v="211,211,158,200"/><prop k="color_border" v="0,0,0,255"/><prop k="offset" v="0,0"/><prop k="style" v="solid"/><prop k="style_border" v="solid"/><prop k="width_border" v="0.26"/></layer></symbol></symbols><rotation field=""/><sizescale field=""/></renderer-v2>', ] # constructor / destructor ############################### def __init__(self, app): """ constructor - initialize UI elements - connect UI elements to callback """ super(WidgetResult, self).__init__() self.ui = Ui_widgetResult() self.ui.setupUi(self) # create canvas self.canvas = QgsMapCanvas(self.ui.widget_map) self.canvas.setGeometry( 0, # x self.ui.widget_map_menu_l.x()+self.ui.widget_map_menu_l.height(), # y self.ui.widget_map.width() - 2*UI_PADDING, # width self.ui.widget_map.width() - 2*UI_PADDING # height ) self.canvas.setCanvasColor(Qt.white) self.canvas.enableAntiAliasing(True) self.canvas.mapRenderer().setProjectionsEnabled(True) self.canvas.mapRenderer().setDestinationCrs(QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.PostgisCrsId)) self.canvas.zoomNextStatusChanged.connect(self.checkRendering) self.canvas.xyCoordinates.connect(self.currentLocation) self.registry = QgsMapLayerRegistry.instance() self.map_layers = [None] * len(self.LAYER_NAMES) self.map_layer_renderer = [None] * len(self.LAYER_NAMES) for idx, str_style in enumerate(self.LAYER_STYLES): rdoc = QDomDocument("renderer") rdoc.setContent(str_style) self.map_layer_renderer[idx] = QgsFeatureRendererV2.load(rdoc.firstChild().toElement()) # populate export list self.ui.cb_export_format.clear() for export_format in self.EXPORT_FORMATS.keys(): self.ui.cb_export_format.addItem(export_format) # style object required for QgsRendererV2PropertiesDialog self.style = QgsStyleV2() # create the map tools self.toolPan = QgsMapToolPan(self.canvas) self.toolZoomIn = QgsMapToolZoom(self.canvas, False) # false = in self.toolZoomOut = QgsMapToolZoom(self.canvas, True) # true = out self.toolInfo = QgsMapToolEmitPoint(self.canvas) self.toolInfo.canvasClicked.connect(self.showInfo) self.canvas.setMapTool(self.toolPan) # additional self.dlgResultDetail = DialogResult() self.dlgResultDetail.setModal(True) # set link to application main controller self.app = app # reset project self._project = None # default export setting self.export_format = ExportTypes.Shapefile # connect slots (ui event) self.ui.btn_zoom_full.clicked.connect(self.mapZoomFull) self.ui.btn_zoom_in.clicked.connect(self.mapZoomIn) self.ui.btn_zoom_out.clicked.connect(self.mapZoomOut) self.ui.btn_stop.clicked.connect(self.stopRendering) self.ui.btn_zoom_layer.clicked.connect(self.mapZoomLayer) self.ui.btn_pan.clicked.connect(self.mapPan) self.ui.btn_theme.clicked.connect(self.mapEditTheme) self.ui.btn_info.clicked.connect(self.mapIdentify) self.ui.btn_zoom_to_feature.clicked.connect(self.searchFeature) self.ui.cb_export_format.currentIndexChanged[str].connect(self.exportFormatChanged) self.ui.btn_export.clicked.connect(self.exportData) self.ui.btn_export_select_path.clicked.connect(self.selectExportFile) @pyqtSlot(QgsPoint) def currentLocation(self, point): self.app.updateMapLocation(point.x(),point.y()) #self.canvas.mouseMoveEvent(mouseEvent) # UI event handling calls (Qt slots) ############################### @pyqtSlot(QObject) def resizeEvent(self, event): """ handle window resize """ # find left coordinate for right side panels x_right_side = self.width()-self.ui.widget_export.width()-UI_PADDING # adjust right side panels self.ui.widget_export.move(x_right_side, self.ui.widget_map.y()+30) self.ui.widget_dq_test.move(x_right_side, self.ui.widget_export.y()+self.ui.widget_export.height()+UI_PADDING) # adjust map panel (left side) self.ui.widget_map.resize(x_right_side-UI_PADDING, self.height()-2*UI_PADDING) # adjust map canvas within the map panel map_top = self.ui.widget_map_menu_l.x()+self.ui.widget_map_menu_l.height()+UI_PADDING self.canvas.resize( x_right_side-UI_PADDING, # same width as self.ui.widget_map self.ui.widget_map.height()-map_top-2*UI_PADDING) # height # adjust map menu self.ui.widget_map_menu_r.move( self.ui.widget_map.width()-self.ui.widget_map_menu_r.width(), # right align with map panel 0) # logo self.ui.lb_gem_logo.move(self.width()-self.ui.lb_gem_logo.width(), self.ui.lb_gem_logo.y()) @logUICall @pyqtSlot() def mapPan(self): """ event handler for btn_pan - pan map """ self.canvas.unsetMapTool(self.toolInfo) self.canvas.setMapTool(self.toolPan) @logUICall @pyqtSlot() def mapZoomIn(self): """ event handler for btn_zoom_in - zoom in on map """ self.canvas.unsetMapTool(self.toolInfo) self.canvas.setMapTool(self.toolZoomIn) @logUICall @pyqtSlot() def mapZoomOut(self): """ event handler for btn_zoom_out - zoom out on map """ self.canvas.unsetMapTool(self.toolInfo) self.canvas.setMapTool(self.toolZoomOut) @logUICall @pyqtSlot() def mapZoomFull(self): """ event handler for btn_zoom_full - zoom to full map """ self.canvas.zoomToFullExtent() def checkRendering(self, changed): self.canvas.setRenderFlag(True) @logUICall @pyqtSlot() def stopRendering(self): self.canvas.setRenderFlag(False) @logUICall @pyqtSlot() def mapZoomLayer(self): self.canvas.unsetMapTool(self.toolInfo) cur_layer_name = self.ui.cb_layer_selector.currentText() if cur_layer_name.isEmpty(): return self.zoomToLayer(self.map_layers[self.LAYER_NAMES.index(cur_layer_name)]) @logUICall @pyqtSlot() def mapEditTheme(self): """ event handler for btn_edit - identify item on map """ cur_layer_name = self.ui.cb_layer_selector.currentText() if cur_layer_name.isEmpty(): return try: cur_layer_idx = self.LAYER_NAMES.index(cur_layer_name) # build layer render property Dialog for selected layer dlg_render = QDialog() dlg_render.setWindowTitle(get_ui_string('widget.result.renderer.settings')) dlg_render.setModal(True) dlg_render.setFixedSize(530, 370) dlg_render.renderer = QgsRendererV2PropertiesDialog(self.map_layers[cur_layer_idx], self.style, True) dlg_render.renderer.setParent(dlg_render) dlg_render.renderer.setGeometry(QRect(10, 10, 510, 325)) dlg_render.buttonBox = QDialogButtonBox(dlg_render) dlg_render.buttonBox.setGeometry(QRect(10, 335, 510, 25)) dlg_render.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok) dlg_render.buttonBox.accepted.connect(dlg_render.accept) dlg_render.buttonBox.accepted.connect(dlg_render.renderer.onOK) dlg_render.buttonBox.rejected.connect(dlg_render.reject) dlg_render.setVisible(True) # get user input and update renderer answer = dlg_render.exec_() if answer == QDialog.Accepted: self.map_layer_renderer[cur_layer_idx] = None self.map_layer_renderer[cur_layer_idx] = self.map_layers[cur_layer_idx].rendererV2().clone() self.canvas.refresh() dlg_render.destroy() del dlg_render except Exception as err: # thematic is not-critical, allow continue on exception logUICall.log(str(err), logUICall.WARNING) @logUICall @pyqtSlot() def searchFeature(self): cur_layer_name = self.ui.cb_layer_selector.currentText() if cur_layer_name.isEmpty(): return try: cur_layer_idx = self.LAYER_NAMES.index(cur_layer_name) layer = self.map_layers[cur_layer_idx] fields = [] for fidx in layer.dataProvider().fields(): fields.append(layer.dataProvider().fields()[fidx].name()) dlg_search = DialogSearchFeature(fields) answer = dlg_search.exec_() if answer == QDialog.Accepted: extent = self.findFeatureExtentByAttribute(layer, dlg_search.attribute, dlg_search.value) if extent is not None: self.zoomToExtent(extent) else: logUICall.log(get_ui_string("widget.result.info.notfound"), logUICall.WARNING) dlg_search.destroy() except Exception as err: # thematic is not-critical, allow continue on exception logUICall.log(str(err), logUICall.WARNING) @logUICall @pyqtSlot() def mapIdentify(self): """ event handler for btn_info This only enables map querying, method connected to canvasClicked signal does the actual point-polygon query """ self.canvas.setMapTool(self.toolInfo) @logUICall @pyqtSlot() def selectExportFile(self): """ event handler for btn_export_select_path - open save file dialog box to select file name for export """ filename = QFileDialog.getSaveFileName(self, get_ui_string("widget.result.export.file.open"), ".", self.ui.cb_export_format.currentText()) if not filename.isNull(): self.ui.txt_export_select_path.setText(filename) @logUICall @pyqtSlot(str) def exportFormatChanged(self, selected_val): """ event handler for cb_export_format - update selected file after format change """ self.ui.txt_export_select_path.setText("") self.export_format = self.EXPORT_FORMATS[str(selected_val)] @logUICall @pyqtSlot() def exportData(self): """ event handler for btn_export - do export data """ export_path = str(self.ui.txt_export_select_path.text()) if export_path == "": logUICall.log(get_ui_string("app.error.path.is.null"), logUICall.WARNING) return self.app.exportResults(self.export_format, export_path) @logUICall @pyqtSlot(QPoint, QObject) def showInfo(self, point, mouseButton): """ event handler for toolInfo @see QGIS tutorial for detail point-polygon search on currently selected layer """ cur_layer_name = self.ui.cb_layer_selector.currentText() if cur_layer_name.isEmpty(): return try: cur_layer_idx = self.LAYER_NAMES.index(cur_layer_name) cur_layer = self.map_layers[cur_layer_idx] # if layer is not in same projection as map canvas # need to project query point if cur_layer.crs() != self.canvas.mapRenderer().destinationCrs(): transform = QgsCoordinateTransform(self.canvas.mapRenderer().destinationCrs(), cur_layer.crs()) point = transform.transform(point) # do query provider = cur_layer.dataProvider() provider.rewind() feature = QgsFeature() colonIndexes = provider.attributeIndexes() # search using point as center of rectangle polygon search_buffer_x = self.canvas.extent().width() * self.SEARCH_BUFFER / self.canvas.width() search_buffer_y = self.canvas.extent().height() * self.SEARCH_BUFFER / self.canvas.height() provider.select(colonIndexes, QgsRectangle(point.x()-search_buffer_x, point.y()-search_buffer_y, point.x()+search_buffer_x, point.y()+search_buffer_y), True) # get selected and display in result detail dialog box selected = [] while provider.nextFeature(feature): # for polygons, only show geometry containing query point if cur_layer.geometryType() == QGis.Polygon: if feature.geometry() is not None and not feature.geometry().contains (point): continue selected.append(feature.attributeMap()) if len(selected)>0: # display result if exists if cur_layer_idx == self.EXPOSURE: self.dlgResultDetail.showExposureData(provider.fields(), selected) else: self.dlgResultDetail.showInfoData(provider.fields(), selected) self.dlgResultDetail.exec_() else: logUICall.log(get_ui_string("widget.result.info.notfound"), logUICall.WARNING) except Exception as err: # point-in-polygon search is not critical, continue on error logUICall.log(str(err), logUICall.WARNING) # public methods ############################### def set_project(self, project): ''' set project to preview. force refresh view on set''' self._project = project if project is None: return self.refreshView() self.canvas.zoomToFullExtent() logUICall.log("Project preview initialized sucessfully", logUICall.INFO) def get_project(self): return self._project # property access to project project = property(get_project, set_project) def refreshView(self): ''' reload all QGIS layers in currently defined project ''' if self._project is None: return # display layers if exists if self._project.fp_file is not None and exists(self._project.fp_file): if self.map_layers[self.FOOTPRINT] is None or self.map_layers[self.FOOTPRINT].source() != self._project.fp_file: self.showDataLayer(self.FOOTPRINT, load_shapefile(self._project.fp_file, 'footprint')) else: self.removeDataLayer(self.FOOTPRINT) if self._project.zone_file is not None and exists(self._project.zone_file): if self.map_layers[self.ZONES] is None or self.map_layers[self.ZONES].source() != self._project.zone_file: self.showDataLayer(self.ZONES, load_shapefile(self._project.zone_file, 'zones')) else: self.removeDataLayer(self.ZONES) if self._project.survey_file is not None and exists(self._project.survey_file): if getattr(self._project, 'survey', None) is None: self._project.load_survey() self.showDataLayer(self.SURVEY, self._project.survey) else: self.removeDataLayer(self.SURVEY) if self._project.popgrid_file is not None and exists(self._project.popgrid_file): if getattr(self._project, 'popgrid', None) is None: self.showDataLayer(self.POP_GRID, load_shapefile(self._project.popgrid_file, 'popgrid')) else: self.removeDataLayer(self.POP_GRID) # set export options for idx, export_format in enumerate(self.EXPORT_FORMATS.values()): if export_format == self._project.export_type: self.ui.cb_export_format.setCurrentIndex(idx) self.ui.txt_export_select_path.setText(self._project.export_path) # refreshResult contains refresh call to update all layers currently loaded self.refreshResult() def refreshResult(self): ''' reload result QGIS layer and data quality reports in currently defined project ''' exposure = getattr(self._project, 'exposure', None) if exposure is not None: self.showDataLayer(self.EXPOSURE, exposure) has_result = True else: self.removeDataLayer(self.EXPOSURE) has_result = False if has_result: # build quality report report_lines = [] if self._project.operator_options.has_key("proc.extrapolation"): proc_option = self._project.operator_options["proc.extrapolation"] if proc_option == ExtrapolateOptions.RandomWalk: proc_method = get_ui_string("widget.result.dq.method", get_ui_string("dlg.options.ep.random")) elif proc_option == ExtrapolateOptions.Fraction: proc_method = get_ui_string("widget.result.dq.method", get_ui_string("dlg.options.ep.fraction")) elif proc_option == ExtrapolateOptions.FractionRounded: proc_method = get_ui_string("widget.result.dq.method", get_ui_string("dlg.options.ep.fraction.rounded")) else: proc_method = get_ui_string("widget.result.dq.method", get_ui_string("dlg.options.ep.random")) report_lines.append(proc_method) report_lines.append('') # total tests report_lines.append(get_ui_string('widget.result.dq.total_tests', len(self._project.quality_reports.keys()))) report_lines.append('') # detail for each test for key, report in self._project.quality_reports.iteritems(): report_lines.append(get_ui_string('widget.result.dq.tests.%s' % key)) for title, value in report.iteritems(): report_lines.append( get_ui_string('widget.result.dq.tests.%s.%s' % (key, title), value) ) report_lines.append('') self.ui.txt_dq_test_details.setText("\n".join(report_lines)) self.ui.btn_export.setEnabled(has_result) self.ui.widget_dq_test.setVisible(has_result) self.ui.txt_export_select_path.setEnabled(has_result) self.ui.btn_export_select_path.setEnabled(has_result) self.ui.cb_export_format.setEnabled(has_result) # this call refresh all layers currently loaded self.refreshLayers() @logUICall def closeResult(self): ''' remove from map result QGIS layer and reset quality report display ''' self.canvas.setLayerSet([]) # call necessary to remove all layers to avoid disconnect errors self.removeDataLayer(self.EXPOSURE) self.refreshLayers() self.ui.txt_dq_test_details.setText("") @logUICall def closeAll(self): ''' remove from map all QGIS layer in currently defined project ''' self.ui.cb_layer_selector.clear() try: self.canvas.setLayerSet([]) # call necessary to remove all layers to avoid disconnect errors for i in range(5): self.removeDataLayer(i) self.ui.txt_dq_test_details.setText("") self.refreshLayers() except: pass # exception will is thrown when registry is empty # internal helper methods ############################### def showDataLayer(self, index, layer): """ display given QGIS layer on map """ try: # add to QGIS registry and refresh view if self.map_layers[index] is not None: self.removeDataLayer(index) self.map_layers[index] = layer self.registry.addMapLayer(layer) layer.setRendererV2(self.map_layer_renderer[index]) except: pass def removeDataLayer(self, index): """ remove from map the layer identified with index """ layer = self.map_layers[index] self.map_layers[index] = None if layer is not None: try: self.registry.removeMapLayer(layer.getLayerID(), False) del layer except: pass # do nothing if it fails. probably already deleted def findFeatureExtentByAttribute(self, layer, field, value): """ find extent of all objects in QGIS layer matching condition "field=value" """ fidx = layer_field_index(layer, field) if fidx == -1: return None xmin, xmax, ymin, ymax = 180, -180, 90, -90 extent = QgsRectangle(xmin, ymin, xmax, ymax) need_transform = layer.crs() != self.canvas.mapRenderer().destinationCrs() if need_transform: transform = QgsCoordinateTransform(layer.crs(), self.canvas.mapRenderer().destinationCrs()) for feature in layer_features(layer): if str(value) == feature.attributeMap()[fidx].toString(): f_extent = feature.geometry().boundingBox() if need_transform: f_extent = transform.transform(f_extent) xmin = min(f_extent.xMinimum(), xmin) xmax = max(f_extent.xMaximum(), xmax) ymin = min(f_extent.yMinimum(), ymin) ymax = max(f_extent.yMaximum(), ymax) extent.set (xmin, ymin, xmax, ymax) return extent def zoomToLayer(self, layer): """ zoom canvas to extent of given layer """ try: lyr_extent = layer.extent() if layer.crs() != self.canvas.mapRenderer().destinationCrs(): transform = QgsCoordinateTransform(layer.crs(), self.canvas.mapRenderer().destinationCrs()) lyr_extent = transform.transform(lyr_extent) self.zoomToExtent(lyr_extent) except: pass def zoomToExtent(self, extent): """ zoom canvas to given extent """ try: self.canvas.setExtent(extent) self.canvas.zoomByFactor(1.1) except: self.mapZoomFull() def refreshLayers(self): """ refresh all layers in canvas """ # add each layer according to order layerSet = [] self.ui.cb_layer_selector.clear() for idx, lyr in enumerate(self.map_layers): if lyr is not None: layerSet.append(QgsMapCanvasLayer(lyr)) self.ui.cb_layer_selector.addItem(self.LAYER_NAMES[idx]) if len(layerSet) > 0:
class ConflictDialog(WIDGET, BASE): LOCAL, REMOTE, DELETE = 1,2, 3 def __init__(self, conflicts): super(ConflictDialog, self).__init__(None, Qt.WindowSystemMenuHint | Qt.WindowTitleHint) self.solved = False self.resolvedConflicts = {} self.conflicts = conflicts self.setupUi(self) self.setWindowFlags(self.windowFlags() | Qt.WindowSystemMenuHint | Qt.WindowMinMaxButtonsHint) self.zoomButton.clicked.connect(self.zoomToFullExtent) self.solveButton.clicked.connect(self.solve) self.conflictsTree.itemClicked.connect(self.treeItemClicked) self.attributesTable.cellClicked.connect(self.cellClicked) self.solveAllLocalButton.clicked.connect(self.solveAllLocal) self.solveAllRemoteButton.clicked.connect(self.solveAllRemote) self.solveLocalButton.clicked.connect(self.solveLocal) self.solveRemoteButton.clicked.connect(self.solveRemote) self.showRemoteCheck.stateChanged.connect(self.showGeoms) self.showLocalCheck.stateChanged.connect(self.showGeoms) self.lastSelectedItem = None self.currentPath = None self.currentConflict = None self.theirsLayer = None self.oursLayer = None settings = QSettings() horizontalLayout = QHBoxLayout() horizontalLayout.setSpacing(0) horizontalLayout.setMargin(0) self.mapCanvas = QgsMapCanvas() self.mapCanvas.setCanvasColor(Qt.white) self.mapCanvas.enableAntiAliasing(settings.value("/qgis/enable_anti_aliasing", False, type = bool)) self.mapCanvas.useImageToRender(settings.value("/qgis/use_qimage_to_render", False, type = bool)) self.mapCanvas.mapRenderer().setProjectionsEnabled(True) action = settings.value("/qgis/wheel_action", 0, type = float) zoomFactor = settings.value("/qgis/zoom_factor", 2, type = float) self.mapCanvas.setWheelAction(QgsMapCanvas.WheelAction(action), zoomFactor) horizontalLayout.addWidget(self.mapCanvas) self.canvasWidget.setLayout(horizontalLayout) self.panTool = QgsMapToolPan(self.mapCanvas) self.mapCanvas.setMapTool(self.panTool) self.solveButton.setEnabled(False) self.solveLocalButton.setEnabled(False) self.solveRemoteButton.setEnabled(False) self.fillConflictsTree() def fillConflictsTree(self): topTreeItems = {} for c in self.conflicts: path = os.path.dirname(c.path) if path in topTreeItems: topItem = topTreeItems[path] else: topItem = QTreeWidgetItem() topItem.setText(0, path) topItem.setIcon(0, layerIcon) topTreeItems[path] = topItem conflictItem = ConflictItem(c) topItem.addChild(conflictItem) for item in list(topTreeItems.values()): self.conflictsTree.addTopLevelItem(item) def cellClicked(self, row, col): if col > 2: return value = self.attributesTable.item(row, col).value geoms = (self.oursgeom, self.theirsgeom) self.attributesTable.setItem(row, 4, ValueItem(value, False, geoms)); self.attributesTable.item(row, 0).setBackgroundColor(Qt.white); self.attributesTable.item(row, 1).setBackgroundColor(Qt.white); self.attributesTable.item(row, 2).setBackgroundColor(Qt.white); attrib = self.attributesTable.item(row, 3).text() if attrib in self.conflicted: self.conflicted.remove(attrib) self.updateSolveButton() self.showGeoms() def treeItemClicked(self): item = self.conflictsTree.selectedItems()[0] if self.lastSelectedItem == item: return if isinstance(item, ConflictItem): self.lastSelectedItem = item self.currentPath = item.conflict.path self.updateCurrentPath() self.solveLocalButton.setEnabled(True) self.solveRemoteButton.setEnabled(True) self.solveButton.setEnabled(False) def updateCurrentPath(self): self.solveButton.setEnabled(False) self.solveLocalButton.setEnabled(False) self.solveRemoteButton.setEnabled(False) self.cleanCanvas() self.showFeatureAttributes() self.createLayers() self.showGeoms() self.zoomToFullExtent() def zoomToFullExtent(self): layers = [lay.extent() for lay in self.mapCanvas.layers() if lay.type() == lay.VectorLayer] if layers: ext = layers[0] for layer in layers[1:]: ext.combineExtentWith(layer) self.mapCanvas.setExtent(ext) self.mapCanvas.refresh() def cleanCanvas(self): self.mapCanvas.setLayerSet([]) layers = [self.oursLayer, self.theirsLayer] for layer in layers: if layer is not None: QgsMapLayerRegistry.instance().removeMapLayer(layer.id()) self.oursLayer = None self.theirsLayer = None def solveAllRemote(self): ret = QMessageBox.warning(self, "Solve conflict", "Are you sure you want to solve all conflicts using the 'To merge' version?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes); if ret == QMessageBox.Yes: self.solved = True self.resolvedConflicts = {c.path:self.REMOTE for c in self.conflicts} self.close() def solveAllLocal(self): ret = QMessageBox.warning(self, "Solve conflict", "Are you sure you want to solve all conflict using the 'Local' version?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes); if ret == QMessageBox.Yes: self.solved = True self.resolvedConflicts = {c.path:self.LOCAL for c in self.conflicts} self.close() def _afterSolve(self, remove = True): if remove: parent = self.lastSelectedItem.parent() parent.removeChild(self.lastSelectedItem) self.lastSelectedItem = None if parent.childCount() == 0: self.conflictsTree.invisibleRootItem().removeChild(parent) if self.conflictsTree.topLevelItemCount() == 0: self.solved = True self.close() self.attributesTable.setRowCount(0) self.cleanCanvas() self.solveButton.setEnabled(False) self.solveLocalButton.setEnabled(False) self.solveRemoteButton.setEnabled(False) def solveLocal(self): self.resolvedConflicts[self.currentPath] = self.LOCAL self._afterSolve() def solveRemote(self): self.resolvedConflicts[self.currentPath] = self.REMOTE self._afterSolve() def solve(self): attribs = {} for i in range(self.attributesTable.rowCount()): value = self.attributesTable.item(i, 4).value name = str(self.attributesTable.item(i, 3).text()) attribs[name] = value self.resolvedConflicts[self.currentPath] = attribs self._afterSolve() def updateSolveButton(self): self.solveButton.setEnabled(len(self.conflicted) == 0) def showFeatureAttributes(self): conflictItem = self.lastSelectedItem self.oursgeom = None self.theirsgeom = None geoms = (self.oursgeom, self.theirsgeom) self.currentConflictedAttributes = [] attribs = list(conflictItem.origin.keys()) self.attributesTable.setRowCount(len(attribs)) self.conflicted = [] for idx, name in enumerate(attribs): font = QFont() font.setBold(True) font.setWeight(75) item = QTableWidgetItem(name) item.setFont(font) self.attributesTable.setItem(idx, 3, item); self.attributesTable.setItem(idx, 4, ValueItem(None, False)); try: values = (conflictItem.origin[name], conflictItem.local[name], conflictItem.remote[name]) except Exception: #Local has been deleted self._afterSolve(False) self.solveModifyAndDelete(conflictItem.conflict.path, self.REMOTE) return except TypeError: #Remote has been deleted self._afterSolve(False) self.solveModifyAndDelete(conflictItem.conflict.path,self.LOCAL) return try: geom = QgsGeometry.fromWkt(values[0]) except: geom = None if geom is not None: self.theirsgeom = QgsGeometry().fromWkt(values[1]) self.oursgeom = QgsGeometry.fromWkt(values[2]) geoms = (self.oursgeom, self.theirsgeom) ok = values[0] == values[1] or values[1] == values[2] or values[0] == values[2] for i, v in enumerate(values): self.attributesTable.setItem(idx, i, ValueItem(v, not ok, geoms)); if not ok: self.conflicted.append(name) else: if values[0] == values[1]: newvalue = values[2] else: newvalue = values[1] self.attributesTable.setItem(idx, 4, ValueItem(newvalue, False, geoms)); self.attributesTable.resizeRowsToContents() self.attributesTable.horizontalHeader().setMinimumSectionSize(150) self.attributesTable.horizontalHeader().setStretchLastSection(True) def solveModifyAndDelete(self, path, modified): msgBox = QMessageBox() msgBox.setText("The feature has been modified in one version and deleted in the other one.\n" "How do you want to solve the conflict?") msgBox.addButton(QPushButton('Modify'), QMessageBox.YesRole) msgBox.addButton(QPushButton('Delete'), QMessageBox.NoRole) msgBox.addButton(QPushButton('Cancel'), QMessageBox.RejectRole) ret = msgBox.exec_() if ret == 0: self.resolvedConflicts[path] = modified self._afterSolve() elif ret == 1: self.resolvedConflicts[path] = self.DELETE self._afterSolve() else: pass def createLayers(self): types = [("Point", ptOursStyle, ptTheirsStyle), ("LineString", lineOursStyle, lineTheirsStyle), ("Polygon", polygonOursStyle, polygonTheirsStyle)] if self.oursgeom is not None: geomtype = types[int(self.oursgeom.type())][0] style = types[int(self.oursgeom.type())][1] self.oursLayer = loadLayerNoCrsDialog(geomtype + "?crs=EPSG:4326", "ours", "memory") pr = self.oursLayer.dataProvider() feat = QgsFeature() feat.setGeometry(self.oursgeom) pr.addFeatures([feat]) self.oursLayer.loadNamedStyle(style) self.oursLayer.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(self.oursLayer, False) else: self.oursLayer = None if self.theirsgeom is not None: geomtype = types[int(self.theirsgeom.type())][0] style = types[int(self.theirsgeom.type())][2] self.theirsLayer = loadLayerNoCrsDialog(geomtype + "?crs=EPSG:4326", "theirs", "memory") pr = self.theirsLayer.dataProvider() feat = QgsFeature() feat.setGeometry(self.theirsgeom) pr.addFeatures([feat]) self.theirsLayer.loadNamedStyle(style) self.theirsLayer.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(self.theirsLayer, False) else: self.theirsLayer = None def showGeoms(self): checks = [self.showRemoteCheck, self.showLocalCheck] layers = [self.oursLayer, self.theirsLayer] toShow = [] for lay, chk in zip(layers, checks): if lay is not None and chk.isChecked(): toShow.append(lay) self.mapCanvas.setRenderFlag(False) self.mapCanvas.setLayerSet([QgsMapCanvasLayer(layer) for layer in toShow]) self.mapCanvas.setRenderFlag(True) def closeEvent(self, evnt): if not self.solved: ret = QMessageBox.warning(self, "Conflict resolution", "There are unsolved conflicts.\n" "Do you really want to exit and abort the sync operation?", QMessageBox.Yes | QMessageBox.No) if ret == QMessageBox.No: evnt.ignore() return self.cleanCanvas()
class PolygonMapWindow(QMainWindow): """Open a map window where the user can draw a polygon and use it to crop data. Shares a lot of similarities with MapWindow calss, but there're enough differences that I decided not to inherit from it.""" # signal emitted when polygons succesfully selected finished = pyqtSignal() def __init__(self): QMainWindow.__init__(self) # creating map canvas, which draws the maplayers # setting up features like canvas color self.canvas = QgsMapCanvas() self.canvas.setMinimumSize(550, 700) self.canvas.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.canvas.setCanvasColor(Qt.white) self.canvas.enableAntiAliasing(True) # Qmainwindow requires a central widget. Canvas is placed self.setCentralWidget(self.canvas) # creating each desired action self.actionGet = QAction("Return polygon and close", self) self.actionPan = QAction("Pan tool", self) self.actionDraw = QAction("Polygon tool", self) self.actionConnect = QAction("Connect polygon", self) self.actionClear = QAction("Clear", self) self.actionCancel = QAction("Cancel and close", self) # these two function as on/off. the rest are clickable self.actionPan.setCheckable(True) self.actionDraw.setCheckable(True) # when actions are clicked, do corresponding function self.actionPan.triggered.connect(self.pan) self.actionDraw.triggered.connect(self.draw) self.actionClear.triggered.connect(self.clear) self.actionGet.triggered.connect(self.finishedSelection) self.actionConnect.triggered.connect(self.connect) self.actionCancel.triggered.connect(self.cancel) # toolbar at the top of the screen: houses actions as buttons # change order here to change their placement on toolbar self.toolbar = self.addToolBar("Canvas actions") self.toolbar.setContextMenuPolicy(Qt.PreventContextMenu) self.toolbar.setMovable(False) self.toolbar.addAction(self.actionGet) self.toolbar.addAction(self.actionPan) self.toolbar.addAction(self.actionDraw) self.toolbar.addAction(self.actionConnect) self.toolbar.addAction(self.actionClear) self.toolbar.addAction(self.actionCancel) # link actions to premade map tools self.toolPan = QgsMapToolPan(self.canvas) self.toolPan.setAction(self.actionPan) self.toolDraw = PolygonMapTool(self.canvas) self.toolDraw.setAction(self.actionDraw) # set draw tool by default self.draw() def pan(self): """Simply activates the tool""" self.canvas.setMapTool(self.toolPan) # make sure the other button isn't checked to avoid confusion self.actionDraw.setChecked(False) def draw(self): """Activates draw tool""" self.canvas.setMapTool(self.toolDraw) self.actionPan.setChecked(False) def clear(self): self.toolDraw.reset() def connect(self): """Calls the polygon tool to connect an unconnected polygon""" self.toolDraw.finishPolygon() def finishedSelection(self): """Activated when user clicks 'returns selection'. Closes window and emits signal to indicate the job is finished""" self.close() self.finished.emit() def cancel(self): """In case user changes their mind. Does the same as above, but doesn't emit signal.""" self.close() def showCanvas(self): """Shows the map canvas with a vector background map for reference""" """ url = ("http://86.50.168.160/geoserver/ows?service=wfs&version=2.0.0"+ "&request=GetFeature&typename=ogiir:maakuntajako_2018_4500k&pagingEnabled=true") #self.bg_layer = QgsVectorLayer(url, "BACKGROUND-REMOVE", "WFS") """ self.bg_layer = QgsRasterLayer( "url=http://86.50.168.160/ogiir_cache/wmts/1.0.0/" + "WMTSCapabilities.xml&crs=EPSG:3067&dpiMode=7&format=image/" + "png&layers=taustakartta&styles=default&tileMatrixSet=GRIDI-FIN", 'GEOCUBES POLYGON BG-LAYER - TEMPORARY', 'wms') if self.bg_layer.isValid(): QgsProject.instance().addMapLayer(self.bg_layer, False) self.canvas.setExtent(self.bg_layer.extent()) self.canvas.setLayers([self.bg_layer]) self.show() def closeEvent(self, event): """Activated anytime Mapwindow is closed either programmatically or if the user finds some other way to close the window. Automatically finishes the polygon if it's unconnected.""" try: QgsProject.instance().removeMapLayer(self.bg_layer) except Exception: pass self.toolDraw.finishPolygon() QMainWindow.closeEvent(self, event) def getPolygon(self): return self.toolDraw.getPoints() def getPolygonBbox(self): return self.toolDraw.getPolyBbox()
class ViewerWnd(QMainWindow): def __init__(self, app, dictOpts): QMainWindow.__init__(self) self.setWindowTitle("PostGIS Layer Viewer - v.1.6.1") self.setTabPosition(Qt.BottomDockWidgetArea, QTabWidget.North) self.canvas = QgsMapCanvas() self.canvas.setCanvasColor(Qt.white) self.canvas.useImageToRender(True) self.canvas.enableAntiAliasing(True) self.setCentralWidget(self.canvas) actionZoomIn = QAction(QIcon(imgs_dir + "mActionZoomIn.png"), QString("Zoom in"), self) actionZoomOut = QAction(QIcon(imgs_dir + "mActionZoomOut.png"), QString("Zoom out"), self) actionPan = QAction(QIcon(imgs_dir + "mActionPan.png"), QString("Pan"), self) actionZoomFullExtent = QAction( QIcon(imgs_dir + "mActionZoomFullExtent.png"), QString("Zoom full"), self) actionZoomIn.setCheckable(True) actionZoomOut.setCheckable(True) actionPan.setCheckable(True) self.connect(actionZoomIn, SIGNAL("triggered()"), self.zoomIn) self.connect(actionZoomOut, SIGNAL("triggered()"), self.zoomOut) self.connect(actionPan, SIGNAL("triggered()"), self.pan) self.connect(actionZoomFullExtent, SIGNAL("triggered()"), self.zoomFullExtent) self.actionGroup = QActionGroup(self) self.actionGroup.addAction(actionPan) self.actionGroup.addAction(actionZoomIn) self.actionGroup.addAction(actionZoomOut) # Create the toolbar self.toolbar = self.addToolBar("Map tools") self.toolbar.addAction(actionPan) self.toolbar.addAction(actionZoomIn) self.toolbar.addAction(actionZoomOut) self.toolbar.addAction(actionZoomFullExtent) # Create the map tools self.toolPan = QgsMapToolPan(self.canvas) self.toolPan.setAction(actionPan) self.toolZoomIn = QgsMapToolZoom(self.canvas, False) # false = in self.toolZoomIn.setAction(actionZoomIn) self.toolZoomOut = QgsMapToolZoom(self.canvas, True) # true = out self.toolZoomOut.setAction(actionZoomOut) # Create the statusbar self.statusbar = QStatusBar(self) self.statusbar.setObjectName("statusbar") self.setStatusBar(self.statusbar) self.lblXY = QLabel() self.lblXY.setFrameStyle(QFrame.Box) self.lblXY.setMinimumWidth(170) self.lblXY.setAlignment(Qt.AlignCenter) self.statusbar.setSizeGripEnabled(False) self.statusbar.addPermanentWidget(self.lblXY, 0) self.lblScale = QLabel() self.lblScale.setFrameStyle(QFrame.StyledPanel) self.lblScale.setMinimumWidth(140) self.statusbar.addPermanentWidget(self.lblScale, 0) self.createLegendWidget() # Create the legend widget self.connect(app, SIGNAL("loadPgLayer"), self.loadLayer) self.connect(self.canvas, SIGNAL("scaleChanged(double)"), self.changeScale) self.connect(self.canvas, SIGNAL("xyCoordinates(const QgsPoint&)"), self.updateXY) self.pan() # Default self.plugins = Plugins(self, self.canvas, dictOpts['-h'], dictOpts['-p'], dictOpts['-d'], dictOpts['-U'], dictOpts['-W']) self.createAboutWidget() self.layerSRID = '-1' self.loadLayer(dictOpts) def zoomIn(self): self.canvas.setMapTool(self.toolZoomIn) def zoomOut(self): self.canvas.setMapTool(self.toolZoomOut) def pan(self): self.canvas.setMapTool(self.toolPan) def zoomFullExtent(self): self.canvas.zoomToFullExtent() def about(self): pass def createLegendWidget(self): """ Create the map legend widget and associate it to the canvas """ self.legend = Legend(self) self.legend.setCanvas(self.canvas) self.legend.setObjectName("theMapLegend") self.LegendDock = QDockWidget("Layers", self) self.LegendDock.setObjectName("legend") self.LegendDock.setTitleBarWidget(QWidget()) self.LegendDock.setWidget(self.legend) self.LegendDock.setContentsMargins(0, 0, 0, 0) self.addDockWidget(Qt.BottomDockWidgetArea, self.LegendDock) def createAboutWidget(self): self.AboutDock = QDockWidget("About", self) self.AboutDock.setObjectName("about") self.AboutDock.setTitleBarWidget(QWidget()) self.AboutDock.setContentsMargins(0, 0, 0, 0) self.tabifyDockWidget(self.LegendDock, self.AboutDock) self.LegendDock.raise_() # legendDock at the top from PyQt4.QtCore import QRect from PyQt4.QtGui import QSizePolicy, QGridLayout, QFont font = QFont() font.setFamily("Sans Serif") font.setPointSize(8.7) self.AboutWidget = QWidget() self.AboutWidget.setFont(font) self.AboutWidget.setObjectName("AboutWidget") self.AboutDock.setWidget(self.AboutWidget) self.labelAbout = QLabel(self.AboutWidget) self.labelAbout.setAlignment(Qt.AlignCenter) self.labelAbout.setWordWrap(True) self.gridLayout = QGridLayout(self.AboutWidget) self.gridLayout.setContentsMargins(0, 0, 0, 0) self.gridLayout.setObjectName("gridLayout") self.gridLayout.addWidget(self.labelAbout, 0, 1, 1, 1) self.labelAbout.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard | Qt.TextSelectableByKeyboard | Qt.TextSelectableByMouse) self.labelAbout.setOpenExternalLinks(True) self.labelAbout.setText("<html><head/><body><a href=\"http://geotux.tuxfamily.org/index.php/en/geo-blogs/item/293-consola-sql-para-plugin-pgadmin-postgis-viewer\">PostGIS Layer Viewer</a> v.1.6.1 (2015.02.24)<br \><br \>" \ "Copyright (c) 2010 Ivan Mincik,<br \>[email protected]<br \>" \ u"Copyright (c) 2011-2015 Germán Carrillo,<br \>[email protected]<br \><br \>" \ "<i>Licensed under the terms of GNU GPL v.2.0</i><br \><br \>" \ "Based on PyQGIS. Plugin Fast SQL Layer by Pablo T. Carreira.</body></html>" ) def loadLayer(self, dictOpts): print 'I: Loading the layer...' self.layerSRID = dictOpts[ 'srid'] # To access the SRID when querying layer properties if not self.isActiveWindow(): self.activateWindow() self.raise_() if dictOpts['type'] == 'vector': # QGIS connection uri = QgsDataSourceURI() uri.setConnection(dictOpts['-h'], dictOpts['-p'], dictOpts['-d'], dictOpts['-U'], dictOpts['-W']) uri.setDataSource(dictOpts['-s'], dictOpts['-t'], dictOpts['-g']) layer = QgsVectorLayer(uri.uri(), dictOpts['-s'] + '.' + dictOpts['-t'], "postgres") elif dictOpts['type'] == 'raster': connString = "PG: dbname=%s host=%s user=%s password=%s port=%s mode=2 " \ "schema=%s column=%s table=%s" % ( dictOpts['-d'], dictOpts['-h'], dictOpts['-U'], dictOpts['-W'], dictOpts['-p'], dictOpts['-s'], dictOpts['col'], dictOpts['-t'] ) layer = QgsRasterLayer(connString, dictOpts['-s'] + '.' + dictOpts['-t']) if layer.isValid(): layer.setContrastEnhancement( QgsContrastEnhancement.StretchToMinimumMaximum) self.addLayer(layer, self.layerSRID) def addLayer(self, layer, srid='-1'): if layer.isValid(): # Only in case that srid != -1, read the layer SRS properties, otherwise don't since it will return 4326 if srid != '-1': self.layerSRID = layer.crs().description() + ' (' + str( layer.crs().postgisSrid()) + ')' else: self.layerSRID = 'Unknown SRS (-1)' if self.canvas.layerCount() == 0: self.canvas.setExtent(layer.extent()) if srid != '-1': print 'I: Map SRS (EPSG): %s' % self.layerSRID self.canvas.setMapUnits(layer.crs().mapUnits()) else: print 'I: Unknown Reference System' self.canvas.setMapUnits(0) # 0: QGis.Meters return QgsMapLayerRegistry.instance().addMapLayer(layer) return False def activeLayer(self): """ Returns the active layer in the layer list widget """ return self.legend.activeLayer() def getLayerProperties(self, l): """ Create a layer-properties string (l:layer)""" print 'I: Generating layer properties...' if l.type() == 0: # Vector wkbType = [ "WKBUnknown", "WKBPoint", "WKBLineString", "WKBPolygon", "WKBMultiPoint", "WKBMultiLineString", "WKBMultiPolygon", "WKBNoGeometry", "WKBPoint25D", "WKBLineString25D", "WKBPolygon25D", "WKBMultiPoint25D", "WKBMultiLineString25D", "WKBMultiPolygon25D" ] properties = "Source: %s\n" \ "Geometry type: %s\n" \ "Number of features: %s\n" \ "Number of fields: %s\n" \ "SRS (EPSG): %s\n" \ "Extent: %s " \ % ( l.source(), wkbType[l.wkbType()], l.featureCount(), l.dataProvider().fields().count(), self.layerSRID, l.extent().toString() ) elif l.type() == 1: # Raster rType = [ "GrayOrUndefined (single band)", "Palette (single band)", "Multiband", "ColorLayer" ] properties = "Source: %s\n" \ "Raster type: %s\n" \ "Width-Height (pixels): %sx%s\n" \ "Bands: %s\n" \ "SRS (EPSG): %s\n" \ "Extent: %s" \ % ( l.source(), rType[l.rasterType()], l.width(), l.height(), l.bandCount(), self.layerSRID, l.extent().toString() ) self.layerSRID = '-1' # Initialize the srid return properties def changeScale(self, scale): self.lblScale.setText("Scale 1:" + formatNumber(scale)) def updateXY(self, p): if self.canvas.mapUnits() == 2: # Degrees self.lblXY.setText( formatToDegrees( p.x() ) + " | " \ + formatToDegrees( p.y() ) ) else: # Unidad lineal self.lblXY.setText( formatNumber( p.x() ) + " | " \ + formatNumber( p.y() ) + "" )
class MapWindow(QMainWindow): """This class offers a canvas and tools to select polygons from a vector layer provided by the main app.""" # signal emitted when polygons succesfully selected finished = pyqtSignal() def __init__(self): QMainWindow.__init__(self) #self.setWindowFlags(Qt.CustomizeWindowHint) #self.setWindowFlags(Qt.WindowMinMaxButtonsHint) # creating map canvas, which draws the maplayers # setting up features like canvas color self.canvas = QgsMapCanvas() self.canvas.setMinimumSize(550, 700) self.canvas.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.canvas.setCanvasColor(Qt.white) self.canvas.setSelectionColor(QColor(255,255,26,200)) self.canvas.enableAntiAliasing(True) self.canvas.setParallelRenderingEnabled(True) # empty list for selected polygons self.selected_features = [] # setting up label settings: object below houses all of them self.label_settings = QgsPalLayerSettings() # object for text settings text_format = QgsTextFormat() text_format.setFont(QFont("Helvetica", 12)) text_format.setSize(7) # setting up a white buffer around the labels buffer_settings = QgsTextBufferSettings() buffer_settings.setEnabled(True) buffer_settings.setSize(0.65) buffer_settings.setColor(Qt.white) text_format.setBuffer(buffer_settings) # label settings: # fieldName = which field is shown as the label (currently Finnish name) # placement = labels can be placed differently in relation to one another # - see documentation for details self.label_settings.setFormat(text_format) self.label_settings.fieldName = "namefin" self.label_settings.placement = 0 self.label_settings.enabled = True # Qmainwindow requires a central widget. Canvas is placed self.setCentralWidget(self.canvas) # creating each desired action self.actionGet = QAction("Return selected and close", self) self.actionPan = QAction("Pan tool", self) self.actionSelect = QAction("Select tool", self) self.actionClear = QAction("Clear selection", self) self.actionCancel = QAction("Cancel and close", self) # these two function as on/off. the rest are clickable self.actionPan.setCheckable(True) self.actionSelect.setCheckable(True) # when actions are clicked, do corresponding function self.actionPan.triggered.connect(self.pan) self.actionSelect.triggered.connect(self.select) self.actionClear.triggered.connect(self.clearSelection) self.actionGet.triggered.connect(self.finishedSelection) self.actionCancel.triggered.connect(self.cancel) # toolbar at the top of the screen: houses actions as buttons # change order here to change their placement on window self.toolbar = self.addToolBar("Canvas actions") self.toolbar.setContextMenuPolicy(Qt.PreventContextMenu) self.toolbar.setMovable(False) self.toolbar.addAction(self.actionGet) self.toolbar.addAction(self.actionPan) self.toolbar.addAction(self.actionSelect) self.toolbar.addAction(self.actionClear) self.toolbar.addAction(self.actionCancel) # link actions to premade map tools self.toolPan = QgsMapToolPan(self.canvas) self.toolPan.setAction(self.actionPan) self.toolSelect = QgsMapToolIdentifyFeature(self.canvas) self.toolSelect.setAction(self.actionSelect) self.toolSelect.featureIdentified.connect(self.selectFeature) self.blocks_flag = False self.selection_rectangle = False # set select tool as default self.select() def pan(self): """Simply activates the tool""" self.canvas.setMapTool(self.toolPan) def select(self): self.canvas.setMapTool(self.toolSelect) def addLayer(self, layer): """Called when user click button on the main plugin: receives a vector layer, sets up labels & rendering parameters and shows the layer.""" # empty output list in case function is called multiple times self.selected_features.clear() self.selection_rectangle = False # layer into a self variable self.layer = layer # add layer to project: required to show it on screen # False = do not show the layer on the legend listing nor draw on main canvas QgsProject.instance().addMapLayer(self.layer, False) # set up visual stuff self.layer.setLabelsEnabled(True) layer_labeling = QgsVectorLayerSimpleLabeling(self.label_settings) self.layer.setLabeling(layer_labeling) self.layer.renderer().symbol().setColor(QColor(220,220,220)) # select tool needs a vector layer assigned to it self.toolSelect.setLayer(self.layer) self.canvas.setExtent(self.layer.extent()) # set layer to canvas self.canvas.setLayers([self.layer]) # show to user self.show() def addBlocksLayer(self, layer): self.selected_features.clear() self.blocks_flag = True self.layer = layer QgsProject.instance().addMapLayer(self.layer, False) self.layer.renderer().symbol().setColor(Qt.cyan) self.layer.renderer().symbol().setOpacity(0.30) # select tool needs a vector layer assigned to it self.toolSelect.setLayer(self.layer) self.canvas.setExtent(self.layer.extent()) # set layer to canvas """ url = ("https://vm0160.kaj.pouta.csc.fi/geoserver/ows?service=wfs&version=2.0.0"+ "&request=GetFeature&typename=ogiir:maakuntajako_2018_4500k&pagingEnabled=true") self.bg_layer = QgsVectorLayer(url, "BACKGROUND-REMOVE", "WFS") """ self.bg_layer = QgsRasterLayer("url=https://vm0160.kaj.pouta.csc.fi/ogiir_cache/wmts/1.0.0/" + "WMTSCapabilities.xml&crs=EPSG:3067&dpiMode=7&format=image/"+ "png&layers=taustakartta&styles=default&tileMatrixSet=GRIDI-FIN", 'GEOCUBES BG-LAYER - TEMPORARY', 'wms') if self.bg_layer.isValid(): QgsProject.instance().addMapLayer(self.bg_layer, False) self.canvas.setLayers([self.layer, self.bg_layer]) else: self.canvas.setLayers([self.layer]) self.show() def selectFeature(self, feat): """Activated when user clicks something on screen. This returns the clicked feature. The function does 2 things: 1. selects the feature on the map / deselects if already selected 2. adds features to a list in the same format (name, id_code) as they're stored in the 'Admin areas box' in the main file """ idx = feat.id() if self.blocks_flag: xmin = feat[0] ymax = feat[1] label = str(xmin) + "|" + str(ymax) else: code = feat[1] name = feat[2] label = name + "|" + code if label in self.selected_features: self.layer.deselect(idx) self.selected_features.remove(label) else: self.layer.select(idx) self.selected_features.append(label) def clearSelection(self): """Clear map selection and list on button click""" self.layer.removeSelection() self.selected_features.clear() def finishedSelection(self): """Activated when user clicks 'return selection'. Closes window and emits signal to indicate the job is finished""" self.close() self.finished.emit() def cancel(self): """In case user changes their mind. Does the same as above, but doesn't emit signal.""" self.close() def getSelection(self): """Returns list of selected features (polygons)""" return self.selected_features def getSelectionBbox(self): return self.selection_rectangle def closeEvent(self, event): """Activated anytime Mapwindow is closed either by buttons given or if the user finds some other way to close the window. Removes selection and deletes scrap maplayer.""" self.selection_rectangle = self.layer.boundingBoxOfSelected() self.layer.removeSelection() QgsProject.instance().removeMapLayer(self.layer) try: QgsProject.instance().removeMapLayer(self.bg_layer) except Exception: pass self.blocks_flag = False QMainWindow.closeEvent(self, event)
class PdfMaker(object): """A generator that takes a QGIS project file and a layout template and makes a pdf.""" def __init__(self, template_path, debug=False): """Constructor. :param template_path: Absolute path to a QGIS composer template file. :type template_path: str """ gui_flag = True self.app = QgsApplication(sys.argv, gui_flag) # Make sure QGIS_PREFIX_PATH is set in your env if needed! self.app.initQgis() if debug: print QgsProviderRegistry.instance().pluginList() self.canvas = QgsMapCanvas() self.canvas.enableAntiAliasing(True) self.template_path = template_path def __del__(self): """Destructor.""" del self.app def _load_template(self): """Load the template. :return: QgsComposition containing the loaded template. :rtype: QgsComposition """ template_file = file(self.template_path) template_content = template_file.read() template_file.close() document = QDomDocument() document.setContent(template_content) composition = QgsComposition(self.canvas.mapSettings()) # You can use this to replace any string like this [key] # in the template with a new value. e.g. to replace # [date] pass a map like this {'date': '1 Jan 2012'} substitution_map = {'DATE_TIME_START': 'foo', 'DATE_TIME_END': 'bar'} composition.loadFromTemplate(document, substitution_map) return composition def _load_layers(self): """Manually load all the layers for our project. :return: A list of QgsMapLayer instances. :rtype: list """ layers = [] # First the RW layer host = 'db' port = '5432' user = '******' password = '******' dbname = 'gis' uri = QgsDataSourceURI() uri.setConnection(host, port, dbname, user, password) schema = 'public' table = 'flood_mapper_rw' geometry_column = 'geometry' where_clause = '' title = 'RW' uri.setDataSource(schema, table, geometry_column, where_clause) layer = QgsVectorLayer(uri.uri(), title, 'postgres') QgsMapLayerRegistry.instance().addMapLayer(layer, False) canvas_layer = QgsMapCanvasLayer(layer) layers.append(canvas_layer) # Now the JK layer path = './data/jk.shp' title = 'JK' layer = QgsVectorLayer(path, title, 'ogr') QgsMapLayerRegistry.instance().addMapLayer(layer, False) canvas_layer = QgsMapCanvasLayer(layer) layers.append(canvas_layer) return layers def make_pdf(self, pdf_path): """Generate a pdf for the given project and template files. :param pdf_path: Absolute path for the output PDF file. :type pdf_path: str """ layers = self._load_layers() self.canvas.setLayerSet(layers) if self.canvas.layerCount() < 1: print 'No layers loaded from this project, exiting.' return self.canvas.setDestinationCrs( QgsCoordinateReferenceSystem('EPSG:3857')) self.canvas.setCrsTransformEnabled(True) self.canvas.zoomToFullExtent() print 'Extent: %s' % self.canvas.mapSettings().extent().toString() # self._load_project() composition = self._load_template() # You must set the id in the template map_item = composition.getComposerItemById('map') map_item.setMapCanvas(self.canvas) map_item.zoomToExtent(self.canvas.extent()) # You must set the id in the template legend_item = composition.getComposerItemById('legend') legend_item.updateLegend() composition.refreshItems() composition.exportAsPDF(pdf_path) QgsProject.instance().clear()
class VersionViewerDialog(BASE, WIDGET): def __init__(self, repo, path): super(VersionViewerDialog, self).__init__(config.iface.mainWindow(), Qt.WindowSystemMenuHint | Qt.WindowTitleHint) self.repo = repo self.path = path self.setupUi(self) self.listWidget.itemClicked.connect(self.commitClicked) settings = QSettings() horizontalLayout = QHBoxLayout() horizontalLayout.setSpacing(0) horizontalLayout.setMargin(0) self.mapCanvas = QgsMapCanvas() self.mapCanvas.setCanvasColor(Qt.white) self.mapCanvas.enableAntiAliasing(settings.value("/qgis/enable_anti_aliasing", False, type = bool)) self.mapCanvas.useImageToRender(settings.value("/qgis/use_qimage_to_render", False, type = bool)) action = settings.value("/qgis/wheel_action", 0, type = float) zoomFactor = settings.value("/qgis/zoom_factor", 2, type = float) self.mapCanvas.setWheelAction(QgsMapCanvas.WheelAction(action), zoomFactor) horizontalLayout.addWidget(self.mapCanvas) self.mapWidget.setLayout(horizontalLayout) self.panTool = QgsMapToolPan(self.mapCanvas) self.mapCanvas.setMapTool(self.panTool) versions = repo.log(path = path) if versions: for commit in versions: item = CommitListItem(commit, repo, path) self.listWidget.addItem(item) ''''w = CommitListItemWidget(commit) self.ui.listWidget.setItemWidget(item, w)''' else: raise GeoGigException("The selected feature is not versioned yet") def commitClicked(self): feature = self.listWidget.currentItem().feature geom = None self.attributesTable.setRowCount(len(feature)) for idx, attrname in enumerate(feature): value = feature[attrname] font = QFont() font.setBold(True) font.setWeight(75) item = QTableWidgetItem(attrname) item.setFont(font) self.attributesTable.setItem(idx, 0, item); self.attributesTable.setItem(idx, 1, QTableWidgetItem(str(value))); if geom is None: try: geom = QgsGeometry.fromWkt(value) except: pass self.attributesTable.resizeRowsToContents() self.attributesTable.horizontalHeader().setMinimumSectionSize(150) self.attributesTable.horizontalHeader().setStretchLastSection(True) settings = QSettings() prjSetting = settings.value('/Projections/defaultBehaviour') settings.setValue('/Projections/defaultBehaviour', '') types = ["Point", "LineString", "Polygon"] layers = [] if geom is not None: geomtype = types[int(geom.type())] layer = loadLayerNoCrsDialog(geomtype + "?crs=EPSG:4326", "temp", "memory") pr = layer.dataProvider() feat = QgsFeature() feat.setGeometry(geom) pr.addFeatures([feat]) layer.updateExtents() layer.selectAll() layer.setExtent(layer.boundingBoxOfSelected()) layer.invertSelection() symbol = QgsSymbolV2.defaultSymbol(layer.geometryType()) symbol.setColor(Qt.green) symbol.setAlpha(0.5) if QGis.QGIS_VERSION_INT < 29900: layer.setRendererV2(QgsSingleSymbolRendererV2(symbol)) else: layer.setRenderer(QgsSingleSymbolRenderer(symbol)) self.mapCanvas.setRenderFlag(False) self.mapCanvas.setLayerSet([QgsMapCanvasLayer(layer)]) QgsMapLayerRegistry.instance().addMapLayer(layer, False) self.mapCanvas.setExtent(layer.extent()) self.mapCanvas.setRenderFlag(True) layers.append(layer) else: self.mapCanvas.setLayerSet([]) settings.setValue('/Projections/defaultBehaviour', prjSetting)
class ConflictDialog(WIDGET, BASE): LOCAL, REMOTE, DELETE = 1, 2, 3 def __init__(self, conflicts): super(ConflictDialog, self).__init__(None, Qt.WindowSystemMenuHint | Qt.WindowTitleHint) self.solved = False self.resolvedConflicts = {} self.conflicts = conflicts self.setupUi(self) self.setWindowFlags(self.windowFlags() | Qt.WindowSystemMenuHint | Qt.WindowMinMaxButtonsHint) self.zoomButton.clicked.connect(self.zoomToFullExtent) self.solveButton.clicked.connect(self.solve) self.conflictsTree.itemClicked.connect(self.treeItemClicked) self.attributesTable.cellClicked.connect(self.cellClicked) self.solveAllLocalButton.clicked.connect(self.solveAllLocal) self.solveAllRemoteButton.clicked.connect(self.solveAllRemote) self.solveLocalButton.clicked.connect(self.solveLocal) self.solveRemoteButton.clicked.connect(self.solveRemote) self.showRemoteCheck.stateChanged.connect(self.showGeoms) self.showLocalCheck.stateChanged.connect(self.showGeoms) self.lastSelectedItem = None self.currentPath = None self.currentConflict = None self.theirsLayer = None self.oursLayer = None settings = QSettings() horizontalLayout = QHBoxLayout() horizontalLayout.setSpacing(0) horizontalLayout.setMargin(0) self.mapCanvas = QgsMapCanvas() self.mapCanvas.setCanvasColor(Qt.white) self.mapCanvas.enableAntiAliasing( settings.value("/qgis/enable_anti_aliasing", False, type=bool)) self.mapCanvas.useImageToRender( settings.value("/qgis/use_qimage_to_render", False, type=bool)) self.mapCanvas.mapRenderer().setProjectionsEnabled(True) action = settings.value("/qgis/wheel_action", 0, type=float) zoomFactor = settings.value("/qgis/zoom_factor", 2, type=float) self.mapCanvas.setWheelAction(QgsMapCanvas.WheelAction(action), zoomFactor) horizontalLayout.addWidget(self.mapCanvas) self.canvasWidget.setLayout(horizontalLayout) self.panTool = QgsMapToolPan(self.mapCanvas) self.mapCanvas.setMapTool(self.panTool) self.solveButton.setEnabled(False) self.solveLocalButton.setEnabled(False) self.solveRemoteButton.setEnabled(False) self.fillConflictsTree() def fillConflictsTree(self): topTreeItems = {} for c in self.conflicts: path = os.path.dirname(c.path) if path in topTreeItems: topItem = topTreeItems[path] else: topItem = QTreeWidgetItem() topItem.setText(0, path) topItem.setIcon(0, layerIcon) topTreeItems[path] = topItem conflictItem = ConflictItem(c) topItem.addChild(conflictItem) for item in list(topTreeItems.values()): self.conflictsTree.addTopLevelItem(item) def cellClicked(self, row, col): if col > 2: return value = self.attributesTable.item(row, col).value geoms = (self.oursgeom, self.theirsgeom) self.attributesTable.setItem(row, 4, ValueItem(value, False, geoms)) self.attributesTable.item(row, 0).setBackgroundColor(Qt.white) self.attributesTable.item(row, 1).setBackgroundColor(Qt.white) self.attributesTable.item(row, 2).setBackgroundColor(Qt.white) attrib = self.attributesTable.item(row, 3).text() if attrib in self.conflicted: self.conflicted.remove(attrib) self.updateSolveButton() self.showGeoms() def treeItemClicked(self): item = self.conflictsTree.selectedItems()[0] if self.lastSelectedItem == item: return if isinstance(item, ConflictItem): self.lastSelectedItem = item self.currentPath = item.conflict.path self.updateCurrentPath() self.solveLocalButton.setEnabled(True) self.solveRemoteButton.setEnabled(True) self.solveButton.setEnabled(False) def updateCurrentPath(self): self.solveButton.setEnabled(False) self.solveLocalButton.setEnabled(False) self.solveRemoteButton.setEnabled(False) self.cleanCanvas() self.showFeatureAttributes() self.createLayers() self.showGeoms() self.zoomToFullExtent() def zoomToFullExtent(self): layers = [ lay.extent() for lay in self.mapCanvas.layers() if lay.type() == lay.VectorLayer ] if layers: ext = layers[0] for layer in layers[1:]: ext.combineExtentWith(layer) self.mapCanvas.setExtent(ext) self.mapCanvas.refresh() def cleanCanvas(self): self.mapCanvas.setLayerSet([]) layers = [self.oursLayer, self.theirsLayer] for layer in layers: if layer is not None: QgsMapLayerRegistry.instance().removeMapLayer(layer.id()) self.oursLayer = None self.theirsLayer = None def solveAllRemote(self): ret = QMessageBox.warning( self, "Solve conflict", "Are you sure you want to solve all conflicts using the 'To merge' version?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if ret == QMessageBox.Yes: self.solved = True self.resolvedConflicts = { c.path: self.REMOTE for c in self.conflicts } self.close() def solveAllLocal(self): ret = QMessageBox.warning( self, "Solve conflict", "Are you sure you want to solve all conflict using the 'Local' version?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if ret == QMessageBox.Yes: self.solved = True self.resolvedConflicts = { c.path: self.LOCAL for c in self.conflicts } self.close() def _afterSolve(self, remove=True): if remove: parent = self.lastSelectedItem.parent() parent.removeChild(self.lastSelectedItem) self.lastSelectedItem = None if parent.childCount() == 0: self.conflictsTree.invisibleRootItem().removeChild(parent) if self.conflictsTree.topLevelItemCount() == 0: self.solved = True self.close() self.attributesTable.setRowCount(0) self.cleanCanvas() self.solveButton.setEnabled(False) self.solveLocalButton.setEnabled(False) self.solveRemoteButton.setEnabled(False) def solveLocal(self): self.resolvedConflicts[self.currentPath] = self.LOCAL self._afterSolve() def solveRemote(self): self.resolvedConflicts[self.currentPath] = self.REMOTE self._afterSolve() def solve(self): attribs = {} for i in range(self.attributesTable.rowCount()): value = self.attributesTable.item(i, 4).value name = str(self.attributesTable.item(i, 3).text()) attribs[name] = value self.resolvedConflicts[self.currentPath] = attribs self._afterSolve() def updateSolveButton(self): self.solveButton.setEnabled(len(self.conflicted) == 0) def showFeatureAttributes(self): conflictItem = self.lastSelectedItem self.oursgeom = None self.theirsgeom = None geoms = (self.oursgeom, self.theirsgeom) self.currentConflictedAttributes = [] attribs = list(conflictItem.origin.keys()) self.attributesTable.setRowCount(len(attribs)) self.conflicted = [] for idx, name in enumerate(attribs): font = QFont() font.setBold(True) font.setWeight(75) item = QTableWidgetItem(name) item.setFont(font) self.attributesTable.setItem(idx, 3, item) self.attributesTable.setItem(idx, 4, ValueItem(None, False)) try: values = (conflictItem.origin[name], conflictItem.local[name], conflictItem.remote[name]) except Exception: #Local has been deleted self._afterSolve(False) self.solveModifyAndDelete(conflictItem.conflict.path, self.REMOTE) return except TypeError: #Remote has been deleted self._afterSolve(False) self.solveModifyAndDelete(conflictItem.conflict.path, self.LOCAL) return try: geom = QgsGeometry.fromWkt(values[0]) except: geom = None if geom is not None: self.theirsgeom = QgsGeometry().fromWkt(values[1]) self.oursgeom = QgsGeometry.fromWkt(values[2]) geoms = (self.oursgeom, self.theirsgeom) ok = values[0] == values[1] or values[1] == values[2] or values[ 0] == values[2] for i, v in enumerate(values): self.attributesTable.setItem(idx, i, ValueItem(v, not ok, geoms)) if not ok: self.conflicted.append(name) else: if values[0] == values[1]: newvalue = values[2] else: newvalue = values[1] self.attributesTable.setItem(idx, 4, ValueItem(newvalue, False, geoms)) self.attributesTable.resizeRowsToContents() self.attributesTable.horizontalHeader().setMinimumSectionSize(150) self.attributesTable.horizontalHeader().setStretchLastSection(True) def solveModifyAndDelete(self, path, modified): msgBox = QMessageBox() msgBox.setText( "The feature has been modified in one version and deleted in the other one.\n" "How do you want to solve the conflict?") msgBox.addButton(QPushButton('Modify'), QMessageBox.YesRole) msgBox.addButton(QPushButton('Delete'), QMessageBox.NoRole) msgBox.addButton(QPushButton('Cancel'), QMessageBox.RejectRole) ret = msgBox.exec_() if ret == 0: self.resolvedConflicts[path] = modified self._afterSolve() elif ret == 1: self.resolvedConflicts[path] = self.DELETE self._afterSolve() else: pass def createLayers(self): types = [("Point", ptOursStyle, ptTheirsStyle), ("LineString", lineOursStyle, lineTheirsStyle), ("Polygon", polygonOursStyle, polygonTheirsStyle)] if self.oursgeom is not None: geomtype = types[int(self.oursgeom.type())][0] style = types[int(self.oursgeom.type())][1] self.oursLayer = loadLayerNoCrsDialog(geomtype + "?crs=EPSG:4326", "ours", "memory") pr = self.oursLayer.dataProvider() feat = QgsFeature() feat.setGeometry(self.oursgeom) pr.addFeatures([feat]) self.oursLayer.loadNamedStyle(style) self.oursLayer.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(self.oursLayer, False) else: self.oursLayer = None if self.theirsgeom is not None: geomtype = types[int(self.theirsgeom.type())][0] style = types[int(self.theirsgeom.type())][2] self.theirsLayer = loadLayerNoCrsDialog( geomtype + "?crs=EPSG:4326", "theirs", "memory") pr = self.theirsLayer.dataProvider() feat = QgsFeature() feat.setGeometry(self.theirsgeom) pr.addFeatures([feat]) self.theirsLayer.loadNamedStyle(style) self.theirsLayer.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(self.theirsLayer, False) else: self.theirsLayer = None def showGeoms(self): checks = [self.showRemoteCheck, self.showLocalCheck] layers = [self.oursLayer, self.theirsLayer] toShow = [] for lay, chk in zip(layers, checks): if lay is not None and chk.isChecked(): toShow.append(lay) self.mapCanvas.setRenderFlag(False) self.mapCanvas.setLayerSet( [QgsMapCanvasLayer(layer) for layer in toShow]) self.mapCanvas.setRenderFlag(True) def closeEvent(self, evnt): if not self.solved: ret = QMessageBox.warning( self, "Conflict resolution", "There are unsolved conflicts.\n" "Do you really want to exit and abort the sync operation?", QMessageBox.Yes | QMessageBox.No) if ret == QMessageBox.No: evnt.ignore() return self.cleanCanvas()
class RenderWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.setupUi() self.layer = None self.detection_layer = None self.crs = None def setupUi(self): gridLayout = QGridLayout(self) gridLayout.setContentsMargins(0, 0, 0, 0) self.canvas = QgsMapCanvas() self.canvas.setCanvasColor(QColor(255, 255, 255)) self.canvas.setStyleSheet("border: 0px;") settings = QSettings() self.canvas.enableAntiAliasing( settings.value("/qgis/enable_anti_aliasing", False, type=bool)) self.setMinimumSize(15, 15) # action pan and zoom self.pan_zoom_tool = PanAndZoomPointTool(self) self.canvas.setMapTool(self.pan_zoom_tool, clean=True) gridLayout.addWidget(self.canvas) def render_layer(self, layer): with block_signals_to(self): # set the CRS of the canvas view if self.crs: self.canvas.setDestinationCrs(self.crs) # set the sampling over the layer to view self.canvas.setLayers([layer]) # set init extent from other view if any is activated else set layer extent from pca4cd.gui.main_analysis_dialog import MainAnalysisDialog others_view = [ view_widget.render_widget.canvas.extent() for view_widget in MainAnalysisDialog.view_widgets if not view_widget.render_widget.canvas.extent().isEmpty() ] if others_view: extent = others_view[0] self.update_canvas_to(extent) else: self.canvas.setExtent(layer.extent()) self.canvas.refresh() self.layer = layer def update_canvas_to(self, new_extent): with block_signals_to(self.canvas): self.canvas.setExtent(new_extent) self.canvas.refresh() def set_detection_layer(self, detection_layer): self.detection_layer = detection_layer self.show_detection_layer() # hide the detection layer in combobox menu from pca4cd.gui.main_analysis_dialog import MainAnalysisDialog detection_layers = [ view_widget.render_widget.detection_layer for view_widget in MainAnalysisDialog.view_widgets if view_widget.pc_id is not None and view_widget.render_widget.detection_layer is not None and view_widget.id != self.parent_view.id ] + ([self.detection_layer] if self.detection_layer else []) for view_widget in MainAnalysisDialog.view_widgets: if view_widget.pc_id is None: view_widget.QCBox_RenderFile.setExceptedLayerList( MainAnalysisDialog.pca_layers + detection_layers) def show_detection_layer(self): if self.layer: self.canvas.setLayers([self.detection_layer, self.layer] if self. detection_layer else [self.layer]) self.canvas.refreshAllLayers() def hide_detection_layer(self): if self.layer: self.canvas.setLayers([self.layer]) self.canvas.refresh() @pyqtSlot() def layer_style_editor(self): style_editor_dlg = StyleEditorDialog(self.layer, self.canvas, self.parent()) if style_editor_dlg.exec_(): style_editor_dlg.apply()
class WidgetResult(Ui_widgetResult, QWidget): """ Widget (Panel) for result review """ ''' buffer around clicked point for point in polygon query ''' SEARCH_BUFFER = 20.0 ''' supported export formats ''' EXPORT_FORMATS = { get_ui_string("app.extension.shapefile"): ExportTypes.Shapefile, #get_ui_string("app.extension.kml"):ExportTypes.KML, #get_ui_string("app.extension.nrml"):ExportTypes.NRML, get_ui_string("app.extension.csv"): ExportTypes.CSV, } ''' enumeration of Layer to be previewed ''' EXPOSURE, SURVEY, POP_GRID, FOOTPRINT, ZONES = range(5) ''' name for Layer to be previewed ''' LAYER_NAMES = [ get_ui_string("widget.result.layer.exposure"), get_ui_string("widget.result.layer.survey"), get_ui_string("widget.result.layer.popgrid"), get_ui_string("widget.result.layer.footprint"), get_ui_string("widget.result.layer.zones"), ] LAYER_STYLES = [ '<!DOCTYPE renderer><renderer-v2 symbollevels="0" type="singleSymbol"><symbols><symbol outputUnit="MM" alpha="1" type="fill" name="0"><layer pass="******" class="SimpleLine" locked="0"><prop k="capstyle" v="square"/><prop k="color" v="0,0,0,255"/><prop k="customdash" v="5;2"/><prop k="joinstyle" v="bevel"/><prop k="offset" v="0"/><prop k="penstyle" v="solid"/><prop k="use_custom_dash" v="0"/><prop k="width" v="0.26"/></layer></symbol></symbols><rotation field=""/><sizescale field=""/></renderer-v2>', '<!DOCTYPE renderer><renderer-v2 symbollevels="0" type="singleSymbol"><symbols><symbol outputUnit="MM" alpha="1" type="marker" name="0"><layer pass="******" class="SimpleMarker" locked="0"><prop k="angle" v="0"/><prop k="color" v="0,0,255,255"/><prop k="color_border" v="0,0,255,255"/><prop k="name" v="circle"/><prop k="offset" v="0,0"/><prop k="size" v="2"/></layer></symbol></symbols><rotation field=""/><sizescale field=""/></renderer-v2>', '<!DOCTYPE renderer><renderer-v2 symbollevels="0" type="singleSymbol"><symbols><symbol outputUnit="MM" alpha="1" type="marker" name="0"><layer pass="******" class="SimpleMarker" locked="0"><prop k="angle" v="0"/><prop k="color" v="0,255,0,255"/><prop k="color_border" v="0,255,0,255"/><prop k="name" v="rectangle"/><prop k="offset" v="0,0"/><prop k="size" v="4"/></layer></symbol></symbols><rotation field=""/><sizescale field=""/></renderer-v2>', '<!DOCTYPE renderer><renderer-v2 symbollevels="0" type="singleSymbol"><symbols><symbol outputUnit="MM" alpha="1" type="fill" name="0"><layer pass="******" class="SimpleFill" locked="0"><prop k="color" v="170,250,170,255"/><prop k="color_border" v="0,0,0,255"/><prop k="offset" v="0,0"/><prop k="style" v="solid"/><prop k="style_border" v="solid"/><prop k="width_border" v="0.26"/></layer></symbol></symbols><rotation field=""/><sizescale field=""/></renderer-v2>', '<!DOCTYPE renderer><renderer-v2 symbollevels="0" type="singleSymbol"><symbols><symbol outputUnit="MM" alpha="1" type="fill" name="0"><layer pass="******" class="SimpleFill" locked="0"><prop k="color" v="211,211,158,200"/><prop k="color_border" v="0,0,0,255"/><prop k="offset" v="0,0"/><prop k="style" v="solid"/><prop k="style_border" v="solid"/><prop k="width_border" v="0.26"/></layer></symbol></symbols><rotation field=""/><sizescale field=""/></renderer-v2>', ] # constructor / destructor ############################### def __init__(self, app): """ constructor - initialize UI elements - connect UI elements to callback """ super(WidgetResult, self).__init__() self.ui = Ui_widgetResult() self.ui.setupUi(self) # create canvas self.canvas = QgsMapCanvas(self.ui.widget_map) self.canvas.setGeometry( 0, # x self.ui.widget_map_menu_l.x() + self.ui.widget_map_menu_l.height(), # y self.ui.widget_map.width() - 2 * UI_PADDING, # width self.ui.widget_map.width() - 2 * UI_PADDING # height ) self.canvas.setCanvasColor(Qt.white) self.canvas.enableAntiAliasing(True) self.canvas.mapRenderer().setProjectionsEnabled(True) self.canvas.mapRenderer().setDestinationCrs( QgsCoordinateReferenceSystem( 4326, QgsCoordinateReferenceSystem.PostgisCrsId)) self.canvas.zoomNextStatusChanged.connect(self.checkRendering) self.canvas.xyCoordinates.connect(self.currentLocation) self.registry = QgsMapLayerRegistry.instance() self.map_layers = [None] * len(self.LAYER_NAMES) self.map_layer_renderer = [None] * len(self.LAYER_NAMES) for idx, str_style in enumerate(self.LAYER_STYLES): rdoc = QDomDocument("renderer") rdoc.setContent(str_style) self.map_layer_renderer[idx] = QgsFeatureRendererV2.load( rdoc.firstChild().toElement()) # populate export list self.ui.cb_export_format.clear() for export_format in self.EXPORT_FORMATS.keys(): self.ui.cb_export_format.addItem(export_format) # style object required for QgsRendererV2PropertiesDialog self.style = QgsStyleV2() # create the map tools self.toolPan = QgsMapToolPan(self.canvas) self.toolZoomIn = QgsMapToolZoom(self.canvas, False) # false = in self.toolZoomOut = QgsMapToolZoom(self.canvas, True) # true = out self.toolInfo = QgsMapToolEmitPoint(self.canvas) self.toolInfo.canvasClicked.connect(self.showInfo) self.canvas.setMapTool(self.toolPan) # additional self.dlgResultDetail = DialogResult() self.dlgResultDetail.setModal(True) # set link to application main controller self.app = app # reset project self._project = None # default export setting self.export_format = ExportTypes.Shapefile # connect slots (ui event) self.ui.btn_zoom_full.clicked.connect(self.mapZoomFull) self.ui.btn_zoom_in.clicked.connect(self.mapZoomIn) self.ui.btn_zoom_out.clicked.connect(self.mapZoomOut) self.ui.btn_stop.clicked.connect(self.stopRendering) self.ui.btn_zoom_layer.clicked.connect(self.mapZoomLayer) self.ui.btn_pan.clicked.connect(self.mapPan) self.ui.btn_theme.clicked.connect(self.mapEditTheme) self.ui.btn_info.clicked.connect(self.mapIdentify) self.ui.btn_zoom_to_feature.clicked.connect(self.searchFeature) self.ui.cb_export_format.currentIndexChanged[str].connect( self.exportFormatChanged) self.ui.btn_export.clicked.connect(self.exportData) self.ui.btn_export_select_path.clicked.connect(self.selectExportFile) @pyqtSlot(QgsPoint) def currentLocation(self, point): self.app.updateMapLocation(point.x(), point.y()) #self.canvas.mouseMoveEvent(mouseEvent) # UI event handling calls (Qt slots) ############################### @pyqtSlot(QObject) def resizeEvent(self, event): """ handle window resize """ # find left coordinate for right side panels x_right_side = self.width() - self.ui.widget_export.width( ) - UI_PADDING # adjust right side panels self.ui.widget_export.move(x_right_side, self.ui.widget_map.y() + 30) self.ui.widget_dq_test.move( x_right_side, self.ui.widget_export.y() + self.ui.widget_export.height() + UI_PADDING) # adjust map panel (left side) self.ui.widget_map.resize(x_right_side - UI_PADDING, self.height() - 2 * UI_PADDING) # adjust map canvas within the map panel map_top = self.ui.widget_map_menu_l.x( ) + self.ui.widget_map_menu_l.height() + UI_PADDING self.canvas.resize( x_right_side - UI_PADDING, # same width as self.ui.widget_map self.ui.widget_map.height() - map_top - 2 * UI_PADDING) # height # adjust map menu self.ui.widget_map_menu_r.move( self.ui.widget_map.width() - self.ui.widget_map_menu_r.width(), # right align with map panel 0) # logo self.ui.lb_gem_logo.move(self.width() - self.ui.lb_gem_logo.width(), self.ui.lb_gem_logo.y()) @logUICall @pyqtSlot() def mapPan(self): """ event handler for btn_pan - pan map """ self.canvas.unsetMapTool(self.toolInfo) self.canvas.setMapTool(self.toolPan) @logUICall @pyqtSlot() def mapZoomIn(self): """ event handler for btn_zoom_in - zoom in on map """ self.canvas.unsetMapTool(self.toolInfo) self.canvas.setMapTool(self.toolZoomIn) @logUICall @pyqtSlot() def mapZoomOut(self): """ event handler for btn_zoom_out - zoom out on map """ self.canvas.unsetMapTool(self.toolInfo) self.canvas.setMapTool(self.toolZoomOut) @logUICall @pyqtSlot() def mapZoomFull(self): """ event handler for btn_zoom_full - zoom to full map """ self.canvas.zoomToFullExtent() def checkRendering(self, changed): self.canvas.setRenderFlag(True) @logUICall @pyqtSlot() def stopRendering(self): self.canvas.setRenderFlag(False) @logUICall @pyqtSlot() def mapZoomLayer(self): self.canvas.unsetMapTool(self.toolInfo) cur_layer_name = self.ui.cb_layer_selector.currentText() if cur_layer_name.isEmpty(): return self.zoomToLayer( self.map_layers[self.LAYER_NAMES.index(cur_layer_name)]) @logUICall @pyqtSlot() def mapEditTheme(self): """ event handler for btn_edit - identify item on map """ cur_layer_name = self.ui.cb_layer_selector.currentText() if cur_layer_name.isEmpty(): return try: cur_layer_idx = self.LAYER_NAMES.index(cur_layer_name) # build layer render property Dialog for selected layer dlg_render = QDialog() dlg_render.setWindowTitle( get_ui_string('widget.result.renderer.settings')) dlg_render.setModal(True) dlg_render.setFixedSize(530, 370) dlg_render.renderer = QgsRendererV2PropertiesDialog( self.map_layers[cur_layer_idx], self.style, True) dlg_render.renderer.setParent(dlg_render) dlg_render.renderer.setGeometry(QRect(10, 10, 510, 325)) dlg_render.buttonBox = QDialogButtonBox(dlg_render) dlg_render.buttonBox.setGeometry(QRect(10, 335, 510, 25)) dlg_render.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) dlg_render.buttonBox.accepted.connect(dlg_render.accept) dlg_render.buttonBox.accepted.connect(dlg_render.renderer.onOK) dlg_render.buttonBox.rejected.connect(dlg_render.reject) dlg_render.setVisible(True) # get user input and update renderer answer = dlg_render.exec_() if answer == QDialog.Accepted: self.map_layer_renderer[cur_layer_idx] = None self.map_layer_renderer[cur_layer_idx] = self.map_layers[ cur_layer_idx].rendererV2().clone() self.canvas.refresh() dlg_render.destroy() del dlg_render except Exception as err: # thematic is not-critical, allow continue on exception logUICall.log(str(err), logUICall.WARNING) @logUICall @pyqtSlot() def searchFeature(self): cur_layer_name = self.ui.cb_layer_selector.currentText() if cur_layer_name.isEmpty(): return try: cur_layer_idx = self.LAYER_NAMES.index(cur_layer_name) layer = self.map_layers[cur_layer_idx] fields = [] for fidx in layer.dataProvider().fields(): fields.append(layer.dataProvider().fields()[fidx].name()) dlg_search = DialogSearchFeature(fields) answer = dlg_search.exec_() if answer == QDialog.Accepted: extent = self.findFeatureExtentByAttribute( layer, dlg_search.attribute, dlg_search.value) if extent is not None: self.zoomToExtent(extent) else: logUICall.log(get_ui_string("widget.result.info.notfound"), logUICall.WARNING) dlg_search.destroy() except Exception as err: # thematic is not-critical, allow continue on exception logUICall.log(str(err), logUICall.WARNING) @logUICall @pyqtSlot() def mapIdentify(self): """ event handler for btn_info This only enables map querying, method connected to canvasClicked signal does the actual point-polygon query """ self.canvas.setMapTool(self.toolInfo) @logUICall @pyqtSlot() def selectExportFile(self): """ event handler for btn_export_select_path - open save file dialog box to select file name for export """ filename = QFileDialog.getSaveFileName( self, get_ui_string("widget.result.export.file.open"), ".", self.ui.cb_export_format.currentText()) if not filename.isNull(): self.ui.txt_export_select_path.setText(filename) @logUICall @pyqtSlot(str) def exportFormatChanged(self, selected_val): """ event handler for cb_export_format - update selected file after format change """ self.ui.txt_export_select_path.setText("") self.export_format = self.EXPORT_FORMATS[str(selected_val)] @logUICall @pyqtSlot() def exportData(self): """ event handler for btn_export - do export data """ export_path = str(self.ui.txt_export_select_path.text()) if export_path == "": logUICall.log(get_ui_string("app.error.path.is.null"), logUICall.WARNING) return self.app.exportResults(self.export_format, export_path) @logUICall @pyqtSlot(QPoint, QObject) def showInfo(self, point, mouseButton): """ event handler for toolInfo @see QGIS tutorial for detail point-polygon search on currently selected layer """ cur_layer_name = self.ui.cb_layer_selector.currentText() if cur_layer_name.isEmpty(): return try: cur_layer_idx = self.LAYER_NAMES.index(cur_layer_name) cur_layer = self.map_layers[cur_layer_idx] # if layer is not in same projection as map canvas # need to project query point if cur_layer.crs() != self.canvas.mapRenderer().destinationCrs(): transform = QgsCoordinateTransform( self.canvas.mapRenderer().destinationCrs(), cur_layer.crs()) point = transform.transform(point) # do query provider = cur_layer.dataProvider() provider.rewind() feature = QgsFeature() colonIndexes = provider.attributeIndexes() # search using point as center of rectangle polygon search_buffer_x = self.canvas.extent().width( ) * self.SEARCH_BUFFER / self.canvas.width() search_buffer_y = self.canvas.extent().height( ) * self.SEARCH_BUFFER / self.canvas.height() provider.select( colonIndexes, QgsRectangle(point.x() - search_buffer_x, point.y() - search_buffer_y, point.x() + search_buffer_x, point.y() + search_buffer_y), True) # get selected and display in result detail dialog box selected = [] while provider.nextFeature(feature): # for polygons, only show geometry containing query point if cur_layer.geometryType() == QGis.Polygon: if feature.geometry( ) is not None and not feature.geometry().contains(point): continue selected.append(feature.attributeMap()) if len(selected) > 0: # display result if exists if cur_layer_idx == self.EXPOSURE: self.dlgResultDetail.showExposureData( provider.fields(), selected) else: self.dlgResultDetail.showInfoData(provider.fields(), selected) self.dlgResultDetail.exec_() else: logUICall.log(get_ui_string("widget.result.info.notfound"), logUICall.WARNING) except Exception as err: # point-in-polygon search is not critical, continue on error logUICall.log(str(err), logUICall.WARNING) # public methods ############################### def set_project(self, project): ''' set project to preview. force refresh view on set''' self._project = project if project is None: return self.refreshView() self.canvas.zoomToFullExtent() logUICall.log("Project preview initialized sucessfully", logUICall.INFO) def get_project(self): return self._project # property access to project project = property(get_project, set_project) def refreshView(self): ''' reload all QGIS layers in currently defined project ''' if self._project is None: return # display layers if exists if self._project.fp_file is not None and exists(self._project.fp_file): if self.map_layers[self.FOOTPRINT] is None or self.map_layers[ self.FOOTPRINT].source() != self._project.fp_file: self.showDataLayer( self.FOOTPRINT, load_shapefile(self._project.fp_file, 'footprint')) else: self.removeDataLayer(self.FOOTPRINT) if self._project.zone_file is not None and exists( self._project.zone_file): if self.map_layers[self.ZONES] is None or self.map_layers[ self.ZONES].source() != self._project.zone_file: self.showDataLayer( self.ZONES, load_shapefile(self._project.zone_file, 'zones')) else: self.removeDataLayer(self.ZONES) if self._project.survey_file is not None and exists( self._project.survey_file): if getattr(self._project, 'survey', None) is None: self._project.load_survey() self.showDataLayer(self.SURVEY, self._project.survey) else: self.removeDataLayer(self.SURVEY) if self._project.popgrid_file is not None and exists( self._project.popgrid_file): if getattr(self._project, 'popgrid', None) is None: self.showDataLayer( self.POP_GRID, load_shapefile(self._project.popgrid_file, 'popgrid')) else: self.removeDataLayer(self.POP_GRID) # set export options for idx, export_format in enumerate(self.EXPORT_FORMATS.values()): if export_format == self._project.export_type: self.ui.cb_export_format.setCurrentIndex(idx) self.ui.txt_export_select_path.setText(self._project.export_path) # refreshResult contains refresh call to update all layers currently loaded self.refreshResult() def refreshResult(self): ''' reload result QGIS layer and data quality reports in currently defined project ''' exposure = getattr(self._project, 'exposure', None) if exposure is not None: self.showDataLayer(self.EXPOSURE, exposure) has_result = True else: self.removeDataLayer(self.EXPOSURE) has_result = False if has_result: # build quality report report_lines = [] if self._project.operator_options.has_key("proc.extrapolation"): proc_option = self._project.operator_options[ "proc.extrapolation"] if proc_option == ExtrapolateOptions.RandomWalk: proc_method = get_ui_string( "widget.result.dq.method", get_ui_string("dlg.options.ep.random")) elif proc_option == ExtrapolateOptions.Fraction: proc_method = get_ui_string( "widget.result.dq.method", get_ui_string("dlg.options.ep.fraction")) elif proc_option == ExtrapolateOptions.FractionRounded: proc_method = get_ui_string( "widget.result.dq.method", get_ui_string("dlg.options.ep.fraction.rounded")) else: proc_method = get_ui_string( "widget.result.dq.method", get_ui_string("dlg.options.ep.random")) report_lines.append(proc_method) report_lines.append('') # total tests report_lines.append( get_ui_string('widget.result.dq.total_tests', len(self._project.quality_reports.keys()))) report_lines.append('') # detail for each test for key, report in self._project.quality_reports.iteritems(): report_lines.append( get_ui_string('widget.result.dq.tests.%s' % key)) for title, value in report.iteritems(): report_lines.append( get_ui_string( 'widget.result.dq.tests.%s.%s' % (key, title), value)) report_lines.append('') self.ui.txt_dq_test_details.setText("\n".join(report_lines)) self.ui.btn_export.setEnabled(has_result) self.ui.widget_dq_test.setVisible(has_result) self.ui.txt_export_select_path.setEnabled(has_result) self.ui.btn_export_select_path.setEnabled(has_result) self.ui.cb_export_format.setEnabled(has_result) # this call refresh all layers currently loaded self.refreshLayers() @logUICall def closeResult(self): ''' remove from map result QGIS layer and reset quality report display ''' self.canvas.setLayerSet( [] ) # call necessary to remove all layers to avoid disconnect errors self.removeDataLayer(self.EXPOSURE) self.refreshLayers() self.ui.txt_dq_test_details.setText("") @logUICall def closeAll(self): ''' remove from map all QGIS layer in currently defined project ''' self.ui.cb_layer_selector.clear() try: self.canvas.setLayerSet( [] ) # call necessary to remove all layers to avoid disconnect errors for i in range(5): self.removeDataLayer(i) self.ui.txt_dq_test_details.setText("") self.refreshLayers() except: pass # exception will is thrown when registry is empty # internal helper methods ############################### def showDataLayer(self, index, layer): """ display given QGIS layer on map """ try: # add to QGIS registry and refresh view if self.map_layers[index] is not None: self.removeDataLayer(index) self.map_layers[index] = layer self.registry.addMapLayer(layer) layer.setRendererV2(self.map_layer_renderer[index]) except: pass def removeDataLayer(self, index): """ remove from map the layer identified with index """ layer = self.map_layers[index] self.map_layers[index] = None if layer is not None: try: self.registry.removeMapLayer(layer.getLayerID(), False) del layer except: pass # do nothing if it fails. probably already deleted def findFeatureExtentByAttribute(self, layer, field, value): """ find extent of all objects in QGIS layer matching condition "field=value" """ fidx = layer_field_index(layer, field) if fidx == -1: return None xmin, xmax, ymin, ymax = 180, -180, 90, -90 extent = QgsRectangle(xmin, ymin, xmax, ymax) need_transform = layer.crs() != self.canvas.mapRenderer( ).destinationCrs() if need_transform: transform = QgsCoordinateTransform( layer.crs(), self.canvas.mapRenderer().destinationCrs()) for feature in layer_features(layer): if str(value) == feature.attributeMap()[fidx].toString(): f_extent = feature.geometry().boundingBox() if need_transform: f_extent = transform.transform(f_extent) xmin = min(f_extent.xMinimum(), xmin) xmax = max(f_extent.xMaximum(), xmax) ymin = min(f_extent.yMinimum(), ymin) ymax = max(f_extent.yMaximum(), ymax) extent.set(xmin, ymin, xmax, ymax) return extent def zoomToLayer(self, layer): """ zoom canvas to extent of given layer """ try: lyr_extent = layer.extent() if layer.crs() != self.canvas.mapRenderer().destinationCrs(): transform = QgsCoordinateTransform( layer.crs(), self.canvas.mapRenderer().destinationCrs()) lyr_extent = transform.transform(lyr_extent) self.zoomToExtent(lyr_extent) except: pass def zoomToExtent(self, extent): """ zoom canvas to given extent """ try: self.canvas.setExtent(extent) self.canvas.zoomByFactor(1.1) except: self.mapZoomFull() def refreshLayers(self): """ refresh all layers in canvas """ # add each layer according to order layerSet = [] self.ui.cb_layer_selector.clear() for idx, lyr in enumerate(self.map_layers): if lyr is not None: layerSet.append(QgsMapCanvasLayer(lyr)) self.ui.cb_layer_selector.addItem(self.LAYER_NAMES[idx]) if len(layerSet) > 0: self.canvas.setLayerSet(layerSet)
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
class FeatureOfInterestDefinerConfigurationWidget(StandardModuleConfigurationWidget): """A widget to configure the FeatureOfInterestDefiner Module.""" def __init__(self, module, controller, parent=None): StandardModuleConfigurationWidget.__init__(self, module, controller, parent) self.foi_type = module.name #self.module = module self.setObjectName("FeatureOfInterestDefinerWidget") self.parent_widget = module # FIXME these modules don't exist self.path_png_icon = vistrails.packages.eo4vistrails.geoinf.visual.__path__[0] self.path_bkgimg = vistrails.packages.eo4vistrails.geoinf.visual.__path__[0] self.create_config_window() def create_config_window(self): """TO DO - add docstring""" self.setWindowTitle(self.foi_type) self.setMinimumSize(800, 850) self.center() self.mainLayout = QtGui.QVBoxLayout() self.setLayout(self.mainLayout) #set up Group Box for organising CRS of FOI self.crsGroupBox = QtGui.QGroupBox("Define Projection or Coordinate Reference System") self.crsLayout = QtGui.QHBoxLayout() self.crsProj4Label = QtGui.QLabel('SRS Proj4: ') self.crsTextAsProj4 = QtGui.QLineEdit('4326') self.crsChooseButton = QtGui.QPushButton('&Choose SRS') self.crsChooseButton.setAutoDefault(False) self.crsChooseButton.setToolTip('Choose a Spatial Reference System or Projection') self.crsLayout.addWidget(self.crsProj4Label) self.crsLayout.addWidget(self.crsTextAsProj4) self.crsLayout.addWidget(self.crsChooseButton) self.crsGroupBox.setLayout(self.crsLayout) #set up Group Box for getting coords of Bounding Box self.bbGroupBox = QtGui.QGroupBox("Define Area of Interest via a Bounding Box in units of SRS") self.bbLayout = QtGui.QHBoxLayout() self.bbMinXLabel = QtGui.QLabel('MinX/Left: ') self.bbMinYLabel = QtGui.QLabel('MinY/Bottom: ') self.bbMaxXLabel = QtGui.QLabel('MaxX/Right: ') self.bbMaxYLabel = QtGui.QLabel('MaxY/Top: ') self.bbMinXText = QtGui.QLineEdit('15') self.bbMinYText = QtGui.QLineEdit('-35') self.bbMaxXText = QtGui.QLineEdit('35') self.bbMaxYText = QtGui.QLineEdit('-20') self.bbToMapButton = QtGui.QPushButton('&To Map') self.bbToMapButton.setAutoDefault(False) self.bbToMapButton.setToolTip('Show Bounding Box on Map') self.bbLayout.addWidget(self.bbMinXLabel) self.bbLayout.addWidget(self.bbMinXText) self.bbLayout.addWidget(self.bbMinYLabel) self.bbLayout.addWidget(self.bbMinYText) self.bbLayout.addWidget(self.bbMaxXLabel) self.bbLayout.addWidget(self.bbMaxXText) self.bbLayout.addWidget(self.bbMaxYLabel) self.bbLayout.addWidget(self.bbMaxYText) self.bbLayout.addWidget(self.bbToMapButton) self.bbGroupBox.setLayout(self.bbLayout) #set up Group Box for getting text representation of a geometry self.asTxtGroupBox = QtGui.QGroupBox("Define Area of Interest via a WKT string in units of SRS") self.asTxtLayout = QtGui.QVBoxLayout() self.asTxtLabel = QtGui.QLabel('WKT String: ') self.asTxtText = QtGui.QTextEdit('') self.asTxtToMapButton = QtGui.QPushButton('&To Map') self.asTxtToMapButton.setAutoDefault(False) self.asTxtToMapButton.setToolTip('Show Bounding Box on Map') self.asTxtLayout.addWidget(self.asTxtLabel) self.asTxtLayout.addWidget(self.asTxtText) self.asTxtLayout.addWidget(self.asTxtToMapButton) self.asTxtGroupBox.setLayout(self.asTxtLayout) #set up Group Box for Map self.MapGroupBox = QtGui.QGroupBox("Map Viewer") self.MapLayout = QtGui.QHBoxLayout() #sz = QtCore.QSize(200, 300) #self.MapLayout.setGeometry(QtCore.QRect(300, 700, 780, 680)) self.MapGroupBox.setLayout(self.MapLayout) ## create canvas self.canvas = QgsMapCanvas() self.canvas.setCanvasColor(QtGui.QColor(200, 200, 255)) #self.mainLayout.addWidget(self.canvas) # icons actionAddLayer = QtGui.QAction(QtGui.QIcon(self.path_png_icon + \ "/mActionAddLayer.png"), "Add Layer", self) actionZoomIn = QtGui.QAction(QtGui.QIcon(self.path_png_icon + \ "/mActionZoomIn.png"), "Zoom In", self) actionZoomOut = QtGui.QAction(QtGui.QIcon(self.path_png_icon + \ "/mActionZoomOut.png"), "Zoom Out", self) actionPan = QtGui.QAction(QtGui.QIcon(self.path_png_icon + \ "/mActionPan.png"), "Pan", self) actionIdentify = QtGui.QAction(QtGui.QIcon(self.path_png_icon + \ "/mActionIdentify.png"), "Feature Information", self) # create toolbar self.toolbar = QtGui.QToolBar() # "Canvas actions" self.toolbar.addAction(actionAddLayer) self.toolbar.addAction(actionZoomIn) self.toolbar.addAction(actionZoomOut) self.toolbar.addAction(actionPan) self.toolbar.addAction(actionIdentify) # create layer explorer pane self.explorer = QtGui.QDockWidget("Layers") self.explorer.resize(60, 100) #~self.explorerListWidget = QtGui.QListWidget() #~self.explorerListWidget.setObjectName("listWidget") #~self.explorer.setWidget(self.explorerListWidget) # create map tools self.toolPan = QgsMapToolPan(self.canvas,) self.toolPan.setAction(actionPan) self.toolZoomIn = QgsMapToolZoom(self.canvas, False) # false == in self.toolZoomIn.setAction(actionZoomIn) self.toolZoomOut = QgsMapToolZoom(self.canvas, True) # true == out self.toolZoomOut.setAction(actionZoomOut) self.toolAOI = QgsMapTool(self.canvas) self.toolIdentify = GetFeatureInfoTool(self.canvas, self.gotFeatureForIdentification) self.toolIdentify.setAction(actionIdentify) # layerList explorer self.GroupBoxLyrExplorer = QtGui.QGroupBox("") self.vboxLyrExplorer = QtGui.QVBoxLayout() self.GroupBoxLyrExplorer.setLayout(self.vboxLyrExplorer) self.MapLayout.addWidget(self.GroupBoxLyrExplorer) self.label = QtGui.QLabel("") self.vboxLyrExplorer.addWidget(self.label) self.vboxLyrExplorer.addWidget(self.explorer) # toolbar and canvas layout self.GroupBoxToolBarMapCanvas = QtGui.QGroupBox("") self.vboxToolBarMapCanvas = QtGui.QVBoxLayout() self.vboxToolBarMapCanvas.setGeometry(QtCore.QRect(300, 700, 780, 680)) self.GroupBoxToolBarMapCanvas.setLayout(self.vboxToolBarMapCanvas) self.MapLayout.addWidget(self.GroupBoxToolBarMapCanvas) self.vboxToolBarMapCanvas.addWidget(self.toolbar) self.vboxToolBarMapCanvas.addWidget(self.canvas) #global list to hold inputlayers list -> accessible for toggleLayer self.mylist = [] #finalise/cancel buttons self.finishGroupBox = QtGui.QGroupBox("Finish") self.buttonLayout = QtGui.QHBoxLayout() self.finishGroupBox.setLayout(self.buttonLayout) self.buttonLayout.setGeometry(QtCore.QRect(300, 500, 780, 680)) self.buttonLayout.setMargin(5) self.cancelButton = QtGui.QPushButton('&Cancel', self) self.cancelButton.setAutoDefault(False) self.cancelButton.setShortcut('Esc') self.buttonLayout.addStretch(1) # force buttons to the right self.buttonLayout.addWidget(self.cancelButton) self.okButton = QtGui.QPushButton('&OK', self) self.okButton.setAutoDefault(False) self.buttonLayout.addWidget(self.okButton) self.connect(self.okButton, QtCore.SIGNAL('clicked(bool)'), self.okTriggered) self.connect(self.cancelButton, QtCore.SIGNAL('clicked(bool)'), self.close) self.mainLayout.addWidget(self.crsGroupBox) self.mainLayout.addWidget(self.bbGroupBox) self.mainLayout.addWidget(self.asTxtGroupBox) self.mainLayout.addWidget(self.MapGroupBox) self.mainLayout.addWidget(self.finishGroupBox) # set signals self.connect(self.crsChooseButton, QtCore.SIGNAL('clicked(bool)'), self.getSRS) self.connect(self.bbToMapButton, QtCore.SIGNAL('clicked(bool)'), self.bbToMapBB) self.connect(self.asTxtToMapButton, QtCore.SIGNAL('clicked(bool)'), self.bbToMapTxt) self.connect(actionAddLayer, QtCore.SIGNAL("activated()"), self.addLayer) self.connect(actionZoomIn, QtCore.SIGNAL("activated()"), self.zoomIn) self.connect(actionZoomOut, QtCore.SIGNAL("activated()"), self.zoomOut) self.connect(actionPan, QtCore.SIGNAL("activated()"), self.pan) self.connect(actionIdentify, QtCore.SIGNAL("triggered()"), self.identifyFeature) #load a backdrop layer self.mapCanvasLayers = [] fname = self.path_bkgimg + '/bluemarblemerged.img' fileInfo = QtCore.QFileInfo(fname) baseName = fileInfo.baseName() self.bmLayer = QgsRasterLayer(fname, baseName) QgsMapLayerRegistry.instance().addMapLayer(self.bmLayer) self.cl = QgsMapCanvasLayer(self.bmLayer) self.mapCanvasLayers.append(self.cl) # Set extent to the extent of our layer self.canvas.setExtent(self.bmLayer.extent()) self.canvas.enableAntiAliasing(True) self.canvas.freeze(False) self.canvas.setLayerSet(self.mapCanvasLayers) self.canvas.refresh() #now, add a container layer for our text based/ digitised or selected geoms self.addMemoryLayer() #self.update() def center(self): """TO DO - add docstring""" screen = QtGui.QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) def getSRS(self): # retruns the description and proj4 string of the chosen SRS, from the SRSDialog srsdlg = SRSChooserDialog("Choose SRS") if srsdlg.exec_(): self.crsTextAsProj4.setText(srsdlg.getProjection()) def bbToMapBB(self): self.bbToMap(fullWkt=False) def bbToMapTxt(self): self.bbToMap(fullWkt=True) def bbToMap(self, fullWkt=False): '''takes bounding box coords and puts them on the map''' #if self.foi_type == "AreaOfInterestDefiner": if not fullWkt: ix = self.bbMinXText.text() iy = self.bbMinYText.text() ax = self.bbMaxXText.text() ay = self.bbMaxYText.text() wkt = "POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))" % \ (ix, iy, ix, ay, ax, ay, ax, iy, ix, iy) else: wkt = self.asTxtText.toPlainText() try: errnum = 0 geom = QgsGeometry().fromWkt(wkt) print "gotGeom" if self.foi_type == "AreaOfInterestDefiner" and geom.type() != 2: errnum = 1 elif self.foi_type == "LineOfInterestDefiner" and geom.type() != 1: errnum = 1 elif self.foi_type == "PointOfInterestDefiner" and geom.type() != 0: errnum = 1 else: print "attempting to add geometry to mem layer" self.addGeomToMemoryLayer(geom) if errnum == 1: raise ModuleError(self, "Incorrect Geometry Type chosen") except: raise ModuleError(self, "Could not generate Geometry from text provided") #else: #print "Cannot create a Bounding box feature on a line or point layer" #add to map #map tool functions def addLayer(self): """TO DO: Add doc string""" fileName = QtGui.QFileDialog.getOpenFileName( parent=None, caption="Select Vector Overlay Layer", filter="Vector Files (*.shp *.geojson *.gml)") print fileName info = QtCore.QFileInfo(fileName) print info.filePath() print info.completeBaseName() # create layer layer = QgsVectorLayer(info.filePath(), info.completeBaseName(), "ogr") if not layer.isValid(): print "invalid layer" return # add layer to the registry QgsMapLayerRegistry.instance().addMapLayer(layer) # set extent to the extent of our layer #self.canvas.setExtent(layer.extent()) # set the map canvas layer set cl = QgsMapCanvasLayer(layer) self.mapCanvasLayers.insert(len(self.mapCanvasLayers) - 2, cl) #layers = [cl] self.canvas.setLayerSet(self.mapCanvasLayers) print "added Layer" def addMemoryLayer(self): '''Adds a layer to contain the feature defined by a bounding box, wkt, digitised poly|line|point or selection from other layer. ''' foi_type = self.foi_type.lower() if foi_type == 'areaofinterestdefiner': layer = QgsVectorLayer("Polygon", "Area of Interest", "memory") if foi_type == 'lineofinterestdefiner': layer = QgsVectorLayer("Linestring", "Line of Interest", "memory") if foi_type == 'pointofinterestdefiner': layer = QgsVectorLayer("Point", "Point of Interest", "memory") if foi_type == 'areaofinterestdefiner': sym = QgsSymbol(QGis.Polygon) sym.setColor(QtCore.Qt.black) sym.setFillColor(QtCore.Qt.green) sym.setFillStyle(QtCore.Qt.Dense6Pattern) sym.setLineWidth(0.5) sr = QgsSingleSymbolRenderer(QGis.Polygon) if foi_type == 'lineofinterestdefiner': sym = QgsSymbol(QGis.Line) sym.setColor(QtCore.Qt.black) sym.setFillColor(QtCore.Qt.green) sym.setFillStyle(QtCore.Qt.SolidPattern) sym.setLineWidth(0.5) sr = QgsSingleSymbolRenderer(QGis.Line) if foi_type == 'pointofinterestdefiner': sym = QgsSymbol(QGis.Point) sym.setColor(QtCore.Qt.black) sym.setFillColor(QtCore.Qt.green) sym.setFillStyle(QtCore.Qt.SolidPattern) sym.setLineWidth(0.3) sym.setPointSize(4) sym.setNamedPointSymbol("hard:triangle") sr = QgsSingleSymbolRenderer(QGis.Point) sr.addSymbol(sym) layer.setRenderer(sr) if not layer.isValid(): print "invalid layer" return ml_dp = layer.dataProvider() ml_dp.addAttributes([QgsField("gid", QtCore.QVariant.String)]) # add layer to the registry self.mem_layer_obj = QgsMapLayerRegistry.instance().addMapLayer(layer) # set extent to the extent of our layer #self.canvas.setExtent(layer.extent()) # set the map canvas layer set cl = QgsMapCanvasLayer(layer) self.mapCanvasLayers.insert(0, cl) #layers = [cl] self.canvas.setLayerSet(self.mapCanvasLayers) print "added Layer" def addGeomToMemoryLayer(self, the_geom, origin=0, delete_when_done=False): """TO DO: Add doc string""" foi_type = self.foi_type.lower() print "got foi_type" if self.mem_layer_obj.featureCount() > 0: if origin == 1: # is added by identify operation pass else: print self.mem_layer_obj.featureCount() print "there exists a feature, kill it!" self.mem_layer_obj.select() print "Feature count selcted for deletion:" print self.mem_layer_obj.selectedFeatureCount() self.mem_layer_obj.deleteSelectedFeatures() #self.mem_layer_obj.deleteFeature(0) self.mem_layer_obj.commitChanges() self.mem_layer_obj.triggerRepaint() ml_dp = self.mem_layer_obj.dataProvider() print "got DP" uuid_gid = QtCore.QUuid().createUuid().toString() print "got uuid" fet = QgsFeature() print "got feature with id" fet.setGeometry(the_geom) print "set geometry" fet.addAttribute(0, uuid_gid) print "set attr " ml_dp.addFeatures([fet]) self.mem_layer_obj.commitChanges() print "added layers" #self.mem_layer_obj.updateFeatureAttributes(fet) #self.mem_layer_obj.updateFeatureGeometry(fet) self.mem_layer_obj.updateExtents() print "updated extents" #self.mem_layer_obj.drawFeature(fet) self.mem_layer_obj.triggerRepaint() print "trp" return fet.id() def zoomIn(self): """TO DO: Add doc string""" self.canvas.setMapTool(self.toolZoomIn) def zoomOut(self): """TO DO: Add doc string""" self.canvas.setMapTool(self.toolZoomOut) def pan(self): """TO DO: Add doc string""" self.canvas.setMapTool(self.toolPan) def identifyFeature(self): '''getFeatureInfo functionality''' self.canvas.setMapTool(self.toolIdentify) #print "GFI not yet implemented" def gotFeatureForIdentification(self, pos): """Show a dialog with road information """ #pos is a rectangle self.mem_layer_obj.select() ftr = QgsFeature() ftr_ids = [] while self.mem_layer_obj.nextFeature(ftr): if ftr.geometry().intersects(pos): ftr_ids.append(ftr.id()) self.chosenFOIGeoms = [] self.info = QgsMessageViewer() if ftr_ids != []: f = QgsFeature() foi_type = self.foi_type.lower() if foi_type == 'areaofinterestdefiner': ftrData = "You have selected the following feature(s) for use as an Area of Interest:\n\n" if foi_type == 'lineofinterestdefiner': ftrData = "You have selected the following feature(s) for use as a Line of Interest:\n\n" if foi_type == 'pointofinterestdefiner': ftrData = "You have selected the following feature(s) for use as a Point of Interest:\n\n" for fid in ftr_ids: self.mem_layer_obj.dataProvider().featureAtId(fid, f, True) ftrData += f.attributeMap()[0].toString() ftrData += "\n_____________________________\n" self.chosenFOIGeoms.append(f.geometry()) id_fid = self.addGeomToMemoryLayer(f.geometry()) self.info.setMessageAsPlainText(ftrData) else: self.info.setMessageAsPlainText("no data to show") self.info.show() return def makeAOI(self): pass def makeLOI(self): pass def makePOI(self): pass def okTriggered(self): the_fet = QgsFeature() the_geoms = [] print self.mem_layer_obj.featureCount() self.mem_layer_obj.select() while self.mem_layer_obj.nextFeature(the_fet): #self.mem_layer_obj.featureAtId(0, the_fet) the_geoms.append(str(the_fet.geometry().exportToWkt())) print the_geoms wktstr = WKTString() print wktstr wktstr.setValue(the_geoms[0]) self.controller.update_ports_and_functions( self.module.id, [], [], [("WKTGeometry", the_geoms), ("SRS", [self.crsTextAsProj4.text()])]) self.close()
class GeometryDiffViewerDialog(QDialog): def __init__(self, geoms, crs, parent=None): super(GeometryDiffViewerDialog, self).__init__(parent) self.geoms = geoms self.crs = crs self.initGui() def initGui(self): layout = QVBoxLayout() self.tab = QTabWidget() self.table = QTableView() self.setLayout(layout) self.canvas = QgsMapCanvas() self.canvas.setCanvasColor(Qt.white) settings = QSettings() self.canvas.enableAntiAliasing( settings.value("/qgis/enable_anti_aliasing", False, type=bool)) self.canvas.useImageToRender( settings.value("/qgis/use_qimage_to_render", False, type=bool)) self.canvas.mapSettings().setDestinationCrs(self.crs) action = settings.value("/qgis/wheel_action", 0, type=float) zoomFactor = settings.value("/qgis/zoom_factor", 2, type=float) self.canvas.setWheelAction(QgsMapCanvas.WheelAction(action), zoomFactor) self.panTool = QgsMapToolPan(self.canvas) self.canvas.setMapTool(self.panTool) execute(self.createLayers) model = GeomDiffTableModel(self.data) self.table.setModel(model) self.table.resizeColumnsToContents() self.table.resizeRowsToContents() self.tab.addTab(self.canvas, "Map view") self.tab.addTab(self.table, "Table view") layout.addWidget(self.tab) self.resize(600, 500) self.setWindowTitle("Geometry comparison") def createLayers(self): textGeometries = [] for geom in self.geoms: text = geom.exportToWkt() valid = " -1234567890.," text = "".join([c for c in text if c in valid]) textGeometries.append(text.split(",")) lines = difflib.Differ().compare(textGeometries[0], textGeometries[1]) self.data = [] for line in lines: if line.startswith("+"): self.data.append([None, line[2:]]) if line.startswith("-"): self.data.append([line[2:], None]) if line.startswith(" "): self.data.append([line[2:], line[2:]]) types = [("LineString", lineBeforeStyle, lineAfterStyle), ("Polygon", polygonBeforeStyle, polygonAfterStyle)] layers = [] extent = self.geoms[0].boundingBox() for i, geom in enumerate(self.geoms): geomtype = types[int(geom.type() - 1)][0] style = types[int(geom.type() - 1)][i + 1] layer = loadLayerNoCrsDialog( geomtype + "?crs=" + self.crs.authid(), "layer", "memory") pr = layer.dataProvider() feat = QgsFeature() feat.setGeometry(geom) pr.addFeatures([feat]) layer.loadNamedStyle(style) layer.updateExtents() layers.append(layer) QgsMapLayerRegistry.instance().addMapLayer(layer, False) extent.combineExtentWith(geom.boundingBox()) layer = loadLayerNoCrsDialog( "Point?crs=%s&field=changetype:string" % self.crs.authid(), "points", "memory") pr = layer.dataProvider() feats = [] for coords in self.data: coord = coords[0] or coords[1] feat = QgsFeature() x, y = coord.strip().split(" ") x, y = (float(x), float(y)) pt = QgsGeometry.fromPoint(QgsPoint(x, y)) feat.setGeometry(pt) if coords[0] is None: changetype = "A" elif coords[1] is None: changetype = "R" else: changetype = "U" feat.setAttributes([changetype]) feats.append(feat) pr.addFeatures(feats) layer.loadNamedStyle(pointsStyle) QgsMapLayerRegistry.instance().addMapLayer(layer, False) layers.append(layer) self.mapLayers = [QgsMapCanvasLayer(lay) for lay in layers] self.canvas.setLayerSet(self.mapLayers) self.canvas.setExtent(extent) self.canvas.refresh() def reject(self): QDialog.reject(self)
class VersionViewerDialog(BASE, WIDGET): def __init__(self, repo, path): super(VersionViewerDialog, self).__init__(config.iface.mainWindow(), Qt.WindowSystemMenuHint | Qt.WindowTitleHint) self.repo = repo self.path = path self.setupUi(self) self.listWidget.itemClicked.connect(self.commitClicked) settings = QSettings() horizontalLayout = QHBoxLayout() horizontalLayout.setSpacing(0) horizontalLayout.setMargin(0) self.mapCanvas = QgsMapCanvas() self.mapCanvas.setCanvasColor(Qt.white) self.mapCanvas.enableAntiAliasing( settings.value("/qgis/enable_anti_aliasing", False, type=bool)) self.mapCanvas.useImageToRender( settings.value("/qgis/use_qimage_to_render", False, type=bool)) action = settings.value("/qgis/wheel_action", 0, type=float) zoomFactor = settings.value("/qgis/zoom_factor", 2, type=float) self.mapCanvas.setWheelAction(QgsMapCanvas.WheelAction(action), zoomFactor) horizontalLayout.addWidget(self.mapCanvas) self.mapWidget.setLayout(horizontalLayout) self.panTool = QgsMapToolPan(self.mapCanvas) self.mapCanvas.setMapTool(self.panTool) versions = repo.log(path=path) if versions: for commit in versions: item = CommitListItem(commit, repo, path) self.listWidget.addItem(item) ''''w = CommitListItemWidget(commit) self.ui.listWidget.setItemWidget(item, w)''' else: raise GeoGigException("The selected feature is not versioned yet") def commitClicked(self): feature = self.listWidget.currentItem().feature geom = None self.attributesTable.setRowCount(len(feature)) for idx, attrname in enumerate(feature): value = feature[attrname] font = QFont() font.setBold(True) font.setWeight(75) item = QTableWidgetItem(attrname) item.setFont(font) self.attributesTable.setItem(idx, 0, item) self.attributesTable.setItem(idx, 1, QTableWidgetItem(str(value))) if geom is None: try: geom = QgsGeometry.fromWkt(value) except: pass self.attributesTable.resizeRowsToContents() self.attributesTable.horizontalHeader().setMinimumSectionSize(150) self.attributesTable.horizontalHeader().setStretchLastSection(True) settings = QSettings() prjSetting = settings.value('/Projections/defaultBehaviour') settings.setValue('/Projections/defaultBehaviour', '') types = ["Point", "LineString", "Polygon"] layers = [] if geom is not None: geomtype = types[int(geom.type())] layer = loadLayerNoCrsDialog(geomtype + "?crs=EPSG:4326", "temp", "memory") pr = layer.dataProvider() feat = QgsFeature() feat.setGeometry(geom) pr.addFeatures([feat]) layer.updateExtents() layer.selectAll() layer.setExtent(layer.boundingBoxOfSelected()) layer.invertSelection() symbol = QgsSymbolV2.defaultSymbol(layer.geometryType()) symbol.setColor(Qt.green) symbol.setAlpha(0.5) if QGis.QGIS_VERSION_INT < 29900: layer.setRendererV2(QgsSingleSymbolRendererV2(symbol)) else: layer.setRenderer(QgsSingleSymbolRenderer(symbol)) self.mapCanvas.setRenderFlag(False) self.mapCanvas.setLayerSet([QgsMapCanvasLayer(layer)]) QgsMapLayerRegistry.instance().addMapLayer(layer, False) self.mapCanvas.setExtent(layer.extent()) self.mapCanvas.setRenderFlag(True) layers.append(layer) else: self.mapCanvas.setLayerSet([]) settings.setValue('/Projections/defaultBehaviour', prjSetting)
class VisorShapefiles(QMainWindow, Ui_MainWindow): def __init__(self): QMainWindow.__init__(self) self.setupUi(self) self.setWindowTitle(u'Visor de Shapefiles') self.canvas = QgsMapCanvas() self.canvas.setCanvasColor(QColor(255, 255, 255)) self.canvas.enableAntiAliasing(True) self.canvas.useImageToRender(False) self.canvas.show() self.layout = QVBoxLayout(self.frame) self.layout.addWidget(self.canvas) self.actionAddLayer = QAction(QIcon('images/mActionAddOgrLayer.svg'), u'Agregar capa', self.frame) self.connect(self.actionAddLayer, SIGNAL('activated()'), self.addLayer) self.actionZoomIn = QAction(QIcon('images/mActionZoomIn.svg'), u'Acercar', self.frame) self.connect(self.actionZoomIn, SIGNAL('activated()'), self.zoomIn) self.actionZoomOut = QAction(QIcon('images/mActionZoomOut.svg'), u'Alejar', self.frame) self.connect(self.actionZoomOut, SIGNAL('activated()'), self.zoomOut) self.actionMove = QAction(QIcon('images/mActionPan.svg'), u'Mover', self.frame) self.connect(self.actionMove, SIGNAL('activated()'), self.pan) self.actionZoomFull = QAction( QIcon('images/mActionZoomFullExtent.svg'), u'Vista Completa', self.frame) self.connect(self.actionZoomFull, SIGNAL('activated()'), self.zoomFull) self.actionPoint = QAction(QIcon('images/mActionCapturePoint.svg'), u'Capturar Punto', self.frame) self.actionPoint.setCheckable(True) self.connect(self.actionPoint, SIGNAL('triggered()'), self.point) self.actionPoly = QAction(QIcon('images/mActionCapturePolygon.svg'), u'Capturar Polígono', self.frame) self.actionPoly.setCheckable(True) self.connect(self.actionPoly, SIGNAL('triggered()'), self.poly) self.toolbar = self.addToolBar('Map') self.toolbar.addAction(self.actionAddLayer) self.toolbar.addAction(self.actionZoomIn) self.toolbar.addAction(self.actionZoomOut) self.toolbar.addAction(self.actionMove) self.toolbar.addAction(self.actionZoomFull) self.toolbar.addAction(self.actionPoint) self.toolbar.addAction(self.actionPoly) self.toolPan = QgsMapToolPan(self.canvas) self.toolZoomIn = QgsMapToolZoom(self.canvas, False) self.toolZoomOut = QgsMapToolZoom(self.canvas, True) self.toolPoint = PointMapTool(self.canvas) self.toolPoly = PolyMapTool(self.canvas) self.toolPoint.setAction(self.actionPoint) self.toolPoly.setAction(self.actionPoly) self.layers = [] def poly(self): self.canvas.setMapTool(self.toolPoly) def point(self): self.canvas.setMapTool(self.toolPoint) def zoomIn(self): self.canvas.setMapTool(self.toolZoomIn) def zoomOut(self): self.canvas.setMapTool(self.toolZoomOut) def pan(self): self.canvas.setMapTool(self.toolPan) def zoomFull(self): self.canvas.zoomToFullExtent() def addLayer(self): layerPath = QFileDialog.getOpenFileName(self, u'Abrir shapefile', '.', 'Shapefiles (*.shp)') layerInfo = QFileInfo(layerPath) layerProvider = 'ogr' # name = '/home/cbdavide/Documentos/Projects/shape-viewer/Colombia/Colombia.shp' # layer = QgsVectorLayer(name, 'ejje', layerProvider) layer = QgsVectorLayer(layerPath, layerInfo.fileName(), layerProvider) if not layer.isValid(): return # Cambiar el color del layer symbol_layer = layer.rendererV2().symbols()[0].symbolLayer(0) symbol_layer.setColor(QColor(176, 251, 163)) QgsMapLayerRegistry.instance().addMapLayer(layer) if self.canvas.layerCount() == 0: self.canvas.setExtent(layer.extent()) self.layers.insert(0, QgsMapCanvasLayer(layer)) self.canvas.setLayerSet(self.layers)
class RenderWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.setupUi() self.active_layers = None # instances of active layers self.crs = None def setupUi(self): gridLayout = QGridLayout(self) gridLayout.setContentsMargins(0, 0, 0, 0) self.canvas = QgsMapCanvas() self.canvas.setCanvasColor(QColor(255, 255, 255)) self.canvas.setStyleSheet("border: 0px;") settings = QSettings() self.canvas.enableAntiAliasing( settings.value("/qgis/enable_anti_aliasing", False, type=bool)) self.setMinimumSize(15, 15) # action pan and zoom self.default_point_tool = QgsMapToolPan(self.canvas) self.canvas.setMapTool(self.default_point_tool, clean=True) gridLayout.addWidget(self.canvas) def refresh(self): if self.active_layers is not None: [ active_layer.layer.reload() for active_layer in self.active_layers if active_layer.is_active ] [ active_layer.layer.triggerRepaint() for active_layer in self.active_layers if active_layer.is_active ] self.canvas.refreshAllLayers() def set_crs(self, crs): self.crs = crs self.update_render_layers() def update_render_layers(self): with block_signals_to(self): # set the CRS of the canvas view if self.crs: # use the crs of thematic raster to edit self.canvas.setDestinationCrs(self.crs) else: # use the crs set in Qgis self.canvas.setDestinationCrs( iface.mapCanvas().mapSettings().destinationCrs()) # get all valid activated layers valid_layers = [ active_layer.layer for active_layer in self.active_layers if active_layer.is_active ] if len(valid_layers) == 0: self.canvas.setLayers([]) self.refresh() return # set to canvas self.canvas.setLayers(valid_layers) # set init extent from other view if any is activated else set layer extent from ThRasE.gui.main_dialog import ThRasEDialog others_extents = [ view_widget.render_widget.canvas.extent() for view_widget in ThRasEDialog.view_widgets if view_widget.is_active and view_widget.render_widget != self and not view_widget.render_widget.canvas.extent().isEmpty() ] if others_extents: # set extent using the extent of the other valid view (or self) with at least one layer extent = others_extents[0] self.update_canvas_to(extent) elif self.canvas.extent().isEmpty(): # first layer to render # set the extent using the extent of the Qgis project but first transform the crs if it is different new_layer = valid_layers[0] transform = QgsCoordinateTransform( new_layer.crs(), self.canvas.mapSettings().destinationCrs(), QgsProject.instance()) new_extent = transform.transformBoundingBox(new_layer.extent()) self.canvas.setExtent(new_extent) self.refresh() def update_canvas_to(self, new_extent): with block_signals_to(self.canvas): self.canvas.setExtent(new_extent) self.refresh()
import os from qgis.core import QgsProject from qgis.core.contextmanagers import qgisapp from PyQt4.QtCore import QFileInfo # Get all layer names allLayers = QgsMapLayerRegistry.instance().mapLayers() for name,layer in allLayers.iteritems(): print layer.name() #show and set map canvas canvas = QgsMapCanvas() canvas.setCanvasColor(Qt.white) #canvas.setCanvasColor(Qt.red) canvas.enableAntiAliasing(True) # set extent to the extent of our layer canvas.setExtent(baselayer.extent()) # Load our project bridge = QgsLayerTreeMapCanvasBridge(QgsProject.instance().layerTreeRoot(), canvas) #QgsProject.instance().read(QFileInfo(project_path)) bridge.setCanvasLayers() canvas.show() #---------------------------------------------------------------------------------------------------------------------------------------- #Part 2. Select local .shp file and load as vector layer #---------------------- from PyQt4.QtCore import *
class ViewerWnd(QMainWindow): def __init__(self, app, dictOpts): QMainWindow.__init__(self) self.canvas = QgsMapCanvas() self.canvas.setCanvasColor(Qt.white) self.canvas.useImageToRender(True) self.canvas.enableAntiAliasing(True) self.setCentralWidget(self.canvas) actionZoomIn = QAction(QIcon(imgs_dir + "mActionZoomIn.png"), QString("Zoom in"), self) actionZoomOut = QAction(QIcon(imgs_dir + "mActionZoomOut.png"), QString("Zoom out"), self) actionPan = QAction(QIcon(imgs_dir + "mActionPan.png"), QString("Pan"), self) actionZoomIn.setCheckable(True) actionZoomOut.setCheckable(True) actionPan.setCheckable(True) self.connect(actionZoomIn, SIGNAL("triggered()"), self.zoomIn) self.connect(actionZoomOut, SIGNAL("triggered()"), self.zoomOut) self.connect(actionPan, SIGNAL("triggered()"), self.pan) # Create the toolbar self.toolbar = self.addToolBar("Map tools") self.toolbar.addAction(actionZoomIn) self.toolbar.addAction(actionZoomOut) self.toolbar.addAction(actionPan) # Create the map tools self.toolPan = QgsMapToolPan(self.canvas) self.toolPan.setAction(actionPan) self.toolZoomIn = QgsMapToolZoom(self.canvas, False) # false = in self.toolZoomIn.setAction(actionZoomIn) self.toolZoomOut = QgsMapToolZoom(self.canvas, True) # true = out self.toolZoomOut.setAction(actionZoomOut) # Create the statusbar self.statusbar = QStatusBar(self) self.statusbar.setObjectName("statusbar") self.setStatusBar(self.statusbar) self.lblXY = QLabel() self.lblXY.setFrameStyle(QFrame.Box) self.lblXY.setMinimumWidth(170) self.lblXY.setAlignment(Qt.AlignCenter) self.statusbar.setSizeGripEnabled(False) self.statusbar.addPermanentWidget(self.lblXY, 0) self.lblScale = QLabel() self.lblScale.setFrameStyle(QFrame.StyledPanel) self.lblScale.setMinimumWidth(140) self.statusbar.addPermanentWidget(self.lblScale, 0) self.createLegendWidget() # Create the legend widget self.connect(app, SIGNAL("loadPgLayer"), self.loadLayer) self.connect(self.canvas, SIGNAL("scaleChanged(double)"), self.changeScale) self.connect(self.canvas, SIGNAL("xyCoordinates(const QgsPoint&)"), self.updateXY) self.pan() self.layerSRID = "" self.loadLayer(dictOpts) def zoomIn(self): self.canvas.setMapTool(self.toolZoomIn) def zoomOut(self): self.canvas.setMapTool(self.toolZoomOut) def pan(self): self.canvas.setMapTool(self.toolPan) def createLegendWidget(self): """ Create the map legend widget and associate to the canvas """ self.legend = Legend(self) self.legend.setCanvas(self.canvas) self.legend.setObjectName("theMapLegend") self.LegendDock = QDockWidget("Layers", self) self.LegendDock.setObjectName("legend") # self.LegendDock.setAllowedAreas( Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea ) self.LegendDock.setWidget(self.legend) self.LegendDock.setContentsMargins(0, 0, 0, 0) self.addDockWidget(Qt.BottomDockWidgetArea, self.LegendDock) def loadLayer(self, dictOpts): print "I: Loading the layer..." self.layerSRID = dictOpts["srid"] # To access the SRID when querying layer properties if not self.isActiveWindow(): self.activateWindow() self.raise_() if dictOpts["type"] == "vector": # QGIS connection uri = QgsDataSourceURI() uri.setConnection(dictOpts["-h"], dictOpts["-p"], dictOpts["-d"], dictOpts["-U"], dictOpts["-W"]) uri.setDataSource(dictOpts["-s"], dictOpts["-t"], dictOpts["-g"]) layer = QgsVectorLayer(uri.uri(), dictOpts["-s"] + "." + dictOpts["-t"], "postgres") elif dictOpts["type"] == "raster": connString = "PG: dbname=%s host=%s user=%s password=%s port=%s schema=%s table=%s" % ( dictOpts["-d"], dictOpts["-h"], dictOpts["-U"], dictOpts["-W"], dictOpts["-p"], dictOpts["-s"], dictOpts["-t"], ) layer = QgsRasterLayer(connString, dictOpts["-s"] + "." + dictOpts["-t"]) layer.setNoDataValue(-32768) layer.rasterTransparency().initializeTransparentPixelList(-32768) if layer.isValid(): if self.canvas.layerCount() == 0: self.canvas.setExtent(layer.extent()) if dictOpts["srid"] != "-1": print "I: Map SRS (EPSG): %s" % dictOpts["srid"] self.canvas.setMapUnits(layer.srs().mapUnits()) else: print "I: Unknown Reference System" self.canvas.setMapUnits(0) # 0: QGis.Meters QgsMapLayerRegistry.instance().addMapLayer(layer) def getLayerProperties(self, l): """ Create a layer-properties string (l:layer)""" print "I: Generating layer properties..." if l.type() == 0: # Vector wkbType = [ "WKBUnknown", "WKBPoint", "WKBLineString", "WKBPolygon", "WKBMultiPoint", "WKBMultiLineString", "WKBMultiPolygon", "WKBNoGeometry", "WKBPoint25D", "WKBLineString25D", "WKBPolygon25D", "WKBMultiPoint25D", "WKBMultiLineString25D", "WKBMultiPolygon25D", ] properties = ( "Source: %s\n" "Geometry type: %s\n" "Number of features: %s\n" "Number of fields: %s\n" "SRS (EPSG): %s\n" "Extent: %s " % ( l.source(), wkbType[l.wkbType()], l.featureCount(), l.dataProvider().fieldCount(), self.layerSRID, l.extent().toString(), ) ) elif l.type() == 1: # Raster rType = ["GrayOrUndefined (single band)", "Palette (single band)", "Multiband"] properties = ( "Source: %s\n" "Raster type: %s\n" "Width-Height (pixels): %sx%s\n" "Bands: %s\n" "SRS (EPSG): %s\n" "Extent: %s" % ( l.source(), rType[l.rasterType()], l.width(), l.height(), l.bandCount(), self.layerSRID, l.extent().toString(), ) ) return properties def changeScale(self, scale): self.lblScale.setText("Scale 1:" + formatNumber(scale)) def updateXY(self, p): if self.canvas.mapUnits() == 2: # Degrees self.lblXY.setText(formatToDegrees(p.x()) + " | " + formatToDegrees(p.y())) else: # Unidad lineal self.lblXY.setText(formatNumber(p.x()) + " | " + formatNumber(p.y()) + "")
class DiviPluginHistoryDialog(QDialog, FORM_CLASS): def __init__(self, plugin, parent=None): """Constructor.""" super(DiviPluginHistoryDialog, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.plugin = plugin #self.iface = plugin.iface self.setupUi(self) self.initGui() def initGui(self): #Models self.tblChanges.setModel( ChangeModel() ) proxyChanges = HistoryProxyModel() proxyChanges.setSourceModel( HistoryModel() ) self.tblHistory.setModel( proxyChanges ) #Signals self.plugin.tvIdentificationResult.model().sourceModel().on_history.connect( self.historyChanged ) self.tblHistory.selectionModel().currentChanged.connect( self.currentHistoryChanged ) #Widgets settings = QSettings() self.mapCanvas = QgsMapCanvas(self.vSplitter) self.mapCanvas.setDestinationCrs( QgsCoordinateReferenceSystem('EPSG:4326') ) zoomFactor = settings.value( "/qgis/zoom_factor", 2.0, type=float ) action = settings.value( "/qgis/wheel_action", 0, type=int) self.mapCanvas.setWheelFactor( zoomFactor ) self.mapCanvas.enableAntiAliasing( settings.value( "/qgis/enable_anti_aliasing", False, type=bool )) #self.mapCanvas.useImageToRender( settings.value( "/qgis/use_qimage_to_render", False, type=bool )) self.toolPan = QgsMapToolPan( self.mapCanvas ) self.mapCanvas.setMapTool( self.toolPan ) #Canvas items self.new_geometry = QgsRubberBand(self.mapCanvas) self.new_geometry.setWidth(2) self.new_geometry.setIcon( QgsRubberBand.ICON_CIRCLE ) g = QColor(0, 128, 0, 100) self.new_geometry.setColor( g ) self.old_geometry = QgsRubberBand(self.mapCanvas) self.old_geometry.setWidth(2) self.old_geometry.setIcon( QgsRubberBand.ICON_CIRCLE ) r = QColor(255, 0, 0, 100) self.old_geometry.setColor( r ) def show(self, data=[]): model = self.tblHistory.model().sourceModel() model.addItems(data) if data: self.tblHistory.selectionModel().setCurrentIndex( model.index(0,0), QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows ) super(DiviPluginHistoryDialog, self).show() def historyChanged(self): """ Reaload data if window is visible """ if self.isVisible(): self.plugin.showHistoryDialog() def currentHistoryChanged(self, current, previous): self.new_geometry.reset() self.old_geometry.reset() self.tblChanges.model().removeRows() if not current.isValid(): return item = current.data(Qt.UserRole) if item is None: data = {} else: data = current.data(Qt.UserRole).getDetails() with SetLocale_CtxDec(): extent = None if data.get('new_geometry'): wkt = CreateGeometryFromJson( json.dumps(data['new_geometry']) ).ExportToWkt() geom = QgsGeometry.fromWkt( wkt ) l = QgsVectorLayer('Point?crs=epsg:4326', 'asd', 'memory') self.new_geometry.setToGeometry( geom, l ) extent = QgsRectangle(geom.boundingBox()) if data.get('old_geometry'): wkt = CreateGeometryFromJson( json.dumps(data['old_geometry']) ).ExportToWkt() geom = QgsGeometry.fromWkt( wkt ) l = QgsVectorLayer('Point?crs=epsg:4326', 'asd', 'memory') self.old_geometry.setToGeometry( geom, l ) if extent is None: extent = QgsRectangle(geom.boundingBox()) else: extent.combineExtentWith( geom.boundingBox() ) if extent is not None: extent.grow(0.01) self.mapCanvas.setExtent( extent ) self.mapCanvas.refresh() if data.get('what_attributes', []): self.tblChanges.model().insertRows( 0, data.get('what_attributes', []) )
class MyWnd(QMainWindow): def __init__(self, layer): QMainWindow.__init__(self) self.canvas = QgsMapCanvas() self.canvas.show() self.canvas.enableAntiAliasing(True) self.canvas.setCanvasColor(Qt.white) #urlWithParams = 'url=https://sedac.ciesin.columbia.edu:443/geoserver/ows?SERVICE=WMS&layers=ipcc:ipcc-synthetic-vulnerability-climate-2005-2050-2100&format=image/png&crs=EPSG:4326&styles=' #urlWithParams = 'url=https://sedac.ciesin.columbia.edu:443/geoserver/ows?SERVICE=WMS&layers=cartographic:national-boundaries&format=image/png&crs=EPSG:4326&styles=' urlWithParams = 'url=https://sedac.ciesin.columbia.edu:443/geoserver/ows?SERVICE=WMS&layers=other:srtm-elevation-above-sea-level_1km&format=image/png&crs=EPSG:4326&styles=' self.layer = QgsRasterLayer(urlWithParams, 'Climate Vulnerability', 'wms') if not self.layer.isValid(): print("Layer failed to load!") # path_to_ports_layer = "C:/Users/shara/Desktop/Final_Results/User_Scenario.shp" # self.layer = QgsVectorLayer(path_to_ports_layer, "User Scenario", "ogr") # if not self.layer.isValid(): # print("Layer failed to load!") #self.layer = QgsVectorLayer("C:/Users/shara/Desktop/Final_Results/User_Scenario.shp","ogr") #QgsMapLayerRegistry.instance().addMapLayer(self.layer) #QgsProject.instance().addMapLayer(self.layer) self.canvas.setExtent(self.layer.extent()) self.canvas.setLayers([self.layer]) self.setCentralWidget(self.canvas) self.actionPoly = QAction("Draw Rectangle", self) self.actionZoomIn = QAction("Zoom in", self) self.actionZoomOut = QAction("Zoom out", self) self.actionPan = QAction("Pan", self) self.actionPoly.setCheckable(True) self.actionZoomIn.setCheckable(True) self.actionZoomOut.setCheckable(True) self.actionPan.setCheckable(True) self.actionPoly.triggered.connect(self.poly) self.actionZoomIn.triggered.connect(self.zoomIn) self.actionZoomOut.triggered.connect(self.zoomOut) self.actionPan.triggered.connect(self.pan) self.toolbar = self.addToolBar("Canvas actions") self.toolbar.addAction(self.actionPoly) self.toolbar.addAction(self.actionZoomIn) self.toolbar.addAction(self.actionZoomOut) self.toolbar.addAction(self.actionPan) self.toolPoly = RectangleMapTool(self.canvas) self.toolPoly.setAction(self.actionPoly) 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.pan() def poly(self): self.canvas.setMapTool(self.toolPoly) def zoomIn(self): self.canvas.setMapTool(self.toolZoomIn) def zoomOut(self): self.canvas.setMapTool(self.toolZoomOut) def pan(self): self.canvas.setMapTool(self.toolPan)
class MirrorMap(QWidget): def __init__(self, parent, iface): QWidget.__init__(self, parent) self.setAttribute(Qt.WA_DeleteOnClose) self.iface = iface self.layerId2canvasLayer = {} self.canvasLayers = [] self.setupUi() def closeEvent(self, event): # self.scaleFactor.valueChanged.disconnect(self.onExtentsChanged) QObject.disconnect(self.iface.mapCanvas(), SIGNAL("extentsChanged()"), self.onExtentsChanged) QObject.disconnect(self.iface.mapCanvas().mapRenderer(), SIGNAL("destinationCrsChanged()"), self.onCrsChanged) QObject.disconnect(self.iface.mapCanvas().mapRenderer(), SIGNAL("mapUnitsChanged()"), self.onCrsChanged) QObject.disconnect(self.iface.mapCanvas().mapRenderer(), SIGNAL("hasCrsTransformEnabled(bool)"), self.onCrsTransformEnabled) QObject.disconnect(QgsMapLayerRegistry.instance(), SIGNAL("layerWillBeRemoved(QString)"), self.delLayer) QObject.disconnect(self.iface, SIGNAL("currentLayerChanged(QgsMapLayer *)"), self.refreshLayerButtons) self.emit(SIGNAL("closed(PyQt_PyObject)"), self) return QWidget.closeEvent(self, event) def setupUi(self): self.setObjectName("dockablemirrormap_mirrormap") gridLayout = QGridLayout(self) gridLayout.setContentsMargins(0, 0, gridLayout.verticalSpacing(), gridLayout.verticalSpacing()) self.canvas = QgsMapCanvas(self) self.canvas.setCanvasColor(QColor(255, 255, 255)) settings = QSettings() self.canvas.enableAntiAliasing(settings.value("/qgis/enable_anti_aliasing", False, type=bool)) self.canvas.useImageToRender(settings.value("/qgis/use_qimage_to_render", False, type=bool)) self.canvas.setWheelAction(3) gridLayout.addWidget(self.canvas, 0, 0, 1, 5) QObject.connect(self.iface.mapCanvas(), SIGNAL("extentsChanged()"), self.onExtentsChanged) QObject.connect(self.iface.mapCanvas().mapRenderer(), SIGNAL("destinationCrsChanged()"), self.onCrsChanged) QObject.connect(self.iface.mapCanvas().mapRenderer(), SIGNAL("mapUnitsChanged()"), self.onCrsChanged) QObject.connect(self.iface.mapCanvas().mapRenderer(), SIGNAL("hasCrsTransformEnabled(bool)"), self.onCrsTransformEnabled) QObject.connect(QgsMapLayerRegistry.instance(), SIGNAL("layerWillBeRemoved(QString)"), self.delLayer) self.onExtentsChanged() self.onCrsChanged() self.onCrsTransformEnabled(self.iface.mapCanvas().hasCrsTransformEnabled()) def toggleRender(self, enabled): self.canvas.setRenderFlag(enabled) self.canvas.refresh() self.canvas.repaint() def onExtentsChanged(self): try : prevFlag = self.canvas.renderFlag() self.canvas.setRenderFlag(False) self.canvas.setExtent(self.iface.mapCanvas().extent()) # self.canvas.zoomByFactor( self.scaleFactor.value() ) self.canvas.setRenderFlag(prevFlag) self.canvas.repaint() self.canvas.refresh() except Exception: pass def mirror_extent_changed(self): logger.debug(self.canvas.extent()) logger.debug(self.iface.mapCanvas().extent()) if self.canvas.extent() != self.iface.mapCanvas().extent(): self.emit(SIGNAL("extentChanged( QgsRectangle )"), self.canvas.extent()) def onCrsChanged(self): try: prevFlag = self.canvas.renderFlag() self.canvas.setRenderFlag(False) renderer = self.iface.mapCanvas().mapRenderer() self._setRendererCrs(self.canvas.mapRenderer(), self._rendererCrs(renderer)) self.canvas.mapRenderer().setMapUnits(renderer.mapUnits()) self.canvas.setRenderFlag(prevFlag) self.canvas.repaint() self.canvas.refresh() except Exception: pass def onCrsTransformEnabled(self, enabled): try: prevFlag = self.canvas.renderFlag() self.canvas.setRenderFlag(False) self.canvas.mapRenderer().setProjectionsEnabled(enabled) self.canvas.setRenderFlag(prevFlag) self.canvas.repaint() self.canvas.refresh() except Exception: pass def getLayerSet(self): return map(lambda x: self._layerId(x.layer()), self.canvasLayers) def setLayerSet(self, layerIds=None): prevFlag = self.canvas.renderFlag() self.canvas.setRenderFlag(False) if layerIds is None: self.layerId2canvasLayer = {} self.canvasLayers = [] self.canvas.setLayerSet([]) else: for lid in layerIds: self.addLayer(lid) self.onExtentsChanged() self.canvas.setRenderFlag(prevFlag) self.canvas.repaint() self.canvas.refresh() def addLayer(self, layerId = None): if layerId is None: layer = self.iface.activeLayer() else: layer = QgsMapLayerRegistry.instance().mapLayer(layerId) if layer is None: return prevFlag = self.canvas.renderFlag() self.canvas.setRenderFlag(False) # add the layer to the map canvas layer set self.canvasLayers = [] id2cl_dict = {} for l in self.iface.legendInterface().layers(): lid = self._layerId(l) if self.layerId2canvasLayer.has_key(lid): # previously added cl = self.layerId2canvasLayer[ lid ] elif l == layer: # selected layer cl = QgsMapCanvasLayer(layer) else: continue id2cl_dict[ lid ] = cl self.canvasLayers.append(cl) self.layerId2canvasLayer = id2cl_dict self.canvas.setLayerSet(self.canvasLayers) self.onExtentsChanged() self.canvas.setRenderFlag(prevFlag) self.canvas.repaint() self.canvas.refresh() def delLayer(self, layerId=None): if layerId is None: layer = self.iface.activeLayer() if layer is None: return layerId = self._layerId(layer) # remove the layer from the map canvas layer set if layerId not in self.layerId2canvasLayer: return prevFlag = self.canvas.renderFlag() self.canvas.setRenderFlag(False) cl = self.layerId2canvasLayer[ layerId ] if cl is not None: del self.layerId2canvasLayer[ layerId ] self.canvasLayers.remove(cl) self.canvas.setLayerSet(self.canvasLayers) del cl self.onExtentsChanged() self.canvas.setRenderFlag(prevFlag) self.canvas.repaint() self.canvas.refresh() def _layerId(self, layer): if hasattr(layer, 'id'): return layer.id() return layer.getLayerID() def _rendererCrs(self, renderer): if hasattr(renderer, 'destinationCrs'): return renderer.destinationCrs() return renderer.destinationSrs() def _setRendererCrs(self, renderer, crs): if hasattr(renderer, 'setDestinationCrs'): return renderer.setDestinationCrs(crs) return renderer.setDestinationSrs(crs)
class PdfMaker(object): """A generator that takes a QGIS project file and a layout template and makes a pdf.""" def __init__(self, template_path, debug=False): """Constructor. :param template_path: Absolute path to a QGIS composer template file. :type template_path: str """ gui_flag = True self.app = QgsApplication(sys.argv, gui_flag) # Make sure QGIS_PREFIX_PATH is set in your env if needed! self.app.initQgis() if debug: print QgsProviderRegistry.instance().pluginList() self.canvas = QgsMapCanvas() self.canvas.enableAntiAliasing(True) self.template_path = template_path def __del__(self): """Destructor.""" del self.app def _load_template(self): """Load the template. :return: QgsComposition containing the loaded template. :rtype: QgsComposition """ template_file = file(self.template_path) template_content = template_file.read() template_file.close() document = QDomDocument() document.setContent(template_content) composition = QgsComposition(self.canvas.mapSettings()) # You can use this to replace any string like this [key] # in the template with a new value. e.g. to replace # [date] pass a map like this {'date': '1 Jan 2012'} substitution_map = { 'DATE_TIME_START': 'foo', 'DATE_TIME_END': 'bar'} composition.loadFromTemplate(document, substitution_map) return composition def _load_layers(self): """Manually load all the layers for our project. :return: A list of QgsMapLayer instances. :rtype: list """ layers = [] # First the RW layer host = 'db' port = '5432' user = '******' password = '******' dbname = 'gis' uri = QgsDataSourceURI() uri.setConnection(host, port, dbname, user, password) schema = 'public' table = 'flood_mapper_rw' geometry_column = 'geometry' where_clause = '' title = 'RW' uri.setDataSource(schema, table, geometry_column, where_clause) layer = QgsVectorLayer(uri.uri(), title, 'postgres') QgsMapLayerRegistry.instance().addMapLayer(layer, False) canvas_layer = QgsMapCanvasLayer(layer) layers.append(canvas_layer) # Now the JK layer path = './data/jk.shp' title = 'JK' layer = QgsVectorLayer(path, title, 'ogr') QgsMapLayerRegistry.instance().addMapLayer(layer, False) canvas_layer = QgsMapCanvasLayer(layer) layers.append(canvas_layer) return layers def make_pdf(self, pdf_path): """Generate a pdf for the given project and template files. :param pdf_path: Absolute path for the output PDF file. :type pdf_path: str """ layers = self._load_layers() self.canvas.setLayerSet(layers) if self.canvas.layerCount() < 1: print 'No layers loaded from this project, exiting.' return self.canvas.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3857')) self.canvas.setCrsTransformEnabled(True) self.canvas.zoomToFullExtent() print 'Extent: %s' % self.canvas.mapSettings().extent().toString() # self._load_project() composition = self._load_template() # You must set the id in the template map_item = composition.getComposerItemById('map') map_item.setMapCanvas(self.canvas) map_item.zoomToExtent(self.canvas.extent()) # You must set the id in the template legend_item = composition.getComposerItemById('legend') legend_item.updateLegend() composition.refreshItems() composition.exportAsPDF(pdf_path) QgsProject.instance().clear()