diff -r e4ebb16b39ea -r 603d3f8b6302 plugins/contacts/maemo5/qcontactabook.cpp --- a/plugins/contacts/maemo5/qcontactabook.cpp Fri Sep 17 08:34:34 2010 +0300 +++ b/plugins/contacts/maemo5/qcontactabook.cpp Mon Oct 04 01:37:06 2010 +0300 @@ -327,6 +327,7 @@ return rtn; */ } +#include "qcontactdetail_p.h" QContact* QContactABook::getQContact(const QContactLocalId& contactId, QContactManager::Error* error) const { @@ -824,18 +825,11 @@ /* Note */ detailList << getNoteDetail(eContact); - /* Online Account & presences*/ - QList onlineAccounts; - QList presences; - getOnlineAccountAndPresenceDetails(eContact, onlineAccounts, presences); - + /* Online Account */ + QList onlineAccountList = getOnlineAccountDetail(eContact); QContactOnlineAccount* onlineAccount; - foreach(onlineAccount, onlineAccounts) + foreach(onlineAccount, onlineAccountList) detailList << onlineAccount; - - QContactPresence* presence; - foreach(presence, presences) - detailList << presence; /* Organization */ detailList << getOrganizationDetail(eContact); @@ -902,15 +896,29 @@ QCM5_DEBUG << "Getting aContact with id " << m_localIds[contactId] << "local contactId is" << contactId; - if(QString::fromAscii(m_localIds[contactId]).compare("osso-abook-self") == 0) { + if(QString(m_localIds[contactId]).compare("osso-abook-self") == 0) { *error = QContactManager::NoError; rtn = A_CONTACT(osso_abook_self_contact_get_default()); } else { - GList* c = osso_abook_aggregator_lookup(m_abookAgregator, m_localIds[contactId]); - if (c) - rtn = A_CONTACT(c->data); - *error = rtn ? QContactManager::NoError : QContactManager::DoesNotExistError; - return rtn; + EBookQuery* query; + GList* contacts; + + query = e_book_query_field_test(E_CONTACT_UID, E_BOOK_QUERY_IS, m_localIds[contactId]); + contacts = osso_abook_aggregator_find_contacts(m_abookAgregator, query); + if (query) + e_book_query_unref(query); + + if (g_list_length(contacts) == 1) { + *error = QContactManager::NoError; + rtn = A_CONTACT(contacts->data); + } else if (g_list_length(contacts) == 0) { + *error = QContactManager::DoesNotExistError; + } else { + // Several contacts have the same UID or the contactId belongs to a roster contact. + *error = QContactManager::UnspecifiedError; + } + if (contacts) + g_list_free(contacts); } return rtn; @@ -972,15 +980,14 @@ // Set Address Values GList *v = NULL; v =e_vcard_attribute_get_values(attr); - if (!v) { - // ADR attribute data is corrupted. Skipping. - g_list_free(attrList); - return rtnList; + if (!v) + qFatal("ADR attribute data is corrupted"); + if (g_list_length(v) != 7){ + g_list_free(v); + qCritical() << "ADR attribute data is corrupted"; } - int i = 0; - while (v && i < 7) { - // we only deal with the first 7 fields: pobox, extension, street, locality, region, postcode, country. + while (v){ map[addressFields[i]] = QString::fromUtf8(CONST_CHAR(v->data)); i++; v = v->next; @@ -993,6 +1000,7 @@ } g_list_free(attrList); + return rtnList; } @@ -1226,52 +1234,28 @@ return QStringList(); } -#if 0 -// BUG? This code has been commented out because osso_abook_presence_get_presence_status returns empty strings -static QContactPresence::PresenceState telepathyStatusToPresenceState(const QString& status){ - if (status == "offline") - return QContactPresence::PresenceOffline; - else if (status == "unknown" || status == "error") - return QContactPresence::PresenceUnknown; - else if (status == "available") - return QContactPresence::PresenceAvailable; - else if (status == "away" || status == "brb" ) //Be Right Back (a more specific form of Away) - return QContactPresence::PresenceAway; - else if (status == "busy" || status == "dnd") //Do Not Disturb (a more specific form of Busy) - return QContactPresence::PresenceBusy; - else if (status == "xa") //Extended Away - return QContactPresence::PresenceExtendedAway; - else if (status == "hidden") // "Invisible" or "Appear Offline" - return QContactPresence::PresenceHidden; -} -#endif - -void QContactABook::getOnlineAccountAndPresenceDetails(EContact *eContact, - QList& onlineAccounts, - QList& presences) const +QList QContactABook::getOnlineAccountDetail(EContact *eContact) const { + QList rtnList; + + // Get VCards that store Online Account Details. const QStringList telepathyVCards = vcardsManagedByTelepathy(); - // Parsing Attributes associated to the Telepathy VCards + // Parsing Attributes associated to the previous VCards GList *attributeList = e_vcard_get_attributes((EVCard*)eContact); GList *node; if (!attributeList) - return; + return rtnList; for (node = attributeList; node != NULL; node = g_list_next (node)) { - QContactOnlineAccount* onlineAccount = new QContactOnlineAccount; - QContactPresence* contactPresence = new QContactPresence; - + QContactOnlineAccount* rtn = new QContactOnlineAccount; const char* accountUri = NULL; const char* serviceProvider = NULL; const char* accountPath = NULL; // Outgoing account path eg: SERVICE_NAME/PROTOCOL_NAME/USER_NAME - EVCardAttribute* attr = NULL; - QVariantMap map; - QString presenceMsg, presenceIcon, presenceDisplayState, presenceNickname; + QStringList caps; - - attr = (EVCardAttribute*)node->data; + EVCardAttribute* attr = (EVCardAttribute*)node->data; if (!attr) continue; @@ -1284,50 +1268,32 @@ accountUri = e_vcard_attribute_get_value(attr); // Get AccountPath and service provider for the roster contact associated to the attribute - // Note: there should be just one roster contact associated to the attribute GList* rContacts = osso_abook_contact_find_roster_contacts_for_attribute(A_CONTACT(eContact), attr); for (GList * node = rContacts; node != NULL; node = g_list_next(node)){ OssoABookContact* c = NULL; + McAccount* a = NULL; c = A_CONTACT(node->data); if (c) { - McAccount* a = NULL; - OssoABookPresence *p = NULL; - a = osso_abook_contact_get_account(c); if (a){ accountPath = a->name; serviceProvider = mc_account_compat_get_profile(a); } - - p = OSSO_ABOOK_PRESENCE(c); - presenceMsg = QString::fromUtf8(osso_abook_presence_get_presence_status_message(p)); - presenceIcon = QString::fromUtf8(osso_abook_presence_get_icon_name(p)); - // presenceState = QString::fromUtf8(osso_abook_presence_get_presence_status(p)); //BUG in osso_abook_presence_get_presence_status?? - presenceDisplayState = QString::fromUtf8(osso_abook_presence_get_display_status(p)); - presenceNickname = QString::fromUtf8(osso_abook_contact_get_display_name(c)); - // Set OnlineAccount details - map.clear(); - map[QContactOnlineAccount::FieldAccountUri] = accountUri; - map[QContactOnlineAccount::FieldCapabilities] = serviceProviderCapabilities(serviceProvider); - map[QContactOnlineAccount::FieldServiceProvider] = serviceProvider; // eg: facebook-chat, - map["AccountPath"] = accountPath; - setDetailValues(map, onlineAccount); - onlineAccounts << onlineAccount; - - // Set OnlinePresence details - map.clear(); - map[QContactDetail::FieldLinkedDetailUris] = accountUri; - map[QContactPresence::FieldCustomMessage] = presenceMsg; - map[QContactPresence::FieldPresenceStateImageUrl] = presenceIcon; - map[QContactPresence::FieldPresenceStateText] = presenceDisplayState; - map[QContactPresence::FieldNickname] = presenceNickname; - //map[QContactPresence::FieldPresenceState] = telepathyStatusToPresenceState(presenceState); - //map[QContactPresence::FieldTimestamp] = ; - setDetailValues(map, contactPresence); - presences << contactPresence; } } + + // Set details + QVariantMap map; + map[QContactOnlineAccount::FieldAccountUri] = accountUri; + map[QContactOnlineAccount::FieldCapabilities] = serviceProviderCapabilities(serviceProvider); + map[QContactOnlineAccount::FieldServiceProvider] = serviceProvider; // eg: facebook-chat, + map["AccountPath"] = accountPath; + setDetailValues(map, rtn); + + rtnList << rtn; } + + return rtnList; } QContactOrganization* QContactABook::getOrganizationDetail(EContact *eContact) const @@ -1388,6 +1354,134 @@ return rtnList; } + +QList QContactABook::getPresenceDetail(EContact *eContact) const +{ + QList rtnList; + + QStringList evcardToSkip = vcardsManagedByTelepathy(); + + // Gets info of online accounts from roster contacts associated to the master one + if (!osso_abook_contact_is_roster_contact (A_CONTACT(eContact))) { + QContactPresence* rtn = new QContactPresence; + + GList *contacts = osso_abook_contact_get_roster_contacts(A_CONTACT(eContact)); + GList *node; + for (node = contacts; node != NULL; node = g_list_next(node)){ + OssoABookContact *rosterContact = A_CONTACT(node->data); + + McProfile* id = osso_abook_contact_get_profile(rosterContact); + McAccount* account = osso_abook_contact_get_account(rosterContact); + + // Avoid to look for Roster contacts into the VCard + QString accountVCard = mc_profile_get_vcard_field(id); + evcardToSkip.removeOne(accountVCard); + + // Presence + OssoABookPresence *presence = OSSO_ABOOK_PRESENCE (rosterContact); + TpConnectionPresenceType presenceType = osso_abook_presence_get_presence_type (presence); + QString presenceTypeString; + QContactPresence::PresenceState presenceTypeEnum; + switch (presenceType) { + case TP_CONNECTION_PRESENCE_TYPE_UNSET: presenceTypeString = "Unset"; presenceTypeEnum = QContactPresence::PresenceUnknown; break; + case TP_CONNECTION_PRESENCE_TYPE_OFFLINE: presenceTypeString = "Offline"; presenceTypeEnum = QContactPresence::PresenceOffline; break; + case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE: presenceTypeString = "Available"; presenceTypeEnum = QContactPresence::PresenceAvailable; break; + case TP_CONNECTION_PRESENCE_TYPE_AWAY: presenceTypeString = "Away"; presenceTypeEnum = QContactPresence::PresenceAway; break; + case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY: presenceTypeString = "Extended Away"; presenceTypeEnum = QContactPresence::PresenceExtendedAway; break; + case TP_CONNECTION_PRESENCE_TYPE_HIDDEN: presenceTypeString = "Hidden"; presenceTypeEnum = QContactPresence::PresenceHidden; break; + case TP_CONNECTION_PRESENCE_TYPE_BUSY: presenceTypeString = "Busy"; presenceTypeEnum = QContactPresence::PresenceBusy; break; + case TP_CONNECTION_PRESENCE_TYPE_UNKNOWN: presenceTypeString = "Unknown"; presenceTypeEnum = QContactPresence::PresenceUnknown; break; + case TP_CONNECTION_PRESENCE_TYPE_ERROR: presenceTypeString = "Error"; presenceTypeEnum = QContactPresence::PresenceUnknown; break; + default: + qCritical() << "Presence type is not valid" << presenceType; + } + + QVariantMap map; // XXX FIXME + map[QContactPresence::FieldNickname] = osso_abook_contact_get_display_name(rosterContact); + map[QContactPresence::FieldPresenceState] = presenceTypeEnum; + map[QContactPresence::FieldPresenceStateText] = QString::fromUtf8(osso_abook_presence_get_presence_status_message(presence)); + map[QContactPresence::FieldLinkedDetailUris] = mc_profile_get_unique_name(id); //use the unique name as a detail uri of the online account. + map["AccountPath"] = account->name; //MCAccount name: variable part of the D-Bus object path. + + setDetailValues(map, rtn); + } + rtnList << rtn; + g_list_free (contacts); + } + + /* Users can add Online account details manually. Eg: IRC username. + * evcardToSkip stringlist contains evCard attributes that have been already processed. + */ + GList *attributeList = e_vcard_get_attributes((EVCard*)eContact); + GList *node; + + if (attributeList) { + for (node = attributeList; node != NULL; node = g_list_next (node)) { + EVCardAttribute* attr = (EVCardAttribute*)node->data; + if (!attr) + continue; + QString attributeName = e_vcard_attribute_get_name(attr); + + // Skip attributes processed scanning roster contacts. + if (!evcardToSkip.contains(attributeName)) + continue; + + GList *params = e_vcard_attribute_get_params(attr); + GList *nodeP; + QString type; + // If the parameter list lenght is 1, X-OSSO-VALID is not specified + bool ossoValidIsOk = (g_list_length(params) == 1) ? true : false; + + for (nodeP = params; nodeP != NULL; nodeP = g_list_next (nodeP)) { + EVCardAttributeParam* p = (EVCardAttributeParam*) nodeP->data; + QString paramName = e_vcard_attribute_param_get_name(p); + bool attrIsType = false; + bool attrIsOssoValid = false; + + //If type is empty check if the attribute is "TYPE" + if (type.isEmpty()) + attrIsType = paramName.contains(EVC_TYPE); + + if(!ossoValidIsOk) + attrIsOssoValid = paramName.contains("X-OSSO-VALID"); + + if (!attrIsType && !attrIsOssoValid) { + //qWarning () << "Skipping attribute parameter checking for" << paramName; + continue; + } + + GList *values = e_vcard_attribute_param_get_values(p); + GList *node; + for (node = values; node != NULL; node = g_list_next (node)) { + QString attributeParameterValue = CONST_CHAR(node->data); + if (attrIsOssoValid) { + ossoValidIsOk = (attributeParameterValue == "yes")? true : false; + if (!ossoValidIsOk) { + //qWarning() << "X-OSSO-VALID is false."; + break; + } + } else if (type.isEmpty()) { + type = attributeParameterValue; + if (type.isEmpty()) + qCritical() << "TYPE is empty"; + } + } + + if (ossoValidIsOk && !type.isEmpty()) { + QContactPresence* rtn = new QContactPresence; + QVariantMap map; + map[QContactPresence::FieldNickname] = QString::fromUtf8(e_vcard_attribute_get_value(attr)); + map[QContactPresence::FieldLinkedDetailUris] = type; // XXX FIXME + setDetailValues(map, rtn); + rtnList << rtn; + } + } + } + } + + return rtnList; +} + QContactTimestamp* QContactABook::getTimestampDetail(EContact *eContact) const { QContactTimestamp* rtn = new QContactTimestamp;