#include "stdafx.h" #include "mirandahistory.h" #include "mirandasettings.h" /* * MirandaHistory */ void MirandaHistory::populateProtocols() { m_Protocols.clear(); PROTOACCOUNT **protoList; int protoCount; Proto_EnumAccounts(&protoCount, &protoList); upto_each_(i, protoCount) { ext::a::string protoName = protoList[i]->szModuleName; m_Protocols[protoName] = protoList[i]->tszAccountName; } m_DefaultProtocol = TranslateT("(Unknown)"); } const ext::string& MirandaHistory::getProtocol(const ext::a::string& protocol) const { auto i = m_Protocols.find(protocol); return (i != m_Protocols.end()) ? i->second : m_DefaultProtocol; } void MirandaHistory::makeContactsAvailable() { if (m_bContactsAvailable) return; // make protocols available populateProtocols(); // first run: // - enum all contacts // - skip for ignored protocol // - handle meta contacts (if enabled and available) // - skip manually excluded readContacts(); // second run: // - merge contacts with similar names mergeContacts(); m_bContactsAvailable = true; } void MirandaHistory::readContacts() { bool bHandleMeta = m_Settings.m_MetaContactsMode != Settings::mcmIgnoreMeta; ext::a::string strMetaProto = bHandleMeta ? META_PROTO : ""; MirandaSettings db; db.setModule(con::ModCList); std::vector sources; for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { db.setContact(hContact); const char* pProtoName = GetContactProto(hContact); // ignore because of bad or not loaded protocol? if (!pProtoName) pProtoName = con::ProtoUnknown; // MEMO: alternative would be "break;" ext::string curNick = pcli->pfnGetContactDisplayName(hContact, 0); // retrieve protocol const ext::a::string curProtoName = pProtoName; const ext::string& curProto = getProtocol(curProtoName); // retrieve group ext::string curGroup = db.readStrDirect(con::SettGroup, TranslateT("(none)")); // ignore because of filtered protocol? if (m_Settings.m_ProtosIgnore.find(curProtoName) != m_Settings.m_ProtosIgnore.end()) continue; // init list of event sources sources.clear(); sources.push_back(hContact); // handle meta-contacts if (bHandleMeta) { if (curProtoName == strMetaProto) { // don't include meta-contact history if (m_Settings.m_MetaContactsMode == Settings::mcmSubOnly) sources.clear(); // include meta-contact's subcontact if (m_Settings.m_MetaContactsMode != Settings::mcmMetaOnly) { // find subcontacts to read history from int numSubs = db_mc_getSubCount(hContact); if (numSubs > 0) { for (int i = 0; i < numSubs; ++i) { MCONTACT hSubContact = db_mc_getSub(hContact, i); if (hSubContact) sources.push_back(hSubContact); } } } } else { // ignore because of meta-contact? if (db_mc_isMeta(hContact)) continue; } } // ignore because of exclude? if (db_get_b(hContact, con::ModHistoryStats, con::SettExclude, false)) continue; // finally add to list MirandaContact* pContact = MirandaContactFactory::makeMirandaContact(m_Settings.m_MergeMode, curNick, curProto, curGroup, sources); m_Contacts.push_back(pContact); } } void MirandaHistory::mergeContacts() { if (!m_Settings.m_MergeContacts) return; for (size_t i = 0; i < m_Contacts.size(); ++i) { MirandaContact& cur = *m_Contacts[i]; for (size_t j = i + 1; j < m_Contacts.size(); ++j) { if (m_Contacts[j]->getNick() == cur.getNick()) { if (!m_Settings.m_MergeContactsGroups || m_Contacts[j]->getGroup() == cur.getGroup()) { cur.merge(*m_Contacts[j]); delete m_Contacts[j]; m_Contacts.erase(m_Contacts.begin() + j); --j; } } } } } MirandaHistory::MirandaHistory(const Settings& settings) : m_Settings(settings), m_bContactsAvailable(false) { } MirandaHistory::~MirandaHistory() { citer_each_(ContactList, i, m_Contacts) { delete *i; } m_Contacts.clear(); } int MirandaHistory::getContactCount() { if (!m_bContactsAvailable) makeContactsAvailable(); return m_Contacts.size(); } MirandaContact& MirandaHistory::getContact(int index) { if (!m_bContactsAvailable) makeContactsAvailable(); assert(index >= 0 && index < m_Contacts.size()); return *m_Contacts[index]; }