[gnome-maps/wip/mlundblad/improve-osm-url-parsing: 7/7] placeEntry: Don't re-trigger place set when set from URL




commit 58dbcbbe03fb486e372e79a6d28d658b579446d5
Author: Marcus Lundblad <ml update uu se>
Date:   Sat Nov 28 23:30:29 2020 +0100

    placeEntry: Don't re-trigger place set when set from URL
    
    When a URL matching coordinates is entered, the entry
    will be re-set to the bare coordinates. In this case
    don't trigger a re-set of the place property, as this
    would overwrite the initial zoom level set from the URL.

 src/place.js      | 94 +++++++++----------------------------------------------
 src/placeEntry.js | 18 ++++++++++-
 2 files changed, 31 insertions(+), 81 deletions(-)
---
diff --git a/src/place.js b/src/place.js
index b7d0bdab..b0e50e9e 100644
--- a/src/place.js
+++ b/src/place.js
@@ -27,6 +27,7 @@ const GObject = imports.gi.GObject;
 
 const Location = imports.location;
 const Overpass = imports.overpass;
+const URLS = imports.urls;
 const Utils = imports.utils;
 
 // Matches coordinates string in 'Decimal Degrees' format
@@ -41,9 +42,6 @@ const DMS_COORDINATES_REGEX = new RegExp(
     "i"
 );
 
-// Matches URLs for OpenStreetMap (for addressing objects or coordinates)
-const OSM_URL_REGEX = new RegExp(/https?:\/\/(www\.)?openstreetmap\.org./);
-
 var Place = GObject.registerClass(
 class Place extends Geocode.Place {
 
@@ -396,24 +394,8 @@ let overpass = null;
  */
 const Application = imports.application;
 
-function _parseOSMPath(path) {
-    let parts = path.split('/');
-
-    if (parts.length === 2) {
-        let type = parts[0];
-        let id = parts[1];
-
-        if (type === 'node' || type === 'way' || type === 'relation')
-            return [type, id];
-        else
-            return [null, null];
-    } else {
-        return [null, null];
-    }
-}
-
-function _parseOSMObjectURL(path, callback) {
-    let [type, id] = _parseOSMPath(path);
+function parseHttpURL(text, callback) {
+    let [type, id] = URLS.parseAsObjectURL(text);
 
     if (type && id) {
         let storedPlace = Application.placeStore.existsWithOsmTypeAndId(type, id);
@@ -435,69 +417,21 @@ function _parseOSMObjectURL(path, callback) {
                 callback(null, _("Place not found in OpenStreetMap"));
         });
     } else {
-        callback(null, _("OpenStreetMap URL is not valid"));
-    }
-}
-
-function _parseOSMCoordParams(params, callback) {
-    let lat = params.lat;
-    let lon = params.lon;
-    let mlat = params.mlat;
-    let mlon = params.mlon;
-    let zoom = params.zoom;
-    let map = params['#map'];
+        let [lat, lon, zoom] = URLS.parseAsCoordinateURL(text);
 
-    if (map) {
-        let parts = map.split('/');
+        if (lat && lon) {
+            if (!Place.validateCoordinates(lat, lon)) {
+                callback(null, _("Coordinates in URL are not valid"));
+            } else {
+                let location = new Location.Location({ latitude: lat, longitude: lon });
+                let place = zoom ? new Place({ location: location, initialZoom: zoom }) :
+                                   new Place({ location: location });
 
-        if (parts.length !== 3) {
-            callback(null, _("OpenStreetMap URL is not valid"));
-            return;
+                callback(place, null);
+            }
         } else {
-            zoom = parseInt(parts[0]);
-            lat = parseFloat(parts[1]);
-            lon = parseFloat(parts[2]);
-        }
-    } else if (mlat && mlon) {
-        lat = parseFloat(mlat);
-        lon = parseFloat(mlon);
-    } else if (lat && lon) {
-        lat = parseFloat(lat);
-        lon = parseFloat(lon);
-    } else {
-        callback(null, _("OpenStreetMap URL is not valid"));
-        return;
-    }
-
-    if (!Place.validateCoordinates(lat, lon)) {
-        callback(null, _("Coordinates in URL are not valid"));
-        return;
-    }
-
-    let location = new Location.Location({ latitude: lat, longitude: lon });
-    let place = zoom ? new Place({ location: location, initialZoom: zoom }) :
-                       new Place({ location: location });
-
-    callback(place, null);
-}
-
-function parseHttpURL(text, callback) {
-    let match = text.match(OSM_URL_REGEX);
-
-    if (match) {
-        let uri = GLib.Uri.parse(text, GLib.UriFlags.NONE);
-        let path = uri.get_path();
-
-        if (path.length > 1) {
-            _parseOSMObjectPath(path, callback);
-        } else  {
-            let params = GLib.Uri.parse_params(uri.get_query(), -1, '&',
-                                               GLib.UriParamsFlags.NONE);
-
-            _parseOSMCoordParams(params, callback);
+            callback(null, _("URL is not supported"));
         }
-    } else {
-        callback(null, _("URL is not supported"));
     }
 }
 
diff --git a/src/placeEntry.js b/src/placeEntry.js
index 7be0aa04..732d3f0f 100644
--- a/src/placeEntry.js
+++ b/src/placeEntry.js
@@ -199,6 +199,15 @@ var PlaceEntry = GObject.registerClass({
             return false;
     }
 
+    /**
+     * Returns true if two locations are equal when rounded to displayes
+     * coordinate precision
+     */
+    _roundedLocEquals(locA, locB) {
+        return '%.5f, %.5f'.format(locA.latitude, locA.longitude) ===
+               '%.5f, %.5f'.format(locB.latitude, locB.longitude)
+    }
+
     _parse() {
         let parsed = false;
 
@@ -218,7 +227,14 @@ var PlaceEntry = GObject.registerClass({
 
         let parsedLocation = Place.Place.parseCoordinates(this.text);
         if (parsedLocation) {
-            this.place = new Place.Place({ location: parsedLocation });
+            /* if the place was a parsed OSM coordinate URL, it will have
+             * gotten re-written as bare coordinates and trigger a search-changed,
+             * in this case don't re-set the place, as it will loose the zoom
+             * level from the URL if set
+             */
+            if (!this.place ||
+                !this._roundedLocEquals(parsedLocation, this.place.location))
+                this.place = new Place.Place({ location: parsedLocation });
             parsed = true;
         }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]