File Add-DBus-API-for-adding-contact-with-preset-properties.patch of Package gnome-contacts-42.0-1.25

From: Julian Sparber <julian@sparber.net>
Date: Thu, 24 Oct 2019 10:30:09 +0200
Subject: Add DBus API for adding contact with preset properties

The API takes an array of (key, value) pairs.

Supported keys:

These can be specified multiple times:
  "email-addresses", "notes", "phone-numbers"

Only the last will be stored (because this properies are unique):
"alias", "full-name", "nickname"

Not all properites are supported for now because they can't be easily
set via DBus because they arn't a string

Example DBus usage:

gdbus call --session --dest org.gnome.Contacts --object-path  /org/gnome/Contacts --method org.gtk.Actions.Activate 'new-contact-data' '[<[("email-addresses", "julian@sparber.net"), ("phone-numbers", "+39333333"), ("email-addresses", "secondo@example.com")]>]' '{}'

Upstream: https://gitlab.gnome.org/GNOME/gnome-contacts/-/merge_requests/95
---
 data/ui/contacts-main-window.ui |  4 +--
 src/contacts-app.vala           | 65 +++++++++++++++++++++++++++++++++++++++++
 src/contacts-contact-pane.vala  |  3 +-
 src/contacts-main-window.vala   |  6 ++--
 4 files changed, 71 insertions(+), 7 deletions(-)

diff --git a/data/ui/contacts-main-window.ui b/data/ui/contacts-main-window.ui
index 41b99e8..17709e1 100644
--- a/data/ui/contacts-main-window.ui
+++ b/data/ui/contacts-main-window.ui
@@ -52,7 +52,7 @@
         <child>
           <object class="GtkShortcut">
             <property name="trigger">&lt;Control&gt;n</property>
-            <property name="action">action(window.new-contact)</property>
+            <property name="action">action(app.new-contact)</property>
           </object>
         </child>
       </object>
@@ -81,7 +81,7 @@
                           <object class="GtkButton" id="add_button">
                             <property name="tooltip-text" translatable="yes">Create new contact</property>
                             <property name="icon-name">list-add-symbolic</property>
-                            <property name="action-name">window.new-contact</property>
+                            <property name="action-name">app.new-contact</property>
                           </object>
                         </child>
 
diff --git a/src/contacts-app.vala b/src/contacts-app.vala
index d241830..019241f 100644
--- a/src/contacts-app.vala
+++ b/src/contacts-app.vala
@@ -15,6 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+using Gee;
 using Folks;
 
 public class Contacts.App : Adw.Application {
@@ -30,6 +31,8 @@ public class Contacts.App : Adw.Application {
     { "about",            show_about          },
     { "change-book",      change_address_book },
     { "online-accounts",  online_accounts     },
+    { "new-contact",      on_new_contact      },
+    { "new-contact-data", on_new_contact,  "a(ss)" },
     { "show-contact",     on_show_contact, "s"}
   };
 
@@ -290,6 +293,68 @@ public class Contacts.App : Adw.Application {
     setup_window.show ();
   }
 
+  private void on_new_contact (SimpleAction action, Variant? param) {
+    HashTable<string, Value?> details = null;
+    if (param != null)
+      details = array_to_details (param);
+
+    if (window == null)
+      create_window ();
+
+     window.present ();
+     window.new_contact (details);
+  }
+
+  private void add_field_details<T> (HashTable<string, Value?> details, string key, string value) {
+    var val = details.get(key);
+    Set<T> current = (val != null) ? (Set<T>) details.get(key): null;
+
+    if (current == null) {
+      current = new HashSet<T> ();
+      details.set (key, current);
+    }
+    // WORKAROUND: This is a workaround for https://gitlab.gnome.org/GNOME/vala/issues/871
+    var obj = Object.new (typeof (T),
+                          "t-type", typeof(string),
+                          "t-dup-func", string.dup,
+                          "t-destroy-func", free,
+                          "value", value);
+    current.add (obj);
+  }
+
+  /* This converts a array of (key, value) to HashTable details expected by folks */
+  /* Todo: implement all property, currently only a couple of properties can be set via dbus */
+  private HashTable<string, Value?> array_to_details (Variant param) {
+    var details = new HashTable<string, Value?> (str_hash, str_equal);
+    foreach (Variant item in param) {
+      string? key = item.get_child_value(0) as string;
+      string? value = item.get_child_value(1) as string;
+      if (key == null || value == null)
+        continue;
+
+      switch (key) {
+        case "alias":
+        case "full-name":
+        case "nickname":
+          details.set (key, value);
+          break;
+        case "email-addresses":
+          add_field_details<EmailFieldDetails> (details, key, value);
+          break;
+        case "notes":
+          add_field_details<NoteFieldDetails> (details, key, value);
+          break;
+        case "phone-numbers":
+          add_field_details<PhoneFieldDetails> (details, key, value);
+          break;
+        default:
+          warning ("Not implemented or unknown property '%s'", key);
+          break;
+      }
+    }
+    return details;
+  }
+
   private void on_show_contact(SimpleAction action, Variant? param) {
     activate();
 
diff --git a/src/contacts-contact-pane.vala b/src/contacts-contact-pane.vala
index 9726216..f1e2d12 100644
--- a/src/contacts-contact-pane.vala
+++ b/src/contacts-contact-pane.vala
@@ -204,8 +204,7 @@ public class Contacts.ContactPane : Adw.Bin {
     start_editing ();
   }
 
-  public void new_contact () {
-    var details = new HashTable<string, Value?> (str_hash, str_equal);
+  public void new_contact (HashTable<string, Value?> details) {
     string[] writeable_properties;
     // TODO: make sure we have a primary_store
     if (this.store.aggregator.primary_store != null) {
diff --git a/src/contacts-main-window.vala b/src/contacts-main-window.vala
index 4750f53..ce54571 100644
--- a/src/contacts-main-window.vala
+++ b/src/contacts-main-window.vala
@@ -22,7 +22,6 @@ using Folks;
 public class Contacts.MainWindow : Adw.ApplicationWindow {
 
   private const GLib.ActionEntry[] ACTION_ENTRIES = {
-    { "new-contact", new_contact },
     { "edit-contact", edit_contact },
     // { "share-contact", share_contact },
     { "unlink-contact", unlink_contact },
@@ -333,7 +332,7 @@ public class Contacts.MainWindow : Adw.ApplicationWindow {
     }
   }
 
-  public void new_contact (GLib.SimpleAction action, GLib.Variant? parameter) {
+  public void new_contact (HashTable<string, Value?>? details = null) {
     if (this.state == UiState.UPDATING || this.state == UiState.CREATING)
       return;
 
@@ -343,7 +342,8 @@ public class Contacts.MainWindow : Adw.ApplicationWindow {
 
     this.right_header.title_widget = new Adw.WindowTitle (_("New Contact"), "");
 
-    this.contact_pane.new_contact ();
+    this.contact_pane.new_contact (
+      (details != null) ? details: new HashTable<string, Value?> (str_hash, str_equal));
     show_contact_pane ();
   }
 
openSUSE Build Service is sponsored by