Exemple #1
0
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)
Exemple #5
0
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()
Exemple #7
0
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()
Exemple #8
0
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() ) + "" )
Exemple #9
0
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)
Exemple #12
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()
Exemple #13
0
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()
Exemple #14
0
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)
Exemple #15
0
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
Exemple #16
0
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)
Exemple #20
0
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()
Exemple #21
0
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)
Exemple #25
0
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()