class VideoWidget(QVideoWidget): def __init__(self, parent=None): ''' Constructor ''' super().__init__(parent) self.surface = VideoWidgetSurface(self) self.setAttribute(Qt.WA_OpaquePaintEvent) self.Tracking_Video_RubberBand = QRubberBand(QRubberBand.Rectangle, self) self.Censure_RubberBand = QRubberBand(QRubberBand.Rectangle, self) color_blue = QColor(Qt.blue) color_black = QColor(Qt.black) color_amber = QColor(252, 215, 108) pal_blue = QPalette() pal_blue.setBrush(QPalette.Highlight, QBrush(color_blue)) self.Tracking_Video_RubberBand.setPalette(pal_blue) pal_black = QPalette() pal_black.setBrush(QPalette.Highlight, QBrush(color_black)) self.Censure_RubberBand.setPalette(pal_black) self._interaction = InteractionState() self._filterSatate = FilterState() self._isinit = False self._MGRS = False self.gt = None self.drawCesure = [] self.poly_coordinates, self.drawPtPos, self.drawLines, self.drawMeasureDistance, self.drawMeasureArea, self.drawPolygon = [], [], [], [], [], [] # Draw Polygon Canvas Rubberband self.poly_Canvas_RubberBand = QgsRubberBand( iface.mapCanvas(), True) # Polygon type # set rubber band style self.poly_Canvas_RubberBand.setColor(color_amber) self.poly_Canvas_RubberBand.setWidth(3) # Tracking Canvas Rubberband self.Track_Canvas_RubberBand = QgsRubberBand( iface.mapCanvas(), QgsWkbTypes.LineGeometry) # set rubber band style self.Track_Canvas_RubberBand.setColor(color_blue) self.Track_Canvas_RubberBand.setWidth(5) # Cursor Canvas Rubberband self.Cursor_Canvas_RubberBand = QgsRubberBand( iface.mapCanvas(), QgsWkbTypes.PointGeometry) self.Cursor_Canvas_RubberBand.setWidth(4) self.Cursor_Canvas_RubberBand.setColor(QColor(255, 100, 100, 250)) self.Cursor_Canvas_RubberBand.setIcon(QgsRubberBand.ICON_FULL_DIAMOND) self.parent = parent.parent() palette = self.palette() palette.setColor(QPalette.Background, Qt.transparent) self.setPalette(palette) self.origin, self.dragPos = QPoint(), QPoint() self.tapTimer = QBasicTimer() self.brush = QBrush(color_black) self.blue_Pen = QPen(color_blue, 3) def removeLastLine(self): ''' Remove Last Line Objects ''' if self.drawLines: try: if self.drawLines[-1][3] == "mouseMoveEvent": del self.drawLines[-1] # Remove mouseMoveEvent element except Exception: None for pt in range(len(self.drawLines) - 1, -1, -1): del self.drawLines[pt] try: if self.drawLines[pt - 1][0] is None: break except Exception: None self.UpdateSurface() AddDrawLineOnMap(self.drawLines) return def removeLastSegmentLine(self): ''' Remove Last Segment Line Objects ''' try: if self.drawLines[-1][3] == "mouseMoveEvent": del self.drawLines[-1] # Remove mouseMoveEvent element except Exception: None if self.drawLines: if self.drawLines[-1][0] is None: del self.drawLines[-1] del self.drawLines[-1] self.UpdateSurface() AddDrawLineOnMap(self.drawLines) return def removeAllLines(self): ''' Resets Line List ''' if self.drawLines: self.drawLines = [] self.UpdateSurface() # Clear all Layer RemoveAllDrawLineOnMap() def ResetDrawMeasureDistance(self): ''' Resets Measure Distance List ''' self.drawMeasureDistance = [] def ResetDrawMeasureArea(self): ''' Resets Measure Area List ''' self.drawMeasureArea = [] def removeAllCensure(self): ''' Remove All Censure Objects ''' if self.drawCesure: self.drawCesure = [] self.UpdateSurface() def removeLastCensured(self): ''' Remove Last Censure Objects ''' if self.drawCesure: del self.drawCesure[-1] self.UpdateSurface() def removeLastPoint(self): ''' Remove All Point Drawer Objects ''' if self.drawPtPos: del self.drawPtPos[-1] self.UpdateSurface() RemoveLastDrawPointOnMap() return def removeAllPoint(self): ''' Remove All Point Drawer Objects ''' if self.drawPtPos: self.drawPtPos = [] self.UpdateSurface() # Clear all Layer RemoveAllDrawPointOnMap() return def removeAllPolygon(self): ''' Remove All Polygon Drawer Objects ''' if self.drawPolygon: self.drawPolygon = [] self.UpdateSurface() # Clear all Layer RemoveAllDrawPolygonOnMap() def removeLastPolygon(self): ''' Remove Last Polygon Drawer Objects ''' if self.drawPolygon: try: if self.drawPolygon[-1][3] == "mouseMoveEvent": del self.drawPolygon[-1] # Remove mouseMoveEvent element except Exception: None for pt in range(len(self.drawPolygon) - 1, -1, -1): del self.drawPolygon[pt] try: if self.drawPolygon[pt - 1][0] is None: break except Exception: None self.UpdateSurface() # remove last index layer RemoveLastDrawPolygonOnMap() def keyPressEvent(self, event): '''Exit fullscreen :type event: QKeyEvent :param event: :return: ''' if event.key() == Qt.Key_Escape and self.isFullScreen(): self.setFullScreen(False) event.accept() elif event.key() == Qt.Key_Enter and event.modifiers() & Qt.Key_Alt: self.setFullScreen(not self.isFullScreen()) event.accept() else: super().keyPressEvent(event) def mouseDoubleClickEvent(self, event): """ Mouse double click event :type event: QMouseEvent :param event: :return: """ if GetImageHeight() == 0: return if(not vut.IsPointOnScreen(event.x(), event.y(), self.surface)): return if self.gt is not None and self._interaction.lineDrawer: self.drawLines.append([None, None, None]) return if self.gt is not None and self._interaction.measureDistance: self.drawMeasureDistance.append([None, None, None]) return if self.gt is not None and self._interaction.measureArea: self.drawMeasureArea.append([None, None, None]) return if self.gt is not None and self._interaction.polygonDrawer: ok = AddDrawPolygonOnMap(self.poly_coordinates) # Prevent invalid geometry (Polygon with 2 points) if not ok: return self.drawPolygon.append([None, None, None]) # Empty RubberBand for _ in range(self.poly_Canvas_RubberBand.numberOfVertices()): self.poly_Canvas_RubberBand.removeLastPoint() # Empty List self.poly_coordinates = [] return self.UpdateSurface() self.setFullScreen(not self.isFullScreen()) event.accept() def videoSurface(self): ''' Return video Surface ''' return self.surface def UpdateSurface(self): ''' Update Video Surface only is is stopped or paused ''' if self.parent.playerState in (QMediaPlayer.StoppedState, QMediaPlayer.PausedState): self.update() QApplication.processEvents() def sizeHint(self): ''' This property holds the recommended size for the widget ''' return self.surface.surfaceFormat().sizeHint() def currentFrame(self): ''' Return current frame QImage ''' return self.surface.image def SetInvertColor(self, value): '''Set Invert color filter @type value: bool @param value: @return: ''' self._filterSatate.invertColorFilter = value def SetObjectTracking(self, value): '''Set Object Tracking @type value: bool @param value: @return: ''' self._interaction.objectTracking = value def SetMeasureDistance(self, value): '''Set measure Distance @type value: bool @param value: @return: ''' self._interaction.measureDistance = value def SetMeasureArea(self, value): '''Set measure Area @type value: bool @param value: @return: ''' self._interaction.measureArea = value def SetHandDraw(self, value): '''Set Hand Draw @type value: bool @param value: @return: ''' self._interaction.HandDraw = value def SetCensure(self, value): '''Set Censure Video Parts @type value: bool @param value: @return: ''' self._interaction.censure = value def SetMGRS(self, value): '''Set MGRS Cursor Coordinates @type value: bool @param value: @return: ''' self._MGRS = value def SetGray(self, value): '''Set gray scale @type value: bool @param value: @return: ''' self._filterSatate.grayColorFilter = value def SetMirrorH(self, value): '''Set Horizontal Mirror @type value: bool @param value: @return: ''' self._filterSatate.MirroredHFilter = value def SetNDVI(self, value): '''Set NDVI @type value: bool @param value: @return: ''' self._filterSatate.NDVI = value def SetEdgeDetection(self, value): '''Set Canny Edge filter @type value: bool @param value: @return: ''' self._filterSatate.edgeDetectionFilter = value def SetAutoContrastFilter(self, value): '''Set Automatic Contrast filter @type value: bool @param value: @return: ''' self._filterSatate.contrastFilter = value def SetMonoFilter(self, value): '''Set mono filter @type value: bool @param value: @return: ''' self._filterSatate.monoFilter = value def RestoreFilters(self): ''' Remove and restore all video filters ''' self._filterSatate.clear() def RestoreDrawer(self): ''' Remove and restore all Drawer Options ''' self._interaction.clear() # Magnifier Glass self.dragPos = QPoint() self.tapTimer.stop() def RemoveCanvasRubberbands(self): ''' Remove Canvas Rubberbands ''' self.poly_Canvas_RubberBand.reset() self.Track_Canvas_RubberBand.reset(QgsWkbTypes.LineGeometry) self.Cursor_Canvas_RubberBand.reset(QgsWkbTypes.PointGeometry) def paintEvent(self, event): """ @type event: QPaintEvent @param event: @return: """ if not self.surface.isActive(): return self.painter = QPainter(self) self.painter.setRenderHint(QPainter.HighQualityAntialiasing) region = event.region() self.painter.fillRect(region.boundingRect(), self.brush) # Background painter color try: self.surface.paint(self.painter) SetImageSize(self.currentFrame().width(), self.currentFrame().height()) except Exception: None # Prevent draw on video if not started or finished if self.parent.player.position() == 0: self.painter.end() return self.gt = GetGCPGeoTransform() # Draw On Video draw.drawOnVideo(self.drawPtPos, self.drawLines, self.drawPolygon, self.drawMeasureDistance, self.drawMeasureArea, self.drawCesure, self.painter, self.surface, self.gt) # Draw On Video Object tracking test if self._interaction.objectTracking and self._isinit: frame = convertQImageToMat(self.currentFrame()) offset = self.surface.videoRect() # Update tracker result = resize(frame, (offset.width(), offset.height())) ok, bbox = self.tracker.update(result) # Draw bounding box if ok: # check negative values x = bbox[0] + offset.x() y = bbox[1] + offset.y() if vut.IsPointOnScreen(x, y, self.surface): self.painter.setPen(self.blue_Pen) self.painter.drawRect(x, y, bbox[2], bbox[3]) # Get Track object center xc = x + (bbox[2] / 2) yc = y + (bbox[3] / 2) p = QPoint(xc, yc) Longitude, Latitude, _ = vut.GetPointCommonCoords( p, self.surface) # Draw Rubber Band on canvas self.Track_Canvas_RubberBand.addPoint(QgsPointXY(Longitude, Latitude)) else: self._isinit = False del self.tracker # Magnifier Glass if self._interaction.magnifier and not self.dragPos.isNull(): draw.drawMagnifierOnVideo(self, self.dragPos, self.currentFrame(), self.painter) # Stamp On Video if self._interaction.stamp: draw.drawStampOnVideo(self, self.painter) self.painter.end() return def resizeEvent(self, _): """ @type _: QMouseEvent @param _: @return: """ self.surface.updateVideoRect() self.update() # Magnifier Glass if self._interaction.magnifier and not self.dragPos.isNull(): draw.drawMagnifierOnVideo(self, self.dragPos, self.currentFrame(), self.painter) # QApplication.processEvents() def AddMoveEventValue(self, values, Longitude, Latitude, Altitude): """ Remove and Add move value for fluid drawing @type values: list @param values: Points list @type Longitude: float @param Longitude: Longitude value @type Latitude: float @param Latitude: Latitude value @type Altitude: float @param Altitude: Altitude value """ for idx, pt in enumerate(values): if pt[-1] == "mouseMoveEvent": del values[idx] values.append([Longitude, Latitude, Altitude, "mouseMoveEvent"]) self.UpdateSurface() def mouseMoveEvent(self, event): """ @type event: QMouseEvent @param event: @return: """ # Magnifier mouseMoveEvent # Magnifier can move on black screen for show image borders if self._interaction.magnifier: if event.buttons(): self.dragPos = event.pos() self.UpdateSurface() # check if the point is on picture (not in black borders) if(not vut.IsPointOnScreen(event.x(), event.y(), self.surface)): self.setCursor(QCursor(Qt.ArrowCursor)) self.Cursor_Canvas_RubberBand.reset(QgsWkbTypes.PointGeometry) return # Prevent draw on video if not started or finished if self.parent.player.position() == 0: return # Mouser cursor drawing if self._interaction.pointDrawer or self._interaction.polygonDrawer or self._interaction.lineDrawer or self._interaction.measureDistance or self._interaction.measureArea or self._interaction.censure or self._interaction.objectTracking: self.setCursor(QCursor(Qt.CrossCursor)) # Cursor Coordinates if self.gt is not None: Longitude, Latitude, Altitude = vut.GetPointCommonCoords( event, self.surface) tr = QgsCoordinateTransform( QgsCoordinateReferenceSystem( 'EPSG:4326' ), iface.mapCanvas().mapSettings().destinationCrs(), QgsProject.instance().transformContext() ) mapPt = tr.transform( QgsPointXY(Longitude, Latitude) ) vertices = self.Cursor_Canvas_RubberBand.numberOfVertices() if vertices > 0: self.Cursor_Canvas_RubberBand.removePoint(0, True, 0) self.Cursor_Canvas_RubberBand.movePoint( mapPt, 0) else: self.Cursor_Canvas_RubberBand.addPoint( mapPt ) if self._MGRS: try: mgrsCoords = mgrs.toMgrs(Latitude, Longitude) except Exception: mgrsCoords = "" txt = "<span style='font-size:9pt; font-weight:normal;'>" + \ ("%s" % mgrsCoords) + "</span>" else: txt = "<span style='font-size:10pt; font-weight:bold;'>Lon : </span>" txt += "<span style='font-size:9pt; font-weight:normal;'>" + \ ("%.3f" % Longitude) + "</span>" txt += "<span style='font-size:10pt; font-weight:bold;'> Lat : </span>" txt += "<span style='font-size:9pt; font-weight:normal;'>" + \ ("%.3f" % Latitude) + "</span>" if hasElevationModel(): txt += "<span style='font-size:10pt; font-weight:bold;'> Alt : </span>" txt += "<span style='font-size:9pt; font-weight:normal;'>" + \ ("%.0f" % Altitude) + "</span>" else: txt += "<span style='font-size:10pt; font-weight:bold;'> Alt : </span>" txt += "<span style='font-size:9pt; font-weight:normal;'>-</span>" self.parent.lb_cursor_coord.setText(txt) # Polygon drawer mouseMoveEvent if self._interaction.polygonDrawer: self.AddMoveEventValue(self.drawPolygon, Longitude, Latitude, Altitude) # Line drawer mouseMoveEvent if self._interaction.lineDrawer: self.AddMoveEventValue(self.drawLines, Longitude, Latitude, Altitude) # Measure Distance drawer mouseMoveEvent if self._interaction.measureDistance and self.drawMeasureDistance: self.AddMoveEventValue(self.drawMeasureDistance, Longitude, Latitude, Altitude) # Measure Area drawer mouseMoveEvent if self._interaction.measureArea and self.drawMeasureArea: self.AddMoveEventValue(self.drawMeasureArea, Longitude, Latitude, Altitude) else: self.parent.lb_cursor_coord.setText("<span style='font-size:10pt; font-weight:bold;'>Lon :</span>" + "<span style='font-size:9pt; font-weight:normal;'>-</span>" + "<span style='font-size:10pt; font-weight:bold;'> Lat :</span>" + "<span style='font-size:9pt; font-weight:normal;'>-</span>" + "<span style='font-size:10pt; font-weight:bold;'> Alt :</span>" + "<span style='font-size:9pt; font-weight:normal;'>-</span>") if not event.buttons(): return # Object tracking rubberband if not self.Tracking_Video_RubberBand.isHidden(): self.Tracking_Video_RubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) # Censure rubberband if not self.Censure_RubberBand.isHidden(): self.Censure_RubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) def timerEvent(self, _): """ Time Event (Magnifier method)""" if not self._interaction.magnifier: self.activateMagnifier() def mousePressEvent(self, event): """ @type event: QMouseEvent @param event: @return: """ if GetImageHeight() == 0: return # Prevent draw on video if not started or finished if self.parent.player.position() == 0: return if event.button() == Qt.LeftButton: # Magnifier Glass if self._interaction.magnifier: self.dragPos = event.pos() self.tapTimer.stop() self.tapTimer.start(10, self) if(not vut.IsPointOnScreen(event.x(), event.y(), self.surface)): return # point drawer if self.gt is not None and self._interaction.pointDrawer: Longitude, Latitude, Altitude = vut.GetPointCommonCoords( event, self.surface) pointIndex = len(self.drawPtPos) + 1 AddDrawPointOnMap(pointIndex, Longitude, Latitude, Altitude) self.drawPtPos.append([Longitude, Latitude, Altitude]) # polygon drawer if self.gt is not None and self._interaction.polygonDrawer: Longitude, Latitude, Altitude = vut.GetPointCommonCoords( event, self.surface) self.poly_Canvas_RubberBand.addPoint(QgsPointXY(Longitude, Latitude)) self.poly_coordinates.extend(QgsPointXY(Longitude, Latitude)) self.drawPolygon.append([Longitude, Latitude, Altitude]) # line drawer if self.gt is not None and self._interaction.lineDrawer: Longitude, Latitude, Altitude = vut.GetPointCommonCoords( event, self.surface) self.drawLines.append([Longitude, Latitude, Altitude]) AddDrawLineOnMap(self.drawLines) self.origin = event.pos() # Object Tracking Interaction if self._interaction.objectTracking: self.Tracking_Video_RubberBand.setGeometry( QRect(self.origin, QSize())) self.Tracking_Video_RubberBand.show() # Censure Interaction if self._interaction.censure: self.Censure_RubberBand.setGeometry( QRect(self.origin, QSize())) self.Censure_RubberBand.show() # Measure Distance drawer if self.gt is not None and self._interaction.measureDistance: Longitude, Latitude, Altitude = vut.GetPointCommonCoords( event, self.surface) self.drawMeasureDistance.append([Longitude, Latitude, Altitude]) # Measure Distance drawer if self.gt is not None and self._interaction.measureArea: Longitude, Latitude, Altitude = vut.GetPointCommonCoords( event, self.surface) self.drawMeasureArea.append([Longitude, Latitude, Altitude]) # if not called, the paint event is not triggered. self.UpdateSurface() def activateMagnifier(self): """ Activate Magnifier Glass """ self.tapTimer.stop() self.UpdateSurface() def SetMagnifier(self, value): """Set Magnifier Glass @type value: bool @param value: """ self._interaction.magnifier = value # We avoid that the second time we activate the tool, save the previous position. # Always keep the same behavior of the tool if not value: self.dragPos = QPoint() self.tapTimer.stop() def SetStamp(self, value): """Set Stamp @type value: bool @param value: """ self._interaction.stamp = value def SetPointDrawer(self, value): """Set Point Drawer @type value: bool @param value: """ self._interaction.pointDrawer = value def SetLineDrawer(self, value): """Set Line Drawer @type value: bool @param value: """ self._interaction.lineDrawer = value def SetPolygonDrawer(self, value): """Set Polygon Drawer @type value: bool @param value: """ self._interaction.polygonDrawer = value def mouseReleaseEvent(self, _): """ @type event: QMouseEvent @param event: @return: """ # Prevent draw on video if not started or finished if self.parent.player.position() == 0: return # Censure Draw Interaction if self._interaction.censure: geom = self.Censure_RubberBand.geometry() self.Censure_RubberBand.hide() self.drawCesure.append([geom]) # Object Tracking Interaction if self._interaction.objectTracking: geom = self.Tracking_Video_RubberBand.geometry() offset = self.surface.videoRect() bbox = (geom.x() - offset.x(), geom.y() - offset.y(), geom.width(), geom.height()) img = self.currentFrame() frame = convertQImageToMat(img) # Remo rubberband on canvas and video self.Tracking_Video_RubberBand.hide() self.Track_Canvas_RubberBand.reset() self.tracker = TrackerMOSSE_create() result = resize(frame, (offset.width(), offset.height())) try: ok = self.tracker.init(result, bbox) except Exception: return if ok: self._isinit = True # Get Traker center xc = bbox[0] + (geom.width() / 2) yc = bbox[1] + (geom.height() / 2) p = QPoint(xc, yc) Longitude, Latitude, _ = vut.GetPointCommonCoords( p, self.surface) # Draw Rubber Band on canvas self.Track_Canvas_RubberBand.addPoint(QgsPointXY(Longitude, Latitude)) else: self._isinit = False def leaveEvent(self, _): """ @type _: QEvent @param _: @return: """ # Remove coordinates label value self.parent.lb_cursor_coord.setText("") # Change cursor self.setCursor(QCursor(Qt.ArrowCursor)) # Reset mouse rubberband self.Cursor_Canvas_RubberBand.reset(QgsWkbTypes.PointGeometry)
class AgknowDockWidgetTimeSlider(QtWidgets.QDockWidget, FORM_CLASS): """ Class for the timeslider dockwidget of the agknow plugin. """ closingPlugin = pyqtSignal() productChanged = pyqtSignal(str) def __init__(self, parent=None): """Constructor.""" super(AgknowDockWidgetTimeSlider, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) # GUI Events # lambda keyword allows the button itself to be passed #https://www.tutorialspoint.com/pyqt/pyqt_qradiobutton_widget.htm self.rdBtnVisible.toggled.connect( lambda: self.rdBtnProductState_toggled(self.rdBtnVisible)) self.rdBtnVitality.toggled.connect( lambda: self.rdBtnProductState_toggled(self.rdBtnVitality)) self.rdBtnVariations.toggled.connect( lambda: self.rdBtnProductState_toggled(self.rdBtnVariations)) self.rdBtnNDRE1.toggled.connect( lambda: self.rdBtnProductState_toggled(self.rdBtnNDRE1)) self.rdBtnNDRE2.toggled.connect( lambda: self.rdBtnProductState_toggled(self.rdBtnNDRE2)) self.rdBtnNDWI.toggled.connect( lambda: self.rdBtnProductState_toggled(self.rdBtnNDWI)) self.rdBtnSAVI.toggled.connect( lambda: self.rdBtnProductState_toggled(self.rdBtnSAVI)) self.rdBtnEVI2.toggled.connect( lambda: self.rdBtnProductState_toggled(self.rdBtnEVI2)) self.rdBtnCIRE.toggled.connect( lambda: self.rdBtnProductState_toggled(self.rdBtnCIRE)) self.rdBtnNDVI.toggled.connect( lambda: self.rdBtnProductState_toggled(self.rdBtnNDVI)) self.rdBtnRefl.toggled.connect( lambda: self.rdBtnProductState_toggled(self.rdBtnRefl)) self.sliderTime.valueChanged.connect(self.sliderValue_changed) self.btnTimePlay.clicked.connect(self.btnTimePlay_clicked) self.btnTimeBackward.clicked.connect(self.btnTimeBackward_clicked) self.btnTimeForward.clicked.connect(self.btnTimeForward_clicked) self.product = "vitality" self.rasters = [ ] # it's a list here - a dict in agknow_qgis_dockwidget.py self.data_source = "sentinel2" self.current_parcel_id = None # timeslider self.timer = QBasicTimer() self.step = 0 self.iface = qgis.utils.iface def set_data_source(self, data_source): """ Setter for the data_source (landsat-8 or sentinel-2). """ self.data_source = data_source self.toggle_products_data_source_compatibility() def set_product(self, product): """ Setter for the product (vitality, variations, visible, etc). """ self.product = product # notify slots of change self.productChanged.emit(product) def set_current_parcel_id(self, parcel_id): """ Setter for the current parcel_id. """ self.current_parcel_id = parcel_id def timerEvent(self, e): """ Event handler for the timer. :param e: """ print("timerEvent()") if self.step == self.sliderTime.maximum(): self.timer.stop() self.step = 0 #reset step return else: self.step = self.step + 1 self.sliderTime.setValue(self.sliderTime.value() + 1) def rdBtnProductState_toggled(self, btn): """ Handles the toggled event of the given radio button. :param btn: radio button (QRadioButton) """ # trigger update # if radio button is checked at the end if btn.isChecked(): if btn.text().lower() == "refl.": self.set_product("reflectances") else: self.set_product(btn.text().lower()) parcel_id = self.current_parcel_id if len(self.rasters) > 0: # find subgroup root = QgsProject.instance().layerTreeRoot() parcel_group = root.findGroup( "parcel id: {0}".format(parcel_id)) # select active layer for identity e.g. self.set_layer_active_toc(parcel_id) if parcel_group is not None: self.toggle_products(parcel_group) def set_layer_active_toc(self, parcel_id): """ Sets the group layer of the given parcel ID in the TOC to active. :param parcel_id: parcel's ID (integer) """ # take the first layer of the group "parcel id: - source - product" data_source_group = self.find_data_source_group( parcel_id, self.product, self.data_source) # layer name date = self.rasters[0]["date"] raster_id = self.rasters[0]["raster_id"] activeLyrName = date + " - " + str(raster_id) if data_source_group is not None: for lyr in data_source_group.findLayers(): #print("searching for {0}..".format(activeLyrName)) # QGIS >= 2.18.1 : name(), QGIS 2.18.0 : layerName() if lyr.name() == activeLyrName: # QgsLayerTreeLayer to QgsMapLayer per .layer() #print("setting lyr {0} active".format(lyr.layerName())) self.iface.setActiveLayer(lyr.layer()) else: pass #print("data_source_group not found: {0} - {1} - {2}".format(parcel_id, self.product, self.data_source)) def sliderValue_changed(self): """ Handles the value changed event of the timeslider. """ if len(self.rasters) > 0: #print(self.sliderTime.value()) idx = self.sliderTime.value() #set current raster to visible - the rest invisible # get data from position in self.rasters product_id = self.product + " " #whitespace! data_source = self.rasters[idx]["source"] parcel_id = self.rasters[idx]["parcel_id"] raster_id = self.rasters[idx]["raster_id"] date = self.rasters[idx]["date"] #print(product_id, data_source, parcel_id, raster_id, date) activeLyrName = "{0}|{1}|{2}|{3}".format( product_id.strip(), date, raster_id, data_source) #date + " - " + str(raster_id) #print(activeLyrName) self.toggle_image_layer(activeLyrName, data_source, parcel_id, product_id) else: QgsMessageLog.logMessage( "AgknowDockWidgetTimeSlider - sliderValue_changed() - rasters are not set!", "agknow", Qgis.Critical) def toggle_image_layer(self, activeLyrName, data_source, parcel_id, product_id): """ Toggles all other image layers off except the given activeLayer. :param activeLyrName: active layer group (string) :param data_source: landsat-8 or sentinel-2 (string) :param parcel_id: parcel's ID (integer) :param product_id: product id: visible, vitality, variations, etc. (string) """ # find subgroup data_source_group = self.find_data_source_group( parcel_id, product_id, data_source) if data_source_group is not None: for lyr in data_source_group.findLayers(): # QGIS 2.18.1 : name(), QGIS 2.18.0 : layerName() if lyr.name() == activeLyrName: # set active layer visible lyr.setItemVisibilityChecked(Qt.Checked) # select active layer for identity e.g. # QgsLayerTreeLayer to QgsMapLayer per .layer() self.iface.setActiveLayer(lyr.layer()) else: lyr.setItemVisibilityChecked(Qt.Unchecked) def find_data_source_group(self, parcel_id, product_id, data_source): """ Returns the data source group layer of the TOC for the given parcel id, product and data source. :param parcel_id: parcel's ID (integer) :param product_id: product id: visible, vitality, variations, etc. (string) :param data_source: landsat-8 or sentinel-2 (string) :return: data_source_group (QgsLayerTreeGroup) """ root = QgsProject.instance().layerTreeRoot() parcel_group = root.findGroup("parcel id: {0}".format(parcel_id)) if parcel_group is not None: #print("parcel group found") product_group = parcel_group.findGroup(product_id) #print(product_group) if product_group is not None: #print("product group found") data_source_group = product_group.findGroup(data_source) return data_source_group def toggle_products(self, parcel_group): """ Toggle all other product groups off except the given parcel_group. :param parcel_group: (QgsLayerTreeGroup) """ data_source_list = ["landsat8", "sentinel2"] matrix = { "landsat8": ["visible", "vitality", "variations"], "sentinel2": [ "visible", "vitality", "variations", "reflectances", "ndvi", "ndre1", "ndre2", "ndre3", "ndwi", "savi", "evi2", "cire" ] } # turn off other data_source groups for ds in data_source_list: #print("checking {0}..".format(ds)) for p in matrix[ds]: #print("checking product {0}..".format(p)) pg = parcel_group.findGroup(p + " ") if pg is not None: #print("group {0} found!".format(p)) g = pg.findGroup(ds) if g is not None: if p == self.product and ds == self.data_source: #print("group {0} visible".format(ds)) g.setItemVisibilityChecked(Qt.Checked) else: #print("group {0} invisible!".format(ds)) g.setItemVisibilityChecked(Qt.Unchecked) def toggle_products_data_source_compatibility(self): """ Handles radio buttons for compatibility of products & data_source """ print("toggle_products_data_source_compatibility()") matrix = { "landsat8": ["Visible", "Vitality", "Variations"], "sentinel2": [ "Visible", "Vitality", "Variations", "Refl.", "NDVI", "NDRE1", "NDRE2", "NDRE3", "NDWI", "SAVI", "EVI2", "CIRE" ] } radioBtns = [ self.rdBtnVisible, self.rdBtnVitality, self.rdBtnVariations, self.rdBtnNDRE1, self.rdBtnNDRE2, self.rdBtnNDWI, self.rdBtnSAVI, self.rdBtnEVI2, self.rdBtnCIRE, self.rdBtnNDVI, self.rdBtnRefl ] for rdBtn in radioBtns: # disable all other radio buttons if rdBtn.text() in matrix[self.data_source]: rdBtn.setEnabled(True) else: rdBtn.setEnabled(False) #TODO: if data source disables product - select another product # leads to segmentation faults at the moment because several threads are started then #for rdBtn in radioBtns: # # check if selected radio button is disabled # if rdBtn.isChecked() and not rdBtn.isEnabled(): # # if so take the first of possible radio buttons # rdBtnToCheckName = matrix[self.data_source][0] # print(rdBtnToCheckName) # for r in radioBtns: # if r.text() == rdBtnToCheckName: # r.setChecked(Qt.Checked) def btnTimePlay_clicked(self): """ Handles the click event of the Button btnTimePlay. """ self.btnTimePlay.setText(" || ") interval = 1000 #ms # stop timer if it is already active if self.timer.isActive(): self.btnTimePlay.setText(" > ") self.timer.stop() # reset timer self.step = 0 self.sliderTime.setValue(0) # start timer else: self.timer.start(interval, self) def btnTimeForward_clicked(self): """ Handles the click event of the Button btnTimeForward. """ self.sliderTime.setValue(self.sliderTime.value() + 1) def btnTimeBackward_clicked(self): """ Handles the click event of the Button btnTimeBackward. """ self.sliderTime.setValue(self.sliderTime.value() - 1) def reload_images(self, rasters): """ Reloads images for the given rasters. :param rasters: () """ #print("reload_images({0})".format(rasters)) if rasters is not None: self.sliderTime.setRange(0, len(rasters) - 1) self.sliderTime.setTickInterval = 1 self.rasters = rasters if len(self.rasters) > 0: #print(self.rasters) parcel_id = self.rasters[0]["parcel_id"] QgsMessageLog.logMessage( "AgknowDockWidgetTimeSlider - activating parcel {0}..". format(parcel_id), "agknow", Qgis.Info) # select first image layer active in toc for identity e.g. self.set_layer_active_toc(parcel_id) else: QgsMessageLog.logMessage( "AgknowDockWidgetTimeSlider - rasters is None!", "agknow", Qgis.Warning) def closeEvent(self, event): """ Handles the close event of the class. :param event: """ self.closingPlugin.emit() event.accept()