From 6124c46a1ce49103be088d9823e894d5643eaf8c Mon Sep 17 00:00:00 2001 From: blue Date: Fri, 19 Apr 2019 12:12:12 +0300 Subject: [PATCH] new contact handeling in core --- core/account.cpp | 242 ++++++++++++++++++++++++++++------------------- core/account.h | 12 +++ core/contact.cpp | 42 +++++++- core/contact.h | 14 ++- 4 files changed, 209 insertions(+), 101 deletions(-) diff --git a/core/account.cpp b/core/account.cpp index 58227df..9517c39 100644 --- a/core/account.cpp +++ b/core/account.cpp @@ -48,6 +48,9 @@ Account::Account(const QString& p_login, const QString& p_server, const QString& Account::~Account() { + for (std::map::const_iterator itr = contacts.begin(), end = contacts.end(); itr != end; ++itr) { + delete itr->second; + } } Shared::ConnectionState Core::Account::getState() const @@ -133,121 +136,82 @@ void Core::Account::onRosterItemAdded(const QString& bareJid) void Core::Account::onRosterItemChanged(const QString& bareJid) { + std::map::const_iterator itr = contacts.find(bareJid); + if (itr == contacts.end()) { + qDebug() << "An attempt to change non existing contact" << bareJid << "from account" << name << ", skipping"; + return; + } + Contact* contact = itr->second; QXmppRosterManager& rm = client.rosterManager(); QXmppRosterIq::Item re = rm.getRosterEntry(bareJid); - QSet newGroups = re.groups(); - QSet oldGroups; - QStringList res = rm.getResources(bareJid); - unsigned int state = re.subscriptionType(); - if (state == QXmppRosterIq::Item::NotSet) { - state = Shared::unknown; - } - QMap cData({ - {"name", re.name()}, - {"state", state} - }); - - emit changeContact(bareJid, cData); - - for (std::map>::iterator itr = groups.begin(), end = groups.end(); itr != end; ++itr) { - std::set& contacts = itr->second; - std::set::const_iterator cItr = contacts.find(bareJid); - if (cItr != contacts.end()) { - oldGroups.insert(itr->first); - } - } - - QSet toRemove = oldGroups - newGroups; - QSet toAdd = newGroups - oldGroups; - - QSet removeGroups; - for (QSet::iterator itr = toRemove.begin(), end = toRemove.end(); itr != end; ++itr) { - const QString& groupName = *itr; - std::set& contacts = groups.find(groupName)->second; - contacts.erase(bareJid); - emit removeContact(bareJid, groupName); - if (contacts.size() == 0) { - removeGroups.insert(groupName); - } - } - - for (QSet::iterator itr = toAdd.begin(), end = toAdd.end(); itr != end; ++itr) { - const QString& groupName = *itr; - std::map>::iterator cItr = groups.find(groupName); - if (cItr == groups.end()) { - cItr = groups.insert(std::make_pair(groupName, std::set())).first; - emit addGroup(groupName); - } - cItr->second.insert(bareJid); - emit addContact(bareJid, groupName, cData); - } - - for (QSet::iterator itr = removeGroups.begin(), end = removeGroups.end(); itr != end; ++itr) { - const QString& groupName = *itr; - emit removeGroup(groupName); - groups.erase(groupName); - } + Shared::SubscriptionState state = castSubscriptionState(re.subscriptionType()); + + contact->setGroups(re.groups()); + contact->setSubscriptionState(state); + contact->setName(name); } void Core::Account::onRosterItemRemoved(const QString& bareJid) { + std::map::const_iterator itr = contacts.find(bareJid); + if (itr == contacts.end()) { + qDebug() << "An attempt to remove non existing contact" << bareJid << "from account" << name << ", skipping"; + return; + } + Contact* contact = itr->second; + QSet cGroups = contact->getGroups(); + for (QSet::const_iterator itr = cGroups.begin(), end = cGroups.end(); itr != end; ++itr) { + removeFromGroup(bareJid, *itr); + } emit removeContact(bareJid); - - QSet toRemove; - for (std::map>::iterator itr = groups.begin(), end = groups.end(); itr != end; ++itr) { - std::set contacts = itr->second; - std::set::const_iterator cItr = contacts.find(bareJid); - if (cItr != contacts.end()) { - contacts.erase(cItr); - if (contacts.size() == 0) { - toRemove.insert(itr->first); - } - } - } - - for (QSet::iterator itr = toRemove.begin(), end = toRemove.end(); itr != end; ++itr) { - const QString& groupName = *itr; - emit removeGroup(groupName); - groups.erase(groupName); - } } void Core::Account::addedAccount(const QString& jid) { QXmppRosterManager& rm = client.rosterManager(); - std::map::const_iterator itr = contacts.find(jid); - if (itr == contacts.end()) { - - } - QXmppRosterIq::Item re = rm.getRosterEntry(jid); - QSet gr = re.groups(); - unsigned int state = re.subscriptionType(); - if (state == QXmppRosterIq::Item::NotSet) { - state = Shared::unknown; - } - QMap cData({ - {"name", re.name()}, - {"state", state} - }); - int grCount = 0; - for (QSet::const_iterator itr = gr.begin(), end = gr.end(); itr != end; ++itr) { - const QString& groupName = *itr; - std::map>::iterator gItr = groups.find(groupName); - if (gItr == groups.end()) { - gItr = groups.insert(std::make_pair(groupName, std::set())).first; - emit addGroup(groupName); - } - gItr->second.insert(jid); - emit addContact(jid, groupName, cData); - grCount++; + Contact* contact; + bool newContact = false; + if (itr == contacts.end()) { + newContact = true; + contact = new Contact(jid, name); + contacts.insert(std::make_pair(jid, contact)); + + } else { + contact = itr->second; } - if (grCount == 0) { - emit addContact(jid, "", cData); + QSet gr = re.groups(); + Shared::SubscriptionState state = castSubscriptionState(re.subscriptionType()); + contact->setGroups(gr); + contact->setSubscriptionState(state); + contact->setName(re.name()); + + if (newContact) { + QMap cData({ + {"name", re.name()}, + {"state", state} + }); + int grCount = 0; + for (QSet::const_iterator itr = gr.begin(), end = gr.end(); itr != end; ++itr) { + const QString& groupName = *itr; + addToGroup(jid, groupName); + emit addContact(jid, groupName, cData); + grCount++; + } + + if (grCount == 0) { + emit addContact(jid, "", cData); + } + + QObject::connect(contact, SIGNAL(groupAdded(const QString&)), this, SLOT(onContactGroupAdded(const QString&))); + QObject::connect(contact, SIGNAL(groupRemoved(const QString&)), this, SLOT(onContactGroupRemoved(const QString&))); + QObject::connect(contact, SIGNAL(nameChanged(const QString&)), this, SLOT(onContactNameChanged(const QString&))); + QObject::connect(contact, SIGNAL(subscriptionStateChanged(Shared::SubscriptionState)), + this, SLOT(onContactSubscriptionStateChanged(Shared::SubscriptionState))); } } @@ -486,3 +450,87 @@ void Core::Account::onMamResultsReceived(const QString& queryId, const QXmppResu achiveQueries.insert(std::make_pair(nQ, jid)); } } + +void Core::Account::onContactGroupAdded(const QString& group) +{ + Contact* contact = static_cast(sender()); + if (contact->groupsCount() == 1) { + // not sure i need to handle it here, the situation with grouped and ungrouped contacts handled on the client anyway + } + + QMap cData({ + {"name", contact->getName()}, + {"state", contact->getSubscriptionState()} + }); + addToGroup(contact->jid, group); + emit addContact(contact->jid, group, cData); +} + +void Core::Account::onContactGroupRemoved(const QString& group) +{ + Contact* contact = static_cast(sender()); + if (contact->groupsCount() == 0) { + // not sure i need to handle it here, the situation with grouped and ungrouped contacts handled on the client anyway + } + + emit removeContact(contact->jid, group); + removeFromGroup(contact->jid, group); +} + +void Core::Account::onContactNameChanged(const QString& cname) +{ + Contact* contact = static_cast(sender()); + QMap cData({ + {"name", cname}, + }); + emit changeContact(contact->jid, cData); +} + +void Core::Account::onContactSubscriptionStateChanged(Shared::SubscriptionState cstate) +{ + Contact* contact = static_cast(sender()); + QMap cData({ + {"state", cstate}, + }); + emit changeContact(contact->jid, cData); +} + +void Core::Account::addToGroup(const QString& jid, const QString& group) +{ + std::map>::iterator gItr = groups.find(group); + if (gItr == groups.end()) { + gItr = groups.insert(std::make_pair(group, std::set())).first; + emit addGroup(group); + } + gItr->second.insert(jid); +} + +void Core::Account::removeFromGroup(const QString& jid, const QString& group) +{ + QSet toRemove; + std::map>::iterator itr = groups.find(group); + if (itr == groups.end()) { + qDebug() << "An attempt to remove contact" << jid << "of account" << name << "from non existing group" << group << ", skipping"; + return; + } + std::set contacts = itr->second; + std::set::const_iterator cItr = contacts.find(jid); + if (cItr != contacts.end()) { + contacts.erase(cItr); + if (contacts.size() == 0) { + emit removeGroup(group); + groups.erase(group); + } + } +} + +Shared::SubscriptionState Core::Account::castSubscriptionState(QXmppRosterIq::Item::SubscriptionType qs) const +{ + Shared::SubscriptionState state; + if (qs == QXmppRosterIq::Item::NotSet) { + state = Shared::unknown; + } else { + state = static_cast(qs); + } + return state; +} diff --git a/core/account.h b/core/account.h index 104b407..72abb55 100644 --- a/core/account.h +++ b/core/account.h @@ -71,21 +71,33 @@ private: private slots: void onClientConnected(); void onClientDisconnected(); + void onRosterReceived(); void onRosterItemAdded(const QString& bareJid); void onRosterItemChanged(const QString& bareJid); void onRosterItemRemoved(const QString& bareJid); void onRosterPresenceChanged(const QString& bareJid, const QString& resource); + void onPresenceReceived(const QXmppPresence& presence); void onMessageReceived(const QXmppMessage& message); + void onCarbonMessageReceived(const QXmppMessage& message); void onCarbonMessageSent(const QXmppMessage& message); + void onMamMessageReceived(const QString& bareJid, const QXmppMessage& message); void onMamResultsReceived(const QString &queryId, const QXmppResultSetReply &resultSetReply, bool complete); + + void onContactGroupAdded(const QString& group); + void onContactGroupRemoved(const QString& group); + void onContactNameChanged(const QString& name); + void onContactSubscriptionStateChanged(Shared::SubscriptionState state); private: void addedAccount(const QString &bareJid); bool handleChatMessage(const QXmppMessage& msg, bool outgoing = false, bool forwarded = false, bool guessing = false); + void addToGroup(const QString& jid, const QString& group); + void removeFromGroup(const QString& jid, const QString& group); + Shared::SubscriptionState castSubscriptionState(QXmppRosterIq::Item::SubscriptionType qs) const; }; } diff --git a/core/contact.cpp b/core/contact.cpp index 06f7ddd..1cc7e8a 100644 --- a/core/contact.cpp +++ b/core/contact.cpp @@ -23,8 +23,9 @@ Core::Contact::Contact(const QString& pJid, const QString& account, QObject* par jid(pJid), name(), groups(), - state(empty), - archive(new Archive(jid)) + archiveState(empty), + archive(new Archive(jid)), + subscriptionState(Shared::unknown) { archive->open(account); } @@ -36,7 +37,7 @@ Core::Contact::~Contact() Core::Contact::ArchiveState Core::Contact::getArchiveState() const { - return state; + return archiveState; } QSet Core::Contact::getGroups() const @@ -53,5 +54,40 @@ void Core::Contact::setName(const QString& n) { if (name != n) { name = n; + emit nameChanged(name); } } + +Shared::SubscriptionState Core::Contact::getSubscriptionState() const +{ + return subscriptionState; +} + +void Core::Contact::setGroups(const QSet& set) +{ + QSet toRemove = groups - set; + QSet toAdd = set - groups; + + groups = set; + + for (QSet::iterator itr = toRemove.begin(), end = toRemove.end(); itr != end; ++itr) { + emit groupRemoved(*itr); + } + + for (QSet::iterator itr = toAdd.begin(), end = toAdd.end(); itr != end; ++itr) { + emit groupAdded(*itr); + } +} + +void Core::Contact::setSubscriptionState(Shared::SubscriptionState state) +{ + if (subscriptionState != state) { + subscriptionState = state; + emit subscriptionStateChanged(subscriptionState); + } +} + +unsigned int Core::Contact::groupsCount() const +{ + return groups.size(); +} diff --git a/core/contact.h b/core/contact.h index 5b5d5c0..b245d45 100644 --- a/core/contact.h +++ b/core/contact.h @@ -22,6 +22,7 @@ #include #include #include "archive.h" +#include "../global.h" namespace Core { @@ -43,6 +44,16 @@ public: QString getName() const; void setName(const QString& n); QSet getGroups() const; + void setGroups(const QSet& set); + void setSubscriptionState(Shared::SubscriptionState state); + Shared::SubscriptionState getSubscriptionState() const; + unsigned int groupsCount() const; + +signals: + void groupAdded(const QString& name); + void groupRemoved(const QString& name); + void nameChanged(const QString& name); + void subscriptionStateChanged(Shared::SubscriptionState state); public: const QString jid; @@ -50,8 +61,9 @@ public: private: QString name; QSet groups; - ArchiveState state; + ArchiveState archiveState; Archive* archive; + Shared::SubscriptionState subscriptionState; }; }