[gnome-contacts/feature/open-map-button: 2/2] sheet: Add button to open a contact's address




commit 3b1675be1c67407ee8ade0413d356e0f57319a0f
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Wed Jan 12 13:16:46 2022 +0100

    sheet: Add button to open a contact's address
    
    This commit adds the ability for the user to open up GNOME Maps (or any
    application that registers itself as a URI handler for "maps:" URIs) to
    the specified location.
    
    We do this by creating a "maps:" URI which takes the (encoded form of
    the) address as a parameter. If there is one result, the maps
    application can show it; if there are more, they can provide the user
    with a list of selections.
    
    Successfully tested that this works with GNOME Maps' nightly flatpak.
    
    See also: https://gitlab.gnome.org/GNOME/gnome-maps/-/merge_requests/199
    
    Fixes: https://gitlab.gnome.org/GNOME/gnome-contacts/-/issues/87

 data/contacts.gresource.xml     |  1 +
 data/icons/map-symbolic.svg     |  4 ++++
 src/contacts-contact-sheet.vala | 20 +++++++++++++++++
 src/contacts-utils.vala         | 50 +++++++++++------------------------------
 4 files changed, 38 insertions(+), 37 deletions(-)
---
diff --git a/data/contacts.gresource.xml b/data/contacts.gresource.xml
index 20343b5f..fbe88459 100644
--- a/data/contacts.gresource.xml
+++ b/data/contacts.gresource.xml
@@ -7,6 +7,7 @@
     <file preprocess="xml-stripblanks">icons/external-link-symbolic.svg</file>
     <file preprocess="xml-stripblanks">icons/note-symbolic.svg</file>
     <file preprocess="xml-stripblanks">icons/photo-camera-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/map-symbolic.svg</file>
 
     <file compressed="true" preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/contacts-accounts-list.ui</file>
diff --git a/data/icons/map-symbolic.svg b/data/icons/map-symbolic.svg
new file mode 100644
index 00000000..2a513ae3
--- /dev/null
+++ b/data/icons/map-symbolic.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg";>
+    <path d="m 15 2 v 10 l -5 3 l -5 -3 l -5 3 v -10 l 5 -3 l 5 3 z m -10 1 v 8 l 5 3 v -8 z m 0 0" 
fill="#2e3436"/>
+</svg>
diff --git a/src/contacts-contact-sheet.vala b/src/contacts-contact-sheet.vala
index 43aae398..88d414a4 100644
--- a/src/contacts-contact-sheet.vala
+++ b/src/contacts-contact-sheet.vala
@@ -356,6 +356,11 @@ public class Contacts.ContactSheet : Gtk.Grid {
     if (addr_details == null)
       return;
 
+    // Check outside of the loop if we have a "maps:" URI handler
+    var appinfo = AppInfo.get_default_for_uri_scheme ("maps");
+    var map_uris_supported = (appinfo != null);
+    debug ("Opening 'maps:' URIs supported: %s", map_uris_supported.to_string ());
+
     foreach (var addr in addr_details.postal_addresses) {
       if (addr.value.is_empty ())
         continue;
@@ -363,6 +368,21 @@ public class Contacts.ContactSheet : Gtk.Grid {
       var row = new ContactSheetRow (property,
                                      string.joinv ("\n", Utils.format_address (addr.value)),
                                      TypeSet.general.format_type (addr));
+
+      if (map_uris_supported) {
+        var button = row.add_button ("map-symbolic");
+        button.tooltip_text = _("Show on the map");
+        button.clicked.connect (() => {
+          unowned var window = button.get_root () as MainWindow;
+          if (window == null)
+            return;
+
+          var uri = Utils.create_maps_uri (addr.value);
+          // FIXME: use show_uri_full so we can show errors
+          Gtk.show_uri (window, uri, Gdk.CURRENT_TIME);
+        });
+      }
+
       this.attach_row (row);
     }
   }
diff --git a/src/contacts-utils.vala b/src/contacts-utils.vala
index 667c6911..fd8196d2 100644
--- a/src/contacts-utils.vala
+++ b/src/contacts-utils.vala
@@ -25,43 +25,6 @@ namespace Contacts {
   public void add_separator (Gtk.ListBoxRow row, Gtk.ListBoxRow? before_row) {
     row.set_header (new Gtk.Separator (Gtk.Orientation.HORIZONTAL));
   }
-
-  [DBus (name = "org.freedesktop.Application")]
-  interface FreedesktopApplication : Object {
-    [DBus (name = "ActivateAction")]
-    public abstract void ActivateAction (string action,
-                                         Variant[] parameter,
-                                         HashTable<string, Variant> data) throws Error;
-  }
-
-  public void activate_action (string app_id,
-                               string action,
-                               Variant? parameter,
-                               uint32 timestamp) {
-    FreedesktopApplication? con = null;
-
-    try {
-      string object_path = "/" + app_id.replace(".", "/");
-      Gdk.Display display = Gdk.Display.get_default ();
-      DesktopAppInfo info = new DesktopAppInfo (app_id + ".desktop");
-      Gdk.AppLaunchContext context = display.get_app_launch_context ();
-
-      con = Bus.get_proxy_sync (BusType.SESSION, app_id, object_path);
-      context.set_timestamp (timestamp);
-
-      Variant[] param_array = {};
-      if (parameter != null)
-        param_array += parameter;
-
-      var startup_id = context.get_startup_notify_id (info,
-                                                      new GLib.List<File>());
-      var data = new HashTable<string, Variant>(str_hash, str_equal);
-      data.insert ("desktop-startup-id", new Variant.string (startup_id));
-      con.ActivateAction (action, param_array, data);
-    } catch (Error e) {
-      debug ("Failed to activate action '%s': %s", action, e.message);
-    }
-  }
 }
 
 namespace Contacts.Utils {
@@ -322,6 +285,19 @@ namespace Contacts.Utils {
     return lines;
   }
 
+  /**
+   * Takes an individual's postal address and creates a "maps:q=..." URI for
+   * it, which can be launched to use the local system's maps handler
+   * (e.g. GNOME Maps).
+   *
+   * See also https://www.iana.org/assignments/uri-schemes/prov/maps for the
+   * "specification"
+   */
+  public string create_maps_uri (PostalAddress address) {
+    var address_parts = string.joinv (" ", Utils.format_address (address));
+    return "maps:q=%s".printf (GLib.Uri.escape_string (address_parts));
+  }
+
 #if HAVE_TELEPATHY
   public Tpf.Persona? find_im_persona (Individual individual, string protocol, string im_address) {
     var iid = protocol + ":" + im_address;


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