Exemplo n.º 1
0
class FsApp(QMainWindow):

    def __init__(self, app):
        super(FsApp, self).__init__()
        self.app       = app
        self.selRect   = None
        self.screenPix = None

        # Set up the user interface from Designer.
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        #self.setWindowOpacity(0.5)
        #self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
        self.captureScreen()
        self.showMaximized()
        self.showFullScreen()


        #capture screen and display
        rec = QApplication.desktop().screenGeometry()
        height = rec.height()
        width = rec.width()
        self.ui.labPix.resize(width, height)
        self.ui.labPix.setScaledContents(True)
        self.ui.labPix.setPixmap(self.screenPix)

        #start rubberband
        self.rubberband = QRubberBand(QRubberBand.Rectangle, self)
        bla = QtGui.QPalette()
        bla.setBrush(QtGui.QPalette.Highlight, QtGui.QBrush(QtCore.Qt.red))
        self.rubberband.setPalette(bla)
        self.rubberband.setWindowOpacity(1.0)

    def captureScreen(self):
        screens = self.app.screens()
        self.screenPix = screens[0].grabWindow(0)

    def mousePressEvent(self, event):
        self.origin = event.pos()
        self.rubberband.setGeometry(QtCore.QRect(self.origin, QtCore.QSize()))
        self.rubberband.show()
        QWidget.mousePressEvent(self, event)

    def mouseMoveEvent(self, event):
        if self.rubberband.isVisible():
            self.rubberband.setGeometry(QtCore.QRect(self.origin, event.pos()).normalized())
        QWidget.mouseMoveEvent(self, event)

    def mouseReleaseEvent(self, event):
        if self.rubberband.isVisible():
            self.selRect = self.rubberband.geometry()
            self.rubberband.hide()
            codePix = self.screenPix.copy(    self.selRect.x(),
                            self.selRect.y(), 
                            self.selRect.width(),
                            self.selRect.height())
            QApplication.clipboard().setPixmap(codePix)
            self.exit()
        QWidget.mouseReleaseEvent(self, event)

    def exit(self):
        sys.exit(0)
Exemplo n.º 2
0
class VideoWidget(QVideoWidget):
    def __init__(self, parent=None):
        ''' Constructor '''
        super(VideoWidget, self).__init__(parent)
        self.surface = VideoWidgetSurface(self)
        self.Tracking_RubberBand = QRubberBand(QRubberBand.Rectangle, self)

        self.Censure_RubberBand = QRubberBand(QRubberBand.Rectangle, self)

        pal = QPalette()
        pal.setBrush(QPalette.Highlight, QBrush(QColor(Qt.blue)))
        self.Tracking_RubberBand.setPalette(pal)

        pal = QPalette()
        pal.setBrush(QPalette.Highlight, QBrush(QColor(Qt.black)))
        self.Censure_RubberBand.setPalette(pal)

        self.var_currentMouseMoveEvent = None

        self._interaction = InteractionState()
        self._filterSatate = FilterState()

        self.setUpdatesEnabled(True)
        self.snapped = False
        self.zoomed = False
        self._isinit = False
        self.gt = None

        self.drawCesure = []
        self.poly_coordinates, self.drawPtPos, self.drawLines, self.drawRuler, self.drawPolygon = [], [], [], [], []
        self.poly_RubberBand = QgsRubberBand(iface.mapCanvas(),
                                             True)  # Polygon type
        # set rubber band style
        color = QColor(176, 255, 128)
        self.poly_RubberBand.setColor(color)
        color.setAlpha(190)
        self.poly_RubberBand.setStrokeColor(color)
        self.poly_RubberBand.setWidth(3)

        self.parent = parent.parent()

        self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)

        self.setAttribute(Qt.WA_NoSystemBackground)
        self.setAttribute(Qt.WA_PaintOnScreen)
        self.setAttribute(Qt.WA_OpaquePaintEvent)
        self.setAttribute(Qt.WA_DeleteOnClose)
        palette = self.palette()
        palette.setColor(QPalette.Background, Qt.black)
        self.setPalette(palette)
        self.setSizePolicy(QSizePolicy.MinimumExpanding,
                           QSizePolicy.MinimumExpanding)

        self.offset, self.origin, self.pressPos, self.dragPos = QPoint(
        ), QPoint(), QPoint(), QPoint()
        self.tapTimer = QBasicTimer()
        self.zoomPixmap, self.maskPixmap = QPixmap(), QPixmap()

    def removeLastLine(self):
        ''' Remove Last Line Objects '''
        if len(self.drawLines) > 0:
            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 '''
        if len(self.drawLines) > 0:
            del self.drawLines[-1]
            self.UpdateSurface()
            AddDrawLineOnMap(self.drawLines)
        return

    def removeAllLines(self):
        ''' Resets Line List '''
        self.drawLines = []
        self.UpdateSurface()
        # Clear all Layer
        RemoveAllDrawLineOnMap()

    def ResetDrawRuler(self):
        ''' Resets Ruler List '''
        self.drawRuler = []

    def removeAllCensure(self):
        ''' Remove All Censure Objects '''
        self.drawCesure = []

    def removeLastCensured(self):
        ''' Remove Last Censure Objects '''
        if len(self.drawCesure) > 0:
            del self.drawCesure[-1]

    def removeLastPoint(self):
        ''' Remove All Point Drawer Objects '''
        if len(self.drawPtPos) > 0:
            del self.drawPtPos[-1]
            self.UpdateSurface()
            RemoveLastDrawPointOnMap()
        return

    def removeAllPoint(self):
        ''' Remove All Point Drawer Objects '''
        self.drawPtPos = []
        self.UpdateSurface()
        # Clear all Layer
        RemoveAllDrawPointOnMap()
        return

    def removeAllPolygon(self):
        ''' Remove All Polygon Drawer Objects '''
        self.drawPolygon = []
        self.UpdateSurface()
        # Clear all Layer
        RemoveAllDrawPolygonOnMap()

    def removeLastPolygon(self):
        ''' Remove Last Polygon Drawer Objects '''
        if len(self.drawPolygon) > 0:
            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 currentMouseMoveEvent(self, event):
        self.var_currentMouseMoveEvent = event

    def keyPressEvent(self, event):
        ''' Exit fullscreen '''
        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(VideoWidget, self).keyPressEvent(event)

    def mouseDoubleClickEvent(self, 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])
            self.UpdateSurface()
            return
        if self.gt is not None and self._interaction.ruler:
            self.drawRuler.append([None, None, None])
            self.UpdateSurface()
            return
        if self.gt is not None and self._interaction.polygonDrawer:
            self.drawPolygon.append([None, None, None])

            AddDrawPolygonOnMap(self.poly_coordinates)

            # Empty RubberBand
            for _ in range(self.poly_RubberBand.numberOfVertices()):
                self.poly_RubberBand.removeLastPoint()
            # Empty List
            self.poly_coordinates = []
            self.UpdateSurface()
            return

        self.setFullScreen(not self.isFullScreen())
        event.accept()

    def videoSurface(self):
        ''' Return video Surface '''
        return self.surface

    def UpdateSurface(self):
        ''' Update Video Surface '''
        self.surface.widget.update()

    def sizeHint(self):
        ''' This property holds the recommended size for the widget '''
        return self.surface.surfaceFormat().sizeHint()

    def GetCurrentFrame(self):
        ''' Return current frame QImage '''
        return self.surface.image

    def SetInvertColor(self, value):
        ''' Set Invert color filter '''
        self._filterSatate.invertColorFilter = value

    def SetObjectTracking(self, value):
        ''' Set Object Tracking '''
        self._interaction.objectTracking = value

    def SetRuler(self, value):
        ''' Set Ruler '''
        self._interaction.ruler = value

    def SetHandDraw(self, value):
        ''' Set Hand Draw '''
        self._interaction.HandDraw = value

    def SetCensure(self, value):
        ''' Set Censure Video Parts '''
        self._interaction.censure = value

    def SetGray(self, value):
        ''' Set gray scale '''
        self._filterSatate.grayColorFilter = value

    def SetMirrorH(self, value):
        ''' Set Horizontal Mirror '''
        self._filterSatate.MirroredHFilter = value

    def SetEdgeDetection(self, value):
        ''' Set Canny Edge filter '''
        self._filterSatate.edgeDetectionFilter = value

    def SetAutoContrastFilter(self, value):
        ''' Set Automatic Contrast filter '''
        self._filterSatate.contrastFilter = value

    def SetMonoFilter(self, value):
        ''' Set mono filter '''
        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()

    def paintEvent(self, event):
        ''' Paint Event '''
        self.gt = GetGCPGeoTransform()

        self.painter = QPainter(self)
        self.painter.setRenderHint(QPainter.HighQualityAntialiasing)

        if (self.surface.isActive()):
            videoRect = self.surface.videoRect()
            if not videoRect.contains(event.rect()):
                region = event.region()
                region.subtracted(QRegion(videoRect))
                brush = self.palette().window()
                for rect in region.rects():
                    self.painter.fillRect(rect, brush)

            try:
                self.painter = self.surface.paint(self.painter)
            except Exception:
                None
        else:
            self.painter.fillRect(event.rect(), self.palette().window())
        try:
            SetImageSize(self.surface.currentFrame.width(),
                         self.surface.currentFrame.height())
        except Exception:
            None

        # Draw On Video
        draw.drawOnVideo(self.drawPtPos, self.drawLines, self.drawPolygon,
                         self.drawRuler, self.drawCesure, self.painter,
                         self.surface, self.gt)

        # Magnifier Glass
        if self.zoomed and self._interaction.magnifier:
            draw.drawMagnifierOnVideo(self.width(), self.height(),
                                      self.maskPixmap, self.dragPos,
                                      self.zoomPixmap, self.surface,
                                      self.painter, self.offset)

        self.painter.end()
        return

    def resizeEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        QWidget.resizeEvent(self, event)
        self.zoomed = False
        self.surface.updateVideoRect()

    def mouseMoveEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        if GetImageHeight() == 0:
            return

        # check if the point  is on picture (not in black borders)
        if (not vut.IsPointOnScreen(event.x(), event.y(), self.surface)):
            return

        if self._interaction.pointDrawer or self._interaction.polygonDrawer or self._interaction.lineDrawer or self._interaction.ruler:
            self.setCursor(QCursor(Qt.CrossCursor))

        # Cursor Coordinates
        if self.gt is not None:

            Longitude, Latitude, Altitude = vut.GetPointCommonCoords(
                event, self.surface)

            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)

        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

        if not self.Tracking_RubberBand.isHidden():
            self.Tracking_RubberBand.setGeometry(
                QRect(self.origin, event.pos()).normalized())

        if not self.Censure_RubberBand.isHidden():
            self.Censure_RubberBand.setGeometry(
                QRect(self.origin, event.pos()).normalized())

        if not self.zoomed:
            delta = event.pos() - self.pressPos
            if not self.snapped:
                self.pressPos = event.pos()
                self.pan(delta)
                self.tapTimer.stop()
                return
            else:
                threshold = 10
                self.snapped &= delta.x() < threshold
                self.snapped &= delta.y() < threshold
                self.snapped &= delta.x() > -threshold
                self.snapped &= delta.y() > -threshold

        else:
            self.dragPos = event.pos()
            self.surface.updateVideoRect()

    def pan(self, delta):
        """ Pan Action (Magnifier method)"""
        self.offset += delta
        self.surface.updateVideoRect()

    def timerEvent(self, _):
        """ Time Event (Magnifier method)"""
        if not self.zoomed:
            self.activateMagnifier()
        self.surface.updateVideoRect()

    def mousePressEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        if GetImageHeight() == 0:
            return

        if event.button() == Qt.LeftButton:
            self.snapped = True
            self.pressPos = self.dragPos = event.pos()
            self.tapTimer.stop()
            self.tapTimer.start(100, self)

            if (not vut.IsPointOnScreen(event.x(), event.y(), self.surface)):
                self.UpdateSurface()
                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_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)

            if self._interaction.objectTracking:
                self.origin = event.pos()
                self.Tracking_RubberBand.setGeometry(
                    QRect(self.origin, QSize()))
                self.Tracking_RubberBand.show()

            if self._interaction.censure:
                self.origin = event.pos()
                self.Censure_RubberBand.setGeometry(QRect(
                    self.origin, QSize()))
                self.Censure_RubberBand.show()

            # Ruler drawer
            if self.gt is not None and self._interaction.ruler:
                Longitude, Latitude, Altitude = vut.GetPointCommonCoords(
                    event, self.surface)
                self.drawRuler.append([Longitude, Latitude, Altitude])

        # if not called, the paint event is not triggered.
        self.UpdateSurface()

    def activateMagnifier(self):
        """ Activate Magnifier Glass """
        self.zoomed = True
        self.tapTimer.stop()
        self.surface.updateVideoRect()

    def SetMagnifier(self, value):
        """ Set Magnifier Glass """
        self._interaction.magnifier = value

    def SetPointDrawer(self, value):
        """ Set Point Drawer """
        self._interaction.pointDrawer = value

    def SetLineDrawer(self, value):
        """ Set Line Drawer """
        self._interaction.lineDrawer = value

    def SetPolygonDrawer(self, value):
        """ Set Polygon Drawer """
        self._interaction.polygonDrawer = value

    def mouseReleaseEvent(self, _):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        if self._interaction.censure:
            geom = self.Tracking_RubberBand.geometry()
            self.Censure_RubberBand.hide()
            self.drawCesure.append([geom])

        if self._interaction.objectTracking:
            geom = self.Tracking_RubberBand.geometry()
            bbox = (geom.x(), geom.y(), geom.width(), geom.height())
            frame = convertQImageToMat(self.GetCurrentFrame())
            self.Tracking_RubberBand.hide()
            self.tracker = cv2.TrackerBoosting_create()
            self.tracker.clear()
            ok = self.tracker.init(frame, bbox)
            if ok:
                self._isinit = True
            else:
                self._isinit = False

    def leaveEvent(self, _):
        self.parent.lb_cursor_coord.setText("")
        self.setCursor(QCursor(Qt.ArrowCursor))
class CaptureImage(QLabel):

    sequence = []
    bag = None
    imageLabel = ImageLabel()

    def __init__(self, timeline, topic, msg, stamp):
        super(CaptureImage, self).__init__()
        self._timeline = timeline
        self._topic = topic
        #INISIALIZING MESSAGE AND COMMON ATTRIBUTES
        self._msg = msg
        self.imageLabel.header = self._msg.header
        self.imageLabel.imageTopic = self._topic
        #ORIGINAL TIME FROM THE ORIGINAL BAG SO THAT WE SAVE THAT SAME TIME IN THE NEW BAG
        self.stamp = stamp
        #WE HAVE TO DO BECAUSE RECT ARE RELATED WITH THE WIDGET WHICH CREATED THEM
        #SO IN ORDER TO SEE AND DELETE THEM FROM THE NEW WIDGET WE HAVE TO RELATE THEM WITH IT
        #***NOTE***: OBJECTS STORED IN SEQUENCE ARE OF TYPE QRUBBERBAND WHEREAS IN IMAGELABEL ARE
        #OF TYPE RECT
        if len(self.sequence) > 0:
            aux_sequence = []
            for rectangle in self.sequence:
                self.currentQRubberBand = QRubberBand(QRubberBand.Rectangle,
                                                      self)
                self.currentQRubberBand.setGeometry(rectangle.x(),
                                                    rectangle.y(),
                                                    rectangle.width(),
                                                    rectangle.height())
                aux_sequence.append(self.currentQRubberBand)
                self.currentQRubberBand.show()
            del self.sequence[:]
            for rectangle in aux_sequence:
                self.sequence.append(rectangle)

    def mousePressEvent(self, eventQMouseEvent):

        if eventQMouseEvent.buttons() == Qt.LeftButton:
            self.originQPoint = eventQMouseEvent.pos()
            self.currentQRubberBand = QRubberBand(QRubberBand.Rectangle, self)
            self.sequence.append(self.currentQRubberBand)

            r = randint(0, 255)
            g = randint(0, 255)
            b = randint(0, 255)
            palette = QPalette()
            palette.setColor(self.currentQRubberBand.foregroundRole(),
                             QColor(r, g, b))
            self.currentQRubberBand.setPalette(palette)

            self.currentQRubberBand.setGeometry(
                QRect(self.originQPoint, QSize()))
            self.currentQRubberBand.show()

        elif eventQMouseEvent.buttons() == Qt.RightButton:
            found = False
            for rect in self.sequence:
                if (rect.geometry().contains(eventQMouseEvent.pos())):
                    self.menu = MenuRectangle(self._timeline, eventQMouseEvent,
                                              rect, self.imageLabel,
                                              self.sequence)
                    found = True
            if not found:
                self.menuglobalimage = MenuGlobalImage(
                    self._timeline, eventQMouseEvent, self._topic,
                    self.sequence, self.imageLabel, self.stamp)

    def mouseMoveEvent(self, eventQMouseEvent):
        self.currentQRubberBand.setGeometry(
            QRect(self.originQPoint, eventQMouseEvent.pos()).normalized())
Exemplo n.º 4
0
class PictureBox(QLabel):
    changedNumberRegions = pyqtSignal(int)

    def __init__(self, image, regions, parent=None):

        QLabel.__init__(self, parent)
        self.rubberBand = QRubberBand(QRubberBand.Rectangle, self)
        self.origin = QPoint()
        self.regions = None
        self.image = image

        def region_to_rect(region):
            y1, x1, y2, x2 = region.bbox
            return QRect(x1, y1, x2 - x1, y2 - y1)

        self.regions = list(map(region_to_rect, regions))
        self._update_picture()

    def mousePressEvent(self, event):
        pal = QPalette()
        if event.button() == Qt.LeftButton:
            pal.setBrush(QPalette.Highlight, QBrush(Qt.blue))
        elif event.button() == Qt.RightButton:
            pal.setBrush(QPalette.Highlight, QBrush(Qt.green))
        self.rubberBand.setPalette(pal)
        self.origin = QPoint(event.pos())
        self.rubberBand.setGeometry(QRect(self.origin, QSize()))
        self.rubberBand.show()

    def mouseMoveEvent(self, event):
        if not self.origin.isNull():
            self.rubberBand.setGeometry(
                QRect(self.origin, event.pos()).normalized())

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            drawnRect = QRect(self.origin, event.pos()).normalized()
            for region in self.getIntersectedRegions(drawnRect):
                self.regions.remove(region)
        elif event.button() == Qt.RightButton:
            drawnRect = QRect(self.origin, event.pos()).normalized()
            meanArea = np.mean([r.width() * r.height() for r in self.regions])
            meanHeight = np.mean([r.height() for r in self.regions])
            meanWidth = np.mean([r.width() for r in self.regions])
            if drawnRect.width() * drawnRect.height() * 2 < meanArea:
                rect = QRect(self.origin.x() - meanWidth / 2,
                             self.origin.y() - meanHeight / 2, meanWidth,
                             meanHeight)
                self.regions.append(rect)
            else:
                self.regions.append(drawnRect)
        self.rubberBand.hide()
        self._update_picture()

    def getIntersectedRegions(self, drawnRect):
        result = []
        for region in self.regions:
            if region.intersects(drawnRect):
                result.append(region)
        return result

    def _update_regions(self):
        pixmap = self._get_pixmap()
        paint = QPainter(pixmap)
        paint.setPen(QColor("green"))
        for region in self.regions:
            paint.drawRect(region)
            # rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr,
            #                          fill=False, edgecolor='green', linewidth=2)
        del paint
        return pixmap

    def savePicture(self, fname):
        pixmap = self._update_regions()
        return pixmap.save(fname)

    def _update_picture(self):
        pixmap = self._update_regions()
        self.setAlignment(Qt.AlignLeft | Qt.AlignTop)
        self.setPixmap(pixmap)
        self.changedNumberRegions.emit(len(self.regions))

    def _get_pixmap(self):
        # Convert image to QImage
        qimg = qimage2ndarray.array2qimage(self.image, True)
        return QPixmap(qimg)
Exemplo n.º 5
0
class VideoWidget(QVideoWidget):
    def __init__(self, parent=None):
        super(VideoWidget, self).__init__(parent)
        self.rubberBand = QRubberBand(QRubberBand.Rectangle, self)
        pal = QPalette()
        pal.setBrush(QPalette.Highlight, QBrush(QColor(Qt.green)))
        self.rubberBand.setPalette(pal)
        self.setUpdatesEnabled(True)
        self.setMouseTracking(True)
        self.origin = QPoint()
        self.changeRubberBand = False

        self.parent = parent.parent()
        self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)

        self.setAttribute(Qt.WA_NoSystemBackground, True)
        self.setAttribute(Qt.WA_PaintOnScreen, True)
        palette = self.palette()
        palette.setColor(QPalette.Background, Qt.black)
        self.setPalette(palette)
        self.setSizePolicy(QSizePolicy.MinimumExpanding,
                           QSizePolicy.MinimumExpanding)

        self.surface = VideoWidgetSurface(self)

        self.setAttribute(Qt.WA_OpaquePaintEvent)
        self.gt = None

        self.pressed = False
        self.snapped = False
        self.zoomed = False
        self.zoomedRect = False

        self.offset = QPoint()
        self.pressPos = QPoint()
        self.dragPos = QPoint()
        self.tapTimer = QBasicTimer()
        self.zoomPixmap = QPixmap()
        self.maskPixmap = QPixmap()

    def keyPressEvent(self, event):
        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(VideoWidget, self).keyPressEvent(event)

    def mouseDoubleClickEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        self.setFullScreen(not self.isFullScreen())
        event.accept()

    def videoSurface(self):
        return self.surface

    def UpdateSurface(self):
        self.surface.widget.update()

    def sizeHint(self):
        return self.surface.surfaceFormat().sizeHint()

    def GetCurrentFrame(self):
        return self.surface.image

    def SetInvertColor(self, value):
        global invertColorFilter
        invertColorFilter = value

    def SetGray(self, value):
        global grayColorFilter
        grayColorFilter = value

    def SetEdgeDetection(self, value):
        global edgeDetectionFilter
        edgeDetectionFilter = value

    def SetAutoContrastFilter(self, value):
        global contrastFilter
        contrastFilter = value

    def SetMonoFilter(self, value):
        global monoFilter
        monoFilter = value

    def RestoreFilters(self):
        global invertColorFilter, grayColorFilter, edgeDetectionFilter, monoFilter, contrastFilter
        invertColorFilter = grayColorFilter = edgeDetectionFilter = monoFilter = contrastFilter = False

    def GetXBlackZone(self):
        x = 0.0
        normalizedWidth = self.surface.widget.height() * (GetImageWidth() /
                                                          GetImageHeight())
        if (self.surface.widget.width() / self.surface.widget.height()) > (
                GetImageWidth() / GetImageHeight()):
            x = (self.surface.widget.width() - (normalizedWidth)) / 2.0
        return x

    def GetYBlackZone(self):
        y = 0.0
        normalizedHeight = self.surface.widget.width() / (GetImageWidth() /
                                                          GetImageHeight())
        if (self.surface.widget.width() / self.surface.widget.height()) < (
                GetImageWidth() / GetImageHeight()):
            y = (self.surface.widget.height() - (normalizedHeight)) / 2.0
        return y

    # determines if a clicked point lands on the image (False if lands on the
    # black borders or outside)
    def IsPointOnScreen(self, x, y):
        res = True
        normalizedWidth = self.surface.widget.height() * (GetImageWidth() /
                                                          GetImageHeight())
        normalizedHeight = self.surface.widget.width() / (GetImageWidth() /
                                                          GetImageHeight())
        if x > (normalizedWidth +
                self.GetXBlackZone()) or x < self.GetXBlackZone():
            res = False
        if y > (normalizedHeight +
                self.GetYBlackZone()) or y < self.GetYBlackZone():
            res = False
        return res

    # ratio between event.x() and real image width on screen.
    def GetXRatio(self):
        return GetImageWidth() / (self.surface.widget.width() -
                                  (2 * self.GetXBlackZone()))

    # ratio between event.y() and real image height on screen.
    def GetYRatio(self):
        return GetImageHeight() / (self.surface.widget.height() -
                                   (2 * self.GetYBlackZone()))

    def paintEvent(self, event):
        self.gt = GetGCPGeoTransform()
        painter = QPainter(self)

        if (self.surface.isActive()):
            videoRect = self.surface.videoRect()
            if not videoRect.contains(event.rect()):
                region = event.region()
                region.subtracted(QRegion(videoRect))
                brush = self.palette().window()
                for rect in region.rects():
                    painter.fillRect(rect, brush)

            try:
                self.surface.paint(painter)
            except Exception:
                None
        else:
            painter.fillRect(event.rect(), self.palette().window())
        try:
            SetImageSize(self.surface.currentFrame.width(),
                         self.surface.currentFrame.height())
        except:
            None

        # Magnifier Glass
        if self.zoomed and magnifier:
            dim = min(self.width(), self.height())
            magnifierSize = min(MAX_MAGNIFIER, dim * 2 / 3)
            radius = magnifierSize / 2
            ring = radius - 15
            box = QSize(magnifierSize, magnifierSize)

            # reupdate our mask
            if self.maskPixmap.size() != box:
                self.maskPixmap = QPixmap(box)
                self.maskPixmap.fill(Qt.transparent)
                g = QRadialGradient()
                g.setCenter(radius, radius)
                g.setFocalPoint(radius, radius)
                g.setRadius(radius)
                g.setColorAt(1.0, QColor(64, 64, 64, 0))
                g.setColorAt(0.5, QColor(0, 0, 0, 255))
                mask = QPainter(self.maskPixmap)
                mask.setRenderHint(QPainter.Antialiasing)
                mask.setCompositionMode(QPainter.CompositionMode_Source)
                mask.setBrush(g)
                mask.setPen(Qt.NoPen)
                mask.drawRect(self.maskPixmap.rect())
                mask.setBrush(QColor(Qt.transparent))
                mask.drawEllipse(g.center(), ring, ring)
                mask.end()

            center = self.dragPos - QPoint(0, radius)
            center += QPoint(0, radius / 2)
            corner = center - QPoint(radius, radius)
            xy = center * 2 - QPoint(radius, radius)
            # only set the dimension to the magnified portion
            if self.zoomPixmap.size() != box:
                self.zoomPixmap = QPixmap(box)
                self.zoomPixmap.fill(Qt.lightGray)

            if True:
                painter = QPainter(self.zoomPixmap)
                painter.translate(-xy)
                self.largePixmap = QPixmap.fromImage(self.surface.image)
                painter.drawPixmap(self.offset, self.largePixmap)
                painter.end()

            clipPath = QPainterPath()
            clipPath.addEllipse(QPointF(center), ring, ring)
            painter = QPainter(self)
            painter.setRenderHint(QPainter.Antialiasing)
            painter.setClipPath(clipPath)
            painter.drawPixmap(corner, self.zoomPixmap)
            painter.drawPixmap(corner, self.maskPixmap)
            painter.setPen(Qt.gray)
            painter.drawPath(clipPath)
        return

    def resizeEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        QWidget.resizeEvent(self, event)
        self.zoomed = False
        if zoomRect and self.surface.zoomedrect is not None:
            self.surface.updatetest()
            return
        self.surface.updateVideoRect()

    def mouseMoveEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        # Cursor Coordinates
        if self.gt is not None:

            # check if the point  is on picture (not in black borders)
            if (not self.IsPointOnScreen(event.x(), event.y())):
                return

            transf = self.gt([
                (event.x() - self.GetXBlackZone()) * self.GetXRatio(),
                (event.y() - self.GetYBlackZone()) * self.GetYRatio()
            ])

            Longitude = transf[1]
            Latitude = transf[0]
            Altitude = 0.0

            self.parent.lb_cursor_coord.setText(
                "<span style='font-size:10pt; font-weight:bold;'>Lon :</span>"
                + "<span style='font-size:9pt; font-weight:normal;'>" +
                ("%.3f" % Longitude) + "</span>" +
                "<span style='font-size:10pt; font-weight:bold;'> Lat :</span>"
                + "<span style='font-size:9pt; font-weight:normal;'>" +
                ("%.3f" % Latitude) + "</span>")
        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;'>Null</span>"
                +
                "<span style='font-size:10pt; font-weight:bold;'> Lat :</span>"
                +
                "<span style='font-size:9pt; font-weight:normal;'>Null</span>")

        if not event.buttons():
            return

        if self.changeRubberBand:
            self.rubberBand.setGeometry(
                QRect(self.origin, event.pos()).normalized())

        if self.zoomed is True:
            self.rubberBand.hide()
            self.zoomedRect = False

        if not self.zoomed:
            if not self.pressed or not self.snapped:
                delta = event.pos() - self.pressPos
                self.pressPos = event.pos()
                self.pan(delta)
                return
            else:
                threshold = 10
                delta = event.pos() - self.pressPos
                if self.snapped:
                    self.snapped &= delta.x() < threshold
                    self.snapped &= delta.y() < threshold
                    self.snapped &= delta.x() > -threshold
                    self.snapped &= delta.y() > -threshold

                if not self.snapped:
                    self.tapTimer.stop()

        else:
            self.dragPos = event.pos()
            self.surface.updateVideoRect()

#     TODO: MAKE PAINT GEOMETRY ACTION AND CREATE SHAPES

    def pan(self, delta):
        """ Pan Action """
        self.offset += delta
        self.surface.updateVideoRect()

    def timerEvent(self, _):
        """ Time Event """
        if not self.zoomed:
            self.activateMagnifier()
        self.surface.updateVideoRect()

    def mousePressEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        if event.button() == Qt.LeftButton:
            self.pressed = self.snapped = True
            self.pressPos = self.dragPos = event.pos()
            self.tapTimer.stop()
            self.tapTimer.start(HOLD_TIME, self)

        if zoomRect and event.button() == Qt.LeftButton:
            self.origin = event.pos()
            self.rubberBand.setGeometry(QRect(self.origin, QSize()))
            self.rubberBand.show()
            self.changeRubberBand = True

    def activateMagnifier(self):
        """ Activate Magnifier Glass """
        self.zoomed = True
        self.tapTimer.stop()
        self.surface.updateVideoRect()

    def SetMagnifier(self, value):
        """ Set Magnifier Glass """
        global magnifier
        magnifier = value

    def SetZoomRect(self, value):
        """ Set Zoom Rectangle """
        global zoomRect
        zoomRect = value

    def mouseReleaseEvent(self, _):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        self.changeRubberBand = False
        if self.zoomed is True:
            return
        self.zoomed = False
        if not zoomRect:
            self.surface.updateVideoRect()
        else:
            self.rubberBand.hide()
            self.zoomedRect = True

            # TODO :  ACTUALIZAR LA IMAGEN
            selRect = self.rubberBand.geometry()

            orig2widgScale = self.surface.widget.contentsRect().width() / \
                self.surface.image.width()

            X1 = selRect.topLeft().x() / orig2widgScale
            Y1 = selRect.topLeft().y() / orig2widgScale
            X2 = selRect.bottomRight().x() / self.surface.widget.contentsRect().bottomRight().x() * \
                self.surface.image.width()
            Y2 = selRect.bottomRight().y() / self.surface.widget.contentsRect().bottomRight().y() * \
                self.surface.image.height()

            self.surface.image.width()
            self.surface.image.height()

            wid2origRect = QRect(X1, Y1, X2, Y2)
            zoom_img = self.surface.image.copy(wid2origRect)
            # zoom_img.save('D:\\test.png')
            #             n_img = self.surface.image.copy(selRect)
            #             n_img.save('D:\\test.png')
            zoom_img.scaled(1920, 1080)
            self.surface.currentFrame = QVideoFrame(zoom_img)
            #             self.surface.targetRect=selRect
            self.surface.currentFrame.unmap()
            self.UpdateSurface()

    def leaveEvent(self, _):
        self.parent.lb_cursor_coord.setText("")
Exemplo n.º 6
0
class VideoWidget(QVideoWidget):
    def __init__(self, parent=None):
        super(VideoWidget, self).__init__(parent)
        self.rubberBand = QRubberBand(QRubberBand.Rectangle, self)
        pal = QPalette()
        pal.setBrush(QPalette.Highlight, QBrush(QColor(Qt.green)))
        self.rubberBand.setPalette(pal)
        self.setUpdatesEnabled(True)
        self.setMouseTracking(True)
        self.origin = QPoint()
        self.changeRubberBand = False

        self.parent = parent.parent()
        self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)

        self.setAttribute(Qt.WA_NoSystemBackground, True)
        self.setAttribute(Qt.WA_PaintOnScreen, True)
        palette = self.palette()
        palette.setColor(QPalette.Background, Qt.black)
        self.setPalette(palette)
        self.setSizePolicy(QSizePolicy.MinimumExpanding,
                           QSizePolicy.MinimumExpanding)

        self.surface = VideoWidgetSurface(self)

        self.setAttribute(Qt.WA_OpaquePaintEvent)
        self.gt = None

        self.pressed = False
        self.snapped = False
        self.zoomed = False
        self.zoomedRect = False

        self.offset = QPoint()
        self.pressPos = QPoint()
        self.drawPtPos = []
        self.drawLines = []
        self.dragPos = QPoint()
        self.tapTimer = QBasicTimer()
        self.zoomPixmap = QPixmap()
        self.maskPixmap = QPixmap()

    def keyPressEvent(self, event):
        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(VideoWidget, self).keyPressEvent(event)

    def mouseDoubleClickEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        self.setFullScreen(not self.isFullScreen())
        event.accept()

    def videoSurface(self):
        return self.surface

    def UpdateSurface(self):
        self.surface.widget.update()

    def sizeHint(self):
        return self.surface.surfaceFormat().sizeHint()

    def GetCurrentFrame(self):
        return self.surface.image

    def SetInvertColor(self, value):
        global invertColorFilter
        invertColorFilter = value

    def SetGray(self, value):
        global grayColorFilter
        grayColorFilter = value

    def SetEdgeDetection(self, value):
        global edgeDetectionFilter
        edgeDetectionFilter = value

    def SetAutoContrastFilter(self, value):
        global contrastFilter
        contrastFilter = value

    def SetMonoFilter(self, value):
        global monoFilter
        monoFilter = value

    def RestoreFilters(self):
        global invertColorFilter, grayColorFilter, edgeDetectionFilter, monoFilter, contrastFilter
        invertColorFilter = grayColorFilter = edgeDetectionFilter = monoFilter = contrastFilter = False

    def GetXBlackZone(self):
        x = 0.0
        normalizedWidth = self.surface.widget.height() * (GetImageWidth() /
                                                          GetImageHeight())
        if (self.surface.widget.width() / self.surface.widget.height()) > (
                GetImageWidth() / GetImageHeight()):
            x = (self.surface.widget.width() - (normalizedWidth)) / 2.0
        return x

    def GetYBlackZone(self):
        y = 0.0
        normalizedHeight = self.surface.widget.width() / (GetImageWidth() /
                                                          GetImageHeight())
        if (self.surface.widget.width() / self.surface.widget.height()) < (
                GetImageWidth() / GetImageHeight()):
            y = (self.surface.widget.height() - (normalizedHeight)) / 2.0
        return y

    # determines if a clicked point lands on the image (False if lands on the
    # black borders or outside)
    def IsPointOnScreen(self, x, y):
        res = True
        normalizedWidth = self.surface.widget.height() * (GetImageWidth() /
                                                          GetImageHeight())
        normalizedHeight = self.surface.widget.width() / (GetImageWidth() /
                                                          GetImageHeight())
        if x > (normalizedWidth +
                self.GetXBlackZone()) or x < self.GetXBlackZone():
            res = False
        if y > (normalizedHeight +
                self.GetYBlackZone()) or y < self.GetYBlackZone():
            res = False
        return res

    def GetXRatio(self):
        ''' ratio between event.x() and real image width on screen. '''
        return GetImageWidth() / (self.surface.widget.width() -
                                  (2 * self.GetXBlackZone()))

    def GetYRatio(self):
        ''' ratio between event.y() and real image height on screen. '''
        return GetImageHeight() / (self.surface.widget.height() -
                                   (2 * self.GetYBlackZone()))

    def paintEvent(self, event):
        self.gt = GetGCPGeoTransform()
        painter = QPainter(self)

        if (self.surface.isActive()):
            videoRect = self.surface.videoRect()
            if not videoRect.contains(event.rect()):
                region = event.region()
                region.subtracted(QRegion(videoRect))
                brush = self.palette().window()
                for rect in region.rects():
                    painter.fillRect(rect, brush)

            try:
                self.surface.paint(painter)
            except Exception:
                None
        else:
            painter.fillRect(event.rect(), self.palette().window())
        try:
            SetImageSize(self.surface.currentFrame.width(),
                         self.surface.currentFrame.height())
        except:
            None

        #Draw clicked points on video
        for pt in self.drawPtPos:
            #adds a mark on the video
            self.drawPointOnVideo(pt)

        #Draw clicked lines on video
        for pt in self.drawLines:
            #adds a mark on the video
            self.drawLinesOnVideo(pt)

        # Magnifier Glass
        if self.zoomed and magnifier:
            dim = min(self.width(), self.height())
            magnifierSize = min(MAX_MAGNIFIER, dim * 2 / 3)
            radius = magnifierSize / 2
            ring = radius - 15
            box = QSize(magnifierSize, magnifierSize)

            # reupdate our mask
            if self.maskPixmap.size() != box:
                self.maskPixmap = QPixmap(box)
                self.maskPixmap.fill(Qt.transparent)
                g = QRadialGradient()
                g.setCenter(radius, radius)
                g.setFocalPoint(radius, radius)
                g.setRadius(radius)
                g.setColorAt(1.0, QColor(64, 64, 64, 0))
                g.setColorAt(0.5, QColor(0, 0, 0, 255))
                mask = QPainter(self.maskPixmap)
                mask.setRenderHint(QPainter.Antialiasing)
                mask.setCompositionMode(QPainter.CompositionMode_Source)
                mask.setBrush(g)
                mask.setPen(Qt.NoPen)
                mask.drawRect(self.maskPixmap.rect())
                mask.setBrush(QColor(Qt.transparent))
                mask.drawEllipse(g.center(), ring, ring)
                mask.end()

            center = self.dragPos - QPoint(0, radius)
            center += QPoint(0, radius / 2)
            corner = center - QPoint(radius, radius)
            xy = center * 2 - QPoint(radius, radius)
            # only set the dimension to the magnified portion
            if self.zoomPixmap.size() != box:
                self.zoomPixmap = QPixmap(box)
                self.zoomPixmap.fill(Qt.lightGray)

            if True:
                painter = QPainter(self.zoomPixmap)
                painter.translate(-xy)
                self.largePixmap = QPixmap.fromImage(self.surface.image)
                painter.drawPixmap(self.offset, self.largePixmap)
                painter.end()

            clipPath = QPainterPath()
            clipPath.addEllipse(QPointF(center), ring, ring)
            painter = QPainter(self)
            painter.setRenderHint(QPainter.Antialiasing)
            painter.setClipPath(clipPath)
            painter.drawPixmap(corner, self.zoomPixmap)
            painter.drawPixmap(corner, self.maskPixmap)
            painter.setPen(Qt.gray)
            painter.drawPath(clipPath)
        return

    def GetInverseMatrix(self, x, y):
        ''' inverse matrix transformation (lon-lat to video units x,y) '''
        transf = (~self.gt)([x, y])
        scr_x = (transf[0] / self.GetXRatio()) + self.GetXBlackZone()
        scr_y = (transf[1] / self.GetYRatio()) + self.GetYBlackZone()
        return scr_x, scr_y

    def drawLinesOnVideo(self, pt):
        ''' Draw Lines on Video '''
        scr_x, scr_y = self.GetInverseMatrix(pt[1], pt[0])

        radius = 3
        center = QPoint(scr_x, scr_y)

        pen = QPen(Qt.yellow)
        pen.setWidth(radius)
        pen.setCapStyle(Qt.RoundCap)
        pen.setDashPattern([1, 4, 5, 4])
        painter_p = QPainter(self)
        painter_p.setPen(pen)
        painter_p.setRenderHint(QPainter.HighQualityAntialiasing, True)
        painter_p.drawPoint(center)

        if len(self.drawLines) > 1:
            try:
                idx = self.drawLines.index(pt)
                scr_x, scr_y = self.GetInverseMatrix(
                    self.drawLines[idx + 1][1], self.drawLines[idx + 1][0])
                end = QPoint(scr_x, scr_y)
                painter_p.drawLine(center, end)
            except:
                None

        return

    def drawPointOnVideo(self, pt):
        scr_x, scr_y = self.GetInverseMatrix(pt[1], pt[0])

        radius = 10
        center = QPoint(scr_x, scr_y)

        pen = QPen(Qt.red)
        pen.setWidth(radius)
        pen.setCapStyle(Qt.RoundCap)
        painter_p = QPainter(self)
        painter_p.setPen(pen)
        painter_p.setRenderHint(QPainter.HighQualityAntialiasing, True)
        painter_p.drawPoint(center)

        return

    def resizeEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        QWidget.resizeEvent(self, event)
        self.zoomed = False
        if zoomRect and self.surface.zoomedrect is not None:
            self.surface.updatetest()
            return
        self.surface.updateVideoRect()

    def mouseMoveEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        # check if the point  is on picture (not in black borders)
        if (not self.IsPointOnScreen(event.x(), event.y())):
            return

#         # Draw Line on the fly
#         if self.gt is not None and lineDrawer:
#                 if len(self.drawLines) > 0:
#                     scr_x, scr_y = self.GetInverseMatrix(self.drawLines[-1][1],self.drawLines[-1][1])
#
#                     radius = 3
#                     center = QPoint(scr_x, scr_y)
#
#                     pen = QPen(Qt.yellow)
#                     pen.setWidth(radius)
#                     pen.setCapStyle(Qt.RoundCap)
#                     pen.setDashPattern([1, 4, 5, 4])
#                     painter_p = QPainter(self)
#                     painter_p.setPen(pen)
#                     painter_p.setRenderHint(QPainter.HighQualityAntialiasing, True)
#                     painter_p.drawPoint(center)
#
#                     try:
#                         transf = self.gt([(event.x() - self.GetXBlackZone()) * self.GetXRatio(), (event.y() - self.GetYBlackZone()) * self.GetYRatio()])
#                         scr_x, scr_y = self.GetInverseMatrix(float(round(transf[1], 4)) , float(round(transf[0], 4)))
#                         end = QPoint(scr_x, scr_y)
#                         painter_p.drawLine(center, end)
#                         self.UpdateSurface()
#                     except:
#                         None

# Cursor Coordinates
        if self.gt is not None:

            transf = self.gt([
                (event.x() - self.GetXBlackZone()) * self.GetXRatio(),
                (event.y() - self.GetYBlackZone()) * self.GetYRatio()
            ])

            Longitude = transf[1]
            Latitude = transf[0]
            #Altitude = 0.0

            self.parent.lb_cursor_coord.setText(
                "<span style='font-size:10pt; font-weight:bold;'>Lon :</span>"
                + "<span style='font-size:9pt; font-weight:normal;'>" +
                ("%.3f" % Longitude) + "</span>" +
                "<span style='font-size:10pt; font-weight:bold;'> Lat :</span>"
                + "<span style='font-size:9pt; font-weight:normal;'>" +
                ("%.3f" % Latitude) + "</span>")
        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;'>Null</span>"
                +
                "<span style='font-size:10pt; font-weight:bold;'> Lat :</span>"
                +
                "<span style='font-size:9pt; font-weight:normal;'>Null</span>")

        if not event.buttons():
            return

        if self.changeRubberBand:
            self.rubberBand.setGeometry(
                QRect(self.origin, event.pos()).normalized())

        if self.zoomed is True:
            self.rubberBand.hide()
            self.zoomedRect = False

        if not self.zoomed:
            if not self.pressed or not self.snapped:
                delta = event.pos() - self.pressPos
                self.pressPos = event.pos()
                self.pan(delta)
                return
            else:
                threshold = 10
                delta = event.pos() - self.pressPos
                if self.snapped:
                    self.snapped &= delta.x() < threshold
                    self.snapped &= delta.y() < threshold
                    self.snapped &= delta.x() > -threshold
                    self.snapped &= delta.y() > -threshold

                if not self.snapped:
                    self.tapTimer.stop()

        else:
            self.dragPos = event.pos()
            self.surface.updateVideoRect()

    def pan(self, delta):
        """ Pan Action """
        self.offset += delta
        self.surface.updateVideoRect()

    def timerEvent(self, _):
        """ Time Event """
        if not self.zoomed:
            self.activateMagnifier()
        self.surface.updateVideoRect()

    def mousePressEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        if event.button() == Qt.LeftButton:
            self.pressed = self.snapped = True
            self.pressPos = self.dragPos = event.pos()
            self.tapTimer.stop()
            self.tapTimer.start(HOLD_TIME, self)

            #point drawer
            if self.gt is not None and pointDrawer:
                if (not self.IsPointOnScreen(event.x(), event.y())):
                    return

                transf = self.gt([
                    (event.x() - self.GetXBlackZone()) * self.GetXRatio(),
                    (event.y() - self.GetYBlackZone()) * self.GetYRatio()
                ])
                #targetAlt = GetFrameCenter()[2]
                Longitude = float(round(transf[1], 4))
                Latitude = float(round(transf[0], 4))
                #Altitude = targetAlt
                Altitude = 0.0
                #add pin point on the map
                pointLyr = qgsu.selectLayerByName(Point_lyr)
                pointLyr.startEditing()
                feature = QgsFeature()
                feature.setAttributes([Longitude, Latitude, Altitude])
                p = QgsPointXY()
                p.set(Longitude, Latitude)
                geom = QgsGeometry.fromPointXY(p)
                feature.setGeometry(geom)
                pointLyr.addFeatures([feature])

                CommonLayer(pointLyr)

                self.drawPtPos.append([Longitude, Latitude])
                #if not called, the paint event is not triggered.
                self.UpdateSurface()

            #line drawer
            if self.gt is not None and lineDrawer:
                if (not self.IsPointOnScreen(event.x(), event.y())):
                    return

                transf = self.gt([
                    (event.x() - self.GetXBlackZone()) * self.GetXRatio(),
                    (event.y() - self.GetYBlackZone()) * self.GetYRatio()
                ])
                #targetAlt = GetFrameCenter()[2]
                Longitude = float(round(transf[1], 4))
                Latitude = float(round(transf[0], 4))
                #Altitude = targetAlt
                Altitude = 0.0
                #add pin point on the map
                linelyr = qgsu.selectLayerByName(Line_lyr)
                linelyr.startEditing()
                feature = QgsFeature()
                f = QgsFeature()
                if linelyr.featureCount() == 0:
                    f.setAttributes([Longitude, Latitude, Altitude])
                    surface = QgsGeometry.fromPolylineXY([
                        QgsPointXY(Longitude, Latitude),
                        QgsPointXY(Longitude, Latitude)
                    ])
                    f.setGeometry(surface)
                    linelyr.addFeatures([f])

                else:
                    f_last = linelyr.getFeature(linelyr.featureCount())
                    f.setAttributes([Longitude, Latitude, Altitude])
                    surface = QgsGeometry.fromPolylineXY([
                        QgsPointXY(Longitude, Latitude),
                        QgsPointXY(f_last.attribute(0), f_last.attribute(1))
                    ])
                    f.setGeometry(surface)
                    linelyr.addFeatures([f])

                CommonLayer(linelyr)

                self.drawLines.append([Longitude, Latitude])
                #if not called, the paint event is not triggered.
                self.UpdateSurface()

        if zoomRect and event.button() == Qt.LeftButton:
            self.origin = event.pos()
            self.rubberBand.setGeometry(QRect(self.origin, QSize()))
            self.rubberBand.show()
            self.changeRubberBand = True

    def activateMagnifier(self):
        """ Activate Magnifier Glass """
        self.zoomed = True
        self.tapTimer.stop()
        self.surface.updateVideoRect()

    def SetMagnifier(self, value):
        """ Set Magnifier Glass """
        global magnifier
        magnifier = value

    def SetPointDrawer(self, value):
        """ Set Point Drawer """
        global pointDrawer
        pointDrawer = value

    def SetLineDrawer(self, value):
        """ Set Line Drawer """
        global lineDrawer
        lineDrawer = value

    def SetZoomRect(self, value):
        """ Set Zoom Rectangle """
        global zoomRect
        zoomRect = value

    def mouseReleaseEvent(self, _):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        self.changeRubberBand = False
        if self.zoomed is True:
            return
        self.zoomed = False
        if not zoomRect:
            self.surface.updateVideoRect()
        else:
            self.rubberBand.hide()
            self.zoomedRect = True

            # TODO :  make zoom rectangle functionality
            selRect = self.rubberBand.geometry()

            orig2widgScale = self.surface.widget.contentsRect().width() / \
                self.surface.image.width()

            X1 = selRect.topLeft().x() / orig2widgScale
            Y1 = selRect.topLeft().y() / orig2widgScale
            X2 = selRect.bottomRight().x() / self.surface.widget.contentsRect().bottomRight().x() * \
                self.surface.image.width()
            Y2 = selRect.bottomRight().y() / self.surface.widget.contentsRect().bottomRight().y() * \
                self.surface.image.height()

            self.surface.image.width()
            self.surface.image.height()

            wid2origRect = QRect(X1, Y1, X2, Y2)
            zoom_img = self.surface.image.copy(wid2origRect)
            #             zoom_img.save('D:\\test.png')
            #             n_img = self.surface.image.copy(selRect)
            #             n_img.save('D:\\test.png')
            zoom_img.scaled(1920, 1080)
            self.surface.currentFrame = QVideoFrame(zoom_img)
            #             self.surface.targetRect=selRect
            self.surface.currentFrame.unmap()
            self.UpdateSurface()

    def leaveEvent(self, _):
        self.parent.lb_cursor_coord.setText("")
Exemplo n.º 7
0
class ToolWindowManager ( QWidget ):
	'''docstring for ToolWindowManager'''
	#! The area tool windows has been added to most recently.
	LastUsedArea = 1
	#! New area in a detached window.
	NewFloatingArea = 2
	#! Area inside the manager widget (only available when there is no tool windows in it).
	EmptySpace = 3
	#! Tool window is hidden.
	NoArea = 4
	#! Existing area specified in AreaReference argument.
	AddTo = 5
	#! New area to the left of the area specified in AreaReference argument.
	LeftOf = 6
	#! New area to the right of the area specified in AreaReference argument.
	RightOf = 7
	#! New area to the top of the area specified in AreaReference argument.
	TopOf = 8
	#! New area to the bottom of the area specified in AreaReference argument.
	BottomOf = 9

	#signal
	toolWindowVisibilityChanged = pyqtSignal ( QWidget, bool )

	def __init__ ( self, parent = None ):
		super ( ToolWindowManager, self ).__init__ ( parent )
		self.lastUsedArea = None
		self.suggestions = []
		self.wrappers = []
		self.areas = []
		self.toolWindowList = []
		self.draggedToolWindows = []
		#----
		self.borderSensitivity = 12
		testSplitter = QSplitter ()
		self.rubberBandLineWidth = testSplitter.handleWidth ()
		self.dragIndicator = QtWidgets.QLabel ( None, Qt.ToolTip) # 使用QLabel来显示拖拽的提示
		self.dragIndicator.setAttribute ( Qt.WA_ShowWithoutActivating)
		mainLayout = QtWidgets.QVBoxLayout ( self )
		mainLayout.setContentsMargins ( 0, 0, 0, 0 )
		
		wrapper = ToolWindowManagerWrapper ( self )
		wrapper.setWindowFlags ( wrapper.windowFlags () & ~Qt.Tool )
		mainLayout.addWidget ( wrapper )

		self.dropSuggestionSwitchTimer = QtCore.QTimer ( self )
		self.dropSuggestionSwitchTimer.timeout.connect ( self.showNextDropSuggestion )
		self.dropSuggestionSwitchTimer.setInterval ( 800 )
		self.dropCurrentSuggestionIndex = 0

		palette = QtGui.QPalette ()
		color = QtGui.QColor ( Qt.blue )
		color.setAlpha ( 80 )
		palette.setBrush ( QtGui.QPalette.Highlight, QtGui.QBrush ( color ) )
		
		self.rectRubberBand = QRubberBand ( QRubberBand.Rectangle, self )
		self.lineRubberBand = QRubberBand ( QRubberBand.Line, self )
		self.rectRubberBand.setPalette ( palette )
		self.lineRubberBand.setPalette ( palette )

	def hideToolWindow ( self, toolWindow ):
		self.moveToolWindow ( toolWindow, ToolWindowManager.NoArea )

	def toolWindows ( self ):
		return self.toolWindowList

	def hasToolWindow ( self, toolWindow ):
		return toolWindow in self.toolWindowList

	def addToolWindow ( self, toolWindow, area ):
		return self.addToolWindows ( [toolWindow], area )

	def addToolWindows ( self, toolWindows, area ):
		for toolWindow in toolWindows:
			if self.hasToolWindow ( toolWindow ): continue
			toolWindow.hide ()
			toolWindow.setParent ( None )
			self.toolWindowList.append ( toolWindow )
		self.moveToolWindows ( toolWindows, area )

	def areaOf ( self, toolWindow ) -> ToolWindowManagerArea:
		'''
		查找toolWindow所属的area
		'''
		return findClosestParent ( toolWindow, ToolWindowManagerArea )

	def moveToolWindow ( self, toolWindow, area ):
		self.moveToolWindows ( [ toolWindow ], area )

	def moveToolWindows ( self, toolWindows, area ):
		if type ( area ) == int:
			area = AreaReference ( area )

		for toolWindow in toolWindows:
			if not self.hasToolWindow ( toolWindow ): return
			if toolWindow.parentWidget ():
				self.releaseToolWindow ( toolWindow )

		areaType = area.type

		if areaType == ToolWindowManager.LastUsedArea and not self.lastUsedArea:
			foundArea = self.findChild ( ToolWindowManagerArea )
			if foundArea:
				area = AreaReference ( ToolWindowManager.AddTo, foundArea )
			else:
				area = ToolWindowManager.EmptySpace

		if areaType == ToolWindowManager.NoArea:
			#do nothing
			# qWarning ( '[moveToolWindows] areaType = NoArea' )
			pass

		elif areaType == ToolWindowManager.NewFloatingArea:
			area = self.createArea ()
			area.addToolWindows ( toolWindows )
			wrapper = ToolWindowManagerWrapper ( self )
			wrapper.layout ().addWidget ( area )
			wrapper.move ( QCursor.pos () )
			wrapper.show ()

			# qWarning ( '[moveToolWindows] areaType = NewFloatingArea' )

		elif areaType == ToolWindowManager.AddTo:
			area.area ().addToolWindows ( toolWindows )

			# qWarning ( '[moveToolWindows] areaType = AddTo' )

		elif areaType in ( ToolWindowManager.LeftOf, ToolWindowManager.RightOf, ToolWindowManager.TopOf, ToolWindowManager.BottomOf ):
			parentSplitter = cast ( area.widget.parentWidget (), QSplitter )
			wrapper = cast ( area.widget.parentWidget (), ToolWindowManagerWrapper )
			if not ( parentSplitter or wrapper ):
				qWarning ( 'unknown parent type' )
				return
			# import pudb; pu.db
			useParentSplitter = False
			indexInParentSplitter = 0
			if parentSplitter:
				indexInParentSplitter = parentSplitter.indexOf ( area.widget )
				if parentSplitter.orientation () == Qt.Vertical:
					useParentSplitter = areaType in ( ToolWindowManager.TopOf, ToolWindowManager.BottomOf )
				else:
					useParentSplitter = areaType in ( ToolWindowManager.LeftOf, ToolWindowManager.RightOf )

			if useParentSplitter:
				if areaType in ( ToolWindowManager.BottomOf , ToolWindowManager.RightOf ):
					indexInParentSplitter += 1
				newArea = self.createArea ()
				newArea.addToolWindows ( toolWindows )
				parentSplitter.insertWidget ( indexInParentSplitter, newArea )

			else:
				area.widget.hide ()
				area.widget.setParent ( None )
				splitter = self.createSplitter ()
				if areaType in ( ToolWindowManager.TopOf, ToolWindowManager.BottomOf ):
					splitter.setOrientation (Qt.Vertical)
				else:
					splitter.setOrientation (Qt.Horizontal)

				splitter.addWidget ( area.widget )
				area.widget.show ()
				newArea = self.createArea ()
				if areaType in ( ToolWindowManager.TopOf, ToolWindowManager.LeftOf ):
					splitter.insertWidget ( 0, newArea )
				else:
					splitter.addWidget ( newArea )

				if parentSplitter:
					parentSplitter.insertWidget ( indexInParentSplitter, splitter )
				else:
					wrapper.layout ().addWidget ( splitter )
				newArea.addToolWindows ( toolWindows )

			# qWarning ( '[moveToolWindows] areaType = LeftOf/RightOf/TopOf/BottomOf' )

		elif areaType == ToolWindowManager.EmptySpace:
			wrapper = self.findChild ( ToolWindowManagerWrapper )
			if wrapper.isOccupied ():
				self.lastUsedArea.addToolWindows ( toolWindows )
			else:
				newArea = self.createArea ()
				wrapper.layout ().addWidget ( newArea )
				newArea.addToolWindows ( toolWindows )

			# qWarning ( '[moveToolWindows] areaType = EmptySpace' )

		elif areaType == ToolWindowManager.LastUsedArea:
			self.lastUsedArea.addToolWindows ( toolWindows )

			# qWarning ( '[moveToolWindows] areaType = areaType == ToolWindowManager.LastUsedArea' )

		else:
			qWarning ( 'invalid type' )

		self.simplifyLayout ()
		for toolWindow in toolWindows:
			self.toolWindowVisibilityChanged.emit ( toolWindow, toolWindow.parent () != None )

	def removeToolWindow ( self, toolWindow ):
		if toolWindow not in self.toolWindowList:
			qWarning ( 'unknown tool window' )
			return
		self.moveToolWindow ( toolWindow, ToolWindowManager.NoArea )
		self.toolWindowList.removeOne (toolWindow)

	def setSuggestionSwitchInterval ( self, msec ):
		self.dropSuggestionSwitchTimer.setInterval (msec)

	def suggestionSwitchInterval ( self ):
		return self.dropSuggestionSwitchTimer.interval ()

	def setBorderSensitivity ( self, pixels ):
		self.borderSensitivity = pixels

	def setRubberBandLineWidth ( self, pixels ):
		self.rubberBandLineWidth = pixels

	def saveState ( self ):
		result = {}
		result[ 'toolWindowManagerStateFormat' ] = 1
		mainWrapper = self.findChild ( ToolWindowManagerWrapper )
		if mainWrapper == None:
			qWarning ( 'can not find main wrapper' )
			return {}

		result[ 'mainWrapper' ] = mainWrapper.saveState ()
		floatingWindowsData = []
		for wrapper in self.wrappers:
			if not wrapper.isWindow (): continue
			floatingWindowsData.append ( wrapper.saveState () )
		result[ 'floatingWindows' ] = floatingWindowsData
		return result

	def restoreState ( self, data ):
		if not isinstance ( data, dict ): return
		if data[ 'toolWindowManagerStateFormat' ] != 1:
			qWarning ( 'state format is not recognized' )
			return
		self.moveToolWindows ( self.toolWindowList, ToolWindowManager.NoArea )
		mainWrapper = self.findChild ( ToolWindowManagerWrapper )
		if not mainWrapper:
			qWarning ( 'can not find main wrapper' )

		mainWrapper.restoreState ( data['mainWrapper'] )
		for windowData in data['floatingWindows']:
			wrapper = ToolWindowManagerWrapper ( self )
			wrapper.restoreState ( windowData )
			wrapper.show ()

		self.simplifyLayout ()
		for toolWindow in self.toolWindowList:
			self.toolWindowVisibilityChanged.emit ( toolWindow, toolWindow.parentWidget () != None )

	def createArea ( self ) -> ToolWindowManagerArea:
		'''
		创建area并监听area的tabClose事件
		'''
		area = ToolWindowManagerArea ( self, None )
		area.tabCloseRequested.connect ( self.tabCloseRequested )
		return area

	def handleNoSuggestions ( self ):
		self.rectRubberBand.hide ()
		self.lineRubberBand.hide ()
		self.lineRubberBand.setParent (self)
		self.rectRubberBand.setParent (self)
		self.suggestions = []
		self.dropCurrentSuggestionIndex = 0
		if self.dropSuggestionSwitchTimer.isActive ():
			self.dropSuggestionSwitchTimer.stop ()

	def releaseToolWindow ( self, toolWindow ):
		previousTabWidget = findClosestParent ( toolWindow, ToolWindowManagerArea )
		if not previousTabWidget:
			qWarning ( 'cannot find tab widget for tool window' )
			return
		previousTabWidget.removeTab ( previousTabWidget.indexOf (toolWindow) )
		toolWindow.hide ()
		toolWindow.setParent ( None )

	def removeArea ( self, area ):
		area.manager = None
		area.deleteLater ()

	def removeWrapper ( self, wrapper ):
		wrapper.deleteLater ()
		self.wrappers.remove ( wrapper )

	def simplifyLayout ( self ):
		newAreas = []
		currentAreas = self.areas
		for area in currentAreas:
			if area.parentWidget () is None:
				if area.count () == 0:
					if area == self.lastUsedArea: self.lastUsedArea = None
					self.removeArea ( area )
				continue

			splitter = cast ( area.parentWidget (), QSplitter )
			validSplitter   = None # least top level splitter that should remain
			invalidSplitter = None #most top level splitter that should be deleted
			while ( splitter ):
				if splitter.count () > 1:
					validSplitter = splitter
					break
				else:
					invalidSplitter = splitter
					splitter = cast ( splitter.parentWidget (), QSplitter )
			if not validSplitter:
				wrapper = findClosestParent ( area, ToolWindowManagerWrapper )
				if not wrapper:
					qWarning ( 'can not find wrapper' )
					print ( findClosestParent ( area, ToolWindowManagerWrapper ) )
					print ( type ( area.parentWidget () ) == ToolWindowManagerWrapper )
					return
				if area.count () == 0 and wrapper.isWindow ():
					wrapper.hide ()
					wrapper.setParent ( None )
					# can not deleteLater immediately (strange MacOS bug)
					self.removeWrapper ( wrapper )
					
				elif area.parent () != wrapper:
					wrapper.layout ().addWidget ( area )

			else:
				if area.count () > 0:
					if validSplitter and area.parent () != validSplitter:
						index = validSplitter.indexOf ( invalidSplitter )
						validSplitter.insertWidget ( index, area )

			if not invalidSplitter is None:
				invalidSplitter.hide ()
				invalidSplitter.setParent ( None )
				invalidSplitter.deleteLater ()

			if area.count () == 0:
				area.hide ()
				area.setParent ( None )
				if area == self.lastUsedArea: self.lastUsedArea = None
				self.removeArea ( area )
				continue

			newAreas.append ( area )
		#keep
		self.areas = newAreas

	def dragInProgress ( self ):
		'''
		指示当前是否正处于拖拽状态
		'''
		return len ( self.draggedToolWindows ) > 0

	def startDrag ( self, toolWindows ):
		'''
		开始拖拽,在指针位置显示拖拽toolWindows的简略快照
		'''
		if self.dragInProgress ():
			qWarning ( 'ToolWindowManager::execDrag: drag is already in progress' )
			return
		if not toolWindows: return
		self.draggedToolWindows = toolWindows
		self.dragIndicator.setPixmap ( self.generateDragPixmap ( toolWindows ) )
		self.updateDragPosition ()
		self.dragIndicator.show ()

	def saveSplitterState ( self, splitter ):
		result = {}
		result['state'] = splitter.saveState ()
		result['type'] = 'splitter'
		
		items = []
		for i in range ( splitter.count () ):
			item = splitter.widget ( i )
			area = cast ( item, ToolWindowManagerArea )
			if area:
				items.append ( area.saveState () )
			else:
				childSplitter = cast ( item, QSplitter )
				if childSplitter:
					items.append ( self. saveSplitterState ( childSplitter ) )
				else:
					qWarning ( 'unknown splitter item' )
		result[ 'items' ] = items
		return result

	def restoreSplitterState ( self, data ):
		if len ( data[ 'items' ] )< 2:
			qWarning ( 'invalid splitter encountered' )

		splitter = self.createSplitter ()

		for itemData in data[ 'items' ]:
			itemType = itemData['type']
			if itemType == 'splitter':
				splitter.addWidget ( self.restoreSplitterState ( itemData ) )
			elif itemType == 'area':
				area = self.createArea ()
				area.restoreState ( itemData )
				splitter.addWidget ( area )
			else:
				qWarning ( 'unknown item type' )
		splitter.restoreState ( data['state'] )
		return splitter

	def generateDragPixmap ( self, toolWindows ):
		'''
		生成一个QTabBar的快照
		'''
		widget = QTabBar ()
		widget.setDocumentMode (True)
		for toolWindow in toolWindows:
			widget.addTab (toolWindow.windowIcon (), toolWindow.windowTitle ())
		#if QT_VERSION >= 0x050000 # Qt5
			return widget.grab ()
		#else #Qt4
		# return QtGui.QPixmap.grabWidget ( widget )
		#endif

	def showNextDropSuggestion ( self ):
		if len ( self.suggestions ) == 0:
			qWarning ( 'showNextDropSuggestion called but no suggestions' )
			return

		self.dropCurrentSuggestionIndex += 1
		if self.dropCurrentSuggestionIndex >= len ( self.suggestions ):
			self.dropCurrentSuggestionIndex = 0
		
		suggestion = self.suggestions[ self.dropCurrentSuggestionIndex ]
		if suggestion.type in ( ToolWindowManager.AddTo , ToolWindowManager.EmptySpace ):
			if suggestion.type == ToolWindowManager.EmptySpace:
				widget = self.findChild ( ToolWindowManagerWrapper )
			else:
				widget = suggestion.widget
			
			if widget.window () == self.window ():
				placeHolderParent = self
			else:
				placeHolderParent = widget.window ()

			placeHolderGeometry = widget.rect ()
			placeHolderGeometry.moveTopLeft (
				widget.mapTo ( placeHolderParent, placeHolderGeometry.topLeft () )
			)
			self.rectRubberBand.setGeometry ( placeHolderGeometry )
			self.rectRubberBand.setParent ( placeHolderParent )
			self.rectRubberBand.show ()
			self.lineRubberBand.hide ()

		elif suggestion.type in (
			ToolWindowManager.LeftOf , ToolWindowManager.RightOf,
			ToolWindowManager.TopOf , ToolWindowManager.BottomOf ):
			if suggestion.widget.window () == self.window ():
				placeHolderParent = self
			else:
				placeHolderParent = suggestion.widget.window ()

			placeHolderGeometry = self.sidePlaceHolderRect ( suggestion.widget, suggestion.type )
			placeHolderGeometry.moveTopLeft (
				suggestion.widget.mapTo ( placeHolderParent, placeHolderGeometry.topLeft () )
			)
			self.lineRubberBand.setGeometry (placeHolderGeometry)
			self.lineRubberBand.setParent (placeHolderParent)
			self.lineRubberBand.show ()
			self.rectRubberBand.hide ()

		else:
			qWarning ( 'unsupported suggestion type' )

	def findSuggestions ( self, wrapper ):
		self.suggestions = []
		self.dropCurrentSuggestionIndex = -1
		globalPos  = QCursor.pos ()
		candidates = []
		for splitter in wrapper.findChildren ( QSplitter ):
			candidates.append ( splitter )

		for area in self.areas:
			if area.window () == wrapper.window ():
				candidates.append ( area )

		for widget in candidates:
			splitter = cast ( widget, QSplitter )
			area = cast ( widget, ToolWindowManagerArea )
			if not ( splitter or area ):
				qWarning ( 'unexpected widget type' )
				continue

			parentSplitter = cast ( widget.parentWidget (), QSplitter )
			lastInSplitter = parentSplitter and \
					parentSplitter.indexOf (widget) == parentSplitter.count () - 1

			allowedSides = []
			if not splitter or splitter.orientation () == Qt.Vertical:
				allowedSides.append ( ToolWindowManager.LeftOf )

			if not splitter or splitter.orientation () == Qt.Horizontal:
				allowedSides.append ( ToolWindowManager.TopOf )

			if not parentSplitter or parentSplitter.orientation () == Qt.Vertical or lastInSplitter:
				if not splitter or splitter.orientation () == Qt.Vertical:
					allowedSides.append ( ToolWindowManager.RightOf )

			if not parentSplitter or parentSplitter.orientation () == Qt.Horizontal or lastInSplitter:
				if not splitter or splitter.orientation () == Qt.Horizontal:
					allowedSides.append ( ToolWindowManager.BottomOf )
			for side in allowedSides:
				rect = self.sideSensitiveArea ( widget, side )
				pos  = widget.mapFromGlobal ( globalPos )
				if rect.contains ( pos ):
					self.suggestions.append ( AreaReference ( side, widget ) )
			if area:
				rect = area.rect ()
				pos  = area.mapFromGlobal ( globalPos )
				if rect.contains ( pos ):
					self.suggestions.append ( AreaReference ( ToolWindowManager.AddTo, area ) )

		#end of for
		if not candidates:
			self.suggestions.append ( AreaReference ( ToolWindowManager.EmptySpace ) )

		if len ( self.suggestions ) == 0:
			self.handleNoSuggestions ()
		else:
			self.showNextDropSuggestion ()

	def sideSensitiveArea ( self, widget, side ):
		widgetRect = widget.rect ()
		if side == ToolWindowManager.TopOf:
			return QRect (QPoint (widgetRect.left (), widgetRect.top () - self.borderSensitivity),
									 QSize (widgetRect.width (), self.borderSensitivity * 2))
		elif side == ToolWindowManager.LeftOf:
			return QRect (QPoint (widgetRect.left () - self.borderSensitivity, widgetRect.top ()),
									 QSize (self.borderSensitivity * 2, widgetRect.height ()))

		elif side == ToolWindowManager.BottomOf:
			return QRect (QPoint (widgetRect.left (), widgetRect.top () + widgetRect.height () - self.borderSensitivity),
									 QSize (widgetRect.width (), self.borderSensitivity * 2))
		elif side == ToolWindowManager.RightOf:
			return QRect (QPoint (widgetRect.left () + widgetRect.width () - self.borderSensitivity, widgetRect.top ()),
									 QSize (self.borderSensitivity * 2, widgetRect.height ()))
		else:
			qWarning ( 'invalid side' )
			return QRect ()

	def sidePlaceHolderRect ( self, widget, side ):
		widgetRect = widget.rect ()
		parentSplitter = cast ( widget.parentWidget (), QSplitter )
		if parentSplitter and parentSplitter.indexOf (widget) > 0:
			delta = parentSplitter.handleWidth () / 2 + self.rubberBandLineWidth / 2
			if side == ToolWindowManager.TopOf and parentSplitter.orientation () == Qt.Vertical:
				return QRect (QPoint ( widgetRect.left (), widgetRect.top () - int (delta) ),
										 QSize ( widgetRect.width (), self.rubberBandLineWidth ) )
			elif side == ToolWindowManager.LeftOf and parentSplitter.orientation () == Qt.Horizontal:
				return QRect (QPoint (widgetRect.left () - int (delta), widgetRect.top ()),
										 QSize (self.rubberBandLineWidth, widgetRect.height ()))

		if side == ToolWindowManager.TopOf:
			return QRect (QPoint (widgetRect.left (), widgetRect.top ()),
									 QSize (widgetRect.width (), self.rubberBandLineWidth))
		elif side == ToolWindowManager.LeftOf:
			return QRect (QPoint (widgetRect.left (), widgetRect.top ()),
									 QSize (self.rubberBandLineWidth, widgetRect.height ()))
		elif side == ToolWindowManager.BottomOf:
			return QRect (QPoint (widgetRect.left (), widgetRect.top () + widgetRect.height () - self.rubberBandLineWidth),
									 QSize (widgetRect.width (), self.rubberBandLineWidth))
		elif side == ToolWindowManager.RightOf:
			return QRect (QPoint (widgetRect.left () + widgetRect.width () - self.rubberBandLineWidth, widgetRect.top ()),
									 QSize (self.rubberBandLineWidth, widgetRect.height ()))
		else:
			qWarning ( 'invalid side' )
			return QRect ()

	def updateDragPosition ( self ):
		if not self.dragInProgress (): return
		if not QApplication.mouseButtons () & Qt.LeftButton :
			self.finishDrag ()
			return

		pos = QCursor.pos ()
		self.dragIndicator.move ( pos + QPoint (1, 1) )
		foundWrapper = False
		window = QApplication.topLevelAt ( pos )
		for wrapper in self.wrappers:
			if wrapper.window () == window:
				if wrapper.rect ().contains ( wrapper.mapFromGlobal (pos) ):
					self.findSuggestions ( wrapper )
					if len ( self.suggestions ) > 0:
						#starting or restarting timer
						if self.dropSuggestionSwitchTimer.isActive ():
							self.dropSuggestionSwitchTimer.stop ()
						self.dropSuggestionSwitchTimer.start ()
						foundWrapper = True
				break
		if not foundWrapper:
			self.handleNoSuggestions ()

	def finishDrag ( self ):
		if not self.dragInProgress ():
			qWarning ( 'unexpected finishDrag' )
			return

		# 如果suggestions数组中没有建议位置,则创建一个Wrapper窗口
		# 反之,则移动toolWindow到建议位置
		if len ( self.suggestions ) == 0:
			self.moveToolWindows ( self.draggedToolWindows, ToolWindowManager.NewFloatingArea )
		else:
			if self.dropCurrentSuggestionIndex >= len ( self.suggestions ):
				qWarning ( 'invalid self.dropCurrentSuggestionIndex' )
				return
			suggestion = self.suggestions[ self.dropCurrentSuggestionIndex ]
			self.handleNoSuggestions ()
			self.moveToolWindows ( self.draggedToolWindows, suggestion )

		self.dragIndicator.hide ()
		self.draggedToolWindows = []

	def tabCloseRequested ( self, index ):
		'''
		处理area控件的子tab关闭事件
		'''
		if not isinstance ( self.sender (), ToolWindowManagerArea ):
			qWarning ( 'sender is not a ToolWindowManagerArea' )
			return
		area = self.sender ()
		toolWindow = area.widget ( index )
		if not self.hasToolWindow ( toolWindow ):
			qWarning ( 'unknown tab in tab widget' )
			return
		self.hideToolWindow ( toolWindow )

	def createSplitter ( self ):
		splitter = QSplitter ()
		splitter.setChildrenCollapsible ( False )
		return splitter
Exemplo n.º 8
0
 def _create_rubber_band(self):
     rubber_band = QRubberBand(QRubberBand.Rectangle, self.label_image)
     pal = QPalette()
     pal.setBrush(QPalette.Highlight, QBrush(Qt.red))
     rubber_band.setPalette(pal)
     return rubber_band