Skip to content
This repository has been archived by the owner on Sep 4, 2021. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #30 from matthewvogt/grouping-chars
[libcontacts] Use MLocale for localized alphabet grouping
  • Loading branch information
matthewvogt committed Sep 6, 2013
2 parents dedbd89 + 608453f commit 08a5ce2
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 83 deletions.
1 change: 1 addition & 0 deletions rpm/libcontacts-qt5.spec
Expand Up @@ -12,6 +12,7 @@ BuildRequires: pkgconfig(Qt5Test)
BuildRequires: pkgconfig(Qt5Contacts)
BuildRequires: pkgconfig(Qt5Versit)
BuildRequires: pkgconfig(mlite5)
BuildRequires: pkgconfig(mlocale5)
BuildRequires: pkgconfig(qtcontacts-sqlite-qt5-extensions) >= 0.1.8

%description
Expand Down
112 changes: 43 additions & 69 deletions src/seasidecache.cpp
Expand Up @@ -67,12 +67,16 @@

#include <QtDebug>

#include <mlocale.h>

#ifdef USING_QTPIM
QTVERSIT_USE_NAMESPACE
#endif

namespace {

ML10N::MLocale mLocale;

const QString aggregateRelationshipType =
#ifdef USING_QTPIM
QContactRelationship::Aggregates();
Expand All @@ -83,39 +87,10 @@ const QString aggregateRelationshipType =
const QString syncTargetLocal = QLatin1String("local");
const QString syncTargetWasLocal = QLatin1String("was_local");

QList<QChar> getAllContactNameGroups()
{
QList<QChar> groups;
groups << QLatin1Char('A')
<< QLatin1Char('B')
<< QLatin1Char('C')
<< QLatin1Char('D')
<< QLatin1Char('E')
<< QLatin1Char('F')
<< QLatin1Char('G')
<< QLatin1Char('H')
<< QLatin1Char('I')
<< QLatin1Char('J')
<< QLatin1Char('K')
<< QLatin1Char('L')
<< QLatin1Char('M')
<< QLatin1Char('N')
<< QLatin1Char('O')
<< QLatin1Char('P')
<< QLatin1Char('Q')
<< QLatin1Char('R')
<< QLatin1Char('S')
<< QLatin1Char('T')
<< QLatin1Char('U')
<< QLatin1Char('V')
<< QLatin1Char('W')
<< QLatin1Char('X')
<< QLatin1Char('Y')
<< QLatin1Char('Z')
<< QChar(0x00c5) // Å
<< QChar(0x00c4) // Ä
<< QChar(0x00d6) // Ö
<< QLatin1Char('#');
QStringList getAllContactNameGroups()
{
QStringList groups(mLocale.exemplarCharactersIndex());
groups.append(QString::fromLatin1("#"));
return groups;
}

Expand Down Expand Up @@ -307,7 +282,7 @@ bool ignoreContactForNameGroups(const QContact &contact)
}

SeasideCache *SeasideCache::instancePtr = 0;
QList<QChar> SeasideCache::allContactNameGroups = getAllContactNameGroups();
QStringList SeasideCache::allContactNameGroups = getAllContactNameGroups();

SeasideCache* SeasideCache::instance()
{
Expand Down Expand Up @@ -583,29 +558,29 @@ void SeasideCache::setNameGrouper(SeasideNameGrouper *grouper)
instancePtr->m_nameGrouper.reset(grouper);

allContactNameGroups = getAllContactNameGroups();
QList<QChar> groups = instancePtr->m_nameGrouper->allNameGroups();
QStringList groups = instancePtr->m_nameGrouper->allNameGroups();
for (int i = groups.count() - 1; i > -1; --i) {
const QChar &group = groups.at(i);
const QString &group = groups.at(i);
if (!allContactNameGroups.contains(group))
allContactNameGroups.prepend(group);
}
}

QChar SeasideCache::nameGroup(const CacheItem *cacheItem)
QString SeasideCache::nameGroup(const CacheItem *cacheItem)
{
if (!cacheItem)
return QChar();
return QString();

return cacheItem->nameGroup;
}

QChar SeasideCache::determineNameGroup(const CacheItem *cacheItem)
QString SeasideCache::determineNameGroup(const CacheItem *cacheItem)
{
if (!cacheItem)
return QChar();
return QString();

if (!instancePtr->m_nameGrouper.isNull()) {
QChar group = instancePtr->m_nameGrouper->nameGroupForContact(cacheItem->contact, instancePtr->m_groupProperty);
QString group = instancePtr->m_nameGrouper->nameGroupForContact(cacheItem->contact, instancePtr->m_groupProperty);
if (!group.isNull()) {
return group;
}
Expand All @@ -614,37 +589,36 @@ QChar SeasideCache::determineNameGroup(const CacheItem *cacheItem)
const QContactName name(cacheItem->contact.detail<QContactName>());
const QString nameProperty(instancePtr->m_groupProperty == QString::fromLatin1("firstName") ? name.firstName() : name.lastName());

QChar group;
QString group;
if (!nameProperty.isEmpty()) {
group = nameProperty[0].toUpper();
group = mLocale.indexBucket(nameProperty);
} else if (!cacheItem->displayLabel.isEmpty()) {
group = cacheItem->displayLabel[0].toUpper();
group = mLocale.indexBucket(cacheItem->displayLabel);
}

// XXX temporary workaround for non-latin names: use non-name details to try to find a
// latin character group
if (!group.isNull() && group.toLatin1() != group) {
if (group.isNull() || !allContactNameGroups.contains(group)) {
QString displayLabel = generateDisplayLabelFromNonNameDetails(cacheItem->contact);
if (!displayLabel.isEmpty())
group = displayLabel[0].toUpper();
group = mLocale.indexBucket(displayLabel);
}

if (group.isNull() || !allContactNameGroups.contains(group)) {
group = QLatin1Char('#'); // 'other' group
group = QString::fromLatin1("#"); // 'other' group
}
return group;
}

QList<QChar> SeasideCache::allNameGroups()
QStringList SeasideCache::allNameGroups()
{
if (!instancePtr)
new SeasideCache;
return allContactNameGroups;
}

QHash<QChar, QSet<quint32> > SeasideCache::nameGroupMembers()
QHash<QString, QSet<quint32> > SeasideCache::nameGroupMembers()
{
if (instancePtr)
return instancePtr->m_contactNameGroups;
return QHash<QChar, QSet<quint32> >();
return QHash<QString, QSet<quint32> >();
}

SeasideCache::DisplayLabelOrder SeasideCache::displayLabelOrder()
Expand Down Expand Up @@ -892,9 +866,9 @@ void SeasideCache::removeContactData(
m_contacts[filter].remove(row);

if (filter == FilterAll) {
const QChar group(nameGroup(existingItem(contactId)));
const QString group(nameGroup(existingItem(contactId)));
if (!group.isNull()) {
QSet<QChar> modifiedNameGroups;
QSet<QString> modifiedNameGroups;
removeFromContactNameGroup(internalId(contactId), group, &modifiedNameGroups);
notifyNameGroupsChanged(modifiedNameGroups);
}
Expand Down Expand Up @@ -1642,7 +1616,7 @@ void SeasideCache::contactsAvailable()
appendContacts(contacts, type, partialFetch);
} else {
// An update.
QSet<QChar> modifiedGroups;
QSet<QString> modifiedGroups;

for (int i = m_resultsRead; i < contacts.count(); ++i) {
QContact contact = contacts.at(i);
Expand All @@ -1658,7 +1632,7 @@ void SeasideCache::contactsAvailable()
item->iid = iid;
}

QChar oldNameGroup;
QString oldNameGroup;
QString oldDisplayLabel;

if (preexisting) {
Expand Down Expand Up @@ -1710,7 +1684,7 @@ void SeasideCache::contactsAvailable()
}
}

void SeasideCache::addToContactNameGroup(quint32 iid, const QChar &group, QSet<QChar> *modifiedGroups)
void SeasideCache::addToContactNameGroup(quint32 iid, const QString &group, QSet<QString> *modifiedGroups)
{
if (!group.isNull()) {
QSet<quint32> &set(m_contactNameGroups[group]);
Expand All @@ -1723,7 +1697,7 @@ void SeasideCache::addToContactNameGroup(quint32 iid, const QChar &group, QSet<Q
}
}

void SeasideCache::removeFromContactNameGroup(quint32 iid, const QChar &group, QSet<QChar> *modifiedGroups)
void SeasideCache::removeFromContactNameGroup(quint32 iid, const QString &group, QSet<QString> *modifiedGroups)
{
if (!group.isNull()) {
QSet<quint32> &set(m_contactNameGroups[group]);
Expand All @@ -1735,13 +1709,13 @@ void SeasideCache::removeFromContactNameGroup(quint32 iid, const QChar &group, Q
}
}

void SeasideCache::notifyNameGroupsChanged(const QSet<QChar> &groups)
void SeasideCache::notifyNameGroupsChanged(const QSet<QString> &groups)
{
if (groups.isEmpty() || m_nameGroupChangeListeners.isEmpty())
return;

QHash<QChar, QSet<quint32> > updates;
foreach (const QChar &group, groups)
QHash<QString, QSet<quint32> > updates;
foreach (const QString &group, groups)
updates.insert(group, m_contactNameGroups[group]);

for (int i = 0; i < m_nameGroupChangeListeners.count(); ++i)
Expand Down Expand Up @@ -1785,14 +1759,14 @@ void SeasideCache::removeRange(FilterType filter, int index, int count)
for (int i = 0; i < models.count(); ++i)
models[i]->sourceAboutToRemoveItems(index, index + count - 1);

QSet<QChar> modifiedNameGroups;
QSet<QString> modifiedNameGroups;

for (int i = 0; i < count; ++i) {
if (filter == FilterAll) {
const ContactIdType apiId = cacheIds.at(index);
m_expiredContacts[apiId] -= 1;

const QChar group(nameGroup(existingItem(apiId)));
const QString group(nameGroup(existingItem(apiId)));
if (!group.isNull()) {
removeFromContactNameGroup(internalId(apiId), group, &modifiedNameGroups);
}
Expand Down Expand Up @@ -1853,7 +1827,7 @@ void SeasideCache::appendContacts(const QList<QContact> &contacts, FilterType fi
int end = cacheIds.count() + contacts.count() - m_appendIndex - 1;

if (begin <= end) {
QSet<QChar> modifiedGroups;
QSet<QString> modifiedGroups;

for (int i = 0; i < models.count(); ++i)
models.at(i)->sourceAboutToInsertItems(begin, end);
Expand Down Expand Up @@ -2139,7 +2113,7 @@ void SeasideCache::displayLabelOrderChanged()
if (displayLabelOrder.isValid() && displayLabelOrder.toInt() != m_displayLabelOrder) {
m_displayLabelOrder = static_cast<DisplayLabelOrder>(displayLabelOrder.toInt());

QSet<QChar> modifiedGroups;
QSet<QString> modifiedGroups;

// Update the display labels
typedef QHash<quint32, CacheItem>::iterator iterator;
Expand All @@ -2158,7 +2132,7 @@ void SeasideCache::displayLabelOrderChanged()
}

// If the contact's name group is derived from display label, it may have changed
const QChar group(determineNameGroup(&*it));
const QString group(determineNameGroup(&*it));
if (group != it->nameGroup) {
if (!ignoreContactForNameGroups(it->contact)) {
if (!it->nameGroup.isNull()) {
Expand Down Expand Up @@ -2230,12 +2204,12 @@ void SeasideCache::groupPropertyChanged()
m_groupProperty = newProperty;

// Update the name groups
QSet<QChar> modifiedGroups;
QSet<QString> modifiedGroups;

typedef QHash<quint32, CacheItem>::iterator iterator;
for (iterator it = m_people.begin(); it != m_people.end(); ++it) {
// Update the nameGroup for this contact
const QChar group(determineNameGroup(&*it));
const QString group(determineNameGroup(&*it));
if (group != it->nameGroup) {
if (!ignoreContactForNameGroups(it->contact)) {
if (!it->nameGroup.isNull()) {
Expand Down
22 changes: 11 additions & 11 deletions src/seasidecache.h
Expand Up @@ -82,7 +82,7 @@ class CONTACTCACHE_EXPORT SeasideNameGroupChangeListener
SeasideNameGroupChangeListener() {}
~SeasideNameGroupChangeListener() {}

virtual void nameGroupsUpdated(const QHash<QChar, QSet<quint32> > &groups) = 0;
virtual void nameGroupsUpdated(const QHash<QString, QSet<quint32> > &groups) = 0;
};

class CONTACTCACHE_EXPORT SeasideCache : public QObject
Expand Down Expand Up @@ -206,7 +206,7 @@ class CONTACTCACHE_EXPORT SeasideCache : public QObject
quint64 statusFlags;
ContactState contactState;
ItemListener *listeners;
QChar nameGroup;
QString nameGroup;
QString displayLabel;
};

Expand Down Expand Up @@ -308,11 +308,11 @@ class CONTACTCACHE_EXPORT SeasideCache : public QObject
static void ensureCompletion(CacheItem *cacheItem);
static void refreshContact(CacheItem *cacheItem);

static QChar nameGroup(const CacheItem *cacheItem);
static QChar determineNameGroup(const CacheItem *cacheItem);
static QString nameGroup(const CacheItem *cacheItem);
static QString determineNameGroup(const CacheItem *cacheItem);

static QList<QChar> allNameGroups();
static QHash<QChar, QSet<quint32> > nameGroupMembers();
static QStringList allNameGroups();
static QHash<QString, QSet<quint32> > nameGroupMembers();

static CacheItem *itemByPhoneNumber(const QString &number, bool requireComplete = true);
static CacheItem *itemByEmailAddress(const QString &address, bool requireComplete = true);
Expand Down Expand Up @@ -413,9 +413,9 @@ private slots:
void removeContactData(const ContactIdType &contactId, FilterType filter);
void makePopulated(FilterType filter);

void addToContactNameGroup(quint32 iid, const QChar &group, QSet<QChar> *modifiedGroups = 0);
void removeFromContactNameGroup(quint32 iid, const QChar &group, QSet<QChar> *modifiedGroups = 0);
void notifyNameGroupsChanged(const QSet<QChar> &groups);
void addToContactNameGroup(quint32 iid, const QString &group, QSet<QString> *modifiedGroups = 0);
void removeFromContactNameGroup(quint32 iid, const QString &group, QSet<QString> *modifiedGroups = 0);
void notifyNameGroupsChanged(const QSet<QString> &groups);

void updateConstituentAggregations(const ContactIdType &contactId);
void completeContactAggregation(const ContactIdType &contact1Id, const ContactIdType &contact2Id);
Expand All @@ -431,7 +431,7 @@ private slots:
QHash<QString, quint32> m_emailAddressIds;
QHash<QPair<QString, QString>, quint32> m_onlineAccountIds;
QHash<ContactIdType, QContact> m_contactsToSave;
QHash<QChar, QSet<quint32> > m_contactNameGroups;
QHash<QString, QSet<quint32> > m_contactNameGroups;
QList<QContact> m_contactsToCreate;
QList<ContactIdType> m_contactsToRemove;
QList<ContactIdType> m_changedContacts;
Expand Down Expand Up @@ -501,7 +501,7 @@ private slots:
QElapsedTimer m_fetchPostponed;

static SeasideCache *instancePtr;
static QList<QChar> allContactNameGroups;
static QStringList allContactNameGroups;
};

#endif
5 changes: 2 additions & 3 deletions src/seasidenamegrouper.h
Expand Up @@ -34,7 +34,6 @@

#include "contactcacheexport.h"

#include <QChar>
#include <QList>
#include <QContact>

Expand All @@ -50,8 +49,8 @@ class CONTACTCACHE_EXPORT SeasideNameGrouper
SeasideNameGrouper() {}
virtual ~SeasideNameGrouper() {}

virtual QChar nameGroupForContact(const QContact &contact, const QString &groupProperty) const = 0;
virtual QList<QChar> allNameGroups() const = 0;
virtual QString nameGroupForContact(const QContact &contact, const QString &groupProperty) const = 0;
virtual QStringList allNameGroups() const = 0;
};

#endif // SEASIDENAMEGROUPER_H
1 change: 1 addition & 0 deletions src/src.pro
Expand Up @@ -31,6 +31,7 @@ equals(QT_MAJOR_VERSION, 5) {
} else {
warning("mlite not available. Some functionality may not work as expected.")
}
PKGCONFIG += mlocale5
}

DEFINES += CONTACTCACHE_BUILD
Expand Down

0 comments on commit 08a5ce2

Please sign in to comment.