xref: /haiku/src/apps/mail/People.cpp (revision d0ac609964842f8cdb6d54b3c539c6c15293e172)
1 /*
2  * Copyright 2015, 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
16 PersonName(BNode& node)
17 {
18 	BString fullName;
19 	node.ReadAttrString("META:name", &fullName);
20 
21 	return fullName;
22 }
23 
24 
25 static void
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
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 
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 
87 Person::~Person()
88 {
89 }
90 
91 
92 bool
93 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 
106 PersonList::PersonList(QueryList& query)
107 	:
108 	fQueryList(query),
109 	fPersons(10, true)
110 {
111 	fQueryList.AddListener(this);
112 }
113 
114 
115 PersonList::~PersonList()
116 {
117 	fQueryList.RemoveListener(this);
118 }
119 
120 
121 void
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
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 		fPersons.RemoveItem(person);
141 		fPersonMap.erase(found);
142 		delete person;
143 	}
144 }
145 
146 
147 // #pragma mark - GroupList
148 
149 
150 GroupList::GroupList(QueryList& query)
151 	:
152 	fQueryList(query)
153 {
154 	fQueryList.AddListener(this);
155 }
156 
157 
158 GroupList::~GroupList()
159 {
160 	fQueryList.RemoveListener(this);
161 }
162 
163 
164 void
165 GroupList::EntryCreated(QueryList& source, const entry_ref& ref, ino_t _node)
166 {
167 	BNode node(&ref);
168 	if (node.InitCheck() != B_OK)
169 		return;
170 
171 	BAutolock locker(this);
172 
173 	BStringList groups;
174 	AddPersonGroups(node, groups);
175 
176 	for (int32 index = 0; index < groups.CountStrings(); index++) {
177 		BString group = groups.StringAt(index);
178 
179 		StringCountMap::iterator found = fGroupMap.find(group);
180 		if (found != fGroupMap.end())
181 			found->second++;
182 		else {
183 			fGroupMap[group] = 1;
184 			fGroups.Add(group);
185 		}
186 	}
187 
188 	// TODO: sort groups
189 }
190 
191 
192 void
193 GroupList::EntryRemoved(QueryList& source, const node_ref& nodeRef)
194 {
195 	// TODO!
196 }
197