#include "stdafx.h" #include "CContactList.h" #include "CConfig.h" #include "CAppletManager.h" const int aiStatusPriority[] = { 0, // ID_STATUS_OFFLINE 40071 9, // ID_STATUS_ONLINE 40072 8, // ID_STATUS_AWAY 40073 1, // ID_STATUS_DND 40074 7, // ID_STATUS_NA 40075 6, // ID_STATUS_OCCUPIED 40076 10, // ID_STATUS_FREECHAT 40077 9, // ID_STATUS_INVISIBLE 40078 8, // ID_STATUS_ONTHEPHONE 40079 8 // ID_STATUS_OUTTOLUNCH 40080 }; //************************************************************************ // constructor //************************************************************************ CContactList::CContactList() : m_bUseGroups(false), m_bUseMetaContacts(false), m_dwLastScroll(0) { } //************************************************************************ // destructor //************************************************************************ CContactList::~CContactList() { } //************************************************************************ // initializes the list //************************************************************************ bool CContactList::Initialize() { if(!CLCDList::Initialize()) return false; InitializeGroupObjects(); RefreshList(); return true; } //************************************************************************ // deinitializes the list //************************************************************************ bool CContactList::Shutdown() { if(!CLCDList::Shutdown()) return false; UninitializeGroupObjects(); return false; } //************************************************************************ // returns the contacts ccontactlistentry class //************************************************************************ CContactListEntry *CContactList::GetContactData(CListEntry *pEntry) { if(pEntry->GetType() == ITEM) return ((CListItem*)pEntry)->GetItemData(); else return ((CListContainer*)pEntry)->GetGroupData()->pContactListEntry; } //************************************************************************ // returns the contacts group path //************************************************************************ tstring CContactList::GetContactGroupPath(MCONTACT hContact) { tstring strGroup = L""; if(db_get_b(0, "MetaContacts", "Enabled", 1) && db_mc_isSub(hContact)) { MCONTACT hMetaContact = db_mc_getMeta(hContact); if(CConfig::GetBoolSetting(CLIST_USEGROUPS)) strGroup = CAppletManager::GetContactGroup(hMetaContact); tstring strMetaName = CAppletManager::GetContactDisplayname(hMetaContact); strGroup += (strGroup.empty()?L"":L"\\")+ strMetaName; } else strGroup = CAppletManager::GetContactGroup(hContact); return strGroup; } //************************************************************************ // adds a contact to the list //************************************************************************ void CContactList::AddContact(MCONTACT hContact) { CListContainer *pGroup = nullptr; tstring strName = CAppletManager::GetContactDisplayname(hContact); char *szProto = GetContactProto(hContact); tstring strGroup = GetContactGroupPath(hContact); // ignore contacts without a valid protocoll if(szProto == nullptr) return; int iStatus = db_get_w(hContact,szProto,"Status",ID_STATUS_OFFLINE); wchar_t *szStatus = pcli->pfnGetStatusModeDescription(iStatus, 0); CContactListEntry *psContact = new CContactListEntry(); psContact->strName = strName; psContact->iMessages = 0; psContact->hHandle = hContact; psContact->iStatus = iStatus; if(szStatus != nullptr) psContact->strStatus =toTstring(szStatus); psContact->strProto = toTstring(szProto); // check wether the contact should be listed if(!IsVisible(psContact)) { delete psContact; return; } // Don't add metacontacts as contacts if(!mir_strcmpi(szProto,"MetaContacts")) { if(!CConfig::GetBoolSetting(CLIST_USEGROUPS)) strGroup = L""; strGroup += (strGroup.empty()?L"":L"\\")+psContact->strName; pGroup = GetGroupByString(strGroup); if(pGroup == nullptr) pGroup = AddGroupByString(strGroup); pGroup->GetGroupData()->hMetaContact = hContact; pGroup->GetGroupData()->pContactListEntry = psContact; pGroup = (CListContainer*)pGroup->GetParent(); if(pGroup->GetType() != ROOT && iStatus != ID_STATUS_OFFLINE) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,1); pGroup->sort(CContactList::CompareEntries); // check that all subcontacts exist int numContacts = db_mc_getSubCount(hContact); MCONTACT hSubContact = NULL; for(int i=0;i *pItem = nullptr; if((!db_mc_isSub(hContact) && !CConfig::GetBoolSetting(CLIST_USEGROUPS)) || strGroup.empty()) { pItem = AddItem(psContact); ((CListContainer*)this)->sort(CContactList::CompareEntries); } else { pGroup = GetGroupByString(strGroup); if(pGroup == nullptr) { pGroup = AddGroupByString(strGroup); } pItem = pGroup->AddItem(psContact); if(!db_mc_isSub(hContact) && iStatus != ID_STATUS_OFFLINE) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,1); pGroup->sort(CContactList::CompareEntries); } UpdateMessageCounter((CListEntry*)pItem); } //************************************************************************ // returns wether a contact should be listed or not //************************************************************************ bool CContactList::IsVisible(CContactListEntry *pEntry) { if(!pEntry) { return false; } if(pEntry->strProto != L"MetaContacts") { if(pEntry->iStatus == ID_STATUS_OFFLINE && CConfig::GetBoolSetting(CLIST_HIDEOFFLINE)) { return false; } } else { if(pEntry->iStatus == ID_STATUS_OFFLINE) { int dwNumContacts = db_mc_getSubCount(pEntry->hHandle); for(int i = 0; i < dwNumContacts; i++) { MCONTACT hSubContact = db_mc_getSub(pEntry->hHandle,i); char *szProto = GetContactProto(hSubContact); if(db_get_w(hSubContact,szProto,"Status",ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) return true; } } } if(pEntry->iMessages > 0) return true; if(CConfig::GetBoolSetting(CLIST_USEIGNORE)) { if(db_get_b(pEntry->hHandle,"CList","Hidden",0)) return false; if(db_mc_isSub(pEntry->hHandle)) { MCONTACT hMetaContact = db_mc_getMeta(pEntry->hHandle); if(db_get_b(hMetaContact,"CList","Hidden",0)) return false; } } if(!CConfig::GetProtocolContactlistFilter(pEntry->strProto)) return false; if(CConfig::GetBoolSetting(CLIST_HIDEOFFLINE) && pEntry->iStatus == ID_STATUS_OFFLINE) return false; return true; } //************************************************************************ // removes a contact from the list //************************************************************************ void CContactList::RemoveContact(MCONTACT hContact) { CListContainer *pGroup = nullptr; ///tstring strGroup = GetContactGroupPath(hContact); CListEntry *pContactEntry = FindContact(hContact); if(!pContactEntry) { return; } if( !CConfig::GetBoolSetting(CLIST_USEGROUPS)){ if(pContactEntry->GetType() == ITEM) RemoveItem(((CListItem*)pContactEntry)->GetItemData()); else RemoveGroup(((CListContainer*)pContactEntry)->GetGroupData()); } else { pGroup = (CListContainer*)pContactEntry->GetParent(); ASSERT(pGroup != nullptr); CContactListEntry *pEntry = GetContactData(pContactEntry); if(!pEntry) { return; } // Update the contacts group if it has one if(pGroup->GetType() != ROOT) { if(!db_mc_isSub(hContact) && pEntry->iStatus != ID_STATUS_OFFLINE) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,-1); if(!db_mc_isSub(hContact) && pEntry->iMessages > 0) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,0,-pEntry->iMessages); } if(pContactEntry->GetType() == ITEM) pGroup->RemoveItem(((CListItem*)pContactEntry)->GetItemData()); else { pGroup->RemoveGroup(((CListContainer*)pContactEntry)->GetGroupData()); // Reenumerate all subcontacts (maybe MetaContacts was disabled int numContacts = db_mc_getSubCount(hContact); for(int i=0;i *pParent = (CListContainer*)pGroup->GetParent(); while(pParent != nullptr && pGroup->IsEmpty() && !pGroup->GetGroupData()->hMetaContact) { pParent->RemoveGroup(pGroup->GetGroupData()); pGroup = pParent; pParent = (CListContainer*)pGroup->GetParent(); } } } //************************************************************************ // get group by string //************************************************************************ CListContainer *CContactList::GetGroupByString(tstring strGroup) { tstring strParse = strGroup; CListContainer *pGroup = (CListContainer*)this; tstring::size_type pos; while((pos = strParse.find('\\')) != tstring::npos ) { strGroup = strParse.substr(0,pos); strParse = strParse.substr(pos+1); pGroup = FindGroupInGroup(strGroup,pGroup); if(pGroup == nullptr) return nullptr; } pGroup = FindGroupInGroup(strParse,pGroup); return pGroup; } //************************************************************************ // Adds a group //************************************************************************ CListContainer *CContactList::AddGroupByString(tstring strGroup) { tstring strParse = strGroup; tstring strPath = L""; CListContainer *pGroup = (CListContainer*)this; CListContainer *pGroup2 = nullptr; tstring::size_type pos; while((pos = strParse.find('\\')) != tstring::npos ) { strGroup = strParse.substr(0,pos); strParse = strParse.substr(pos+1); strPath += strGroup; if(pGroup2 = FindGroupInGroup(strGroup,pGroup)) pGroup = pGroup2; else { CContactListGroup *pGroupObject = GetGroupObjectByPath(strPath); if(!pGroupObject) pGroupObject = CreateGroupObjectByPath(strPath); pGroup2 = pGroup->InsertGroup(pGroup->begin(),pGroupObject); pGroup->sort(CContactList::CompareEntries); pGroup = pGroup2; } ASSERT(pGroup != nullptr); strPath += L"\\"; } strPath += strParse; if(pGroup2 = FindGroupInGroup(strParse,pGroup)) return pGroup2; else { CContactListGroup *pGroupObject = GetGroupObjectByPath(strPath); if(!pGroupObject) pGroupObject = CreateGroupObjectByPath(strPath); pGroup2 = pGroup->InsertGroup(pGroup->begin(),pGroupObject); pGroup->sort(CContactList::CompareEntries); return pGroup2; } } //************************************************************************ // returns the contact's status //************************************************************************ int CContactList::GetContactStatus(MCONTACT hContact) { CListEntry *pContactEntry = FindContact(hContact); if(!pContactEntry) return ID_STATUS_OFFLINE; CContactListEntry *pEntry = GetContactData(pContactEntry); if(!pEntry) { return ID_STATUS_OFFLINE; } return pEntry->iStatus; } //************************************************************************ // Called to delete the specified item //************************************************************************ void CContactList::DeleteItem(CContactListEntry *pEntry) { delete pEntry; } //************************************************************************ // Called to delete the specified group //************************************************************************ void CContactList::DeleteGroup(CContactListGroup*) { } //************************************************************************ // Called to draw the specified entry //************************************************************************ void CContactList::DrawEntry(CLCDGfx *pGfx,CContactListEntry *pEntry,bool bSelected) { if(pEntry == nullptr) return; tstring strText = L""; if(pEntry->iMessages > 0) { strText = L"["; strText += pEntry->strMessages; strText += L"]"; } strText += pEntry->strName; if(CConfig::GetBoolSetting(CLIST_SHOWPROTO) && !CConfig::GetBoolSetting(CLIST_COLUMNS)) { int w = pGfx->GetClipWidth(); pGfx->DrawText(w-w*0.3,0,w*0.3,pEntry->strProto); pGfx->DrawText(8,0,w*0.7-8,strText); } else pGfx->DrawText(8,0,pGfx->GetClipWidth()-8,strText); pGfx->DrawBitmap(1,ceil((pGfx->GetClipHeight()-5)/2.0f),5,5,CAppletManager::GetInstance()->GetStatusBitmap(pEntry->iStatus)); if(bSelected && (GetTickCount() - m_dwLastScroll < 1000 || !CConfig::GetBoolSetting(CLIST_SELECTION))) { RECT invert = { 0,0,GetWidth(),m_iFontHeight}; InvertRect(pGfx->GetHDC(), &invert); } } //************************************************************************ // Called to draw the specified group //************************************************************************ void CContactList::DrawGroup(CLCDGfx *pGfx,CContactListGroup *pGroup,bool bOpen,bool bSelected) { if(pGroup == nullptr || ( pGroup->hMetaContact && pGroup->pContactListEntry == nullptr)) { return; } char num[10],num2[10]; itoa(pGroup->iMembers,num,10); itoa(pGroup->iOnline,num2,10); int iEvents = pGroup->iEvents; tstring strText = pGroup->strName; if(!pGroup->hMetaContact) { if(CConfig::GetBoolSetting(CLIST_COUNTERS)) strText = strText + L" (" + toTstring(num2).c_str()+ L"/" + toTstring(num).c_str() + L")"; } else { pGfx->DrawBitmap(8,ceil((pGfx->GetClipHeight()-5)/2.0f),5,5,CAppletManager::GetInstance()->GetStatusBitmap(pGroup->pContactListEntry->iStatus)); iEvents += pGroup->pContactListEntry->iMessages; } if(iEvents != 0) { itoa(iEvents,num,10); strText = L"[" + toTstring(num) + L"]" + strText; } int iOffset = !pGroup->hMetaContact?m_iFontHeight*0.8:m_iFontHeight*0.8+8; pGfx->DrawText(iOffset,0,pGfx->GetClipWidth()-iOffset,strText.c_str()); if(bOpen) pGfx->DrawText(1,0,L"-"); else pGfx->DrawText(1,0,L"+"); if(bSelected && (GetTickCount() - m_dwLastScroll < 1000|| !CConfig::GetBoolSetting(CLIST_SELECTION))) { RECT invert2 = { 0,0,GetWidth(),m_iFontHeight}; InvertRect(pGfx->GetHDC(),&invert2); } } //************************************************************************ // Called to compare two entrys //************************************************************************ bool CContactList::CompareEntries(CListEntry *pLeft,CListEntry *pRight) { CContactListEntry *pLeftEntry = GetContactData(pLeft); CContactListEntry *pRightEntry = GetContactData(pRight); if(pLeftEntry && pRightEntry) { int iLeftMessages = pLeftEntry->iMessages; int iRightMessages = pRightEntry->iMessages; if(pLeft->GetType() == CONTAINER) iLeftMessages += ((CListContainer*)pLeft)->GetGroupData()->iEvents; if(pRight->GetType() == CONTAINER) iRightMessages += ((CListContainer*)pRight)->GetGroupData()->iEvents; if (!iRightMessages && iLeftMessages) return true; else if (iRightMessages && !iLeftMessages) return false; else if (iLeftMessages && iRightMessages) return (iLeftMessages > iRightMessages); else if(pLeftEntry->iStatus != pRightEntry->iStatus) return (aiStatusPriority[pLeftEntry->iStatus - ID_STATUS_OFFLINE] > aiStatusPriority[pRightEntry->iStatus - ID_STATUS_OFFLINE]); else return mir_wstrcmpi(pLeftEntry->strName.c_str(),pRightEntry->strName.c_str())<0; } else if(pLeft->GetType() == ITEM && pRight->GetType() == CONTAINER) return false; else if(pLeft->GetType() == CONTAINER && pRight->GetType() == ITEM) return true; else if(pLeft->GetType() == CONTAINER && pRight->GetType() == CONTAINER) { CContactListGroup *pGroup1 = ((CListContainer*)pLeft)->GetGroupData(); CContactListGroup *pGroup2 = ((CListContainer*)pRight)->GetGroupData(); if (!pGroup2->iEvents && pGroup1->iEvents) return true; else if (pGroup2->iEvents && !pGroup1->iEvents) return false; else if (pGroup1->iEvents && pGroup2->iEvents) return (pGroup1->iEvents > pGroup2->iEvents); else return mir_wstrcmpi(pGroup1->strName.c_str(),pGroup2->strName.c_str())<0; } return false; } //************************************************************************ // refreshes the list //************************************************************************ void CContactList::RefreshList() { if((db_get_b(NULL,"MetaContacts","Enabled",1) != 0) != m_bUseMetaContacts || CConfig::GetBoolSetting(CLIST_USEGROUPS) != m_bUseGroups) { InitializeGroupObjects(); Clear(); } m_bUseGroups = CConfig::GetBoolSetting(CLIST_USEGROUPS); m_bUseMetaContacts = db_get_b(NULL,"MetaContacts","Enabled",1) != 0; CListEntry *pContactEntry = nullptr; MCONTACT hContact = db_find_first(); while(hContact != NULL) { pContactEntry = FindContact(hContact); if(!pContactEntry) AddContact(hContact); else if(pContactEntry && !IsVisible(GetContactData(pContactEntry))) RemoveContact(hContact); hContact = db_find_next(hContact); } } //************************************************************************ // set the contactlists font //************************************************************************ bool CContactList::SetFont(LOGFONT &lf) { if(!CLCDList::SetFont(lf)) return false; SetEntryHeight(m_iFontHeight<5?5:m_iFontHeight); return true; } //************************************************************************ // called when the configuration has changed //************************************************************************ void CContactList::OnConfigChanged() { RefreshList(); } //************************************************************************ // returns the entry for the specified group name //************************************************************************ CListContainer *CContactList::FindGroup(tstring strGroup) { return FindGroupInGroup(strGroup,(CListContainer*)this); } //************************************************************************ // returns the entry for the specified group name //************************************************************************ CListContainer *CContactList::FindGroupInGroup(tstring strGroup,CListContainer *pGroup) { CListContainer::iterator iter = pGroup->begin(); CListContainer *pItem = nullptr; while(!pGroup->empty() && iter != pGroup->end()) { if((*iter)->GetType() == CONTAINER) { pItem = (CListContainer*)*iter; if(pItem->GetGroupData()->strName == strGroup) return pItem; //pItem = FindGroupInGroup(strGroup,(CListContainer *)*iter); //if(pItem) // return pItem; } iter++; } return nullptr; } //************************************************************************ // returns the entry for the specified handle //************************************************************************ CListEntry *CContactList::FindContact(MCONTACT hContact) { if(hContact == NULL) return nullptr; return FindContactInGroup(hContact,(CListContainer*)this); } //************************************************************************ // returns the entry for the specified handle //************************************************************************ CListEntry *CContactList::FindContactInGroup(MCONTACT hContact,CListContainer *pGroup) { if(hContact == NULL) return nullptr; CListItem *pItemEntry = nullptr; CListEntry *pEntry = nullptr; CListContainer *pGroupEntry = nullptr; CListContainer::iterator iter = pGroup->begin(); while(iter != pGroup->end()) { if((*iter)->GetType() == ITEM) { pItemEntry = (CListItem*)*iter; if(pItemEntry->GetItemData()->hHandle == hContact) return *iter; } else { pGroupEntry = (CListContainer *)*iter; if(pGroupEntry->GetGroupData()->hMetaContact == hContact) return *iter; pEntry = FindContactInGroup(hContact,pGroupEntry); if(pEntry) return pEntry; } iter++; } return nullptr; } //************************************************************************ // called when a contacts hidden flag has changed //************************************************************************ void CContactList::OnContactHiddenChanged(MCONTACT hContact, bool bHidden) { CListEntry *pContactEntry = FindContact(hContact); if(!pContactEntry && !bHidden) { AddContact(hContact); return; } else if(!pContactEntry) return; if(!IsVisible(GetContactData(pContactEntry))) RemoveContact(hContact); } //************************************************************************ // called when a contacts nickname has changed //************************************************************************ void CContactList::OnContactNickChanged(MCONTACT hContact, tstring strNick) { CListEntry *pContactEntry = FindContact(hContact); if(!pContactEntry) return; if(pContactEntry->GetType() == CONTAINER) { CListContainer *pGroup = ((CListContainer*)pContactEntry); pGroup->GetGroupData()->strName = strNick; tstring strPath = GetContactGroupPath(hContact); pGroup->GetGroupData()->strPath = strPath + (strPath.empty()?L"":L"\\") + strNick; } CContactListEntry* pEntry = GetContactData(pContactEntry); if(!pEntry) { return; } pEntry->strName = strNick; ((CListContainer*)pContactEntry->GetParent())->sort(CContactList::CompareEntries); } //************************************************************************ // called when a contacts status has changed //************************************************************************ void CContactList::OnStatusChange(MCONTACT hContact,int iStatus) { // find the entry in the list CListEntry *pContactEntry = FindContact(hContact); if(!pContactEntry) { AddContact(hContact); return; } CContactListEntry *pItemData = GetContactData(pContactEntry); if(!pItemData) { return; } // get the old status int iOldStatus = pItemData->iStatus; // Update the list entry wchar_t *szStatus = pcli->pfnGetStatusModeDescription(iStatus, 0); if(szStatus != nullptr) pItemData->strStatus =toTstring(szStatus); pItemData->iStatus = iStatus; // update the contacts group CListContainer* pGroup = ((CListContainer*)pContactEntry->GetParent()); if(pGroup->GetType() != ROOT) { if(!db_mc_isSub(hContact) && iStatus == ID_STATUS_OFFLINE && iOldStatus != ID_STATUS_OFFLINE) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,-1); else if(!db_mc_isSub(hContact) && iStatus != ID_STATUS_OFFLINE && iOldStatus == ID_STATUS_OFFLINE) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,1); } // check if the entry is still visible if(!IsVisible(pItemData)) { RemoveContact(hContact); return; } // sort the list pGroup->sort(CContactList::CompareEntries); } //************************************************************************ // called when the contacts message count has changed //************************************************************************ void CContactList::OnMessageCountChanged(MCONTACT hContact) { CListEntry *pContactEntry = FindContact(hContact); if(!pContactEntry) { AddContact(hContact); return; } UpdateMessageCounter(pContactEntry); if(!IsVisible(GetContactData(pContactEntry))) RemoveContact(hContact); ((CListContainer*)pContactEntry->GetParent())->sort(CContactList::CompareEntries); } //************************************************************************ // called when a contact has been added //************************************************************************ void CContactList::OnContactAdded(MCONTACT hContact) { // Update the list AddContact(hContact); // increase the membercount of the new group, and check if it needs to be created tstring strGroup = GetContactGroupPath(hContact); if(!strGroup.empty()) { CContactListGroup *pGroup = GetGroupObjectByPath(strGroup); if(!pGroup) pGroup = CreateGroupObjectByPath(strGroup); if(!db_mc_isSub(hContact)) ChangeGroupObjectCounters(strGroup,1); } } //************************************************************************ // called when a contact has been deleted //************************************************************************ void CContactList::OnContactDeleted(MCONTACT hContact) { // Update the list RemoveContact(hContact); // Decrease the membercount of the old group, and check if it needs to be deleted tstring strGroup = GetContactGroupPath(hContact); if(!strGroup.empty()) { CContactListGroup *pGroup = GetGroupObjectByPath(strGroup); if(!db_mc_isSub(hContact)) ChangeGroupObjectCounters(strGroup,-1); if(pGroup && pGroup->iMembers <= 0) DeleteGroupObjectByPath(pGroup->strPath); } } //************************************************************************ // called when a contacts group has changed //************************************************************************ void CContactList::OnContactGroupChanged(MCONTACT hContact,tstring strGroup) { bool bMetaContact = false; strGroup = GetContactGroupPath(hContact); // Decrease the membercount of the old group CListEntry *pContactEntry = FindContact(hContact); CContactListGroup *pOldGroup = nullptr; // If the contactentry was not found, try adding the contact (metacontacts fix) if(!pContactEntry) { return; } if(pContactEntry->GetType() == CONTAINER) bMetaContact = true; CListContainer* pContainer = ((CListContainer*)pContactEntry->GetParent()); // Update the contacts group if it has one if(pContainer->GetType() != ROOT) { pOldGroup = pContainer->GetGroupData(); if(!db_mc_isSub(hContact)) ChangeGroupObjectCounters(pOldGroup->strPath,-1); } // increase the membercount of the new group, and check if it needs to be created if(!strGroup.empty()) { CContactListGroup *pGroup = GetGroupObjectByPath(strGroup); if(!pGroup) pGroup = CreateGroupObjectByPath(strGroup); if(!db_mc_isSub(hContact)) ChangeGroupObjectCounters(strGroup,1); } // move subcontacts if(pContactEntry->GetType() == CONTAINER) { CListContainer *pGroup = (CListContainer*)pContactEntry; CListContainer::iterator iter = pGroup->begin(); while(!pGroup->empty()) { iter = pGroup->begin(); if((*iter)->GetType() == ITEM) OnContactGroupChanged(GetContactData(*iter)->hHandle,L""); Sleep(1); } } // update the list RemoveContact(hContact); AddContact(hContact); if(bMetaContact) { tstring strName = CAppletManager::GetContactDisplayname(hContact); tstring strPath = L""; if(pOldGroup) strPath += pOldGroup->strPath; strPath += (strPath.empty()?L"":L"\\") + strName; DeleteGroupObjectByPath(strPath); } // check if the old group ( if it exists ) needs to be deleted if(pOldGroup && !pOldGroup->hMetaContact && pOldGroup->iMembers <= 0 && pOldGroup->iGroups <= 0) DeleteGroupObjectByPath(pOldGroup->strPath); } //************************************************************************ // updates the message count for the specified contact //************************************************************************ void CContactList::UpdateMessageCounter(CListEntry *pContactEntry) { CContactListEntry *pEntry = GetContactData(pContactEntry); if(!pEntry) { return; } int iOldMessages = pEntry->iMessages; bool bSort = false; MEVENT hEvent = db_event_firstUnread(pEntry->hHandle); if(CAppletManager::IsMessageWindowOpen(pEntry->hHandle) || (hEvent == NULL && pEntry->iMessages > 0)) { pEntry->iMessages = 0; bSort = true; } else { pEntry->iMessages = 0; MEVENT hLastEvent = db_event_last(pEntry->hHandle); while(hLastEvent != NULL && hEvent != NULL) { pEntry->iMessages++; if(hLastEvent == hEvent) break; hLastEvent = db_event_prev(pEntry->hHandle, hLastEvent); } } if(pEntry->iMessages >= 100) pEntry->strMessages = L">99"; else { char buffer[8]; buffer[0] = 0; itoa(pEntry->iMessages,buffer,10); pEntry->strMessages = toTstring(buffer); } CListContainer* pContainer = ((CListContainer*)pContactEntry->GetParent()); // Update the contacts group if it has one if(pContainer->GetType() != ROOT) { // Update the groups event count if(iOldMessages != 0 && pEntry->iMessages == 0) ChangeGroupObjectCounters(pContainer->GetGroupData()->strPath,0,0,-1); else if(iOldMessages == 0 && pEntry->iMessages != 0) ChangeGroupObjectCounters(pContainer->GetGroupData()->strPath,0,0,1); else return; // sort the groups parent ((CListContainer*)pContainer->GetParent())->sort(CContactList::CompareEntries); } } //************************************************************************ // changes the groups membercount //************************************************************************ void CContactList::ChangeGroupObjectCounters(tstring strGroup,int iMembers,int iOnline,int iEvents) { CContactListGroup* pGroup = GetGroupObjectByPath(strGroup); if(!pGroup) return; pGroup->iMembers += iMembers; pGroup->iOnline += iOnline; pGroup->iEvents += iEvents; tstring strParse = pGroup->strPath; tstring::size_type pos; while((pos = strParse.rfind('\\')) != tstring::npos ) { strParse = strParse.substr(0,pos); pGroup = GetGroupObjectByPath(strParse); if(!pGroup) break; pGroup->iMembers += iMembers; pGroup->iOnline += iOnline; pGroup->iEvents += iEvents; } } //************************************************************************ // uninitializes the group objects //************************************************************************ void CContactList::UninitializeGroupObjects() { vector::iterator iter = m_Groups.begin(); while(iter != m_Groups.end()) { delete (*iter); iter++; } m_Groups.clear(); } //************************************************************************ // initializes the group objects //************************************************************************ void CContactList::InitializeGroupObjects() { UninitializeGroupObjects(); for(MCONTACT hContact = db_find_first();hContact != NULL;hContact = db_find_next(hContact)) { tstring strGroup = GetContactGroupPath(hContact); char *szProto = GetContactProto(hContact); if(szProto && db_get_b(NULL,META_PROTO,"Enabled",1) && !mir_strcmpi(szProto,META_PROTO)) { tstring strName = CAppletManager::GetContactDisplayname(hContact); tstring strPath = L""; if(CConfig::GetBoolSetting(CLIST_USEGROUPS)) strPath += strGroup; strPath += (strPath.empty()?L"":L"\\") + strName; CContactListGroup *pGroup = CreateGroupObjectByPath(strPath); pGroup->hMetaContact = hContact; if(!strGroup.empty()) ChangeGroupObjectCounters(strGroup,1); } // If the contact has no group, continue else if(!strGroup.empty() && CConfig::GetBoolSetting(CLIST_USEGROUPS)) { CContactListGroup *pGroup = GetGroupObjectByPath(strGroup); // create the group if(!pGroup) CreateGroupObjectByPath(strGroup); // update it's counters if(!db_mc_isSub(hContact)) ChangeGroupObjectCounters(strGroup,1); } } } //************************************************************************ // get group object by string //************************************************************************ CContactListGroup *CContactList::GetGroupObjectByPath(tstring strPath) { ASSERT(!strPath.empty()); CContactListGroup *pGroup = nullptr; vector::iterator iter = m_Groups.begin(); for(;iter != m_Groups.end();iter++) { if((*iter)->strPath == strPath) { pGroup = *iter; break; } } return pGroup; } //************************************************************************ // creates a group object by string //************************************************************************ CContactListGroup *CContactList::CreateGroupObjectByPath(tstring strPath) { ASSERT(!strPath.empty()); CContactListGroup *pNewGroup = new CContactListGroup(); CContactListGroup *pParentGroup = nullptr; tstring strParsePath = L""; tstring strName = strPath; tstring::size_type pos; while((pos = strName.find('\\')) != tstring::npos ) { strParsePath += strName.substr(0,pos); strName = strName.substr(pos+1); pParentGroup = GetGroupObjectByPath(strParsePath); if(!pParentGroup) pParentGroup = CreateGroupObjectByPath(strParsePath); strParsePath += L"\\"; } if(pParentGroup) pParentGroup->iGroups++; pNewGroup->strName = strName; pNewGroup->strPath = strPath; pNewGroup->iMembers = 0; pNewGroup->iOnline = 0; pNewGroup->iGroups = 0; pNewGroup->iEvents = 0; pNewGroup->hMetaContact = NULL; pNewGroup->pContactListEntry = nullptr; m_Groups.push_back(pNewGroup); return pNewGroup; } //************************************************************************ // deletes a group object by string //************************************************************************ void CContactList::DeleteGroupObjectByPath(tstring strPath) { ASSERT(!strPath.empty()); for(vector::iterator iter = m_Groups.begin();iter != m_Groups.end();iter++) { if((*iter)->strPath == strPath) { CContactListGroup *pGroup = *iter; m_Groups.erase(iter); if(pGroup->pContactListEntry) { DeleteEntry(pGroup->pContactListEntry); } delete pGroup; tstring strParse = strPath; tstring::size_type pos = strParse.rfind('\\'); if (pos != tstring::npos) { strParse = strParse.substr(0, pos); CContactListGroup *pParentGroup = GetGroupObjectByPath(strParse); if (pParentGroup) { pParentGroup->iGroups--; if (pParentGroup->iMembers <= 0 && pParentGroup->iGroups <= 0) DeleteGroupObjectByPath(strParse); } } return; } } } void CContactList::SetPosition(CListEntry *pEntry) { CLCDList::SetPosition(pEntry); } bool CContactList::ScrollUp() { m_dwLastScroll = GetTickCount(); return CLCDList::ScrollUp(); } bool CContactList::ScrollDown() { m_dwLastScroll = GetTickCount(); return CLCDList::ScrollDown(); } void CContactList::ShowSelection() { m_dwLastScroll = GetTickCount(); }