...
 
Commits (10)
Name: qtcontacts-sqlite-qt5
Version: 0.2.34
Version: 0.2.36
Release: 0
Summary: SQLite-based plugin for QtPIM Contacts
Group: System/Plugins
......
......@@ -160,6 +160,12 @@ void ContactNotifier::relationshipsRemoved(const QSet<QContactId> &contactIds)
}
}
void ContactNotifier::displayLabelGroupsChanged()
{
QDBusMessage message = createSignal("displayLabelGroupsChanged", m_nonprivileged);
QDBusConnection::sessionBus().send(message);
}
bool ContactNotifier::connect(const char *name, const char *signature, QObject *receiver, const char *slot)
{
static QDBusConnection connection(QDBusConnection::sessionBus());
......
......@@ -55,6 +55,7 @@ public:
void selfContactIdChanged(QContactId oldId, QContactId newId);
void relationshipsAdded(const QSet<QContactId> &contactIds);
void relationshipsRemoved(const QSet<QContactId> &contactIds);
void displayLabelGroupsChanged();
bool connect(const char *name, const char *signature, QObject *receiver, const char *slot);
};
......
......@@ -595,13 +595,14 @@ static void readDetail(QContact *contact, QSqlQuery &query, quint32 contactId, q
const quint32 contactId = query.value(1).toUInt();
const QString detailName = query.value(2).toString();
*/
const QString detailUriValue = query.value(3).toString();
const QString linkedDetailUrisValue = query.value(4).toString();
const QString contextValue = query.value(5).toString();
const int accessConstraints = query.value(6).toInt();
QString provenance = query.value(7).toString();
const bool modifiable = query.value(8).toBool();
const bool nonexportable = query.value(9).toBool();
int col = 3;
const QString detailUriValue = query.value(col++).toString();
const QString linkedDetailUrisValue = query.value(col++).toString();
const QString contextValue = query.value(col++).toString();
const int accessConstraints = query.value(col++).toInt();
QString provenance = query.value(col++).toString();
const bool modifiable = query.value(col++).toBool();
const bool nonexportable = query.value(col++).toBool();
if (!detailUriValue.isEmpty()) {
setValue(&detail,
......@@ -2136,30 +2137,31 @@ QContactManager::Error ContactReader::queryContacts(
const int batchSize = (maximumCount > 0) ? 0 : ReportBatchSize; // If count is constrained, don't report periodically
while (contactQuery.next()) {
quint32 dbId = contactQuery.value(0).toUInt();
int col = 0;
quint32 dbId = contactQuery.value(col++).toUInt();
QContact contact;
QContactId id(ContactId::contactId(ContactId::apiId(dbId)));
contact.setId(id);
QString persistedDL = contactQuery.value(1).toString();
QString displayLabelGroup = contactQuery.value(2).toString();
QString persistedDL = contactQuery.value(col++).toString();
QString displayLabelGroup = contactQuery.value(col++).toString();
ContactsEngine::setContactDisplayLabel(&contact, persistedDL, displayLabelGroup);
QContactName name;
setValue(&name, QContactName::FieldFirstName , contactQuery.value(3));
// ignore lowerFirstName
setValue(&name, QContactName::FieldLastName , contactQuery.value(5));
// ignore lowerLastName
setValue(&name, QContactName::FieldMiddleName , contactQuery.value(7));
setValue(&name, QContactName::FieldPrefix , contactQuery.value(8));
setValue(&name, QContactName::FieldSuffix , contactQuery.value(9));
setValue(&name, QContactName__FieldCustomLabel, contactQuery.value(10));
setValue(&name, QContactName::FieldFirstName , contactQuery.value(col++));
col++; // ignore lowerFirstName
setValue(&name, QContactName::FieldLastName , contactQuery.value(col++));
col++; // ignore lowerLastName
setValue(&name, QContactName::FieldMiddleName , contactQuery.value(col++));
setValue(&name, QContactName::FieldPrefix , contactQuery.value(col++));
setValue(&name, QContactName::FieldSuffix , contactQuery.value(col++));
setValue(&name, QContactName__FieldCustomLabel, contactQuery.value(col++));
if (!name.isEmpty())
contact.saveDetail(&name);
const QString syncTarget(contactQuery.value(11).toString());
const QString syncTarget(contactQuery.value(col++).toString());
QContactSyncTarget starget;
setValue(&starget, QContactSyncTarget::FieldSyncTarget, syncTarget);
......@@ -2167,27 +2169,27 @@ QContactManager::Error ContactReader::queryContacts(
contact.saveDetail(&starget);
QContactTimestamp timestamp;
setValue(&timestamp, QContactTimestamp::FieldCreationTimestamp , ContactsDatabase::fromDateTimeString(contactQuery.value(12).toString()));
setValue(&timestamp, QContactTimestamp::FieldModificationTimestamp, ContactsDatabase::fromDateTimeString(contactQuery.value(13).toString()));
setValue(&timestamp, QContactTimestamp::FieldCreationTimestamp , ContactsDatabase::fromDateTimeString(contactQuery.value(col++).toString()));
setValue(&timestamp, QContactTimestamp::FieldModificationTimestamp, ContactsDatabase::fromDateTimeString(contactQuery.value(col++).toString()));
QContactGender gender;
// Gender is an enum in qtpim
QString genderText = contactQuery.value(14).toString();
QString genderText = contactQuery.value(col++).toString();
gender.setGender(static_cast<QContactGender::GenderField>(genderText.toInt()));
contact.saveDetail(&gender);
QContactFavorite favorite;
setValue(&favorite, QContactFavorite::FieldFavorite, contactQuery.value(15).toBool());
setValue(&favorite, QContactFavorite::FieldFavorite, contactQuery.value(col++).toBool());
if (!favorite.isEmpty())
contact.saveDetail(&favorite);
QContactStatusFlags flags;
flags.setFlag(QContactStatusFlags::HasPhoneNumber, contactQuery.value(16).toBool());
flags.setFlag(QContactStatusFlags::HasEmailAddress, contactQuery.value(17).toBool());
flags.setFlag(QContactStatusFlags::HasOnlineAccount, contactQuery.value(18).toBool());
flags.setFlag(QContactStatusFlags::IsOnline, contactQuery.value(19).toBool());
flags.setFlag(QContactStatusFlags::IsDeactivated, contactQuery.value(20).toBool());
flags.setFlag(QContactStatusFlags::IsIncidental, contactQuery.value(21).toBool());
flags.setFlag(QContactStatusFlags::HasPhoneNumber, contactQuery.value(col++).toBool());
flags.setFlag(QContactStatusFlags::HasEmailAddress, contactQuery.value(col++).toBool());
flags.setFlag(QContactStatusFlags::HasOnlineAccount, contactQuery.value(col++).toBool());
flags.setFlag(QContactStatusFlags::IsOnline, contactQuery.value(col++).toBool());
flags.setFlag(QContactStatusFlags::IsDeactivated, contactQuery.value(col++).toBool());
flags.setFlag(QContactStatusFlags::IsIncidental, contactQuery.value(col++).toBool());
if (flags.testFlag(QContactStatusFlags::IsDeactivated)) {
QContactDeactivated deactivated;
......@@ -2198,7 +2200,7 @@ QContactManager::Error ContactReader::queryContacts(
contact.saveDetail(&incidental);
}
int contactType = contactQuery.value(22).toInt();
int contactType = contactQuery.value(col++).toInt();
QContactType typeDetail = contact.detail<QContactType>();
typeDetail.setType(static_cast<QContactType::TypeValues>(contactType));
contact.saveDetail(&typeDetail);
......
......@@ -1924,6 +1924,7 @@ static bool executeDisplayLabelGroupLocalizationStatements(QSqlDatabase &databas
}
// for every single contact in our database, read the data required to generate the display label group data.
bool emitDisplayLabelGroupChange = false;
QVariantList contactIds;
QVariantList displayLabelGroups;
QVariantList displayLabelGroupSortOrders;
......@@ -1959,7 +1960,7 @@ static bool executeDisplayLabelGroupLocalizationStatements(QSqlDatabase &databas
c.saveDetail(&n);
c.saveDetail(&dl);
const QString dlg = cdb->determineDisplayLabelGroup(c);
const QString dlg = cdb->determineDisplayLabelGroup(c, &emitDisplayLabelGroupChange);
displayLabelGroups.append(dlg);
displayLabelGroupSortOrders.append(cdb->displayLabelGroupSortValue(dlg));
}
......@@ -2698,7 +2699,10 @@ static size_t writeAccessIndex = 2;
static QVector<QtContactsSqliteExtensions::DisplayLabelGroupGenerator*> initializeDisplayLabelGroupGenerators()
{
QVector<QtContactsSqliteExtensions::DisplayLabelGroupGenerator*> generators;
const QString pluginsPath = QStringLiteral("/usr/lib/qtcontacts-sqlite-qt5/");
QByteArray pluginsPathEnv = qgetenv("QTCONTACTS_SQLITE_PLUGIN_PATH");
const QString pluginsPath = pluginsPathEnv.isEmpty() ?
QStringLiteral("/usr/lib/qtcontacts-sqlite-qt5/") :
QString::fromUtf8(pluginsPathEnv);
QDir pluginDir(pluginsPath);
const QStringList pluginNames = pluginDir.entryList();
for (const QString &plugin : pluginNames) {
......@@ -3473,7 +3477,7 @@ QString ContactsDatabase::displayLabelGroupPreferredProperty() const
return retn;
}
QString ContactsDatabase::determineDisplayLabelGroup(const QContact &c)
QString ContactsDatabase::determineDisplayLabelGroup(const QContact &c, bool *emitDisplayLabelGroupChange)
{
// Read system setting to determine whether display label group
// should be generated from last name, first name, or display label.
......@@ -3532,19 +3536,17 @@ QString ContactsDatabase::determineDisplayLabelGroup(const QContact &c)
}
}
if (!group.isEmpty() && !m_knownDisplayLabelGroupsSortValues.contains(group)) {
if (emitDisplayLabelGroupChange && !group.isEmpty() && !m_knownDisplayLabelGroupsSortValues.contains(group)) {
// We are about to write a contact to the database which has a
// display label group which previously was not known / observed.
// Calculate the sort value for the display label group,
// and add it to our map of displayLabelGroup->sortValue.
// Note: this should be thread-safe since we only call this method within writes.
*emitDisplayLabelGroupChange = true;
m_knownDisplayLabelGroupsSortValues.insert(
group, ::displayLabelGroupSortValue(
group,
m_knownDisplayLabelGroupsSortValues));
// and invoke engine->_q_displayLabelGroupsChanged() asynchronously.
QMetaObject::invokeMethod(m_engine, "_q_displayLabelGroupsChanged", Qt::QueuedConnection);
}
return group;
......
......@@ -159,7 +159,7 @@ public:
void regenerateDisplayLabelGroups();
QString displayLabelGroupPreferredProperty() const;
QString determineDisplayLabelGroup(const QContact &c);
QString determineDisplayLabelGroup(const QContact &c, bool *emitDisplayLabelGroupChange = Q_NULLPTR);
QStringList displayLabelGroups() const;
int displayLabelGroupSortValue(const QString &group) const;
......
......@@ -898,6 +898,7 @@ QContactManager::Error ContactsEngine::open()
m_notifier->connect("selfContactIdChanged", "uu", this, SLOT(_q_selfContactIdChanged(quint32,quint32)));
m_notifier->connect("relationshipsAdded", "au", this, SLOT(_q_relationshipsAdded(QVector<quint32>)));
m_notifier->connect("relationshipsRemoved", "au", this, SLOT(_q_relationshipsRemoved(QVector<quint32>)));
m_notifier->connect("displayLabelGroupsChanged", "", this, SLOT(_q_displayLabelGroupsChanged()));
}
} else {
QTCONTACTS_SQLITE_WARNING(QString::fromLatin1("Unable to open asynchronous engine database connection"));
......
......@@ -139,6 +139,7 @@ ContactWriter::ContactWriter(ContactsEngine &engine, ContactsDatabase &database,
, m_database(database)
, m_notifier(notifier)
, m_reader(reader)
, m_displayLabelGroupsChanged(false)
{
Q_ASSERT(notifier);
Q_ASSERT(reader);
......@@ -177,6 +178,10 @@ bool ContactWriter::commitTransaction()
return false;
}
if (m_displayLabelGroupsChanged) {
m_notifier->displayLabelGroupsChanged();
m_displayLabelGroupsChanged = false;
}
if (!m_addedIds.isEmpty()) {
m_notifier->contactsAdded(m_addedIds.toList());
m_addedIds.clear();
......@@ -218,6 +223,7 @@ void ContactWriter::rollbackTransaction()
m_presenceChangedIds.clear();
m_changedIds.clear();
m_addedIds.clear();
m_displayLabelGroupsChanged = false;
}
QContactManager::Error ContactWriter::setIdentity(ContactsDatabase::Identity identity, QContactId contactId)
......@@ -3205,10 +3211,11 @@ QContactManager::Error ContactWriter::calculateDelta(QContact *contact, const Co
query.reportError("Failed to select modifiable details");
} else {
while (query.next()) {
const QString syncTarget = query.value<QString>(0);
const QString detail = query.value<QString>(1);
const quint32 contactId = query.value<quint32>(2);
const quint32 detailId = query.value<quint32>(3);
int col = 0;
const QString syncTarget = query.value<QString>(col++);
const QString detail = query.value<QString>(col++);
const quint32 contactId = query.value<quint32>(col++);
const quint32 detailId = query.value<quint32>(col++);
const QString provenance(QStringLiteral("%1:%2:%3").arg(contactId).arg(detailId).arg(syncTarget));
const StringPair identity = qMakePair(provenance, detail);
......@@ -4063,10 +4070,11 @@ QContactManager::Error ContactWriter::syncFetch(const QString &syncTarget, const
return QContactManager::UnspecifiedError;
}
while (query.next()) {
const quint32 aggId(query.value<quint32>(0));
const quint32 constituentId(query.value<quint32>(1));
const QString st(query.value<QString>(2));
const bool incidental(query.value<bool>(3));
int col = 0;
const quint32 aggId(query.value<quint32>(col++));
const quint32 constituentId(query.value<quint32>(col++));
const QString st(query.value<QString>(col++));
const bool incidental(query.value<bool>(col++));
ConstituentDetails details = { constituentId, st, incidental };
constituentDetails[aggId].append(details);
......@@ -5588,35 +5596,37 @@ ContactsDatabase::Query ContactWriter::bindContactDetails(const QContact &contac
const QString firstName(name.value<QString>(QContactName::FieldFirstName).trimmed());
const QString lastName(name.value<QString>(QContactName::FieldLastName).trimmed());
int col = 0;
QContactDisplayLabel label = contact.detail<QContactDisplayLabel>();
const QString displayLabel = label.label().trimmed();
query.bindValue(0, displayLabel);
const QString displayLabelGroup = m_database.determineDisplayLabelGroup(contact);
query.bindValue(1, displayLabelGroup);
query.bindValue(col++, displayLabel);
const QString displayLabelGroup = m_database.determineDisplayLabelGroup(contact, &m_displayLabelGroupsChanged);
query.bindValue(col++, displayLabelGroup);
const int displayLabelGroupSortOrder = m_database.displayLabelGroupSortValue(displayLabelGroup);
query.bindValue(2, displayLabelGroupSortOrder);
query.bindValue(col++, displayLabelGroupSortOrder);
query.bindValue(3, firstName);
query.bindValue(4, firstName.toLower());
query.bindValue(5, lastName);
query.bindValue(6, lastName.toLower());
query.bindValue(7, name.value<QString>(QContactName::FieldMiddleName).trimmed());
query.bindValue(8, name.value<QString>(QContactName::FieldPrefix).trimmed());
query.bindValue(9, name.value<QString>(QContactName::FieldSuffix).trimmed());
query.bindValue(10, name.value<QString>(QContactName__FieldCustomLabel).trimmed());
query.bindValue(col++, firstName);
query.bindValue(col++, firstName.toLower());
query.bindValue(col++, lastName);
query.bindValue(col++, lastName.toLower());
query.bindValue(col++, name.value<QString>(QContactName::FieldMiddleName).trimmed());
query.bindValue(col++, name.value<QString>(QContactName::FieldPrefix).trimmed());
query.bindValue(col++, name.value<QString>(QContactName::FieldSuffix).trimmed());
query.bindValue(col++, name.value<QString>(QContactName__FieldCustomLabel).trimmed());
const QString syncTarget(contact.detail<QContactSyncTarget>().syncTarget());
query.bindValue(11, syncTarget);
query.bindValue(col++, syncTarget);
const QContactTimestamp timestamp = contact.detail<QContactTimestamp>();
query.bindValue(12, ContactsDatabase::dateTimeString(timestamp.value<QDateTime>(QContactTimestamp::FieldCreationTimestamp).toUTC()));
query.bindValue(13, ContactsDatabase::dateTimeString(timestamp.value<QDateTime>(QContactTimestamp::FieldModificationTimestamp).toUTC()));
query.bindValue(col++, ContactsDatabase::dateTimeString(timestamp.value<QDateTime>(QContactTimestamp::FieldCreationTimestamp).toUTC()));
query.bindValue(col++, ContactsDatabase::dateTimeString(timestamp.value<QDateTime>(QContactTimestamp::FieldModificationTimestamp).toUTC()));
const QContactGender gender = contact.detail<QContactGender>();
query.bindValue(14, QString::number(static_cast<int>(gender.gender())));
query.bindValue(col++, QString::number(static_cast<int>(gender.gender())));
const QContactFavorite favorite = contact.detail<QContactFavorite>();
query.bindValue(15, favorite.isFavorite());
query.bindValue(col++, favorite.isFavorite());
// Does this contact contain the information needed to update hasPhoneNumber?
bool hasPhoneNumberKnown = definitionMask.isEmpty() || detailListContains<QContactPhoneNumber>(definitionMask);
......@@ -5651,26 +5661,26 @@ ContactsDatabase::Query ContactWriter::bindContactDetails(const QContact &contac
}
if (update) {
query.bindValue(16, hasPhoneNumberKnown);
query.bindValue(17, hasPhoneNumber);
query.bindValue(18, hasEmailAddressKnown);
query.bindValue(19, hasEmailAddress);
query.bindValue(20, hasOnlineAccountKnown);
query.bindValue(21, hasOnlineAccount);
query.bindValue(22, isOnlineKnown);
query.bindValue(23, isOnline);
query.bindValue(24, isDeactivatedKnown);
query.bindValue(25, isDeactivated);
query.bindValue(26, contactId);
query.bindValue(col++, hasPhoneNumberKnown);
query.bindValue(col++, hasPhoneNumber);
query.bindValue(col++, hasEmailAddressKnown);
query.bindValue(col++, hasEmailAddress);
query.bindValue(col++, hasOnlineAccountKnown);
query.bindValue(col++, hasOnlineAccount);
query.bindValue(col++, isOnlineKnown);
query.bindValue(col++, isOnline);
query.bindValue(col++, isDeactivatedKnown);
query.bindValue(col++, isDeactivated);
query.bindValue(col++, contactId);
} else {
query.bindValue(16, hasPhoneNumber);
query.bindValue(17, hasEmailAddress);
query.bindValue(18, hasOnlineAccount);
query.bindValue(19, isOnline);
query.bindValue(20, isDeactivated);
query.bindValue(col++, hasPhoneNumber);
query.bindValue(col++, hasEmailAddress);
query.bindValue(col++, hasOnlineAccount);
query.bindValue(col++, isOnline);
query.bindValue(col++, isDeactivated);
// Incidental state only applies to creation
query.bindValue(21, !contact.details<QContactIncidental>().isEmpty());
query.bindValue(col++, !contact.details<QContactIncidental>().isEmpty());
}
return query;
......
......@@ -172,6 +172,7 @@ private:
ContactNotifier *m_notifier;
ContactReader *m_reader;
bool m_displayLabelGroupsChanged;
QSet<QContactId> m_addedIds;
QSet<QContactId> m_removedIds;
QSet<QContactId> m_changedIds;
......
......@@ -34,6 +34,7 @@
#include <QContactDetail>
#include <QContactId>
#include <QContactManager>
#include <QContactOnlineAccount>
#include <QContactPhoneNumber>
......
......@@ -34,6 +34,8 @@
#include <qtcontacts-extensions.h>
#include <QDebug>
namespace {
QString normalize(const QString &input, int flags, int maxCharacters)
......
......@@ -3,5 +3,5 @@ includedir=${prefix}/include/qtcontacts-sqlite-qt5-extensions
Name: qtcontacts-sqlite-qt5-extensions
Description: QtContacts extensions implemented by qtcontacts-sqlite-qt5
Version: 0.2.34
Version: 0.2.36
Cflags: -I${includedir}
TARGET = tst_displaylabelgroups
include (../../../common.pri)
# We need access to QtContacts private headers
QT += contacts-private
# And we need access to the ContactManagerEngine header and moc output
# We need access to the ContactManagerEngine header and moc output
INCLUDEPATH += ../../../../src/extensions/
HEADERS += ../../../../src/extensions/contactmanagerengine.h
SOURCES += tst_displaylabelgroups.cpp
# Override the test command to setup the environment
check.commands = "QTCONTACTS_SQLITE_PLUGIN_PATH=../testplugin/contacts_dlgg/ $${check.commands}"
......@@ -40,10 +40,10 @@
#include <QContactPhoneNumber>
#include <QContactHobby>
#include <private/qcontactmanager_p.h>
#include "contactmanagerengine.h"
#include "qtcontacts-extensions.h"
#include "qtcontacts-extensions_manager_impl.h"
QTCONTACTS_USE_NAMESPACE
......@@ -288,8 +288,8 @@ void tst_DisplayLabelGroups::testDisplayLabelGroups()
// display label group generator plugin will generate a group
// for it which was previously "unknown".
// We expect that group to be added before '#' but after other groups.
typedef QtContactsSqliteExtensions::ContactManagerEngine EngineType;
EngineType *cme = dynamic_cast<EngineType *>(QContactManagerData::managerData(m_cm)->m_engine);
QtContactsSqliteExtensions::ContactManagerEngine *cme =
QtContactsSqliteExtensions::contactManagerEngine(*m_cm);
const QStringList oldContactDisplayLabelGroups = cme->displayLabelGroups();
QSignalSpy dlgcSpy(cme, SIGNAL(displayLabelGroupsChanged(QStringList)));
......