Bug 627400 - Add location awareness support
Add location awareness support
Status: NEW
Product: folks
Classification: Platform
Component: libfolks
git master
Other Linux
: Normal enhancement
: Future
Assigned To: folks-maint
folks-maint
:
Depends on:
Blocks: 676015 658553
  Show dependency tree
 
Reported: 2010-08-19 18:09 UTC by Philip Withnall
Modified: 2013-02-20 14:38 UTC (History)
7 users (show)

See Also:
GNOME target: ---
GNOME version: ---


Attachments
infrastructure extensions + EDS (14.15 KB, patch)
2013-02-08 14:31 UTC, Patrick Ohly
needs-work Details | Diff | Review
revised solution, without EDS ContactGeo workaround (14.48 KB, patch)
2013-02-18 11:14 UTC, Patrick Ohly
needs-work Details | Diff | Review
revised comments (15.74 KB, patch)
2013-02-19 08:11 UTC, Patrick Ohly
committed Details | Diff | Review

Description Philip Withnall 2010-08-19 18:09:24 UTC
We need a location interface, so that an Individual can easily expose the locations of all its Personas.

See location_update() in empathy-individual-widget.c.
Comment 1 Philip Withnall 2010-09-13 13:54:24 UTC
(Mass changing milestones; please search for this phrase to delete the bug spam.)
Comment 2 Raul Gutierrez Segales 2011-09-08 13:08:16 UTC
e-d-s provides EContactGeo, so we can easily support this now.
Comment 3 Guillaume Desmottes 2011-12-02 14:51:43 UTC
Any progress on this? Having location API on FolksIndividual would make things easier in Empathy.
Comment 4 Travis Reitter 2011-12-02 22:42:38 UTC
(In reply to comment #3)
> Any progress on this? Having location API on FolksIndividual would make things
> easier in Empathy.

Nope, none to speak of.
Comment 5 Philip Withnall 2012-05-11 18:37:05 UTC
Timezone data would be good too (see: http://blogs.gnome.org/wjjt/2012/05/11/maps-and-clocks-and-contact-locations/).
Comment 6 Philip Withnall 2013-02-06 15:12:45 UTC
Just to note: in the EDS backend, this would be implemented using the GEO vCard property.
Comment 7 Patrick Ohly 2013-02-08 14:31:02 UTC
Created attachment 235511 [details] [review]
infrastructure extensions + EDS
Comment 8 Philip Withnall 2013-02-11 00:04:11 UTC
Review of attachment 235511 [details] [review]:

A good start. I think the Location API needs some more discussion.

::: backends/eds/lib/edsf-persona-store.vala
@@ +36,3 @@
+ * and typecase into E.ContactGeo -
+ * this is reasonably safe, because the struct is part of the
+ * EDS ABI and unlikely to change.

Is it possible to fix the EDS bindings? If so, can we have a bug number referenced here please?

s/typecase/typecast/

@@ +41,3 @@
+{
+        public double latitude;
+        public double longitude;

These should use 2-space indenting.

@@ +2247,3 @@
+      else
+        {
+          MyContactGeo? geo = new MyContactGeo();

Missing space before ‘()’.

@@ +2250,3 @@
+          geo.latitude = location.latitude;
+          geo.longitude = location.longitude;
+          contact.set (ContactField.GEO, (E.ContactGeo)geo);

Missing space after the typecast.

::: backends/eds/lib/edsf-persona.vala
@@ +2112,3 @@
+          if (this._location == null ||
+              this._location.latitude != _location.latitude ||
+              this._location.longitude != _location.longitude)

This (latitude != latitude || …) logic should be wrapped up in a Location.equal() method.

@@ +2117,3 @@
+                {
+                  this._location.latitude = _location.latitude;
+                  this._location.longitude = _location.longitude;

What’s the purpose of this? Why not create a new Location?

::: folks/individual.vala
@@ +2328,3 @@
+        }, (a, b) =>
+        {
+          /* TODO (?): pick the "better" location information. For now, pick more or less randomly. */

This should be implemented before the patch is committed.

@@ +2339,3 @@
+            }
+
+          if (new_location != this.location)

Does this comparison make sense? At the moment, I think it’s just a pointer comparison, so a notification will almost always be emitted, even if the coordinates are unchanged.

Perhaps the Location class should gain a ‘accuracy’ field which gives a radius around the latitude/longitude which contains the contact. A new ‘equal’ method on the Location class could then compare locations, returning true if their error circles overlapped?

::: folks/location-details.vala
@@ +22,3 @@
+
+/**
+ * A location. Typically latidue and longitude will

s/latidue/latitude/

@@ +32,3 @@
+{
+  /**
+   * The latitude.

These two fields need a ‘@since’ line each.

@@ +40,3 @@
+ public double longitude;
+
+ public Location(double latitude, double longitude)

This method needs documentation. Also missing a space before the opening ‘(’.

@@ +58,3 @@
+{
+  /**
+   * The current location of the contact.

Please add something stating what a null location value means.

@@ +65,3 @@
+
+  /**
+   * Change the contact's location.

Might want to rephrase this so it doesn’t sound like calling the method will teleport the person to somewhere new. :-P
Perhaps “Update the contact’s currently advertised location.”?

@@ +74,3 @@
+   * @param location the contact's location
+   * @throws PropertyError if setting the location failed
+   * @since 0.6.2

0.6.2? :-)

@@ +80,3 @@
+      /* Default implementation. */
+      throw new PropertyError.NOT_WRITEABLE (
+          _("Location is not writeable on this contact."));

This file needs listing in POTFILES.in because of the translatable string.
Comment 9 Patrick Ohly 2013-02-18 11:14:03 UTC
Created attachment 236576 [details] [review]
revised solution, without EDS ContactGeo workaround

(In reply to comment #8)
> ::: backends/eds/lib/edsf-persona-store.vala
> @@ +36,3 @@
> + * and typecase into E.ContactGeo -
> + * this is reasonably safe, because the struct is part of the
> + * EDS ABI and unlikely to change.
> 
> Is it possible to fix the EDS bindings? If so, can we have a bug number
> referenced here please?

I submitted a fix which was included in EDS master. As you depend on that in 0.9.x already, I removed the MyContactGeo workaround.

> @@ +2117,3 @@
> +                {
> +                  this._location.latitude = _location.latitude;
> +                  this._location.longitude = _location.longitude;
> 
> What’s the purpose of this? Why not create a new Location?

Performance and memory fragmentation. I need to write the two values either way, so why should I allocate a completely new instance? I've added comment in the code to explain that.

> ::: folks/individual.vala
> @@ +2328,3 @@
> +        }, (a, b) =>
> +        {
> +          /* TODO (?): pick the "better" location information. For now, pick
> more or less randomly. */
> 
> This should be implemented before the patch is committed.

As discussed before, this is a bit out of scope for me ATM. I hope that's okay.

One would have to look at other sources for location to determine how folks should choose the latest value, and how often it should update.

> @@ +2339,3 @@
> +            }
> +
> +          if (new_location != this.location)
> 
> Does this comparison make sense? At the moment, I think it’s just a pointer
> comparison, so a notification will almost always be emitted, even if the
> coordinates are unchanged.

The comparison detects when a location gets added or removed. I've also added a check for the actual value changes.

> Perhaps the Location class should gain a ‘accuracy’ field which gives a radius
> around the latitude/longitude which contains the contact. A new ‘equal’ method
> on the Location class could then compare locations, returning true if their
> error circles overlapped?

This is part of the questions which still need to be determined. Is it worth updating the location if the contact only moved a few centimeters? I don't know.

At the moment, the only source of location information is EDS, and there every update is assumed to be intentional and thus applied to the persona and individual.

> @@ +32,3 @@
> +{
> +  /**
> +   * The latitude.
> 
> These two fields need a ‘@since’ line each.

Really? The whole class is new and has a "@since UNRELEASED" remark (in the new revision of the patch). To avoid chatter, I've not added that remark to members.

> @@ +65,3 @@
> +
> +  /**
> +   * Change the contact's location.
> 
> Might want to rephrase this so it doesn’t sound like calling the method will
> teleport the person to somewhere new. :-P

Heh, wouldn't that be neat? :-)

> Perhaps “Update the contact’s currently advertised location.”?

Done. As in the constructor, I mentioned that null means "removing location".
Comment 10 Philip Withnall 2013-02-18 13:27:27 UTC
Review of attachment 236576 [details] [review]:

Lots of minor changes. Sorry to be picky.

> This is part of the questions which still need to be determined. Is it worth
> updating the location if the contact only moved a few centimeters? I don't
> know.
>
> At the moment, the only source of location information is EDS, and there every
> update is assumed to be intentional and thus applied to the persona and
> individual.

I think a reasonable policy would be for backends to determine whether incoming location changes are intentional or not (so for EDS, all changes are intentional, even if they’re only a few cm; for a backend which uses location from GPS, only larger changes should be considered intentional), and for the backends themselves to only update a persona’s location on _intentional_ location changes. Individual should then update its location whenever any of its personas’ locations change (so no intentional/unintentional update policy is applied in the Individual code). It would be good to get this documented in the code, e.g. in individual.vala’s _update_location().

::: backends/eds/lib/edsf-persona.vala
@@ +2138,3 @@
+        {
+          if (this._location == null ||
+              !this._location.equal_coordinates(_geo.latitude, _geo.longitude))

Missing space before ‘(’.

Would be useful to add a comment explaining that we assume every change to GEO is intentional, and thus always notify of it. (As opposed to, e.g., in a backend where location comes from some noisy source like GPS, where the backend would have to filter out unintentional location changes.)

@@ +2149,3 @@
+              else
+                {
+                  this._location = new Location(_geo.latitude, _geo.longitude);

Missing space before ‘(’.

::: folks/individual.vala
@@ +2329,3 @@
+        }, (a, b) =>
+        {
+          /* TODO (?): pick the "better" location information. For now, pick more or less randomly. */

Hmm. I guess this is OK to leave for now, but please add a reference to this bug report.

@@ +2340,3 @@
+            }
+
+          if (new_location != this.location /* adding or removing a location? */ ||

This will produce spurious change notifications in the case the pointers are different but latitude and longitude are unchanged. How about:
   (new_location == null) != (this._location == null)

::: folks/location-details.vala
@@ +32,3 @@
+{
+  /**
+   * The latitude.

As mentioned on IRC, it’s useful to be explicit about the ‘@since’ entries on *every* piece of API documentation.

@@ +41,3 @@
+
+ /**
+  * Constructs a new instance with the given coordinates.

Missing ‘@param latitude …’ and ‘@param longitude …’.

@@ +50,3 @@
+
+ /**
+  * Strict comparison (= floats must be exactly the same).

That isn’t very clear to me. How about “Compare this location to another by geographical position, returning ``true`` iff the latitude and longitude match exactly.”.

Also needs a ‘@param other …’ line and a @return line.

@@ +52,3 @@
+  * Strict comparison (= floats must be exactly the same).
+  */
+ public bool equal(Location other)

Missing space before ‘(’.

@@ +59,3 @@
+
+ /**
+  * Strict comparison (= floats must be exactly the same).

Again, this documentation isn’t very clear to me and is missing @param lines and a @return line.

Also, the above three documentation comments have indentation problems (need to be indented further by 1 space).

@@ +61,3 @@
+  * Strict comparison (= floats must be exactly the same).
+  */
+  public bool equal_coordinates(double latitude, double longitude)

Missing space before ‘(’.

@@ +80,3 @@
+  /**
+   * The current location of the contact. Null if not
+   * set.

How about “Null if the contact’s current location isn’t known, or they’re keeping it private.”.
Comment 11 Patrick Ohly 2013-02-19 08:11:21 UTC
Created attachment 236728 [details] [review]
revised comments

(In reply to comment #10)
> Lots of minor changes. Sorry to be picky.

No problem. It's worth getting this right.

I'm not a fan of documenting every single parameter and return value just for the sake of it. It's a slippery slope which leads to useless comments which just repeat the parameter name without adding further information. Anyway, I've added it to the updated patch.

> > This is part of the questions which still need to be determined. Is it worth
> > updating the location if the contact only moved a few centimeters? I don't
> > know.
> >
> > At the moment, the only source of location information is EDS, and there every
> > update is assumed to be intentional and thus applied to the persona and
> > individual.
> 
> I think a reasonable policy would be for backends to determine whether incoming
> location changes are intentional or not (so for EDS, all changes are
> intentional, even if they’re only a few cm; for a backend which uses location
> from GPS, only larger changes should be considered intentional), and for the
> backends themselves to only update a persona’s location on _intentional_
> location changes. Individual should then update its location whenever any of
> its personas’ locations change (so no intentional/unintentional update policy
> is applied in the Individual code). It would be good to get this documented in
> the code, e.g. in individual.vala’s _update_location().

I decided to put that into LocationDetails instead, because knowing how folks behaves is relevant for users of it.
Comment 12 Philip Withnall 2013-02-20 00:29:19 UTC
Review of attachment 236728 [details] [review]:

Looks good. Please fix the few tiny issues below and commit directly to master. Thanks!

> I'm not a fan of documenting every single parameter and return value just for
> the sake of it. It's a slippery slope which leads to useless comments which
> just repeat the parameter name without adding further information. Anyway, I've
> added it to the updated patch.

I know what you mean. I guess the argument for documenting every single parameter and return value is that it means warnings and errors from valadoc are useful; and you won’t miss warnings about missing documentation for _important_ parameters. Thanks for adding it.

> I decided to put that into LocationDetails instead, because knowing how folks
> behaves is relevant for users of it.

Good idea.

::: folks/individual.vala
@@ +581,3 @@
     }
 
+  private Location _location = null;

This needs to have nullable type ‘Location?’ rather than just ‘Location’.

@@ +1860,3 @@
       persona.notify["local-ids"].connect
           (this._notify_local_ids_cb);
+      persona.notify["location"].connect (this._notify_location_cb);

Need to add an equivalent disconnect() in _disconnect_from_persona().

@@ +2341,3 @@
+
+          if ((new_location == null) != (this.location == null) /* adding or removing a location? */ ||
+              new_location != null && !new_location.equal(this.location) /* different value? */)

Another missing space before the ’(’.
Comment 13 Patrick Ohly 2013-02-20 14:30:25 UTC
Comment on attachment 236728 [details] [review]
revised comments

Committed including the fixes for the latest comment.

Note You need to log in before you can comment on or make changes to this bug.