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