Skip to content

Commit

Permalink
[libcommhistory] Consolidate contact/recipient event models and fix u…
Browse files Browse the repository at this point in the history
…nit tests. JB#48263

Remove SingleContactEventModel; move its features into
RecipientEventModel, which now accepts either recipients or a contact
id as the event filter. We can do without the class split for
filtering events by saved vs non-saved contacts, and combining these
into a single model simplifies the code base.

RecipientEventModel can resolve contacts into recipients and also
recipients into contacts (for e.g. when a recipient matches a contact
that has multiple phone numbers). Instead of having multiple getEvents()
functions, it now has setRecipients() functions to set the filter,
then getEvents() can be called to execute the query.

Remove ContactEventModel, and add DeclarativeRecipientEventModel as
a QML wrapper around RecipientEventModel.

Fix various issues in the unit tests where contact creation/editing
were failing as they were operating on aggregates (which are read-only)
rather than local constituents (which are writable). The unit tests in
SingleContactEventModelTest have been moved into
RecipientEventModelTest.

The unit tests now modify the main contacts database directly instead
of creating a separate test database. This avoids test failures where
the tests are accessing a QContactManager instance that is different
from the one accessed via the SeasideCache in the library (to resolve
contacts, for example).
  • Loading branch information
blammit committed Dec 2, 2020
1 parent eca57e9 commit 5566f3c
Show file tree
Hide file tree
Showing 23 changed files with 489 additions and 659 deletions.
4 changes: 2 additions & 2 deletions declarative/declarative.pro
Expand Up @@ -9,7 +9,7 @@ INCLUDEPATH += ../src

SOURCES += src/plugin.cpp \
src/callproxymodel.cpp \
src/contacteventmodel.cpp \
src/declarativerecipienteventmodel.cpp \
src/conversationproxymodel.cpp \
src/declarativegroupmanager.cpp \
src/sharedbackgroundthread.cpp \
Expand All @@ -18,7 +18,7 @@ SOURCES += src/plugin.cpp \

HEADERS += src/constants.h \
src/callproxymodel.h \
src/contacteventmodel.h \
src/declarativerecipienteventmodel.h \
src/conversationproxymodel.h \
src/declarativegroupmanager.h \
src/sharedbackgroundthread.h \
Expand Down
12 changes: 4 additions & 8 deletions declarative/plugins.qmltypes
Expand Up @@ -427,10 +427,6 @@ Module {
Property { name: "resolving"; type: "bool"; isReadonly: true }
Method { name: "getEvents"; type: "bool" }
}
Component {
name: "CommHistory::SingleContactEventModel"
prototype: "CommHistory::EventModel"
}
Component {
name: "CommHistoryConstants"
prototype: "QObject"
Expand Down Expand Up @@ -504,12 +500,12 @@ Module {
}
}
Component {
name: "ContactEventModel"
prototype: "CommHistory::SingleContactEventModel"
exports: ["org.nemomobile.commhistory/CommContactEventModel 1.0"]
name: "DeclarativeRecipientEventModel"
prototype: "CommHistory::RecipientEventModel"
exports: ["org.nemomobile.commhistory/CommRecipientEventModel 1.0"]
exportMetaObjectRevisions: [0]
Property { name: "contactId"; type: "int" }
Method { name: "reload" }
Property { name: "remoteUid"; type: "string" }
}
Component {
name: "ConversationProxyModel"
Expand Down
@@ -1,5 +1,6 @@
/* Copyright (C) 2015 Jolla Ltd.
* Contact: Matt Vogt <matthew.vogt@jollamobile.com>
/*
* Copyright (C) 2015 - 2019 Jolla Ltd.
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* You may use this file under the terms of the BSD license as follows:
*
Expand Down Expand Up @@ -29,54 +30,83 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/

#include "contacteventmodel.h"
#include "declarativerecipienteventmodel.h"
#include "commonutils.h"
#include <QTimer>

#include <QQmlInfo>

using namespace CommHistory;

ContactEventModel::ContactEventModel(QObject *parent)
: SingleContactEventModel(parent)
, m_contactId(0)

DeclarativeRecipientEventModel::DeclarativeRecipientEventModel(QObject *parent)
: RecipientEventModel(parent)
{
}

void ContactEventModel::setContactId(int contactId)
void DeclarativeRecipientEventModel::setContactId(int contactId)
{
if (contactId == m_contactId)
return;

if (!m_remoteUid.isEmpty()) {
qmlInfo(this) << "remoteUid already set to" << m_remoteUid
<< ", ignoring contactId change to" << contactId;
return;
}

m_contactId = contactId;
reload();
emit contactIdChanged();
}

QTimer::singleShot(0, this, SLOT(reload()));
int DeclarativeRecipientEventModel::contactId() const
{
return m_contactId;
}

void ContactEventModel::setFallbackPhoneId(const QString &fallbackPhoneId)
void DeclarativeRecipientEventModel::setRemoteUid(const QString &remoteUid)
{
if (fallbackPhoneId == m_fallbackPhoneId)
if (remoteUid == m_remoteUid)
return;

m_fallbackPhoneId = fallbackPhoneId;
emit fallbackPhoneIdChanged();

if (!m_contactId) {
QTimer::singleShot(0, this, SLOT(reload()));
if (m_contactId > 0) {
qmlInfo(this) << "contactId already set to" << m_contactId
<< ", ignoring remoteUid change to" << remoteUid;
return;
}

m_remoteUid = remoteUid;
reload();
emit remoteUidChanged();
}

void ContactEventModel::reload()
QString DeclarativeRecipientEventModel::remoteUid() const
{
return m_remoteUid;
}

void DeclarativeRecipientEventModel::classBegin()
{
}

void DeclarativeRecipientEventModel::componentComplete()
{
m_complete = true;
reload();
}

void DeclarativeRecipientEventModel::reload()
{
if (!m_complete)
return;

if (m_contactId > 0) {
getEvents(m_contactId);
} else if (!m_fallbackPhoneId.isEmpty()) {
// LocalUID is set to QString because we don't care about which sim
setRecipients(m_contactId);
} else if (!m_remoteUid.isEmpty()) {
// Use the generic RING_ACCOUNT because we don't care about which SIM
// the call was received on.
// SingleContactEventModel::getEvents(Recipient) also exists and
// is matching a stored contact from recipient phone number. We actually
// need here to get events for a recipient event if not saved, so we
// must call the RecipientEventModel::getEvents() explicitely to avoid
// calling implicitely the SingleContactEventModel variant.
RecipientEventModel::getEvents(Recipient(QString(), m_fallbackPhoneId));
setRecipients(Recipient(RING_ACCOUNT, m_remoteUid));
}

getEvents();
}
@@ -1,5 +1,6 @@
/* Copyright (C) 2015 Jolla Ltd.
* Contact: Matt Vogt <matthew.vogt@jollamobile.com>
/*
* Copyright (C) 2015 - 2019 Jolla Ltd.
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* You may use this file under the terms of the BSD license as follows:
*
Expand Down Expand Up @@ -29,38 +30,44 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/

#ifndef COMMHISTORY_DECLARATIVE_CONTACTEVENTMODEL_H
#define COMMHISTORY_DECLARATIVE_CONTACTEVENTMODEL_H
#ifndef COMMHISTORY_DECLARATIVE_RECIPIENTEVENTMODEL_H
#define COMMHISTORY_DECLARATIVE_RECIPIENTEVENTMODEL_H

#include "singlecontacteventmodel.h"
#include "recipienteventmodel.h"

#include <QHash>
#include <QQmlParserStatus>

class ContactEventModel : public CommHistory::SingleContactEventModel
class DeclarativeRecipientEventModelPrivate;

class DeclarativeRecipientEventModel : public CommHistory::RecipientEventModel, public QQmlParserStatus
{
Q_OBJECT
Q_INTERFACES(QQmlParserStatus)
Q_PROPERTY(int contactId READ contactId WRITE setContactId NOTIFY contactIdChanged)
Q_PROPERTY(QString fallbackPhoneId READ fallbackPhoneId WRITE setFallbackPhoneId NOTIFY fallbackPhoneIdChanged)
Q_PROPERTY(QString remoteUid READ remoteUid WRITE setRemoteUid NOTIFY remoteUidChanged)

public:
ContactEventModel(QObject *parent = 0);
DeclarativeRecipientEventModel(QObject *parent = 0);

int contactId() const { return m_contactId; }
int contactId() const;
void setContactId(int contactId);

QString fallbackPhoneId() const { return m_fallbackPhoneId; }
void setFallbackPhoneId(const QString &fallbackPhoneId);
QString remoteUid() const;
void setRemoteUid(const QString &remoteUid);

void classBegin() override;
void componentComplete() override;

signals:
void contactIdChanged();
void fallbackPhoneIdChanged();
void remoteUidChanged();

public slots:
private:
void reload();

private:
int m_contactId;
QString m_fallbackPhoneId;
QString m_remoteUid;
int m_contactId = 0;
bool m_complete = false;
};

#endif
4 changes: 2 additions & 2 deletions declarative/src/plugin.cpp
Expand Up @@ -35,7 +35,7 @@
#include "groupobject.h"
#include "eventmodel.h"
#include "groupmodel.h"
#include "contacteventmodel.h"
#include "declarativerecipienteventmodel.h"
#include "contactgroupmodel.h"
#include "callproxymodel.h"
#include "conversationproxymodel.h"
Expand Down Expand Up @@ -64,7 +64,7 @@ void CommHistoryPlugin::registerTypes(const char *uri)
qmlRegisterType<CommHistory::EventModel>(uri, 1, 0, "CommEventModel");
qmlRegisterType<CommHistory::GroupModel>(uri, 1, 0, "CommGroupModel");
qmlRegisterType<CallProxyModel>(uri, 1, 0, "CommCallModel");
qmlRegisterType<ContactEventModel>(uri, 1, 0, "CommContactEventModel");
qmlRegisterType<DeclarativeRecipientEventModel>(uri, 1, 0, "CommRecipientEventModel");
qmlRegisterType<ConversationProxyModel>(uri, 1, 0, "CommConversationModel");
qmlRegisterType<CommHistory::ContactGroupModel>(uri, 1, 0, "CommContactGroupModel");
qmlRegisterType<CommHistory::RecentContactsModel>(uri, 1, 0, "CommRecentContactsModel");
Expand Down
15 changes: 12 additions & 3 deletions src/eventmodel_p.cpp
Expand Up @@ -195,8 +195,11 @@ bool EventModelPrivate::fillModel(int start, int end, QList<CommHistory::Event>
Q_UNUSED(end);
Q_UNUSED(resolved);

if (events.isEmpty())
return false;
if (events.isEmpty()) {
// Empty results are still "ready"
modelUpdatedSlot(true);
return true;
}

Q_Q(EventModel);
DEBUG() << Q_FUNC_INFO << ": read" << events.count() << "events";
Expand Down Expand Up @@ -224,8 +227,14 @@ bool EventModelPrivate::fillModel(QList<CommHistory::Event> events, bool resolve
}
}

if (!events.isEmpty())
if (events.isEmpty()) {
// Empty results are still "ready"
modelUpdatedSlot(true);
return true;
} else {
return fillModel(q->rowCount(), q->rowCount() + events.count() - 1, events, resolved);
}


return true;
}
Expand Down
3 changes: 2 additions & 1 deletion src/recipient.cpp
Expand Up @@ -417,7 +417,8 @@ RecipientList RecipientList::fromCacheItem(const SeasideCache::CacheItem *item)
re << Recipient(account.value<QString>(QContactOnlineAccount__FieldAccountPath), account.accountUri());
}
foreach (const QContactPhoneNumber &phoneNumber, item->contact.details<QContactPhoneNumber>()) {
re << Recipient(QString(), phoneNumber.number());
// Match with recipients calling from any SIM
re << Recipient(RING_ACCOUNT, phoneNumber.number());
}
}
return re;
Expand Down

0 comments on commit 5566f3c

Please sign in to comment.