def loadModel(self):
        imd = None
        try:
            loader = ModelLoader(self.ui.mDataLineEdit.text())
            models = loader.detect_models()
            model_names = map(lambda m: m.name, models)
            self._log_output("Looking up models: " + ', '.join(model_names))
            ili = loader.gen_lookup_ili()
            qDebug(ili)
            wpsreq = self._create_wps_request(ili)
            url = self.ui.mIlisMetaUrlLineEdit.text()
            req = QNetworkRequest(QUrl(url))
            req.setHeader(QNetworkRequest.ContentTypeHeader, 'application/xml')
            data = QByteArray()
            data.append(wpsreq)
            reply = QgsNetworkAccessManager.instance().blockingPost(req, data)

            if reply.error() == QNetworkReply.NoError:
                result = reply.content()
                imd = self._parse_wps_response(result)
        except Exception as e:
            qDebug("Exception during IlisModel download")
        if imd is None:
            self._show_log_window()
            QgsApplication.messageLog().logMessage(
                "Couldn't download Ilismeta model", "Interlis",
                Qgis.MessageLevel(1))
            self.ui.mModelLineEdit.setText("")
        else:
            fh, imdfn = tempfile.mkstemp(suffix='.imd')
            os.close(fh)
            with codecs.open(imdfn, "w", encoding='utf-8') as file:
                file.write(imd)
            self.ui.mModelLineEdit.setText(imdfn)
Exemplo n.º 2
0
    def send_request(self, request_type: str = "search"):
        """Sends a request to the Isogeo's API using QNetworkRequestManager. That's the
        handle_reply method which get the API's response. See below.

        :param str request_type: type of request to send. Options:
            - 'token'
            - 'search'
            - 'details'
            - 'shares'
        """
        logger.info(
            "-------------- Sending a '{}' request --------------".format(
                request_type))
        # creating the QNetworkRequest appropriate to the request_type
        request = self.create_request(request_type)
        # post request for 'token' request
        if request_type == "token":
            data = QByteArray()
            data.append(urlencode({"grant_type": "client_credentials"}))
            self.request = self.qnam.post(request, data)
        # get request for other
        else:
            self.request = self.qnam.get(request)
        # to catch SSL errors
        # (see https://github.com/isogeo/isogeo-plugin-qgis/issues/266)
        self.request.sslErrors.connect(self.ssl_error_catcher)
        # since https://github.com/isogeo/isogeo-plugin-qgis/issues/288, the slot is
        # connected to the request's signal and no more to QgsNetworkAccessManager's one
        # because otherwise, the plugin doesn't work on QGIS 3.6.x
        self.request.finished.connect(partial(self.handle_reply, self.request))
        return
    def api_authentification(self):
        logger.debug("\n------------------ Authentication ------------------")

        # creating credentials header
        crd_header_value = QByteArray()
        crd_header_value.append("Basic ")
        crd_header_value.append(
            base64.b64encode("{}:{}".format(self.app_id, self.app_secrets).encode())
        )

        crd_header_name = QByteArray()
        crd_header_name.append("Authorization")

        # creating Content-Type header
        ct_header_value = QByteArray()
        ct_header_value.append("application/json")

        # creating request
        token_rqst = QNetworkRequest(QUrl(self.token_url))

        # setting headers
        token_rqst.setRawHeader(crd_header_name, crd_header_value)
        token_rqst.setHeader(token_rqst.ContentTypeHeader, ct_header_value)

        # creating data
        data = QByteArray()
        data.append(urlencode({"grant_type": "client_credentials"}))

        # requesting and handle reply
        logger.debug("Asking for token")
        token_reply = self.naMngr.post(token_rqst, data)
        token_reply.finished.connect(partial(self.api_handle_token, reply=token_reply))
Exemplo n.º 4
0
    def ask_for_token(self, c_id, c_secret):
        """Ask a token from Isogeo API authentification page.

        This send a POST request to Isogeo API with the user id and secret in
        its header. The API should return an access token
        """
        # check if API access are already set
        if self.api_id != 0 and self.api_secret != 0:
            logger.info("User_authentication function is trying "
                        "to get a token from the id/secret")
            self.request_status_clear = 1
            pass
        else:
            logger.error("No id/secret.")
            return 0

        # API token request
        headervalue = "Basic " + base64.b64encode(c_id + ":" + c_secret)
        data = urlencode({"grant_type": "client_credentials"})
        databyte = QByteArray()
        databyte.append(data)
        url = QUrl("https://id.api.isogeo.com/oauth/token")
        request = QNetworkRequest(url)
        request.setRawHeader("Authorization", headervalue)
        if self.request_status_clear:
            self.request_status_clear = 0
            token_reply = self.manager.post(request, databyte)
            token_reply.finished.connect(
                partial(self.handle_token, answer=token_reply))
            QgsMessageLog.logMessage("Authentication succeeded", "Isogeo")
        else:
            pass
Exemplo n.º 5
0
    def api_get_request(self):
        logger.debug("\n------------------ Sending request ------------------")

        # creating credentials header
        logger.debug("Creating credentials header")

        crd_header_value = QByteArray()
        crd_header_value.append(self.token)

        crd_header_name = QByteArray()
        crd_header_name.append("Authorization")

        # creating request
        rqst = QNetworkRequest(QUrl(self.request_url))
        logger.debug("Creating request : {}".format(rqst.url()))

        # setting credentials header
        rqst.setRawHeader(crd_header_name, crd_header_value)
        logger.debug("Setting credentials header : {}".format(
            rqst.rawHeader(crd_header_name)))

        # sending request
        rqst_reply = self.naMngr.get(rqst)
        logger.debug("Sending request")

        rqst_reply.finished.connect(
            partial(self.api_handle_request, reply=rqst_reply))
class CloudqubeJsonReply(CloudqubeReply):
    def __init__(self, reply, stream, callback, finished, error):
        super().__init__(reply, error)
        #reply.readyRead.connect(self.read)
        reply.finished.connect(self.finished)
        reply.setReadBufferSize(1024 * 1024)
        self._callback = callback
        self._finished = finished
        self._data = QByteArray()
        # Storing request data stream so that it doesn't get
        # destroyed before sending it
        self._stream = stream

    def read(self):
        bytes_available = self._reply.bytesAvailable()
        data = self._reply.read(bytes_available)
        self._data.append(data)

    def finished(self):
        err = self._reply.error()
        if (err == QNetworkReply.NoError):
            self._data.append(self._reply.readAll())
            data_str = self._data.data().decode('utf-8')
            if len(data_str) > 0:
                self._callback(json.loads(data_str))
            else:
                self._callback()
            self._finished(self)
        else:
            QgsMessageLog.logMessage('Error {0}: {1}!'.format(
                err, self._reply.errorString()))
Exemplo n.º 7
0
 def save_cookies(self):
     with QMutexLocker(self.mutex):
         cookies = self.allCookies()
         data = QByteArray()
         for cookie in cookies:
             if not cookie.isSessionCookie():
                 data.append(cookie.toRawForm())
                 data.append("\n")
         QSettings().setValue("irmt/cookies", data)
Exemplo n.º 8
0
    def create_request(self, request_type: str):
        """Creates a QNetworkRequest() with appropriate headers and URL according to the
        'request_type' parameter.

        :param str request_type: type of request to create. Options:
            - 'token'
            - 'search'
            - 'details'
            - 'shares'

        :returns: the QNetworkRequest to send to the Isogeo's API

        :rtype: QNetworkRequest
        """
        # creating headers (same steps wathever request_type value)
        header_value = QByteArray()
        header_name = QByteArray()
        header_name.append("Authorization")
        # for token request
        if request_type == "token":
            # filling request header with credentials
            header_value.append("Basic ")
            header_value.append(
                base64.b64encode("{}:{}".format(self.app_id,
                                                self.app_secret).encode()))
            # creating the QNetworkRequest from oAuth2 authentication URL
            request = QNetworkRequest(QUrl(self.api_url_token))
            # creating and setting the 'Content-type header'
            ct_header_value = QByteArray()
            ct_header_value.append("application/json")
            request.setHeader(request.ContentTypeHeader, ct_header_value)
        # for other request_type, setting appropriate url
        else:
            if request_type == "shares":
                url = QUrl("{}/shares".format(self.api_url_base))
            elif request_type == "search" or request_type == "details":
                url = QUrl(self.currentUrl)
            else:
                logger.debug(
                    "Unkown request type asked : {}".format(request_type))
                raise ValueError
                return 0
            # filling request header with token
            header_value.append(self.token)
            request = QNetworkRequest(url)
        # creating QNetworkRequest from appropriate url
        request.setRawHeader(header_name, header_value)
        return request
Exemplo n.º 9
0
    def api_get_request(self):
        # creating credentials header
        crd_header_value = QByteArray()
        crd_header_value.append(self.token)
        crd_header_name = QByteArray()
        crd_header_name.append("Authorization")

        # creating request
        rqst = QNetworkRequest(QUrl(self.request_url))

        # setting credentials header
        rqst.setRawHeader(crd_header_name, crd_header_value)

        # sending request and handle API reply
        rqst_reply = self.naMngr.get(rqst)
        rqst_reply.finished.connect(
            partial(self.api_handle_request, reply=rqst_reply))
Exemplo n.º 10
0
        def run():
            def sslVerifyNone(req):
                conf = req.sslConfiguration()
                conf.setPeerVerifyMode( QSslSocket.VerifyNone )
                req.setSslConfiguration( conf )

            req = QNetworkRequest( url )
            sslVerifyNone( req ) # Need for Windows, error 'Handshake failed'
            if json_request is None:
                reply = self.nam.get( req )
            else:
                req.setHeader( QNetworkRequest.ContentTypeHeader, "application/json" )
                data = QByteArray()
                data.append( json.dumps( json_request ) )
                reply = self.nam.post( req, data )
            if reply is None:
                response = { 'isOk': False, 'message': "Network error", 'errorCode': -1 }
                self.finished.emit( response )
                return
            self.abortReply.connect( reply.abort )
            if not self.responseAllFinished:
                self._connectReply( reply )
Exemplo n.º 11
0
    def test_network_mixin_post(self):
        """Test network mixin post"""
        request_url = 'http://jsonplaceholder.typicode.com/posts'

        post_data = QByteArray()
        post_data.append("title=%s&" % self.api_results['title'])
        post_data.append("body=%s&" % self.api_results['body'])
        post_data.append("userId=%d&" % self.api_results['userId'])

        manager = NetworkMixin(request_url=request_url)
        manager.connect_post(post_data)
        while not manager.reply.isFinished():
            QCoreApplication.processEvents()
        self.assertIsNotNone(manager.get_json_results())
        self.assertEqual(manager.get_json_results()['userId'],
                         self.api_results['userId'])
        self.assertEqual(manager.get_json_results()['body'],
                         self.api_results['body'])
Exemplo n.º 12
0
    def xmlDownloaded(self):
        """ populate the plugins object with the fetched data """
        reply = self.sender()
        reposName = reply.property('reposName')
        if reply.error() != QNetworkReply.NoError:                             # fetching failed
            self.mRepositories[reposName]["state"] = 3
            self.mRepositories[reposName]["error"] = reply.errorString()
            if reply.error() == QNetworkReply.OperationCanceledError:
                self.mRepositories[reposName]["error"] += "\n\n" + QCoreApplication.translate("QgsPluginInstaller", "If you haven't canceled the download manually, it was most likely caused by a timeout. In this case consider increasing the connection timeout value in QGIS options window.")
        elif reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 301:
            redirectionUrl = reply.attribute(QNetworkRequest.RedirectionTargetAttribute)
            if redirectionUrl.isRelative():
                redirectionUrl = reply.url().resolved(redirectionUrl)
            redirectionCounter = reply.property('redirectionCounter') + 1
            if redirectionCounter > 4:
                self.mRepositories[reposName]["state"] = 3
                self.mRepositories[reposName]["error"] = QCoreApplication.translate("QgsPluginInstaller", "Too many redirections")
            else:
                # Fire a new request and exit immediately in order to quietly destroy the old one
                self.requestFetching(reposName, redirectionUrl, redirectionCounter)
                reply.deleteLater()
                return
        else:
            reposXML = QDomDocument()
            content = reply.readAll()
            # Fix lonely ampersands in metadata
            a = QByteArray()
            a.append("& ")
            b = QByteArray()
            b.append("& ")
            content = content.replace(a, b)
            reposXML.setContent(content)
            pluginNodes = reposXML.elementsByTagName("pyqgis_plugin")
            if pluginNodes.size():
                for i in range(pluginNodes.size()):
                    fileName = pluginNodes.item(i).firstChildElement("file_name").text().strip()
                    if not fileName:
                        fileName = QFileInfo(pluginNodes.item(i).firstChildElement("download_url").text().strip().split("?")[0]).fileName()
                    name = fileName.partition(".")[0]
                    experimental = False
                    if pluginNodes.item(i).firstChildElement("experimental").text().strip().upper() in ["TRUE", "YES"]:
                        experimental = True
                    deprecated = False
                    if pluginNodes.item(i).firstChildElement("deprecated").text().strip().upper() in ["TRUE", "YES"]:
                        deprecated = True
                    trusted = False
                    if pluginNodes.item(i).firstChildElement("trusted").text().strip().upper() in ["TRUE", "YES"]:
                        trusted = True
                    icon = pluginNodes.item(i).firstChildElement("icon").text().strip()
                    if icon and not icon.startswith("http"):
                        icon = "http://{}/{}".format(QUrl(self.mRepositories[reposName]["url"]).host(), icon)

                    if pluginNodes.item(i).toElement().hasAttribute("plugin_id"):
                        plugin_id = pluginNodes.item(i).toElement().attribute("plugin_id")
                    else:
                        plugin_id = None

                    plugin = {
                        "id": name,
                        "plugin_id": plugin_id,
                        "name": pluginNodes.item(i).toElement().attribute("name"),
                        "version_available": pluginNodes.item(i).toElement().attribute("version"),
                        "description": pluginNodes.item(i).firstChildElement("description").text().strip(),
                        "about": pluginNodes.item(i).firstChildElement("about").text().strip(),
                        "author_name": pluginNodes.item(i).firstChildElement("author_name").text().strip(),
                        "homepage": pluginNodes.item(i).firstChildElement("homepage").text().strip(),
                        "download_url": pluginNodes.item(i).firstChildElement("download_url").text().strip(),
                        "category": pluginNodes.item(i).firstChildElement("category").text().strip(),
                        "tags": pluginNodes.item(i).firstChildElement("tags").text().strip(),
                        "changelog": pluginNodes.item(i).firstChildElement("changelog").text().strip(),
                        "author_email": pluginNodes.item(i).firstChildElement("author_email").text().strip(),
                        "tracker": pluginNodes.item(i).firstChildElement("tracker").text().strip(),
                        "code_repository": pluginNodes.item(i).firstChildElement("repository").text().strip(),
                        "downloads": pluginNodes.item(i).firstChildElement("downloads").text().strip(),
                        "average_vote": pluginNodes.item(i).firstChildElement("average_vote").text().strip(),
                        "rating_votes": pluginNodes.item(i).firstChildElement("rating_votes").text().strip(),
                        "icon": icon,
                        "experimental": experimental,
                        "deprecated": deprecated,
                        "trusted": trusted,
                        "filename": fileName,
                        "installed": False,
                        "available": True,
                        "status": "not installed",
                        "error": "",
                        "error_details": "",
                        "version_installed": "",
                        "zip_repository": reposName,
                        "library": "",
                        "readonly": False
                    }
                    qgisMinimumVersion = pluginNodes.item(i).firstChildElement("qgis_minimum_version").text().strip()
                    if not qgisMinimumVersion:
                        qgisMinimumVersion = "2"
                    qgisMaximumVersion = pluginNodes.item(i).firstChildElement("qgis_maximum_version").text().strip()
                    if not qgisMaximumVersion:
                        qgisMaximumVersion = qgisMinimumVersion[0] + ".99"
                    # if compatible, add the plugin to the list
                    if not pluginNodes.item(i).firstChildElement("disabled").text().strip().upper() in ["TRUE", "YES"]:
                        if isCompatible(pyQgisVersion(), qgisMinimumVersion, qgisMaximumVersion):
                            # add the plugin to the cache
                            plugins.addFromRepository(plugin)
                self.mRepositories[reposName]["state"] = 2
            else:
                # no plugin metadata found
                self.mRepositories[reposName]["state"] = 3
                if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 200:
                    self.mRepositories[reposName]["error"] = QCoreApplication.translate("QgsPluginInstaller", "Server response is 200 OK, but doesn't contain plugin metatada. This is most likely caused by a proxy or a wrong repository URL. You can configure proxy settings in QGIS options.")
                else:
                    self.mRepositories[reposName]["error"] = QCoreApplication.translate("QgsPluginInstaller", "Status code:") + " {} {}".format(
                        reply.attribute(QNetworkRequest.HttpStatusCodeAttribute),
                        reply.attribute(QNetworkRequest.HttpReasonPhraseAttribute)
                    )

        self.repositoryFetched.emit(reposName)

        # is the checking done?
        if not self.fetchingInProgress():
            self.checkingDone.emit()

        reply.deleteLater()
Exemplo n.º 13
0
    def xmlDownloaded(self):
        """ populate the plugins object with the fetched data """
        reply = self.sender()
        reposName = reply.property('reposName')
        if reply.error() != QNetworkReply.NoError:  # fetching failed
            self.mRepositories[reposName]["state"] = 3
            self.mRepositories[reposName]["error"] = reply.errorString()
            if reply.error() == QNetworkReply.OperationCanceledError:
                self.mRepositories[reposName][
                    "error"] += "\n\n" + QCoreApplication.translate(
                        "QgsPluginInstaller",
                        "If you haven't canceled the download manually, it was most likely caused by a timeout. In this case consider increasing the connection timeout value in QGIS options window."
                    )
        elif reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 301:
            redirectionUrl = reply.attribute(
                QNetworkRequest.RedirectionTargetAttribute)
            if redirectionUrl.isRelative():
                redirectionUrl = reply.url().resolved(redirectionUrl)
            redirectionCounter = reply.property('redirectionCounter') + 1
            if redirectionCounter > 4:
                self.mRepositories[reposName]["state"] = 3
                self.mRepositories[reposName][
                    "error"] = QCoreApplication.translate(
                        "QgsPluginInstaller", "Too many redirections")
            else:
                # Fire a new request and exit immediately in order to quietly destroy the old one
                self.requestFetching(reposName, redirectionUrl,
                                     redirectionCounter)
                reply.deleteLater()
                return
        else:
            reposXML = QDomDocument()
            content = reply.readAll()
            # Fix lonely ampersands in metadata
            a = QByteArray()
            a.append("& ")
            b = QByteArray()
            b.append("& ")
            content = content.replace(a, b)
            reposXML.setContent(content)
            pluginNodes = reposXML.elementsByTagName("pyqgis_plugin")
            if pluginNodes.size():
                for i in range(pluginNodes.size()):
                    fileName = pluginNodes.item(i).firstChildElement(
                        "file_name").text().strip()
                    if not fileName:
                        fileName = QFileInfo(
                            pluginNodes.item(i).firstChildElement(
                                "download_url").text().strip().split("?")
                            [0]).fileName()
                    name = fileName.partition(".")[0]
                    experimental = False
                    if pluginNodes.item(i).firstChildElement(
                            "experimental").text().strip().upper() in [
                                "TRUE", "YES"
                            ]:
                        experimental = True
                    deprecated = False
                    if pluginNodes.item(i).firstChildElement(
                            "deprecated").text().strip().upper() in [
                                "TRUE", "YES"
                            ]:
                        deprecated = True
                    trusted = False
                    if pluginNodes.item(i).firstChildElement(
                            "trusted").text().strip().upper() in [
                                "TRUE", "YES"
                            ]:
                        trusted = True
                    icon = pluginNodes.item(i).firstChildElement(
                        "icon").text().strip()
                    if icon and not icon.startswith("http"):
                        icon = "http://{}/{}".format(
                            QUrl(self.mRepositories[reposName]["url"]).host(),
                            icon)

                    if pluginNodes.item(i).toElement().hasAttribute(
                            "plugin_id"):
                        plugin_id = pluginNodes.item(i).toElement().attribute(
                            "plugin_id")
                    else:
                        plugin_id = None

                    plugin = {
                        "id":
                        name,
                        "plugin_id":
                        plugin_id,
                        "name":
                        pluginNodes.item(i).toElement().attribute("name"),
                        "version_available":
                        pluginNodes.item(i).toElement().attribute("version"),
                        "description":
                        pluginNodes.item(i).firstChildElement(
                            "description").text().strip(),
                        "about":
                        pluginNodes.item(i).firstChildElement(
                            "about").text().strip(),
                        "author_name":
                        pluginNodes.item(i).firstChildElement(
                            "author_name").text().strip(),
                        "homepage":
                        pluginNodes.item(i).firstChildElement(
                            "homepage").text().strip(),
                        "download_url":
                        pluginNodes.item(i).firstChildElement(
                            "download_url").text().strip(),
                        "category":
                        pluginNodes.item(i).firstChildElement(
                            "category").text().strip(),
                        "tags":
                        pluginNodes.item(i).firstChildElement(
                            "tags").text().strip(),
                        "changelog":
                        pluginNodes.item(i).firstChildElement(
                            "changelog").text().strip(),
                        "author_email":
                        pluginNodes.item(i).firstChildElement(
                            "author_email").text().strip(),
                        "tracker":
                        pluginNodes.item(i).firstChildElement(
                            "tracker").text().strip(),
                        "code_repository":
                        pluginNodes.item(i).firstChildElement(
                            "repository").text().strip(),
                        "downloads":
                        pluginNodes.item(i).firstChildElement(
                            "downloads").text().strip(),
                        "average_vote":
                        pluginNodes.item(i).firstChildElement(
                            "average_vote").text().strip(),
                        "rating_votes":
                        pluginNodes.item(i).firstChildElement(
                            "rating_votes").text().strip(),
                        "icon":
                        icon,
                        "experimental":
                        experimental,
                        "deprecated":
                        deprecated,
                        "trusted":
                        trusted,
                        "filename":
                        fileName,
                        "installed":
                        False,
                        "available":
                        True,
                        "status":
                        "not installed",
                        "error":
                        "",
                        "error_details":
                        "",
                        "version_installed":
                        "",
                        "zip_repository":
                        reposName,
                        "library":
                        "",
                        "readonly":
                        False
                    }
                    qgisMinimumVersion = pluginNodes.item(i).firstChildElement(
                        "qgis_minimum_version").text().strip()
                    if not qgisMinimumVersion:
                        qgisMinimumVersion = "2"
                    qgisMaximumVersion = pluginNodes.item(i).firstChildElement(
                        "qgis_maximum_version").text().strip()
                    if not qgisMaximumVersion:
                        qgisMaximumVersion = qgisMinimumVersion[0] + ".99"
                    # if compatible, add the plugin to the list
                    if not pluginNodes.item(i).firstChildElement(
                            "disabled").text().strip().upper() in [
                                "TRUE", "YES"
                            ]:
                        if isCompatible(pyQgisVersion(), qgisMinimumVersion,
                                        qgisMaximumVersion):
                            # add the plugin to the cache
                            plugins.addFromRepository(plugin)
                self.mRepositories[reposName]["state"] = 2
            else:
                # no plugin metadata found
                self.mRepositories[reposName]["state"] = 3
                if reply.attribute(
                        QNetworkRequest.HttpStatusCodeAttribute) == 200:
                    self.mRepositories[reposName][
                        "error"] = QCoreApplication.translate(
                            "QgsPluginInstaller",
                            "Server response is 200 OK, but doesn't contain plugin metatada. This is most likely caused by a proxy or a wrong repository URL. You can configure proxy settings in QGIS options."
                        )
                else:
                    self.mRepositories[reposName][
                        "error"] = QCoreApplication.translate(
                            "QgsPluginInstaller",
                            "Status code:") + " {} {}".format(
                                reply.attribute(
                                    QNetworkRequest.HttpStatusCodeAttribute),
                                reply.attribute(
                                    QNetworkRequest.HttpReasonPhraseAttribute))

        self.repositoryFetched.emit(reposName)

        # is the checking done?
        if not self.fetchingInProgress():
            self.checkingDone.emit()

        reply.deleteLater()
Exemplo n.º 14
0
class FileDownloader():

    """The blueprint for downloading file from url."""

    def __init__(self, url, output_path, progress_dialog=None):
        """Constructor of the class.

        .. versionchanged:: 3.3 removed manager parameter.

        :param url: URL of file.
        :type url: str

        :param output_path: Output path.
        :type output_path: str

        :param progress_dialog: Progress dialog widget.
        :type progress_dialog: QWidget
        """
        # noinspection PyArgumentList
        self.manager = QgsNetworkAccessManager.instance()
        self.url = QUrl(url)
        self.output_path = output_path
        self.progress_dialog = progress_dialog
        if self.progress_dialog:
            self.prefix_text = self.progress_dialog.labelText()
        self.output_file = None
        self.reply = None
        self.downloaded_file_buffer = None
        self.finished_flag = False

    def download(self):
        """Downloading the file.

        :returns: True if success, otherwise returns a tuple with format like
            this (QNetworkReply.NetworkError, error_message)

        :raises: IOError - when cannot create output_path
        """
        # Prepare output path
        self.output_file = QFile(self.output_path)
        if not self.output_file.open(QFile.WriteOnly):
            raise IOError(self.output_file.errorString())

        # Prepare downloaded buffer
        self.downloaded_file_buffer = QByteArray()

        # Request the url
        request = QNetworkRequest(self.url)
        self.reply = self.manager.get(request)
        self.reply.readyRead.connect(self.get_buffer)
        self.reply.finished.connect(self.write_data)
        self.manager.requestTimedOut.connect(self.request_timeout)

        if self.progress_dialog:
            # progress bar
            def progress_event(received, total):
                """Update progress.

                :param received: Data received so far.
                :type received: int

                :param total: Total expected data.
                :type total: int
                """
                # noinspection PyArgumentList
                QgsApplication.processEvents()

                self.progress_dialog.adjustSize()

                human_received = humanize_file_size(received)
                human_total = humanize_file_size(total)

                label_text = tr("%s : %s of %s" % (
                    self.prefix_text, human_received, human_total))

                self.progress_dialog.setLabelText(label_text)
                self.progress_dialog.setMaximum(total)
                self.progress_dialog.setValue(received)

            # cancel
            def cancel_action():
                """Cancel download."""
                self.reply.abort()
                self.reply.deleteLater()

            self.reply.downloadProgress.connect(progress_event)
            self.progress_dialog.canceled.connect(cancel_action)

        # Wait until finished
        # On Windows 32bit AND QGIS 2.2, self.reply.isFinished() always
        # returns False even after finished slot is called. So, that's why we
        # are adding self.finished_flag (see #864)
        while not self.reply.isFinished() and not self.finished_flag:
            # noinspection PyArgumentList
            QgsApplication.processEvents()

        result = self.reply.error()
        try:
            http_code = int(self.reply.attribute(
                QNetworkRequest.HttpStatusCodeAttribute))
        except TypeError:
            # If the user cancels the request, the HTTP response will be None.
            http_code = None

        self.reply.abort()
        self.reply.deleteLater()

        if result == QNetworkReply.NoError:
            return True, None

        elif result == QNetworkReply.UnknownNetworkError:
            return False, tr(
                'The network is unreachable. Please check your internet '
                'connection.')

        elif http_code == 408:
            msg = tr(
                'Sorry, the server aborted your request. '
                'Please try a smaller area.')
            LOGGER.debug(msg)
            return False, msg

        elif http_code == 509:
            msg = tr(
                'Sorry, the server is currently busy with another request. '
                'Please try again in a few minutes.')
            LOGGER.debug(msg)
            return False, msg

        elif result == QNetworkReply.ProtocolUnknownError or \
                result == QNetworkReply.HostNotFoundError:
            # See http://doc.qt.io/qt-5/qurl-obsolete.html#encodedHost
            encoded_host = self.url.toAce(self.url.host())
            LOGGER.exception('Host not found : %s' % encoded_host)
            return False, tr(
                'Sorry, the server is unreachable. Please try again later.')

        elif result == QNetworkReply.ContentNotFoundError:
            LOGGER.exception('Path not found : %s' % self.url.path())
            return False, tr('Sorry, the layer was not found on the server.')

        else:
            return result, self.reply.errorString()

    def get_buffer(self):
        """Get buffer from self.reply and store it to our buffer container."""
        buffer_size = self.reply.size()
        data = self.reply.read(buffer_size)
        self.downloaded_file_buffer.append(data)

    def write_data(self):
        """Write data to a file."""
        self.output_file.write(self.downloaded_file_buffer)
        self.output_file.close()
        self.finished_flag = True

    def request_timeout(self):
        """The request timed out."""
        if self.progress_dialog:
            self.progress_dialog.hide()
Exemplo n.º 15
0
class FileDownloader():
    """The blueprint for downloading file from url."""
    def __init__(self, url, output_path, progress_dialog=None):
        """Constructor of the class.

        .. versionchanged:: 3.3 removed manager parameter.

        :param url: URL of file.
        :type url: str

        :param output_path: Output path.
        :type output_path: str

        :param progress_dialog: Progress dialog widget.
        :type progress_dialog: QWidget
        """
        # noinspection PyArgumentList
        self.manager = QgsNetworkAccessManager.instance()
        self.url = QUrl(url)
        self.output_path = output_path
        self.progress_dialog = progress_dialog
        if self.progress_dialog:
            self.prefix_text = self.progress_dialog.labelText()
        self.output_file = None
        self.reply = None
        self.downloaded_file_buffer = None
        self.finished_flag = False

    def download(self):
        """Downloading the file.

        :returns: True if success, otherwise returns a tuple with format like
            this (QNetworkReply.NetworkError, error_message)

        :raises: IOError - when cannot create output_path
        """
        # Prepare output path
        self.output_file = QFile(self.output_path)
        if not self.output_file.open(QFile.WriteOnly):
            raise IOError(self.output_file.errorString())

        # Prepare downloaded buffer
        self.downloaded_file_buffer = QByteArray()

        # Request the url
        request = QNetworkRequest(self.url)
        self.reply = self.manager.get(request)
        self.reply.readyRead.connect(self.get_buffer)
        self.reply.finished.connect(self.write_data)
        self.manager.requestTimedOut.connect(self.request_timeout)

        if self.progress_dialog:
            # progress bar
            def progress_event(received, total):
                """Update progress.

                :param received: Data received so far.
                :type received: int

                :param total: Total expected data.
                :type total: int
                """
                # noinspection PyArgumentList
                QgsApplication.processEvents()

                self.progress_dialog.adjustSize()

                human_received = humanize_file_size(received)
                human_total = humanize_file_size(total)

                label_text = tr(
                    "%s : %s of %s" %
                    (self.prefix_text, human_received, human_total))

                self.progress_dialog.setLabelText(label_text)
                self.progress_dialog.setMaximum(total)
                self.progress_dialog.setValue(received)

            # cancel
            def cancel_action():
                """Cancel download."""
                self.reply.abort()
                self.reply.deleteLater()

            self.reply.downloadProgress.connect(progress_event)
            self.progress_dialog.canceled.connect(cancel_action)

        # Wait until finished
        # On Windows 32bit AND QGIS 2.2, self.reply.isFinished() always
        # returns False even after finished slot is called. So, that's why we
        # are adding self.finished_flag (see #864)
        while not self.reply.isFinished() and not self.finished_flag:
            # noinspection PyArgumentList
            QgsApplication.processEvents()

        result = self.reply.error()
        try:
            http_code = int(
                self.reply.attribute(QNetworkRequest.HttpStatusCodeAttribute))
        except TypeError:
            # If the user cancels the request, the HTTP response will be None.
            http_code = None

        self.reply.abort()
        self.reply.deleteLater()

        if result == QNetworkReply.NoError:
            return True, None

        elif result == QNetworkReply.UnknownNetworkError:
            return False, tr(
                'The network is unreachable. Please check your internet '
                'connection.')

        elif http_code == 408:
            msg = tr('Sorry, the server aborted your request. '
                     'Please try a smaller area.')
            LOGGER.debug(msg)
            return False, msg

        elif http_code == 509:
            msg = tr(
                'Sorry, the server is currently busy with another request. '
                'Please try again in a few minutes.')
            LOGGER.debug(msg)
            return False, msg

        elif result == QNetworkReply.ProtocolUnknownError or \
                result == QNetworkReply.HostNotFoundError:
            # See http://doc.qt.io/qt-5/qurl-obsolete.html#encodedHost
            encoded_host = self.url.toAce(self.url.host())
            LOGGER.exception('Host not found : %s' % encoded_host)
            return False, tr(
                'Sorry, the server is unreachable. Please try again later.')

        elif result == QNetworkReply.ContentNotFoundError:
            LOGGER.exception('Path not found : %s' % self.url.path())
            return False, tr('Sorry, the layer was not found on the server.')

        else:
            return result, self.reply.errorString()

    def get_buffer(self):
        """Get buffer from self.reply and store it to our buffer container."""
        buffer_size = self.reply.size()
        data = self.reply.read(buffer_size)
        self.downloaded_file_buffer.append(data)

    def write_data(self):
        """Write data to a file."""
        self.output_file.write(self.downloaded_file_buffer)
        self.output_file.close()
        self.finished_flag = True

    def request_timeout(self):
        """The request timed out."""
        if self.progress_dialog:
            self.progress_dialog.hide()