Example #1
0
    def is_source_service_valid(self):
        res = False
        msg = {'text': '', 'level': Qgis.Warning}
        url = self.txt_service_endpoint.text().strip()
        if url:
            with OverrideCursor(Qt.WaitCursor):
                self.qgis_utils.status_bar_message_emitted.emit("Checking source service availability (this might take a while)...", 0)
                QCoreApplication.processEvents()
                if self.qgis_utils.is_connected(TEST_SERVER):

                    nam = QNetworkAccessManager()
                    request = QNetworkRequest(QUrl(url))
                    reply = nam.get(request)

                    loop = QEventLoop()
                    reply.finished.connect(loop.quit)
                    loop.exec_()

                    allData = reply.readAll()
                    response = QTextStream(allData, QIODevice.ReadOnly)
                    status = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
                    if status == 200:
                        try:
                            data = json.loads(response.readAll())
                            if 'id' in data and data['id'] == SOURCE_SERVICE_EXPECTED_ID:
                                res = True
                                msg['text'] = QCoreApplication.translate("SettingsDialog",
                                    "The tested service is valid to upload files!")
                                msg['level'] = Qgis.Info
                            else:
                                res = False
                                msg['text'] = QCoreApplication.translate("SettingsDialog",
                                    "The tested upload service is not compatible: no valid 'id' found in response.")
                        except json.decoder.JSONDecodeError as e:
                            res = False
                            msg['text'] = QCoreApplication.translate("SettingsDialog",
                                "Response from the tested service is not compatible: not valid JSON found.")
                    else:
                        res = False
                        msg['text'] = QCoreApplication.translate("SettingsDialog",
                            "There was a problem connecting to the server. The server might be down or the service cannot be reached at the given URL.")
                else:
                    res = False
                    msg['text'] = QCoreApplication.translate("SettingsDialog",
                        "There was a problem connecting to Internet.")

                self.qgis_utils.clear_status_bar_emitted.emit()
        else:
            res = False
            msg['text'] = QCoreApplication.translate("SettingsDialog", "Not valid service URL to test!")

        return (res, msg)
    def download_image(self, url):
        res = False
        img = None
        msg = {'text': '', 'level': Qgis.Warning}
        if url:
            self.log.logMessage("Downloading file from {}".format(url),
                                PLUGIN_NAME, Qgis.Info)
            with OverrideCursor(Qt.WaitCursor):
                self.qgis_utils.status_bar_message_emitted.emit(
                    "Downloading image from document repository (this might take a while)...",
                    0)
                QCoreApplication.processEvents()
                if self.qgis_utils.is_connected(TEST_SERVER):

                    nam = QNetworkAccessManager()
                    request = QNetworkRequest(QUrl(url))
                    reply = nam.get(request)

                    loop = QEventLoop()
                    reply.finished.connect(loop.quit)
                    loop.exec_()

                    status = reply.attribute(
                        QNetworkRequest.HttpStatusCodeAttribute)
                    if status == 200:
                        res = True
                        img = reply.readAll()
                    else:
                        res = False
                        msg['text'] = QCoreApplication.translate(
                            "SettingsDialog",
                            "There was a problem connecting to the server. The server might be down or the service cannot be reached at the given URL."
                        )
                else:
                    res = False
                    msg['text'] = QCoreApplication.translate(
                        "SettingsDialog",
                        "There was a problem connecting to Internet.")

                self.qgis_utils.clear_status_bar_emitted.emit()
        else:
            res = False
            msg['text'] = QCoreApplication.translate("SettingsDialog",
                                                     "Not valid URL")

        if not res:
            self.log.logMessage(msg['text'], PLUGIN_NAME, msg['level'])
        return (res, img)
def save_wms_image(filename, url, layer, extent):
    bbox = "%f,%f,%f,%f" % (extent.xMinimum(), extent.yMinimum(),
                            extent.xMaximum(), extent.yMaximum())
    h = int(extent.height() / extent.width() * WIDTH)
    url = (
        "%s/wms?request=GetMap&service=WMS&version=1.1.1&srs=EPSG:4326&layers=visualtests:%s&"
        "styles=visualtests:%s&format=image/png&width=%i&height=%i&bbox=%s" %
        (url, layer.name(), layer.name(), WIDTH, h, bbox))
    nam = QNetworkAccessManager()
    reply = nam.get(QNetworkRequest(QUrl(url)))
    loop = QEventLoop()
    reply.finished.connect(loop.quit)
    loop.exec()
    img = QImage()
    img.loadFromData(reply.readAll())
    img.save(filename)
    def download_image(self, url):
        res = False
        img = None
        msg = {'text': '', 'level': Qgis.Warning}
        if url:
            self.logger.info(__name__, "Downloading file from {}".format(url))
            msg_status_bar = "Downloading image from document repository (this might take a while)..."
            with ProcessWithStatus(msg_status_bar):
                if is_connected(TEST_SERVER):

                    nam = QNetworkAccessManager()
                    request = QNetworkRequest(QUrl(url))
                    reply = nam.get(request)

                    loop = QEventLoop()
                    reply.finished.connect(loop.quit)
                    loop.exec_()

                    status = reply.attribute(
                        QNetworkRequest.HttpStatusCodeAttribute)
                    if status == 200:
                        res = True
                        img = reply.readAll()
                    else:
                        res = False
                        msg['text'] = QCoreApplication.translate(
                            "SettingsDialog",
                            "There was a problem connecting to the server. The server might be down or the service cannot be reached at the given URL."
                        )
                else:
                    res = False
                    msg['text'] = QCoreApplication.translate(
                        "SettingsDialog",
                        "There was a problem connecting to Internet.")

        else:
            res = False
            msg['text'] = QCoreApplication.translate("SettingsDialog",
                                                     "Not valid URL")

        if not res:
            self.logger.log_message(__name__, msg['text'], msg['level'])

        return res, img
def _sync_get(url):
    global __network_manager
    if __network_manager is None:
        __network_manager = QNetworkAccessManager()
        __network_manager.setProxy(QgsNetworkAccessManager.instance().proxy())
    pause = QEventLoop()
    req = QNetworkRequest(url)
    req.setRawHeader(b"Accept", b"application/xml")
    req.setRawHeader(b"Accept-Language", bytes(settings.value("default_language", "fr"), "utf8"))
    req.setRawHeader(b"User-Agent", bytes(settings.value('http_user_agent', plugin_name()), "utf8"))
    reply = __network_manager.get(req)
    reply.finished.connect(pause.quit)
    is_ok = [True]
    def onError(self):
        is_ok[0] = False
        pause.quit()
    reply.error.connect(onError)
    pause.exec_()
    return reply, is_ok[0]
def _sync_get(url):
    global __network_manager
    if __network_manager is None:
        __network_manager = QNetworkAccessManager()
        __network_manager.setProxy(QgsNetworkAccessManager.instance().proxy())
    pause = QEventLoop()
    req = QNetworkRequest(url)
    req.setRawHeader(b"Accept", b"application/xml")
    req.setRawHeader(b"Accept-Language", b"fr")
    reply = __network_manager.get(req)
    reply.finished.connect(pause.quit)
    is_ok = [True]

    def onError(self):
        is_ok[0] = False
        pause.quit()

    reply.error.connect(onError)
    pause.exec_()
    return reply, is_ok[0]
def _sync_get(url):
    global __network_manager
    if __network_manager is None:
        __network_manager = QNetworkAccessManager()
        __network_manager.setProxy(QgsNetworkAccessManager.instance().proxy())
    pause = QEventLoop()
    req = QNetworkRequest(url)
    req.setRawHeader(b"Accept", b"application/xml")
    req.setRawHeader(b"Accept-Language",
                     bytes(settings.value("default_language", "fr"), "utf8"))
    req.setRawHeader(
        b"User-Agent",
        bytes(settings.value("http_user_agent", plugin_name()), "utf8"))
    reply = __network_manager.get(req)
    reply.finished.connect(pause.quit)
    is_ok = [True]

    def onError(self):
        is_ok[0] = False
        pause.quit()

    reply.error.connect(onError)
    pause.exec_()
    return reply, is_ok[0]
Example #8
0
class NetManager(QObject):
    def __init__(self, parent):
        super().__init__(parent)
        self.network = QNetworkAccessManager(self)

    #############
    def _pre_send_request(self,conn_info, endpoint, kw_request=dict()):
        assert(isinstance(endpoint,str))
        request = make_conn_request(conn_info, endpoint,**kw_request)
        return request

    def _post_send_request(self, reply, conn_info, kw_prop=dict()):
        set_qt_property(reply, conn_info=conn_info, **kw_prop)

    def _send_request(self,conn_info, endpoint, kw_request=dict(), kw_prop=dict()):
        
        request = self._pre_send_request(conn_info,endpoint,kw_request=kw_request)

        reply = self.network.get(request)

        self._post_send_request(reply,conn_info, kw_prop=kw_prop)
        return reply

    #############
    # TODO: remove callback params
    def get_statistics(self, conn_info):
        reply = self._get_space_(conn_info, "statistics")
        timeout = TIMEOUT_COUNT
        QTimer.singleShot(timeout, reply.abort)
        return reply
    def get_count(self, conn_info):
        reply = self._get_space_(conn_info, "count")
        return reply
    def get_meta(self, conn_info):
        return self._get_space_(conn_info, "space_meta")

    def _get_space_(self, conn_info, reply_tag):
        tag = "/" + reply_tag if reply_tag != "space_meta" else ""
        
        endpoint = "/spaces/{space_id}" + tag
        kw_request = dict()
        kw_prop = dict(reply_tag=reply_tag)
        return self._send_request(conn_info, endpoint, kw_request=kw_request, kw_prop=kw_prop)
        
    def list_spaces(self, conn_info):
        endpoint = "/spaces"
        kw_request = dict(includeRights="true")
        kw_prop = dict(reply_tag="spaces")
        return self._send_request(conn_info, endpoint, kw_request=kw_request, kw_prop=kw_prop)
        
    def add_space(self, conn_info, space_info):
        space_info = prepare_new_space_info(space_info)
        
        endpoint = "/spaces"
        kw_request = dict(req_type="json")
        kw_prop = dict(reply_tag="add_space")

        request = self._pre_send_request(conn_info,endpoint,kw_request=kw_request)
        reply = self.network.post(request, make_payload(space_info))

        self._post_send_request(reply,conn_info, kw_prop=kw_prop)
        return reply
    def edit_space(self, conn_info, space_info):
                
        endpoint = "/spaces/{space_id}"
        kw_request = dict(req_type="json")
        kw_prop = dict(reply_tag="edit_space")

        request = self._pre_send_request(conn_info,endpoint,kw_request=kw_request)
        buffer = make_buffer(space_info)
        reply = self.network.sendCustomRequest(request, b"PATCH", buffer)
        buffer.setParent(reply)
        
        self._post_send_request(reply,conn_info, kw_prop=kw_prop)
        return reply
        
    def del_space(self, conn_info):
        
        endpoint = "/spaces/{space_id}"
        kw_request = dict()
        kw_prop = dict(reply_tag="del_space")

        request = self._pre_send_request(conn_info,endpoint,kw_request=kw_request)
        reply = self.network.sendCustomRequest(request, b"DELETE")

        self._post_send_request(reply,conn_info, kw_prop=kw_prop)
        
        return reply
        
    def load_features_bbox(self, conn_info, bbox, **kw):

        endpoint = "/spaces/{space_id}/bbox"
        kw_request = dict(bbox)
        kw_request.update(kw)
        kw_prop = dict(reply_tag="bbox")
        kw_prop.update(kw)
        kw_prop["bbox"] = bbox
        
        return self._send_request(conn_info, endpoint, kw_request=kw_request, kw_prop=kw_prop)

    def load_features_tile(self, conn_info, tile_id="0", tile_schema="quadkey", **kw):
        reply_tag = "tile"
        tile_url = "tile/{tile_schema}/{tile_id}".format(
            tile_schema=tile_schema, tile_id=tile_id)
        endpoint = "/spaces/{space_id}/" + tile_url
        return self._load_features_endpoint(endpoint, conn_info, reply_tag=reply_tag, **kw)

    def load_features_iterate(self, conn_info, **kw_iterate):
        reply_tag = kw_iterate.pop("reply_tag","iterate")
        endpoint = "/spaces/{space_id}/iterate"
        return self._load_features_endpoint(endpoint, conn_info, reply_tag=reply_tag, **kw_iterate)

    def load_features_search(self, conn_info, **kw_iterate):
        reply_tag = kw_iterate.pop("reply_tag","search")
        endpoint = "/spaces/{space_id}/search"
        return self._load_features_endpoint(endpoint, conn_info, reply_tag=reply_tag, **kw_iterate)
        
    def _load_features_endpoint(self, endpoint, conn_info, reply_tag=None, **kw_iterate):
        """ Iterate through all ordered features (no feature is repeated twice)
        """
        kw_request = dict(kw_iterate)
        kw_prop = dict(reply_tag=reply_tag)
        kw_prop.update(kw_iterate)
        
        return self._send_request(conn_info, endpoint, kw_request=kw_request, kw_prop=kw_prop)

    ###### feature function
    def add_features(self, conn_info, added_feat, **kw):
        send_request = self.network.post # create or modify (merge existing feature with payload) # might add attributes
        return self._add_features(conn_info, added_feat, send_request, **kw)
    def modify_features(self, conn_info, added_feat, **kw):
        return self.add_features(conn_info, added_feat, **kw)
    def replace_features(self, conn_info, added_feat, **kw):
        send_request = self.network.put # create or replace (replace existing feature with payload) # might add or drop attributes
        return self._add_features(conn_info, added_feat, send_request, **kw)
    def _add_features(self, conn_info, added_feat, send_request, **kw):
        # POST, payload: list of FeatureCollection
        
        endpoint = "/spaces/{space_id}/features"
        if "tags" in kw: kw["addTags"] = kw["tags"]
        kw_request = dict(req_type="geo", **kw) # kw: query
        kw_prop = dict(reply_tag="add_feat")
        kw_prop.update(kw)
        request = self._pre_send_request(conn_info,endpoint,kw_request=kw_request)
        
        payload = make_payload(added_feat)
        reply = send_request(request, payload)
        self._post_send_request(reply, conn_info, kw_prop=kw_prop)

        #parallel case (merge output ? split input?)
        return reply
    def del_features(self, conn_info, removed_feat, **kw):
        # DELETE by Query URL, required list of feat_id

        query_del = {"id": ",".join(str(i) for i in removed_feat)}
        kw.update(query_del)

        endpoint = "/spaces/{space_id}/features"
        kw_request = dict(kw) # kw: query
        kw_prop = dict(reply_tag="del_feat")

        request = self._pre_send_request(conn_info,endpoint,kw_request=kw_request)
    
        reply = self.network.sendCustomRequest(request, b"DELETE")
        self._post_send_request(reply, conn_info, kw_prop=kw_prop)

        return reply
class BBOXDialog(QDialog, FORM_CLASS):
    def __init__(self, inp_sparql, triplestoreconf, endpointIndex):
        super(QDialog, self).__init__()
        self.setupUi(self)
        self.inp_sparql = inp_sparql
        self.triplestoreconf = triplestoreconf
        self.endpointIndex = endpointIndex
        self.vl = QgsVectorLayer("Point", "temporary_points", "memory")
        self.map_canvas = QgsMapCanvas(self)
        self.layerExtentOrBBOX = False
        self.map_canvas.setMinimumSize(500, 475)
        self.map_canvas.move(0, 30)
        self.nominatimmap = {}
        actionPan = QAction("Pan", self)
        actionPan.setCheckable(True)
        actionPan.triggered.connect(self.pan)
        self.toolPan = QgsMapToolPan(self.map_canvas)
        self.toolPan.setAction(actionPan)
        uri = "url=http://a.tile.openstreetmap.org/{z}/{x}/{y}.png&zmin=0&type=xyz"
        self.mts_layer = QgsRasterLayer(uri, 'OSM', 'wms')
        if not self.mts_layer.isValid():
            print("Layer failed to load!")
        self.rect_tool = RectangleMapTool(self.map_canvas)
        self.circ_tool = CircleMapTool(self.map_canvas, 1)
        self.poly_tool = PolygonMapTool(self.map_canvas)
        self.map_canvas.setMapTool(self.rect_tool)
        self.map_canvas.setExtent(self.mts_layer.extent())
        self.map_canvas.setLayers([self.vl, self.mts_layer])
        self.map_canvas.setCurrentLayer(self.mts_layer)
        self.pan()
        self.selectCircle.hide()
        self.geocodeSearch = NominatimText(self, self.nominatimmap,
                                           self.map_canvas)
        self.move(120, 0)
        self.crsdialog = QgsProjectionSelectionWidget(self)
        self.crsdialog.move(160, 540)
        self.crsdialog.resize(331, 30)
        self.crsdialog.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
        self.crsdialog.show()
        self.nominatimurl = 'https://nominatim.openstreetmap.org/search?format=json&q={address}'
        self.panButton.clicked.connect(self.pan)
        self.selectCircle.clicked.connect(self.selectcircle)
        self.selectPolygon.clicked.connect(self.selectpolygon)
        self.selectButton.clicked.connect(self.selectarea)
        self.zoomIn.clicked.connect(self.map_canvas.zoomIn)
        self.zoomOut.clicked.connect(self.map_canvas.zoomOut)
        self.b2.clicked.connect(self.setBBOXExtentQuery)
        self.searchButton.hide()
        self.searchPlace.hide()
        self.geocodeSearch.hide()
        layers = QgsProject.instance().layerTreeRoot().children()
        for layer in layers:
            self.chooseBBOXLayer.addItem(layer.name())
        self.searchButton.clicked.connect(self.geocode)
        self.b1.clicked.connect(self.setBBOXInQuery)

    def geocode(self):
        try:
            nominatimurl = self.nominatimurl.format(
                **{'address': self.geocodeSearch.text()})
            self.networkrequest(nominatimurl)
        except Exception as e:
            msgBox = QMessageBox()
            msgBox.setWindowTitle("Mandatory variables missing!")
            msgBox.setText(str(e))
            msgBox.exec()

    def networkrequest(self, nurl):
        global reply
        self.manager = QNetworkAccessManager()
        url = QUrl(nurl)
        request = QNetworkRequest(url)
        self.manager.finished.connect(self.handleResponse)
        self.manager.get(request)

    def handleResponse(self, reply):
        er = reply.error()
        if er == QNetworkReply.NoError:
            bytes_string = reply.readAll()
            print(str(bytes_string, 'utf-8'))
            results = json.loads(str(bytes_string, 'utf-8'))
            self.nominatimmap = {}
            chooselist = []
            for rec in results:
                chooselist.append(rec['display_name'])
                self.nominatimmap[rec['display_name']] = [
                    rec['lon'], rec['lat']
                ]
            completer = SPARQLCompleter(chooselist)
            self.geocodeSearch.setMap(self.nominatimmap)
            self.geocodeSearch.setCompleter(completer)
            #self.geocodeSearch.insertCompletion.connect(self.zoomToCoordinates)
            completer.popup().show()
        else:
            print("Error occured: ", er)

    def zoomToCoordinates(self, completion):
        msgBox = QMessageBox()
        msgBox.setText(completion)
        msgBox.exec()
        self.map_canvas.zoomWithCenter(self.nominatimmap[completion][0],
                                       self.nominatimmap[completion][1], True)

    def pan(self):
        self.map_canvas.setMapTool(self.toolPan)

    def selectarea(self):
        self.rectangle = True
        self.circle = False
        self.polygon = False
        self.map_canvas.setMapTool(self.rect_tool)

    def selectcircle(self):
        self.rectangle = False
        self.circle = True
        self.polygon = False
        self.map_canvas.setMapTool(self.circ_tool)

    def selectpolygon(self):
        self.rectangle = False
        self.circle = False
        self.polygon = True
        self.map_canvas.setMapTool(self.poly_tool)

    def setBBOXExtentQuery(self):
        if len(QgsProject.instance().layerTreeRoot().children()) > 0:
            self.mts_layer = QgsProject.instance().layerTreeRoot().children()[
                self.chooseBBOXLayer.currentIndex()].layer()
            self.layerExtentOrBBOX = True
            self.setBBOXInQuery()
            self.close()
        else:
            msgBox = QMessageBox()
            msgBox.setWindowTitle("No layer loaded in QGIS!")
            msgBox.setText(
                "No layer has been loaded in QGIS to get an extent from!")
            msgBox.exec()

    def setBBOXInQuery(self):
        sourceCrs = None
        if self.layerExtentOrBBOX:
            xMax = self.mts_layer.extent().xMaximum()
            xMin = self.mts_layer.extent().xMinimum()
            yMin = self.mts_layer.extent().yMinimum()
            yMax = self.mts_layer.extent().yMaximum()
            pointt1 = QgsGeometry.fromPointXY(QgsPointXY(xMax, yMin))
            pointt2 = QgsGeometry.fromPointXY(QgsPointXY(xMin, yMin))
            pointt3 = QgsGeometry.fromPointXY(QgsPointXY(xMin, yMax))
            pointt4 = QgsGeometry.fromPointXY(QgsPointXY(xMax, yMax))
            sourceCrs = QgsCoordinateReferenceSystem(self.mts_layer.crs())
        else:
            sourceCrs = QgsCoordinateReferenceSystem(self.mts_layer.crs())
            destCrs = self.crsdialog.crs()
            if self.polygon:
                polygon = self.poly_tool.rb.asGeometry()
                tr = QgsCoordinateTransform(sourceCrs, destCrs,
                                            QgsProject.instance())
                polygon.transform(tr)
            elif self.circle:
                pointt1 = QgsGeometry.fromWkt(self.circ_tool.point1.asWkt())
                pointt2 = QgsGeometry.fromWkt(self.circ_tool.point2.asWkt())
                pointt3 = QgsGeometry.fromWkt(self.circ_tool.point3.asWkt())
                pointt4 = QgsGeometry.fromWkt(self.circ_tool.point4.asWkt())
            else:
                pointt1 = QgsGeometry.fromWkt(self.rect_tool.point1.asWkt())
                pointt2 = QgsGeometry.fromWkt(self.rect_tool.point2.asWkt())
                pointt3 = QgsGeometry.fromWkt(self.rect_tool.point3.asWkt())
                pointt4 = QgsGeometry.fromWkt(self.rect_tool.point4.asWkt())
                if sourceCrs != None:
                    tr = QgsCoordinateTransform(sourceCrs, destCrs,
                                                QgsProject.instance())
                    pointt1.transform(tr)
                    pointt2.transform(tr)
                    pointt3.transform(tr)
                    pointt4.transform(tr)
                polygon = QgsGeometry.fromPolylineXY([
                    pointt1.asPoint(),
                    pointt2.asPoint(),
                    pointt3.asPoint(),
                    pointt4.asPoint()
                ])
        center = polygon.centroid()
        #distance = QgsDistanceArea()
        #distance.setSourceCrs(destCrs)
        #distance.setEllipsoidalMode(True)
        #distance.setEllipsoid('WGS84')
        curquery = self.inp_sparql.toPlainText()
        if self.rectangle or self.circle:
            widthm = 100  #distance.measureLine(pointt1, pointt2)
            self.curbbox = []
            self.curbbox.append(pointt1)
            self.curbbox.append(pointt2)
            self.curbbox.append(pointt3)
            self.curbbox.append(pointt4)
            self.close()
            if "bboxquery" in self.triplestoreconf[
                    self.endpointIndex] and self.triplestoreconf[
                        self.
                        endpointIndex]["bboxquery"]["type"] == "geosparql":
                curquery = curquery[
                    0:curquery.rfind('}')] + self.triplestoreconf[
                        self.endpointIndex]["bboxquery"]["query"].replace(
                            "%%x1%%", str(pointt1.asPoint().x())).replace(
                                "%%x2%%", str(pointt3.asPoint().x())).replace(
                                    "%%y1%%",
                                    str(pointt1.asPoint().y())).replace(
                                        "%%y2%%", str(pointt3.asPoint().y())
                                    ) + "}\n" + curquery[curquery.rfind('}') +
                                                         1:]
            elif "bboxquery" in self.triplestoreconf[
                    self.endpointIndex] and self.triplestoreconf[
                        self.endpointIndex]["bboxquery"]["type"] == "minmax":
                curquery = curquery[
                    0:curquery.rfind('}')] + self.triplestoreconf[
                        self.endpointIndex]["bboxquery"]["query"].replace(
                            "%%minPoint%%", pointt2.asWkt()).replace(
                                "%%maxPoint%%", pointt4.asWkt()
                            ) + curquery[curquery.rfind('}') + 1:]
            elif "bboxquery" in self.triplestoreconf[
                    self.endpointIndex] and self.triplestoreconf[
                        self.
                        endpointIndex]["bboxquery"]["type"] == "pointdistance":
                curquery = curquery[
                    0:curquery.rfind('}')] + self.triplestoreconf[
                        self.endpointIndex]["bboxquery"]["query"].replace(
                            "%%lat%%", str(center.asPoint().y())).replace(
                                "%%lon%%", str(center.asPoint().x())).replace(
                                    "%%distance%%", str(widthm / 1000)
                                ) + curquery[curquery.rfind('}') + 1:]
        elif polygon:
            widthm = 100
            if "bboxquery" in self.triplestoreconf[
                    self.endpointIndex] and self.triplestoreconf[
                        self.
                        endpointIndex]["bboxquery"]["type"] == "geosparql":
                curquery = curquery[0:curquery.rfind(
                    '}')] + "FILTER(geof:sfIntersects(?geo,\"" + polygon.asWkt(
                    ) + "\"^^geo:wktLiteral))"
            elif "bboxquery" in self.triplestoreconf[
                    self.endpointIndex] and self.triplestoreconf[
                        self.endpointIndex]["bboxquery"]["type"] == "minmax":
                curquery = curquery[
                    0:curquery.rfind('}')] + self.triplestoreconf[
                        self.endpointIndex]["bboxquery"]["query"].replace(
                            "%%minPoint%%",
                            "POINT(" + str(polygon.boundingBox().yMinimum()) +
                            " " + str(polygon.boundingBox().xMinimum()) +
                            ")").replace(
                                "%%maxPoint%%", "POINT(" +
                                str(polygon.boundingBox().yMaximum()) + " " +
                                str(polygon.boundingBox().xMaximum()) +
                                ")") + curquery[curquery.rfind('}') + 1:]
            elif "bboxquery" in self.triplestoreconf[
                    self.endpointIndex] and self.triplestoreconf[
                        self.
                        endpointIndex]["bboxquery"]["type"] == "pointdistance":
                curquery = curquery[
                    0:curquery.rfind('}')] + self.triplestoreconf[
                        self.endpointIndex]["bboxquery"]["query"].replace(
                            "%%lat%%",
                            str(polygon.boundingBox().center().asPoint().y(
                            ))).replace(
                                "%%lon%%",
                                str(polygon.boundingBox().center().asPoint().x(
                                ))).replace("%%distance%%", str(
                                    widthm /
                                    1000)) + curquery[curquery.rfind('}') + 1:]
        self.inp_sparql.setPlainText(curquery)
        self.close()
Example #10
0
class Download:
    def __init__(self, parent=None, iface=None):
        self.parent = parent
        self.iface = iface
        self.login_accepted = False
        self.akt_download = 0
        self.all_download = 0
        self.request_is_aborted = False
        self.nam = QNetworkAccessManager()
        self.nam.authenticationRequired.connect(self.set_credentials)
        self.nam.finished.connect(self.reply_finished)

    def layer_exists(self, name):

        if len(QgsProject.instance().mapLayersByName(name)) != 0:
            return True
        else:
            return False

    def get_image(self, url, filename, lat_tx, lon_tx, load_to_canvas=True):
        layer_name = "%s%s.hgt" % (lat_tx, lon_tx)

        if not self.layer_exists(layer_name):
            self.filename = filename
            self.load_to_canvas = True
            download_url = QUrl(url)
            req = QNetworkRequest(download_url)
            self.nam.get(req)

    def set_credentials(self, reply, authenticator):
        if not self.request_is_aborted:
            self.get_settings()
            self.login = Login(self.username, self.password)

            if self.login.exec_():
                self.authenticator = authenticator
                self.authenticator.setUser(self.login.username)
                self.authenticator.setPassword(self.login.password)
                if self.login.chk_save_credentials.isChecked():
                    self.set_settings()
        else:
            reply.abort()
            self.request_is_aborted = True
            self.parent.download_finished(show_message=False, abort=True)

    def reply_finished(self, reply):

        if reply != None:
            possibleRedirectUrl = reply.attribute(
                QNetworkRequest.RedirectionTargetAttribute)

            # If the URL is not empty, we're being redirected.
            if possibleRedirectUrl != None:
                request = QNetworkRequest(possibleRedirectUrl)
                result = self.nam.get(request)
                self.parent.init_progress()
                self.parent.add_download_progress(reply)
                result.downloadProgress.connect(
                    lambda done, all, reply=result: self.progress(
                        done, all, reply))
            else:
                if reply.error() != None:
                    if reply.error() == QNetworkReply.ContentNotFoundError:
                        self.parent.set_progress()
                        reply.abort()
                        reply.deleteLater()

                    elif reply.error() == QNetworkReply.NoError:
                        result = reply.readAll()
                        f = open(self.filename, 'wb')
                        f.write(result)
                        f.close()

                        out_image = self.unzip(self.filename)
                        (dir, file) = os.path.split(out_image)
                        if not self.layer_exists(file):
                            self.iface.addRasterLayer(out_image, file)

                        self.parent.set_progress()

                        # Clean up. */
                        reply.deleteLater()

    def progress(self, akt, max, reply):
        is_image = QFileInfo(
            reply.url().path()).completeSuffix() == 'SRTMGL1.hgt.zip'

        if is_image:
            current_row = self.parent.progress_widget_item_list[QFileInfo(
                reply.url().path()).baseName()]
            progress_widget = self.parent.tableWidget.cellWidget(
                current_row, 1)
            progress_widget.setValue(akt)
            progress_widget.setMaximum(max)

            if reply.isFinished():
                self.drop_row(current_row)

    def drop_row(self, i):
        self.parent.tableWidget.removeRow(i)

        for key, value in self.parent.progress_widget_item_list.items():
            if value == i:
                self.parent.progress_widget_item_list.pop(key)
                break

        for key, value in self.parent.progress_widget_item_list.items():
            if value > i:
                self.parent.progress_widget_item_list[key] = value - 1

    def unzip(self, zip_file):
        import zipfile
        (dir, file) = os.path.split(zip_file)

        if not dir.endswith(':') and not os.path.exists(dir):
            os.mkdir(dir)

        try:
            zf = zipfile.ZipFile(zip_file)

            # extract files to directory structure
            for i, name in enumerate(zf.namelist()):
                if not name.endswith('/'):
                    outfile = open(os.path.join(dir, name), 'wb')
                    outfile.write(zf.read(name))
                    outfile.flush()
                    outfile.close()
                    return os.path.join(dir, name)
        except:
            return None

    def _makedirs(self, directories, basedir):
        """ Create any directories that don't currently exist """
        for dir in directories:
            curdir = os.path.join(basedir, dir)
            if not os.path.exists(curdir):
                os.mkdir(curdir)

    def _listdirs(self, file):
        """ Grabs all the directories in the zip structure
        This is necessary to create the structure before trying
        to extract the file to it. """
        zf = zipfile.ZipFile(file)

        dirs = []

        for name in zf.namelist():
            if name.endswith('/'):
                dirs.append(name)

        dirs.sort()
        return dirs

    def set_settings(self):
        settings = QSettings()
        mySettingsPath = "/SRTM-Downloader"
        settings.setValue(mySettingsPath + "/username", self.login.username)
        settings.setValue(mySettingsPath + "/password", self.login.password)

    def get_settings(self):
        settings = QSettings()
        mySettingsPath = "/SRTM-Downloader"
        self.username = settings.value(mySettingsPath + "/username")
        self.password = settings.value(mySettingsPath + "/password")
Example #11
0
class KfConfig(QtCore.QObject):

    kf_con_error = QtCore.pyqtSignal()
    kf_settings_warning = QtCore.pyqtSignal()
    loaded = QtCore.pyqtSignal()

    def __init__(self, settings):
        super(KfConfig, self).__init__()
        self.settings = settings
        self.cached_kf_qlr_filename = None
        self.allowed_kf_services = {}
        self.kf_qlr_file = None
        self.background_category = None
        self.categories = None

        # Network
        self._services_network_manager = QNetworkAccessManager()
        self._qlr_network_manager = QNetworkAccessManager()
        self._services_network_manager.finished.connect(
            self._handle_services_response)
        self._qlr_network_manager.finished.connect(self._handle_qlr_response)

    def begin_load(self):
        self.cached_kf_qlr_filename = (
            self.settings.value("cache_path") +
            hashlib.md5(self.settings.value("token").encode()).hexdigest() +
            "_kortforsyning_data.qlr")
        self.allowed_kf_services = {}
        if self.settings.is_set():
            try:
                self._request_services()
            except Exception as e:
                log_message(traceback.format_exc())
                self.kf_con_error.emit()
                self.background_category = None
                self.categories = []
            self.debug_write_allowed_services()
        else:
            self.kf_settings_warning.emit()
            self.background_category = None
            self.categories = []

    def _request_services(self):
        url_to_get = self.insert_token(KF_SERVICES_URL)
        self._services_network_manager.get(QNetworkRequest(QUrl(url_to_get)))

    def _handle_services_response(self, network_reply):
        if network_reply.error():
            self.background_category = None
            self.categories = []
            self.kf_con_error.emit()
            log_message(
                f"Network error getting services from kf. Error code : " +
                str(network_reply.error()))
            return
        response = str(network_reply.readAll(), "utf-8")
        doc = QtXml.QDomDocument()
        doc.setContent(response)
        service_types = doc.documentElement().childNodes()
        i = 0
        allowed = {}
        allowed["any_type"] = {"services": []}
        while i < service_types.count():
            service_type = service_types.at(i)
            service_type_name = service_type.nodeName()
            allowed[service_type_name] = {"services": []}
            services = service_type.childNodes()
            j = 0
            while j < services.count():
                service = services.at(j)
                service_name = service.nodeName()
                allowed[service_type_name]["services"].append(service_name)
                allowed["any_type"]["services"].append(service_name)
                j = j + 1
            i = i + 1
        self.allowed_kf_services = allowed
        if not allowed["any_type"]["services"]:
            self.kf_con_error.emit()
            log_message(
                f"Kortforsyningen returned an empty list of allowed services for token: {self.settings.value('token')}"
            )
        # Go on and get QLR
        self._get_qlr_file()

    def _get_qlr_file(self):
        local_file_exists = os.path.exists(self.cached_kf_qlr_filename)
        if local_file_exists:
            local_file_time = datetime.datetime.fromtimestamp(
                os.path.getmtime(self.cached_kf_qlr_filename))
            use_cached = local_file_time > datetime.datetime.now(
            ) - FILE_MAX_AGE
            if use_cached:
                # Skip requesting remote qlr
                self._load_config_from_cached_kf_qlr()
                return
        # Get qlr from KF
        self._request_kf_qlr_file()

    def _request_kf_qlr_file(self):
        url_to_get = self.settings.value("kf_qlr_url")
        self._qlr_network_manager.get(QNetworkRequest(QUrl(url_to_get)))

    def _handle_qlr_response(self, network_reply):
        if network_reply.error():
            log_message("No contact to the configuration at " +
                        self.settings.value("kf_qlr_url") + ". Error code : " +
                        str(network_reply.error()))
        else:
            response = str(network_reply.readAll(), "utf-8")
            response = self.insert_token(response)
            self.write_cached_kf_qlr(response)
        # Now load and use it
        self._load_config_from_cached_kf_qlr()

    def _load_config_from_cached_kf_qlr(self):
        self.kf_qlr_file = QlrFile(self._read_cached_kf_qlr())
        self.background_category, self.categories = self.get_kf_categories()
        self.loaded.emit()

    def get_categories(self):
        return self.categories

    def get_background_category(self):
        return self.background_category

    def get_maplayer_node(self, id):
        return self.kf_qlr_file.get_maplayer_node(id)

    def get_kf_categories(self):
        kf_categories = []
        kf_background_category = None
        groups_with_layers = self.kf_qlr_file.get_groups_with_layers()
        for group in groups_with_layers:
            kf_category = {"name": group["name"], "selectables": []}
            for layer in group["layers"]:
                if self.user_has_access(layer["service"]):
                    kf_category["selectables"].append({
                        "type": "layer",
                        "source": "kf",
                        "name": layer["name"],
                        "id": layer["id"],
                    })
            if len(kf_category["selectables"]) > 0:
                kf_categories.append(kf_category)
                if group["name"] == "Baggrundskort":
                    kf_background_category = kf_category
        return kf_background_category, kf_categories

    def user_has_access(self, service_name):
        return service_name in self.allowed_kf_services["any_type"]["services"]

    def get_custom_categories(self):
        return []

    def _read_cached_kf_qlr(self):
        # return file(unicode(self.cached_kf_qlr_filename)).read()
        f = QFile(self.cached_kf_qlr_filename)
        f.open(QIODevice.ReadOnly)
        return f.readAll()

    def write_cached_kf_qlr(self, contents):
        """We only call this function IF we have a new version downloaded"""
        # Remove old versions file
        for filename in glob.glob(
                self.settings.value("cache_path") +
                "*_kortforsyning_data.qlr"):
            os.remove(filename)

        # Write new version
        with codecs.open(self.cached_kf_qlr_filename, "w", "utf-8") as f:
            f.write(contents)

    def debug_write_allowed_services(self):
        try:
            debug_filename = (self.settings.value("cache_path") +
                              self.settings.value("username") + ".txt")
            if os.path.exists(debug_filename):
                os.remove(debug_filename)
            with codecs.open(debug_filename, "w", "utf-8") as f:
                f.write(
                    json.dumps(
                        self.allowed_kf_services["any_type"]["services"],
                        indent=2).replace("[", "").replace("]", ""))
        except Exception:
            pass

    def insert_token(self, text):
        result = text
        replace_vars = {}
        replace_vars["kf_token"] = self.settings.value("token")
        for i, j in replace_vars.items():
            result = result.replace("{{" + str(i) + "}}", str(j))
        return result
Example #12
0
class AutoSuggest(QObject):
    def __init__(self, geturl_func, parseresult_func, parent=None):
        QObject.__init__(self, parent)
        self.geturl_func = geturl_func
        self.parseresult_func = parseresult_func

        self.editor = parent
        self.networkManager = QNetworkAccessManager()

        self.selectedObject = None
        self.isUnloaded = False

        self.popup = QTreeWidget(parent)
        #self.popup.setColumnCount(2)
        self.popup.setColumnCount(1)
        self.popup.setUniformRowHeights(True)
        self.popup.setRootIsDecorated(False)
        self.popup.setEditTriggers(QTreeWidget.NoEditTriggers)
        self.popup.setSelectionBehavior(QTreeWidget.SelectRows)
        self.popup.setFrameStyle(QFrame.Box | QFrame.Plain)
        self.popup.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.popup.header().hide()
        self.popup.installEventFilter(self)
        self.popup.setMouseTracking(True)

        #self.connect(self.popup, SIGNAL("itemClicked(QTreeWidgetItem*, int)"),
        #             self.doneCompletion)
        self.popup.itemClicked.connect(self.doneCompletion)

        self.popup.setWindowFlags(Qt.Popup)
        self.popup.setFocusPolicy(Qt.NoFocus)
        self.popup.setFocusProxy(parent)

        self.timer = QTimer(self)
        self.timer.setSingleShot(True)
        self.timer.setInterval(500)
        #self.connect(self.timer, SIGNAL("timeout()"), self.autoSuggest)
        self.timer.timeout.connect(self.autoSuggest)

        #self.connect(self.editor, SIGNAL("textEdited(QString)"), self.timer, SLOT("start()"))
        #self.editor.textEdited.connect( self.timer.start )
        self.editor.textEdited.connect(self.timer.start)
        #self.editor.textChanged.connect( self.timer.start )

        #self.connect(self.networkManager, SIGNAL("finished(QNetworkReply*)"),
        #             self.handleNetworkData)
        self.networkManager.finished.connect(self.handleNetworkData)

    def eventFilter(self, obj, ev):
        if obj != self.popup:
            return False

        if ev.type() == QEvent.MouseButtonPress:
            self.popup.hide()
            self.editor.setFocus()
            return True

        if ev.type() == QEvent.KeyPress:
            consumed = False
            key = ev.key()
            if key == Qt.Key_Enter or key == Qt.Key_Return:
                self.doneCompletion()
                consumed = True

            elif key == Qt.Key_Escape:
                self.editor.setFocus()
                self.popup.hide()
                consumed = True

            elif key in (Qt.Key_Up, Qt.Key_Down, Qt.Key_Home, Qt.Key_End,
                         Qt.Key_PageUp, Qt.Key_PageDown):
                pass

            else:
                self.editor.setFocus()
                self.editor.event(ev)
                self.popup.hide()

            return consumed

        return False

    def showCompletion(self, rows):
        # Rows is an iterable of tuples like [("text",object1),("text2", object2),...]
        pal = self.editor.palette()
        color = pal.color(QPalette.Disabled, QPalette.WindowText)

        self.popup.setUpdatesEnabled(False)
        self.popup.clear()
        if rows is None or len(rows) < 1:
            return

        for row in rows:
            item = QTreeWidgetItem(self.popup)
            item.setText(0, row[0])
            #item.setText(1, hit['type'])
            item.setTextAlignment(1, Qt.AlignRight)
            item.setForeground(1, color)
            item.setData(
                2, Qt.UserRole, (row[1], )
            )  # Try immutable py obj #http://stackoverflow.com/questions/9257422/how-to-get-the-original-python-data-from-qvariant

        self.popup.setCurrentItem(self.popup.topLevelItem(0))
        self.popup.resizeColumnToContents(0)
        #self.popup.resizeColumnToContents(1)
        self.popup.adjustSize()
        self.popup.setUpdatesEnabled(True)

        h = self.popup.sizeHintForRow(0) * min(15, len(rows)) + 3
        w = max(self.popup.width(), self.editor.width())
        self.popup.resize(w, h)

        self.popup.move(
            self.editor.mapToGlobal(QPoint(0, self.editor.height())))
        self.popup.setFocus()
        self.popup.show()

    def doneCompletion(self):
        self.timer.stop()
        self.popup.hide()
        self.editor.setFocus()
        item = self.popup.currentItem()
        if item:
            self.editor.setText(item.text(0))
            obj = item.data(2, Qt.UserRole)  #.toPyObject()
            self.selectedObject = obj[0]
            e = QKeyEvent(QEvent.KeyPress, Qt.Key_Enter, Qt.NoModifier)
            QApplication.postEvent(self.editor, e)
            e = QKeyEvent(QEvent.KeyRelease, Qt.Key_Enter, Qt.NoModifier)
            QApplication.postEvent(self.editor, e)

    def preventSuggest(self):
        self.timer.stop()

    def autoSuggest(self):
        term = self.editor.text()
        if term:
            qurl = self.geturl_func(term)
            if qurl:
                # TODO: Cancel existing requests: http://qt-project.org/forums/viewthread/18073
                self.networkManager.get(QNetworkRequest(qurl))  #QUrl(url)))

    def handleNetworkData(self, networkReply):
        url = networkReply.url()
        #print "received url:", url.toString()
        if not networkReply.error():
            response = networkReply.readAll()
            pystring = str(response, 'utf-8')
            #print "Response: ", response
            rows = self.parseresult_func(pystring)
            self.showCompletion(rows)

        networkReply.deleteLater()

    def unload(self):
        # Avoid processing events after QGIS shutdown has begun
        self.popup.removeEventFilter(self)
        self.isUnloaded = True
class KeyWordsSelection:
    def __init__(self, auth_file):

        logger.debug("\n================== ISOGEO API WITH QT ==================")

        # getting credentials :
        logger.debug("Getting credentials")
        self.utils = IsogeoUtils()
        self.app_creds = self.utils.credentials_loader(auth_file)
        self.app_id = self.app_creds.get("client_id")
        self.app_secrets = self.app_creds.get("client_secret")

        # for connection :
        self.naMngr = QNetworkAccessManager()
        self.token_url = "https://id.api.isogeo.com/oauth/token"
        self.request_url = (
            "https://v1.api.isogeo.com/resources/search?_limit=0&_offset=0"
        )

        # init variables :
        self.token = ""
        self.search_type = "init"
        self.checked_kw = {}

        # for ui (launch and display):
        logger.debug("Processing and displaying UI")
        self.app = QApplication(sys.argv)
        self.ui = AuthWidget()
        self.ui.resize(400, 100)
        self.pysdk_checking()
        self.api_authentification()
        self.ui.btn_reset.pressed.connect(self.reset)
        self.ui.show()
        self.app.exec()

    def pysdk_checking(self):
        logger.debug("\n--------------- isogeo-pysdk ---------------")
        logger.debug("Checking credentials")
        try:
            isogeo = Isogeo(self.app_id, self.app_secrets)
            isogeo.connect()
        except OSError as e:
            logger.debug("Credentials issue : {}".format(e))
            return
        except ValueError as e:
            logger.debug("Credentials issue : {}".format(e))
            return

        if self.search_type == "init":
            result = isogeo.search(
                whole_share=0, page_size=0, augment=0, tags_as_dicts=1
            )
        else:
            query = " ".join(list(self.checked_kw.keys()))
            result = isogeo.search(
                whole_share=0, page_size=0, augment=0, tags_as_dicts=1, query=query
            )

        self.tags_expected = result.get("tags")
        self.kw_expected_nb = len(self.tags_expected.get("keywords"))
        self.ui.lbl_expected.setText(
            "Expected : {} resources and {} keywords".format(
                result.get("total"), self.kw_expected_nb
            )
        )
        logger.debug(
            "isogeo-pysdk validates the authentication file, {} accessible resources".format(
                result.get("total")
            )
        )

    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))

    def api_handle_token(self, reply):
        logger.debug("Token asked and API reply received")

        # formating API response
        bytarray = reply.readAll()
        content = bytarray.data().decode("utf8")

        # check API response structure
        try:
            parsed_content = json.loads(content)
        except:
            logger.debug("Reply format issue")
            return

        # check API response content
        if "access_token" in parsed_content:
            self.token = "Bearer " + parsed_content.get("access_token")
            self.api_get_request()
        else:
            logger.debug("ya une couille dans la magouille : {}".format(parsed_content))

    def api_get_request(self):
        logger.debug("\n----------------- Sending request -----------------")

        # 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

        rqst_reply = self.naMngr.get(rqst)
        rqst_reply.finished.connect(partial(self.api_handle_request, reply=rqst_reply))

    def api_handle_request(self, reply):
        logger.debug("Request sent and API reply received")
        bytarray = reply.readAll()
        content = bytarray.data().decode("utf8")

        if reply.error() == 0:
            # check API response structure
            try:
                parsed_content = json.loads(content)
            except:
                logger.debug("Reply format issue")
                return

            # check API response content
            self.tags_found = parsed_content.get("tags")
            self.kw_found = {}
            for tag in sorted(self.tags_found):
                if tag.startswith("keyword:is"):
                    self.kw_found[tag] = self.tags_found.get(tag)
                else:
                    pass

            # displaying result
            self.ui.lbl_found.setText(
                "Found : {} resources and {} keywords".format(
                    parsed_content.get("total"), len(self.kw_found)
                )
            )

            if self.search_type == "init":
                if len(self.kw_found) == self.kw_expected_nb:
                    logger.debug("!!! It's working !!!")
                else:
                    logger.debug("It's NOT working")
            else:
                pass

            # filling keywords checkable combo box
            self.pop_kw_cbbox()

        elif self.search_type != "init":
            logger.debug("token expired, renewing it")
            self.api_authentification()

        else:
            pass

    def pop_kw_cbbox(self):
        logger.debug("\n-------------- Poping Keywords ComboBox --------------")

        # to prepare the filling
        self.ui.kw_cbbox.clear()
        if self.search_type != "init":
            self.ui.kw_cbbox.activated.disconnect(self.get_checked_kw)

        # filling the combobox with checkable items
        self.ui.kw_cbbox.addItem("-- Keywords --")
        first_item = self.ui.kw_cbbox.model().item(0, 0)
        first_item.setEnabled(False)
        i = 1
        for kw_code, kw_lbl in self.kw_found.items():

            if self.search_type == "kw" and kw_code in self.checked_kw.keys():
                self.ui.kw_cbbox.insertItem(1, kw_lbl)
                item = self.ui.kw_cbbox.model().item(1, 0)
                item.setCheckState(Qt.Checked)
            else:
                self.ui.kw_cbbox.addItem(kw_lbl)
                item = self.ui.kw_cbbox.model().item(i, 0)
                item.setCheckState(Qt.Unchecked)
            item.setData(kw_code, 32)
            i += 1
        logger.debug("Keywords Combobox filled")

        self.ui.kw_cbbox.setEnabled(True)
        # connecting to a signal returning the checked item's index
        self.ui.kw_cbbox.activated.connect(self.get_checked_kw)

    def get_checked_kw(self, index):
        logger.debug("\n------------ Getting Checked Keywords ------------")

        self.ui.kw_cbbox.setEnabled(False)
        self.ui.kw_cbbox.setCurrentText(self.ui.kw_cbbox.itemText(index))

        # Testing if checked keyword is already in the dict is easier than
        # testing if the user checked or unchecked it :
        # removing the selected keyword from the dict if it is already in
        if self.ui.kw_cbbox.itemData(index, 32) in self.checked_kw.keys():
            del self.checked_kw[self.ui.kw_cbbox.itemData(index, 32)]
        # adding the selected keyword to the dict if it is not already in
        else:
            self.checked_kw[
                self.ui.kw_cbbox.itemData(index, 32)
            ] = self.ui.kw_cbbox.itemText(index)
        logger.debug("ckeched kw : {}".format(self.checked_kw))

        self.ui.lbl_selection.setText(
            "{} keywords selected".format(len(self.checked_kw))
        )
        self.ui.kw_cbbox.setToolTip(" / ".join(list(self.checked_kw.values())))
        # now selected keywords are stocked, time to request the API
        self.kw_search()

    def kw_search(self):
        logger.debug("\n------------ Searching with keywords -------------")
        # preparing the request
        self.search_type = "kw"
        self.request_url = self.url_builder()
        self.pysdk_checking()
        # launching the request
        self.api_get_request()

    def url_builder(self):
        logger.debug("\n------------------ Building URL ------------------")
        # adding selected keywords to the request URL
        search_url = "https://v1.api.isogeo.com/resources/search?q="
        for kw in self.checked_kw:
            search_url += "{} ".format(str(kw))
        logger.debug("URL : {}".format(search_url))
        return search_url[:-1]

    def reset(self):
        logger.debug("----------------- RESET -------------------")
        self.search_type = "reset"
        self.checked_kw = {}
        self.request_url = (
            "https://v1.api.isogeo.com/resources/search?_limit=0&_offset=0"
        )
        self.ui.lbl_selection.setText("")
        self.ui.kw_cbbox.setToolTip("")
        self.pysdk_checking()
        self.api_get_request()
Example #14
0
class AutoSuggest(QObject):

    def __init__(self, geturl_func, parseresult_func, parent = None):
        QObject.__init__(self, parent)
        self.geturl_func = geturl_func
        self.parseresult_func = parseresult_func
        
        self.editor = parent
        self.networkManager = QNetworkAccessManager()

        self.selectedObject = None
        self.isUnloaded = False

        self.popup = QTreeWidget(parent)
        #self.popup.setColumnCount(2)
        self.popup.setColumnCount(1)
        self.popup.setUniformRowHeights(True)
        self.popup.setRootIsDecorated(False)
        self.popup.setEditTriggers(QTreeWidget.NoEditTriggers)
        self.popup.setSelectionBehavior(QTreeWidget.SelectRows)
        self.popup.setFrameStyle(QFrame.Box | QFrame.Plain)
        self.popup.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.popup.header().hide()
        self.popup.installEventFilter(self)
        self.popup.setMouseTracking(True)

        #self.connect(self.popup, SIGNAL("itemClicked(QTreeWidgetItem*, int)"),
        #             self.doneCompletion)
        self.popup.itemClicked.connect( self.doneCompletion )

        self.popup.setWindowFlags(Qt.Popup)
        self.popup.setFocusPolicy(Qt.NoFocus)
        self.popup.setFocusProxy(parent)

        self.timer = QTimer(self)
        self.timer.setSingleShot(True)
        self.timer.setInterval(500)
        #self.connect(self.timer, SIGNAL("timeout()"), self.autoSuggest)
        self.timer.timeout.connect( self.autoSuggest )
        
        #self.connect(self.editor, SIGNAL("textEdited(QString)"), self.timer, SLOT("start()"))
        #self.editor.textEdited.connect( self.timer.start )
        self.editor.textEdited.connect( self.timer.start )
        #self.editor.textChanged.connect( self.timer.start )

        #self.connect(self.networkManager, SIGNAL("finished(QNetworkReply*)"),
        #             self.handleNetworkData)
        self.networkManager.finished.connect( self.handleNetworkData )

    def eventFilter(self, obj, ev):
        if obj != self.popup:
            return False

        if ev.type() == QEvent.MouseButtonPress:
            self.popup.hide()
            self.editor.setFocus()
            return True

        if ev.type() == QEvent.KeyPress:
            consumed = False
            key = ev.key()
            if key == Qt.Key_Enter or key == Qt.Key_Return:
                self.doneCompletion()
                consumed = True

            elif key == Qt.Key_Escape:
                self.editor.setFocus()
                self.popup.hide()
                consumed = True

            elif key in (Qt.Key_Up, Qt.Key_Down, Qt.Key_Home, Qt.Key_End,
                         Qt.Key_PageUp, Qt.Key_PageDown):
                pass

            else:
                self.editor.setFocus()
                self.editor.event(ev)
                self.popup.hide()

            return consumed

        return False

    def showCompletion(self, rows):
        # Rows is an iterable of tuples like [("text",object1),("text2", object2),...]
        pal = self.editor.palette()
        color = pal.color(QPalette.Disabled, QPalette.WindowText)

        self.popup.setUpdatesEnabled(False)
        self.popup.clear()
        if rows is None or len( rows ) < 1:
            return

        for row in rows:
            item = QTreeWidgetItem(self.popup)
            item.setText(0, row[0])
            #item.setText(1, hit['type'])
            item.setTextAlignment(1, Qt.AlignRight)
            item.setForeground(1, color)
            item.setData(2, Qt.UserRole, (row[1],)) # Try immutable py obj #http://stackoverflow.com/questions/9257422/how-to-get-the-original-python-data-from-qvariant

        self.popup.setCurrentItem(self.popup.topLevelItem(0))
        self.popup.resizeColumnToContents(0)
        #self.popup.resizeColumnToContents(1)
        self.popup.adjustSize()
        self.popup.setUpdatesEnabled(True)

        h = self.popup.sizeHintForRow(0) * min(15, len(rows)) + 3
        w = max(self.popup.width(), self.editor.width())
        self.popup.resize(w, h)

        self.popup.move(self.editor.mapToGlobal(QPoint(0, self.editor.height())))
        self.popup.setFocus()
        self.popup.show()

    def doneCompletion(self):
        self.timer.stop()
        self.popup.hide()
        self.editor.setFocus()
        item = self.popup.currentItem()
        if item:
            self.editor.setText(item.text(0) )
            obj =  item.data(2, Qt.UserRole) #.toPyObject()
            self.selectedObject = obj[0]
            e = QKeyEvent(QEvent.KeyPress, Qt.Key_Enter, Qt.NoModifier)
            QApplication.postEvent(self.editor, e)
            e = QKeyEvent(QEvent.KeyRelease, Qt.Key_Enter, Qt.NoModifier)
            QApplication.postEvent(self.editor, e)

    def preventSuggest(self):
        self.timer.stop()

    def autoSuggest(self):
        term = self.editor.text()
        if term:
            qurl = self.geturl_func( term )
            if qurl:
                # TODO: Cancel existing requests: http://qt-project.org/forums/viewthread/18073
                self.networkManager.get(QNetworkRequest( qurl ))      #QUrl(url)))


    def handleNetworkData(self, networkReply):
        url = networkReply.url()
        #print "received url:", url.toString()
        if not networkReply.error():
            response = networkReply.readAll()
            pystring = str(response, 'utf-8')
            #print "Response: ", response
            rows = self.parseresult_func( pystring )
            self.showCompletion( rows )

        networkReply.deleteLater()

    def unload( self ):
        # Avoid processing events after QGIS shutdown has begun
        self.popup.removeEventFilter(self)
        self.isUnloaded = True
Example #15
0
class ApiConnection:
    def __init__(self, auth_file):

        logger.debug(
            "\n================== ISOGEO API WITH QT ==================")

        # getting credentials :
        logger.debug("Getting credentials")
        self.utils = IsogeoUtils()
        self.app_creds = self.utils.credentials_loader(auth_file)
        self.app_id = self.app_creds.get("client_id")
        self.app_secrets = self.app_creds.get("client_secret")

        # for connection :
        self.naMngr = QNetworkAccessManager()
        self.token_url = "https://id.api.isogeo.com/oauth/token"
        self.request_url = (
            "https://v1.api.isogeo.com/resources/search?_limit=0&_offset=0")
        self.token = ""

        # for ui :
        logger.debug("Processing and displaying UI")
        self.app = QApplication([])
        self.ui = AuthWidget()
        self.ui.resize(350, 100)
        self.ui.btn.clicked.connect(self.api_authentification)
        self.pysdk_checking()
        self.ui.show()
        self.app.exec()

    def pysdk_checking(self):
        logger.debug("\n------------------ isogeo-pysdk ------------------")
        logger.debug("Checking credentials")
        try:
            isogeo = Isogeo(self.app_id, self.app_secrets)
            isogeo.connect()
        except OSError as e:
            logger.debug("Credentials issue : {}".format(e))
            return
        except ValueError as e:
            logger.debug("Credentials issue : {}".format(e))
            return

        self.md_expected = isogeo.search(whole_share=0, page_size=0,
                                         augment=0).get("total")
        self.ui.lbl_expected.setText("{} expected resources".format(
            self.md_expected))
        logger.debug(
            "isogeo-pysdk validates the authentication file, {} accessible resources"
            .format(self.md_expected))

    def api_authentification(self):
        logger.debug("\n------------------ Authentication ------------------")

        # creating credentials header
        logger.debug("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
        logger.debug("Creating 'Content-Type' header")

        ct_header_value = QByteArray()
        ct_header_value.append("application/json")

        # creating request
        token_rqst = QNetworkRequest(QUrl(self.token_url))
        logger.debug("Creating token request : {}".format(token_rqst.url()))

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

        token_rqst.setHeader(token_rqst.ContentTypeHeader, ct_header_value)
        logger.debug("Setting 'Content-Type' header : {}".format(
            token_rqst.header(token_rqst.ContentTypeHeader)))

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

        # 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))

    def api_handle_token(self, reply):
        logger.debug("\n------------------ Token retrieval ------------------")
        logger.debug("Token asked and API reply received : {}".format(reply))

        logger.debug("Storage and formatting of the reply")
        bytarray = reply.readAll()
        content = bytarray.data().decode("utf8")

        # check API response structure
        try:
            parsed_content = json.loads(content)
        except:
            logger.debug("Reply format issue")
            return
        logger.debug("Reply format is good")

        if "access_token" in parsed_content:
            self.token = "Bearer " + parsed_content.get("access_token")
            logger.debug("TOKEN STORED")
            self.api_get_request()
        else:
            logger.debug(
                "ya une couille dans la magouille : {}".format(parsed_content))

    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))

    def api_handle_request(self, reply):
        logger.debug("\n------------------ Reply retrieval ------------------")
        logger.debug("Request sent and API reply received : {}".format(reply))

        logger.debug("Storage and formatting of the reply")
        bytarray = reply.readAll()
        content = bytarray.data().decode("utf8")

        # check API response structure
        try:
            parsed_content = json.loads(content)
        except:
            logger.debug("Reply format issue")
            return
        logger.debug("Reply format is good")

        self.md_found = parsed_content.get("total")
        logger.debug("RESULT STORED")
        self.ui.lbl_found.setText("{} resources found".format(self.md_found))

        if self.md_found == self.md_expected:
            logger.debug("!!! It's working !!!")
        else:
            logger.debug("It's NOT working")
Example #16
0
class NetManager(QObject):
    def __init__(self, parent):
        super().__init__(parent)
        self.network = QNetworkAccessManager(self)

    #############
    def _pre_send_request(self, conn_info, endpoint, kw_request=dict()):
        assert (isinstance(endpoint, str))
        request = make_conn_request(conn_info, endpoint, **kw_request)
        return request

    def _post_send_request(self, reply, conn_info, kw_prop=dict()):
        set_qt_property(reply, conn_info=conn_info, **kw_prop)

    def _send_request(self,
                      conn_info,
                      endpoint,
                      kw_request=dict(),
                      kw_prop=dict()):

        request = self._pre_send_request(conn_info,
                                         endpoint,
                                         kw_request=kw_request)

        reply = self.network.get(request)

        self._post_send_request(reply, conn_info, kw_prop=kw_prop)
        return reply

    #############
    # TODO: remove callback params
    def get_statistics(self, conn_info):
        reply = self._get_space_(conn_info, "statistics")
        timeout = TIMEOUT_COUNT
        QTimer.singleShot(timeout, reply.abort)
        return reply

    def get_count(self, conn_info):
        reply = self._get_space_(conn_info, "count")
        return reply

    def get_meta(self, conn_info):
        return self._get_space_(conn_info, "space_meta")

    def _get_space_(self, conn_info, reply_tag):
        tag = "/" + reply_tag if reply_tag != "space_meta" else ""

        endpoint = "/spaces/{space_id}" + tag
        kw_request = dict()
        kw_prop = dict(reply_tag=reply_tag)
        return self._send_request(conn_info,
                                  endpoint,
                                  kw_request=kw_request,
                                  kw_prop=kw_prop)

    def list_spaces(self, conn_info):
        endpoint = "/spaces"
        kw_request = dict(includeRights="true")
        kw_prop = dict(reply_tag="spaces")
        return self._send_request(conn_info,
                                  endpoint,
                                  kw_request=kw_request,
                                  kw_prop=kw_prop)

    def add_space(self, conn_info, space_info):
        space_info = prepare_new_space_info(space_info)

        endpoint = "/spaces"
        kw_request = dict(req_type="json")
        kw_prop = dict(reply_tag="add_space")

        request = self._pre_send_request(conn_info,
                                         endpoint,
                                         kw_request=kw_request)
        reply = self.network.post(request, make_payload(space_info))

        self._post_send_request(reply, conn_info, kw_prop=kw_prop)
        return reply

    def edit_space(self, conn_info, space_info):

        endpoint = "/spaces/{space_id}"
        kw_request = dict(req_type="json")
        kw_prop = dict(reply_tag="edit_space")

        request = self._pre_send_request(conn_info,
                                         endpoint,
                                         kw_request=kw_request)
        buffer = make_buffer(space_info)
        reply = self.network.sendCustomRequest(request, b"PATCH", buffer)
        buffer.setParent(reply)

        self._post_send_request(reply, conn_info, kw_prop=kw_prop)
        return reply

    def del_space(self, conn_info):

        endpoint = "/spaces/{space_id}"
        kw_request = dict()
        kw_prop = dict(reply_tag="del_space")

        request = self._pre_send_request(conn_info,
                                         endpoint,
                                         kw_request=kw_request)
        reply = self.network.sendCustomRequest(request, b"DELETE")

        self._post_send_request(reply, conn_info, kw_prop=kw_prop)

        return reply

    def _prefix_query(self, txt, prefix="p.", prefixes=tuple()):
        """ return prefix to xyz query: 
            prefixes = ["p.", "f."] # add prefix if none in prefixes exists
            prefixes = [] # always add prefix, dont check existing
        """
        return prefix if not any(map(txt.startswith, prefixes)) else ""

    def _process_queries(self, kw):
        selection = ",".join(
            "{prefix}{name}".format(name=p, prefix=self._prefix_query(p, "p."))
            for p in kw.pop("selection", "").split(",") if p)
        if selection: kw["selection"] = selection
        self._process_raw_queries(kw)

    def _process_raw_queries(self, kw):
        filters = [
            "{prefix}{name}{operator}{value}".format(name=p["name"],
                                                     operator=p["operator"],
                                                     value=p["values"],
                                                     prefix=self._prefix_query(
                                                         p["name"], "p."))
            for p in kw.pop("filters", list())
        ]
        if filters: kw.setdefault("raw_queries", list()).extend(filters)

    def load_features_bbox(self, conn_info, bbox, **kw):
        reply_tag = "bbox"
        endpoint = "/spaces/{space_id}/bbox"
        self._process_queries(kw)
        kw_request = dict(bbox, **kw)
        kw_prop = dict(reply_tag=reply_tag, bbox=bbox, **kw)
        return self._send_request(conn_info,
                                  endpoint,
                                  kw_request=kw_request,
                                  kw_prop=kw_prop)

    def load_features_tile(self,
                           conn_info,
                           tile_id="0",
                           tile_schema="quadkey",
                           **kw):
        reply_tag = "tile"
        kw_tile = dict(tile_schema=tile_schema, tile_id=tile_id)
        tile_url = "tile/{tile_schema}/{tile_id}".format(**kw_tile)
        endpoint = "/spaces/{space_id}/" + tile_url
        self._process_queries(kw)
        kw_prop = dict(reply_tag=reply_tag, **dict(kw, **kw_tile))
        return self._send_request(conn_info,
                                  endpoint,
                                  kw_request=kw,
                                  kw_prop=kw_prop)

    def load_features_iterate(self, conn_info, **kw):
        reply_tag = kw.pop("reply_tag", "iterate")
        endpoint = "/spaces/{space_id}/iterate"
        self._process_queries(kw)
        kw_prop = dict(reply_tag=reply_tag, **kw)
        return self._send_request(conn_info,
                                  endpoint,
                                  kw_request=kw,
                                  kw_prop=kw_prop)

    def load_features_search(self, conn_info, **kw):
        reply_tag = kw.pop("reply_tag", "search")
        endpoint = "/spaces/{space_id}/search"
        self._process_queries(kw)
        kw_prop = dict(reply_tag=reply_tag, **kw)
        return self._send_request(conn_info,
                                  endpoint,
                                  kw_request=kw,
                                  kw_prop=kw_prop)

    ###### feature function
    def add_features(self, conn_info, added_feat, **kw):
        send_request = self.network.post  # create or modify (merge existing feature with payload) # might add attributes
        return self._add_features(conn_info, added_feat, send_request, **kw)

    def modify_features(self, conn_info, added_feat, **kw):
        return self.add_features(conn_info, added_feat, **kw)

    def replace_features(self, conn_info, added_feat, **kw):
        send_request = self.network.put  # create or replace (replace existing feature with payload) # might add or drop attributes
        return self._add_features(conn_info, added_feat, send_request, **kw)

    def _add_features(self, conn_info, added_feat, send_request, **kw):
        # POST, payload: list of FeatureCollection

        endpoint = "/spaces/{space_id}/features"
        if "tags" in kw: kw["addTags"] = kw["tags"]
        kw_request = dict(req_type="geo", **kw)  # kw: query
        kw_prop = dict(reply_tag="add_feat")
        kw_prop.update(kw)
        request = self._pre_send_request(conn_info,
                                         endpoint,
                                         kw_request=kw_request)

        payload = make_payload(added_feat)
        reply = send_request(request, payload)
        self._post_send_request(reply, conn_info, kw_prop=kw_prop)

        #parallel case (merge output ? split input?)
        return reply

    def del_features(self, conn_info, removed_feat, **kw):
        # DELETE by Query URL, required list of feat_id

        query_del = {"id": ",".join(str(i) for i in removed_feat)}
        kw.update(query_del)

        endpoint = "/spaces/{space_id}/features"
        kw_request = dict(kw)  # kw: query
        kw_prop = dict(reply_tag="del_feat")

        request = self._pre_send_request(conn_info,
                                         endpoint,
                                         kw_request=kw_request)

        reply = self.network.sendCustomRequest(request, b"DELETE")
        self._post_send_request(reply, conn_info, kw_prop=kw_prop)

        return reply
Example #17
0
class NetManager(QObject):
    def __init__(self, parent):
        super().__init__(parent)
        self.network = QNetworkAccessManager(self)

    #############
    def _pre_send_request(self,conn_info, endpoint, kw_request=dict()):
        assert(isinstance(endpoint,str))
        request = make_conn_request(conn_info, endpoint,**kw_request)
        return request

    def _post_send_request(self, reply, conn_info, kw_prop=dict()):
        set_qt_property(reply, conn_info=conn_info, **kw_prop)

    def _send_request(self,conn_info, endpoint, kw_request=dict(), kw_prop=dict()):
        
        request = self._pre_send_request(conn_info,endpoint,kw_request=kw_request)

        reply = self.network.get(request)

        self._post_send_request(reply,conn_info, kw_prop=kw_prop)
        return reply

    #############
    # TODO: remove callback params
    def get_statistics(self, conn_info):
        return self._get_space_(conn_info, "statistics")
    def get_count(self, conn_info):
        reply = self._get_space_(conn_info, "count")
        # timeout = 1000
        # QTimer.singleShot(timeout, reply.abort)
        return reply
    def get_meta(self, conn_info):
        return self._get_space_(conn_info, "space_meta")

    def _get_space_(self, conn_info, reply_tag):
        tag = "/" + reply_tag if reply_tag != "space_meta" else ""
        
        endpoint = "/spaces/{space_id}" + tag
        kw_request = dict()
        kw_prop = dict(reply_tag=reply_tag)
        return self._send_request(conn_info, endpoint, kw_request=kw_request, kw_prop=kw_prop)
        
    def list_spaces(self, conn_info):
        endpoint = "/spaces"
        kw_request = dict(includeRights="true")
        kw_prop = dict(reply_tag="spaces")
        return self._send_request(conn_info, endpoint, kw_request=kw_request, kw_prop=kw_prop)
        
    def add_space(self, conn_info, space_info):
        space_info = prepare_new_space_info(space_info)
        
        endpoint = "/spaces"
        kw_request = dict(req_type="json")
        kw_prop = dict(reply_tag="add_space")

        request = self._pre_send_request(conn_info,endpoint,kw_request=kw_request)
        reply = self.network.post(request, make_payload(space_info))

        self._post_send_request(reply,conn_info, kw_prop=kw_prop)
        return reply
    def edit_space(self, conn_info, space_info):
                
        endpoint = "/spaces/{space_id}"
        kw_request = dict(req_type="json")
        kw_prop = dict(reply_tag="edit_space")

        request = self._pre_send_request(conn_info,endpoint,kw_request=kw_request)
        reply = self.network.sendCustomRequest(request, b"PATCH", make_payload(space_info))
        
        self._post_send_request(reply,conn_info, kw_prop=kw_prop)
        return reply
        
    def del_space(self, conn_info):
        
        endpoint = "/spaces/{space_id}"
        kw_request = dict()
        kw_prop = dict(reply_tag="del_space")

        request = self._pre_send_request(conn_info,endpoint,kw_request=kw_request)
        reply = self.network.sendCustomRequest(request, b"DELETE")

        self._post_send_request(reply,conn_info, kw_prop=kw_prop)
        
        return reply
        
    def load_features_bbox(self, conn_info, bbox, **kw):

        endpoint = "/spaces/{space_id}/bbox"
        kw_request = dict(bbox)
        kw_request.update(kw)
        kw_prop = dict(reply_tag="bbox")
        kw_prop.update(kw)
        kw_prop["bbox"] = bbox
        
        return self._send_request(conn_info, endpoint, kw_request=kw_request, kw_prop=kw_prop)

    def load_features_iterate(self, conn_info, **kw_iterate):
        reply_tag = kw_iterate.pop("reply_tag","iterate")
        endpoint = "/spaces/{space_id}/iterate"
        return self._load_features_endpoint(endpoint, conn_info, reply_tag=reply_tag, **kw_iterate)

    def load_features_search(self, conn_info, **kw_iterate):
        reply_tag = kw_iterate.pop("reply_tag","search")
        endpoint = "/spaces/{space_id}/search"
        return self._load_features_endpoint(endpoint, conn_info, reply_tag=reply_tag, **kw_iterate)
        
    def _load_features_endpoint(self, endpoint, conn_info, reply_tag=None, **kw_iterate):
        """ Iterate through all ordered features (no feature is repeated twice)
        """
        kw_request = dict(kw_iterate)
        kw_prop = dict(reply_tag=reply_tag)
        kw_prop.update(kw_iterate)
        
        return self._send_request(conn_info, endpoint, kw_request=kw_request, kw_prop=kw_prop)

    ###### feature function

    def add_features(self, conn_info, added_feat, layer_id=None, **kw):
        # POST, payload: list of FeatureCollection
        
        endpoint = "/spaces/{space_id}/features"
        kw_request = dict(req_type="geo", **kw) # kw: query
        kw_prop = dict(reply_tag="add_feat",layer_id=layer_id)
        kw_prop.update(kw)
        request = self._pre_send_request(conn_info,endpoint,kw_request=kw_request)
        
        buffer = make_payload(added_feat)
        reply = self.network.post(request, buffer)
        self._post_send_request(reply, conn_info, kw_prop=kw_prop)

        #parallel case (merge output ? split input?)
        return reply
    def del_features(self, conn_info, removed_feat, layer_id, **kw):
        # DELETE by Query URL, required list of feat_id

        query_del = {"id": ",".join(str(i) for i in removed_feat)}
        kw.update(query_del)

        endpoint = "/spaces/{space_id}/features"
        kw_request = dict(kw) # kw: query
        kw_prop = dict(reply_tag="del_feat",layer_id=layer_id)

        request = self._pre_send_request(conn_info,endpoint,kw_request=kw_request)
    
        reply = self.network.sendCustomRequest(request, b"DELETE")
        self._post_send_request(reply, conn_info, kw_prop=kw_prop)

        return reply
    def sync(self, conn_info, feat, layer_id, **kw):
        added_feat, removed_feat = feat
        token, space_id = conn_info.get_xyz_space()
        if not added_feat is None:
            self.add_features(conn_info, added_feat, layer_id)
        if len(removed_feat):
            self.del_features(conn_info, removed_feat, layer_id)
Example #18
0
class AccessSite(QObject):
    abortReply = pyqtSignal()
    finished = pyqtSignal(dict)
    send_data = pyqtSignal(QByteArray)
    status_download = pyqtSignal(int, int)
    status_erros = pyqtSignal(list)
  
    ErrorCodeAttribute = {
        10:  'Canceled request',
        400: 'Bad request syntax',
        401: 'Unauthorized',
        402: 'Payment required',
        403: 'Forbidden',
        404: 'Not found',
        500: 'Internal error',
        501: 'Not implemented',
        502: 'Bad Gateway'  
    }

    def __init__(self):
        super().__init__()
        self.isKill = None
        self.responseAllFinished = None
        self.nam = QNetworkAccessManager(self)
        self.nam.finished.connect( self.replyFinished )

    def _connectReply(self, reply, isConnect=True):
        ss = [
            { 'signal': reply.readyRead, 'slot': self.readyRead },
            { 'signal': reply.sslErrors, 'slot': self.sslErrors }
        ]
        if isConnect:
            if not self.responseAllFinished:
                reply.downloadProgress.connect( self.downloadProgress )
            for item in ss:
                item['signal'].connect( item['slot'] )  
        else:
            if not self.responseAllFinished:
                reply.downloadProgress.disconnect( self.downloadProgress )
            for item in ss:
                item['signal'].disconnect( item['slot'] )

    def _closeReply(self, reply):
        def connect(isConnect=True):
            f_nam = self.nam.finished.connect if isConnect else self.nam.finished.disconnect
            f_nam( self.replyFinished )
            if not self.responseAllFinished:
                self._connectReply( reply, isConnect )

        # reply.close() call replyFinished
        connect(False)
        reply.close()
        connect()
        reply.deleteLater()

    def _redirectionReply(self, reply, url):
        self._closeReply( reply )
        if url.isRelative():
            url = url.resolved( url )
        request = QNetworkRequest( url )
        reply = self.nam.get( request )
        if reply is None:
            response = { 'isOk': False, 'message': "Netwok error", 'errorCode': -1 }
            self.finished.emit( response )
            return
        if not self.responseAllFinished:
            self._connectReply( reply )

    def _emitErrorCodeAttribute(self, code, reply):
        msg = 'Error network' if not code in self.ErrorCodeAttribute.keys() else self.ErrorCodeAttribute[ code ]
        response = { 'isOk': False, 'message': msg, 'errorCode': code }
        self._closeReply( reply )
        self.finished.emit( response )

    def _checkRedirectionAttribute(self, reply):
        urlRedir = reply.attribute( QNetworkRequest.RedirectionTargetAttribute )
        if not urlRedir is None and urlRedir != reply.url():
            self._redirectionReply( reply, urlRedir )
            return { 'isOk': True }
        codeAttribute = reply.attribute( QNetworkRequest.HttpStatusCodeAttribute )
        if not ( 200 <= codeAttribute <= 299 ):
            self._emitErrorCodeAttribute( codeAttribute, reply )
            return  { 'isOk': False }
        return { 'isOk': True }

    def _clearResponse(self, response):
        if 'data' in response:
            response['data'].clear()
            del response[ 'data' ]
        if 'statusRequest' in response:
            del response['statusRequest']
        if response['isOk']:
            if 'errorCode' in response:
                del response['errorCode']

    def requestUrl(self, paramsAccess, addFinishedResponse, setFinished):
        @pyqtSlot(dict)
        def finished( response):
            loop.quit()
            self.finished.disconnect( finished )
            if 'notResponseAllFinished' in paramsAccess:
                self.send_data.disconnect( paramsAccess['notResponseAllFinished']['writePackageImage'] )
                self.status_download.disconnect( paramsAccess['notResponseAllFinished']['progressPackageImage'] )
            response = addFinishedResponse( response )
            if response['isOk']:
                self._clearResponse( response )
            setFinished( response )
        
        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 )

        loop = QEventLoop()
        self.finished.connect( finished )
        json_request = None if not 'json_request' in paramsAccess else paramsAccess['json_request']
        self.responseAllFinished = True
        if 'notResponseAllFinished' in paramsAccess:
            self.responseAllFinished = False
            self.send_data.connect( paramsAccess['notResponseAllFinished']['writePackageImage'] )
            self.status_download.connect( paramsAccess['notResponseAllFinished']['progressPackageImage'] )     
        url = paramsAccess['url']
        if 'credential' in paramsAccess:
            userInfo = "{user}:{pwd}".format( user=paramsAccess['credential']['user'], pwd=paramsAccess['credential']['password'] )
            url.setUserInfo( userInfo )
        self.isKill = False
        run()
        loop.exec_()

    def isHostLive(self, url, setFinished):
        def addFinishedResponse(response):
            if response['isOk']:
                return response
            else:
                if response['errorCode'] == QNetworkReply.HostNotFoundError:
                    response['message'] = "{}\nURL = {}".format( response['message'], self.urlGeoserver )
                else:
                    response['isOk'] = True
            return response

        p = { 'url': QUrl( url ) }
        self.requestUrl( p, addFinishedResponse, setFinished )

    def getThumbnail(self, url, setFinished):
        def addFinishedResponse(response):
            if not response['isOk']:
                return response
            if 'data' in response: # The user can quickly change a item
                pixmap = QPixmap()
                if not pixmap.loadFromData( response['data'] ):
                    response['isOk'] = False
                    response['message'] = 'Invalid image from Mapbiomas server'
                else:
                    response['thumbnail'] = pixmap
            return response

        p = { 'url': QUrl( url ) }
        self.requestUrl( p, addFinishedResponse, setFinished )

    @pyqtSlot('QNetworkReply*')
    def replyFinished(self, reply) :
        if self.isKill:
            self._emitErrorCodeAttribute(10, reply )
            return
        if reply.error() != QNetworkReply.NoError:
            response = { 'isOk': False, 'message': reply.errorString(), 'errorCode': reply.error() }
            self._closeReply( reply )
            self.finished.emit( response )
            return
        r = self._checkRedirectionAttribute( reply )
        if not r['isOk']:
            return

        statusRequest = {
            'contentTypeHeader': reply.header( QNetworkRequest.ContentTypeHeader ),
            'lastModifiedHeader': reply.header( QNetworkRequest.LastModifiedHeader ),
            'contentLengthHeader': reply.header( QNetworkRequest.ContentLengthHeader ),
            'statusCodeAttribute': reply.attribute( QNetworkRequest.HttpStatusCodeAttribute ),
            'reasonPhraseAttribute': reply.attribute( QNetworkRequest.HttpReasonPhraseAttribute )
        }
        response = { 'isOk': True, 'statusRequest': statusRequest }
        if self.responseAllFinished:
            response['data'] = reply.readAll()
        self._closeReply( reply )
        self.finished.emit( response )

    @pyqtSlot()
    def readyRead(self):
        reply = self.sender()
        if self.isKill:
            self._emitErrorCodeAttribute(10, reply )
            return
        r = self._checkRedirectionAttribute( reply )
        if not r['isOk']:
            return
        if not reply.isOpen():
            reply.open( QNetworkReply.ReadOnly )
        data = reply.readAll()
        if data is None:
            return
        self.send_data.emit( data )

    @pyqtSlot('qint64', 'qint64')
    def downloadProgress(self, bytesReceived, bytesTotal):
        reply = self.sender()
        if self.isKill:
            self._emitErrorCodeAttribute(10, reply )
        else:
            self.status_download.emit( bytesReceived, bytesTotal )

    @pyqtSlot('QList<QSslError>')
    def sslErrors(self, errors):
        reply = self.sender()
        lstErros = map( lambda e: e.errorString(), errors )
        self.status_erros.emit( lstErros )
        reply.ignoreSslErrors()

    @staticmethod
    def loadJsonData(response):
        data = response['data'].data()
        sdata = str(data, encoding='utf-8')
        return json.loads( sdata )