class LineDrawer(QgsMapToolEmitPoint): def __init__(self, canvas): # call the parent constructor QgsMapToolEmitPoint.__init__(self, canvas) # store the passed canvas self.canvas = canvas # flag to know whether the tool is performing a drawing operation self.isDrawing = False # create and setup the rubber band to display the line self.rubberBand = QgsRubberBand( self.canvas, False ) # False = not a polygon = a line self.rubberBand.setColor( Qt.red ) self.rubberBand.setWidth( 1 ) def clear(self): self.rubberBand.reset( False ) # False = not a polygon = a line def delete(self): self.canvas.scene().removeItem( self.rubberBand ) def canvasPressEvent(self, e): # which the mouse button? if e.button() == Qt.LeftButton: # left click # if it's the first left click, clear the rubberband if not self.isDrawing: self.clear() # we are drawing now self.isDrawing = True # convert the clicked position to map coordinates point = self.toMapCoordinates( e.pos() ) # add a new point to the rubber band self.rubberBand.addPoint( point, True ) # True = display updates on the canvas # and finally show the rubber band self.rubberBand.show() elif e.button() == Qt.RightButton: # right click, stop drawing self.isDrawing = False # emit a signal self.emit( SIGNAL("editingFinished()") ) def canvasMoveEvent(self, e): # check if it's already drawing if not self.isDrawing: return # convert the mouse position to map coordinates point = self.toMapCoordinates( e.pos() ) # move the last point to the new coordinates self.rubberBand.movePoint( point ) def geometry(self): return self.rubberBand.asGeometry()
def _draw_rubberband(self, extent, colour, width=2): """ Draw a rubber band on the canvas. .. versionadded: 2.2.0 :param extent: Extent that the rubber band should be drawn for. :type extent: QgsRectangle :param colour: Colour for the rubber band. :type colour: QColor :param width: The width for the rubber band pen stroke. :type width: int :returns: Rubber band that should be set to the extent. :rtype: QgsRubberBand """ rubberband = QgsRubberBand( self.iface.mapCanvas(), geometryType=QGis.Line) rubberband.setColor(colour) rubberband.setWidth(width) update_display_flag = False point = QgsPoint(extent.xMinimum(), extent.yMinimum()) rubberband.addPoint(point, update_display_flag) point = QgsPoint(extent.xMaximum(), extent.yMinimum()) rubberband.addPoint(point, update_display_flag) point = QgsPoint(extent.xMaximum(), extent.yMaximum()) rubberband.addPoint(point, update_display_flag) point = QgsPoint(extent.xMinimum(), extent.yMaximum()) rubberband.addPoint(point, update_display_flag) point = QgsPoint(extent.xMinimum(), extent.yMinimum()) update_display_flag = True rubberband.addPoint(point, update_display_flag) return rubberband
class QgepMapTool( QgsMapTool ): ''' Base class for all the map tools ''' highLightedPoints = [] logger = logging.getLogger( __name__ ) def __init__( self, iface, button ): QgsMapTool.__init__( self, iface.mapCanvas() ) self.canvas = iface.mapCanvas() self.cursor = QCursor( Qt.CrossCursor ) self.button = button self.msgBar = iface.messageBar() settings = QSettings() currentProfileColor = settings.value( "/QGEP/CurrentProfileColor", u'#FF9500' ) self.rubberBand = QgsRubberBand( self.canvas ) self.rubberBand.setColor( QColor( currentProfileColor ) ) self.rubberBand.setWidth( 3 ) # Gets called when the tool is activated def activate( self ): QgsMapTool.activate( self ) self.canvas.setCursor( self.cursor ) self.button.setChecked( True ) # Gets called whenever the tool is deactivated directly or indirectly def deactivate( self ): QgsMapTool.deactivate( self ) self.button.setChecked( False ) def isZoomTool( self ): return False def setCursor( self, cursor ): self.cursor = QCursor( cursor ) #=========================================================================== # Events #=========================================================================== def canvasMoveEvent( self, event ): try: self.mouseMoved( event ) except AttributeError: pass def canvasReleaseEvent( self, event ): if event.button() == Qt.RightButton: self.rightClicked ( event ) else: self.leftClicked( event ) def canvasDoubleClickEvent( self, event ): try: self.doubleClicked( event ) except AttributeError: pass
def _draw_rubberband(self, geometry, colour, width): """Draw a rubber band on the canvas. .. versionadded: 2.2.0 :param geometry: Extent that the rubber band should be drawn for. :type geometry: QgsGeometry :param colour: Colour for the rubber band. :type colour: QColor :param width: The width for the rubber band pen stroke. :type width: int :returns: Rubber band that should be set to the extent. :rtype: QgsRubberBand """ # noinspection PyArgumentList rubber_band = QgsRubberBand( self._map_canvas, geometryType=QGis.Polygon) rubber_band.setBrushStyle(Qt.NoBrush) rubber_band.setColor(colour) rubber_band.setWidth(width) rubber_band.setToGeometry(geometry, None) return rubber_band
class PlaceMarkerMapTool(QgsMapToolEmitPoint): ''' classdocs ''' def __init__(self, canvas): ''' Constructor ''' self.canvas = canvas super(PlaceMarkerMapTool, self).__init__(self.canvas) self.rubberBand = QgsRubberBand(self.canvas, QGis.Polygon) self.rubberBand.setColor(Qt.red) self.rubberBand.setWidth(1) self.reset() def reset(self): self.rubberBand.reset(QGis.Polygon) def canvasReleaseEvent(self, e): p1 = self.canvas.getCoordinateTransform().toMapCoordinates(e.x() - 2, e.y() - 2) p2 = self.canvas.getCoordinateTransform().toMapCoordinates(e.x() + 2, e.y() - 2) p3 = self.canvas.getCoordinateTransform().toMapCoordinates(e.x() + 2, e.y() + 2) p4 = self.canvas.getCoordinateTransform().toMapCoordinates(e.x() - 2, e.y() + 2) self.reset() self.rubberBand.addPoint(p1, False) self.rubberBand.addPoint(p2, False) self.rubberBand.addPoint(p3, False) self.rubberBand.addPoint(p4, True) self.rubberBand.show() def deactivate(self): self.reset() super(PlaceMarkerMapTool, self).deactivate()
def loadLines(self, lines, points, markers, suffix): no = self.project.readEntry("TUVIEW", "lines{0}no".format(suffix))[0] if no: no = int(no) for i in range(no): a = self.project.readEntry("TUVIEW", 'lines{0}x{1}'.format(suffix, i))[0] a = a.split('~~') b = self.project.readEntry("TUVIEW", 'lines{0}y{1}'.format(suffix, i))[0] b = b.split('~~') points.clear() for j in range(len(a)): x = float(a[j]) y = float(b[j]) point = QgsPoint(x, y) points.append(point) if i + 1 == no: marker = QgsVertexMarker(self.tuView.canvas) if suffix == 'cs': marker.setColor(Qt.red) marker.setIconSize(10) marker.setIconType(QgsVertexMarker.ICON_BOX) else: # 'q' marker.setColor(Qt.blue) marker.setIconSize(12) marker.setIconType(QgsVertexMarker.ICON_DOUBLE_TRIANGLE) marker.setCenter(QgsPointXY(point)) markers.append(marker) line = QgsRubberBand(self.tuView.canvas, False) line.setWidth(2) if suffix == 'cs': line.setColor(QColor(Qt.red)) else: # 'q' line.setColor(QColor(Qt.blue)) line.setToGeometry(QgsGeometry.fromPolyline(points), None) lines.append(line)
def zoomAndShowWKT(self, wtk): geom = QgsGeometry.fromWkt(wtk) canvas = self.iface.mapCanvas() self.clear() r = QgsRubberBand(canvas, geom.type() == 3 ) r.setToGeometry(geom, None) r.setColor(QColor(0, 0, 255)) r.setFillColor(QColor(0, 0, 255, 50)) r.setWidth(3) pt = geom.pointOnSurface().asPoint() m = QgsVertexMarker(canvas) m.setCenter( pt ) m.setColor(QColor(0, 0, 255)) m.setIconSize(5) m.setIconType(QgsVertexMarker.ICON_BOX) m.setPenWidth(3) if geom.type() == 3 or geom.type() == 2: rec = geom.boundingBox() canvas.setExtent(rec) else: self.moveMapTo( pt[0], pt[1], 0) self.graphics.append(r) self.graphics.append(m) self._refresh_layers()
class GetPointMapTool(QgsMapToolEmitPoint): coordCaptured = "" def __init__(self, canvas, iface, dockwidget, currentMapTool): self.canvas = canvas self.iface = iface self.currentMapTool = currentMapTool self.dockwidget = dockwidget QgsMapToolEmitPoint.__init__(self, self.canvas) self.rubberBand = QgsRubberBand(self.canvas, QGis.Point) self.rubberBand.setColor(QColor(255,5,5)) self.rubberBand.setWidth(1) self.reset() def reset(self): self.startPoint = self.endPoint = None self.isEmittingPoint = False self.rubberBand.reset(QGis.Polygon) def canvasPressEvent(self, e): self.point = self.toMapCoordinates(e.pos()) self.isEmittingPoint = True self.showPoint(self.point) def canvasReleaseEvent(self, e): self.isEmittingPoint = False self.coordCaptured = self.pointdef() if self.coordCaptured is not None: print "Point:", self.coordCaptured self.coordCaptured = str(self.coordCaptured).strip("(") self.coordCaptured = str(self.coordCaptured).strip(")") self.dockwidget.munLineEdit.setText(self.coordCaptured) self.iface.mapCanvas().setMapTool(self.currentMapTool) def canvasMoveEvent(self, e): if not self.isEmittingPoint: return self.endPoint = self.toMapCoordinates(e.pos()) # self.showRect(self.startPoint, self.endPoint) def showPoint(self, point): self.rubberBand.reset(QGis.Polygon) point1 = QgsPoint(point.x(), point.y()) self.rubberBand.addPoint(point1, False) self.rubberBand.show() def pointdef(self): return QgsPoint(self.point)
def addGraphic(self, geom ): canvas = self.iface.mapCanvas() rBand = QgsRubberBand(canvas, True) self.graphics.append( rBand ) rBand.setToGeometry( geom, None ) rBand.setColor(QtGui.QColor(0,0,255, 70)) if QGis.QGIS_VERSION_INT >= 20600: rBand.setBorderColor( QtGui.QColor(0,0,250, 220) ) rBand.setWidth(3)
class QgepMapToolAddFeature( QgsMapTool ): def __init__(self, iface, layer): QgsMapTool.__init__(self, iface.mapCanvas() ) self.iface = iface self.canvas = iface.mapCanvas() self.layer = layer self.rubberband = QgsRubberBand( iface.mapCanvas(), layer.geometryType() ) self.rubberband.setColor( QColor( "#ee5555" ) ) self.rubberband.setWidth( 2 ) self.tempRubberband = QgsRubberBand( iface.mapCanvas(), layer.geometryType() ) self.tempRubberband.setColor( QColor( "#ee5555" ) ) self.tempRubberband.setWidth( 2 ) self.tempRubberband.setLineStyle(Qt.DotLine) def activate(self): QgsMapTool.activate( self ) self.canvas.setCursor( QCursor( Qt.CrossCursor ) ) pass def deactivate(self): QgsMapTool.deactivate( self ) self.canvas.unsetCursor() pass def isZoomTool( self ): return False #=========================================================================== # Events #=========================================================================== def canvasMoveEvent( self, event ): self.mouseMoved( event ) def canvasReleaseEvent( self, event ): if event.button() == Qt.RightButton: self.rightClicked ( event ) else: self.leftClicked( event ) def leftClicked(self, event): mousePos = self.canvas.getCoordinateTransform().toMapCoordinates( event.pos().x(), event.pos().y() ) self.rubberband.addPoint( mousePos ) self.tempRubberband.reset() def rightClicked(self, event): f = QgsFeature( self.layer.pendingFields() ) f.setGeometry( self.rubberband.asGeometry() ) dlg = self.iface.getFeatureForm( self.layer, f ) dlg.setIsAddDialog(True) dlg.exec_() self.rubberband.reset() self.tempRubberband.reset() def mouseMoved(self, event): mousePos = self.canvas.getCoordinateTransform().toMapCoordinates( event.pos().x(), event.pos().y() ) self.tempRubberband.movePoint( mousePos )
def _setRubberBandMarker(self, geom): m = QgsRubberBand(self.qgisIface.mapCanvas(), False) # not polygon if QgsWkbTypes.geometryType(geom.wkbType()) == QgsWkbTypes.LineGeometry: linegeom = geom elif QgsWkbTypes.geometryType(geom.wkbType()) == QgsWkbTypes.PolygonGeometry: linegeom = QgsGeometry.fromPolylineXY(geom.asPolygon()[0]) m.setToGeometry(linegeom, None) m.setColor(QColor(self.config['rubber_color'])) m.setWidth(self.config['rubber_width']) return m
def initRubberLayer(self): if self.rubberLayer: rb = self.rubberLayer rb.reset(True) else: rb = QgsRubberBand(self.iface.mapCanvas(), True) rb.setColor(QColor(255, 0, 255, 255)) rb.setWidth(3) rb.setFillColor(QColor(255, 0, 255, 50)) self.rubberLayer = rb
class CurrentSelection(QgsRubberBand): """ Position marker for the current location in the viewer. """ class AniObject(QObject): def __init__(self, band): super(CurrentSelection.AniObject, self).__init__() self.color = QColor() @pyqtProperty(int) def alpha(self): return self.color.alpha() @alpha.setter def alpha(self, value): self.color.setAlpha(value) def __init__(self, canvas): super(CurrentSelection, self).__init__(canvas) self.outline = QgsRubberBand(canvas) self.outline.setBrushStyle(Qt.NoBrush) self.outline.setWidth(5) self.outline.setIconSize(30) self.aniobject = CurrentSelection.AniObject(self) self.anim = QPropertyAnimation(self.aniobject, "alpha") self.anim.setDuration(500) self.anim.setStartValue(50) self.anim.setEndValue(100) self.anim.valueChanged.connect(self.value_changed) def setOutlineColour(self, color): self.outline.setColor(color) def setToGeometry(self, geom, layer): super(CurrentSelection, self).setToGeometry(geom, layer) self.outline.setToGeometry(geom, layer) self.anim.stop() self.anim.start() def reset(self, geomtype=QGis.Line): super(CurrentSelection, self).reset(geomtype) self.outline.reset(geomtype) self.anim.stop() def value_changed(self, value): self.setColor(self.aniobject.color) self.update() def setColor(self, color): self.aniobject.color = color super(CurrentSelection, self).setColor(color)
def drawManyPaths(self, rows, columns, con, args, geomType, canvasItemList, mapCanvas): ''' draws multi line string on the mapCanvas. ''' resultPathsRubberBands = canvasItemList['paths'] rubberBand = None cur_path_id = None for row in rows: cur2 = con.cursor() result_path_id = str(row[columns[0]]) args['result_node_id'] = sql.Literal(row[columns[1]]) args['result_edge_id'] = sql.Literal(row[columns[2]]) if result_path_id != cur_path_id: cur_path_id = result_path_id if rubberBand: resultPathsRubberBands.append(rubberBand) rubberBand = None rubberBand = QgsRubberBand(mapCanvas, Utils.getRubberBandType(False)) rubberBand.setColor(QColor(255, 0, 0, 128)) rubberBand.setWidth(4) if row[columns[2]] != -1: query2 = sql.SQL(""" SELECT ST_AsText({transform_s}{geometry}{transform_e}) FROM {edge_schema}.{edge_table} WHERE {source} = {result_node_id} AND {id} = {result_edge_id} UNION SELECT ST_AsText({transform_s}ST_Reverse({geometry}){transform_e}) FROM {edge_schema}.{edge_table} WHERE {target} = {result_node_id} AND {id} = {result_edge_id} """).format(**args).as_string(con) cur2.execute(query2) row2 = cur2.fetchone() geom = QgsGeometry().fromWkt(str(row2[0])) if geom.wkbType() == QgsWkbTypes.MultiLineString: for line in geom.asMultiPolyline(): for pt in line: rubberBand.addPoint(pt) elif geom.wkbType() == QgsWkbTypes.LineString: for pt in geom.asPolyline(): rubberBand.addPoint(pt) if rubberBand: resultPathsRubberBands.append(rubberBand) rubberBand = None
class DrawPolygon(QgsMapTool): '''Outil de sélection par polygone, tiré de selectPlusFr''' selectionDone = pyqtSignal() move = pyqtSignal() def __init__(self, iface, couleur): canvas = iface.mapCanvas() QgsMapTool.__init__(self, canvas) self.canvas = canvas self.iface = iface self.status = 0 self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rb.setColor(couleur) return None def keyPressEvent(self, e): if e.matches(QKeySequence.Undo): if self.rb.numberOfVertices() > 1: self.rb.removeLastPoint() def canvasPressEvent(self, e): if e.button() == Qt.LeftButton: if self.status == 0: self.rb.reset(QgsWkbTypes.PolygonGeometry) self.status = 1 self.rb.addPoint(self.toMapCoordinates(e.pos())) else: if self.rb.numberOfVertices() > 2: self.status = 0 self.selectionDone.emit() else: self.reset() return None def canvasMoveEvent(self, e): if self.rb.numberOfVertices() > 0 and self.status == 1: self.rb.removeLastPoint(0) self.rb.addPoint(self.toMapCoordinates(e.pos())) self.move.emit() return None def reset(self): self.status = 0 self.rb.reset(True) def deactivate(self): self.rb.reset(True) QgsMapTool.deactivate(self)
def _createRubberBand(self, geometryType, moveBand=False): settings = QSettings() rb = QgsRubberBand(self.canvas(), geometryType) rb.setWidth(int(settings.value('/qgis/digitizing/line_width', 1))) color = QColor(int(settings.value('/qgis/digitizing/line_color_red', 255)), int(settings.value('/qgis/digitizing/line_color_green', 0)), int(settings.value('/qgis/digitizing/line_color_blue', 0))) myAlpha = int(settings.value('/qgis/digitizing/line_color_alpha', 200)) / 255.0 if (moveBand): myAlpha = myAlpha * float(settings.value('/qgis/digitizing/line_color_alpha_scale', 0.75)) rb.setLineStyle(Qt.DotLine) if (geometryType == QGis.Polygon): color.setAlphaF(myAlpha) color.setAlphaF(myAlpha) rb.setColor(color) rb.show() return rb
class lineTool(QgsMapTool): def __init__(self, iface, callback): QgsMapTool.__init__(self,iface.mapCanvas()) self.iface = iface self.canvas = iface.mapCanvas() self.cursor = QCursor(Qt.CrossCursor) self.callback = callback self.rubberBand = QgsRubberBand(self.canvas, False) self.points = [] self.rubberBand.setColor(Qt.red) self.rubberBand.setWidth(1.6) def canvasReleaseEvent(self,event): if event.button() == Qt.RightButton: self.points.append(QgsPoint( self.toMapCoordinates( event.pos()) ) ) if len(self.points) <= 1 :return self.rubberBand.setToGeometry( QgsGeometry.fromPolyline(self.points), None ) self.callback( self.rubberBand ) QgsMapTool.deactivate(self) else: self.points.append(QgsPoint( self.toMapCoordinates(event.pos()) ) ) if len(self.points) <= 1 : return self.rubberBand.setToGeometry( QgsGeometry.fromPolyline(self.points), None ) def canvasDoubleClickEvent(self,event): self.points.append(QgsPoint( self.toMapCoordinates( event.pos()) )) if len(self.points) <= 1 : return self.rubberBand.setToGeometry( QgsGeometry.fromPolyline(self.points), None ) self.callback( self.rubberBand ) QgsMapTool.deactivate(self) def activate(self): QgsMapTool.activate(self) self.canvas.setCursor(self.cursor) def isZoomTool(self): return False def setCursor(self,cursor): self.cursor = QCursor(cursor)
class SelectPoint(QgsMapTool): select = pyqtSignal() selectionDone = pyqtSignal() def __init__(self, iface, couleur): canvas = iface.mapCanvas() QgsMapTool.__init__(self, canvas) self.canvas = canvas self.iface = iface self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rb.setColor(couleur) self.rbSelect = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) return None def canvasReleaseEvent(self, e): if e.button() == Qt.LeftButton: self.rbSelect.reset(QgsWkbTypes.PolygonGeometry) cp = self.toMapCoordinates( QPoint(e.pos().x() - 5, e.pos().y() - 5)) self.rbSelect.addPoint(cp) cp = self.toMapCoordinates( QPoint(e.pos().x() + 5, e.pos().y() - 5)) self.rbSelect.addPoint(cp) cp = self.toMapCoordinates( QPoint(e.pos().x() + 5, e.pos().y() + 5)) self.rbSelect.addPoint(cp) cp = self.toMapCoordinates( QPoint(e.pos().x() - 5, e.pos().y() + 5)) self.rbSelect.addPoint(cp) self.select.emit() else: self.selectionDone.emit() return None def reset(self): self.rb.reset(QgsWkbTypes.PolygonGeometry) self.rbSelect.reset(QgsWkbTypes.PolygonGeometry) def deactivate(self): self.rb.reset(QgsWkbTypes.PolygonGeometry) self.rbSelect.reset(QgsWkbTypes.PolygonGeometry) QgsMapTool.deactivate(self)
class RubberBandResultRenderer(): def __init__(self, iface, color = QColor('magenta'), size = 12): self.iface = iface self.rb = QgsRubberBand(self.iface.mapCanvas(), QGis.Point) self.rb.setColor(color) self.rb.setIconSize(size) self.srs_wgs84 = QgsCoordinateReferenceSystem(4326) self.transformation = QgsCoordinateTransform(self.srs_wgs84, self.srs_wgs84) def show_point(self, point, center=False): #check srs if self.need_transform(): point = self.transform_point(point) self.rb.addPoint(point) if center: self.center_to_point(point) def clear(self): self.rb.reset(QGis.Point) def need_transform(self): return self.iface.mapCanvas().mapRenderer().destinationCrs().postgisSrid() != 4326 def transform_point(self, point): dest_srs_id = self.iface.mapCanvas().mapRenderer().destinationCrs().srsid() self.transformation.setDestCRSID(dest_srs_id) try: return self.transformation.transform(point) except: print 'Error on transform!' # DEBUG! need message??? return def center_to_point(self, point): canvas = self.iface.mapCanvas() new_extent = QgsRectangle(canvas.extent()) new_extent.scale(1, point) canvas.setExtent(new_extent) canvas.refresh()
def createMoveTrack(self, line=False, color=QColor(255, 71, 25, 170), width=0.2): '''Create move track. :param line: Flag indicating if geometry to draw is a line (True) or a polygon(False). :type line: bool :param color: Color of line. :type color: QColor :param width: Width of line. :type width: int :return: Created rubber band. :rtype: QgsRubberBand ''' moveTrack = QgsRubberBand(self.canvas, line) moveTrack.setColor(color) moveTrack.setWidth(width) return moveTrack
class FreehandPolygonMaptool(QgsMapTool, QObject): trigger = pyqtSignal(QgsGeometry) def __init__(self, canvas): QgsMapTool.__init__(self,canvas) self.canvas = canvas self.rb = QgsRubberBand(canvas, QgsWkbTypes.PolygonGeometry) self.rb.setColor(QColor(255, 0, 0, 50)) def activate(self): self.rb.reset(QgsWkbTypes.PolygonGeometry) def deactivate(self): self.rb.reset(QgsWkbTypes.PolygonGeometry) def canvasMoveEvent(self, ev): worldPoint = QgsMapToPixel.toMapCoordinates(self.canvas.getCoordinateTransform(), ev.pos().x(), ev.pos().y()) self.rb.movePoint(worldPoint) def canvasPressEvent(self, ev): if ev.button() == Qt.LeftButton: """ Add a new point to the rubber band """ worldPoint = QgsMapToPixel.toMapCoordinates(self.canvas.getCoordinateTransform(), ev.pos().x(), ev.pos().y()) self.rb.addPoint(worldPoint) elif ev.button() == Qt.RightButton: """ Send back the geometry to the calling class """ self.trigger.emit(self.rb.asGeometry()) def isZoomTool(self): return False def isTransient(self): return False def isEditTool(self): return False
def highlight(self,geometry): def processEvents(): try: qApp.processEvents() except: QApplication.processEvents() highlight = QgsRubberBand(self.canvas, geometry.type()) highlight.setColor(QColor("#36AF6C")) highlight.setFillColor(QColor("#36AF6C")) highlight.setWidth(2) highlight.setToGeometry(geometry,self.canvas.currentLayer()) processEvents() sleep(.1) highlight.hide() processEvents() sleep(.1) highlight.show() processEvents() sleep(.1) highlight.reset() processEvents()
class DistanceDialog(QDialog, Ui_place_distance): def __init__(self, distance, canvas): QDialog.__init__(self) self.setupUi(self) self.settings = MySettings() # this is a reference, distance observation is modified in outer class self.distance = distance self.rubber = QgsRubberBand(canvas) self.rubber.setColor(self.settings.value("rubberColor")) self.rubber.setIconSize(self.settings.value("rubberSize")) self.x.setText("%.3f" % distance.point.x()) self.y.setText("%.3f" % distance.point.y()) self.observation.setValue(distance.observation) self.precision.setValue(distance.precision) self.observation.selectAll() @pyqtSignature("on_observation_valueChanged(double)") def on_observation_valueChanged(self, v): self.distance.observation = v self.rubber.setToGeometry(self.distance.geometry(), None) @pyqtSignature("on_precision_valueChanged(double)") def on_precision_valueChanged(self, v): self.distance.precision = v def accept(self): self.rubber.reset() QDialog.accept(self) def reject(self): self.rubber.reset() QDialog.reject(self) def closeEvent(self, e): self.rubber.reset()
class DrawPoint(QgsMapTool): selectionDone = pyqtSignal() def __init__(self, iface, couleur): canvas = iface.mapCanvas() QgsMapTool.__init__(self, canvas) self.canvas = canvas self.iface = iface self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rb.setColor(couleur) self.rb.setWidth(3) def canvasReleaseEvent(self, e): if e.button() == Qt.LeftButton: self.rb.addPoint(self.toMapCoordinates(e.pos())) self.selectionDone.emit() def reset(self): self.rb.reset(QgsWkbTypes.PointGeometry) def deactivate(self): self.rb.reset(QgsWkbTypes.PointGeometry) QgsMapTool.deactivate(self)
class RectangleMapTool(QgsMapToolEmitPoint): def __init__(self, canvas): QgsMapToolEmitPoint.__init__(self, canvas) self.canvas = canvas self.rubberBand = QgsRubberBand(canvas, QGis.Polygon) self.rubberBand.setColor(QColor(255, 0, 0, 180)) self.rubberBand.setWidth(1) self.reset() def reset(self): self.startPoint = self.endPoint = None self.isDrawing = False self.rubberBand.reset(QGis.Polygon) def canvasPressEvent(self, e): self.startPoint = self.toMapCoordinates(e.pos()) self.endPoint = self.startPoint mapSettings = self.canvas.mapSettings( ) if QGis.QGIS_VERSION_INT >= 20300 else self.canvas.mapRenderer() self.mupp = mapSettings.mapUnitsPerPixel() self.rotation = mapSettings.rotation() if QGis.QGIS_VERSION_INT >= 20700 else 0 self.isDrawing = True self.showRect(self.startPoint, self.endPoint) def canvasReleaseEvent(self, e): self.isDrawing = False self.emit(SIGNAL("rectangleCreated()")) def canvasMoveEvent(self, e): if not self.isDrawing: return self.endPoint = self.toMapCoordinates(e.pos()) self.showRect(self.startPoint, self.endPoint) def showRect(self, startPoint, endPoint): self.rubberBand.reset(QGis.Polygon) if startPoint.x() == endPoint.x() and startPoint.y() == endPoint.y(): return for i, pt in enumerate(self._rect(startPoint, endPoint).vertices()): self.rubberBand.addPoint(pt, bool(i == 3)) self.rubberBand.show() def _rect(self, startPoint, endPoint): if startPoint is None or endPoint is None: return None p0 = self.toCanvasCoordinates(startPoint) p1 = self.toCanvasCoordinates(endPoint) canvas_rect = QgsRectangle( QgsPoint( p0.x(), p0.y()), QgsPoint( p1.x(), p1.y())) center = QgsPoint( (startPoint.x() + endPoint.x()) / 2, (startPoint.y() + endPoint.y()) / 2) return RotatedRect(center, self.mupp * canvas_rect.width(), self.mupp * canvas_rect.height()).rotate(self.rotation, center) def rectangle(self): return self._rect(self.startPoint, self.endPoint) def setRectangle(self, rect): if rect == self._rect(self.startPoint, self.endPoint): return False v = rect.vertices() self.startPoint = v[3] self.endPoint = v[1] self.showRect(self.startPoint, self.endPoint) return True
class EditTool(MapTool): """ Inspection tool which copies the feature to a new layer and copies selected data from the underlying feature. """ finished = pyqtSignal(object, QgsFeature) featuresfound = pyqtSignal(dict) def __init__(self, canvas, forms, snapradius = 2): MapTool.__init__(self, canvas, []) self.canvas = canvas self.radius = snapradius self.forms = forms self.band = QgsRubberBand(self.canvas) self.band.setColor(QColor.fromRgb(224,162,16)) self.band.setWidth(3) self.selectband = None self.selectrect = QRect() self.dragging = False self.cursor = QCursor(QPixmap(["16 16 3 1", " c None", ". c #FF0000", "+ c #FFFFFF", " ", " +.+ ", " ++.++ ", " +.....+ ", " +. .+ ", " +. . .+ ", " +. . .+ ", " ++. . .++", " ... ...+... ...", " ++. . .++", " +. . .+ ", " +. . .+ ", " ++. .+ ", " ++.....+ ", " ++.++ ", " +.+ "])) def addForm(self, form): self.forms.append(form) self.layersupdated.emit(True) def layers(self): """ Return a set of layers that this edit tool can work on """ return set([form.QGISLayer for form in self.forms]) def formsforlayer(self, layer): for form in self.forms: if form.QGISLayer == layer: yield form def reset(self): self.forms = [] self.layersupdated.emit(False) def getFeatures(self, rect): rq = QgsFeatureRequest().setFilterRect(rect) self.band.reset() for layer in self.layers(): forms = list(self.formsforlayer(layer)) rq = QgsFeatureRequest().setFilterRect(rect) for feature in layer.getFeatures(rq): if feature.isValid(): yield feature, forms def toSearchRect(self, point): searchRadius = self.canvas.extent().width() * ( self.radius / 100.0 ) point = self.toMapCoordinates(point) rect = QgsRectangle() rect.setXMinimum(point.x() - searchRadius) rect.setXMaximum(point.x() + searchRadius) rect.setYMinimum(point.y() - searchRadius) rect.setYMaximum(point.y() + searchRadius) return rect def canvasPressEvent(self, event): self.selectrect.setRect( 0, 0, 0, 0 ) self.selectband = QgsRubberBand(self.canvas, QGis.Polygon ) self.selectband.setColor(QColor.fromRgb(0,0,255, 65)) self.selectband.setWidth(5) def canvasMoveEvent(self, event): if not event.buttons() == Qt.LeftButton: return if not self.dragging: self.dragging = True self.selectrect.setTopLeft(event.pos()) self.selectrect.setBottomRight(event.pos()) maptoolutils.setRubberBand(self.canvas, self.selectrect, self.selectband) def canvasReleaseEvent(self, event): if self.dragging: geometry = self.selectband.asGeometry() if not geometry: return rect = geometry.boundingBox() else: rect = self.toSearchRect(event.pos()) self.dragging = False self.selectband.reset() features = dict(self.getFeatures(rect)) print features if len(features) == 1: feature = features.keys()[0] forms = features.values()[0] if len(forms) == 1: self.finished.emit(forms[0], feature) else: self.featuresfound.emit(features) elif len(features) > 0: self.featuresfound.emit(features) def isEditTool(self): return True
class ProfiletoolMapTool(QgsMapTool): # Signals sig_clearMap = pyqtSignal() sig_createProfile = pyqtSignal() sig_changeCoord = pyqtSignal(QgsPointXY, str) def __init__(self, canvas, drawLineButton, showProfileButton): #buttonShowProf QgsMapTool.__init__(self, canvas) self.canvas = canvas self.cursor = QCursor(Qt.CrossCursor) # Red line self.rubberband = QgsRubberBand(self.canvas) self.rubberband.setWidth(3) self.rubberband.setColor(QColor(231, 28, 35)) # Buttons from main dialog self.drawLineButton = drawLineButton self.buttonShowProf = showProfileButton # Coordinates of drawn line points self.pointsToDraw = [] # Temporary save double clicks self.dblclktemp = None # Drawn line geometry self.drawnLine = None # Point markers on each end of the line self.markers = [] # Backup the last active Tool before the pofile tool became active self.savedTool = self.canvas.mapTool() def drawLine(self): # Emit signal that clears map and deletes profile self.sig_clearMap.emit() self.reset() self.canvas.setMapTool(self) # runs function self.activate() def activate(self): self.canvas.setCursor(self.cursor) def deactivate(self): self.canvas.setCursor(QCursor(Qt.OpenHandCursor)) self.pointsToDraw = [] # Stop pressing down button self.drawLineButton.setChecked(False) def reset(self): self.removeStueMarker() self.canvas.setMapTool(self.savedTool) self.rubberband.reset() self.pointsToDraw = [] self.dblclktemp = None self.drawnLine = None def canvasMoveEvent(self, event): if len(self.pointsToDraw) > 0: self.rubberband.reset() line = [self.pointsToDraw[0], event.mapPoint()] self.rubberband.setToGeometry(QgsGeometry.fromPolylineXY(line), None) def canvasReleaseEvent(self, event): mapPos = event.mapPoint() if mapPos == self.dblclktemp: self.dblclktemp = None return else: # Mark point with marker symbol self.drawStueMarker(mapPos) # Klick ist first point of line if len(self.pointsToDraw) == 0: self.rubberband.reset() self.pointsToDraw.append(mapPos) return # Klick is second point of line elif len(self.pointsToDraw) == 1: self.pointsToDraw.append(mapPos) self.removeStueMarker() self.dblclktemp = mapPos self.drawnLine = self.createDigiFeature(self.pointsToDraw) self.sig_changeCoord.emit(self.pointsToDraw[0], 'A') self.sig_changeCoord.emit(self.pointsToDraw[1], 'E') self.canvas.setMapTool(self.savedTool) # self.deactivate() def setCursor(self, cursor): self.cursor = cursor def updateLine(self, points): self.rubberband.setToGeometry(QgsGeometry.fromPolylineXY(points), None) self.drawnLine = self.createDigiFeature(points) self.drawStueMarker(points[0]) self.drawStueMarker(points[1]) def drawStueMarker(self, point): marker = QgsStueMarker(self.canvas) marker.setCenter(point) self.markers.append(marker) self.canvas.refresh() def removeStueMarker(self, position=-1): if position >= 0: marker = self.markers[position] self.canvas.scene().removeItem(marker) self.markers.pop(position) else: for marker in self.markers: self.canvas.scene().removeItem(marker) self.markers = [] self.canvas.refresh() @staticmethod def createDigiFeature(pnts): line = QgsGeometry.fromPolylineXY(pnts) qgFeat = QgsFeature() qgFeat.setGeometry(line) return qgFeat
class BanLocatorFilter(QgsLocatorFilter): HEADERS = {b'User-Agent': b'Mozilla/5.0 QGIS BAN Locator Filter'} message_emitted = pyqtSignal(str, str, Qgis.MessageLevel, QWidget) def __init__(self, iface: QgisInterface = None): """" :param filter_type: the type of filter :param locale_lang: the language of the locale. :param iface: QGIS interface, given when on the main thread (which will display/trigger results), None otherwise :param crs: if iface is not given, it shall be provided, see clone() """ super().__init__() self.rubber_band = None self.feature_rubber_band = None self.iface = iface self.map_canvas = None self.settings = Settings() self.transform_4326 = None self.current_timer = None self.crs = None self.event_loop = None self.result_found = False self.search_delay = 0.5 self.dbg_info("initialisation") if iface is not None: # happens only in main thread self.map_canvas = iface.mapCanvas() self.map_canvas.destinationCrsChanged.connect( self.create_transforms) self.rubber_band = QgsRubberBand(self.map_canvas, QgsWkbTypes.PointGeometry) self.rubber_band.setColor(QColor(255, 255, 50, 200)) self.rubber_band.setIcon(self.rubber_band.ICON_CIRCLE) self.rubber_band.setIconSize(15) self.rubber_band.setWidth(4) self.rubber_band.setBrushStyle(Qt.NoBrush) self.feature_rubber_band = QgsRubberBand( self.map_canvas, QgsWkbTypes.PolygonGeometry) self.feature_rubber_band.setColor(QColor(255, 50, 50, 200)) self.feature_rubber_band.setFillColor(QColor(255, 255, 50, 160)) self.feature_rubber_band.setBrushStyle(Qt.SolidPattern) self.feature_rubber_band.setLineStyle(Qt.SolidLine) self.feature_rubber_band.setWidth(4) self.create_transforms() def name(self): return 'Recherche Adresse BAN' def clone(self): return BanLocatorFilter(self.iface) def priority(self): return self.settings.value('locations_priority') def displayName(self): return self.tr('Ban Adress Location') def prefix(self): return 'ban' def clearPreviousResults(self): self.rubber_band.reset(QgsWkbTypes.PointGeometry) self.feature_rubber_band.reset(QgsWkbTypes.PolygonGeometry) if self.current_timer is not None: self.current_timer.stop() self.current_timer.deleteLater() self.current_timer = None def hasConfigWidget(self): return True def openConfigWidget(self, parent=None): ConfigDialog(parent).exec_() def create_transforms(self): # this should happen in the main thread dst_crs = self.map_canvas.mapSettings().destinationCrs() src_crs_4326 = QgsCoordinateReferenceSystem('EPSG:4326') self.transform_4326 = QgsCoordinateTransform(src_crs_4326, dst_crs, QgsProject.instance()) def group_info(self, group: str) -> str: return TYPE_RESULT[group] @staticmethod def url_with_param(url, params) -> str: url = QUrl(url) q = QUrlQuery(url) for key, value in params.items(): q.addQueryItem(key, value) url.setQuery(q) return url.url() def fetchResults(self, search: str, context: QgsLocatorContext, feedback: QgsFeedback): try: self.dbg_info("start Ban locator search...") if len(search) < 5: return self.result_found = False url = 'https://api-adresse.data.gouv.fr/search/' params = { 'q': str(search), 'limit': str(self.settings.value('locations_limit')) } # Locations, WMS layers nam = NetworkAccessManager() feedback.canceled.connect(nam.abort) url = self.url_with_param(url, params) self.dbg_info(url) try: (response, content) = nam.request(url, headers=self.HEADERS, blocking=True) self.handle_response(response) except RequestsExceptionUserAbort: pass except RequestsException as err: self.info(err) if not self.result_found: result = QgsLocatorResult() result.filter = self result.displayString = self.tr('No result found.') result.userData = NoResult self.resultFetched.emit(result) except Exception as e: self.info(e, Qgis.Critical) exc_type, exc_obj, exc_traceback = sys.exc_info() filename = os.path.split( exc_traceback.tb_frame.f_code.co_filename)[1] self.info( '{} {} {}'.format(exc_type, filename, exc_traceback.tb_lineno), Qgis.Critical) self.info( traceback.print_exception(exc_type, exc_obj, exc_traceback), Qgis.Critical) def handle_response(self, response): try: if response.status_code != 200: if not isinstance(response.exception, RequestsExceptionUserAbort): self.info( "Error in main response with status code: {} from {}". format(response.status_code, response.url)) return data = json.loads(response.content.decode('utf-8')) # self.dbg_info(data) for loc in data['features']: importance = loc['properties']['importance'] citycode = loc['properties']['citycode'] score = loc['properties']['score'] type_result = loc['properties']['type'] label = loc['properties']['label'] x = float(loc['geometry']['coordinates'][0]) y = float(loc['geometry']['coordinates'][1]) result = QgsLocatorResult() result.filter = self result.displayString = label result.group = self.group_info(type_result) result.icon = QIcon( ":/plugins/swiss_locator/icons/ban_locator.png") result.userData = LocationResult(importance, citycode, score, type_result, label, x, y) self.result_found = True self.resultFetched.emit(result) except Exception as e: self.info(str(e), Qgis.Critical) exc_type, exc_obj, exc_traceback = sys.exc_info() filename = os.path.split( exc_traceback.tb_frame.f_code.co_filename)[1] self.info( '{} {} {}'.format(exc_type, filename, exc_traceback.tb_lineno), Qgis.Critical) self.info( traceback.print_exception(exc_type, exc_obj, exc_traceback), Qgis.Critical) def triggerResult(self, result: QgsLocatorResult): # this should be run in the main thread, i.e. mapCanvas should not be None # remove any map tip self.clearPreviousResults() if type(result.userData) == NoResult: pass else: point = QgsGeometry.fromPointXY(result.userData.point) if not point: return point.transform(self.transform_4326) self.highlight(point, result.userData.type_result) if not self.settings.value('keep_marker_visible'): self.current_timer = QTimer() self.current_timer.timeout.connect(self.clearPreviousResults) self.current_timer.setSingleShot(True) self.current_timer.start(8000) def highlight(self, point, type_result=None): self.rubber_band.reset(QgsWkbTypes.PointGeometry) self.rubber_band.addGeometry(point, None) if type_result in ('housenumber', 'street'): zoom = float(self.settings.value('location_housenumber_zoom')) else: zoom = float(self.settings.value('location_default_zoom')) self.map_canvas.setCenter(point.asPoint()) self.map_canvas.zoomScale(zoom) def info(self, msg="", level=Qgis.Info, emit_message: bool = False): self.logMessage(str(msg), level) if emit_message: self.message_emitted.emit(msg, level) def dbg_info(self, msg=""): if DEBUG: self.info(msg)
class IntersectionDialog(QDialog, Ui_Intersection, SettingDialog): def __init__(self, iface, observations, initPoint): QDialog.__init__(self) self.setupUi(self) self.settings = MySettings() SettingDialog.__init__(self, self.settings, UpdateMode.NoUpdate) self.processButton.clicked.connect(self.doIntersection) self.okButton.clicked.connect(self.accept) self.finished.connect(self.resetRubber) self.initPoint = initPoint self.observations = [] self.solution = None self.report = "" self.rubber = QgsRubberBand(iface.mapCanvas(), QGis.Point) self.rubber.setColor(self.settings.value("rubberColor")) self.rubber.setIcon(self.settings.value("rubberIcon")) self.rubber.setIconSize(self.settings.value("rubberSize")) self.observationTableWidget.displayRows(observations) self.observationTableWidget.itemChanged.connect(self.disbaleOKbutton) self.doIntersection() def resetRubber(self, dummy=0): self.rubber.reset() def disbaleOKbutton(self): self.okButton.setDisabled(True) def doIntersection(self): self.observations = [] self.solution = None self.report = "" self.rubber.reset() observations = self.observationTableWidget.getObservations() nObs = len(observations) if nObs < 2: self.reportBrowser.setText(QCoreApplication.translate("IntersectIt", "No intersection can be done " "with less than 2 observations.")) return if nObs == 2: if observations[0]["type"] == "distance" and observations[1]["type"] == "distance": intersection = TwoCirclesIntersection(observations, self.initPoint) elif observations[0]["type"] == "orientation" and observations[1]["type"] == "orientation": intersection = TwoOrientationIntersection(observations) else: intersection = DistanceOrientationIntersection(observations, self.initPoint) else: maxIter = self.advancedIntersecLSmaxIteration.value() threshold = self.advancedIntersecLSconvergeThreshold.value() intersection = LeastSquares(observations, self.initPoint, maxIter, threshold) self.reportBrowser.setText(intersection.report) if intersection.solution is not None: self.solution = intersection.solution self.observations = observations self.report = intersection.report self.okButton.setEnabled(True) self.rubber.setToGeometry(QgsGeometry().fromPoint(self.solution), None)
def _get_rubberband(self): rb_line = QgsRubberBand(self.canvas, QGis.Line) rb_line.setColor(self.color) rb_line.setLineStyle(Qt.DotLine) rb_line.setWidth(3) return rb_line
class VoGISProfilToolMainDialog(QDialog): def __init__(self, interface, settings): self.settings = settings self.iface = interface self.selectingVisibleRasters = False self.thread = None QDialog.__init__(self, interface.mainWindow()) # Set up the user interface from Designer. self.ui = Ui_VoGISProfilToolMain() self.ui.setupUi(self) if self.settings.onlyHektoMode is True: self.ui.IDC_widRaster.hide() self.adjustSize() validator = QIntValidator(-32768, 32768, self) self.ui.IDC_tbNoDataExport.setValidator(validator) self.ui.IDC_tbFromX.setText('-30000') self.ui.IDC_tbFromY.setText('240000') self.ui.IDC_tbToX.setText('-20000') self.ui.IDC_tbToY.setText('230000') self.__addRastersToGui() self.__addPolygonsToGui() for line_lyr in self.settings.mapData.lines.lines(): self.ui.IDC_cbLineLayers.addItem(line_lyr.name, line_lyr) if self.settings.mapData.lines.count() < 1: self.ui.IDC_rbDigi.setChecked(True) self.ui.IDC_rbShapeLine.setEnabled(False) #Einstellungen fuer Linie zeichen self.action = QAction(QIcon(":/plugins/vogisprofiltoolmain/icons/icon.png"), "VoGIS-Profiltool", self.iface.mainWindow()) self.action.setWhatsThis("VoGIS-Profiltool") self.canvas = self.iface.mapCanvas() self.tool = ProfiletoolMapTool(self.canvas, self.action) self.savedTool = self.canvas.mapTool() self.polygon = False self.rubberband = QgsRubberBand(self.canvas, self.polygon) if QGis.QGIS_VERSION_INT >= 10900: #self.rubberband.setBrushStyle() self.rubberband.setLineStyle(Qt.SolidLine) self.rubberband.setWidth(4.0) self.rubberband.setColor(QColor(0, 255, 0)) #http://www.qgis.org/api/classQgsRubberBand.html#a6f7cdabfcf69b65dfc6c164ce2d01fab self.pointsToDraw = [] self.dblclktemp = None self.drawnLine = None def accept(self): try: #QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", "ACCEPTED") #QgsMessageLog.logMessage('nodata: {0}'.format(self.settings.nodata_value), 'VoGis') self.settings.nodata_value = int(self.ui.IDC_tbNoDataExport.text()) QgsMessageLog.logMessage('maindlg: nodata: {0}'.format(self.settings.nodata_value), 'VoGis') if self.settings.onlyHektoMode is True and self.settings.mapData.rasters.count() > 0: self.settings.onlyHektoMode = False if self.settings.onlyHektoMode is False: if self.settings.mapData.rasters.count() < 1: #QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", u"Keine Raster vorhanden. Zum Hektometrieren Dialog neu öffnen.") #return retVal = QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate('code', 'Keine Rasterebene vorhanden oder sichtbar! Nur hektometrieren?', None, QApplication.UnicodeUTF8), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if retVal == QMessageBox.No: return else: self.settings.onlyHektoMode = True self.settings.createHekto = True if self.__getSettingsFromGui() is False: return if self.settings.onlyHektoMode is False: if len(self.settings.mapData.rasters.selectedRasters()) < 1: #QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", "Kein Raster selektiert!") #msg = #QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", msg) QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate('code', 'Kein Raster selektiert!', None, QApplication.UnicodeUTF8)) return QgsMessageLog.logMessage('modeLine!=line: {0}'.format(self.settings.modeLine != enumModeLine.line), 'VoGis') QgsMessageLog.logMessage('customLine is None: {0}'.format(self.settings.mapData.customLine is None), 'VoGis') if self.settings.modeLine != enumModeLine.line and self.settings.mapData.customLine is None: QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate('code', 'Keine Profillinie vorhanden!', None, QApplication.UnicodeUTF8)) return if len(self.settings.mapData.polygons.selected_polygons()) > 0 and len(self.settings.mapData.rasters.selectedRasters()) > 1: raster_names = list(raster.name for raster in self.settings.mapData.rasters.selectedRasters()) sel_raster, ok_clicked = QInputDialog.getItem( self.iface.mainWindow(), u'DHM?', u'Welches DHM soll zur Flächenverschneidung verwendet werden?', raster_names, 0, False ) if ok_clicked is False: return self.settings.intersection_dhm_idx = raster_names.index(sel_raster) #self.rubberband.reset(self.polygon) #QDialog.accept(self) QApplication.setOverrideCursor(Qt.WaitCursor) create_profile = CreateProfile(self.iface, self.settings) thread = QThread(self) create_profile.moveToThread(thread) create_profile.finished.connect(self.profiles_finished) create_profile.error.connect(self.profiles_error) create_profile.progress.connect(self.profiles_progress) thread.started.connect(create_profile.create) thread.start(QThread.LowestPriority) self.thread = thread self.create_profile = create_profile self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) except: QApplication.restoreOverrideCursor() ex = u'{0}'.format(traceback.format_exc()) msg = 'Unexpected ERROR:\n\n{0}'.format(ex[:2000]) QMessageBox.critical(self.iface.mainWindow(), "VoGIS-Profiltool", msg) def profiles_finished(self, profiles, intersections): QApplication.restoreOverrideCursor() self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True) #self.create_profile.deleteLater() self.thread.quit() self.thread.wait() #self.thread.deleteLater() #QGIS 2.0 http://gis.stackexchange.com/a/58754 http://gis.stackexchange.com/a/57090 self.iface.mainWindow().statusBar().showMessage('VoGIS-Profiltool, {0} Profile'.format(len(profiles))) QgsMessageLog.logMessage(u'Profile Count: {0}'.format(len(profiles)), 'VoGis') if len(profiles) < 1: QApplication.restoreOverrideCursor() QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate('code', 'Es konnten keine Profile erstellt werden.', None, QApplication.UnicodeUTF8)) return dlg = VoGISProfilToolPlotDialog(self.iface, self.settings, profiles, intersections) dlg.show() #result = self.dlg.exec_() dlg.exec_() def profiles_error(self, exception_string): QApplication.restoreOverrideCursor() QgsMessageLog.logMessage(u'Error during profile creation: {0}'.format(exception_string), 'VoGis') QMessageBox.critical(self.iface.mainWindow(), "VoGIS-Profiltool", exception_string) def profiles_progress(self, msg): self.iface.mainWindow().statusBar().showMessage(msg) self.ui.IDC_lblCreateStatus.setText(msg) #QgsMessageLog.logMessage(msg, 'VoGis') QApplication.processEvents() def reject(self): if not self.thread is None: if self.thread.isRunning(): self.create_profile.abort() return self.rubberband.reset(self.polygon) QDialog.reject(self) def selectVisibleRasters(self): self.refreshRasterList() self.selectingVisibleRasters = True extCanvas = self.iface.mapCanvas().extent() #alle raster in den einstellunge deselektieren for r in self.settings.mapData.rasters.rasters(): r.selected = False #alle raster in der ListView deselektieren for idx in xrange(self.ui.IDC_listRasters.count()): item = self.ui.IDC_listRasters.item(idx) item.setCheckState(Qt.Unchecked) #Raster im Extent selektieren for idx in xrange(self.ui.IDC_listRasters.count()): item = self.ui.IDC_listRasters.item(idx) if QGis.QGIS_VERSION_INT < 10900: raster = item.data(Qt.UserRole).toPyObject() else: raster = item.data(Qt.UserRole) for r in self.settings.mapData.rasters.rasters(): if extCanvas.intersects(r.grid.extent()): if r.id == raster.id: r.selected = True item.setCheckState(Qt.Checked) self.selectingVisibleRasters = False def lineLayerChanged(self, idx): if self.ui.IDC_rbShapeLine.isChecked() is False: self.ui.IDC_rbShapeLine.setChecked(True) if QGis.QGIS_VERSION_INT < 10900: lineLyr = (self.ui.IDC_cbLineLayers.itemData(self.ui.IDC_cbLineLayers.currentIndex()).toPyObject()) else: lineLyr = (self.ui.IDC_cbLineLayers.itemData(self.ui.IDC_cbLineLayers.currentIndex())) lyr = lineLyr.line #QgsMessageLog.logMessage('{0}'.format(lyr.selectedFeatureCount()), 'VoGis') #QgsMessageLog.logMessage('{0}'.format(dir(lyr)), 'VoGis') if hasattr(lyr, 'selectedFeatureCount'): if(lyr.selectedFeatureCount() < 1): self.ui.IDC_chkOnlySelectedFeatures.setChecked(False) else: self.ui.IDC_chkOnlySelectedFeatures.setChecked(True) def valueChangedEquiDistance(self, val): if self.ui.IDC_rbEquiDistance.isChecked() is False: self.ui.IDC_rbEquiDistance.setChecked(True) def valueChangedVertexCount(self, val): if self.ui.IDC_rbVertexCount.isChecked() is False: self.ui.IDC_rbVertexCount.setChecked(True) def lvRasterItemChanged(self, item): if self.selectingVisibleRasters is True: return if item.checkState() == Qt.Checked: selected = True if item.checkState() == Qt.Unchecked: selected = False item_data = item.data(Qt.UserRole) if QGis.QGIS_VERSION_INT < 10900: raster_lyr = item_data.toPyObject() else: raster_lyr = item_data self.settings.mapData.rasters.getById(raster_lyr.id).selected = selected def lvPolygonItemChanged(self, item): if item.checkState() == Qt.Checked: selected = True if item.checkState() == Qt.Unchecked: selected = False item_data = item.data(Qt.UserRole) if QGis.QGIS_VERSION_INT < 10900: poly_lyr = item_data.toPyObject() else: poly_lyr = item_data self.settings.mapData.polygons.getById(poly_lyr.id).selected = selected def refreshRasterList(self): legend = self.iface.legendInterface() avail_lyrs = legend.layers() raster_coll = RasterCollection() for lyr in avail_lyrs: if legend.isLayerVisible(lyr): lyr_type = lyr.type() lyr_name = unicodedata.normalize('NFKD', unicode(lyr.name())).encode('ascii', 'ignore') if lyr_type == 1: if lyr.bandCount() < 2: new_raster = Raster(lyr.id(), lyr_name, lyr) raster_coll.addRaster(new_raster) self.settings.mapData.rasters = raster_coll self.__addRastersToGui() def __addRastersToGui(self): self.ui.IDC_listRasters.clear() check = Qt.Unchecked if self.settings.mapData.rasters.count() == 1: check = Qt.Checked self.settings.mapData.rasters.rasters()[0].selected = True for raster_lyr in self.settings.mapData.rasters.rasters(): item = QListWidgetItem(raster_lyr.name) item.setData(Qt.UserRole, raster_lyr) item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setCheckState(check) self.ui.IDC_listRasters.addItem(item) def __addPolygonsToGui(self): self.ui.IDC_listPolygons.clear() check = Qt.Unchecked for poly_lyr in self.settings.mapData.polygons.polygons(): item = QListWidgetItem(poly_lyr.name) item.setData(Qt.UserRole, poly_lyr) item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setCheckState(check) self.ui.IDC_listPolygons.addItem(item) def drawLine(self): if self.ui.IDC_rbDigi.isChecked() is False: self.ui.IDC_rbDigi.setChecked(True) self.dblckltemp = None self.rubberband.reset(self.polygon) self.__cleanDigi() self.__activateDigiTool() self.canvas.setMapTool(self.tool) def __createDigiFeature(self, pnts): u = Util(self.iface) f = u.createQgLineFeature(pnts) self.settings.mapData.customLine = f def __lineFinished(self, position): mapPos = self.canvas.getCoordinateTransform().toMapCoordinates(position["x"], position["y"]) newPoint = QgsPoint(mapPos.x(), mapPos.y()) self.pointsToDraw.append(newPoint) #launch analyses self.iface.mainWindow().statusBar().showMessage(str(self.pointsToDraw)) if len(self.pointsToDraw) < 2: self.__cleanDigi() self.pointsToDraw = [] self.dblclktemp = newPoint self.drawnLine = None QMessageBox.warning(self, "VoGIS-Profiltool", QApplication.translate('code', 'Profillinie digitalisieren abgebrochen!', None, QApplication.UnicodeUTF8)) self.drawnLine = self.__createDigiFeature(self.pointsToDraw) self.__cleanDigi() self.pointsToDraw = [] self.dblclktemp = newPoint def __cleanDigi(self): self.pointsToDraw = [] self.canvas.unsetMapTool(self.tool) self.canvas.setMapTool(self.savedTool) def __activateDigiTool(self): QObject.connect(self.tool, SIGNAL("moved"), self.__moved) QObject.connect(self.tool, SIGNAL("rightClicked"), self.__rightClicked) QObject.connect(self.tool, SIGNAL("leftClicked"), self.__leftClicked) QObject.connect(self.tool, SIGNAL("doubleClicked"), self.__doubleClicked) QObject.connect(self.tool, SIGNAL("deactivate"), self.__deactivateDigiTool) def __deactivateDigiTool(self): QObject.disconnect(self.tool, SIGNAL("moved"), self.__moved) QObject.disconnect(self.tool, SIGNAL("leftClicked"), self.__leftClicked) QObject.disconnect(self.tool, SIGNAL("rightClicked"), self.__rightClicked) QObject.disconnect(self.tool, SIGNAL("doubleClicked"), self.__doubleClicked) if QGis.QGIS_VERSION_INT < 10900: self.iface.mainWindow().statusBar().showMessage(QString("")) else: self.iface.mainWindow().statusBar().showMessage('') def __moved(self, position): if len(self.pointsToDraw) > 0: mapPos = self.canvas.getCoordinateTransform().toMapCoordinates(position["x"], position["y"]) self.rubberband.reset(self.polygon) newPnt = QgsPoint(mapPos.x(), mapPos.y()) if QGis.QGIS_VERSION_INT < 10900: for i in range(0, len(self.pointsToDraw)): self.rubberband.addPoint(self.pointsToDraw[i]) self.rubberband.addPoint(newPnt) else: pnts = self.pointsToDraw + [newPnt] self.rubberband.setToGeometry(QgsGeometry.fromPolyline(pnts),None) def __rightClicked(self, position): self.__lineFinished(position) def __leftClicked(self, position): mapPos = self.canvas.getCoordinateTransform().toMapCoordinates(position["x"], position["y"]) newPoint = QgsPoint(mapPos.x(), mapPos.y()) #if self.selectionmethod == 0: if newPoint == self.dblclktemp: self.dblclktemp = None return else: if len(self.pointsToDraw) == 0: self.rubberband.reset(self.polygon) self.pointsToDraw.append(newPoint) def __doubleClicked(self, position): pass #not in use right now def __lineCancel(self): pass def __getSettingsFromGui(self): self.settings.linesExplode = (self.ui.IDC_chkLinesExplode.checkState() == Qt.Checked) self.settings.linesMerge = (self.ui.IDC_chkLinesMerge.checkState() == Qt.Checked) self.settings.onlySelectedFeatures = (self.ui.IDC_chkOnlySelectedFeatures.checkState() == Qt.Checked) self.settings.equiDistance = self.ui.IDC_dblspinDistance.value() self.settings.vertexCnt = self.ui.IDC_dblspinVertexCnt.value() #self.settings.createHekto = (self.ui.IDC_chkCreateHekto.checkState() == Qt.Checked) self.settings.nodesAndVertices = (self.ui.IDC_chkNodesAndVertices.checkState() == Qt.Checked) if QGis.QGIS_VERSION_INT < 10900: self.settings.mapData.selectedLineLyr = (self.ui.IDC_cbLineLayers.itemData( self.ui.IDC_cbLineLayers.currentIndex() ).toPyObject() ) else: self.settings.mapData.selectedLineLyr = (self.ui.IDC_cbLineLayers.itemData(self.ui.IDC_cbLineLayers.currentIndex())) if self.settings.onlySelectedFeatures is True and self.settings.mapData.selectedLineLyr.line.selectedFeatureCount() < 1: QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate('code', u'Der gewählte Layer hat keine selektierten Elemente.', None, QApplication.UnicodeUTF8)) return False if self.ui.IDC_rbDigi.isChecked(): self.settings.modeLine = enumModeLine.customLine elif self.ui.IDC_rbShapeLine.isChecked(): self.settings.modeLine = enumModeLine.line else: #self.ui.IDC_rbStraigthLine self.settings.modeLine = enumModeLine.straightLine if self.ui.IDC_rbEquiDistance.isChecked(): self.settings.modeVertices = enumModeVertices.equiDistant else: self.settings.modeVertices = enumModeVertices.vertexCnt if self.ui.IDC_rbStraigthLine.isChecked(): ut = Util(self.iface) if ut.isFloat(self.ui.IDC_tbFromX.text(), QApplication.translate('code', 'Rechtswert von', None, QApplication.UnicodeUTF8)) is False: return False else: fromX = float(self.ui.IDC_tbFromX.text()) if ut.isFloat(self.ui.IDC_tbFromY.text(), QApplication.translate('code', 'Hochwert von', None, QApplication.UnicodeUTF8)) is False: return False else: fromY = float(self.ui.IDC_tbFromY.text()) if ut.isFloat(self.ui.IDC_tbToX.text(), QApplication.translate('code', 'Rechtswert nach', None, QApplication.UnicodeUTF8)) is False: return False else: toX = float(self.ui.IDC_tbToX.text()) if ut.isFloat(self.ui.IDC_tbToY.text(), QApplication.translate('code', 'Hochwert nach', None, QApplication.UnicodeUTF8)) is False: return False else: toY = float(self.ui.IDC_tbToY.text()) fromPnt = QgsPoint(fromX, fromY) toPnt = QgsPoint(toX, toY) self.settings.mapData.customLine = ut.createQgLineFeature([fromPnt, toPnt]) return True
class QuickFinder(QObject): name = "&Quick Finder" actions = None toolbar = None finders = {} loadingIcon = None def __init__(self, iface): QObject.__init__(self) self.iface = iface self.actions = {} self.finders = {} self.settings = MySettings() self.rubber = None self._init_finders() self.iface.projectRead.connect(self._reload_finders) self.iface.newProjectCreated.connect(self._reload_finders) # translation environment self.plugin_dir = os.path.dirname(__file__) locale = QSettings().value("locale/userLocale")[0:2] localePath = os.path.join(self.plugin_dir, 'i18n', 'quickfinder_{0}.qm'.format(locale)) if os.path.exists(localePath): self.translator = QTranslator() self.translator.load(localePath) QCoreApplication.installTranslator(self.translator) def initGui(self): self.actions['showSettings'] = QAction( QIcon(":/plugins/quickfinder/icons/settings.svg"), self.tr(u"&Settings"), self.iface.mainWindow()) self.actions['showSettings'].triggered.connect(self.show_settings) self.iface.addPluginToMenu(self.name, self.actions['showSettings']) self._init_toolbar() # set selection area sytle and color self.rubber = QgsRubberBand(self.iface.mapCanvas()) self.rubber.setColor(QColor(255, 255, 50, 200)) self.rubber.setIcon(self.rubber.ICON_CIRCLE) self.rubber.setIconSize(15) self.rubber.setWidth(4) self.rubber.setBrushStyle(Qt.NoBrush) def unload(self): """ Unload plugin """ for key in list(self.finders.keys()): self.finders[key].close() for action in self.actions.values(): self.iface.removePluginMenu(self.name, action) if self.toolbar: del self.toolbar if self.rubber: self.iface.mapCanvas().scene().removeItem(self.rubber) del self.rubber def _init_toolbar(self): """setup the plugin toolbar.""" self.toolbar = self.iface.addToolBar(self.name) self.toolbar.setObjectName('mQuickFinderToolBar') self.search_action = QAction( QIcon(":/plugins/quickfinder/icons/magnifier13.svg"), self.tr("Search"), self.toolbar) self.stop_action = QAction( QIcon(":/plugins/quickfinder/icons/wrong2.svg"), self.tr("Cancel"), self.toolbar) self.finder_box = FinderBox(self.finders, self.iface, self.toolbar) self.finder_box.search_started.connect(self.search_started) self.finder_box.search_finished.connect(self.search_finished) self.finder_box_action = self.toolbar.addWidget(self.finder_box) self.finder_box_action.setVisible(True) self.search_action.triggered.connect(self.finder_box.search) self.toolbar.addAction(self.search_action) self.stop_action.setVisible(False) self.stop_action.triggered.connect(self.finder_box.stop) self.toolbar.addAction(self.stop_action) self.toolbar.setVisible(True) def _init_finders(self): # self.finders['geomapfish'] = GeomapfishFinder(self) self.finders['osm'] = OsmFinder(self) self.finders['project'] = ProjectFinder(self) self.finders['amap'] = AmapFinder(self) # self.finders['postgis'] = PostgisFinder(self) for key in list(self.finders.keys()): self.finders[key].message.connect(self.display_message) self.refresh_project() def _reload_finders(self): for key in list(self.finders.keys()): self.finders[key].close() self.finders[key].reload() self.refresh_project() @pyqtSlot(str, Qgis.MessageLevel) def display_message(self, message, level): self.iface.messageBar().pushMessage("QuickFinder", message, level) def show_settings(self): # self.win = ConfigurationDialog() # self.win.show() #ConfigurationDialog().show() if ConfigurationDialog().exec_(): self._reload_finders() def search_started(self): self.search_action.setVisible(False) self.stop_action.setVisible(True) def search_finished(self): self.search_action.setVisible(True) self.stop_action.setVisible(False) def refresh_project(self): if not self.finders['project'].activated: return if not self.settings.value("refreshAuto"): return n_days = self.settings.value("refreshDelay") # do not ask more ofen than 3 days ask_limit = min(3, n_days) recently_asked = self.settings.value( "refreshLastAsked") >= n_days_ago_iso_date(ask_limit) if recently_asked: return thresh_date = n_days_ago_iso_date(n_days) uptodate = True for search in list(self.finders['project'].searches.values()): if search.dateEvaluated <= thresh_date: uptodate = False break if uptodate: return self.settings.setValue("refreshLastAsked", n_days_ago_iso_date(0)) ret = QMessageBox( QMessageBox.Warning, "Quick Finder", QCoreApplication.translate( "Auto Refresh", "Some searches are outdated. Do you want to refresh them ?"), QMessageBox.Cancel | QMessageBox.Yes).exec_() if ret == QMessageBox.Yes: RefreshDialog(self.finders['project']).exec_()
class SelectFeatureTool(QgsMapToolEmitPoint): foundFeature = pyqtSignal(QgsFeature, object, str) def __init__(self, canvas, layer, column, bindto, radius): QgsMapToolEmitPoint.__init__(self, canvas) self.layer = layer self.column = column self.bindto = bindto self.canvas = canvas self.bindto = bindto self.searchradius = radius self.canvasClicked.connect(self.findFeature) self.canvas.setMapTool(self) self.band = QgsRubberBand(self.canvas) self.band.setColor(Qt.blue) self.band.setWidth(3) self.rect = QgsRectangle() self.cursor = QCursor( QPixmap([ "16 16 3 1", " c None", ". c #32CD32", "+ c #32CD32", " ", " +.+ ", " ++.++ ", " +.....+ ", " +. .+ ", " +. . .+ ", " +. . .+ ", " ++. . .++", " ... ...+... ...", " ++. . .++", " +. . .+ ", " +. . .+ ", " ++. .+ ", " ++.....+ ", " ++.++ ", " +.+ " ])) def findFeature(self, point, button): searchRadius = QgsTolerance.toleranceInMapUnits( self.searchradius, self.layer, \ self.canvas.mapRenderer(), QgsTolerance.Pixels) self.rect.setXMinimum(point.x() - searchRadius) self.rect.setXMaximum(point.x() + searchRadius) self.rect.setYMinimum(point.y() - searchRadius) self.rect.setYMaximum(point.y() + searchRadius) self.layer.select(self.layer.pendingAllAttributesList(), self.rect, True, True) feature = QgsFeature() self.layer.nextFeature(feature) try: index = self.layer.fieldNameIndex(self.column) value = feature.attributeMap()[index] self.foundFeature.emit(feature, value, self.bindto) except KeyError: return def canvasMoveEvent(self, event): point = self.toMapCoordinates(event.pos()) searchRadius = QgsTolerance.toleranceInMapUnits( self.searchradius, self.layer, \ self.canvas.mapRenderer(), QgsTolerance.Pixels) self.rect.setXMinimum(point.x() - searchRadius) self.rect.setXMaximum(point.x() + searchRadius) self.rect.setYMinimum(point.y() - searchRadius) self.rect.setYMaximum(point.y() + searchRadius) self.layer.select([], self.rect, True, True) feature = QgsFeature() self.layer.nextFeature(feature) if not feature.isValid(): log("Not a vaild feature") return self.band.setToGeometry(feature.geometry(), None) def setActive(self): self.canvas.setMapTool(self) self.canvas.setCursor(self.cursor) def deactivate(self): self.band.hide()
class InterpolateTool(QgsMapTool): def __init__(self, iface): """ Constructor :param iface: interface """ QgsMapTool.__init__(self, iface.mapCanvas()) self.__iface = iface self.__canvas = iface.mapCanvas() self.__icon_path = ':/plugins/VDLTools/icons/interpolate_icon.png' self.__text = QCoreApplication.translate( "VDLTools", "Interpolate the elevation of a vertex and a point in the middle of a line" ) # self.__oldTool = None self.__layer = None self.setCursor(Qt.ArrowCursor) self.__isEditing = False self.__lastFeatureId = None self.__layerList = None self.__lastLayer = None self.__confDlg = None self.__mapPoint = None self.__rubber = None self.__counter = 0 self.__ownSettings = None self.__selectedFeature = None self.__linesConfig = None self.__findVertex = 0 def icon_path(self): """ To get the icon path :return: icon path """ return self.__icon_path def text(self): """ To get the menu text :return: menu text """ return self.__text def setTool(self): """ To set the current tool as this one """ # self.__oldTool = self.__canvas.mapTool() self.__canvas.setMapTool(self) def setOwnSettings(self, settings): """ To set the settings :param settings: income settings """ self.__ownSettings = settings def activate(self): """ When the action is selected """ QgsMapTool.activate(self) self.__updateList() self.__rubber = QgsRubberBand(self.__canvas, QGis.Point) color = QColor("red") color.setAlphaF(0.78) self.__rubber.setColor(color) self.__rubber.setIcon(4) self.__rubber.setIconSize(20) self.__canvas.layersChanged.connect(self.__updateList) self.__canvas.scaleChanged.connect(self.__updateList) QgsProject.instance().snapSettingsChanged.connect(self.__updateList) def deactivate(self): """ When the action is deselected """ self.__rubber.reset() if self.__lastLayer is not None: self.__lastLayer.removeSelection() self.__canvas.layersChanged.disconnect(self.__updateList) self.__canvas.scaleChanged.disconnect(self.__updateList) QgsProject.instance().snapSettingsChanged.disconnect(self.__updateList) QgsMapTool.deactivate(self) def startEditing(self): """ To set the action as enable, as the layer is editable """ self.action().setEnabled(True) self.__layer.editingStarted.disconnect(self.startEditing) self.__layer.editingStopped.connect(self.stopEditing) def stopEditing(self): """ To set the action as disable, as the layer is not editable """ self.action().setEnabled(False) self.__layer.editingStopped.disconnect(self.stopEditing) self.__layer.editingStarted.connect(self.startEditing) if self.__canvas.mapTool == self: self.__iface.actionPan().trigger() # self.__canvas.setMapTool(self.__oldTool) def removeLayer(self): """ To remove the current working layer """ if self.__layer is not None: if self.__layer.isEditable(): self.__layer.editingStopped.disconnect(self.stopEditing) else: self.__layer.editingStarted.disconnect(self.startEditing) self.__layer = None def setEnable(self, layer): """ To check if we can enable the action for the selected layer :param layer: selected layer """ if layer is not None \ and isinstance(layer, QgsVectorLayer) \ and layer.geometryType() == QGis.Point: if layer == self.__layer: return if self.__layer is not None: if self.__layer.isEditable(): self.__layer.editingStopped.disconnect(self.stopEditing) else: self.__layer.editingStarted.disconnect(self.startEditing) self.__layer = layer if self.__layer.isEditable(): self.action().setEnabled(True) self.__layer.editingStopped.connect(self.stopEditing) else: self.action().setEnabled(False) self.__layer.editingStarted.connect(self.startEditing) if self.__canvas.mapTool == self: self.__iface.actionPan().trigger() # self.__canvas.setMapTool(self.__oldTool) return self.action().setEnabled(False) self.removeLayer() def __updateList(self): """ To update the line layers list that we can use for interpolation """ self.__layerList = [] legend = self.__iface.legendInterface() scale = self.__iface.mapCanvas().scale() for layer in self.__iface.mapCanvas().layers(): noUse, enabled, snappingType, unitType, tolerance, avoidIntersection = \ QgsProject.instance().snapSettingsForLayer(layer.id()) if isinstance(layer, QgsVectorLayer) and layer.hasGeometryType() \ and layer.geometryType() == QGis.Line: if not layer.hasScaleBasedVisibility( ) or layer.minimumScale() < scale <= layer.maximumScale(): if legend.isLayerVisible(layer) and enabled: layerConfig = QgsSnappingUtils.LayerConfig( layer, QgsPointLocator.Vertex, tolerance, unitType) self.__layerList.append(layerConfig) if self.__ownSettings and self.__ownSettings.linesLayer(): noUse, enabled, snappingType, unitType, tolerance, avoidIntersection = \ QgsProject.instance().snapSettingsForLayer(self.__ownSettings.linesLayer().id()) self.__linesConfig = QgsSnappingUtils.LayerConfig( self.__ownSettings.linesLayer(), QgsPointLocator.Vertex, tolerance, unitType) def canvasMoveEvent(self, event): """ When the mouse is moved :param event: mouse event """ if not self.__isEditing and not self.__findVertex and self.__layerList is not None: f_l = Finder.findClosestFeatureLayersAt(event.mapPoint(), self.__layerList, self) if f_l is not None and self.__lastFeatureId != f_l[0].id(): f = f_l[0] self.__lastFeatureId = f.id() if self.__lastLayer is not None: self.__lastLayer.removeSelection() self.__lastLayer = f_l[1] self.__lastLayer.setSelectedFeatures([f.id()]) if f_l is None and self.__lastLayer is not None: self.__lastLayer.removeSelection() # self.__rubber.reset() self.__lastFeatureId = None elif self.__findVertex: self.__rubber.reset() match = Finder.snap(event.mapPoint(), self.__canvas, True) if match.hasVertex() or match.hasEdge(): point = match.point() if match.hasVertex(): if match.layer() and self.__selectedFeature.id( ) == match.featureId(): self.__rubber.setIcon(4) self.__rubber.setToGeometry( QgsGeometry().fromPoint(point), None) else: intersection = Finder.snapCurvedIntersections( match.point(), self.__canvas, self, True, self.__selectedFeature.id()) if intersection: self.__rubber.setIcon(1) self.__rubber.setToGeometry( QgsGeometry().fromPoint(intersection), None) if match.hasEdge(): intersection = Finder.snapCurvedIntersections( match.point(), self.__canvas, self, True, self.__selectedFeature.id()) if intersection: self.__rubber.setIcon(1) self.__rubber.setToGeometry( QgsGeometry().fromPoint(intersection), None) elif self.__selectedFeature.id() == match.featureId(): self.__rubber.setIcon(3) self.__rubber.setToGeometry( QgsGeometry().fromPoint(point), None) def canvasReleaseEvent(self, event): """ When the mouse is clicked :param event: mouse event """ if self.__lastLayer is not None and not self.__findVertex: found_features = self.__lastLayer.selectedFeatures() if len(found_features) > 0: if len(found_features) < 1: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "One feature at a time"), level=QgsMessageBar.INFO) return self.__selectedFeature = found_features[0] self.__findVertex = 1 elif self.__findVertex: self.__rubber.reset() match = Finder.snap(event.mapPoint(), self.__canvas, True) if match.hasVertex() or match.hasEdge(): point = match.point() ok = False if match.hasVertex(): if match.layer() and self.__selectedFeature.id( ) == match.featureId(): ok = True else: intersection = Finder.snapCurvedIntersections( match.point(), self.__canvas, self, True, self.__selectedFeature.id()) if intersection: point = intersection ok = True if match.hasEdge(): intersection = Finder.snapCurvedIntersections( match.point(), self.__canvas, self, True, self.__selectedFeature.id()) if intersection: point = intersection ok = True elif self.__selectedFeature.id() == match.featureId(): ok = True if ok: self.__isEditing = True self.__findVertex = 0 self.__mapPoint = point if not match.hasVertex(): self.__confDlg = InterpolateConfirmDialog() if self.__lastLayer.isEditable() is True: self.__confDlg.setMainLabel( QCoreApplication.translate( "VDLTools", "What do you want to do ?")) self.__confDlg.setAllLabel( QCoreApplication.translate( "VDLTools", "Create point and new vertex")) self.__confDlg.setVtLabel( QCoreApplication.translate( "VDLTools", "Create only the vertex")) self.__confDlg.okButton().clicked.connect( self.__onConfirmOk) self.__confDlg.cancelButton().clicked.connect( self.__onConfirmCancel) self.__confDlg.show() else: self.__ok(False, True) def __onConfirmCancel(self): """ When the Cancel button in Interpolate Confirm Dialog is pushed """ self.__confDlg.close() self.__lastLayer.removeSelection() self.__rubber.reset() self.__lastFeatureId = None self.__isEditing = False def __onConfirmOk(self): id = self.__confDlg.getCheckedId() self.__confDlg.close() withVertex = True withPoint = True if id == 1: withVertex = False else: if self.__lastLayer.isEditable() is False: self.__lastLayer.startEditing() if id == 2: withPoint = False self.__ok(withVertex, withPoint) def __ok(self, withVertex, withPoint): line_v2, curved = GeometryV2.asLineV2( self.__selectedFeature.geometry()) vertex_v2 = QgsPointV2() vertex_id = QgsVertexId() line_v2.closestSegment(QgsPointV2(self.__mapPoint), vertex_v2, vertex_id, 0) x0 = line_v2.xAt(vertex_id.vertex - 1) y0 = line_v2.yAt(vertex_id.vertex - 1) d0 = Finder.sqrDistForCoords(x0, vertex_v2.x(), y0, vertex_v2.y()) x1 = line_v2.xAt(vertex_id.vertex) y1 = line_v2.yAt(vertex_id.vertex) d1 = Finder.sqrDistForCoords(x1, vertex_v2.x(), y1, vertex_v2.y()) z0 = line_v2.zAt(vertex_id.vertex - 1) z1 = line_v2.zAt(vertex_id.vertex) vertex_v2.addZValue((d0 * z1 + d1 * z0) / (d0 + d1)) if withPoint: pt_feat = QgsFeature(self.__layer.pendingFields()) pt_feat.setGeometry(QgsGeometry(vertex_v2)) if self.__layer.editFormConfig().suppress( ) == QgsEditFormConfig.SuppressOn: self.__layer.addFeature(pt_feat) else: self.__iface.openFeatureForm(self.__layer, pt_feat) if withVertex: line_v2.insertVertex(vertex_id, vertex_v2) self.__lastLayer.changeGeometry(self.__selectedFeature.id(), QgsGeometry(line_v2)) self.__lastLayer.removeSelection() self.__rubber.reset() self.__lastFeatureId = None self.__selectedFeature = None self.__isEditing = False def __snapToIntersection(self, mapPoint, selectedFeature): """ To check is we can snap a close intersection :param mapPoint: the point to check :param selectedFeature: the feature that can intersect another one :return: an intersection QgsPointV2 or none """ f = Finder.findClosestFeatureAt(mapPoint, self.__linesConfig, self) if f is None: return None intersect = Finder.intersect(selectedFeature.geometry(), f.geometry(), mapPoint) if intersect is not None: return QgsPointV2(intersect) else: return None
class LatLonTools: def __init__(self, iface): self.iface = iface self.canvas = iface.mapCanvas() self.crossRb = QgsRubberBand(self.canvas, QgsWkbTypes.LineGeometry) self.crossRb.setColor(Qt.red) def initGui(self): '''Initialize Lot Lon Tools GUI.''' # Initialize the Settings Dialog box self.settingsDialog = SettingsWidget(self, self.iface, self.iface.mainWindow()) self.mapTool = CopyLatLonTool(self.settingsDialog, self.iface) self.showMapTool = ShowOnMapTool(self.settingsDialog, self.iface) self.toMGRSDialog = ToMGRSWidget(self.iface, self.iface.mainWindow()) self.MGRStoLayerDialog = MGRStoLayerWidget(self.iface, self.iface.mainWindow()) # Add Interface for Coordinate Capturing icon = QIcon(os.path.dirname(__file__) + "/images/copyicon.png") self.copyAction = QAction(icon, "Copy Latitude, Longitude", self.iface.mainWindow()) self.copyAction.triggered.connect(self.startCapture) self.copyAction.setCheckable(True) self.iface.addToolBarIcon(self.copyAction) self.iface.addPluginToMenu("Lat Lon Tools", self.copyAction) # Add Interface for Zoom to Coordinate icon = QIcon(os.path.dirname(__file__) + "/images/zoomicon.png") self.zoomToAction = QAction(icon, "Zoom To Latitude, Longitude", self.iface.mainWindow()) self.zoomToAction.triggered.connect(self.showZoomToDialog) self.iface.addPluginToMenu('Lat Lon Tools', self.zoomToAction) self.canvas.mapToolSet.connect(self.unsetTool) self.zoomToDialog = ZoomToLatLon(self, self.iface, self.iface.mainWindow()) self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.zoomToDialog) self.zoomToDialog.hide() # Add Interface for External Map icon = QIcon(os.path.dirname(__file__) + "/images/mapicon.png") self.externMapAction = QAction(icon, "Show in External Map", self.iface.mainWindow()) self.externMapAction.triggered.connect(self.setShowMapTool) self.externMapAction.setCheckable(True) self.iface.addToolBarIcon(self.externMapAction) self.iface.addPluginToMenu("Lat Lon Tools", self.externMapAction) # Add Interface for Multi point zoom icon = QIcon(os.path.dirname(__file__) + '/images/multizoom.png') self.multiZoomToAction = QAction(icon, "Multi-location Zoom", self.iface.mainWindow()) self.multiZoomToAction.triggered.connect(self.multiZoomTo) self.iface.addPluginToMenu('Lat Lon Tools', self.multiZoomToAction) self.multiZoomDialog = MultiZoomWidget(self, self.settingsDialog, self.iface.mainWindow()) self.multiZoomDialog.hide() self.multiZoomDialog.setFloating(True) # Add To MGRS conversion icon = QIcon(os.path.dirname(__file__) + '/images/mgrs2point.png') icon2 = QIcon(os.path.dirname(__file__) + '/images/point2mgrs.png') menu = QMenu() menu.addAction(icon, "MGRS to Geometry", self.MGRStoLayer) menu.addAction(icon2, "Geometry to MGRS", self.toMGRS) self.toMGRSAction = QAction(icon2, "MGRS Conversions", self.iface.mainWindow()) self.toMGRSAction.setMenu(menu) self.iface.addPluginToMenu('Lat Lon Tools', self.toMGRSAction) # Initialize the Settings Dialog Box settingsicon = QIcon(os.path.dirname(__file__) + '/images/settings.png') self.settingsAction = QAction(settingsicon, "Settings", self.iface.mainWindow()) self.settingsAction.triggered.connect(self.settings) self.iface.addPluginToMenu('Lat Lon Tools', self.settingsAction) # Help helpicon = QIcon(os.path.dirname(__file__) + '/images/help.png') self.helpAction = QAction(helpicon, "Help", self.iface.mainWindow()) self.helpAction.triggered.connect(self.help) self.iface.addPluginToMenu('Lat Lon Tools', self.helpAction) def unsetTool(self, tool): '''Uncheck the Copy Lat Lon tool''' try: if not isinstance(tool, CopyLatLonTool): self.copyAction.setChecked(False) self.multiZoomDialog.stopCapture() self.mapTool.capture4326 = False if not isinstance(tool, ShowOnMapTool): self.externMapAction.setChecked(False) except: pass def unload(self): '''Unload LatLonTools from the QGIS interface''' self.zoomToDialog.removeMarker() self.multiZoomDialog.removeMarkers() self.canvas.unsetMapTool(self.mapTool) self.canvas.unsetMapTool(self.showMapTool) self.iface.removePluginMenu('Lat Lon Tools', self.copyAction) self.iface.removeToolBarIcon(self.copyAction) self.iface.removePluginMenu('Lat Lon Tools', self.externMapAction) self.iface.removeToolBarIcon(self.externMapAction) self.iface.removePluginMenu('Lat Lon Tools', self.zoomToAction) self.iface.removePluginMenu('Lat Lon Tools', self.multiZoomToAction) self.iface.removePluginMenu('Lat Lon Tools', self.toMGRSAction) self.iface.removePluginMenu('Lat Lon Tools', self.settingsAction) self.iface.removePluginMenu('Lat Lon Tools', self.helpAction) self.iface.removeDockWidget(self.zoomToDialog) self.iface.removeDockWidget(self.multiZoomDialog) self.zoomToDialog = None self.multiZoomDialog = None def startCapture(self): '''Set the focus of the copy coordinate tool and check it''' self.copyAction.setChecked(True) self.canvas.setMapTool(self.mapTool) def setShowMapTool(self): '''Set the focus of the external map tool and check it''' self.externMapAction.setChecked(True) self.canvas.setMapTool(self.showMapTool) def showZoomToDialog(self): '''Show the zoom to docked widget.''' self.zoomToDialog.show() def multiZoomTo(self): '''Display the Multi-zoom to dialog box''' self.multiZoomDialog.show() def toMGRS(self): '''Display the to MGRS dialog box''' self.toMGRSDialog.show() def MGRStoLayer(self): '''Display the to MGRS dialog box''' self.MGRStoLayerDialog.show() def settings(self): '''Show the settings dialog box''' self.settingsDialog.show() def help(self): '''Display a help page''' url = QUrl.fromLocalFile(os.path.dirname(__file__) + "/index.html").toString() webbrowser.open(url, new=2) def settingsChanged(self): # Settings may have changed so we need to make sure the zoomToDialog window is configured properly self.zoomToDialog.configure() self.multiZoomDialog.settingsChanged() def zoomTo(self, srcCrs, lat, lon): canvasCrs = self.canvas.mapSettings().destinationCrs() transform = QgsCoordinateTransform(srcCrs, canvasCrs) x, y = transform.transform(float(lon), float(lat)) rect = QgsRectangle(x,y,x,y) self.canvas.setExtent(rect) pt = QgsPointXY(x,y) self.highlight(pt) self.canvas.refresh() return pt def highlight(self, point): currExt = self.canvas.extent() leftPt = QgsPointXY(currExt.xMinimum(),point.y()) rightPt = QgsPointXY(currExt.xMaximum(),point.y()) topPt = QgsPointXY(point.x(),currExt.yMaximum()) bottomPt = QgsPointXY(point.x(),currExt.yMinimum()) horizLine = QgsGeometry.fromPolyline( [ leftPt , rightPt ] ) vertLine = QgsGeometry.fromPolyline( [ topPt , bottomPt ] ) self.crossRb.reset(QgsWkbTypes.LineGeometry) self.crossRb.addGeometry(horizLine, None) self.crossRb.addGeometry(vertLine, None) QTimer.singleShot(700, self.resetRubberbands) def resetRubberbands(self): self.crossRb.reset()
class RectangleMapTool(QgsMapToolEmitPoint): rectangleCreated = pyqtSignal() deactivated = pyqtSignal() def __init__(self, canvas): self.canvas = canvas QgsMapToolEmitPoint.__init__(self, self.canvas) self.rubberBand = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rubberBand.setColor(QColor(255, 0, 0, 100)) self.rubberBand.setWidth(2) self.reset() def reset(self): self.startPoint = self.endPoint = None self.isEmittingPoint = False self.rubberBand.reset(QgsWkbTypes.PolygonGeometry) def canvasPressEvent(self, e): self.startPoint = self.toMapCoordinates(e.pos()) self.endPoint = self.startPoint self.isEmittingPoint = True self.showRect(self.startPoint, self.endPoint) def canvasReleaseEvent(self, e): self.isEmittingPoint = False if self.rectangle() is not None: self.rectangleCreated.emit() def canvasMoveEvent(self, e): if not self.isEmittingPoint: return self.endPoint = self.toMapCoordinates(e.pos()) self.showRect(self.startPoint, self.endPoint) def showRect(self, startPoint, endPoint): self.rubberBand.reset(QgsWkbTypes.PolygonGeometry) if startPoint.x() == endPoint.x() or startPoint.y() == endPoint.y(): return point1 = QgsPointXY(startPoint.x(), startPoint.y()) point2 = QgsPointXY(startPoint.x(), endPoint.y()) point3 = QgsPointXY(endPoint.x(), endPoint.y()) point4 = QgsPointXY(endPoint.x(), startPoint.y()) self.rubberBand.addPoint(point1, False) self.rubberBand.addPoint(point2, False) self.rubberBand.addPoint(point3, False) # True to update canvas self.rubberBand.addPoint(point4, True) self.rubberBand.show() def rectangle(self): if self.startPoint is None or self.endPoint is None: return None elif self.startPoint.x() == self.endPoint.x() or \ self.startPoint.y() == self.endPoint.y(): return None return QgsRectangle(self.startPoint, self.endPoint) def setRectangle(self, rect): if rect == self.rectangle(): return False if rect is None: self.reset() else: self.startPoint = QgsPointXY(rect.xMaximum(), rect.yMaximum()) self.endPoint = QgsPointXY(rect.xMinimum(), rect.yMinimum()) self.showRect(self.startPoint, self.endPoint) return True def deactivate(self): QgsMapTool.deactivate(self) self.deactivated.emit()
class MapWidget(Ui_CanvasWidget, QMainWindow): def __init__(self, parent=None): super(MapWidget, self).__init__(parent) self.setupUi(self) self.firstshow = True self.layerbuttons = [] self.editfeaturestack = [] self.lastgpsposition = None self.project = None self.gps = None self.gpslogging = None self.selectionbands = defaultdict(partial(QgsRubberBand, self.canvas)) self.canvas.setCanvasColor(Qt.white) self.canvas.enableAntiAliasing(True) self.canvas.setWheelAction(QgsMapCanvas.WheelZoomToMouseCursor) if hasattr(self.canvas, 'setParallelRenderingEnabled'): self.canvas.setParallelRenderingEnabled(True) pal = QgsPalLabeling() self.canvas.mapRenderer().setLabelingEngine(pal) self.canvas.setFrameStyle(QFrame.NoFrame) self.editgroup = QActionGroup(self) self.editgroup.setExclusive(True) self.editgroup.addAction(self.actionPan) self.editgroup.addAction(self.actionZoom_In) self.editgroup.addAction(self.actionZoom_Out) self.editgroup.addAction(self.actionInfo) self.actionGPS = GPSAction(":/icons/gps", self.canvas, self) self.projecttoolbar.addAction(self.actionGPS) gpsspacewidget= QWidget() gpsspacewidget.setMinimumWidth(30) gpsspacewidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.topspaceraction = self.projecttoolbar.insertWidget(self.actionGPS, gpsspacewidget) self.dataentryselection = QAction(self.projecttoolbar) self.dataentryaction = self.projecttoolbar.insertAction(self.topspaceraction, self.dataentryselection) self.dataentryselection.triggered.connect(self.select_data_entry) self.marker = GPSMarker(self.canvas) self.marker.hide() self.currentfeatureband = QgsRubberBand(self.canvas) self.currentfeatureband.setIconSize(20) self.currentfeatureband.setWidth(10) self.currentfeatureband.setColor(QColor(186, 93, 212, 76)) self.gpsband = QgsRubberBand(self.canvas) self.gpsband.setColor(QColor(0, 0, 212, 76)) self.gpsband.setWidth(5) RoamEvents.editgeometry.connect(self.queue_feature_for_edit) RoamEvents.selectioncleared.connect(self.clear_selection) RoamEvents.selectionchanged.connect(self.highlight_selection) RoamEvents.featureformloaded.connect(self.feature_form_loaded) self.connectButtons() def init_qgisproject(self, doc): parser = ProjectParser(doc) canvasnode = parser.canvasnode self.canvas.freeze() self.canvas.mapRenderer().readXML(canvasnode) self.canvaslayers = parser.canvaslayers() self.canvas.setLayerSet(self.canvaslayers) #red = QgsProject.instance().readNumEntry( "Gui", "/CanvasColorRedPart", 255 )[0]; #green = QgsProject.instance().readNumEntry( "Gui", "/CanvasColorGreenPart", 255 )[0]; #blue = QgsProject.instance().readNumEntry( "Gui", "/CanvasColorBluePart", 255 )[0]; #color = QColor(red, green, blue); #self.canvas.setCanvasColor(color) self.canvas.updateScale() return self.canvas.mapRenderer().destinationCrs() def showEvent(self, *args, **kwargs): if self.firstshow: self.canvas.refresh() self.canvas.repaint() self.firstshow = False def feature_form_loaded(self, form, feature, project, editmode): self.currentfeatureband.setToGeometry(feature.geometry(), form.QGISLayer) def highlight_selection(self, results): self.clear_selection() for layer, features in results.iteritems(): band = self.selectionbands[layer] band.setColor(QColor(255, 0, 0, 200)) band.setIconSize(20) band.setWidth(2) band.setBrushStyle(Qt.NoBrush) band.reset(layer.geometryType()) for feature in features: band.addGeometry(feature.geometry(), layer) def highlight_active_selection(self, layer, feature, features): self.clear_selection() self.highlight_selection({layer: features}) self.currentfeatureband.setToGeometry(feature.geometry(), layer) def clear_selection(self): # Clear the main selection rubber band self.currentfeatureband.reset() # Clear the rest for band in self.selectionbands.itervalues(): band.reset() self.editfeaturestack = [] def queue_feature_for_edit(self, form, feature): def trigger_default_action(): for action in self.projecttoolbar.actions(): if action.property('dataentry') and action.isdefault: action.trigger() break self.editfeaturestack.append((form, feature)) self.load_form(form) trigger_default_action() def clear_temp_objects(self): def clear_tool_band(): """ Clear the rubber band of the active tool if it has one """ tool = self.canvas.mapTool() try: tool.clearBand() except AttributeError: # No clearBand method found, but that's cool. pass self.currentfeatureband.reset() clear_tool_band() def settings_updated(self, settings): self.actionGPS.updateGPSPort() gpslogging = settings.get('gpslogging', True) if self.gpslogging: self.gpslogging.logging = gpslogging def set_gps(self, gps, logging): self.gps = gps self.gpslogging = logging self.gps.gpsposition.connect(self.gps_update_canvas) self.gps.firstfix.connect(self.gps_first_fix) self.gps.gpsdisconnected.connect(self.gps_disconnected) def gps_update_canvas(self, position, gpsinfo): # Recenter map if we go outside of the 95% of the area if self.gpslogging.logging: self.gpsband.addPoint(position) self.gpsband.show() if roam.config.settings.get('gpscenter', True): if not self.lastgpsposition == position: self.lastposition = position rect = QgsRectangle(position, position) extentlimt = QgsRectangle(self.canvas.extent()) extentlimt.scale(0.95) if not extentlimt.contains(position): self.zoom_to_location(position) self.marker.show() self.marker.setCenter(position) def gps_first_fix(self, postion, gpsinfo): zoomtolocation = roam.config.settings.get('gpszoomonfix', True) if zoomtolocation: self.canvas.zoomScale(1000) self.zoom_to_location(postion) def zoom_to_location(self, position): rect = QgsRectangle(position, position) self.canvas.setExtent(rect) self.canvas.refresh() def gps_disconnected(self): self.marker.hide() def select_data_entry(self): def showformerror(form): pass def actions(): for form in self.project.forms: action = form.createuiaction() valid, failreasons = form.valid if not valid: roam.utils.warning("Form {} failed to load".format(form.label)) roam.utils.warning("Reasons {}".format(failreasons)) action.triggered.connect(partial(showformerror, form)) else: action.triggered.connect(partial(self.load_form, form)) yield action formpicker = PickActionDialog(msg="Select data entry form") formpicker.addactions(actions()) formpicker.exec_() def project_loaded(self, project): self.project = project self.actionPan.trigger() try: firstform = project.forms[0] self.load_form(firstform) self.dataentryselection.setVisible(True) except IndexError: self.dataentryselection.setVisible(False) # Enable the raster layers button only if the project contains a raster layer. layers = QgsMapLayerRegistry.instance().mapLayers().values() hasrasters = any(layer.type() == QgsMapLayer.RasterLayer for layer in layers) self.actionRaster.setEnabled(hasrasters) self.defaultextent = self.canvas.extent() roam.utils.info("Extent: {}".format(self.defaultextent.toString())) self.infoTool.selectionlayers = project.selectlayersmapping() self.canvas.freeze(False) self.canvas.refresh() def setMapTool(self, tool, *args): self.canvas.setMapTool(tool) def connectButtons(self): def connectAction(action, tool): action.toggled.connect(partial(self.setMapTool, tool)) def cursor(name): pix = QPixmap(name) pix = pix.scaled(QSize(24,24)) return QCursor(pix) self.zoomInTool = QgsMapToolZoom(self.canvas, False) self.zoomOutTool = QgsMapToolZoom(self.canvas, True) self.panTool = PanTool(self.canvas) self.infoTool = InfoTool(self.canvas) connectAction(self.actionZoom_In, self.zoomInTool) connectAction(self.actionZoom_Out, self.zoomOutTool) connectAction(self.actionPan, self.panTool) connectAction(self.actionInfo, self.infoTool) self.zoomInTool.setCursor(cursor(':/icons/in')) self.zoomOutTool.setCursor(cursor(':/icons/out')) self.infoTool.setCursor(cursor(':/icons/info')) self.actionRaster.triggered.connect(self.toggleRasterLayers) self.infoTool.infoResults.connect(RoamEvents.selectionchanged.emit) self.actionHome.triggered.connect(self.homeview) def homeview(self): """ Zoom the mapview canvas to the extents the project was opened at i.e. the default extent. """ self.canvas.setExtent(self.defaultextent) self.canvas.refresh() def load_form(self, form): self.clearCapatureTools() self.dataentryselection.setIcon(QIcon(form.icon)) self.dataentryselection.setText(form.icontext) self.create_capture_buttons(form) def create_capture_buttons(self, form): tool = form.getMaptool()(self.canvas) for action in tool.actions: # Create the action here. if action.ismaptool: action.toggled.connect(partial(self.setMapTool, tool)) # Set the action as a data entry button so we can remove it later. action.setProperty("dataentry", True) self.editgroup.addAction(action) self.layerbuttons.append(action) self.projecttoolbar.insertAction(self.topspaceraction, action) action.setChecked(action.isdefault) if hasattr(tool, 'geometryComplete'): add = partial(self.add_new_feature, form) tool.geometryComplete.connect(add) else: tool.finished.connect(self.openForm) tool.error.connect(partial(self.showUIMessage, form.label)) def add_new_feature(self, form, geometry): """ Add a new new feature to the given layer """ # TODO Extract into function. # NOTE This function is doing too much, acts as add and also edit. layer = form.QGISLayer if layer.geometryType() in [QGis.WKBMultiLineString, QGis.WKBMultiPoint, QGis.WKBMultiPolygon]: geometry.convertToMultiType() try: form, feature = self.editfeaturestack.pop() self.editfeaturegeometry(form, feature, newgeometry=geometry) return except IndexError: pass layer = form.QGISLayer fields = layer.pendingFields() feature = QgsFeature(fields) feature.setGeometry(geometry) for index in xrange(fields.count()): pkindexes = layer.dataProvider().pkAttributeIndexes() if index in pkindexes and layer.dataProvider().name() == 'spatialite': continue value = layer.dataProvider().defaultValue(index) feature[index] = value RoamEvents.open_feature_form(form, feature, editmode=False) def editfeaturegeometry(self, form, feature, newgeometry): # TODO Extract into function. layer = form.QGISLayer layer.startEditing() feature.setGeometry(newgeometry) layer.updateFeature(feature) saved = layer.commitChanges() if not saved: map(roam.utils.error, layer.commitErrors()) self.canvas.refresh() self.currentfeatureband.setToGeometry(feature.geometry(), layer) RoamEvents.editgeometry_complete.emit(form, feature) def clearCapatureTools(self): captureselected = False for action in self.projecttoolbar.actions(): if action.objectName() == "capture" and action.isChecked(): captureselected = True if action.property('dataentry'): self.projecttoolbar.removeAction(action) return captureselected def toggleRasterLayers(self): """ Toggle all raster layers on or off. """ if not self.canvaslayers: return #Freeze the canvas to save on UI refresh self.canvas.freeze() for layer in self.canvaslayers: if layer.layer().type() == QgsMapLayer.RasterLayer: layer.setVisible(not layer.isVisible()) # Really!? We have to reload the whole layer set every time? # WAT? self.canvas.setLayerSet(self.canvaslayers) self.canvas.freeze(False) self.canvas.refresh() def cleanup(self): self.gpsband.reset() self.gpsband.hide() self.clear_selection() self.clear_temp_objects() self.clearCapatureTools() self.canvas.freeze() self.canvas.clear() self.canvas.freeze(False) for action in self.layerbuttons: self.editgroup.removeAction(action)
class SelectDownloadExtentMapTool(QgsMapTool): def __init__(self, canvas, dialog): self.canvas = canvas self.dialog = dialog QgsMapTool.__init__(self, self.canvas) self.setCursor(Qt.CrossCursor) self.rubberBand = QgsRubberBand(self.canvas, QGis.Polygon) self.rubberBand.setColor(Qt.red) self.rubberBand.setWidth(1) self.reset() def reset(self): self.startPoint = self.endPoint = None self.isEmittingPoint = False self.rubberBand.reset(QGis.Polygon) def canvasPressEvent(self, e): self.startPoint = self.toMapCoordinates(e.pos()) self.endPoint = self.startPoint self.isEmittingPoint = True self.showRect(self.startPoint, self.endPoint) def canvasReleaseEvent(self, e): self.isEmittingPoint = False self.dialog.setExtent(self.rectangle()) self.dialog.showNormal() self.dialog.raise_() self.dialog.activateWindow() self.reset() def canvasMoveEvent(self, e): if not self.isEmittingPoint: return self.endPoint = self.toMapCoordinates(e.pos()) self.showRect(self.startPoint, self.endPoint) def showRect(self, startPoint, endPoint): self.rubberBand.reset(QGis.Polygon) if startPoint.x() == endPoint.x() or startPoint.y() == endPoint.y(): return point1 = QgsPoint(startPoint.x(), startPoint.y()) point2 = QgsPoint(startPoint.x(), endPoint.y()) point3 = QgsPoint(endPoint.x(), endPoint.y()) point4 = QgsPoint(endPoint.x(), startPoint.y()) self.rubberBand.addPoint(point1, False) self.rubberBand.addPoint(point2, False) self.rubberBand.addPoint(point3, False) self.rubberBand.addPoint(point4, True) # true to update canvas self.rubberBand.show() def rectangle(self): if self.startPoint is None or self.endPoint is None: return None elif self.startPoint.x() == self.endPoint.x() or self.startPoint.y( ) == self.endPoint.y(): return None return QgsRectangle(self.startPoint, self.endPoint)
class RectangleMapTool(QgsMapToolEmitPoint): """ Map tool that lets the user define the analysis extents. """ rectangle_created = pyqtSignal() deactivated = pyqtSignal() def __init__(self, canvas): """Constructor for the map tool. :param canvas: Canvas that tool will interact with. :type canvas: QgsMapCanvas """ self.canvas = canvas self.start_point = None self.end_point = None self.is_emitting_point = False QgsMapToolEmitPoint.__init__(self, self.canvas) self.rubber_band = QgsRubberBand(self.canvas, geometryType=QGis.Line) self.rubber_band.setColor(QColor(0, 0, 240, 100)) # Needs QGIS 2.6 # self.rubber_band.setFillColor(QColor(0, 0, 240, 0)) self.rubber_band.setWidth(1) self.reset() def reset(self): """ Clear the rubber band for the analysis extents. """ self.start_point = self.end_point = None self.is_emitting_point = False self.rubber_band.reset(QGis.Polygon) def canvasPressEvent(self, e): """ Handle canvas press events so we know when user is capturing the rect. :param e: A Qt event object. :type: QEvent """ self.start_point = self.toMapCoordinates(e.pos()) self.end_point = self.start_point self.is_emitting_point = True self.show_rectangle(self.start_point, self.end_point) def canvasReleaseEvent(self, e): """ Handle canvas release events has finished capturing e :param e: A Qt event object. :type: QEvent """ _ = e self.is_emitting_point = False self.rectangle_created.emit() def canvasMoveEvent(self, e): """ :param e: :return: """ if not self.is_emitting_point: return self.end_point = self.toMapCoordinates(e.pos()) self.show_rectangle(self.start_point, self.end_point) def show_rectangle(self, start_point, end_point): """ Show the rectangle on the canvas. :param start_point: QGIS Point object representing the origin ( top left). :type start_point: QgsPoint :param end_point: QGIS Point object representing the contra-origin ( bottom right). :type end_point: QgsPoint :return: """ self.rubber_band.reset(QGis.Polygon) if (start_point.x() == end_point.x() or start_point.y() == end_point.y()): return point1 = start_point point2 = QgsPoint(end_point.x(), start_point.y()) point3 = end_point point4 = QgsPoint(start_point.x(), end_point.y()) update_canvas = False self.rubber_band.addPoint(point1, update_canvas) self.rubber_band.addPoint(point2, update_canvas) self.rubber_band.addPoint(point3, update_canvas) self.rubber_band.addPoint(point4, update_canvas) # noinspection PyArgumentEqualDefault # no False so canvas will update # close the polygon otherwise it shows as a filled rect self.rubber_band.addPoint(point1) self.rubber_band.show() def rectangle(self): """ Accessor for the rectangle. :return: A rectangle showing the designed extent. :rtype: QgsRectangle """ if self.start_point is None or self.end_point is None: return None elif self.start_point.x() == self.end_point.x() or \ self.start_point.y() == self.end_point.y(): return None return QgsRectangle(self.start_point, self.end_point) def set_rectangle(self, rectangle): """ Set the rectangle for the selection. :param rectangle: :return: """ if rectangle == self.rectangle(): return False if rectangle is None: self.reset() else: self.start_point = QgsPoint( rectangle.xMinimum(), rectangle.yMinimum()) self.end_point = QgsPoint( rectangle.xMaximum(), rectangle.yMaximum()) self.show_rectangle(self.start_point, self.end_point) return True def deactivate(self): """ Disable the tool. """ QgsMapTool.deactivate(self) self.deactivated.emit()
class Qgis2threejsDialog(QDialog): def __init__(self, iface, objectTypeManager, pluginManager, exportSettings=None, lastTreeItemData=None): QDialog.__init__(self, iface.mainWindow()) self.iface = iface self.objectTypeManager = objectTypeManager self.pluginManager = pluginManager self._settings = exportSettings or {} self.lastTreeItemData = lastTreeItemData self.localBrowsingMode = True self.rb_quads = self.rb_point = None self.templateType = None self.currentItem = None self.currentPage = None # Set up the user interface from Designer. self.ui = ui = Ui_Qgis2threejsDialog() ui.setupUi(self) self.setWindowFlags(self.windowFlags() | Qt.WindowMinimizeButtonHint) # output html filename ui.lineEdit_OutputFilename.setText( self._settings.get("OutputFilename", "")) ui.lineEdit_OutputFilename.setPlaceholderText("[Temporary file]") # settings button icon = QIcon(os.path.join(tools.pluginDir(), "icons", "settings.png")) ui.toolButton_Settings.setIcon(icon) # popup menu displayed when settings button is pressed items = [["Load Settings...", self.loadSettings], ["Save Settings As...", self.saveSettings], [None, None], ["Clear Settings", self.clearSettings], [None, None], ["Plugin Settings...", self.pluginSettings]] self.menu = QMenu() self.menu_actions = [] for text, slot in items: if text: action = QAction(text, iface.mainWindow()) action.triggered.connect(slot) self.menu.addAction(action) self.menu_actions.append(action) else: self.menu.addSeparator() ui.toolButton_Settings.setMenu(self.menu) ui.toolButton_Settings.setPopupMode(QToolButton.InstantPopup) # progress bar and message label ui.progressBar.setVisible(False) ui.label_MessageIcon.setVisible(False) # buttons ui.pushButton_Run.clicked.connect(self.run) ui.pushButton_Close.clicked.connect(self.reject) ui.pushButton_Help.clicked.connect(self.help) # set up map tool self.previousMapTool = None self.mapTool = RectangleMapTool(iface.mapCanvas()) #self.mapTool = PointMapTool(iface.mapCanvas()) # set up the template combo box self.initTemplateList() self.ui.comboBox_Template.currentIndexChanged.connect( self.currentTemplateChanged) # set up the properties pages self.pages = {} self.pages[ppages.PAGE_WORLD] = ppages.WorldPropertyPage(self) self.pages[ppages.PAGE_CONTROLS] = ppages.ControlsPropertyPage(self) self.pages[ppages.PAGE_DEM] = ppages.DEMPropertyPage(self) self.pages[ppages.PAGE_VECTOR] = ppages.VectorPropertyPage(self) container = ui.propertyPagesContainer for page in self.pages.itervalues(): page.hide() container.addWidget(page) # build object tree self.topItemPages = { ObjectTreeItem.ITEM_WORLD: ppages.PAGE_WORLD, ObjectTreeItem.ITEM_CONTROLS: ppages.PAGE_CONTROLS, ObjectTreeItem.ITEM_DEM: ppages.PAGE_DEM} self.initObjectTree() self.ui.treeWidget.currentItemChanged.connect( self.currentObjectChanged) self.ui.treeWidget.itemChanged.connect(self.objectItemChanged) self.currentTemplateChanged() # update item visibility ui.toolButton_Browse.clicked.connect(self.browseClicked) # iface.mapCanvas().mapToolSet.connect(self.mapToolSet) # to show # button to enable own map tool def settings(self, clean=False): # save settings of current panel item = self.ui.treeWidget.currentItem() if item and self.currentPage: self.saveProperties(item, self.currentPage) # plugin version self._settings["PluginVersion"] = plugin_version # template and output html file path self._settings["Template"] = self.ui.comboBox_Template.currentText() self._settings[ "OutputFilename"] = self.ui.lineEdit_OutputFilename.text() if not clean: return self._settings # clean up settings - remove layers that don't exist in the layer # registry registry = QgsMapLayerRegistry.instance() for itemId in [ObjectTreeItem.ITEM_OPTDEM, ObjectTreeItem.ITEM_POINT, ObjectTreeItem.ITEM_LINE, ObjectTreeItem.ITEM_POLYGON]: parent = self._settings.get(itemId, {}) for layerId in parent.keys(): if registry.mapLayer(layerId) is None: del parent[layerId] return self._settings def setSettings(self, settings): self._settings = settings # template and output html file path templateName = settings.get("Template") if templateName: cbox = self.ui.comboBox_Template index = cbox.findText(templateName) if index != -1: cbox.setCurrentIndex(index) filename = settings.get("OutputFilename") if filename: self.ui.lineEdit_OutputFilename.setText(filename) # update object tree self.ui.treeWidget.blockSignals(True) self.initObjectTree() self.ui.treeWidget.blockSignals(False) # update tree item visibility self.templateType = None self.currentTemplateChanged() def loadSettings(self): # file open dialog directory = QgsProject.instance().homePath() if not directory: directory = os.path.split( self.ui.lineEdit_OutputFilename.text())[0] if not directory: directory = QDir.homePath() filterString = "Settings files (*.qto3settings);;All files (*.*)" filename = QFileDialog.getOpenFileName( self, "Load Export Settings", directory, filterString) if not filename: return # load settings from file (.qto3settings) import json with open(filename) as f: settings = json.load(f) self.setSettings(settings) def saveSettings(self, filename=None): if not filename: # file save dialog directory = QgsProject.instance().homePath() if not directory: directory = os.path.split( self.ui.lineEdit_OutputFilename.text())[0] if not directory: directory = QDir.homePath() filename = QFileDialog.getSaveFileName( self, "Save Export Settings", directory, "Settings files (*.qto3settings)") if not filename: return # append .qto3settings extension if filename doesn't have if os.path.splitext(filename)[1].lower() != ".qto3settings": filename += ".qto3settings" # save settings to file (.qto3settings) import codecs import json with codecs.open(filename, "w", "UTF-8") as f: json.dump( self.settings(True), f, ensure_ascii=False, indent=2, sort_keys=True) logMessage(u"Settings saved: {0}".format(filename)) def clearSettings(self): if QMessageBox.question(self, "Qgis2threejs", "Are you sure to clear all export settings?", QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Ok: self.setSettings({}) def pluginSettings(self): from settingsdialog import SettingsDialog dialog = SettingsDialog(self) if dialog.exec_(): self.pluginManager.reloadPlugins() self.pages[ppages.PAGE_DEM].initLayerComboBox() def showMessageBar(self, text, level=QgsMessageBar.INFO): # from src/gui/qgsmessagebaritem.cpp if level == QgsMessageBar.CRITICAL: msgIcon = "/mIconCritical.png" bgColor = "#d65253" elif level == QgsMessageBar.WARNING: msgIcon = "/mIconWarn.png" bgColor = "#ffc800" else: msgIcon = "/mIconInfo.png" bgColor = "#e7f5fe" stylesheet = "QLabel {{ background-color:{0}; }}".format(bgColor) label = self.ui.label_MessageIcon label.setPixmap(QgsApplication.getThemeIcon(msgIcon).pixmap(24)) label.setStyleSheet(stylesheet) label.setVisible(True) label = self.ui.label_Status label.setText(text) label.setStyleSheet(stylesheet) def clearMessageBar(self): self.ui.label_MessageIcon.setVisible(False) self.ui.label_Status.setText("") self.ui.label_Status.setStyleSheet( "QLabel { background-color: rgba(0, 0, 0, 0); }") def initTemplateList(self): cbox = self.ui.comboBox_Template cbox.clear() templateDir = QDir(tools.templateDir()) for i, entry in enumerate(templateDir.entryList(["*.html", "*.htm"])): cbox.addItem(entry) config = tools.getTemplateConfig(entry) # get template type templateType = config.get("type", "plain") cbox.setItemData(i, templateType, Qt.UserRole) # set tool tip text desc = config.get("description", "") if desc: cbox.setItemData(i, desc, Qt.ToolTipRole) # select the template of the settings templatePath = self._settings.get("Template") # if no template setting, select the last used template if not templatePath: templatePath = QSettings().value( "/Qgis2threejs/lastTemplate", def_vals.template, type=unicode) if templatePath: index = cbox.findText(templatePath) if index != -1: cbox.setCurrentIndex(index) return index return -1 def initObjectTree(self): tree = self.ui.treeWidget tree.clear() # add vector and raster layers into tree widget topItems = {} for id, name in zip(ObjectTreeItem.topItemIds, ObjectTreeItem.topItemNames): item = QTreeWidgetItem(tree, [name]) item.setData(0, Qt.UserRole, id) topItems[id] = item optDEMChecked = False for layer in self.iface.legendInterface().layers(): parentId = ObjectTreeItem.parentIdByLayer(layer) if parentId is None: continue item = QTreeWidgetItem(topItems[parentId], [layer.name()]) isVisible = self._settings.get(parentId, {}).get(layer.id(), {}).get( "visible", False) # self.iface.legendInterface().isLayerVisible(layer) check_state = Qt.Checked if isVisible else Qt.Unchecked item.setData(0, Qt.CheckStateRole, check_state) item.setData(0, Qt.UserRole, layer.id()) if parentId == ObjectTreeItem.ITEM_OPTDEM and isVisible: optDEMChecked = True for id, item in topItems.iteritems(): if id != ObjectTreeItem.ITEM_OPTDEM or optDEMChecked: tree.expandItem(item) # disable additional DEM item which is selected as main DEM layerId = self._settings.get( ObjectTreeItem.ITEM_DEM, {}).get("comboBox_DEMLayer") if layerId: self.primaryDEMChanged(layerId) def saveProperties(self, item, page): properties = page.properties() parent = item.parent() if parent is None: # top level item self._settings[item.data(0, Qt.UserRole)] = properties else: # layer item parentId = parent.data(0, Qt.UserRole) if parentId not in self._settings: self._settings[parentId] = {} self._settings[parentId][item.data(0, Qt.UserRole)] = properties def setCurrentTreeItemByData(self, data): it = QTreeWidgetItemIterator(self.ui.treeWidget) while it.value(): if it.value().data(0, Qt.UserRole) == data: self.ui.treeWidget.setCurrentItem(it.value()) return True it += 1 return False def currentTemplateChanged(self, index=None): cbox = self.ui.comboBox_Template templateType = cbox.itemData(cbox.currentIndex(), Qt.UserRole) if templateType == self.templateType: return # hide items unsupported by template tree = self.ui.treeWidget for i, id in enumerate(ObjectTreeItem.topItemIds): hidden = (templateType == "sphere" and id != ObjectTreeItem.ITEM_CONTROLS) tree.topLevelItem(i).setHidden(hidden) # set current tree item if templateType == "sphere": tree.setCurrentItem( tree.topLevelItem( ObjectTreeItem.topItemIndex( ObjectTreeItem.ITEM_CONTROLS))) # restore selection elif self.lastTreeItemData is None or not self.setCurrentTreeItemByData(self.lastTreeItemData): tree.setCurrentItem(tree.topLevelItem(ObjectTreeItem.topItemIndex( ObjectTreeItem.ITEM_DEM))) # default selection for plain is DEM # display messages self.clearMessageBar() if templateType != "sphere": # show message if crs unit is degrees mapSettings = self.iface.mapCanvas().mapSettings( ) if QGis.QGIS_VERSION_INT >= 20300 else self.iface.mapCanvas().mapRenderer() if mapSettings.destinationCrs().mapUnits() in [QGis.Degrees]: self.showMessageBar( "The unit of current CRS is degrees, so terrain may not appear well.", QgsMessageBar.WARNING) self.templateType = templateType def currentObjectChanged(self, currentItem, previousItem): # save properties of previous item if previousItem and self.currentPage: self.saveProperties(previousItem, self.currentPage) self.currentItem = currentItem self.currentPage = None # hide text browser and all pages self.ui.textBrowser.hide() for page in self.pages.itervalues(): page.hide() parent = currentItem.parent() if parent is None: topItemIndex = currentItem.data(0, Qt.UserRole) pageType = self.topItemPages.get(topItemIndex, ppages.PAGE_NONE) page = self.pages.get(pageType, None) if page is None: self.showDescription(topItemIndex) return page.setup(self._settings.get(topItemIndex)) page.show() else: parentId = parent.data(0, Qt.UserRole) layerId = currentItem.data(0, Qt.UserRole) layer = QgsMapLayerRegistry.instance().mapLayer(unicode(layerId)) if layer is None: return layerType = layer.type() if layerType == QgsMapLayer.RasterLayer: page = self.pages[ppages.PAGE_DEM] page.setup( self._settings.get( parentId, {}).get( layerId, None), layer, False) elif layerType == QgsMapLayer.VectorLayer: page = self.pages[ppages.PAGE_VECTOR] page.setup( self._settings.get( parentId, {}).get( layerId, None), layer) else: return page.show() self.currentPage = page def objectItemChanged(self, item, column): parent = item.parent() if parent is None: return # checkbox of optional layer checked/unchecked if item == self.currentItem: if self.currentPage: # update enablement of property widgets self.currentPage.itemChanged(item) else: # select changed item self.ui.treeWidget.setCurrentItem(item) # set visible property #visible = item.data(0, Qt.CheckStateRole) == Qt.Checked #parentId = parent.data(0, Qt.UserRole) #layerId = item.data(0, Qt.UserRole) #self._settings.get(parentId, {}).get(layerId, {})["visible"] = visible def primaryDEMChanged(self, layerId): tree = self.ui.treeWidget parent = tree.topLevelItem( ObjectTreeItem.topItemIndex( ObjectTreeItem.ITEM_OPTDEM)) tree.blockSignals(True) for i in range(parent.childCount()): item = parent.child(i) isPrimary = item.data(0, Qt.UserRole) == layerId item.setDisabled(isPrimary) tree.blockSignals(False) def showDescription(self, topItemIndex): fragment = {ObjectTreeItem.ITEM_OPTDEM: "additional-dem", ObjectTreeItem.ITEM_POINT: "point", ObjectTreeItem.ITEM_LINE: "line", ObjectTreeItem.ITEM_POLYGON: "polygon"}.get(topItemIndex) url = "http://qgis2threejs.readthedocs.org/en/docs-release/ExportSettings.html" if fragment: url += "#" + fragment html = '<a href="{0}">Online Help</a> about this item'.format(url) self.ui.textBrowser.setHtml(html) self.ui.textBrowser.show() def numericFields(self, layer): # get attributes of a sample feature and create numeric field name list numeric_fields = [] f = QgsFeature() layer.getFeatures().nextFeature(f) for field in f.fields(): isNumeric = False try: float(f.attribute(field.name())) isNumeric = True except ValueError: pass if isNumeric: numeric_fields.append(field.name()) return numeric_fields def mapTo3d(self): canvas = self.iface.mapCanvas() mapSettings = canvas.mapSettings( ) if QGis.QGIS_VERSION_INT >= 20300 else canvas.mapRenderer() world = self._settings.get(ObjectTreeItem.ITEM_WORLD, {}) bs = float(world.get("lineEdit_BaseSize", def_vals.baseSize)) ve = float(world.get("lineEdit_zFactor", def_vals.zExaggeration)) vs = float(world.get("lineEdit_zShift", def_vals.zShift)) return MapTo3D(mapSettings, bs, ve, vs) def progress(self, percentage=None, statusMsg=None): ui = self.ui if percentage is not None: ui.progressBar.setValue(percentage) if percentage == 100: ui.progressBar.setVisible(False) ui.label_Status.setText("") else: ui.progressBar.setVisible(True) if statusMsg is not None: ui.label_Status.setText(statusMsg) ui.label_Status.repaint() QgsApplication.processEvents(QEventLoop.ExcludeUserInputEvents) def run(self): self.endPointSelection() ui = self.ui filename = ui.lineEdit_OutputFilename.text() # ""=Temporary file if filename and os.path.exists(filename): if QMessageBox.question(self, "Qgis2threejs", "Output file already exists. Overwrite it?", QMessageBox.Ok | QMessageBox.Cancel) != QMessageBox.Ok: return # export to web (three.js) export_settings = ExportSettings( self.pluginManager, self.localBrowsingMode) export_settings.loadSettings(self.settings()) export_settings.setMapCanvas(self.iface.mapCanvas()) err_msg = export_settings.checkValidity() if err_msg is not None: QMessageBox.warning( self, "Qgis2threejs", err_msg or "Invalid settings") return ui.pushButton_Run.setEnabled(False) ui.toolButton_Settings.setVisible(False) self.clearMessageBar() self.progress(0) if export_settings.exportMode == ExportSettings.PLAIN_MULTI_RES: # update quads and point on map canvas self.createRubberBands( export_settings.baseExtent, export_settings.quadtree()) # export ret = exportToThreeJS( export_settings, self.iface.legendInterface(), self.objectTypeManager, self.progress) self.progress(100) ui.pushButton_Run.setEnabled(True) if not ret: ui.toolButton_Settings.setVisible(True) return self.clearRubberBands() # store last selections settings = QSettings() settings.setValue( "/Qgis2threejs/lastTemplate", export_settings.templatePath) settings.setValue( "/Qgis2threejs/lastControls", export_settings.controls) # open web browser if not tools.openHTMLFile(export_settings.htmlfilename): ui.toolButton_Settings.setVisible(True) return # close dialog QDialog.accept(self) def reject(self): # save properties of current object item = self.ui.treeWidget.currentItem() if item and self.currentPage: self.saveProperties(item, self.currentPage) self.endPointSelection() self.clearRubberBands() QDialog.reject(self) def help(self): url = "http://qgis2threejs.readthedocs.org/" import webbrowser webbrowser.open(url, new=2) # new=2: new tab if possible def startPointSelection(self): canvas = self.iface.mapCanvas() if self.previousMapTool != self.mapTool: self.previousMapTool = canvas.mapTool() canvas.setMapTool(self.mapTool) self.pages[ppages.PAGE_DEM].toolButton_PointTool.setVisible(False) def endPointSelection(self): self.mapTool.reset() if self.previousMapTool is not None: self.iface.mapCanvas().setMapTool(self.previousMapTool) def mapToolSet(self, mapTool): return # TODO: unstable if mapTool != self.mapTool and self.currentPage is not None: if self.currentPage.pageType == ppages.PAGE_DEM and self.currentPage.isPrimary: self.currentPage.toolButton_PointTool.setVisible(True) def createRubberBands(self, baseExtent, quadtree): self.clearRubberBands() # create quads with rubber band self.rb_quads = QgsRubberBand(self.iface.mapCanvas(), QGis.Line) self.rb_quads.setColor(Qt.blue) self.rb_quads.setWidth(1) quads = quadtree.quads() for quad in quads: geom = baseExtent.subrectangle(quad.rect).geometry() self.rb_quads.addGeometry(geom, None) self.log("Quad count: %d" % len(quads)) if not quadtree.focusRect: return # create a point with rubber band if quadtree.focusRect.width() == 0 or quadtree.focusRect.height() == 0: npt = quadtree.focusRect.center() self.rb_point = QgsRubberBand(self.iface.mapCanvas(), QGis.Point) self.rb_point.setColor(Qt.red) self.rb_point.addPoint(baseExtent.point(npt)) def clearRubberBands(self): # clear quads and point if self.rb_quads: self.iface.mapCanvas().scene().removeItem(self.rb_quads) self.rb_quads = None if self.rb_point: self.iface.mapCanvas().scene().removeItem(self.rb_point) self.rb_point = None def browseClicked(self): directory = os.path.split(self.ui.lineEdit_OutputFilename.text())[0] if not directory: directory = QDir.homePath() filename = QFileDialog.getSaveFileName( self, self.tr("Output filename"), directory, "HTML file (*.html *.htm)", options=QFileDialog.DontConfirmOverwrite) if not filename: return # append .html extension if filename doesn't have either .html or .htm if filename[-5:].lower() != ".html" and filename[-4:].lower() != ".htm": filename += ".html" self.ui.lineEdit_OutputFilename.setText(filename) def log(self, msg): if debug_mode: qDebug(msg)
from PyQt5.QtCore import Qt from PyQt5.QtGui import QColor from qgis.core import Qgis from qgis.gui import QgsMapToolEmitPoint, QgsRubberBand previousMapTool = iface.mapCanvas().mapTool() myMapTool = QgsMapToolEmitPoint(iface.mapCanvas()) # create the polygon rubber band associated to the current canvas myRubberBand = QgsRubberBand(iface.mapCanvas(), Qgis.Polygon) # set rubber band style color = QColor("red") color.setAlpha(50) myRubberBand.setColor(color) def showCoordinates(currentPos): if myRubberBand and myRubberBand.numberOfVertices(): myRubberBand.removeLastPoint() myRubberBand.addPoint(currentPos) iface.mapCanvas().xyCoordinates.connect(showCoordinates) def manageClick(currentPos, clickedButton): if clickedButton == Qt.LeftButton: myRubberBand.addPoint(currentPos) # terminate rubber band editing session if clickedButton == Qt.RightButton: # remove showCoordinates map canvas callback