/
recipient.h
279 lines (219 loc) · 9 KB
/
recipient.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
/******************************************************************************
**
** This file is part of libcommhistory.
**
** Copyright (C) 2014 Jolla Ltd.
** Contact: John Brooks <john.brooks@jolla.com>
**
** This library is free software; you can redistribute it and/or modify it
** under the terms of the GNU Lesser General Public License version 2.1 as
** published by the Free Software Foundation.
**
** This library is distributed in the hope that it will be useful, but
** WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
** or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
** License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this library; if not, write to the Free Software Foundation, Inc.,
** 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
**
******************************************************************************/
#ifndef COMMHISTORY_RECIPIENT_H
#define COMMHISTORY_RECIPIENT_H
#include "libcommhistoryexport.h"
#include <seasidecache.h>
#include <QObject>
#include <QDBusArgument>
#include <QSharedPointer>
#include <QHash>
#include <QDebug>
namespace CommHistory {
/* TODO:
* - Handling for multiple matching contacts on a recipient
* - hidden/private numbers
* - Outgoing events with multiple recipients
* - Number normalization
* - DB representation
*/
class RecipientPrivate;
typedef QWeakPointer<RecipientPrivate> WeakRecipient;
/* Represents one remote peer's address
*
* A recipient represents the pair of a localUid (local account address)
* and remoteUid (remote peer's address on that account). It centralizes
* logic for comparing addresses, display, and resolving matching contacts.
*
* Recipient's data is shared among instances which represent exactly the
* same address, which ensures contact caching and consistent representation.
*
* Instances may be equal without being exactly identical, e.g. when using
* minimized phone number comparisons. In that case, they may not be shared.
*/
class LIBCOMMHISTORY_EXPORT Recipient
{
public:
struct PhoneNumberMatchDetails {
QString number;
QString minimizedNumber;
quint32 minimizedNumberHash;
};
Recipient();
Recipient(const QString &localUid, const QString &remoteUid);
Recipient(const Recipient &o);
Recipient(const WeakRecipient &weak);
Recipient &operator=(const Recipient &o);
~Recipient();
bool isNull() const;
QString displayName() const;
QString localUid() const;
QString remoteUid() const;
bool isPhoneNumber() const;
QString minimizedPhoneNumber() const;
QString minimizedRemoteUid() const;
bool operator==(const Recipient &o) const;
bool operator!=(const Recipient &o) const { return !operator==(o); }
bool matches(const Recipient &o) const;
bool isSameContact(const Recipient &o) const;
bool matchesRemoteUid(const QString &remoteUid) const;
bool matchesPhoneNumber(const PhoneNumberMatchDetails &phoneNumber) const;
bool matchesAddressFlags(quint64 flags) const;
int contactId() const;
QString contactName() const;
QUrl contactAvatarUrl() const;
bool isContactResolved() const;
/* Update the resolved contact for this recipient
*
* Generally, this is only called by the contact resolver, but it can be
* used to inject known contact matches. The change will apply to all
* Recipient instances that compare equal to this instance.
*
* A null item pointer is taken to mean that no contact matches. In this
* case, the contact is still considered resolved.
*
* Returns true if the receipient resolution was updated.
*/
bool setResolved(SeasideCache::CacheItem *item) const;
/* Removes the resolved contact from this recipient
*
* Generally, this is only called by the contact listener.
*
* Unlike setResolved() called with a null item pointer, after this function
* the contact is no longer considered resolved. Typically, resolution
* will be attempted again, resulting in the recipient being resolved
* once more.
*/
void setUnresolved() const;
/* Returns true if a contact update updates any property of the recipient
*
* Generally, this is only called by the contact listener.
*/
bool contactUpdateIsSignificant() const;
/* Get all existing recipients that are resolved to a contact ID
*
* This is primarily used for contact change notifications. contactId
* may be 0, which returns all Recipient which have been resolved but
* had no contact matches.
*/
static QList<Recipient> recipientsForContact(int contactId);
/* Return the string in the form suitable for testing phone number matches
*/
static PhoneNumberMatchDetails phoneNumberMatchDetails(const QString &s);
/* Represent the current recipient as suitable for phone number matching
*/
PhoneNumberMatchDetails toPhoneNumberMatchDetails() const;
private:
QSharedPointer<RecipientPrivate> d;
friend uint qHash(const CommHistory::Recipient &value, uint seed);
};
class LIBCOMMHISTORY_EXPORT RecipientList
{
public:
RecipientList();
RecipientList(const Recipient &recipient);
RecipientList(const QList<Recipient> &recipients);
static RecipientList fromUids(const QString &localUid, const QStringList &remoteUids);
static RecipientList fromContact(int contactId);
static RecipientList fromContact(const QContactId &contactId);
bool isEmpty() const;
int size() const;
int count() const { return size(); }
QList<Recipient> recipients() const;
QStringList displayNames() const;
QList<int> contactIds() const;
QStringList remoteUids() const;
bool operator==(const RecipientList &o) const;
bool operator!=(const RecipientList &o) const { return !operator==(o); }
bool matches(const RecipientList &o) const;
bool hasSameContacts(const RecipientList &o) const;
bool matchesRemoteUid(const QString &remoteUid) const
{
for (const_iterator it = constBegin(), end = constEnd(); it != end; ++it)
if (it->matchesRemoteUid(remoteUid))
return true;
return false;
}
bool matchesPhoneNumber(const Recipient::PhoneNumberMatchDetails &phoneNumber) const
{
for (const_iterator it = constBegin(), end = constEnd(); it != end; ++it)
if (it->matchesPhoneNumber(phoneNumber))
return true;
return false;
}
template<typename Sequence>
bool intersects(const Sequence &sequence) const
{
for (typename Sequence::const_iterator it = sequence.constBegin(), end = sequence.constEnd(); it != end; ++it)
if (contains(*it))
return true;
return false;
}
template<typename Sequence>
bool intersectsMatch(const Sequence &sequence) const
{
for (typename Sequence::const_iterator it = sequence.constBegin(), end = sequence.constEnd(); it != end; ++it)
if (containsMatch(*it))
return true;
return false;
}
bool allContactsResolved() const;
QString debugString() const;
typedef QList<Recipient>::const_iterator const_iterator;
typedef QList<Recipient>::iterator iterator;
iterator begin();
iterator end();
iterator find(const Recipient &r);
iterator findMatch(const Recipient &r);
const_iterator begin() const { return constBegin(); }
const_iterator end() const { return constEnd(); }
const_iterator constBegin() const;
const_iterator constEnd() const;
const_iterator constFind(const Recipient &r) const;
const_iterator constFindMatch(const Recipient &r) const;
bool contains(const Recipient &r) const;
bool containsMatch(const Recipient &r) const;
Recipient value(int index) const;
const Recipient &at(int index) const;
const Recipient &first() const { return at(0); }
void append(const Recipient &r);
void append(const QList<Recipient> &o);
RecipientList &unite(const RecipientList &other);
RecipientList &operator<<(const Recipient &recipient);
private:
static RecipientList fromCacheItem(const SeasideCache::CacheItem *item);
QList<Recipient> m_recipients;
};
inline uint qHash(const CommHistory::Recipient &value, uint seed = 0)
{
return ::qHash(value.d.data(), seed);
}
}
LIBCOMMHISTORY_EXPORT QDebug &operator<<(QDebug &debug, const CommHistory::Recipient &recipient);
LIBCOMMHISTORY_EXPORT QDebug &operator<<(QDebug &debug, const CommHistory::RecipientList &recipientList);
QDBusArgument &operator<<(QDBusArgument &argument, const CommHistory::Recipient &recipient);
const QDBusArgument &operator>>(const QDBusArgument &argument, CommHistory::Recipient &recipient);
QDBusArgument &operator<<(QDBusArgument &argument, const CommHistory::RecipientList &recipients);
const QDBusArgument &operator>>(const QDBusArgument &argument, CommHistory::RecipientList &recipients);
Q_DECLARE_METATYPE(CommHistory::Recipient)
Q_DECLARE_METATYPE(CommHistory::RecipientList)
#endif