[california/wip/731543-attendees] Refinements
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [california/wip/731543-attendees] Refinements
- Date: Thu, 13 Nov 2014 00:07:20 +0000 (UTC)
commit 48fb987d96a73df1ffbac1ab52dcfc8b1462ae28
Author: Jim Nelson <jim yorba org>
Date: Wed Nov 12 16:07:06 2014 -0800
Refinements
src/component/component-person.vala | 34 ++++++++++++++++--
src/host/host-attendees-editor.vala | 63 ++++++++++++++++++++++++++++++--
src/host/host-create-update-event.vala | 2 +
src/rc/attendees-editor.ui | 31 ++++++++++++----
src/rc/create-update-event.ui | 34 ++----------------
src/toolkit/toolkit-listbox-model.vala | 15 ++++++++
src/util/util-uri.vala | 9 +++++
7 files changed, 144 insertions(+), 44 deletions(-)
---
diff --git a/src/component/component-person.vala b/src/component/component-person.vala
index 4ccfcf7..78a81f6 100644
--- a/src/component/component-person.vala
+++ b/src/component/component-person.vala
@@ -33,6 +33,16 @@ public class Person : BaseObject, Gee.Hashable<Person>, Gee.Comparable<Person> {
public string? common_name { get; private set; default = null; }
/**
+ * The participation ROLE for the { link Person}.
+ */
+ public iCal.icalparameter_role role { get; private set; default =
iCal.icalparameter_role.REQPARTICIPANT; }
+
+ /**
+ * RSVP required for the { link Person}.
+ */
+ public bool rsvp { get; private set; default = false; }
+
+ /**
* The { link mailto} URI as a text string.
*
* @see mailbox
@@ -59,18 +69,28 @@ public class Person : BaseObject, Gee.Hashable<Person>, Gee.Comparable<Person> {
private Gee.HashSet<string> parameters = new Gee.HashSet<string>(String.ci_hash, String.ci_equal);
/**
- * Create an { link Person} with the required { link mailto} and optional { link common_name}.
+ * Create a { link Person} with the required { link mailto} and optional { link common_name}.
*/
- public Person(Soup.URI mailto, string? common_name) throws ComponentError {
+ public Person(Soup.URI mailto, string? common_name = null,
+ iCal.icalparameter_role role = iCal.icalparameter_role.REQPARTICIPANT, bool rsvp = false)
+ throws ComponentError {
validate_mailto(mailto);
this.mailto = mailto;
this.common_name = common_name;
+ this.role = role;
+ this.rsvp = rsvp;
full_mailbox = make_full_address(mailto, common_name);
// store in parameters in case object is serialized as an iCal property.
if (!String.is_empty(common_name))
parameters.add(new iCal.icalparameter.cn(common_name).as_ical_string());
+
+ if (role != iCal.icalparameter_role.REQPARTICIPANT)
+ parameters.add(new iCal.icalparameter.role(role).as_ical_string());
+
+ if (rsvp)
+ parameters.add(new iCal.icalparameter.rsvp(iCal.icalparameter_rsvp.TRUE).as_ical_string());
}
internal Person.from_property(iCal.icalproperty prop) throws Error {
@@ -103,6 +123,14 @@ public class Person : BaseObject, Gee.Hashable<Person>, Gee.Comparable<Person> {
common_name = param.get_cn();
break;
+ case iCal.icalparameter_kind.ROLE_PARAMETER:
+ role = param.get_role();
+ break;
+
+ case iCal.icalparameter_kind.RSVP_PARAMETER:
+ rsvp = param.get_rsvp() == iCal.icalparameter_rsvp.TRUE;
+ break;
+
default:
// fall-through
break;
@@ -115,7 +143,7 @@ public class Person : BaseObject, Gee.Hashable<Person>, Gee.Comparable<Person> {
}
private static void validate_mailto(Soup.URI uri) throws ComponentError {
- if (uri.scheme != "mailto" || String.is_empty(uri.path))
+ if (!String.ci_equal(uri.scheme, "mailto") || String.is_empty(uri.path) ||
!URI.is_valid_mailbox(uri.path))
throw new ComponentError.INVALID("Invalid mailto: %s", uri.to_string(false));
}
diff --git a/src/host/host-attendees-editor.vala b/src/host/host-attendees-editor.vala
index c00b274..5e2646d 100644
--- a/src/host/host-attendees-editor.vala
+++ b/src/host/host-attendees-editor.vala
@@ -22,16 +22,41 @@ public class AttendeesEditor : Gtk.Box, Toolkit.Card {
private Gtk.Entry add_guest_entry;
[GtkChild]
+ private Gtk.Button add_guest_button;
+
+ [GtkChild]
private Gtk.ListBox guest_listbox;
[GtkChild]
+ private Gtk.Button remove_guest_button;
+
+ [GtkChild]
private Gtk.Button accept_button;
private new Component.Event? event = null;
- private Toolkit.ListBoxModel guest_model;
+ private Toolkit.ListBoxModel<Component.Person> guest_model;
public AttendeesEditor() {
guest_model = new Toolkit.ListBoxModel<Component.Person>(guest_listbox, model_presentation);
+
+ add_guest_entry.bind_property("text", add_guest_button, "sensitive", BindingFlags.SYNC_CREATE,
+ transform_add_guest_text_to_button);
+ guest_model.bind_property(Toolkit.ListBoxModel.PROP_SELECTED, remove_guest_button, "sensitive",
+ BindingFlags.SYNC_CREATE, transform_list_selected_to_button);
+ }
+
+ private bool transform_add_guest_text_to_button(Binding binding, Value source_value,
+ ref Value target_value) {
+ target_value = URI.is_valid_mailbox(add_guest_entry.text);
+
+ return true;
+ }
+
+ private bool transform_list_selected_to_button(Binding binding, Value source_value,
+ ref Value target_value) {
+ target_value = guest_model.selected != null;
+
+ return true;
}
public void jumped_to(Toolkit.Card? from, Toolkit.Card.Jump reason, Value? message) {
@@ -39,13 +64,45 @@ public class AttendeesEditor : Gtk.Box, Toolkit.Card {
if (event == null)
return;
+ // clear list and add all attendees who are not organizers
guest_model.clear();
- guest_model.add_many(event.attendees);
+ guest_model.add_many(traverse<Component.Person>(event.attendees)
+ .filter(attendee => !event.organizers.contains(attendee))
+ .to_array_list()
+ );
+ }
+
+ [GtkCallback]
+ private void on_add_guest_button_clicked() {
+ if (!URI.is_valid_mailbox(add_guest_entry.text))
+ return;
+
+ try {
+ // add to model (which adds to listbox) and clear entry
+ guest_model.add(new Component.Person(URI.generate_mailto(add_guest_entry.text)));
+ add_guest_entry.text = "";
+ } catch (Error err) {
+ debug("Unable to generate mailto: %s", err.message);
+ }
+ }
+
+ [GtkCallback]
+ private void on_remove_guest_button_clicked() {
+ if (guest_model.selected != null)
+ guest_model.remove(guest_model.selected);
+ }
+
+ [GtkCallback]
+ private void on_accept_button_clicked() {
+ event.clear_attendees();
+ event.add_attendees(guest_model.all());
+
+ jump_to_card_by_name(CreateUpdateEvent.ID, event);
}
[GtkCallback]
private void on_cancel_button_clicked() {
- jump_home();
+ jump_back();
}
private Gtk.Widget model_presentation(Component.Person person) {
diff --git a/src/host/host-create-update-event.vala b/src/host/host-create-update-event.vala
index 1b781cd..74d8f8e 100644
--- a/src/host/host-create-update-event.vala
+++ b/src/host/host-create-update-event.vala
@@ -160,6 +160,8 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
attendees_text.label = traverse<Component.Person>(event.attendees)
.filter(attendee => !event.organizers.contains(attendee))
.to_string(stringify_attendees);
+ if (String.is_empty(attendees_text.label))
+ attendees_text.label = _("None");
Component.Event master = event.is_master_instance ? event : (Component.Event) event.master;
diff --git a/src/rc/attendees-editor.ui b/src/rc/attendees-editor.ui
index 3296111..00a064a 100644
--- a/src/rc/attendees-editor.ui
+++ b/src/rc/attendees-editor.ui
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.16.1 -->
+<!-- Generated with glade 3.18.3 -->
<interface>
<requires lib="gtk+" version="3.12"/>
<template class="CaliforniaHostAttendeesEditor" parent="GtkBox">
@@ -32,6 +32,7 @@
<object class="GtkEntry" id="add_guest_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">For example, bob example com</property>
<property name="placeholder_text" translatable="yes">Email address</property>
<property name="input_purpose">email</property>
</object>
@@ -49,6 +50,7 @@
<property name="receives_default">True</property>
<property name="use_underline">True</property>
<property name="xalign">0.60000002384185791</property>
+ <signal name="clicked" handler="on_add_guest_button_clicked"
object="CaliforniaHostAttendeesEditor" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -65,15 +67,28 @@
</packing>
</child>
<child>
- <object class="GtkListBox" id="guest_listbox">
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <property name="activate_on_single_click">False</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport" id="viewport1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkListBox" id="guest_listbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="activate_on_single_click">False</property>
+ </object>
+ </child>
+ </object>
+ </child>
</object>
<packing>
- <property name="expand">False</property>
+ <property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
@@ -86,6 +101,7 @@
<property name="receives_default">True</property>
<property name="halign">end</property>
<property name="use_underline">True</property>
+ <signal name="clicked" handler="on_remove_guest_button_clicked"
object="CaliforniaHostAttendeesEditor" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@@ -126,6 +142,7 @@
<property name="has_default">True</property>
<property name="receives_default">True</property>
<property name="use_underline">True</property>
+ <signal name="clicked" handler="on_accept_button_clicked" object="CaliforniaHostAttendeesEditor"
swapped="no"/>
<style>
<class name="suggested-action"/>
</style>
diff --git a/src/rc/create-update-event.ui b/src/rc/create-update-event.ui
index d3969a6..43fb9d0 100644
--- a/src/rc/create-update-event.ui
+++ b/src/rc/create-update-event.ui
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.16.1 -->
+<!-- Generated with glade 3.18.3 -->
<interface>
<requires lib="gtk+" version="3.10"/>
<template class="CaliforniaHostCreateUpdateEvent" parent="GtkGrid">
@@ -23,8 +23,6 @@
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -40,8 +38,6 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -57,8 +53,6 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -105,8 +99,6 @@
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -122,8 +114,6 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -170,8 +160,6 @@
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -189,7 +177,6 @@
<property name="left_attach">0</property>
<property name="top_attach">7</property>
<property name="width">2</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -205,8 +192,6 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">6</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -218,8 +203,6 @@
<packing>
<property name="left_attach">1</property>
<property name="top_attach">6</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -239,8 +222,6 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">5</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -268,8 +249,6 @@
<packing>
<property name="left_attach">1</property>
<property name="top_attach">5</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -287,8 +266,6 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -300,8 +277,6 @@
<packing>
<property name="left_attach">1</property>
<property name="top_attach">4</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -310,7 +285,7 @@
<property name="can_focus">False</property>
<property name="no_show_all">True</property>
<property name="xalign">1</property>
- <property name="label" translatable="yes">_Guests</property>
+ <property name="label" translatable="yes">Invited Guests</property>
<property name="use_underline">True</property>
<style>
<class name="dim-label"/>
@@ -319,8 +294,6 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
<child>
@@ -348,6 +321,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Add and remove invited guests</property>
<property name="relief">none</property>
<signal name="clicked" handler="on_attendees_button_clicked"
object="CaliforniaHostCreateUpdateEvent" swapped="no"/>
<child>
@@ -368,8 +342,6 @@
<packing>
<property name="left_attach">1</property>
<property name="top_attach">3</property>
- <property name="width">1</property>
- <property name="height">1</property>
</packing>
</child>
</template>
diff --git a/src/toolkit/toolkit-listbox-model.vala b/src/toolkit/toolkit-listbox-model.vala
index 951b8ad..b043fda 100644
--- a/src/toolkit/toolkit-listbox-model.vala
+++ b/src/toolkit/toolkit-listbox-model.vala
@@ -197,6 +197,21 @@ public class ListBoxModel<G> : BaseObject {
}
/**
+ * A Gee.Set of all items in the { link ListBoxModel}, sorted if appropriate.
+ */
+ public Gee.Set<G> all() {
+ Gee.TreeSet<G> treeset;
+ if (comparator != null)
+ treeset = new Gee.TreeSet<G>(comparator);
+ else
+ treeset = new Gee.TreeSet<G>();
+
+ treeset.add_all(items.keys);
+
+ return treeset;
+ }
+
+ /**
* Returns the { link ModelPresentation} widget for the item.
*/
public Gtk.Widget? get_widget_for_item(G item) {
diff --git a/src/util/util-uri.vala b/src/util/util-uri.vala
index 0a61e1a..cd92c53 100644
--- a/src/util/util-uri.vala
+++ b/src/util/util-uri.vala
@@ -76,5 +76,14 @@ public bool is_valid_mailbox(string str) {
return email_regex.match(str);
}
+/**
+ * Generates a valid mailto: Soup.URI given a mailbox (i.e. email) address.
+ *
+ * No validity checking is done here on the mailbox; use { link is_valid_mailbox}.
+ */
+public Soup.URI generate_mailto(string mailbox) throws Error {
+ return parse("mailto:%s".printf(GLib.Uri.escape_string(mailbox, "@")));
+}
+
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]