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);
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);
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);
78
contact_name.set_text (null);
82
contacts_pane.show_contact (new_selection, false, false);
84
/* clearing right_toolbar */
85
if (new_selection != null) {
65
92
public void show_contact (Contact? contact) {
66
93
list_pane.select_contact (contact);
67
contacts_pane.show_contact (contact);
95
/* hack for showing contact */
96
selection_changed (contact);
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;
74
103
if (contact != null) {
75
104
list_pane.select_contact (contact);
76
105
contacts_pane.show_contact (contact);
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"));
82
111
dialog.response.connect ( (id) => {
88
117
public void change_address_book () {
89
118
var title = _("Change Address Book");
90
119
var dialog = new Dialog.with_buttons ("",
92
DialogFlags.MODAL | DialogFlags.DESTROY_WITH_PARENT,
93
Stock.CANCEL, ResponseType.CANCEL,
94
_("Select"), ResponseType.OK);
121
DialogFlags.MODAL | DialogFlags.DESTROY_WITH_PARENT,
122
Stock.CANCEL, ResponseType.CANCEL,
123
_("Select"), ResponseType.OK);
96
125
dialog.set_resizable (false);
97
126
dialog.set_default_response (ResponseType.OK);
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);
145
174
dialog.show_all ();
146
175
dialog.response.connect ( (response) => {
147
if (response == ResponseType.OK) {
148
PersonaStore selected_store;
151
if (tree_view.get_selection() .get_selected (null, out iter2)) {
152
store.get (iter2, 1, out selected_store);
154
var e_store = selected_store as Edsf.PersonaStore;
157
E.BookClient.set_default_source (e_store.source);
159
warning ("Failed to set address book");
162
contacts_store.refresh ();
176
if (response == ResponseType.OK) {
177
PersonaStore selected_store;
180
if (tree_view.get_selection() .get_selected (null, out iter2)) {
181
store.get (iter2, 1, out selected_store);
183
var e_store = selected_store as Edsf.PersonaStore;
185
eds_source_registry.set_default_address_book (e_store.source);
187
contacts_store.refresh ();
194
public void show_help () {
195
Gtk.show_uri (window.get_screen (),
196
"help:gnome-help/contacts",
197
Gtk.get_current_event_time ());
169
200
public void show_about () {
170
201
string[] authors = {
171
202
"Alexander Larsson <alexl@redhat.com>",
175
206
"Allan Day <allanpday@gmail.com>"
177
208
Gtk.show_about_dialog (window,
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);
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);
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);
196
227
if (contact != null) {
197
228
list_pane.select_contact (contact);
198
229
contacts_pane.show_contact (contact);
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"));
204
235
dialog.response.connect ( (id) => {
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);
240
291
var grid = new Grid();
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);
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);
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);
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) => {
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);
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);
304
select_button = left_toolbar.add_toggle ("object-select-symbolic", null, false) as ToggleButton;
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);
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);
326
item = new SeparatorToolItem ();
327
(item as SeparatorToolItem).set_draw (false);
328
(item as ToolItem).set_expand (true);
329
right_toolbar.insert (item, -1);
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);
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);
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);
349
overlay.get_child_position.connect ((overlay, widget, alloc) => {
351
widget.get_preferred_width (null, out nat);
354
alloc.x = (overlay.get_allocated_width () - nat) / 2;
355
alloc.y = left_toolbar.get_allocated_height ();
357
widget.get_preferred_height (null, out nat);
363
window.add (overlay);
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);
293
370
grid.attach (list_pane, 0, 1, 1, 1);
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);
377
right_overlay = new Overlay ();
378
right_overlay.override_background_color (0, transparent);
379
right_overlay.add (contacts_pane);
381
grid.attach (right_overlay, 1, 1, 1, 1);
385
select_button.toggled.connect (() => {
386
if (select_button.active)
387
list_pane.show_selection ();
389
list_pane.hide_selection ();
392
edit_button.clicked.connect (() => {
393
if (select_button.active)
394
select_button.set_active (false);
396
var name = _("Editing");
397
if (contacts_pane.contact != null) {
398
name += " %s".printf (contacts_pane.contact.display_name);
401
contact_name.set_markup (Markup.printf_escaped ("<b>%s</b>", name));
404
contacts_pane.set_edit_mode (true);
407
done_button.clicked.connect (() => {
408
contact_name.set_text (null);
411
contacts_pane.set_edit_mode (false);
304
418
public override void startup () {
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)
332
id = contacts_store.prepared.connect (() => {
334
contacts_store.disconnect (id);
338
// Wait at most 0.5 seconds to show the window
339
id2 = Timeout.add (500, () => {
341
contacts_store.disconnect (id);
438
if (contacts_store.is_prepared)
444
id = contacts_store.prepared.connect (() => {
446
contacts_store.disconnect (id);
450
// Wait at most 0.5 seconds to show the window
451
id2 = Timeout.add (500, () => {
453
contacts_store.disconnect (id);
350
462
create_window ();
352
464
// We delay the initial show a tiny bit so most contacts are loaded when we show
353
465
contacts_store.quiescent.connect (() => {
356
468
// Wait at most 0.5 seconds to show the window
357
469
Timeout.add (500, () => {
362
474
window.present ();
366
478
public void show_message (string message) {
367
var notification = new Gtk.Notification ();
479
var notification = new Gd.Notification ();
480
notification.timeout = 5;
369
482
var g = new Grid ();
370
483
g.set_column_spacing (8);
377
490
overlay.add_overlay (notification);
493
public void new_contact () {
494
var dialog = new NewContactDialog (contacts_store, window);
498
private void link_contacts (LinkedList<Contact> contact_list) {
499
/* getting out of selection mode */
501
select_button.set_active (false);
503
LinkOperation2 operation = null;
504
link_contacts_list.begin (contact_list, (obj, result) => {
505
operation = link_contacts_list.end (result);
508
var notification = new Gd.Notification ();
509
notification.timeout = 5;
512
g.set_column_spacing (8);
513
notification.add (g);
515
string msg = ngettext ("%d contacts linked",
516
"%d contacts linked",
517
contact_list.size).printf (contact_list.size);
519
var b = new Button.from_stock (Stock.UNDO);
520
g.add (new Label (msg));
523
notification.show_all ();
524
overlay.add_overlay (notification);
526
/* signal handlers */
527
b.clicked.connect ( () => {
528
/* here, we will unlink the thing in question */
529
operation.undo.begin ();
531
notification.dismiss ();
535
private void delete_contacts (LinkedList<Contact> contact_list) {
536
/* getting out of selection mode */
538
select_button.set_active (false);
540
var notification = new Gd.Notification ();
541
notification.timeout = 5;
544
g.set_column_spacing (8);
545
notification.add (g);
547
string msg = ngettext ("%d contact deleted",
548
"%d contacts deleted",
549
contact_list.size).printf (contact_list.size);
551
var b = new Button.from_stock (Stock.UNDO);
552
g.add (new Label (msg));
555
notification.show_all ();
556
overlay.add_overlay (notification);
558
/* signal handlers */
559
bool really_delete = true;
560
notification.dismissed.connect ( () => {
562
foreach (var c in contact_list) {
563
c.remove_personas.begin ();
567
b.clicked.connect ( () => {
568
really_delete = false;
569
notification.dismiss ();
570
foreach (var c in contact_list) {
380
576
private void delete_contact (Contact contact) {
381
var notification = new Gtk.Notification ();
577
/* unsetting edit-mode */
578
contact_name.set_text (null);
580
contacts_pane.set_edit_mode (false);
582
var notification = new Gd.Notification ();
583
notification.timeout = 5;
383
585
var g = new Grid ();
384
586
g.set_column_spacing (8);