1
/****************************************************************************
2
* Copyright (C) 2013-2014 by Savoir-Faire Linux *
3
* Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> *
5
* This library is free software; you can redistribute it and/or *
6
* modify it under the terms of the GNU Lesser General Public *
7
* License as published by the Free Software Foundation; either *
8
* version 2.1 of the License, or (at your option) any later version. *
10
* This library is distributed in the hope that it will be useful, *
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
13
* Lesser General Public License for more details. *
15
* You should have received a copy of the GNU General Public License *
16
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
17
***************************************************************************/
18
#include "phonenumber.h"
19
#include "phonedirectorymodel.h"
23
#include "dbus/presencemanager.h"
24
#include "numbercategorymodel.h"
25
#include "numbercategory.h"
27
QHash<int,Call*> PhoneNumber::m_shMostUsed = QHash<int,Call*>();
29
const PhoneNumber* PhoneNumber::m_spBlank = nullptr;
30
const PhoneNumber* PhoneNumber::BLANK()
33
m_spBlank = new PhoneNumber("",NumberCategoryModel::other());
34
const_cast<PhoneNumber*>(m_spBlank)->m_Type = PhoneNumber::Type::BLANK;
40
PhoneNumber::PhoneNumber(const QString& number, NumberCategory* cat, Type st) : QObject(PhoneDirectoryModel::instance()),
41
m_Uri(stripUri(number)),m_pCategory(cat),m_Tracked(false),m_Present(false),m_LastUsed(0),
42
m_Type(st),m_PopularityIndex(-1),m_pContact(nullptr),m_pAccount(nullptr),
43
m_LastWeekCount(0),m_LastTrimCount(0),m_HaveCalled(false),m_IsBookmark(false),m_TotalSeconds(0)
46
m_hasType = cat != NumberCategoryModel::other();
48
NumberCategoryModel::instance()->registerNumber(this);
52
PhoneNumber::~PhoneNumber()
56
///Return if this number presence is being tracked
57
bool PhoneNumber::isTracked() const
59
//If the number doesn't support it, ignore the flag
60
return supportPresence() && m_Tracked;
63
///Is this number present
64
bool PhoneNumber::isPresent() const
66
return m_Tracked && m_Present;
69
///This number presence status string
70
QString PhoneNumber::presenceMessage() const
72
return m_PresentMessage;
76
QString PhoneNumber::uri() const {
80
///Return the phone number type
81
NumberCategory* PhoneNumber::category() const {
85
///Return this number associated account, if any
86
Account* PhoneNumber::account() const
91
///Return this number associated contact, if any
92
Contact* PhoneNumber::contact() const
97
///Return when this number was last used
98
time_t PhoneNumber::lastUsed() const
103
///Set this number default account
104
void PhoneNumber::setAccount(Account* account)
106
m_pAccount = account;
108
connect (m_pAccount,SIGNAL(destroyed(QObject*)),this,SLOT(accountDestroyed(QObject*)));
112
///Set this number contact
113
void PhoneNumber::setContact(Contact* contact)
115
m_pContact = contact;
116
if (contact && m_Type != PhoneNumber::Type::TEMPORARY)
117
PhoneDirectoryModel::instance()->indexNumber(this,m_hNames.keys()+QStringList(contact->formattedName()));
121
void PhoneNumber::setCategory(NumberCategory* cat)
123
if (cat == m_pCategory) return;
125
NumberCategoryModel::instance()->unregisterNumber(this);
126
m_hasType = cat != NumberCategoryModel::other();
129
NumberCategoryModel::instance()->registerNumber(this);
133
void PhoneNumber::setBookmarked(bool bookmarked )
135
m_IsBookmark = bookmarked;
138
///Force an Uid on this number (instead of hash)
139
void PhoneNumber::setUid(const QString& uri)
144
///Attempt to change the number type
145
bool PhoneNumber::setType(PhoneNumber::Type t)
147
if (m_Type == PhoneNumber::Type::BLANK)
149
if (account() && t == PhoneNumber::Type::ACCOUNT) {
150
if (account()->supportPresenceSubscribe()) {
151
m_Tracked = true; //The daemon will init the tracker itself
152
emit trackedChanged(true);
160
///Set if this number is tracking presence information
161
void PhoneNumber::setTracked(bool track)
163
if (track != m_Tracked) { //Subscribe only once
164
//You can't subscribe without account
165
if (track && !m_pAccount) return;
167
DBus::PresenceManager::instance().subscribeBuddy(m_pAccount->id(),fullUri(),track);
169
emit trackedChanged(track);
173
///Allow phonedirectorymodel to change presence status
174
void PhoneNumber::setPresent(bool present)
176
if (m_Present != present) {
178
emit presentChanged(present);
182
void PhoneNumber::setPresenceMessage(const QString& message)
184
if (m_PresentMessage != message) {
185
m_PresentMessage = message;
186
emit presenceMessageChanged(message);
190
///Return the current type of the number
191
PhoneNumber::Type PhoneNumber::type() const
196
///Return the number of calls from this number
197
int PhoneNumber::callCount() const
199
return m_lCalls.size();
202
uint PhoneNumber::weekCount() const
204
return m_LastWeekCount;
207
uint PhoneNumber::trimCount() const
209
return m_LastTrimCount;
212
bool PhoneNumber::haveCalled() const
217
///Best bet for this person real name
218
QString PhoneNumber::primaryName() const
221
return m_pContact->formattedName();
222
else if (m_hNames.size() == 1)
223
return m_hNames.constBegin().key();
225
QString toReturn = tr("Unknown");
226
QHash<QString,int>::const_iterator i = m_hNames.constBegin();
228
while (i != m_hNames.end()) {
229
if (i.value() > max) {
238
///Is this number bookmarked
239
bool PhoneNumber::isBookmarked() const
244
///If this number could (theoretically) support presence status
245
bool PhoneNumber::supportPresence() const
247
//Without an account, presence is impossible
250
//The account also have to support it
251
if (!m_pAccount->supportPresenceSubscribe())
254
//In the end, it all come down to this, is the number tracked
258
///Proxy accessor to the category icon
259
QVariant PhoneNumber::icon() const
261
return category()->icon(isTracked(),isPresent());
264
///The number of seconds spent with the URI (from history)
265
int PhoneNumber::totalSpentTime() const
267
return m_TotalSeconds;
270
///Return this number unique identifier (hash)
271
QString PhoneNumber::uid() const
273
return m_Uid.isEmpty()?toHash():m_Uid;
276
///Return all calls from this number
277
QList<Call*> PhoneNumber::calls() const
282
///Return the phonenumber position in the popularity index
283
int PhoneNumber::popularityIndex() const
285
return m_PopularityIndex;
288
QHash<QString,int> PhoneNumber::alternativeNames() const
293
///Add a call to the call list, notify listener
294
void PhoneNumber::addCall(Call* call)
297
m_Type = PhoneNumber::Type::USED;
299
m_TotalSeconds += call->stopTimeStamp() - call->startTimeStamp();
302
if (now - 3600*24*7 < call->stopTimeStamp())
304
if (now - 3600*24*7*15 < call->stopTimeStamp())
307
if (call->historyState() == Call::LegacyHistoryState::OUTGOING || call->direction() == Call::Direction::OUTGOING)
310
emit callAdded(call);
311
if (call->startTimeStamp() > m_LastUsed)
312
m_LastUsed = call->startTimeStamp();
316
///Generate an unique representation of this number
317
QString PhoneNumber::toHash() const
319
return QString("%1///%2///%3").arg(uri()).arg(account()?account()->id():QString()).arg(contact()?contact()->uid():QString());
323
///Return the domaine of an URI (<sip:12345@exemple.com>)
324
QString PhoneNumber::hostname() const
326
if (m_Uri.indexOf('@') != -1) {
327
return m_Uri.split('@')[1].left(m_Uri.split('@')[1].size());
332
QString PhoneNumber::fullUri() const
334
return QString("<sip:%1>").arg(m_Uri);
338
///Strip out <sip:****> from the URI
339
QString PhoneNumber::stripUri(const QString& uri)
341
int start(0),end(uri.size()-1); //Other type of comparaisons were too slow
342
if (uri.size() > 0 && uri[0] == '<' && uri[4] == ':')
344
if (end && uri[end] == '>')
346
return uri.mid(start,end-start+1);
349
///Increment name counter and update indexes
350
void PhoneNumber::incrementAlternativeName(const QString& name)
352
const bool needReIndexing = !m_hNames[name];
354
if (needReIndexing && m_Type != PhoneNumber::Type::TEMPORARY)
355
PhoneDirectoryModel::instance()->indexNumber(this,m_hNames.keys()+(m_pContact?(QStringList(m_pContact->formattedName())):QStringList()));
358
void PhoneNumber::accountDestroyed(QObject* o)
361
m_pAccount = nullptr;
364
/************************************************************************************
366
* Temporary phone number *
368
***********************************************************************************/
370
void TemporaryPhoneNumber::setUri(const QString& uri)
377
TemporaryPhoneNumber::TemporaryPhoneNumber(const PhoneNumber* number) :
378
PhoneNumber(QString(),NumberCategoryModel::other(),PhoneNumber::Type::TEMPORARY)
381
setContact(number->contact());
382
setAccount(number->account());