def __init__(self, remoteName, remoteUrl, parent=None):
        """
        Constructor
        
        @param remoteName name of the remote repository
        @type str
        @param remoteUrl URL of the remote repository
        @type str
        @param parent reference to the parent widget
        @type QWidget
        """
        super(GitChangeRemoteUrlDialog, self).__init__(parent)
        self.setupUi(self)

        url = QUrl(remoteUrl)
        self.__userInfo = url.userInfo()

        self.nameEdit.setText(remoteName)
        self.urlEdit.setText(url.toString(QUrl.RemoveUserInfo))

        self.__updateOK()

        self.newUrlEdit.setFocus(Qt.OtherFocusReason)

        msh = self.minimumSizeHint()
        self.resize(max(self.width(), msh.width()), msh.height())
Exemple #2
0
class NetworkMJPGImage(QQuickPaintedItem):
    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)

        self._stream_buffer = QByteArray()
        self._stream_buffer_start_index = -1
        self._network_manager = None  # type: QNetworkAccessManager
        self._image_request = None  # type: QNetworkRequest
        self._image_reply = None  # type: QNetworkReply
        self._image = QImage()
        self._image_rect = QRect()

        self._source_url = QUrl()
        self._started = False

        self._mirror = False

        self.setAntialiasing(True)

    ##  Ensure that close gets called when object is destroyed
    def __del__(self) -> None:
        self.stop()

    def paint(self, painter: "QPainter") -> None:
        if self._mirror:
            painter.drawImage(self.contentsBoundingRect(),
                              self._image.mirrored())
            return

        painter.drawImage(self.contentsBoundingRect(), self._image)

    def setSourceURL(self, source_url: "QUrl") -> None:
        self._source_url = source_url
        self.sourceURLChanged.emit()
        if self._started:
            self.start()

    def getSourceURL(self) -> "QUrl":
        return self._source_url

    sourceURLChanged = pyqtSignal()
    source = pyqtProperty(QUrl,
                          fget=getSourceURL,
                          fset=setSourceURL,
                          notify=sourceURLChanged)

    def setMirror(self, mirror: bool) -> None:
        if mirror == self._mirror:
            return
        self._mirror = mirror
        self.mirrorChanged.emit()
        self.update()

    def getMirror(self) -> bool:
        return self._mirror

    mirrorChanged = pyqtSignal()
    mirror = pyqtProperty(bool,
                          fget=getMirror,
                          fset=setMirror,
                          notify=mirrorChanged)

    imageSizeChanged = pyqtSignal()

    @pyqtProperty(int, notify=imageSizeChanged)
    def imageWidth(self) -> int:
        return self._image.width()

    @pyqtProperty(int, notify=imageSizeChanged)
    def imageHeight(self) -> int:
        return self._image.height()

    @pyqtSlot()
    def start(self) -> None:
        self.stop()  # Ensure that previous requests (if any) are stopped.

        if not self._source_url:
            Logger.log("w", "Unable to start camera stream without target!")
            return

        auth_data = ""
        if self._source_url.userInfo():
            # move auth data to basic authorization header
            auth_data = base64.b64encode(
                self._source_url.userInfo().encode()).decode("utf-8")
            authority = self._source_url.authority()
            self._source_url.setAuthority(authority.rsplit("@", 1)[1])

        self._image_request = QNetworkRequest(self._source_url)
        self._image_request.setAttribute(
            QNetworkRequest.FollowRedirectsAttribute, True)

        if auth_data:
            self._image_request.setRawHeader(b"Authorization",
                                             ("basic %s" % auth_data).encode())

        if self._source_url.scheme().lower() == "https":
            # ignore SSL errors (eg for self-signed certificates)
            ssl_configuration = QSslConfiguration.defaultConfiguration()
            ssl_configuration.setPeerVerifyMode(QSslSocket.VerifyNone)
            self._image_request.setSslConfiguration(ssl_configuration)

        if self._network_manager is None:
            self._network_manager = QNetworkAccessManager()

        self._image_reply = self._network_manager.get(self._image_request)
        self._image_reply.downloadProgress.connect(
            self._onStreamDownloadProgress)

        self._started = True

    @pyqtSlot()
    def stop(self) -> None:
        self._stream_buffer = QByteArray()
        self._stream_buffer_start_index = -1

        if self._image_reply:
            try:
                try:
                    self._image_reply.downloadProgress.disconnect(
                        self._onStreamDownloadProgress)
                except Exception:
                    pass

                if not self._image_reply.isFinished():
                    self._image_reply.close()
            except Exception as e:  # RuntimeError
                pass  # It can happen that the wrapped c++ object is already deleted.

            self._image_reply = None
            self._image_request = None

        self._network_manager = None

        self._started = False

    def _onStreamDownloadProgress(self, bytes_received: int,
                                  bytes_total: int) -> None:
        # An MJPG stream is (for our purpose) a stream of concatenated JPG images.
        # JPG images start with the marker 0xFFD8, and end with 0xFFD9
        if self._image_reply is None:
            return
        self._stream_buffer += self._image_reply.readAll()

        if (len(self._stream_buffer) >
                5000000):  # No single camera frame should be 5 MB or larger
            Logger.log(
                "w",
                "MJPEG buffer exceeds reasonable size. Restarting stream...")
            self.stop()  # resets stream buffer and start index
            self.start()
            return

        if self._stream_buffer_start_index == -1:
            self._stream_buffer_start_index = self._stream_buffer.indexOf(
                b"\xff\xd8")
        stream_buffer_end_index = self._stream_buffer.lastIndexOf(b"\xff\xd9")
        # If this happens to be more than a single frame, then so be it; the JPG decoder will
        # ignore the extra data. We do it like this in order not to get a buildup of frames

        if self._stream_buffer_start_index != -1 and stream_buffer_end_index != -1:
            jpg_data = self._stream_buffer[
                self._stream_buffer_start_index:stream_buffer_end_index + 2]
            self._stream_buffer = self._stream_buffer[stream_buffer_end_index +
                                                      2:]
            self._stream_buffer_start_index = -1
            self._image.loadFromData(jpg_data)

            if self._image.rect() != self._image_rect:
                self.imageSizeChanged.emit()

            self.update()