xref: /haiku/src/apps/mail/People.cpp (revision bab64f65bb775dc23060e276f1f1c4498ab7af6c)
1 /*
2  * Copyright 2015-2016, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "People.h"
8 
9 #include <stdio.h>
10 
11 #include <Autolock.h>
12 #include <Node.h>
13 
14 
15 static BString
PersonName(BNode & node)16 PersonName(BNode& node)
17 {
18 	BString fullName;
19 	node.ReadAttrString("META:name", &fullName);
20 
21 	return fullName;
22 }
23 
24 
25 static void
AddPersonAddresses(BNode & node,BStringList & addresses)26 AddPersonAddresses(BNode& node, BStringList& addresses)
27 {
28 	BString email;
29 	if (node.ReadAttrString("META:email", &email) != B_OK || email.IsEmpty())
30 		return;
31 
32 	addresses.Add(email);
33 
34 	// Support for 3rd-party People apps
35 	for (int i = 2; i < 99; i++) {
36 		char attr[32];
37 		snprintf(attr, sizeof(attr), "META:email%d", i);
38 
39 		if (node.ReadAttrString(attr, &email) != B_OK)
40 			break;
41 
42 		addresses.Add(email);
43 	}
44 }
45 
46 
47 static void
AddPersonGroups(BNode & node,BStringList & groups)48 AddPersonGroups(BNode& node, BStringList& groups)
49 {
50 	BString groupString;
51 	if (node.ReadAttrString("META:group", &groupString) != B_OK
52 		|| groupString.IsEmpty()) {
53 		return;
54 	}
55 
56 	int first = 0;
57 	while (first < groupString.Length()) {
58 		int end = groupString.FindFirst(',', first);
59 		if (end < 0)
60 			end = groupString.Length();
61 
62 		BString group;
63 		groupString.CopyInto(group, first, end - first);
64 		group.Trim();
65 		groups.Add(group);
66 
67 		first = end + 1;
68 	}
69 }
70 
71 
72 // #pragma mark - Person
73 
74 
Person(const entry_ref & ref)75 Person::Person(const entry_ref& ref)
76 {
77 	BNode node(&ref);
78 	if (node.InitCheck() != B_OK)
79 		return;
80 
81 	fName = PersonName(node);
82 	AddPersonAddresses(node, fAddresses);
83 	AddPersonGroups(node, fGroups);
84 }
85 
86 
~Person()87 Person::~Person()
88 {
89 }
90 
91 
92 bool
IsInGroup(const char * group) const93 Person::IsInGroup(const char* group) const
94 {
95 	for (int32 index = 0; index < CountGroups(); index++) {
96 		if (GroupAt(index) == group)
97 			return true;
98 	}
99 	return false;
100 }
101 
102 
103 // #pragma mark - PersonList
104 
105 
PersonList(QueryList & query)106 PersonList::PersonList(QueryList& query)
107 	:
108 	fQueryList(query),
109 	fPersons(10, true)
110 {
111 	fQueryList.AddListener(this);
112 }
113 
114 
~PersonList()115 PersonList::~PersonList()
116 {
117 	fQueryList.RemoveListener(this);
118 }
119 
120 
121 void
EntryCreated(QueryList & source,const entry_ref & ref,ino_t node)122 PersonList::EntryCreated(QueryList& source, const entry_ref& ref, ino_t node)
123 {
124 	BAutolock locker(this);
125 
126 	Person* person = new Person(ref);
127 	fPersons.AddItem(person);
128 	fPersonMap.insert(std::make_pair(node_ref(ref.device, node), person));
129 }
130 
131 
132 void
EntryRemoved(QueryList & source,const node_ref & nodeRef)133 PersonList::EntryRemoved(QueryList& source, const node_ref& nodeRef)
134 {
135 	BAutolock locker(this);
136 
137 	PersonMap::iterator found = fPersonMap.find(nodeRef);
138 	if (found != fPersonMap.end()) {
139 		Person* person = found->second;
140 		fPersonMap.erase(found);
141 		fPersons.RemoveItem(person);
142 	}
143 }
144 
145 
146 // #pragma mark - GroupList
147 
148 
GroupList(QueryList & query)149 GroupList::GroupList(QueryList& query)
150 	:
151 	fQueryList(query)
152 {
153 	fQueryList.AddListener(this);
154 }
155 
156 
~GroupList()157 GroupList::~GroupList()
158 {
159 	fQueryList.RemoveListener(this);
160 }
161 
162 
163 void
EntryCreated(QueryList & source,const entry_ref & ref,ino_t _node)164 GroupList::EntryCreated(QueryList& source, const entry_ref& ref, ino_t _node)
165 {
166 	BNode node(&ref);
167 	if (node.InitCheck() != B_OK)
168 		return;
169 
170 	BAutolock locker(this);
171 
172 	BStringList groups;
173 	AddPersonGroups(node, groups);
174 
175 	for (int32 index = 0; index < groups.CountStrings(); index++) {
176 		BString group = groups.StringAt(index);
177 
178 		StringCountMap::iterator found = fGroupMap.find(group);
179 		if (found != fGroupMap.end())
180 			found->second++;
181 		else {
182 			fGroupMap[group] = 1;
183 			fGroups.Add(group);
184 		}
185 	}
186 
187 	// TODO: sort groups
188 }
189 
190 
191 void
EntryRemoved(QueryList & source,const node_ref & nodeRef)192 GroupList::EntryRemoved(QueryList& source, const node_ref& nodeRef)
193 {
194 	// TODO!
195 }
196