// // This file is part of the aMule Project. // // Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org ) // Copyright (c) 2005-2011 Dévai Tamás ( gonosztopi@amule.org ) // // Any parts of this program derived from the xMule, lMule or eMule project, // or contributed by third-party developers are copyrighted by their // respective authors. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA // #include "StatTree.h" #include #include "OtherFunctions.h" #ifndef CLIENT_GUI #include // Needed for CFormat #define a_brackets_b(a,b) (a + wxT(" (") + b + wxT(")")) #endif /* !CLIENT_GUI */ #include // Needed for CECTag #ifdef CLIENT_GUI #include // Needed for CEC_StatTree_Node_Tag #else uint32_t NewStatTreeItemId() { static uint32_t lastid = 0; return ++lastid; } #endif /* CStatTreeItemBase */ #ifdef CLIENT_GUI CStatTreeItemBase::CStatTreeItemBase(const CECTag *tag) : m_label(((CEC_StatTree_Node_Tag*)tag)->GetDisplayString()) , m_uniqueid(tag->GetTagByNameSafe(EC_TAG_STATTREE_NODEID)->GetInt()) { wxASSERT(tag->GetTagName() == EC_TAG_STATTREE_NODE); for (CECTag::const_iterator it = tag->begin(); it != tag->end(); it++) { const CECTag *tmp = & *it; if (tmp->GetTagName() == EC_TAG_STATTREE_NODE) { m_children.push_back(new CStatTreeItemBase(tmp)); } } } #endif /* CLIENT_GUI */ CStatTreeItemBase::~CStatTreeItemBase() { DeleteContents(m_children); } #ifndef CLIENT_GUI CStatTreeItemBase* CStatTreeItemBase::AddChild( CStatTreeItemBase* child, uint32_t id, bool skipOneLevel) { wxMutexLocker lock(m_lock); if (skipOneLevel) { child->m_parent = m_parent; } else { child->m_parent = this; } child->m_id = id; if (m_flags & stSortChildren) { std::list::iterator it = m_children.begin(); while (it != m_children.end() && id < (*it)->m_id) { ++it; } m_children.insert(it, child); } else { m_children.push_back(child); } return child; } #endif /* !CLIENT_GUI */ bool CStatTreeItemBase::HasVisibleChildren() { wxMutexLocker lock(m_lock); for (std::list::const_iterator it = m_children.begin(); it != m_children.end(); ++it) { if ((*it)->IsVisible()) { return true; } } return false; } #ifndef CLIENT_GUI bool CStatTreeItemBase::HasChildWithId(uint32_t id) { wxMutexLocker lock(m_lock); for (std::list::const_iterator it = m_children.begin(); it != m_children.end(); ++it) { if ((*it)->m_id == id) { return true; } } return false; } CStatTreeItemBase* CStatTreeItemBase::GetChildById(uint32_t id) { wxMutexLocker lock(m_lock); for (std::list::const_iterator it = m_children.begin(); it != m_children.end(); ++it) { if ((*it)->m_id == id) { return *it; } } return NULL; } // Note: these functions do not lock the list, because it is already locked at the time they're called StatTreeItemIterator CStatTreeItemBase::GetFirstVisibleChild(uint32_t max_children) { StatTreeItemIterator it = m_children.begin(); m_visible_counter = --max_children; while (it != m_children.end() && !(*it)->IsVisible()) ++it; return it; } void CStatTreeItemBase::GetNextVisibleChild(StatTreeItemIterator& it) { if (m_flags & stCapChildren) { if (m_visible_counter == 0) { it = m_children.end(); return; } else { --m_visible_counter; } } if (it != m_children.end()) ++it; while (it != m_children.end() && !(*it)->IsVisible()) ++it; } // // Anything below is only for core. // bool CStatTreeItemBase::ValueSort(const CStatTreeItemBase* a, const CStatTreeItemBase* b) { if (a->m_id < 0x00000100 || a->m_id > 0x7fffffff || b->m_id < 0x00000100 || b->m_id > 0x7fffffff) { return a->m_id > b->m_id; } else { return ((CStatTreeItemCounter*)a)->GetValue() > ((CStatTreeItemCounter*)b)->GetValue(); } } #ifndef AMULE_DAEMON wxString CStatTreeItemBase::GetDisplayString() const { return wxGetTranslation(m_label); } #endif CECTag *CStatTreeItemBase::CreateECTag(uint32_t max_children) { if (IsVisible()) { wxMutexLocker lock(m_lock); CECTag *tag = new CECTag(EC_TAG_STATTREE_NODE, m_label); tag->AddTag(CECTag(EC_TAG_STATTREE_NODEID, m_uniqueid)); AddECValues(tag); m_visible_counter = max_children - 1; for (std::list::const_iterator it = m_children.begin(); it != m_children.end(); ++it) { CECTag *tmp = (*it)->CreateECTag(max_children); if (tmp) { tag->AddTag(*tmp); delete tmp; if (m_flags & stCapChildren) { if (m_visible_counter == 0) { break; } else { --m_visible_counter; } } } } return tag; } else { return NULL; } } /* CStatTreeItemSimple */ #ifndef AMULE_DAEMON wxString CStatTreeItemSimple::GetDisplayString() const { switch (m_valuetype) { case vtInteger: switch (m_displaymode) { case dmTime: return CFormat(wxGetTranslation(m_label)) % CastSecondsToHM(m_intvalue); case dmBytes: return CFormat(wxGetTranslation(m_label)) % CastItoXBytes(m_intvalue); default: return CFormat(wxGetTranslation(m_label)) % m_intvalue; } case vtFloat: return CFormat(wxGetTranslation(m_label)) % m_floatvalue; case vtString: return CFormat(wxGetTranslation(m_label)) % m_stringvalue; default: return wxGetTranslation(m_label); } } #endif bool CStatTreeItemSimple::IsVisible() const { if (m_flags & stHideIfZero) { switch (m_valuetype) { case vtInteger: return m_intvalue != 0; case vtFloat: return m_floatvalue != 0.0; case vtString: return !m_stringvalue.IsEmpty(); default: return false; } } return true; } void CStatTreeItemSimple::AddECValues(CECTag *tag) const { switch (m_valuetype) { case vtInteger: { if (m_displaymode == dmTime) { CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)m_intvalue); value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_TIME)); tag->AddTag(value); } else { CECTag value(EC_TAG_STAT_NODE_VALUE, (uint64)m_intvalue); if (m_displaymode == dmBytes) { value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES)); } tag->AddTag(value); } break; } case vtFloat: { CECTag value(EC_TAG_STAT_NODE_VALUE, m_floatvalue); value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_DOUBLE)); tag->AddTag(value); break; } case vtString: { CECTag value(EC_TAG_STAT_NODE_VALUE, m_stringvalue); value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING)); tag->AddTag(value); break; } default: break; } } /* CStatTreeItemCounterTmpl */ #ifndef AMULE_DAEMON template wxString CStatTreeItemCounterTmpl<_Tp>::GetDisplayString() const { wxString my_label = wxGetTranslation(m_label); // This is needed for client names, for example if (my_label == m_label) { if (m_label.Right(4) == wxT(": %s")) { my_label = wxGetTranslation( m_label.Mid(0, m_label.Length() - 4)) + wxString(wxT(": %s")); } } CFormat label(my_label); if (m_displaymode == dmBytes) { return label % CastItoXBytes(m_value); } else { wxString result = CFormat(wxT("%u")) % m_value; if ((m_flags & stShowPercent) && m_parent) { result += CFormat(wxT(" (%.2f%%)")) % (((double)m_value / ((CStatTreeItemCounterTmpl<_Tp>*)m_parent)->m_value) * 100.0); } return label % result; } } template wxString CStatTreeItemCounter::GetDisplayString() const; template wxString CStatTreeItemNativeCounter::GetDisplayString() const; #endif template void CStatTreeItemCounterTmpl<_Tp>::AddECValues(CECTag *tag) const { CECTag value(EC_TAG_STAT_NODE_VALUE, (uint64)m_value); if (m_displaymode == dmBytes) { value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES)); } else { value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_ISTRING)); if ((m_flags & stShowPercent) && m_parent) { CECTag tmp(EC_TAG_STAT_NODE_VALUE, ((double)m_value / ((CStatTreeItemCounterTmpl<_Tp>*)m_parent)->m_value) * 100.0); tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_DOUBLE)); value.AddTag(tmp); } } tag->AddTag(value); } template void CStatTreeItemCounter::AddECValues(CECTag *tag) const; template void CStatTreeItemNativeCounter::AddECValues(CECTag *tag) const; /* CStatTreeItemUlDlCounter */ #ifndef AMULE_DAEMON wxString CStatTreeItemUlDlCounter::GetDisplayString() const { return CFormat(wxGetTranslation(m_label)) % a_brackets_b(CastItoXBytes(m_value), CastItoXBytes(m_value + m_totalfunc())); } #endif void CStatTreeItemUlDlCounter::AddECValues(CECTag *tag) const { CECTag value(EC_TAG_STAT_NODE_VALUE, m_value); value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES)); CECTag tmp(EC_TAG_STAT_NODE_VALUE, m_value + m_totalfunc()); tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES)); value.AddTag(tmp); tag->AddTag(value); } /* CStatTreeItemCounterMax */ #ifndef AMULE_DAEMON wxString CStatTreeItemCounterMax::GetDisplayString() const { return CFormat(wxGetTranslation(m_label)) % m_value; } #endif void CStatTreeItemCounterMax::AddECValues(CECTag *tag) const { tag->AddTag(CECTag(EC_TAG_STAT_NODE_VALUE, (uint64)m_value)); } /* CStatTreeItemPackets */ #ifndef AMULE_DAEMON wxString CStatTreeItemPackets::GetDisplayString() const { return CFormat(wxGetTranslation(m_label)) % a_brackets_b(CastItoXBytes(m_bytes), CastItoIShort(m_packets)); } #endif void CStatTreeItemPackets::AddECValues(CECTag *tag) const { CECTag value(EC_TAG_STAT_NODE_VALUE, m_bytes); value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES)); CECTag tmp(EC_TAG_STAT_NODE_VALUE, (uint64)m_packets); tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_ISHORT)); value.AddTag(tmp); tag->AddTag(value); } /* CStatTreeItemPacketTotals */ #ifndef AMULE_DAEMON wxString CStatTreeItemPacketTotals::GetDisplayString() const { uint32_t tmp_packets = m_packets; uint64_t tmp_bytes = m_bytes; for (std::vector::const_iterator it = m_counters.begin(); it != m_counters.end(); ++it) { tmp_packets += (*it)->m_packets; tmp_bytes += (*it)->m_bytes; } return CFormat(wxGetTranslation(m_label)) % a_brackets_b(CastItoXBytes(tmp_bytes), CastItoIShort(tmp_packets)); } #endif void CStatTreeItemPacketTotals::AddECValues(CECTag *tag) const { uint32_t tmp_packets = m_packets; uint64_t tmp_bytes = m_bytes; for (std::vector::const_iterator it = m_counters.begin(); it != m_counters.end(); ++it) { tmp_packets += (*it)->m_packets; tmp_bytes += (*it)->m_bytes; } CECTag value(EC_TAG_STAT_NODE_VALUE, tmp_bytes); value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES)); CECTag tmp(EC_TAG_STAT_NODE_VALUE, (uint64)tmp_packets); tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_ISHORT)); value.AddTag(tmp); tag->AddTag(value); } /* CStatTreeItemTimer */ #ifndef AMULE_DAEMON wxString CStatTreeItemTimer::GetDisplayString() const { return CFormat(wxGetTranslation(m_label)) % CastSecondsToHM(m_value ? GetTimerSeconds() : 0); } #endif void CStatTreeItemTimer::AddECValues(CECTag *tag) const { CECTag value(EC_TAG_STAT_NODE_VALUE, m_value ? (uint32)GetTimerSeconds() : (uint32)0); value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_TIME)); tag->AddTag(value); } /* CStatTreeItemAverage */ #ifndef AMULE_DAEMON wxString CStatTreeItemAverage::GetDisplayString() const { if ((*m_divisor) != 0) { switch (m_displaymode) { case dmBytes: return CFormat(wxGetTranslation(m_label)) % CastItoXBytes((*m_dividend)/(*m_divisor)); case dmTime: return CFormat(wxGetTranslation(m_label)) % CastSecondsToHM((*m_dividend)/(*m_divisor)); default: return CFormat(wxGetTranslation(m_label)) % (CFormat(wxT("%u")) % ((uint64)(*m_dividend)/(*m_divisor))).GetString(); } } else { return CFormat(wxGetTranslation(m_label)) % wxT("-"); } } #endif void CStatTreeItemAverage::AddECValues(CECTag *tag) const { if ((*m_divisor) != 0) { uint64 data = (*m_dividend)/(*m_divisor); if (m_displaymode == dmTime) { CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)data); value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_TIME)); tag->AddTag(value); } else { CECTag value(EC_TAG_STAT_NODE_VALUE, data); if (m_displaymode == dmBytes) { value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES)); } tag->AddTag(value); } } else { CECTag value(EC_TAG_STAT_NODE_VALUE, wxString(wxT("-"))); value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING)); tag->AddTag(value); } } /* CStatTreeItemAverageSpeed */ #ifndef AMULE_DAEMON wxString CStatTreeItemAverageSpeed::GetDisplayString() const { uint64 time = m_timer->GetTimerSeconds(); if (time) { return CFormat(wxGetTranslation(m_label)) % CastItoSpeed((*m_counter)/time); } else { return CFormat(wxGetTranslation(m_label)) % CastItoSpeed(0); } } #endif void CStatTreeItemAverageSpeed::AddECValues(CECTag *tag) const { uint64 time = m_timer->GetTimerSeconds(); if (time) { CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)((*m_counter)/time)); value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_SPEED)); tag->AddTag(value); } else { CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)0); value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_SPEED)); tag->AddTag(value); } } /* CStatTreeItemRatio */ wxString CStatTreeItemRatio::GetString() const { wxString ret; double v1 = m_counter1->GetValue(); double v2 = m_counter2->GetValue(); if (v1 > 0 && v2 > 0) { if (v2 < v1) { ret = CFormat(wxT("%.2f : 1")) % (v1 / v2); } else { ret = CFormat(wxT("1 : %.2f")) % (v2 / v1); } if (m_totalfunc1 && m_totalfunc2) { double t1 = m_totalfunc1() + v1; double t2 = m_totalfunc2() + v2; if (t2 < t1) { ret += CFormat(wxT(" (%.2f : 1)")) % (t1 / t2); } else { ret += CFormat(wxT(" (1 : %.2f)")) % (t2 / t1); } } } else { ret = _("Not available"); } return ret; } #ifndef AMULE_DAEMON wxString CStatTreeItemRatio::GetDisplayString() const { return CFormat(wxGetTranslation(m_label)) % GetString(); } #endif void CStatTreeItemRatio::AddECValues(CECTag *tag) const { CECTag value(EC_TAG_STAT_NODE_VALUE, GetString()); value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING)); tag->AddTag(value); } /* CStatTreeItemReconnects */ #ifndef AMULE_DAEMON wxString CStatTreeItemReconnects::GetDisplayString() const { return CFormat(wxGetTranslation(m_label)) % (m_value ? m_value - 1 : 0); } #endif void CStatTreeItemReconnects::AddECValues(CECTag *tag) const { tag->AddTag(CECTag(EC_TAG_STAT_NODE_VALUE, m_value ? (uint64)(m_value - 1) : (uint64)0)); } /* CStatTreeItemMaxConnLimitReached */ #ifndef AMULE_DAEMON wxString CStatTreeItemMaxConnLimitReached::GetDisplayString() const { if (m_count) { return CFormat(wxGetTranslation(m_label)) % (CFormat(wxT("%i : %s %s")) % m_count % m_time.FormatISODate() % m_time.FormatISOTime()); } else { return CFormat(wxGetTranslation(m_label)) % _("Never"); } } #endif void CStatTreeItemMaxConnLimitReached::AddECValues(CECTag *tag) const { wxString result; if (m_count) { result = CFormat(wxT("%i : %s %s")) % m_count % m_time.FormatISODate() % m_time.FormatISOTime(); } else { result = wxTRANSLATE("Never"); } CECTag value(EC_TAG_STAT_NODE_VALUE, result); value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING)); tag->AddTag(value); } /* CStatTreeItemTotalClients */ #ifndef AMULE_DAEMON wxString CStatTreeItemTotalClients::GetDisplayString() const { return CFormat(wxGetTranslation(m_label)) % (m_known->GetValue() + m_unknown->GetValue()) % m_known->GetValue(); } #endif void CStatTreeItemTotalClients::AddECValues(CECTag *tag) const { CECTag value1(EC_TAG_STAT_NODE_VALUE, (uint64)(m_known->GetValue() + m_unknown->GetValue())); tag->AddTag(value1); CECTag value2(EC_TAG_STAT_NODE_VALUE, (uint64)m_known->GetValue()); tag->AddTag(value2); } #endif /* !CLIENT_GUI */ // File_checked_for_headers