qcontactlistmodel.cpp Example File
incomingcalls/qcontactlistmodel.cpp
#include "qcontactlistmodel.h"
#include "qcontactlistmodel_p.h"
#include "qcontact.h"
#include "qcontactmanager.h"
#include "qcontactdetails.h"
#include "qcontactrequests.h"
#include "qcontactfilters.h"
QContactListModel::QContactListModel(QContactManager* manager, int cacheSize)
: QAbstractListModel(),
d(new QContactListModelPrivate)
{
setCacheSize(cacheSize);
setManager(manager);
}
QContactListModel::QContactListModel(const QContactListModel& other)
: QAbstractListModel(), d(other.d)
{
}
QContactListModel& QContactListModel::operator=(const QContactListModel& other)
{
d = other.d;
return *this;
}
QContactListModel::~QContactListModel()
{
}
QContactManager* QContactListModel::manager() const
{
return d->m_manager;
}
void QContactListModel::setManager(QContactManager* manager)
{
QMap<QContactAbstractRequest*, int> updatedRequestCentreRows;
QList<QContactAbstractRequest*> requests = d->m_requestCentreRows.keys();
for (int i = 0; i < requests.size(); i++) {
QContactAbstractRequest* current = requests.at(i);
if (current->manager() == d->m_manager) {
current->cancel();
delete current;
} else {
updatedRequestCentreRows.insert(current, d->m_requestCentreRows.value(current));
}
}
d->m_requestCentreRows = updatedRequestCentreRows;
if (d->m_manager)
d->m_manager->disconnect(this);
d->m_manager = manager;
delete d->m_idRequest;
d->m_idRequest = new QContactLocalIdFetchRequest;
connect(d->m_idRequest, SIGNAL(progress(QContactLocalIdFetchRequest*,bool)), this, SLOT(contactIdFetchRequestProgress(QContactLocalIdFetchRequest*,bool)));
d->m_idRequest->setManager(manager);
if (manager) {
connect(manager, SIGNAL(contactsAdded(QList<QContactLocalId>)), this, SLOT(backendChanged()));
connect(manager, SIGNAL(contactsChanged(QList<QContactLocalId>)), this, SLOT(backendChanged()));
connect(manager, SIGNAL(contactsRemoved(QList<QContactLocalId>)), this, SLOT(backendChanged()));
}
backendChanged();
}
int QContactListModel::cacheSize() const
{
return (d->m_halfCacheSize * 2);
}
bool QContactListModel::setCacheSize(int size)
{
if (size > 0) {
int modulo4 = size % 4;
if (modulo4 == 0) {
d->m_halfCacheSize = size / 2;
d->m_quarterCacheSize = size / 4;
} else {
int test = size + (4 - modulo4);
d->m_halfCacheSize = (test < 0 ? (size - modulo4) : (size + 4 - modulo4));
d->m_halfCacheSize = d->m_halfCacheSize / 2;
d->m_quarterCacheSize = d->m_halfCacheSize / 2;
}
return true;
}
return false;
}
QContactListModel::AsynchronousRequestPolicy QContactListModel::requestPolicy() const
{
return d->m_requestPolicy;
}
void QContactListModel::setRequestPolicy(QContactListModel::AsynchronousRequestPolicy policy)
{
d->m_requestPolicy = policy;
}
QString QContactListModel::relevantDefinitionName() const
{
return d->m_relevantDefinitionName;
}
QString QContactListModel::relevantFieldName() const
{
return d->m_relevantFieldName;
}
bool QContactListModel::setRelevantDetailDefinitionAndFieldNames(const QString& definitionName, const QString& fieldName)
{
if (definitionName.isEmpty() || fieldName.isEmpty())
return false;
d->m_relevantDefinitionName = definitionName;
d->m_relevantFieldName = fieldName;
return true;
}
int QContactListModel::rowCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
return d->m_rowsToIds.count();
}
QVariant QContactListModel::data(const QModelIndex& index, int role) const
{
if (index.row() == -1)
return QVariant();
d->m_currentRow = index.row();
QContact currentContact = d->m_cache.value(d->m_currentRow);
bool cacheUpdateRequired = d->m_cache.isEmpty();
if ((d->m_halfCacheSize * 2) < d->m_rowsToIds.count()) {
int maxActiveCacheRow = d->m_currentRow + d->m_quarterCacheSize;
int minActiveCacheRow = d->m_currentRow - d->m_quarterCacheSize;
if (maxActiveCacheRow <= d->m_lastCacheCentreRow) {
cacheUpdateRequired = true;
} else if (minActiveCacheRow >= d->m_lastCacheCentreRow) {
cacheUpdateRequired = true;
}
}
if (cacheUpdateRequired) {
d->m_lastCacheCentreRow = d->m_currentRow;
int lowerBound = d->m_lastCacheCentreRow - d->m_halfCacheSize;
int upperBound = d->m_lastCacheCentreRow + d->m_halfCacheSize;
QList<int> newCacheRows;
if ((upperBound - lowerBound) >= d->m_rowsToIds.count()) {
newCacheRows = d->m_rowsToIds.keys();
} else {
for (int i = lowerBound; i <= upperBound; i++) {
int rowNumber = i;
if (i < 0)
rowNumber += d->m_rowsToIds.count();
if (i >= d->m_rowsToIds.count())
rowNumber -= d->m_rowsToIds.count();
newCacheRows.append(rowNumber);
}
}
if (d->m_requestPolicy != QContactListModel::NeverCancelPolicy) {
QList<QContactAbstractRequest*> oldRequests = d->m_requestCentreRows.keys();
bool cancelRequest = false;
for (int i = 0; i < oldRequests.size(); i++) {
QContactAbstractRequest* current = oldRequests.at(i);
if (d->m_requestPolicy == QContactListModel::CancelOnCacheUpdatePolicy) {
cancelRequest = true;
} else if (d->m_requestPolicy == QContactListModel::CancelOnCacheMissPolicy) {
if (!newCacheRows.contains(d->m_requestCentreRows.value(current))) {
cancelRequest = true;
}
} else {
int cacheSize = d->m_halfCacheSize * 2;
int requestCentre = d->m_requestCentreRows.value(current);
int requestWindowMax = (requestCentre + d->m_halfCacheSize) % cacheSize;
int requestWindowMin = (requestCentre - d->m_halfCacheSize) % cacheSize;
if (!newCacheRows.contains(requestWindowMax) && !newCacheRows.contains(requestWindowMin) && !newCacheRows.contains(requestCentre)) {
cancelRequest = true;
}
}
if (cancelRequest) {
current->cancel();
d->m_requestCentreRows.remove(current);
delete current;
}
cancelRequest = false;
}
}
QList<int> oldCacheRows = d->m_cache.keys();
foreach (int row, newCacheRows) {
if (!d->m_cache.contains(row)) {
QContact temp;
QContactName loadingName;
loadingName.setCustomLabel(QString(tr("Loading...")));
temp.saveDetail(&loadingName);
d->m_cache.insert(row, temp);
}
}
foreach (int row, oldCacheRows) {
if (row < lowerBound || row > upperBound) {
d->m_cache.remove(row);
}
if (newCacheRows.contains(row)) {
newCacheRows.removeOne(row);
}
}
if (!d->m_cache.contains(d->m_currentRow)) {
QContactName loadingName;
loadingName.setCustomLabel(QString(tr("Loading...")));
currentContact.saveDetail(&loadingName);
}
QContactFetchRequest* req = new QContactFetchRequest;
d->m_requestCentreRows.insert(req, d->m_lastCacheCentreRow);
QContactLocalIdFilter idFil;
QList<QContactLocalId> newCacheIds;
for (int i = 0; i < newCacheRows.size(); i++) {
newCacheIds.append(d->m_rowsToIds.value(newCacheRows.at(i)));
}
idFil.setIds(newCacheIds);
req->setFilter(idFil);
req->setManager(d->m_manager);
connect(req, SIGNAL(progress(QContactFetchRequest*, bool)), this, SLOT(contactFetchRequestProgress(QContactFetchRequest*,bool)));
req->start();
}
QVariant ret;
switch (role) {
case QContactListModel::DisplayLabelRole:
{
ret = currentContact.displayLabel();
}
break;
case QContactListModel::IdRole:
{
ret = currentContact.id().localId();
}
break;
case QContactListModel::AvatarRole:
{
ret = currentContact.detail(QContactAvatar::DefinitionName).value(QContactAvatar::FieldAvatar);
}
break;
case QContactListModel::PresenceRole:
{
if (d->m_manager == 0) {
break;
}
QContactDetailDefinition presenceDef = d->m_manager->detailDefinition(QContactOnlineAccount::DefinitionName);
QList<QVariant> allowablePresenceValues = presenceDef.fields().value(QContactOnlineAccount::FieldPresence).allowableValues();
if (presenceDef.isEmpty() || allowablePresenceValues.isEmpty()) {
break;
}
int bestPresenceSoFar = 0;
QList<QContactDetail> presenceDetails = currentContact.details(QContactOnlineAccount::DefinitionName);
foreach (const QContactOnlineAccount& pres, presenceDetails) {
int index = allowablePresenceValues.indexOf(pres.presence());
if (index > bestPresenceSoFar) {
bestPresenceSoFar = index;
}
}
ret = QVariant(allowablePresenceValues.at(bestPresenceSoFar));
}
break;
case QContactListModel::RelevantDataRole:
{
ret = currentContact.detail(d->m_relevantDefinitionName).value(d->m_relevantFieldName);
}
break;
default:
break;
}
return ret;
}
QVariant QContactListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
Q_UNUSED(section);
Q_UNUSED(orientation);
QVariant ret;
switch (role) {
case QContactListModel::DisplayLabelRole:
{
ret = QString(tr("Name"));
}
break;
case QContactListModel::IdRole:
{
ret = QString(tr("Id"));
}
break;
case QContactListModel::AvatarRole:
{
ret = QString(tr("Avatar"));
}
break;
case QContactListModel::PresenceRole:
{
ret = QString(tr("Presence"));
}
break;
case QContactListModel::RelevantDataRole:
{
ret = QString(tr("Details"));
}
break;
default:
break;
}
return ret;
}
bool QContactListModel::insertRows(int row, int count, const QModelIndex& parent)
{
beginInsertRows(parent, row, count);
endInsertRows();
return false;
}
bool QContactListModel::removeRows(int row, int count, const QModelIndex& parent)
{
beginRemoveRows(parent, row, count);
endRemoveRows();
return false;
}
int QContactListModel::contactRow(const QContactLocalId& contactId) const
{
return d->m_idsToRows.value(contactId, -1);
}
QContact QContactListModel::contact(const QModelIndex& index) const
{
if (d->m_manager)
return d->m_manager->contact(d->m_rowsToIds.value(index.row()));
return QContact();
}
void QContactListModel::contactFetchRequestProgress(QContactFetchRequest* request, bool appendOnly)
{
Q_UNUSED(appendOnly);
if (d->m_manager != request->manager() || request->status() == QContactAbstractRequest::Cancelled) {
d->m_requestCentreRows.remove(request);
delete request;
return;
}
QMap<int, int> rowMap;
QList<QContact> fetched = request->contacts();
foreach (const QContact& c, fetched) {
int fetchedRow = d->m_idsToRows.value(c.id().localId(), -1);
if (!d->m_cache.contains(fetchedRow))
break;
d->m_cache.insert(fetchedRow, c);
rowMap.insert(fetchedRow, fetchedRow);
}
if (request->status() == QContactAbstractRequest::Finished) {
d->m_requestCentreRows.remove(request);
delete request;
}
QList<int> rows = rowMap.keys();
while (rows.size() > 0) {
int lowestIndex = rows.at(0);
int highestIndex = rows.at(0);
int nbrAccountedFor = 1;
int nbrRows = rows.size();
while (nbrAccountedFor < nbrRows) {
int temp = highestIndex;
highestIndex = rows.at(nbrAccountedFor);
if ((highestIndex - temp) > 1) {
highestIndex = temp;
break;
}
nbrAccountedFor += 1;
}
while (nbrAccountedFor > 0) {
rows.removeFirst();
nbrAccountedFor -= 1;
}
QModelIndex lowerBound = QAbstractItemModel::createIndex(lowestIndex, 0);
QModelIndex upperBound = QAbstractItemModel::createIndex(highestIndex, 0);
emit dataChanged(lowerBound, upperBound);
}
}
void QContactListModel::contactIdFetchRequestProgress(QContactLocalIdFetchRequest* request, bool appendOnly)
{
if (!appendOnly) {
d->m_cache.clear();
d->m_rowsToIds.clear();
d->m_idsToRows.clear();
}
QList<QContactLocalId> ids = request->ids();
int startIndex = d->m_idsToRows.count();
int endIndex = ids.size();
for (int i = startIndex; i < endIndex; i++) {
d->m_rowsToIds.insert(i, ids.at(i));
d->m_idsToRows.insert(ids.at(i), i);
}
if (!appendOnly)
reset();
else
emit dataChanged(QAbstractItemModel::createIndex(startIndex,0), QAbstractItemModel::createIndex(endIndex,0));
}
void QContactListModel::backendChanged()
{
d->m_idRequest->start();
d->m_idRequest->waitForFinished();
}
Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies) |
Trademarks |
Qt Mobility Project 1.0.0 (Technology Preview) |