From 180d44199aa35de656b7b8bdb41c8bfb06f0e9fd Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> Date: Thu, 23 Apr 2015 11:06:04 -0400 Subject: [PATCH] autocompletion: Add the dialing number to the choices Refs #71035 --- src/account.cpp | 28 ++++----- src/account.h | 26 ++++---- src/accountmodel.cpp | 12 ++-- src/accountmodel.h | 2 + src/contactmethod.cpp | 5 ++ src/contactmethod.h | 4 +- src/numbercompletionmodel.cpp | 112 ++++++++++++++++++++++++++++++++-- src/useractionmodel.cpp | 9 +-- 8 files changed, 157 insertions(+), 41 deletions(-) diff --git a/src/account.cpp b/src/account.cpp index 30858f1d..839930f2 100644 --- a/src/account.cpp +++ b/src/account.cpp @@ -432,22 +432,22 @@ BootstrapModel* Account::bootstrapModel() const return d_ptr->m_pBootstrapModel; } -bool Account::haveCalled() const +bool Account::isUsedForOutgogingCall() const { return d_ptr->m_HaveCalled; } -uint Account::totalCount() const +uint Account::totalCallCount() const { return d_ptr->m_TotalCount; } -uint Account::lastWeekCount() const +uint Account::weekCallCount() const { return d_ptr->m_LastWeekCount; } -uint Account::lastTrimCount() const +uint Account::trimesterCallCount() const { return d_ptr->m_LastTrimCount; } @@ -961,16 +961,16 @@ QVariant Account::roleData(int role) const return PresenceStatusModel::instance()->currentMessage(); case CAST(Account::Role::RegistrationState): return QVariant::fromValue(registrationState()); - case CAST(Account::Role::HaveCalled ): - return haveCalled (); - case CAST(Account::Role::TotalCount ): - return totalCount (); - case CAST(Account::Role::LastWeekCount): - return lastWeekCount (); - case CAST(Account::Role::LastTrimCount): - return lastTrimCount (); - case CAST(Account::Role::LastUsed ): - return (int)lastUsed (); + case CAST(Account::Role::UsedForOutgogingCall): + return isUsedForOutgogingCall(); + case CAST(Account::Role::TotalCallCount): + return totalCallCount(); + case CAST(Account::Role::WeekCallCount): + return weekCallCount(); + case CAST(Account::Role::TrimesterCallCount): + return trimesterCallCount(); + case CAST(Account::Role::LastUsed): + return (int)lastUsed(); default: return QVariant(); } diff --git a/src/account.h b/src/account.h index 45554484..3476be4a 100644 --- a/src/account.h +++ b/src/account.h @@ -141,10 +141,10 @@ class LIB_EXPORT Account : public QObject { Q_PROPERTY(QString userAgent READ userAgent WRITE setUserAgent ) Q_PROPERTY(bool useDefaultPort READ useDefaultPort WRITE setUseDefaultPort ) Q_PROPERTY(RegistrationState registrationState READ registrationState ) - Q_PROPERTY(bool haveCalled READ haveCalled ) - Q_PROPERTY(uint totalCount READ totalCount ) - Q_PROPERTY(uint lastWeekCount READ lastWeekCount ) - Q_PROPERTY(uint lastTrimCount READ lastTrimCount ) + Q_PROPERTY(bool usedForOutgogingCall READ isUsedForOutgogingCall ) + Q_PROPERTY(uint totalCallCount READ totalCallCount ) + Q_PROPERTY(uint weekCallCount READ weekCallCount ) + Q_PROPERTY(uint trimesterCallCount READ trimesterCallCount ) Q_PROPERTY(time_t lastUsed READ lastUsed ) public: @@ -225,10 +225,10 @@ class LIB_EXPORT Account : public QObject { PresenceMessage = 143, RegistrationState = 144, UseDefaultPort = 145, - HaveCalled = 146, - TotalCount = 147, - LastWeekCount = 148, - LastTrimCount = 149, + UsedForOutgogingCall = 146, + TotalCallCount = 147, + WeekCallCount = 148, + TrimesterCallCount = 149, LastUsed = 150, }; @@ -327,11 +327,11 @@ class LIB_EXPORT Account : public QObject { Protocol protocol () const; KeyExchangeModel::Type keyExchange () const; - bool haveCalled () const; - uint totalCount () const; - uint lastWeekCount () const; - uint lastTrimCount () const; - time_t lastUsed () const; + bool isUsedForOutgogingCall () const; + uint totalCallCount () const; + uint weekCallCount () const; + uint trimesterCallCount () const; + time_t lastUsed () const; Q_INVOKABLE QVariant roleData ( int role ) const; Q_INVOKABLE bool supportScheme( URI::SchemeType type ) ; diff --git a/src/accountmodel.cpp b/src/accountmodel.cpp index 9f331ad3..87200504 100644 --- a/src/accountmodel.cpp +++ b/src/accountmodel.cpp @@ -142,10 +142,10 @@ QHash<int,QByteArray> AccountModel::roleNames() const roles.insert(CAST(Account::Role::TypeName ) ,QByteArray("typeName" )); roles.insert(CAST(Account::Role::PresenceStatus ) ,QByteArray("presenceStatus" )); roles.insert(CAST(Account::Role::PresenceMessage ) ,QByteArray("presenceMessage" )); - roles.insert(CAST(Account::Role::HaveCalled ) ,QByteArray("haveCalled" )); - roles.insert(CAST(Account::Role::TotalCount ) ,QByteArray("totalCount" )); - roles.insert(CAST(Account::Role::LastWeekCount ) ,QByteArray("lastWeekCount" )); - roles.insert(CAST(Account::Role::LastTrimCount ) ,QByteArray("lastTrimCount" )); + roles.insert(CAST(Account::Role::UsedForOutgogingCall ) ,QByteArray("usedForOutgogingCall" )); + roles.insert(CAST(Account::Role::TotalCallCount ) ,QByteArray("totalCallCount" )); + roles.insert(CAST(Account::Role::WeekCallCount ) ,QByteArray("weekCallCount" )); + roles.insert(CAST(Account::Role::TrimesterCallCount ) ,QByteArray("trimesterCallCount" )); roles.insert(CAST(Account::Role::LastUsed ) ,QByteArray("lastUsed" )); } return roles; @@ -403,6 +403,8 @@ void AccountModel::updateAccounts() if (a->id() != DRing::Account::ProtocolNames::IP2IP) d_ptr->enableProtocol(a->protocol()); + + emit accountAdded(a); } else { acc->performAction(Account::EditAction::RELOAD); @@ -673,6 +675,8 @@ Account* AccountModel::add(const QString& alias, const Account::Protocol proto) if (a->id() != DRing::Account::ProtocolNames::IP2IP) d_ptr->enableProtocol(proto); + emit accountAdded(a); + return a; } diff --git a/src/accountmodel.h b/src/accountmodel.h index e6f51857..1451f857 100644 --- a/src/accountmodel.h +++ b/src/accountmodel.h @@ -133,6 +133,8 @@ Q_SIGNALS: void presenceEnabledChanged(bool isPresent ); ///An account has been removed void accountRemoved(Account* account ); + ///An account has been added + void accountAdded(Account* account ); ///Emitted when an account using a previously unsupported protocol is added void supportedProtocolsChanged( ); ///Emitted when an account state change diff --git a/src/contactmethod.cpp b/src/contactmethod.cpp index 82f7e2cc..458be763 100644 --- a/src/contactmethod.cpp +++ b/src/contactmethod.cpp @@ -415,6 +415,11 @@ QVariant ContactMethod::icon() const return category()->icon(isTracked(),isPresent()); } +QVariant TemporaryContactMethod::icon() const +{ + return QVariant(); //TODO use the pixmap delegate to get a better icon +} + ///The number of seconds spent with the URI (from history) int ContactMethod::totalSpentTime() const { diff --git a/src/contactmethod.h b/src/contactmethod.h index 9b3c50d0..faaf10b8 100644 --- a/src/contactmethod.h +++ b/src/contactmethod.h @@ -108,7 +108,7 @@ public: QString primaryName () const; bool isBookmarked () const; bool supportPresence () const; - QVariant icon () const; + virtual QVariant icon () const; int totalSpentTime () const; QString uid () const; URI::ProtocolHint protocolHint () const; @@ -208,7 +208,9 @@ class LIB_EXPORT TemporaryContactMethod : public ContactMethod { Q_OBJECT public: explicit TemporaryContactMethod(const ContactMethod* number = nullptr); + virtual QVariant icon() const override; void setUri(const URI& uri); + }; #endif diff --git a/src/numbercompletionmodel.cpp b/src/numbercompletionmodel.cpp index 2b4ebc5a..e94730fd 100644 --- a/src/numbercompletionmodel.cpp +++ b/src/numbercompletionmodel.cpp @@ -63,6 +63,7 @@ public: void locateNameRange (const QString& prefix, QSet<ContactMethod*>& set); void locateNumberRange(const QString& prefix, QSet<ContactMethod*>& set); uint getWeight(ContactMethod* number); + uint getWeight(Account* account); void getRange(QMap<QString,NumberWrapper*> map, const QString& prefix, QSet<ContactMethod*>& set) const; //Attributes @@ -77,6 +78,9 @@ public: public Q_SLOTS: void setPrefix(const QString& str); + bool accountAdded (Account* a); + void accountRemoved(Account* a); + private: NumberCompletionModel* q_ptr; }; @@ -85,15 +89,44 @@ private: NumberCompletionModelPrivate::NumberCompletionModelPrivate(NumberCompletionModel* parent) : QObject(parent), q_ptr(parent), m_pCall(nullptr),m_Enabled(false),m_UseUnregisteredAccount(true) { + //Create the temporary number list + bool hasNonIp2Ip = false; + Account* ip2ip = AccountModel::instance()->ip2ip(); + + for (int i =0; i < AccountModel::instance()->size();i++) { + Account* a = (*AccountModel::instance())[i]; + if (a != ip2ip) { + hasNonIp2Ip |= accountAdded(a); + } + } + + //If SIP accounts are present, IP2IP is not needed + if (!hasNonIp2Ip) { + TemporaryContactMethod* cm = new TemporaryContactMethod(); + cm->setAccount(ip2ip); + m_hSipIaxTemporaryNumbers[ip2ip] = cm; + } + + connect(AccountModel::instance(), &AccountModel::accountAdded , this, &NumberCompletionModelPrivate::accountAdded ); + connect(AccountModel::instance(), &AccountModel::accountRemoved, this, &NumberCompletionModelPrivate::accountRemoved); } -NumberCompletionModel::NumberCompletionModel() : QAbstractTableModel(QCoreApplication::instance()), d_ptr(new NumberCompletionModelPrivate(this)) +NumberCompletionModel::NumberCompletionModel() : QAbstractTableModel(PhoneDirectoryModel::instance()), d_ptr(new NumberCompletionModelPrivate(this)) { setObjectName("NumberCompletionModel"); } NumberCompletionModel::~NumberCompletionModel() { + QList<TemporaryContactMethod*> l = d_ptr->m_hSipIaxTemporaryNumbers.values(); + + d_ptr->m_hSipIaxTemporaryNumbers.clear(); + + while(l.size()) { + TemporaryContactMethod* cm = l.takeAt(0); + delete cm; + } + delete d_ptr; } @@ -131,7 +164,9 @@ QVariant NumberCompletionModel::data(const QModelIndex& index, int role ) const return n->uri(); break; case Qt::ToolTipRole: - return QString("<table><tr><td>%1</td></tr><tr><td>%2</td></tr></table>").arg(n->primaryName()).arg(n->category()->name()); + return QString("<table><tr><td>%1</td></tr><tr><td>%2</td></tr></table>") + .arg(n->primaryName()) + .arg(n->category() ? n->category()->name() : QString()); break; case Qt::DecorationRole: return n->icon(); @@ -250,6 +285,10 @@ void NumberCompletionModelPrivate::setPrefix(const QString& str) m_hNumbers.clear(); q_ptr->endRemoveRows(); } + + for(TemporaryContactMethod* cm : m_hSipIaxTemporaryNumbers) { + cm->setUri(str); + } } Call* NumberCompletionModel::call() const @@ -260,7 +299,11 @@ Call* NumberCompletionModel::call() const ContactMethod* NumberCompletionModel::number(const QModelIndex& idx) const { if (idx.isValid()) { - return (d_ptr->m_hNumbers.end()-1-idx.row()).value(); + //Keep the temporary contact methods private, export a copy + ContactMethod* m = (d_ptr->m_hNumbers.end()-1-idx.row()).value(); + return m->type() == ContactMethod::Type::TEMPORARY ? + PhoneDirectoryModel::instance()->fromTemporary(qobject_cast<TemporaryContactMethod*>(m)) + : m; } return nullptr; @@ -277,7 +320,16 @@ void NumberCompletionModelPrivate::updateModel() locateNameRange ( m_Prefix, numbers ); locateNumberRange( m_Prefix, numbers ); - foreach(ContactMethod* n,numbers) { + for (TemporaryContactMethod* cm : m_hSipIaxTemporaryNumbers) { + const int weight = getWeight(cm->account()); + if (weight) { + q_ptr->beginInsertRows(QModelIndex(), m_hNumbers.size(), m_hNumbers.size()); + m_hNumbers.insert(weight,cm); + q_ptr->endInsertRows(); + } + } + + for (ContactMethod* n : numbers) { if (m_UseUnregisteredAccount || ((n->account() && n->account()->registrationState() == Account::RegistrationState::READY) || !n->account())) { q_ptr->beginInsertRows(QModelIndex(), m_hNumbers.size(), m_hNumbers.size()); @@ -375,8 +427,8 @@ void NumberCompletionModelPrivate::locateNumberRange(const QString& prefix, QSet uint NumberCompletionModelPrivate::getWeight(ContactMethod* number) { - Q_UNUSED(number) uint weight = 1; + weight += (number->weekCount()+1)*150; weight += (number->trimCount()+1)*75 ; weight += (number->callCount()+1)*35 ; @@ -386,6 +438,21 @@ uint NumberCompletionModelPrivate::getWeight(ContactMethod* number) return weight; } +uint NumberCompletionModelPrivate::getWeight(Account* account) +{ + if ((!account) || account->registrationState() != Account::RegistrationState::READY) + return 0; //TODO handle the case where the account get registered during dialing + + uint weight = 1; + + weight += (account->weekCallCount ()+1)*15; + weight += (account->trimesterCallCount ()+1)*7 ; + weight += (account->totalCallCount ()+1)*3 ; + weight *= (account->isUsedForOutgogingCall()?3:1 ); + + return weight; +} + QString NumberCompletionModel::prefix() const { return d_ptr->m_Prefix; @@ -401,4 +468,39 @@ bool NumberCompletionModel::isUsingUnregisteredAccounts() return d_ptr->m_UseUnregisteredAccount; } +bool NumberCompletionModelPrivate::accountAdded(Account* a) +{ + bool hasNonIp2Ip = false; + + switch(a->protocol()) { + case Account::Protocol::SIP : + hasNonIp2Ip = true; + //no break + case Account::Protocol::IAX : { + TemporaryContactMethod* cm = new TemporaryContactMethod(); + cm->setAccount(a); + m_hSipIaxTemporaryNumbers[a] = cm; + } + break; + case Account::Protocol::RING: + case Account::Protocol::COUNT__: + break; + } + + return hasNonIp2Ip; +} + +void NumberCompletionModelPrivate::accountRemoved(Account* a) +{ + TemporaryContactMethod* cm = m_hSipIaxTemporaryNumbers[a]; + + m_hSipIaxTemporaryNumbers[a] = nullptr; + + setPrefix(q_ptr->prefix()); + + if (cm) { + delete cm; + } +} + #include <numbercompletionmodel.moc> diff --git a/src/useractionmodel.cpp b/src/useractionmodel.cpp index 069a5cdc..885fbdb8 100644 --- a/src/useractionmodel.cpp +++ b/src/useractionmodel.cpp @@ -439,11 +439,12 @@ void UserActionModelPrivate::updateCheckMask(int& ret, UserActionModel::Action a bool UserActionModelPrivate::updateByCall(UserActionModel::Action action, const Call* c) { + Account* a = c->account() ? c->account() : AvailableAccountModel::instance()->currentDefaultAccount(); return (!c) ? false : ( - availableActionMap [action] [c->state() ] && - availableAccountActionMap [action] [c->account()->registrationState()] && - multi_call_options [action] [m_SelectionState ] && - availableProtocolActions [action] [c->account()->protocol() ] // + availableActionMap [action] [c->state() ] && + availableAccountActionMap [action] [a->registrationState() ] && + multi_call_options [action] [m_SelectionState ] && + availableProtocolActions [action] [a->protocol() ] // ); } -- GitLab