Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
GNOME
GNOME Contacts
Commits
06a45451
Commit
06a45451
authored
Sep 06, 2022
by
Niels De Graef
😁
Browse files
WIP
parent
775ce8ff
Pipeline
#457381
failed with stages
in 25 minutes and 32 seconds
Changes
17
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
src/core/contacts-addresses-chunk.vala
View file @
06a45451
...
...
@@ -135,4 +135,16 @@ public class Contacts.Address : BinChunkChild {
return
new
PostalAddressFieldDetails
(
this
.
address
,
this
.
parameters
);
}
protected
override
Variant
?
to_gvariant_internal
()
{
return
new
Variant
(
"(sssssssv)"
,
this
.
address
.
po_box
,
this
.
address
.
extension
,
this
.
address
.
street
,
this
.
address
.
locality
,
this
.
address
.
region
,
this
.
address
.
postal_code
,
this
.
address
.
country
,
parameters_to_gvariant
());
}
}
src/core/contacts-alias-chunk.vala
View file @
06a45451
...
...
@@ -54,4 +54,8 @@ public class Contacts.AliasChunk : Chunk {
yield
((
AliasDetails
)
this
.
persona
).
change_alias
(
this
.
alias
);
}
public
override
Variant
?
to_gvariant
()
{
return
new
Variant
.
string
(
this
.
alias
);
}
}
src/core/contacts-avatar-chunk.vala
View file @
06a45451
...
...
@@ -50,4 +50,9 @@ public class Contacts.AvatarChunk : Chunk {
requires
(
this
.
persona
is
AvatarDetails
)
{
yield
((
AvatarDetails
)
this
.
persona
).
change_avatar
(
this
.
avatar
);
}
public
override
Variant
?
to_gvariant
()
{
// FIXME: implement
return
null
;
}
}
src/core/contacts-bin-chunk.vala
View file @
06a45451
...
...
@@ -107,6 +107,17 @@ public abstract class Contacts.BinChunk : Chunk, GLib.ListModel {
return
afds
;
}
public
override
Variant
?
to_gvariant
()
{
var
builder
=
new
GLib
.
VariantBuilder
(
GLib
.
VariantType
.
ARRAY
);
for
(
uint
i
=
0
;
i
<
this
.
elements
.
length
;
i
++)
{
var
child_variant
=
this
.
elements
[
i
].
to_gvariant
();
if
(
child_variant
!=
null
)
builder
.
add_value
(
child_variant
);
}
return
builder
.
end
();
}
// ListModel implementation
public
uint
n_items
{
get
{
return
this
.
elements
.
length
;
}
}
...
...
@@ -153,6 +164,35 @@ public abstract class Contacts.BinChunkChild : GLib.Object {
*/
public
abstract
AbstractFieldDetails
?
create_afd
();
/**
* XXX
*/
public
Variant
?
to_gvariant
()
{
if
(
this
.
is_empty
)
return
null
;
return
to_gvariant_internal
();
}
protected
abstract
Variant
?
to_gvariant_internal
();
// Helper to serialize the parameters field
protected
Variant
parameters_to_gvariant
()
{
if
(
this
.
parameters
.
size
==
0
)
{
return
new
GLib
.
Variant
(
"a(ss)"
,
null
);
// Empty array
}
var
builder
=
new
GLib
.
VariantBuilder
(
GLib
.
VariantType
.
ARRAY
);
var
iter
=
this
.
parameters
.
map_iterator
();
while
(
iter
.
next
())
{
string
param_name
=
iter
.
get_key
();
string
param_value
=
iter
.
get_value
();
builder
.
add
(
"(ss)"
,
param_name
,
param_value
);
}
return
builder
.
end
();
}
// A helper to change a string field with the proper propery notifies
protected
void
change_string_prop
(
string
prop_name
,
ref
string
old_value
,
...
...
src/core/contacts-birthday-chunk.vala
View file @
06a45451
...
...
@@ -59,4 +59,13 @@ public class Contacts.BirthdayChunk : Chunk {
requires
(
this
.
persona
is
BirthdayDetails
)
{
yield
((
BirthdayDetails
)
this
.
persona
).
change_birthday
(
this
.
birthday
);
}
public
override
Variant
?
to_gvariant
()
{
if
(
this
.
birthday
==
null
)
return
null
;
int
year
,
month
,
day
;
this
.
birthday
.
get_ymd
(
out
year
,
out
month
,
out
day
);
return
new
GLib
.
Variant
(
"(iii)"
,
year
,
month
,
day
);
}
}
src/core/contacts-chunk.vala
View file @
06a45451
...
...
@@ -60,4 +60,9 @@ public abstract class Contacts.Chunk : GLib.Object {
*/
public
abstract
async
void
save_to_persona
()
throws
GLib
.
Error
requires
(
this
.
persona
!=
null
);
/**
* XXX
*/
public
abstract
Variant
?
to_gvariant
();
}
src/core/contacts-email-addresses-chunk.vala
View file @
06a45451
...
...
@@ -87,6 +87,10 @@ public class Contacts.EmailAddress : BinChunkChild {
return
new
EmailFieldDetails
(
this
.
raw_address
,
this
.
parameters
);
}
protected
override
Variant
?
to_gvariant_internal
()
{
return
new
Variant
(
"(sv)"
,
this
.
raw_address
,
parameters_to_gvariant
());
}
public
string
get_mailto_uri
()
{
return
"mailto:"
+
Uri
.
escape_string
(
this
.
raw_address
,
"@"
,
false
);
}
...
...
src/core/contacts-full-name-chunk.vala
View file @
06a45451
...
...
@@ -50,6 +50,11 @@ public class Contacts.FullNameChunk : Chunk {
}
}
public
FullNameChunk
.
from_gvariant
(
GLib
.
Variant
variant
)
{
unowned
var
fn
=
variant
.
get_string
();
Object
(
persona
:
null
,
full_name
:
fn
);
}
public
override
Value
?
to_value
()
{
return
this
.
full_name
;
}
...
...
@@ -58,4 +63,8 @@ public class Contacts.FullNameChunk : Chunk {
requires
(
this
.
persona
is
NameDetails
)
{
yield
((
NameDetails
)
this
.
persona
).
change_full_name
(
this
.
full_name
);
}
public
override
Variant
?
to_gvariant
()
{
return
new
Variant
.
string
(
this
.
full_name
);
}
}
src/core/contacts-im-addresses-chunk.vala
View file @
06a45451
...
...
@@ -96,4 +96,11 @@ public class Contacts.ImAddress : BinChunkChild {
return
new
ImFieldDetails
(
this
.
address
,
this
.
parameters
);
}
protected
override
Variant
?
to_gvariant_internal
()
{
return
new
Variant
(
"(ssv)"
,
this
.
protocol
,
this
.
address
,
parameters_to_gvariant
());
}
}
src/core/contacts-nickname-chunk.vala
View file @
06a45451
...
...
@@ -57,4 +57,8 @@ public class Contacts.NicknameChunk : Chunk {
yield
((
NameDetails
)
this
.
persona
).
change_nickname
(
this
.
nickname
);
}
public
override
Variant
?
to_gvariant
()
{
return
new
Variant
.
string
(
this
.
nickname
);
}
}
src/core/contacts-notes-chunk.vala
View file @
06a45451
...
...
@@ -82,4 +82,8 @@ public class Contacts.Note : BinChunkChild {
return
new
NoteFieldDetails
(
this
.
text
,
this
.
parameters
);
}
protected
override
Variant
?
to_gvariant_internal
()
{
return
new
Variant
(
"(sv)"
,
this
.
text
,
parameters_to_gvariant
());
}
}
src/core/contacts-phones-chunk.vala
View file @
06a45451
...
...
@@ -94,4 +94,8 @@ public class Contacts.Phone : BinChunkChild {
return
new
PhoneFieldDetails
(
this
.
raw_number
,
this
.
parameters
);
}
protected
override
Variant
?
to_gvariant_internal
()
{
return
new
Variant
(
"(sv)"
,
this
.
raw_number
,
parameters_to_gvariant
());
}
}
src/core/contacts-roles-chunk.vala
View file @
06a45451
...
...
@@ -79,6 +79,13 @@ public class Contacts.OrgRole : BinChunkChild {
return
new
RoleFieldDetails
(
this
.
role
,
this
.
parameters
);
}
protected
override
Variant
?
to_gvariant_internal
()
{
return
new
Variant
(
"(ssv)"
,
this
.
role
.
organisation_name
,
this
.
role
.
title
,
parameters_to_gvariant
());
}
public
string
to_string
()
{
if
(
this
.
role
.
title
!=
""
)
{
if
(
this
.
role
.
organisation_name
!=
""
)
{
...
...
src/core/contacts-structured-name-chunk.vala
View file @
06a45451
...
...
@@ -66,4 +66,13 @@ public class Contacts.StructuredNameChunk : Chunk {
requires
(
this
.
persona
is
NameDetails
)
{
yield
((
NameDetails
)
this
.
persona
).
change_structured_name
(
this
.
struct
ured_name
);
}
public
override
Variant
?
to_gvariant
()
{
return
new
Variant
(
"(sssss)"
,
this
.
struct
ured_name
.
family_name
,
this
.
struct
ured_name
.
given_name
,
this
.
struct
ured_name
.
additional_names
,
this
.
struct
ured_name
.
prefixes
,
this
.
struct
ured_name
.
suffixes
);
}
}
src/core/contacts-urls-chunk.vala
View file @
06a45451
...
...
@@ -92,4 +92,8 @@ public class Contacts.Url : BinChunkChild {
return
new
UrlFieldDetails
(
this
.
raw_url
,
this
.
parameters
);
}
protected
override
Variant
?
to_gvariant_internal
()
{
return
new
Variant
(
"(sv)"
,
this
.
raw_url
,
parameters_to_gvariant
());
}
}
src/io/contacts-io-parser.vala
View file @
06a45451
...
...
@@ -18,22 +18,18 @@
using
Folks
;
/**
* A
n
Parser is an object that can deal with importing a specific format
*
of
describing a Contact (
V
Card is the most common example, but there exist
* A Parser is an object that can deal with importing a specific format
of
* describing a Contact (
v
Card is the most common example, but there exist
* also CSV based formats and others).
*
* The main purpose of an Io.Parser is to parser whatever input it gets into a
* {@link GLib.HashTable} with string keys and {@link Value} as values. After
* that, we can choose to either serialize (using the serializing methods in
* Contacts.Io), or to immediately import it in folks using
* {@link Folks.PersonaStore.add_from_details}.
* The main purpose of an Io.Parser is to parser whatever input it gets into an
* array of {@link Contacts.Contact}s. After that, we can for example either
* serialize the contact into a contact again.
*/
public
abstract
class
Contacts
.
Io
.
Parser
:
Object
{
/**
* Takes the given input stream and tries to parse it into a
* {@link GLib.HashTable}, which can then be used for methods like
* {@link Folks.PersonaStore.add_persona_from_details}.
* Takes the given input stream and tries to parse it into a set of contacts.
*/
public
abstract
GLib
.
HashTable
<
string
,
Value
?>
[]
parse
(
InputStream
input
)
throws
GLib
.
Error
;
public
abstract
Contact
[]
parse
(
InputStream
input
)
throws
GLib
.
Error
;
}
src/io/contacts-io-vcard-parser.vala
View file @
06a45451
...
...
@@ -25,7 +25,7 @@ public class Contacts.Io.VCardParser : Contacts.Io.Parser {
public
VCardParser
()
{
}
public
override
HashTable
<
string
,
Value
?>
[]
parse
(
InputStream
input
)
throws
GLib
.
Error
{
public
override
Contact
[]
parse
(
InputStream
input
)
throws
GLib
.
Error
{
// Read the whole input into a string.
// We can probably do better, but that takes a bit of extra work
var
memory_stream
=
new
MemoryOutputStream
.
resizable
();
...
...
@@ -34,7 +34,7 @@ public class Contacts.Io.VCardParser : Contacts.Io.Parser {
memory_stream
.
close
();
var
input_str
=
(
string
)
memory_stream
.
get_data
();
var
result
=
new
GenericArray
<
HashTable
<
string
,
Value
?>
>
();
var
result
=
new
GenericArray
<
Contact
>
();
// Parse the input stream into a set of vcards
int
begin_index
=
input_str
.
index_of
(
"BEGIN:VCARD"
);
...
...
@@ -51,44 +51,44 @@ public class Contacts.Io.VCardParser : Contacts.Io.Parser {
unowned
var
vcard_attrs
=
vcard
.
get_attributes
();
debug
(
"Got %u attributes in this vcard"
,
vcard_attrs
.
length
());
var
details
=
new
HashTable
<
string
,
Value
?>
(
GLib
.
str_hash
,
GLib
.
str_equa
l
);
var
contact
=
new
Contact
.
for_empty
(
nul
l
);
foreach
(
unowned
E
.
VCardAttribute
attr
in
vcard_attrs
)
{
switch
(
attr
.
get_name
())
{
// Identification Properties
case
E
.
EVC_FN
:
handle_fn
(
details
,
attr
);
handle_fn
(
contact
,
attr
);
break
;
case
E
.
EVC_N
:
handle_n
(
details
,
attr
);
handle_n
(
contact
,
attr
);
break
;
case
E
.
EVC_NICKNAME
:
handle_nickname
(
details
,
attr
);
handle_nickname
(
contact
,
attr
);
break
;
/* FIXME
case E.EVC_PHOTO:
handle_photo (
details
, attr);
handle_photo (
contact
, attr);
break;
*/
case
E
.
EVC_BDAY
:
handle_bday
(
details
,
attr
);
handle_bday
(
contact
,
attr
);
break
;
// Delivery Addressing Properties
case
E
.
EVC_ADR
:
handle_adr
(
details
,
attr
);
handle_adr
(
contact
,
attr
);
break
;
// Communications Properties
case
E
.
EVC_TEL
:
handle_tel
(
details
,
attr
);
handle_tel
(
contact
,
attr
);
break
;
case
E
.
EVC_EMAIL
:
handle_email
(
details
,
attr
);
handle_email
(
contact
,
attr
);
break
;
// Explanatory Properties
case
E
.
EVC_NOTE
:
handle_note
(
details
,
attr
);
handle_note
(
contact
,
attr
);
break
;
case
E
.
EVC_URL
:
handle_url
(
details
,
attr
);
handle_url
(
contact
,
attr
);
break
;
default
:
...
...
@@ -97,7 +97,7 @@ public class Contacts.Io.VCardParser : Contacts.Io.Parser {
}
}
result
.
add
(
details
);
result
.
add
(
contact
);
begin_index
=
input_str
.
index_of
(
"BEGIN:VCARD"
,
end_index
);
}
...
...
@@ -106,193 +106,134 @@ public class Contacts.Io.VCardParser : Contacts.Io.Parser {
}
// Handles the "FN" (Full Name) attribute
private
void
handle_fn
(
HashTable
<
string
,
Value
?>
details
,
E
.
VCardAttribute
attr
)
{
private
void
handle_fn
(
Contact
contact
,
E
.
VCardAttribute
attr
)
{
var
full_name
=
attr
.
get_value
();
debug
(
"Got FN '%s'"
,
full_name
);
Value
?
fn_v
=
Value
(
typeof
(
string
));
fn_v
.
set_string
(
full_name
);
details
.
insert
(
Folks
.
PersonaStore
.
detail_key
(
PersonaDetail
.
FULL_NAME
),
(
owned
)
fn_v
);
var
fn_chunk
=
contact
.
create_chunk
(
"full-name"
,
null
);
fn_chunk
.
full_name
=
full_name
;
}
// Handles the "N" (structured Name) attribute
private
void
handle_n
(
HashTable
<
string
,
Value
?>
details
,
E
.
VCardAttribute
attr
)
{
private
void
handle_n
(
Contact
contact
,
E
.
VCardAttribute
attr
)
{
unowned
var
values
=
attr
.
get_values
();
// From the VCard spec:
// The structured property value corresponds, in sequence, to the Family
// Names (also known as surnames), Given Names, Additional Names, Honorific
// Prefixes, and Honorific Suffixes.
unowned
var
family_name
=
values
.
nth_data
(
0
)
??
""
;
unowned
var
given_name
=
values
.
nth_data
(
1
)
??
""
;
unowned
var
additional_names
=
values
.
nth_data
(
2
)
??
""
;
unowned
var
prefixes
=
values
.
nth_data
(
3
)
??
""
;
unowned
var
suffixes
=
values
.
nth_data
(
4
)
??
""
;
var
struct
ured_name
=
new
StructuredName
(
family_name
,
given_name
,
additional_names
,
prefixes
,
suffixes
);
Value
?
n_v
=
Value
(
typeof
(
StructuredName
));
n_v
.
take_object
((
owned
)
struct
ured_name
);
details
.
insert
(
Folks
.
PersonaStore
.
detail_key
(
PersonaDetail
.
STRUCTURED_NAME
),
(
owned
)
n_v
);
var
sn_chunk
=
contact
.
create_chunk
(
"structured-name"
,
null
);
sn_chunk
.
struct
ured_name
.
family_name
=
values
.
nth_data
(
0
)
??
""
;
sn_chunk
.
struct
ured_name
.
given_name
=
values
.
nth_data
(
1
)
??
""
;
sn_chunk
.
struct
ured_name
.
additional_names
=
values
.
nth_data
(
2
)
??
""
;
sn_chunk
.
struct
ured_name
.
prefixes
=
values
.
nth_data
(
3
)
??
""
;
sn_chunk
.
struct
ured_name
.
suffixes
=
values
.
nth_data
(
4
)
??
""
;
}
private
void
handle_nickname
(
HashTable
<
string
,
Value
?>
details
,
E
.
VCardAttribute
attr
)
{
private
void
handle_nickname
(
Contact
contact
,
E
.
VCardAttribute
attr
)
{
var
nickname
=
attr
.
get_value
();
debug
(
"Got nickname '%s'"
,
nickname
);
Value
?
nick_v
=
Value
(
typeof
(
string
));
nick_v
.
set_string
(
nickname
);
details
.
insert
(
Folks
.
PersonaStore
.
detail_key
(
PersonaDetail
.
NICKNAME
),
(
owned
)
nick_v
);
var
nick_chunk
=
contact
.
create_chunk
(
"nickname"
,
null
);
nick_chunk
.
nickname
=
nickname
;
}
// Handles the "BDAY" (birthday) attribute
private
void
handle_bday
(
HashTable
<
string
,
Value
?>
details
,
E
.
VCardAttribute
attr
)
{
// Get the attribute valuec
private
void
handle_bday
(
Contact
contact
,
E
.
VCardAttribute
attr
)
{
var
bday
=
attr
.
get_value
();
// Parse it using the logic in E.ContactDate
var
e_date
=
E
.
ContactDate
.
from_string
(
bday
);
// Turn it into a GLib.DateTime
var
datetime
=
new
DateTime
.
utc
((
int
)
e_date
.
year
,
(
int
)
e_date
.
month
,
(
int
)
e_date
.
day
,
0
,
0
,
0.0
);
// Insert it into the hashtable as a GLib.Value
Value
?
bday_val
=
Value
(
typeof
(
DateTime
));
bday_val
.
take_boxed
((
owned
)
datetime
);
details
.
insert
(
Folks
.
PersonaStore
.
detail_key
(
PersonaDetail
.
BIRTHDAY
),
(
owned
)
bday_val
);
var
bd_chunk
=
contact
.
create_chunk
(
"birthday"
,
null
);
bd_chunk
.
birthday
=
birthday
;
}
private
void
handle_email
(
HashTable
<
string
,
Value
?>
details
,
E
.
VCardAttribute
attr
)
{
private
void
handle_email
(
Contact
contact
,
E
.
VCardAttribute
attr
)
{
var
email
=
attr
.
get_value
();
if
(
email
==
null
||
email
==
""
)
return
;
var
email_fd
=
new
EmailFieldDetails
(
email
);
add_params
(
email_fd
,
attr
);
insert_field_details
<
EmailFieldDetails
>
(
details
,
PersonaDetail
.
EMAIL_ADDRESSES
,
email_fd
,
AbstractFieldDetails
<
string
>.
hash_static
,
AbstractFieldDetails
<
string
>.
equal_static
);
var
child
=
add_chunk_child_for_property
(
contact
,
"email-addresses"
);
((
EmailAddress
)
child
).
raw_address
=
email
;
add_params
(
child
,
attr
);
}
private
void
handle_tel
(
HashTable
<
string
,
Value
?>
details
,
E
.
VCardAttribute
attr
)
{
private
void
handle_tel
(
Contact
contact
,
E
.
VCardAttribute
attr
)
{
var
phone_nr
=
attr
.
get_value
();
if
(
phone_nr
==
null
||
phone_nr
==
""
)
return
;
var
phone_fd
=
new
PhoneFieldDetails
(
phone_nr
);
add_params
(
phone_fd
,
attr
);
insert_field_details
<
PhoneFieldDetails
>
(
details
,
PersonaDetail
.
PHONE_NUMBERS
,
phone_fd
,
AbstractFieldDetails
<
string
>.
hash_static
,
AbstractFieldDetails
<
string
>.
equal_static
);
var
child
=
add_chunk_child_for_property
(
contact
,
"phone-numbers"
);
((
Phone
)
child
).
raw_number
=
phone_nr
;
add_params
(
child
,
attr
);
}
// Handles the ADR (postal address) attributes
private
void
handle_adr
(
HashTable
<
string
,
Value
?>
details
,
E
.
VCardAttribute
attr
)
{
private
void
handle_adr
(
Contact
contact
,
E
.
VCardAttribute
attr
)
{
unowned
var
values
=
attr
.
get_values
();
var
child
=
add_chunk_child_for_property
(
contact
,
"postal-addresses"
);
unowned
var
address
=
((
Addresss
)
child
).
address
;
// From the VCard spec:
// ADR-value = ADR-component-pobox ";" ADR-component-ext ";"
// ADR-component-street ";" ADR-component-locality ";"
// ADR-component-region ";" ADR-component-code ";"
// ADR-component-country
unowned
var
po_box
=
values
.
nth_data
(
0
)
??
""
;
unowned
var
extension
=
values
.
nth_data
(
1
)
??
""
;
unowned
var
street
=
values
.
nth_data
(
2
)
??
""
;
unowned
var
locality
=
values
.
nth_data
(
3
)
??
""
;
unowned
var
region
=
values
.
nth_data
(
4
)
??
""
;
unowned
var
postal_code
=
values
.
nth_data
(
5
)
??
""
;
unowned
var
country
=
values
.
nth_data
(
6
)
??
""
;
var
addr
=
new
PostalAddress
(
po_box
,
extension
,
street
,
locality
,
region
,
postal_code
,
country
,
""
,
null
);
var
addr_fd
=
new
PostalAddressFieldDetails
((
owned
)
addr
);
add_params
(
addr_fd
,
attr
);
insert_field_details
<
PostalAddressFieldDetails
>
(
details
,
PersonaDetail
.
POSTAL_ADDRESSES
,
addr_fd
,
AbstractFieldDetails
<
PostalAddress
>.
hash_static
,
AbstractFieldDetails
<
PostalAddress
>.
equal_static
);
address
.
po_box
=
values
.
nth_data
(
0
)
??
""
;
address
.
extension
=
values
.
nth_data
(
1
)
??
""
;
address
.
street
=
values
.
nth_data
(
2
)
??
""
;
address
.
locality
=
values
.
nth_data
(
3
)
??
""
;
address
.
region
=
values
.
nth_data
(
4
)
??
""
;
address
.
postal_code
=
values
.
nth_data
(
5
)
??
""
;
address
.
country
=
values
.
nth_data
(
6
)
??
""
;
add_params
(
child
,
attr
);
}
private
void
handle_url
(
HashTable
<
string
,
Value
?>
details
,
E
.
VCardAttribute
attr
)
{
private
void
handle_url
(
Contact
contact
,
E
.
VCardAttribute
attr
)
{
var
url
=
attr
.
get_value
();
if
(
url
==
null
||
url
==
""
)
return
;
var
url_fd
=
new
UrlFieldDetails
(
url
);
add_params
(
url_fd
,
attr
);
insert_field_details
<
UrlFieldDetails
>
(
details
,
PersonaDetail
.
URLS
,
url_fd
,
AbstractFieldDetails
<
string
>.
hash_static
,
AbstractFieldDetails
<
string
>.
equal_static
);
var
child
=
add_chunk_child_for_property
(
contact
,
"urls"
);
((
Contacts
.
Url
)
child
).
url
=
url
;
add_params
(
child
,
attr
);
}
private
void
handle_note
(
HashTable
<
string
,
Value
?>
details
,
E
.
VCardAttribute
attr
)
{
private
void
handle_note
(
Contact
contact
,
E
.
VCardAttribute
attr
)
{
var
note
=
attr
.
get_value
();
if
(
note
==
null
||
note
==
""
)
return
;
var
note_fd
=
new
NoteFieldDetails
(
note
);
add_params
(
note_fd
,
attr
);
insert_field_details
<
NoteFieldDetails
>
(
details
,
PersonaDetail
.
NOTES
,
note_fd
,
AbstractFieldDetails
<
string
>.
hash_static
,
AbstractFieldDetails
<
string
>.
equal_static
);
var
child
=
add_chunk_child_for_property
(
contact
,
"notes"
);
((
Contacts
.
Note
)
child
).
text
=
note
;
add_params
(
child
,
attr
);
}
// Helper method for inserting aggregated properties
private
bool
insert_field_details
<
T
>
(
HashTable
<
string
,
Value
?>
details
,
PersonaDetail
key
,
T
field_details
,
owned
Gee
.
HashDataFunc
<
T
>?
hash_func
,
owned
Gee
.
EqualDataFunc
<
T
>?
equal_func
)
{
// Get the existing set, or create a new one and add it
unowned
var
old_val
=
details
.
lookup
(
Folks
.
PersonaStore
.
detail_key
(
key
));
if
(
old_val
!=
null
)
{
unowned
var
values
=
old_val
as
Gee
.
HashSet
<
T
>;
return
values
.
add
(
field_details
);
}
var
values
=
new
Gee
.
HashSet
<
T
>
((
owned
)
hash_func
,
(
owned
)
equal_func
);
Value
?
new_val
=
Value
(
typeof
(
Gee
.
Set
));
new_val
.
set_object
(
values
);
details
.
insert
(
Folks
.
PersonaStore
.
detail_key
(
key
),
(
owned
)
new_val
);
return
values
.
add
(
field_details
);
private
void
add_chunk_child_for_property
(
Contact
contact
,
string
property_name
)
{
var
chunk
=
contact
.
get_most_relevant_chunk
(
property_name
,
true
);
if
(
chunk
==
null
)
chunk
=
contact
.
create_chunk
(
property_name
,
null
);
return_if_fail
(
chunk
is
BinChunk
);
return
((
BinChunk
)
chunk
).
create_empty_child
();
}
// Helper method to get VCard parameters into a
n AbstractFieldDetails object.
// Helper method to get VCard parameters into a
BinChunkChild
// Will take care of setting the correct "type"
private
void
add_params
(
AbstractFieldDetails
deta
il
s
,
E
.
VCardAttribute
attr
)
{
private
void
add_params
(
BinChunkChild
chunk_c
il
d
,
E
.
VCardAttribute
attr
)
{
foreach
(
unowned
E
.
VCardAttributeParam
param
in
attr
.
get_params
())
{
string
param_name
=
param
.
get_name
().
down
();
foreach
(
unowned
string
param_value
in
param
.
get_values
())
{
if
(
param_name
==
AbstractFieldDetails
.
PARAM_TYPE
)
details
.
add_
parameter
(
param_name
,
param_value
.
down
());
if
(
param_name
==
"type"
)
chunk_child
.
parameter
s
.
add
(
param_name
,
param_value
.
down
());
else