예제 #1
0
 def data_product_qgsresult(self, data: dict, sub_layer: bool, score: float,
                            stacktype) -> QgsLocatorResult:
     result = QgsLocatorResult()
     result.filter = self
     result.displayString = '{prefix}{title}'.format(
         prefix=' ↳ ' if sub_layer else '', title=data['display'])
     if stacktype == 'background':
         result.group = 'Hintergrundkarten'
     else:
         loading_mode: LoadingMode = self.settings.value(
             'default_layer_loading_mode')
         result.group = 'Vordergrundkarten (Doppelklick: {normal}, Ctrl-Doppelklick: {alt})'.format(
             normal=loading_mode, alt=loading_mode.alternate_mode())
     result.userData = DataProductResult(
         type=data['type'],
         dataproduct_id=data['dataproduct_id'],
         display=data['display'],
         dset_info=data['dset_info'],
         stacktype=stacktype,
         sublayers=data.get('sublayers', None))
     data_product = 'dataproduct'
     data_type = data['type']
     result.icon, result.description = dataproduct2icon_description(
         data_product, data_type)
     result.score = score
     return result
    def handle_response(self, content: QByteArray):
        try:
            data = json.loads(str(content.data(), encoding='utf-8'))
            # self.dbg_info(data)

            features = data['features']
            for f in features:
                json_geom = json.dumps(f['geometry'])
                ogr_geom = ogr.CreateGeometryFromJson(json_geom)
                wkt = ogr_geom.ExportToWkt()
                geometry = QgsGeometry.fromWkt(wkt)
                self.dbg_info('---------')
                self.dbg_info(
                    QgsWkbTypes.geometryDisplayString(geometry.type()))
                self.dbg_info(f.keys())
                self.dbg_info('{} {}'.format(f['properties']['layer_name'],
                                             f['properties']['label']))
                self.dbg_info(f['bbox'])
                self.dbg_info(f['geometry'])
                if geometry is None:
                    continue
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = f['properties']['label']
                result.group = self.beautify_group(
                    f['properties']['layer_name'])
                result.userData = geometry
                self.resultFetched.emit(result)

        except Exception as e:
            self.info(str(e), Qgis.Critical)
예제 #3
0
    def fetchResults(self, string, context, feedback):
        # collect results in main thread, since this method is inexpensive and
        # accessing the processing registry/current layer is not thread safe

        if iface.activeLayer() is None or iface.activeLayer().type() != QgsMapLayer.VectorLayer or not iface.activeLayer().selectedFeatureCount():
            return

        for a in QgsApplication.processingRegistry().algorithms():
            if not a.flags() & QgsProcessingAlgorithm.FlagSupportsInPlaceEdits:
                continue

            if not a.supportInPlaceEdit(iface.activeLayer()):
                continue

            if QgsLocatorFilter.stringMatches(a.displayName(), string) or [t for t in a.tags() if QgsLocatorFilter.stringMatches(t, string)] or \
                    (context.usingPrefix and not string):
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = a.displayName()
                result.icon = a.icon()
                result.userData = a.id()
                if string and QgsLocatorFilter.stringMatches(a.displayName(), string):
                    result.score = float(len(string)) / len(a.displayName())
                else:
                    result.score = 0
                self.resultFetched.emit(result)
예제 #4
0
    def handle_response(self, response, search_text: str):
        try:
            if response.status_code != 200:
                if not isinstance(response.exception, RequestsExceptionUserAbort):
                    info("Error in main response with status code: "
                         "{} from {}".format(response.status_code, response.url))
                return

            display_name_field = QgsField('display_name', QVariant.String)
            fields = QgsFields()
            fields.append(display_name_field)
            features = QgsJsonUtils.stringToFeatureList(response.content.decode('utf-8'), fields, QTextCodec.codecForName('UTF-8'))
            dbg_info('Found {} features'.format(len(features)))
            dbg_info('Data {}'.format(response.content.decode('utf-8')))

            for feature in features:
                dbg_info('Adding feature {}'.format(feature['display_name']))
                result = QgsLocatorResult()
                result.filter = self
                result.group = 'Objekte'
                result.displayString = feature['display_name']
                result.userData = FeatureResult(feature)
                self.resultFetched.emit(result)

                self.result_found = True

        except Exception as e:
            info(str(e), Qgis.Critical)
            exc_type, exc_obj, exc_traceback = sys.exc_info()
            filename = os.path.split(
                exc_traceback.tb_frame.f_code.co_filename)[1]
            info('{} {} {}'.format(exc_type, filename,
                                   exc_traceback.tb_lineno), Qgis.Critical)
            info(traceback.print_exception(
                exc_type, exc_obj, exc_traceback), Qgis.Critical)
    def fetchResults(self, search, context, feedback):

        if len(search) < 2:
            return

        url = '{}{}'.format(self.SEARCH_URL, search)
        self.info('Search url {}'.format(url))
        nam = NetworkAccessManager()
        try:
            
            headers = {b'User-Agent': self.USER_AGENT}
            # use BLOCKING request, as fetchResults already has it's own thread!
            (response, content) = nam.request(url, headers=headers, blocking=True)
            
            if response.status_code == 200:  # other codes are handled by NetworkAccessManager
                content_string = content.decode('utf-8')
                locations = json.loads(content_string)
                
                #loop on features in json collection
                for loc in locations['features']: 

                    result = QgsLocatorResult()
                    result.filter = self
                    result.displayString = '{} ({})'.format(loc['properties']['label'], loc['properties']['type'])
                    #use the json full item as userData, so all info is in it:
                    result.userData = loc
                    self.resultFetched.emit(result)

        except RequestsException as err:
            # Handle exception..
            self.info(err)
            self.resultProblem.emit('{}'.format(err))
예제 #6
0
    def fetchResults(self, string, context, feedback):
        # collect results in main thread, since this method is inexpensive and
        # accessing the processing registry/current layer is not thread safe

        if iface.activeLayer() is None or iface.activeLayer().type() != QgsMapLayer.VectorLayer:
            return

        for a in QgsApplication.processingRegistry().algorithms():
            if not a.flags() & QgsProcessingAlgorithm.FlagSupportsInPlaceEdits:
                continue

            if not a.supportInPlaceEdit(iface.activeLayer()):
                continue

            if QgsLocatorFilter.stringMatches(a.displayName(), string) or [t for t in a.tags() if QgsLocatorFilter.stringMatches(t, string)] or \
                    (context.usingPrefix and not string):
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = a.displayName()
                result.icon = a.icon()
                result.userData = a.id()
                if string and QgsLocatorFilter.stringMatches(a.displayName(), string):
                    result.score = float(len(string)) / len(a.displayName())
                else:
                    result.score = 0
                self.resultFetched.emit(result)
예제 #7
0
    def fetchResults(self, string, context, feedback):
        # collect results in main thread, since this method is inexpensive and
        # accessing the processing registry is not thread safe
        for a in QgsApplication.processingRegistry().algorithms():
            if a.flags() & QgsProcessingAlgorithm.FlagHideFromToolbox:
                continue
            if not ProcessingConfig.getSetting(ProcessingConfig.SHOW_ALGORITHMS_KNOWN_ISSUES) and \
                    a.flags() & QgsProcessingAlgorithm.FlagKnownIssues:
                continue

            result = QgsLocatorResult()
            result.filter = self
            result.displayString = a.displayName()
            result.icon = a.icon()
            result.userData = a.id()
            result.score = 0

            if (context.usingPrefix and not string):
                self.resultFetched.emit(result)

            string = string.lower()
            tagScore = 0
            tags = [*a.tags(), a.provider().name(), a.group()]

            for t in tags:
                if string in t.lower():
                    tagScore = 1
                    break

            result.score = QgsStringUtils.fuzzyScore(
                result.displayString, string) * 0.5 + tagScore * 0.5

            if result.score > 0:
                self.resultFetched.emit(result)
예제 #8
0
 def fetchResults(self, string, context, feedback):
     for i in range(3):
         #if feedback.isCanceled():
         #    return
         sleep(0.00001)
         result = QgsLocatorResult()
         result.displayString = self.prefix + str(i)
         self.resultFetched.emit(result)
예제 #9
0
 def fetchResults(self, string, context, feedback):
     for i in range(3):
         if feedback.isCanceled():
             return
         sleep(0.001)
         result = QgsLocatorResult()
         result.displayString = self.prefix + str(i)
         self.resultFetched.emit(result)
예제 #10
0
    def fetchResults(self, search, context, feedback):
        key = self.settings.value(self.settings_key,
                                  defaultValue='',
                                  type=str,
                                  section=QgsSettings.Plugins)
        # self.info('fetchResults KEY: "{}" self: {}'.format(key, self))
        if key == '':
            result = QgsLocatorResult()
            result.filter = self
            result.displayString = self.displayName()
            self.resultFetched.emit(result)
            return

        if len(search) < 3:
            return

        search = search.strip()

        # Google geocoding api
        # https://developers.google.com/maps/documentation/geocoding/get-api-key
        # https://developers.google.com/maps/documentation/geocoding/usage-limits  # 2500 requests per day
        url = 'https://maps.googleapis.com/maps/api/geocode/json?key={}&address={}'.format(
            key, search)

        try:
            self.info('{}'.format(url))
            (response, content) = self.nam.request(url)
            # TODO: check statuscode etc

            content_string = content.decode('utf-8')
            obj = json.loads(content_string)

            docs = obj['results']
            for doc in docs:
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = '{} ({})'.format(
                    doc['formatted_address'], doc['types'])
                result.userData = doc
                self.resultFetched.emit(result)

        except networkaccessmanager.RequestsException:
            # Handle exception
            print('!!!!!!!!!!! EXCEPTION !!!!!!!!!!!!!: \n{}'.format(
                RequestsException.args))
예제 #11
0
    def fetchResults(self, query, context, feedback):
        matching_layers = self.data.get_matching_layers(query)
        for layer in matching_layers:
            result = QgsLocatorResult()
            result.filter = self
            result.displayString = layer["title"]
            result.userData = layer["actionindex"]
            result.score = 0

            self.resultFetched.emit(result)
 def emit_bad_configuration(self, err=None):
     result = QgsLocatorResult()
     result.filter = self
     result.displayString = self.tr('Locator filter is not configured.')
     result.description = err if err else self.tr(
         'Double-click to configure.')
     result.userData = FilterNotConfigured
     result.icon = QgsApplication.getThemeIcon('mIconWarning.svg')
     self.resultFetched.emit(result)
     return
예제 #13
0
    def fetchResults(self, search, context, feedback):
        key = self.settings.value(self.settings_key, defaultValue='', type=str, section=QgsSettings.Plugins)
        self.info('KEY: "{}" self: {}'.format(key, self))
        if key == '':
            result = QgsLocatorResult()
            result.filter = self
            result.displayString = self.displayName()
            self.resultFetched.emit(result)
            return

        if len(search) < 3:
            return

        search = search.strip()

        # Google places api
        # https://developers.google.com/places/web-service/query
        # https://developers.google.com/places/web-service/get-api-key
        # https://developers.google.com/places/web-service/usage  # 1000 requests per day
        url = 'https://maps.googleapis.com/maps/api/place/autocomplete/json?types=geocode&key={}&input={}'.format(key, search)

        try:
            self.info('{}'.format(url))
            (response, content) = self.nam.request(url)
            # TODO: check statuscode etc
            #  see https://developers.google.com/places/web-service/search#PlaceSearchResponses for Google status codes
            #self.info('{}'.format(response))
            content_string = content.decode('utf-8')
            obj = json.loads(content_string)

            docs = obj['predictions']
            for doc in docs:
                result = QgsLocatorResult()
                result.filter = self
                self.info('{}'.format(doc['description']))
                result.displayString = '{} ({})'.format(doc['description'], doc['types'])
                result.userData = doc
                self.resultFetched.emit(result)

        except RequestsException:
            # Handle exception
            print('!!!!!!!!!!! EXCEPTION !!!!!!!!!!!!!: \n{}'. format(RequestsException.args))
예제 #14
0
    def fetchResults(self, search, context, feedback):
        # emit resultFetched() signal
        #  /**
        #  * Retrieves the filter results for a specified search \a string. The \a context
        #  * argument encapsulates the context relating to the search (such as a map
        #  * extent to prioritize).
        #  *
        #  * Implementations of fetchResults() should emit the resultFetched()
        #  * signal whenever they encounter a matching result.
        #  *
        #  * Subclasses should periodically check the \a feedback object to determine
        #  * whether the query has been canceled. If so, the subclass should return
        #  * this method as soon as possible.
        #  */
        ##print('--- NominatimFilter fetchResults called')
        ##print('NominatimFilter search: {}'.format(search))
        ##print('NominatimFilter context: {}'.format(context))
        #print('NominatimFilter context.targetExtent: {}'.format(context.targetExtent))
        #print('NominatimFilter context.targetExtentCrs: {}'.format(context.targetExtentCrs))
        ##print('NominatimFilter feedback: {}'.format(feedback))

        if len(search) < 3:
            #print('NOT searching because length: {}'.format(len(search)))
            return

        if search[-1] != ' ':
            #print('NOT searching because last char: "{}"'.format(search[-1]))
            return

        # stripping the search string here to be able to see two geocoders at once and Nominatim needs a space on the end
        #search = search.strip()
        url = 'http://nominatim.openstreetmap.org/search?format=json&q={}'.format(search)
        try:
            self.info('{}'.format(url))
            # TODO: Provide a valid HTTP Referer or User-Agent identifying the application (QGIS geocoder)
            # see https://operations.osmfoundation.org/policies/nominatim/
            (response, content) = self.nam.request(url)
            ##print('xx response: {}'.format(response))
            # TODO: check statuscode etc
            ##print('xx content: {}'.format(content))

            content_string = content.decode('utf-8')
            docs = json.loads(content_string)
            for doc in docs:
                #print(doc)
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = '{} ({})'.format(doc['display_name'], doc['type'])
                result.userData = doc
                self.resultFetched.emit(result)

        except RequestsException:
            # Handle exception
            errno, strerror = RequestsException.args
예제 #15
0
    def fetchResults(self, search, context, feedback):
        try:
            if len(search.strip()) < 4 or search[-1] not in (" ", "\n"):
                return

            r = tools.osmSearch(self.iface.mapCanvas(), search.strip())

            for item in r:
                wkt = item["geotext"]
                """
                id = item["place_id"]
                name = item["display_name"]
                className = item["class"]
                typeName = item["type"]
                """

                sourceCrs = QgsCoordinateReferenceSystem("EPSG:4326")
                targetCrs = self.plugin.canvas.mapSettings().destinationCrs()
                xform = QgsCoordinateTransform(sourceCrs, targetCrs,
                                               QgsProject.instance())

                try:
                    bbox = item["boundingbox"]
                    wkt = "POLYGON(({b[2]} {b[0]}, {b[2]} {b[1]}, {b[3]} {b[1]}, {b[3]} {b[0]}, {b[2]} {b[0]}))".format(
                        b=bbox)
                except Exception:
                    if wkt is None:
                        lat = item["lat"]
                        lng = item["lon"]
                        wkt = "POINT({} {})".format(lng, lat)

                try:
                    geom = QgsGeometry.fromWkt(wkt)
                    geom.transform(xform)

                    data = {
                        "id": item["place_id"],
                        "geom": geom,
                    }

                    result = QgsLocatorResult()
                    result.filter = self
                    result.displayString = "{} {}".format(
                        item["display_name"],
                        item["type"],
                    )
                    result.userData = data
                    self.resultFetched.emit(result)
                except Exception:
                    pass

        except Exception as err:
            self.resultProblem.emit("{}".format(err))
예제 #16
0
 def fetchResults(self, string, context, feedback):
     n = 3 if not self.groupResult else 9
     for i in range(n):
         if feedback.isCanceled():
             return
         sleep(0.001)
         result = QgsLocatorResult()
         result.displayString = self.identifier + str(i)
         if self.groupResult:
             if i < 6:
                 result.group = 'first group'
             elif i < 8:
                 result.group = 'second group'
         self.resultFetched.emit(result)
예제 #17
0
 def fetchResults(self, string, context, feedback):
     n = 3 if not self.groupResult else 9
     for i in range(n):
         if feedback.isCanceled():
             return
         sleep(0.001)
         result = QgsLocatorResult()
         result.displayString = self.identifier + str(i)
         if self.groupResult:
             if i < 6:
                 result.group = 'first group'
             elif i < 8:
                 result.group = 'second group'
         self.resultFetched.emit(result)
    def fetchResults(self, search: str, context: QgsLocatorContext,
                     feedback: QgsFeedback):
        try:
            self.dbg_info("start Ban locator search...")

            if len(search) < 5:
                return

            self.result_found = False

            url = 'https://api-adresse.data.gouv.fr/search/'
            params = {
                'q': str(search),
                'limit': str(self.settings.value('locations_limit'))
            }

            # Locations, WMS layers
            nam = NetworkAccessManager()
            feedback.canceled.connect(nam.abort)
            url = self.url_with_param(url, params)
            self.dbg_info(url)
            try:
                (response, content) = nam.request(url,
                                                  headers=self.HEADERS,
                                                  blocking=True)
                self.handle_response(response)
            except RequestsExceptionUserAbort:
                pass
            except RequestsException as err:
                self.info(err)

            if not self.result_found:
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = self.tr('No result found.')
                result.userData = NoResult
                self.resultFetched.emit(result)

        except Exception as e:
            self.info(e, Qgis.Critical)
            exc_type, exc_obj, exc_traceback = sys.exc_info()
            filename = os.path.split(
                exc_traceback.tb_frame.f_code.co_filename)[1]
            self.info(
                '{} {} {}'.format(exc_type, filename, exc_traceback.tb_lineno),
                Qgis.Critical)
            self.info(
                traceback.print_exception(exc_type, exc_obj, exc_traceback),
                Qgis.Critical)
예제 #19
0
 def data_product_qgsresult(self, data: dict) -> QgsLocatorResult:
     result = QgsLocatorResult()
     result.filter = self
     result.displayString = data['display']
     result.group = 'Karten'
     result.userData = DataProductResult(
         type=data['type'],
         dataproduct_id=data['dataproduct_id'],
         display=data['display'],
         dset_info=data['dset_info'],
         sublayers=data.get('sublayers', None)
     )
     data_product = 'dataproduct'
     data_type = data['type']
     result.icon, result.description = dataproduct2icon_description(
         data_product, data_type)
     return result
예제 #20
0
    def fetchResults(self, string, context, feedback):
        for a in QgsApplication.processingRegistry().algorithms():
            if feedback.isCanceled():
                return
            if a.flags() & QgsProcessingAlgorithm.FlagHideFromToolbox:
                continue

            if QgsLocatorFilter.stringMatches(a.displayName(), string) or [t for t in a.tags() if QgsLocatorFilter.stringMatches(t, string)]:
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = a.displayName()
                result.icon = a.icon()
                result.userData = a.id()
                if string and QgsLocatorFilter.stringMatches(a.displayName(), string):
                    result.score = float(len(string)) / len(a.displayName())
                else:
                    result.score = 0
                self.resultFetched.emit(result)
예제 #21
0
    def fetchResults(self, string, context, feedback):
        # collect results in main thread, since this method is inexpensive and
        # accessing the processing registry is not thread safe
        for a in QgsApplication.processingRegistry().algorithms():
            if a.flags() & QgsProcessingAlgorithm.FlagHideFromToolbox:
                continue

            if QgsLocatorFilter.stringMatches(a.displayName(), string) or [t for t in a.tags() if QgsLocatorFilter.stringMatches(t, string)]:
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = a.displayName()
                result.icon = a.icon()
                result.userData = a.id()
                if string and QgsLocatorFilter.stringMatches(a.displayName(), string):
                    result.score = float(len(string)) / len(a.displayName())
                else:
                    result.score = 0
                self.resultFetched.emit(result)
예제 #22
0
    def fetchResults(self, string, context, feedback):
        for a in QgsApplication.processingRegistry().algorithms():
            if feedback.isCanceled():
                return
            if a.flags() & QgsProcessingAlgorithm.FlagHideFromToolbox:
                continue

            if QgsLocatorFilter.stringMatches(a.displayName(), string) or [t for t in a.tags() if QgsLocatorFilter.stringMatches(t, string)]:
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = a.displayName()
                result.icon = a.icon()
                result.userData = a.id()
                if string and QgsLocatorFilter.stringMatches(a.displayName(), string):
                    result.score = float(len(string)) / len(a.displayName())
                else:
                    result.score = 0
                self.resultFetched.emit(result)
예제 #23
0
    def fetchResults(self, string, context, feedback):
        # collect results in main thread, since this method is inexpensive and
        # accessing the processing registry is not thread safe
        for a in QgsApplication.processingRegistry().algorithms():
            if a.flags() & QgsProcessingAlgorithm.FlagHideFromToolbox:
                continue

            if QgsLocatorFilter.stringMatches(a.displayName(), string) or [t for t in a.tags() if QgsLocatorFilter.stringMatches(t, string)]:
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = a.displayName()
                result.icon = a.icon()
                result.userData = a.id()
                if string and QgsLocatorFilter.stringMatches(a.displayName(), string):
                    result.score = float(len(string)) / len(a.displayName())
                else:
                    result.score = 0
                self.resultFetched.emit(result)
예제 #24
0
    def fetchResults(self, string, context, feedback):
        # collect results in main thread, since this method is inexpensive and
        # accessing the processing registry/current layer is not thread safe

        if iface.activeLayer() is None or iface.activeLayer().type(
        ) != QgsMapLayerType.VectorLayer:
            return

        for a in QgsApplication.processingRegistry().algorithms():
            if not a.flags() & QgsProcessingAlgorithm.FlagSupportsInPlaceEdits:
                continue

            if not a.supportInPlaceEdit(iface.activeLayer()):
                continue

            result = QgsLocatorResult()
            result.filter = self
            result.displayString = a.displayName()
            result.icon = a.icon()
            result.userData = a.id()
            result.score = 0

            if (context.usingPrefix and not string):
                self.resultFetched.emit(result)

            if not string:
                return

            string = string.lower()
            tagScore = 0
            tags = [*a.tags(), a.provider().name()]
            if a.group():
                tags.append(a.group())

            for t in tags:
                if string in t.lower():
                    tagScore = 1
                    break

            result.score = QgsStringUtils.fuzzyScore(
                result.displayString, string) * 0.5 + tagScore * 0.5

            if result.score > 0:
                self.resultFetched.emit(result)
예제 #25
0
    def fetchResults(self, search: str, context: QgsLocatorContext, feedback: QgsFeedback):
        try:
            dbg_info("start shlocator search...")

            if len(search) < 3:
                return

            self.result_found = False

            params = {
                'query': str(search),
                'maxfeatures': str(self.settings.value('max_features'))
            }

            nam = NetworkAccessManager()
            feedback.canceled.connect(nam.abort)
            url = self.url_with_param(
                self.settings.value('service_url'), params)
            dbg_info(url)
            try:
                (response, content) = nam.request(
                    url, headers=self.HEADERS, blocking=True)
                self.handle_response(response, search)
            except RequestsExceptionUserAbort:
                pass
            except RequestsException as err:
                info(err, Qgis.Info)

            if not self.result_found:
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = self.tr('No result found.')
                result.userData = NoResult
                self.resultFetched.emit(result)

        except Exception as e:
            info(e, Qgis.Critical)
            exc_type, exc_obj, exc_traceback = sys.exc_info()
            filename = os.path.split(
                exc_traceback.tb_frame.f_code.co_filename)[1]
            info('{} {} {}'.format(exc_type, filename,
                                   exc_traceback.tb_lineno), Qgis.Critical)
            info(traceback.print_exception(
                exc_type, exc_obj, exc_traceback), Qgis.Critical)
    def fetchResults(self, search, context, feedback):

        if len(search) < 2:
            return

        # see https://operations.osmfoundation.org/policies/nominatim/
        # "Auto-complete search This is not yet supported by Nominatim and you must not implement such a service on the client side using the API."
        # so end with a space to trigger a search:
        if search[-1] != ' ':
            return

        url = '{}{}'.format(self.SEARCH_URL, search)
        self.info('Search url {}'.format(url))
        try:
            # see https://operations.osmfoundation.org/policies/nominatim/
            # "Pro4 vide a valid HTTP Referer or User-Agent identifying the application (QGIS geocoder)"
            # TODO
            #headers = {b'User-Agent': self.USER_AGENT}

            # nam = Network Access Manager
            nam = QgsBlockingNetworkRequest()
            request = QNetworkRequest(QUrl(url))
            request.setHeader(QNetworkRequest.UserAgentHeader, self.USER_AGENT)
            nam.get(request, forceRefresh=True)
            reply = nam.reply()
            if reply.attribute(
                    QNetworkRequest.HttpStatusCodeAttribute
            ) == 200:  # other codes are handled by NetworkAccessManager
                content_string = reply.content().data().decode('utf8')
                locations = json.loads(content_string)
                for loc in locations:
                    result = QgsLocatorResult()
                    result.filter = self
                    result.displayString = '{} ({})'.format(
                        loc['display_name'], loc['type'])
                    # use the json full item as userData, so all info is in it:
                    result.userData = loc
                    self.resultFetched.emit(result)

        except Exception as err:
            # Handle exception..
            # only this one seems to work
            self.info(err)
    def handle_response(self, response):
        try:
            if response.status_code != 200:
                if not isinstance(response.exception,
                                  RequestsExceptionUserAbort):
                    self.info(
                        "Error in main response with status code: {} from {}".
                        format(response.status_code, response.url))
                return

            data = json.loads(response.content.decode('utf-8'))
            # self.dbg_info(data)
            for loc in data['features']:
                importance = loc['properties']['importance']
                citycode = loc['properties']['citycode']
                score = loc['properties']['score']
                type_result = loc['properties']['type']
                label = loc['properties']['label']
                x = float(loc['geometry']['coordinates'][0])
                y = float(loc['geometry']['coordinates'][1])
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = label
                result.group = self.group_info(type_result)
                result.icon = QIcon(
                    ":/plugins/swiss_locator/icons/ban_locator.png")
                result.userData = LocationResult(importance, citycode, score,
                                                 type_result, label, x, y)
                self.result_found = True
                self.resultFetched.emit(result)

        except Exception as e:
            self.info(str(e), Qgis.Critical)
            exc_type, exc_obj, exc_traceback = sys.exc_info()
            filename = os.path.split(
                exc_traceback.tb_frame.f_code.co_filename)[1]
            self.info(
                '{} {} {}'.format(exc_type, filename, exc_traceback.tb_lineno),
                Qgis.Critical)
            self.info(
                traceback.print_exception(exc_type, exc_obj, exc_traceback),
                Qgis.Critical)
예제 #28
0
    def fetch_result_single_database(self, search: str, connection_name: str):
        """ Fetch tables in the given database for a search. """
        connection = self.metadata.findConnection(connection_name)
        if not connection:
            self.logMessage(
                tr("The global variable {}_connection_name is not correct.").
                format(SCHEMA), Qgis.Critical)

        # Search items from pgmetadata.dataset
        sql = "  SELECT concat(d.title, ' (', d.table_name, '.', d.schema_name, ')') AS displayString,"
        sql += " d.schema_name, d.table_name, d.geometry_type, title"
        sql += " FROM pgmetadata.dataset d"
        sql += " INNER JOIN pgmetadata.v_valid_dataset v"
        sql += " ON concat(v.table_name, '.', v.schema_name) = concat(d.table_name, '.', d.schema_name)"
        sql += " WHERE concat(d.title, ' ', d.abstract, ' ', d.table_name) ILIKE '%{}%'".format(
            search)
        sql += " LIMIT 100"

        try:
            data = connection.executeSql(sql)
        except QgsProviderConnectionException as e:
            self.logMessage(str(e), Qgis.Critical)
            return

        if not data:
            return

        for item in data:
            result = QgsLocatorResult()
            result.filter = self
            result.displayString = item[0]
            result.icon = icon_for_geometry_type(item[3])
            result.userData = {
                'name': item[4],
                'connection': connection_name,
                'schema': item[1],
                'table': item[2],
            }
            self.resultFetched.emit(result)
    def fetchResults(self, search, context, feedback):

        if len(search) < 2:
            return

        url = '{}{}'.format(self.SEARCH_URL, search)
        self.info('Search url {}'.format(url))
        nam = NetworkAccessManager()
        try:
            # "Provide a valid HTTP Referer or User-Agent identifying the application (QGIS geocoder)"
            headers = {b'User-Agent': self.USER_AGENT}
            # use BLOCKING request, as fetchResults already has it's own thread!
            (response, content) = nam.request(url,
                                              headers=headers,
                                              blocking=True)
            #self.info(response)
            #self.info(response.status_code)
            if response.status_code == 200:  # other codes are handled by NetworkAccessManager
                content_string = content.decode('utf-8')
                obj = json.loads(content_string)
                docs = obj['response']['docs']
                for doc in docs:
                    result = QgsLocatorResult()
                    result.filter = self
                    result.displayString = '{} ({})'.format(
                        doc['weergavenaam'], doc['type'])
                    # use the json full item as userData, so all info is in it:
                    result.userData = doc
                    self.resultFetched.emit(result)

        except RequestsException as err:
            # Handle exception..
            # only this one seems to work
            self.info(err)
            # THIS: results in a floating window with a warning in it, wrong thread/parent?
            #self.iface.messageBar().pushWarning("PDOKLocatieserverLocatorFilter Error", '{}'.format(err))
            # THIS: emitting the signal here does not work either?
            self.resultProblem.emit('{}'.format(err))
예제 #30
0
    def fetchResults(self, search, context, feedback):
        ##print('--- PdokFilter fetchResults called')
        ##print('PdokFilter search: {}'.format(search))
        ##print('PdokFilter context: {}'.format(context))
        #print('PdokFilter context.targetExtent: {}'.format(context.targetExtent))
        #print('PdokFilter context.targetExtentCrs: {}'.format(context.targetExtentCrs))
        ##print('PdokFilter feedback: {}'.format(feedback))
        self.info(self.tr)
        if len(search) < 3:
            return

        # stripping the search string here to be able to see two geocoders at once and Nominatim needs a space on the end
        search = search.strip()
        url = 'https://geodata.nationaalgeoregister.nl/locatieserver/v3/suggest?q={}'.format(
            search)
        try:
            self.info('{}'.format(url))
            (response, content) = self.nam.request(url)
            ##print('response: {}'.format(response))
            # TODO: check statuscode etc
            ##print('content: {}'.format(content))

            content_string = content.decode('utf-8')
            obj = json.loads(content_string)
            docs = obj['response']['docs']
            for doc in docs:
                ##print(doc)
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = '{} ({})'.format(
                    doc['weergavenaam'], doc['type'])
                result.userData = doc
                self.resultFetched.emit(result)

        except RequestsException:
            # Handle exception
            print('!!!!!!!!!!! EXCEPTION !!!!!!!!!!!!!: \n{}'.format(
                RequestsException.args))
예제 #31
0
 def data_product_qgsresult(self, data: dict, sub_layer: bool, score: float,
                            stacktype) -> QgsLocatorResult:
     result = QgsLocatorResult()
     result.filter = self
     result.displayString = '{prefix}{title}'.format(
         prefix=' ↳ ' if sub_layer else '', title=data['display'])
     if stacktype == 'background':
         result.group = 'Karten (Hintergrundkarten)'
     else:
         result.group = 'Karten (Vordergrundkarten)'
     result.userData = DataProductResult(
         type=data['type'],
         dataproduct_id=data['dataproduct_id'],
         display=data['display'],
         dset_info=data['dset_info'],
         stacktype=stacktype,
         sublayers=data.get('sublayers', None))
     data_product = 'dataproduct'
     data_type = data['type']
     result.icon, result.description = dataproduct2icon_description(
         data_product, data_type)
     result.score = score
     return result
    def handle_response(self, response, content):
        try:
            if response.status_code != 200:
                self.info("Error with status code: {}".format(
                    response.status_code))
                return

            data = json.loads(content.decode('utf-8'))
            #self.dbg_info(data)

            features = data['features']
            for f in features:
                json_geom = json.dumps(f['geometry'])
                ogr_geom = ogr.CreateGeometryFromJson(json_geom)
                wkt = ogr_geom.ExportToWkt()
                geometry = QgsGeometry.fromWkt(wkt)
                self.dbg_info('---------')
                self.dbg_info(
                    QgsWkbTypes.geometryDisplayString(geometry.type()))
                self.dbg_info(f.keys())
                self.dbg_info('{} {}'.format(f['properties']['layer_name'],
                                             f['properties']['label']))
                self.dbg_info(f['bbox'])
                self.dbg_info(f['geometry'])
                if geometry is None:
                    continue
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = f['properties']['label']
                if Qgis.QGIS_VERSION_INT >= 30100:
                    result.group = self.beautify_group(
                        f['properties']['layer_name'])
                result.userData = geometry
                self.resultFetched.emit(result)

        except Exception as e:
            self.info(str(e), Qgis.Critical)
    def handle_response(self, response, search: str, feedback: QgsFeedback):
        try:
            if response.status_code != 200:
                if not isinstance(response.exception,
                                  RequestsExceptionUserAbort):
                    self.info(
                        "Error in main response with status code: {} from {}".
                        format(response.status_code, response.url))
                return

            data = json.loads(response.content.decode('utf-8'))
            # self.dbg_info(data)

            if self.is_opendata_swiss_response(data):
                visited_capabilities = []

                for loc in data['result']['results']:
                    display_name = loc['title'].get(self.lang, "")
                    if not display_name:
                        # Fallback to german
                        display_name = loc['title']['de']

                    for res in loc['resources']:

                        url = res['url']
                        url_components = urlparse(url)
                        wms_url = url_components.scheme + '://' + url_components.netloc + '/' + url_components.path + '?'

                        result = QgsLocatorResult()
                        result.filter = self
                        result.group = 'opendata.swiss'
                        result.icon = QgsApplication.getThemeIcon(
                            "/mActionAddWmsLayer.svg")

                        if 'wms' in url.lower():
                            if res['media_type'] == 'WMS':
                                result.displayString = display_name
                                result.description = url

                                if res['title']['de'] == 'GetMap':
                                    layers = parse_qs(
                                        url_components.query)['LAYERS']
                                    result.userData = WMSLayerResult(
                                        layer=layers[0],
                                        title=display_name,
                                        url=wms_url).as_definition()
                                    self.result_found = True
                                    self.resultFetched.emit(result)

                            elif 'request=getcapabilities' in url.lower(
                            ) and url_components.netloc not in visited_capabilities:
                                visited_capabilities.append(
                                    url_components.netloc)

                                def parse_capabilities_result(response):
                                    capabilities = ET.fromstring(
                                        response.content)

                                    # Get xml namespace
                                    match = re.match(r'\{.*\}',
                                                     capabilities.tag)
                                    namespace = match.group(0) if match else ''

                                    # Search for layers containing the search term in the name or title
                                    for layer in capabilities.findall(
                                            './/{}Layer'.format(namespace)):
                                        layername = self.find_text(
                                            layer, '{}Name'.format(namespace))
                                        layertitle = self.find_text(
                                            layer, '{}Title'.format(namespace))
                                        if layername and (
                                                search in layername.lower() or
                                                search in layertitle.lower()):
                                            if not layertitle:
                                                layertitle = layername

                                            result.displayString = layertitle
                                            result.description = '{}?LAYERS={}'.format(
                                                url.replace(
                                                    'GetCapabilities',
                                                    'GetMap'), layername)
                                            result.userData = WMSLayerResult(
                                                layer=layername,
                                                title=layertitle,
                                                url=wms_url).as_definition()
                                            self.result_found = True
                                            self.resultFetched.emit(result)

                                    self.event_loop.quit()

                                # Retrieve Capabilities xml
                                self.event_loop = QEventLoop()
                                nam = NetworkAccessManager()
                                nam.finished.connect(parse_capabilities_result)
                                nam.request(url,
                                            headers=self.HEADERS,
                                            blocking=False)
                                feedback.canceled.connect(self.event_loop.quit)

                                try:
                                    self.event_loop.exec_(
                                        QEventLoop.ExcludeUserInputEvents)
                                except RequestsExceptionUserAbort:
                                    pass
                                except RequestsException as err:
                                    self.info(err)

            else:
                for loc in data['results']:
                    self.dbg_info("keys: {}".format(loc['attrs'].keys()))

                    result = QgsLocatorResult()
                    result.filter = self
                    result.group = 'Swiss Geoportal'
                    if loc['attrs']['origin'] == 'layer':
                        # available keys: ['origin', 'lang', 'layer', 'staging', 'title', 'topics', 'detail', 'label', 'id']
                        for key, val in loc['attrs'].items():
                            self.dbg_info('{}: {}'.format(key, val))
                        result.displayString = loc['attrs']['title']
                        result.description = loc['attrs']['layer']
                        result.userData = WMSLayerResult(
                            layer=loc['attrs']['layer'],
                            title=loc['attrs']['title'],
                            url='http://wms.geo.admin.ch/?VERSION%3D2.0.0'
                        ).as_definition()
                        result.icon = QgsApplication.getThemeIcon(
                            "/mActionAddWmsLayer.svg")
                        self.result_found = True
                        self.resultFetched.emit(result)

                    elif loc['attrs']['origin'] == 'feature':
                        for key, val in loc['attrs'].items():
                            self.dbg_info('{}: {}'.format(key, val))
                        layer = loc['attrs']['layer']
                        point = QgsPointXY(loc['attrs']['lon'],
                                           loc['attrs']['lat'])
                        if layer in self.searchable_layers:
                            layer_display = self.searchable_layers[layer]
                        else:
                            self.info(
                                self.
                                tr('Layer {} is not in the list of searchable layers.'
                                   ' Please report issue.'.format(layer)),
                                Qgis.Warning)
                            layer_display = layer
                        result.group = layer_display
                        result.displayString = loc['attrs']['detail']
                        result.userData = FeatureResult(
                            point=point,
                            layer=layer,
                            feature_id=loc['attrs']
                            ['feature_id']).as_definition()
                        result.icon = QIcon(
                            ":/plugins/swiss_locator/icons/swiss_locator.png")
                        self.result_found = True
                        self.resultFetched.emit(result)

                    else:  # locations
                        for key, val in loc['attrs'].items():
                            self.dbg_info('{}: {}'.format(key, val))
                        group_name, group_layer = self.group_info(
                            loc['attrs']['origin'])
                        if 'layerBodId' in loc['attrs']:
                            self.dbg_info("layer: {}".format(
                                loc['attrs']['layerBodId']))
                        if 'featureId' in loc['attrs']:
                            self.dbg_info("feature: {}".format(
                                loc['attrs']['featureId']))

                        result.displayString = strip_tags(
                            loc['attrs']['label'])
                        # result.description = loc['attrs']['detail']
                        # if 'featureId' in loc['attrs']:
                        #     result.description = loc['attrs']['featureId']
                        result.group = group_name
                        result.userData = LocationResult(
                            point=QgsPointXY(loc['attrs']['y'],
                                             loc['attrs']['x']),
                            bbox=self.box2geometry(
                                loc['attrs']['geom_st_box2d']),
                            layer=group_layer,
                            feature_id=loc['attrs']['featureId']
                            if 'featureId' in loc['attrs'] else None,
                            html_label=loc['attrs']['label']).as_definition()
                        result.icon = QIcon(
                            ":/plugins/swiss_locator/icons/swiss_locator.png")
                        self.result_found = True
                        self.resultFetched.emit(result)

        except Exception as e:
            self.info(str(e), Qgis.Critical)
            exc_type, exc_obj, exc_traceback = sys.exc_info()
            filename = os.path.split(
                exc_traceback.tb_frame.f_code.co_filename)[1]
            self.info(
                '{} {} {}'.format(exc_type, filename, exc_traceback.tb_lineno),
                Qgis.Critical)
            self.info(
                traceback.print_exception(exc_type, exc_obj, exc_traceback),
                Qgis.Critical)
    def fetchResults(self, search: str, context: QgsLocatorContext,
                     feedback: QgsFeedback):
        try:
            self.dbg_info("start Swiss locator search...")

            if len(search) < 2:
                return

            if len(search) < 4 and self.type is FilterType.Feature:
                return

            self.result_found = False

            swisstopo_base_url = 'https://api3.geo.admin.ch/rest/services/api/SearchServer'
            swisstopo_base_params = {
                'type':
                self.type.value,
                'searchText':
                str(search),
                'returnGeometry':
                'true',
                'lang':
                self.lang,
                'sr':
                self.crs,
                'limit':
                str(
                    self.settings.value(
                        '{type}_limit'.format(type=self.type.value)))
                # bbox Must be provided if the searchText is not.
                # A comma separated list of 4 coordinates representing
                # the bounding box on which features should be filtered (SRID: 21781).
            }
            # Locations, WMS layers
            if self.type is not FilterType.Feature:
                nam = NetworkAccessManager()
                feedback.canceled.connect(nam.abort)

                search_urls = [(swisstopo_base_url, swisstopo_base_params)]

                if self.settings.value('layers_include_opendataswiss'
                                       ) and self.type is FilterType.WMS:
                    search_urls.append(
                        ('https://opendata.swiss/api/3/action/package_search?',
                         {
                             'q': 'q=WMS+%C3' + str(search)
                         }))

                for (swisstopo_base_url, swisstopo_base_params) in search_urls:
                    swisstopo_base_url = self.url_with_param(
                        swisstopo_base_url, swisstopo_base_params)
                    self.dbg_info(swisstopo_base_url)
                    try:
                        (response, content) = nam.request(swisstopo_base_url,
                                                          headers=self.HEADERS,
                                                          blocking=True)
                        self.handle_response(response, search, feedback)
                    except RequestsExceptionUserAbort:
                        pass
                    except RequestsException as err:
                        self.info(err)

            # Feature search
            else:
                # Feature search is split in several requests
                # otherwise URL is too long
                self.access_managers = {}
                try:
                    layers = list(self.searchable_layers.keys())
                    assert len(layers) > 0
                    step = 30
                    for l in range(0, len(layers), step):
                        last = min(l + step - 1, len(layers) - 1)
                        swisstopo_base_params['features'] = ','.join(
                            layers[l:last])
                        self.access_managers[self.url_with_param(
                            swisstopo_base_url, swisstopo_base_params)] = None
                except IOError:
                    self.info(
                        'Layers data file not found. Please report an issue.',
                        Qgis.Critical)

                # init event loop
                # wait for all requests to end
                self.event_loop = QEventLoop()

                def reply_finished(response):
                    self.handle_response(response, search, feedback)
                    if response.url in self.access_managers:
                        self.access_managers[response.url] = None
                    for nam in self.access_managers.values():
                        if nam is not None:
                            return
                        self.event_loop.quit()

                feedback.canceled.connect(self.event_loop.quit)

                # init the network access managers, create the URL
                for swisstopo_base_url in self.access_managers:
                    self.dbg_info(swisstopo_base_url)
                    nam = NetworkAccessManager()
                    self.access_managers[swisstopo_base_url] = nam
                    nam.finished.connect(reply_finished)
                    nam.request(swisstopo_base_url,
                                headers=self.HEADERS,
                                blocking=False)
                    feedback.canceled.connect(nam.abort)

                # Let the requests end and catch all exceptions (and clean up requests)
                if len(self.access_managers) > 0:
                    try:
                        self.event_loop.exec_(
                            QEventLoop.ExcludeUserInputEvents)
                    except RequestsExceptionUserAbort:
                        pass
                    except RequestsException as err:
                        self.info(str(err))

            if not self.result_found:
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = self.tr('No result found.')
                result.userData = NoResult().as_definition()
                self.resultFetched.emit(result)

        except Exception as e:
            self.info(e, Qgis.Critical)
            exc_type, exc_obj, exc_traceback = sys.exc_info()
            filename = os.path.split(
                exc_traceback.tb_frame.f_code.co_filename)[1]
            self.info(
                '{} {} {}'.format(exc_type, filename, exc_traceback.tb_lineno),
                Qgis.Critical)
            self.info(
                traceback.print_exception(exc_type, exc_obj, exc_traceback),
                Qgis.Critical)
예제 #35
0
    def fetchResults(self, search, context, feedback):

        self.info('search {}'.format(search))

        if len(search) < 3:
            return

        if search in 'tomtom ':
            return

        project = QgsProject.instance()
        try:
            key = QgsExpressionContextUtils.projectScope(project).variable(
                'tomtom_api_key').strip()
        except:
            #QgsExpressionContextUtils.setProjectVariable(project, 'tomtom_api_key', '')
            self.info('Add tomtom_api_key variable to your project')
            key = ''
            return

        # End with a space to trigger a search:
        #if search[-1] != ' ':
        #    return

        url = '{}{}'.format(self.SEARCH_URL, search.strip())
        url = url + '.json?'
        url = url + '&key=' + key
        url = url + '&idxSet=POI,Geo,Addr,PAD,Str,Xstr'
        self.info('Search url {}'.format(url))
        nam = NetworkAccessManager()
        try:
            # use BLOCKING request, as fetchResults already has it's own thread!
            (response, content) = nam.request(url, blocking=True)
            #self.info(response)
            #self.info(response.status_code)
            if response.status_code == 200:  # other codes are handled by NetworkAccessManager
                content_string = content.decode('utf-8')
                locations = json.loads(content_string)
                for loc in locations['results']:
                    result = QgsLocatorResult()
                    result.filter = self
                    if loc['type'] == 'Geography':
                        loc_type = loc['entityType']
                    else:
                        loc_type = loc['type']

                    if loc['type'] == 'Geography':
                        loc_display = loc['address'][
                            'freeformAddress'] + ', ' + loc['address'][
                                'country']
                    elif loc['type'] == 'Street' or loc[
                            'type'] == 'Cross Street':
                        loc_display = loc['address']['streetName'] + ', ' + loc[
                            'address']['municipality'] + ', ' + loc['address'][
                                'country']
                    elif loc['type'] == 'POI':
                        if loc['poi'].get('brands'):
                            loc_display = loc['poi']['brands'][0][
                                'name'] + ' ' + loc['poi'][
                                    'name'] + ' - ' + loc['address'][
                                        'municipality'] + ', ' + loc[
                                            'address']['country']
                        else:
                            loc_display = loc['poi']['name'] + ' - ' + loc[
                                'address']['municipality'] + ', ' + loc[
                                    'address']['country']
                    else:
                        loc_display = loc['address'][
                            'freeformAddress'] + ', ' + loc['address'][
                                'country']

                    result.displayString = '{} ({})'.format(
                        loc_display, loc_type)
                    # use the json full item as userData, so all info is in it:
                    result.userData = loc
                    self.resultFetched.emit(result)

        except RequestsException as err:
            # Handle exception..
            # only this one seems to work
            self.info(err)
            # THIS: results in a floating window with a warning in it, wrong thread/parent?
            #self.iface.messageBar().pushWarning("TomTomLocatorFilter Error", '{}'.format(err))
            # THIS: emitting the signal here does not work either?
            self.resultProblem.emit('{}'.format(err))