~ubuntu-branches/ubuntu/trusty/gnome-contacts/trusty

« back to all changes in this revision

Viewing changes to src/contacts-app.vala

  • Committer: Package Import Robot
  • Author(s): Michael Biebl, Jeremy Bicha, Michael Biebl
  • Date: 2013-09-19 18:23:06 UTC
  • mfrom: (1.3.10) (0.3.4 experimental)
  • mto: This revision was merged to the branch mainline in revision 40.
  • Revision ID: package-import@ubuntu.com-20130919182306-rcatwotzg94pr884
Tags: 3.8.3-1
[ Jeremy Bicha ]
* debian/control.in:
  - Drop alternate build-depends on valac-0.18 since it's no longer
    in Debian

[ Michael Biebl ]
* New upstream release.
* Loosen Build-Depends on libgnome-desktop-3-dev, we do not strictly require
  version (>= 3.6.0) which is not yet available in unstable.
* Bump Standards-Version to 3.9.4. No further changes.
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
17
 */
18
18
 
 
19
using Gee;
19
20
using Gtk;
20
21
using Folks;
21
22
 
22
23
public class Contacts.App : Gtk.Application {
 
24
  public static App app;
23
25
  public GLib.Settings settings;
 
26
  public Store contacts_store;
 
27
 
24
28
  public Contacts.Window window;
25
 
  public static App app;
26
 
  public Store contacts_store;
 
29
  private Gtk.Overlay overlay;
 
30
 
 
31
  private Gd.MainToolbar left_toolbar;
 
32
  private ToggleButton select_button;
27
33
  private ListPane list_pane;
 
34
 
 
35
  private Toolbar right_toolbar;
 
36
  private Label contact_name;
 
37
  private Button edit_button;
 
38
  private Button done_button;
 
39
 
28
40
  private ContactPane contacts_pane;
29
 
  private Gtk.Overlay overlay;
 
41
  private Overlay right_overlay;
30
42
 
31
43
  private bool window_delete_event (Gdk.EventAny event) {
32
44
    // Clear the contacts so any changed information is stored
36
48
 
37
49
  private bool window_key_press_event (Gdk.EventKey event) {
38
50
    if ((event.keyval == Gdk.keyval_from_name ("q")) &&
39
 
        ((event.state & Gdk.ModifierType.CONTROL_MASK) != 0)) {
 
51
        ((event.state & Gdk.ModifierType.CONTROL_MASK) != 0)) {
40
52
      // Clear the contacts so any changed information is stored
41
53
      contacts_pane.show_contact (null);
42
54
      window.destroy ();
43
55
    } else if (((event.keyval == Gdk.Key.s) ||
44
 
                (event.keyval == Gdk.Key.f)) &&
45
 
               ((event.state & Gdk.ModifierType.CONTROL_MASK) != 0)) {
46
 
      list_pane.set_search_visible (true);
 
56
                (event.keyval == Gdk.Key.f)) &&
 
57
               ((event.state & Gdk.ModifierType.CONTROL_MASK) != 0)) {
 
58
      Utils.grab_entry_focus_no_select (list_pane.filter_entry);
47
59
    } else if (event.length >= 1 &&
48
 
               Gdk.keyval_to_unicode (event.keyval) != 0 &&
49
 
               (event.state & Gdk.ModifierType.CONTROL_MASK) == 0 &&
50
 
               (event.state & Gdk.ModifierType.MOD1_MASK) == 0 &&
51
 
               (event.keyval != Gdk.Key.Escape) &&
52
 
               (event.keyval != Gdk.Key.Tab) &&
53
 
               (event.keyval != Gdk.Key.BackSpace) ) {
54
 
      list_pane.set_search_visible (true);
 
60
               Gdk.keyval_to_unicode (event.keyval) != 0 &&
 
61
               (event.state & Gdk.ModifierType.CONTROL_MASK) == 0 &&
 
62
               (event.state & Gdk.ModifierType.MOD1_MASK) == 0 &&
 
63
               (event.keyval != Gdk.Key.Escape) &&
 
64
               (event.keyval != Gdk.Key.Tab) &&
 
65
               (event.keyval != Gdk.Key.BackSpace) ) {
 
66
      Utils.grab_entry_focus_no_select (list_pane.filter_entry);
55
67
      window.propagate_key_event (event);
56
68
    }
57
69
 
59
71
  }
60
72
 
61
73
  private void selection_changed (Contact? new_selection) {
62
 
    contacts_pane.show_contact (new_selection);
 
74
    /* FIXME: ask the user lo teave edit-mode and act accordingly */
 
75
    if (contacts_pane.on_edit_mode) {
 
76
      contacts_pane.set_edit_mode (false);
 
77
 
 
78
      contact_name.set_text (null);
 
79
      done_button.hide ();
 
80
    }
 
81
 
 
82
    contacts_pane.show_contact (new_selection, false, false);
 
83
 
 
84
    /* clearing right_toolbar */
 
85
    if (new_selection != null) {
 
86
      edit_button.show ();
 
87
    } else {
 
88
      edit_button.hide ();
 
89
    }
63
90
  }
64
91
 
65
92
  public void show_contact (Contact? contact) {
66
93
    list_pane.select_contact (contact);
67
 
    contacts_pane.show_contact (contact);
 
94
 
 
95
    /* hack for showing contact */
 
96
    selection_changed (contact);
68
97
  }
69
98
 
70
99
  public async void show_individual (string id) {
71
100
    var contact = yield contacts_store.find_contact ( (c) => {
72
 
        return c.individual.id == id;
 
101
        return c.individual.id == id;
73
102
      });
74
103
    if (contact != null) {
75
104
      list_pane.select_contact (contact);
76
105
      contacts_pane.show_contact (contact);
77
106
    } else {
78
107
      var dialog = new MessageDialog (App.app.window, DialogFlags.DESTROY_WITH_PARENT, MessageType.ERROR, ButtonsType.CLOSE,
79
 
                                      _("No contact with id %s found"), id);
 
108
                                      _("No contact with id %s found"), id);
80
109
      dialog.set_title(_("Contact not found"));
81
110
      dialog.show ();
82
111
      dialog.response.connect ( (id) => {
83
 
          dialog.destroy ();
84
 
        });
 
112
          dialog.destroy ();
 
113
        });
85
114
    }
86
115
  }
87
116
 
88
117
  public void change_address_book () {
89
118
    var title = _("Change Address Book");
90
119
    var dialog = new Dialog.with_buttons ("",
91
 
                                          (Window) window,
92
 
                                          DialogFlags.MODAL | DialogFlags.DESTROY_WITH_PARENT,
93
 
                                          Stock.CANCEL, ResponseType.CANCEL,
94
 
                                          _("Select"), ResponseType.OK);
 
120
                                          (Window) window,
 
121
                                          DialogFlags.MODAL | DialogFlags.DESTROY_WITH_PARENT,
 
122
                                          Stock.CANCEL, ResponseType.CANCEL,
 
123
                                          _("Select"), ResponseType.OK);
95
124
 
96
125
    dialog.set_resizable (false);
97
126
    dialog.set_default_response (ResponseType.OK);
133
162
 
134
163
    TreeIter iter;
135
164
 
136
 
    foreach (var persona_store in Contact.get_eds_address_books ()) {
 
165
    foreach (var persona_store in get_eds_address_books ()) {
137
166
      var name = Contact.format_persona_store_name (persona_store);
138
167
      store.append (out iter);
139
168
      store.set (iter, 0, name, 1, persona_store);
140
169
      if (persona_store == contacts_store.aggregator.primary_store) {
141
 
        tree_view.get_selection ().select_iter (iter);
 
170
        tree_view.get_selection ().select_iter (iter);
142
171
      }
143
172
    }
144
173
 
145
174
    dialog.show_all ();
146
175
    dialog.response.connect ( (response) => {
147
 
        if (response == ResponseType.OK) {
148
 
          PersonaStore selected_store;
149
 
          TreeIter iter2;
150
 
 
151
 
          if (tree_view.get_selection() .get_selected (null, out iter2)) {
152
 
            store.get (iter2, 1, out selected_store);
153
 
 
154
 
            var e_store = selected_store as Edsf.PersonaStore;
155
 
 
156
 
            try {
157
 
              E.BookClient.set_default_source (e_store.source);
158
 
            } catch {
159
 
              warning ("Failed to set address book");
160
 
            }
161
 
 
162
 
            contacts_store.refresh ();
163
 
          }
164
 
        }
165
 
        dialog.destroy ();
 
176
        if (response == ResponseType.OK) {
 
177
          PersonaStore selected_store;
 
178
          TreeIter iter2;
 
179
 
 
180
          if (tree_view.get_selection() .get_selected (null, out iter2)) {
 
181
            store.get (iter2, 1, out selected_store);
 
182
 
 
183
            var e_store = selected_store as Edsf.PersonaStore;
 
184
 
 
185
            eds_source_registry.set_default_address_book (e_store.source);
 
186
 
 
187
            contacts_store.refresh ();
 
188
          }
 
189
        }
 
190
        dialog.destroy ();
166
191
      });
167
192
  }
168
193
 
 
194
  public void show_help () {
 
195
    Gtk.show_uri (window.get_screen (),
 
196
         "help:gnome-help/contacts",
 
197
         Gtk.get_current_event_time ());
 
198
  }
 
199
 
169
200
  public void show_about () {
170
201
    string[] authors = {
171
202
      "Alexander Larsson <alexl@redhat.com>",
175
206
      "Allan Day <allanpday@gmail.com>"
176
207
    };
177
208
    Gtk.show_about_dialog (window,
178
 
                           "artists", artists,
179
 
                           "authors", authors,
180
 
                           "translator-credits", _("translator-credits"),
181
 
                           "program-name", _("GNOME Contacts"),
182
 
                           "title", _("About GNOME Contacts"),
183
 
                           "comments", _("Contact Management Application"),
184
 
                           "copyright", "Copyright 2011 Red Hat, Inc.",
185
 
                           "license-type", Gtk.License.GPL_2_0,
186
 
                           "logo-icon-name", "x-office-address-book",
187
 
                           "version", Config.PACKAGE_VERSION,
188
 
                           "website", "https://live.gnome.org/Contacts",
189
 
                           "wrap-license", true);
 
209
                           "artists", artists,
 
210
                           "authors", authors,
 
211
                           "translator-credits", _("translator-credits"),
 
212
                           "program-name", _("GNOME Contacts"),
 
213
                           "title", _("About GNOME Contacts"),
 
214
                           "comments", _("Contact Management Application"),
 
215
                           "copyright", "Copyright 2011 Red Hat, Inc.",
 
216
                           "license-type", Gtk.License.GPL_2_0,
 
217
                           "logo-icon-name", "x-office-address-book",
 
218
                           "version", Config.PACKAGE_VERSION,
 
219
                           "website", "https://live.gnome.org/Contacts",
 
220
                           "wrap-license", true);
190
221
  }
191
222
 
192
223
  public async void show_by_email (string email_address) {
193
224
    var contact = yield contacts_store.find_contact ( (c) => {
194
 
        return c.has_email (email_address);
 
225
        return c.has_email (email_address);
195
226
      });
196
227
    if (contact != null) {
197
228
      list_pane.select_contact (contact);
198
229
      contacts_pane.show_contact (contact);
199
230
    } else {
200
231
      var dialog = new MessageDialog (App.app.window, DialogFlags.DESTROY_WITH_PARENT, MessageType.ERROR, ButtonsType.CLOSE,
201
 
                                      _("No contact with email address %s found"), email_address);
 
232
                                      _("No contact with email address %s found"), email_address);
202
233
      dialog.set_title(_("Contact not found"));
203
234
      dialog.show ();
204
235
      dialog.response.connect ( (id) => {
205
 
          dialog.destroy ();
206
 
        });
 
236
          dialog.destroy ();
 
237
        });
207
238
    }
208
239
  }
209
240
 
212
243
    action.activate.connect (() => { window.destroy (); });
213
244
    this.add_action (action);
214
245
 
 
246
    action = new GLib.SimpleAction ("help", null);
 
247
    action.activate.connect (() => { show_help (); });
 
248
    this.add_action (action);
 
249
    this.add_accelerator ("F1", "app.help", null);
 
250
 
215
251
    action = new GLib.SimpleAction ("about", null);
216
252
    action.activate.connect (() => { show_about (); });
217
253
    this.add_action (action);
220
256
    action.activate.connect (() => { change_address_book (); });
221
257
    this.add_action (action);
222
258
 
 
259
    action = new GLib.SimpleAction ("new_contact", null);
 
260
    action.activate.connect (() => { new_contact (); });
 
261
    this.add_action (action);
 
262
    this.add_accelerator ("<Primary>n", "app.new_contact", null);
 
263
 
 
264
    var view_action = new GLib.SimpleAction.stateful ("view_subset", VariantType.STRING, settings.get_value ("view-subset"));
 
265
    this.add_action (view_action);
 
266
    settings.changed["view-subset"].connect (() => {
 
267
        view_action.set_state (settings.get_value ("view-subset"));
 
268
        list_pane.refilter ();
 
269
      });
 
270
    view_action.activate.connect ((act, parameter) => {
 
271
        settings.set_value ("view-subset", parameter);
 
272
      });
 
273
 
223
274
    var builder = new Builder ();
224
275
    builder.set_translation_domain (Config.GETTEXT_PACKAGE);
225
276
    try {
232
283
    window = new Contacts.Window (this);
233
284
    window.set_application (this);
234
285
    window.set_title (_("Contacts"));
235
 
    window.set_default_size (888, 600);
 
286
    window.set_default_size (800, 600);
236
287
    window.hide_titlebar_when_maximized = true;
237
288
    window.delete_event.connect (window_delete_event);
238
289
    window.key_press_event.connect_after (window_key_press_event);
239
290
 
240
291
    var grid = new Grid();
241
292
 
242
 
    var toolbar = new Toolbar ();
243
 
    toolbar.set_icon_size (IconSize.MENU);
244
 
    toolbar.get_style_context ().add_class (STYLE_CLASS_MENUBAR);
245
 
    toolbar.get_style_context ().add_class ("contacts-left-toolbar");
246
 
    toolbar.set_vexpand (false);
247
 
    toolbar.set_hexpand (false);
248
 
    grid.attach (toolbar, 0, 0, 1, 1);
249
 
 
250
 
    var add_button = new ToolButton (null, _("New"));
251
 
    add_button.margin_left = 4;
252
 
    add_button.is_important = true;
253
 
    toolbar.add (add_button);
254
 
    add_button.clicked.connect ( (button) => {
255
 
        var dialog = new NewContactDialog (contacts_store, window);
256
 
        dialog.show_all ();
257
 
      });
258
 
 
259
 
    toolbar = new Toolbar ();
260
 
    toolbar.set_icon_size (IconSize.MENU);
261
 
    toolbar.get_style_context ().add_class (STYLE_CLASS_MENUBAR);
262
 
    toolbar.set_vexpand (false);
263
 
    toolbar.set_hexpand (true);
264
 
    grid.attach (toolbar, 1, 0, 1, 1);
265
 
 
266
 
    /*
267
 
    var share_button = new ToolButton (null, null);
268
 
    share_button.set_sensitive (false);
269
 
    share_button.margin_right = 4;
270
 
    share_button.set_icon_name ("send-to-symbolic");
271
 
    share_button.is_important = false;
272
 
    share_button.set_halign (Align.END);
273
 
    share_button.set_expand (true);
274
 
    toolbar.add (share_button);
275
 
    share_button.clicked.connect ( (button) => {
276
 
      });
277
 
 
278
 
    */
279
 
    window.add (grid);
280
 
 
281
 
    /* We put in an overlay overlapping the left and right pane for the
282
 
       notifications, so they can show up below the toolbar */
 
293
    left_toolbar = new Gd.MainToolbar ();
 
294
    left_toolbar.get_style_context ().add_class (STYLE_CLASS_MENUBAR);
 
295
    left_toolbar.get_style_context ().add_class ("contacts-left-toolbar");
 
296
    left_toolbar.set_vexpand (false);
 
297
    grid.attach (left_toolbar, 0, 0, 1, 1);
 
298
 
 
299
    var add_button = left_toolbar.add_button (null, _("New"), true) as Gtk.Button;
 
300
    add_button.set_size_request (70, -1);
 
301
    add_button.set_vexpand (true);
 
302
    add_button.clicked.connect (app.new_contact);
 
303
 
 
304
    select_button = left_toolbar.add_toggle ("object-select-symbolic", null, false) as ToggleButton;
 
305
 
 
306
    right_toolbar = new Toolbar ();
 
307
    right_toolbar.get_style_context ().add_class (STYLE_CLASS_MENUBAR);
 
308
    right_toolbar.set_vexpand (false);
 
309
    grid.attach (right_toolbar, 1, 0, 1, 1);
 
310
 
 
311
    contact_name = new Label (null);
 
312
    contact_name.set_ellipsize (Pango.EllipsizeMode.END);
 
313
    contact_name.wrap_mode = Pango.WrapMode.CHAR;
 
314
    contact_name.set_halign (Align.START);
 
315
    contact_name.set_valign (Align.CENTER);
 
316
    contact_name.set_vexpand (true);
 
317
    contact_name.set_hexpand (true);
 
318
    contact_name.margin_left = 12;
 
319
    contact_name.margin_right = 12;
 
320
    var item = new ToolItem ();
 
321
    item.set_expand (true);
 
322
    item.add (contact_name);
 
323
    right_toolbar.insert (item, -1);
 
324
 
 
325
    /* spacer */
 
326
    item = new SeparatorToolItem ();
 
327
    (item as SeparatorToolItem).set_draw (false);
 
328
    (item as ToolItem).set_expand (true);
 
329
    right_toolbar.insert (item, -1);
 
330
 
 
331
    edit_button = new Button.with_label (_("Edit"));
 
332
    edit_button.set_size_request (70, -1);
 
333
    item = new ToolItem ();
 
334
    item.add (edit_button);
 
335
    right_toolbar.insert (item, -1);
 
336
 
 
337
    done_button = new Button.with_label (_("Done"));
 
338
    done_button.set_size_request (70, -1);
 
339
    done_button.get_style_context ().add_class ("suggested-action");
 
340
    item = new ToolItem ();
 
341
    item.add (done_button);
 
342
    right_toolbar.insert (item, -1);
 
343
 
 
344
 
283
345
    overlay = new Gtk.Overlay ();
284
346
    Gdk.RGBA transparent = { 0, 0, 0, 0 };
285
347
    overlay.override_background_color (0, transparent);
286
 
    // Need to put something in here for it to work
287
 
    overlay.add (new Alignment (0,0,0,0));
288
 
    grid.attach (overlay, 0, 1, 2, 1);
 
348
    overlay.add (grid);
 
349
    overlay.get_child_position.connect ((overlay, widget, alloc) => {
 
350
        int nat;
 
351
        widget.get_preferred_width (null, out nat);
 
352
        alloc.width = nat;
 
353
 
 
354
        alloc.x = (overlay.get_allocated_width () - nat) / 2;
 
355
        alloc.y = left_toolbar.get_allocated_height ();
 
356
 
 
357
        widget.get_preferred_height (null, out nat);
 
358
        alloc.height = nat;
 
359
 
 
360
        return true;
 
361
      });
 
362
 
 
363
    window.add (overlay);
289
364
 
290
365
    list_pane = new ListPane (contacts_store);
291
366
    list_pane.selection_changed.connect (selection_changed);
 
367
    list_pane.link_contacts.connect (link_contacts);
 
368
    list_pane.delete_contacts.connect (delete_contacts);
292
369
 
293
370
    grid.attach (list_pane, 0, 1, 1, 1);
294
371
 
296
373
    contacts_pane.set_hexpand (true);
297
374
    contacts_pane.will_delete.connect (delete_contact);
298
375
    contacts_pane.contacts_linked.connect (contacts_linked);
299
 
    grid.attach (contacts_pane, 1, 1, 1, 1);
300
 
 
301
 
    grid.show_all ();
 
376
 
 
377
    right_overlay = new Overlay ();
 
378
    right_overlay.override_background_color (0, transparent);
 
379
    right_overlay.add (contacts_pane);
 
380
 
 
381
    grid.attach (right_overlay, 1, 1, 1, 1);
 
382
 
 
383
    overlay.show_all ();
 
384
 
 
385
    select_button.toggled.connect (() => {
 
386
        if (select_button.active)
 
387
          list_pane.show_selection ();
 
388
        else
 
389
          list_pane.hide_selection ();
 
390
      });
 
391
 
 
392
    edit_button.clicked.connect (() => {
 
393
        if (select_button.active)
 
394
          select_button.set_active (false);
 
395
 
 
396
        var name = _("Editing");
 
397
        if (contacts_pane.contact != null) {
 
398
          name += " %s".printf (contacts_pane.contact.display_name);
 
399
        }
 
400
 
 
401
        contact_name.set_markup (Markup.printf_escaped ("<b>%s</b>", name));
 
402
        edit_button.hide ();
 
403
        done_button.show ();
 
404
        contacts_pane.set_edit_mode (true);
 
405
      });
 
406
 
 
407
    done_button.clicked.connect (() => {
 
408
        contact_name.set_text (null);
 
409
        done_button.hide ();
 
410
        edit_button.show ();
 
411
        contacts_pane.set_edit_mode (false);
 
412
      });
 
413
 
 
414
    edit_button.hide ();
 
415
    done_button.hide ();
302
416
  }
303
417
 
304
418
  public override void startup () {
308
422
  }
309
423
 
310
424
  private void show_setup () {
311
 
    avoid_goa_workaround = true;
312
425
    var setup = new SetupWindow ();
313
426
    setup.set_application (this);
314
427
    setup.destroy.connect ( () => {
315
 
        avoid_goa_workaround = false;
316
 
        setup.destroy ();
317
 
        if (setup.succeeded)
318
 
          this.activate ();
 
428
        setup.destroy ();
 
429
        if (setup.succeeded)
 
430
          this.activate ();
319
431
      });
320
432
    setup.show ();
321
433
  }
323
435
  public override void activate () {
324
436
    if (window == null) {
325
437
      if (!settings.get_boolean ("did-initial-setup")) {
326
 
        if (contacts_store.is_prepared)
327
 
          show_setup ();
328
 
        else {
329
 
          hold ();
330
 
          ulong id = 0;
331
 
          uint id2 = 0;
332
 
          id = contacts_store.prepared.connect (() => {
333
 
              show_setup ();
334
 
              contacts_store.disconnect (id);
335
 
              Source.remove (id2);
336
 
              release ();
337
 
            });
338
 
          // Wait at most 0.5 seconds to show the window
339
 
          id2 = Timeout.add (500, () => {
340
 
              show_setup ();
341
 
              contacts_store.disconnect (id);
342
 
              release ();
343
 
              return false;
344
 
        });
345
 
        }
 
438
        if (contacts_store.is_prepared)
 
439
          show_setup ();
 
440
        else {
 
441
          hold ();
 
442
          ulong id = 0;
 
443
          uint id2 = 0;
 
444
          id = contacts_store.prepared.connect (() => {
 
445
              show_setup ();
 
446
              contacts_store.disconnect (id);
 
447
              Source.remove (id2);
 
448
              release ();
 
449
            });
 
450
          // Wait at most 0.5 seconds to show the window
 
451
          id2 = Timeout.add (500, () => {
 
452
              show_setup ();
 
453
              contacts_store.disconnect (id);
 
454
              release ();
 
455
              return false;
 
456
        });
 
457
        }
346
458
 
347
 
        return;
 
459
        return;
348
460
      }
349
461
 
350
462
      create_window ();
351
463
 
352
464
      // We delay the initial show a tiny bit so most contacts are loaded when we show
353
465
      contacts_store.quiescent.connect (() => {
354
 
          app.window.show ();
355
 
        });
 
466
          app.window.show ();
 
467
        });
356
468
      // Wait at most 0.5 seconds to show the window
357
469
      Timeout.add (500, () => {
358
 
          app.window.show ();
359
 
          return false;
360
 
        });
 
470
          app.window.show ();
 
471
          return false;
 
472
        });
361
473
    } else {
362
474
      window.present ();
363
475
    }
364
476
  }
365
477
 
366
478
  public void show_message (string message) {
367
 
    var notification = new Gtk.Notification ();
 
479
    var notification = new Gd.Notification ();
 
480
    notification.timeout = 5;
368
481
 
369
482
    var g = new Grid ();
370
483
    g.set_column_spacing (8);
377
490
    overlay.add_overlay (notification);
378
491
  }
379
492
 
 
493
  public void new_contact () {
 
494
    var dialog = new NewContactDialog (contacts_store, window);
 
495
    dialog.show_all ();
 
496
  }
 
497
 
 
498
  private void link_contacts (LinkedList<Contact> contact_list) {
 
499
    /* getting out of selection mode */
 
500
    show_contact (null);
 
501
    select_button.set_active (false);
 
502
 
 
503
    LinkOperation2 operation = null;
 
504
    link_contacts_list.begin (contact_list, (obj, result) => {
 
505
        operation = link_contacts_list.end (result);
 
506
      });
 
507
 
 
508
    var notification = new Gd.Notification ();
 
509
    notification.timeout = 5;
 
510
 
 
511
    var g = new Grid ();
 
512
    g.set_column_spacing (8);
 
513
    notification.add (g);
 
514
 
 
515
    string msg = ngettext ("%d contacts linked",
 
516
                           "%d contacts linked",
 
517
                           contact_list.size).printf (contact_list.size);
 
518
 
 
519
    var b = new Button.from_stock (Stock.UNDO);
 
520
    g.add (new Label (msg));
 
521
    g.add (b);
 
522
 
 
523
    notification.show_all ();
 
524
    overlay.add_overlay (notification);
 
525
 
 
526
    /* signal handlers */
 
527
    b.clicked.connect ( () => {
 
528
        /* here, we will unlink the thing in question */
 
529
        operation.undo.begin ();
 
530
 
 
531
        notification.dismiss ();
 
532
      });
 
533
  }
 
534
 
 
535
  private void delete_contacts (LinkedList<Contact> contact_list) {
 
536
    /* getting out of selection mode */
 
537
    show_contact (null);
 
538
    select_button.set_active (false);
 
539
 
 
540
    var notification = new Gd.Notification ();
 
541
    notification.timeout = 5;
 
542
 
 
543
    var g = new Grid ();
 
544
    g.set_column_spacing (8);
 
545
    notification.add (g);
 
546
 
 
547
    string msg = ngettext ("%d contact deleted",
 
548
                           "%d contacts deleted",
 
549
                           contact_list.size).printf (contact_list.size);
 
550
 
 
551
    var b = new Button.from_stock (Stock.UNDO);
 
552
    g.add (new Label (msg));
 
553
    g.add (b);
 
554
 
 
555
    notification.show_all ();
 
556
    overlay.add_overlay (notification);
 
557
 
 
558
    /* signal handlers */
 
559
    bool really_delete = true;
 
560
    notification.dismissed.connect ( () => {
 
561
        if (really_delete) {
 
562
          foreach (var c in contact_list) {
 
563
            c.remove_personas.begin ();
 
564
          }
 
565
        }
 
566
      });
 
567
    b.clicked.connect ( () => {
 
568
        really_delete = false;
 
569
        notification.dismiss ();
 
570
          foreach (var c in contact_list) {
 
571
            c.show ();
 
572
          }
 
573
      });
 
574
  }
 
575
 
380
576
  private void delete_contact (Contact contact) {
381
 
    var notification = new Gtk.Notification ();
 
577
    /* unsetting edit-mode */
 
578
    contact_name.set_text (null);
 
579
    done_button.hide ();
 
580
    contacts_pane.set_edit_mode (false);
 
581
 
 
582
    var notification = new Gd.Notification ();
 
583
    notification.timeout = 5;
382
584
 
383
585
    var g = new Grid ();
384
586
    g.set_column_spacing (8);
392
594
    bool really_delete = true;
393
595
    notification.show_all ();
394
596
    notification.dismissed.connect ( () => {
395
 
        if (really_delete)
396
 
          contact.remove_personas.begin ( () => {
397
 
              contact.show ();
398
 
            });
 
597
        if (really_delete)
 
598
          contact.remove_personas.begin ( () => {
 
599
              contact.show ();
 
600
            });
399
601
      });
400
602
    b.clicked.connect ( () => {
401
 
        really_delete = false;
402
 
        notification.dismiss ();
403
 
        contact.show ();
404
 
        list_pane.select_contact (contact);
405
 
        contacts_pane.show_contact (contact);
 
603
        really_delete = false;
 
604
        notification.dismiss ();
 
605
        contact.show ();
 
606
        show_contact (contact);
406
607
      });
407
608
    overlay.add_overlay (notification);
408
609
  }
418
619
  };
419
620
 
420
621
  private void contacts_linked (string? main_contact, string linked_contact, LinkOperation operation) {
421
 
    var notification = new Gtk.Notification ();
 
622
    var notification = new Gd.Notification ();
 
623
    notification.timeout = 5;
422
624
 
423
625
    var g = new Grid ();
424
626
    g.set_column_spacing (8);
437
639
    notification.show_all ();
438
640
    b.clicked.connect ( () => {
439
641
      notification.dismiss ();
440
 
      operation.undo ();
 
642
      operation.undo.begin ();
441
643
    });
442
644
    overlay.add_overlay (notification);
443
645
  }
470
672
    return 0;
471
673
  }
472
674
 
 
675
  public static PersonaStore[] get_eds_address_books () {
 
676
    PersonaStore[] stores = {};
 
677
    foreach (var backend in app.contacts_store.backend_store.enabled_backends.values) {
 
678
      foreach (var persona_store in backend.persona_stores.values) {
 
679
        if (persona_store.type_id == "eds") {
 
680
          stores += persona_store;
 
681
        }
 
682
      }
 
683
    }
 
684
    return stores;
 
685
  }
 
686
 
473
687
  public App () {
474
688
    Object (application_id: "org.gnome.Contacts", flags: ApplicationFlags.HANDLES_COMMAND_LINE);
475
 
    this.app = this;
 
689
    app = this;
476
690
    settings = new GLib.Settings ("org.gnome.Contacts");
477
691
  }
478
692
}