2 // This file is part of the aMule Project.
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2005-2008 Dévai Tamás ( gonosztopi@amule.org )
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "OtherFunctions.h"
33 #include <common/Format.h> // Needed for CFormat
35 #define a_brackets_b(a,b) (a + wxT(" (") + b + wxT(")"))
37 #endif /* !CLIENT_GUI */
39 #include <ec/cpp/ECTag.h> // Needed for CECTag
42 #include <ec/cpp/ECSpecialTags.h> // Needed for CEC_StatTree_Node_Tag
46 uint32_t NewStatTreeItemId()
48 static uint32_t lastid
= 0;
54 /* CStatTreeItemBase */
57 CStatTreeItemBase::CStatTreeItemBase(const CECTag
*tag
)
58 : m_label(((CEC_StatTree_Node_Tag
*)tag
)->GetDisplayString())
59 , m_uniqueid(tag
->GetTagByNameSafe(EC_TAG_STATTREE_NODEID
)->GetInt())
61 wxASSERT(tag
->GetTagName() == EC_TAG_STATTREE_NODE
);
63 for (CECTag::const_iterator it
= tag
->begin(); it
!= tag
->end(); it
++) {
64 const CECTag
*tmp
= & *it
;
65 if (tmp
->GetTagName() == EC_TAG_STATTREE_NODE
) {
66 m_children
.push_back(new CStatTreeItemBase(tmp
));
70 #endif /* CLIENT_GUI */
72 CStatTreeItemBase::~CStatTreeItemBase()
74 DeleteContents(m_children
);
78 CStatTreeItemBase
* CStatTreeItemBase::AddChild(
79 CStatTreeItemBase
* child
,
83 wxMutexLocker
lock(m_lock
);
86 child
->m_parent
= m_parent
;
88 child
->m_parent
= this;
92 if (m_flags
& stSortChildren
) {
93 std::list
<CStatTreeItemBase
*>::iterator it
= m_children
.begin();
94 while (it
!= m_children
.end() && id
< (*it
)->m_id
) {
97 m_children
.insert(it
, child
);
99 m_children
.push_back(child
);
103 #endif /* !CLIENT_GUI */
105 bool CStatTreeItemBase::HasVisibleChildren()
107 wxMutexLocker
lock(m_lock
);
109 for (std::list
<CStatTreeItemBase
*>::const_iterator it
= m_children
.begin();
110 it
!= m_children
.end(); ++it
) {
111 if ((*it
)->IsVisible()) {
119 bool CStatTreeItemBase::HasChildWithId(uint32_t id
)
121 wxMutexLocker
lock(m_lock
);
123 for (std::list
<CStatTreeItemBase
*>::const_iterator it
= m_children
.begin();
124 it
!= m_children
.end(); ++it
) {
125 if ((*it
)->m_id
== id
) {
132 CStatTreeItemBase
* CStatTreeItemBase::GetChildById(uint32_t id
)
134 wxMutexLocker
lock(m_lock
);
136 for (std::list
<CStatTreeItemBase
*>::const_iterator it
= m_children
.begin();
137 it
!= m_children
.end(); ++it
) {
138 if ((*it
)->m_id
== id
) {
145 // Note: these functions do not lock the list, because it is already locked at the time they're called
146 StatTreeItemIterator
CStatTreeItemBase::GetFirstVisibleChild(uint32_t max_children
)
148 StatTreeItemIterator it
= m_children
.begin();
149 m_visible_counter
= --max_children
;
150 while (it
!= m_children
.end() && !(*it
)->IsVisible()) ++it
;
154 void CStatTreeItemBase::GetNextVisibleChild(StatTreeItemIterator
& it
)
156 if (m_flags
& stCapChildren
) {
157 if (m_visible_counter
== 0) {
158 it
= m_children
.end();
164 if (it
!= m_children
.end()) ++it
;
165 while (it
!= m_children
.end() && !(*it
)->IsVisible()) ++it
;
169 // Anything below is only for core.
172 bool CStatTreeItemBase::ValueSort(const CStatTreeItemBase
* a
, const CStatTreeItemBase
* b
)
174 if (a
->m_id
< 0x00000100 || a
->m_id
> 0x7fffffff || b
->m_id
< 0x00000100 || b
->m_id
> 0x7fffffff) {
175 return a
->m_id
> b
->m_id
;
177 return ((CStatTreeItemCounter
*)a
)->GetValue() > ((CStatTreeItemCounter
*)b
)->GetValue();
182 wxString
CStatTreeItemBase::GetDisplayString() const
184 return wxGetTranslation(m_label
);
188 CECTag
*CStatTreeItemBase::CreateECTag(uint32_t max_children
)
191 wxMutexLocker
lock(m_lock
);
192 CECTag
*tag
= new CECTag(EC_TAG_STATTREE_NODE
, m_label
);
193 tag
->AddTag(CECTag(EC_TAG_STATTREE_NODEID
, m_uniqueid
));
195 m_visible_counter
= max_children
- 1;
196 for (std::list
<CStatTreeItemBase
*>::const_iterator it
= m_children
.begin();
197 it
!= m_children
.end(); ++it
) {
198 CECTag
*tmp
= (*it
)->CreateECTag(max_children
);
202 if (m_flags
& stCapChildren
) {
203 if (m_visible_counter
== 0) {
218 /* CStatTreeItemSimple */
221 wxString
CStatTreeItemSimple::GetDisplayString() const
223 switch (m_valuetype
) {
225 switch (m_displaymode
) {
226 case dmTime
: return CFormat(wxGetTranslation(m_label
)) % CastSecondsToHM(m_intvalue
);
227 case dmBytes
: return CFormat(wxGetTranslation(m_label
)) % CastItoXBytes(m_intvalue
);
228 default: return CFormat(wxGetTranslation(m_label
)) % m_intvalue
;
230 case vtFloat
: return CFormat(wxGetTranslation(m_label
)) % m_floatvalue
;
231 case vtString
: return CFormat(wxGetTranslation(m_label
)) % m_stringvalue
;
232 default: return wxGetTranslation(m_label
);
237 bool CStatTreeItemSimple::IsVisible() const
239 if (m_flags
& stHideIfZero
) {
240 switch (m_valuetype
) {
241 case vtInteger
: return m_intvalue
!= 0;
242 case vtFloat
: return m_floatvalue
!= 0.0;
243 case vtString
: return !m_stringvalue
.IsEmpty();
244 default: return false;
250 void CStatTreeItemSimple::AddECValues(CECTag
*tag
) const
252 switch (m_valuetype
) {
254 if (m_displaymode
== dmTime
) {
255 CECTag
value(EC_TAG_STAT_NODE_VALUE
, (uint32
)m_intvalue
);
256 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_TIME
));
259 CECTag
value(EC_TAG_STAT_NODE_VALUE
, (uint64
)m_intvalue
);
260 if (m_displaymode
== dmBytes
) {
261 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_BYTES
));
268 CECTag
value(EC_TAG_STAT_NODE_VALUE
, m_floatvalue
);
269 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_DOUBLE
));
274 CECTag
value(EC_TAG_STAT_NODE_VALUE
, m_stringvalue
);
275 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_STRING
));
285 /* CStatTreeItemCounterTmpl */
288 template<typename _Tp
>
289 wxString CStatTreeItemCounterTmpl
<_Tp
>::GetDisplayString() const
291 wxString my_label
= wxGetTranslation(m_label
);
292 // This is needed for client names, for example
293 if (my_label
== m_label
) {
294 if (m_label
.Right(4) == wxT(": %s")) {
295 my_label
= wxGetTranslation(
296 m_label
.Mid(0, m_label
.Length() - 4)) +
297 wxString(wxT(": %s"));
300 CFormat
label(my_label
);
301 if (m_displaymode
== dmBytes
) {
302 return label
% CastItoXBytes(m_value
);
304 wxString result
= CFormat(wxT("%u")) % m_value
;
305 if ((m_flags
& stShowPercent
) && m_parent
) {
306 result
+= CFormat(wxT(" (%.2f%%)")) % (((double)m_value
/ ((CStatTreeItemCounterTmpl
<_Tp
>*)m_parent
)->m_value
) * 100.0);
308 return label
% result
;
312 template wxString
CStatTreeItemCounter::GetDisplayString() const;
313 template wxString
CStatTreeItemNativeCounter::GetDisplayString() const;
317 template<typename _Tp
>
318 void CStatTreeItemCounterTmpl
<_Tp
>::AddECValues(CECTag
*tag
) const
320 CECTag
value(EC_TAG_STAT_NODE_VALUE
, (uint64
)m_value
);
321 if (m_displaymode
== dmBytes
) {
322 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_BYTES
));
324 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_ISTRING
));
325 if ((m_flags
& stShowPercent
) && m_parent
) {
326 CECTag
tmp(EC_TAG_STAT_NODE_VALUE
,
327 ((double)m_value
/ ((CStatTreeItemCounterTmpl
<_Tp
>*)m_parent
)->m_value
) * 100.0);
328 tmp
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_DOUBLE
));
335 template void CStatTreeItemCounter::AddECValues(CECTag
*tag
) const;
336 template void CStatTreeItemNativeCounter::AddECValues(CECTag
*tag
) const;
338 /* CStatTreeItemUlDlCounter */
341 wxString
CStatTreeItemUlDlCounter::GetDisplayString() const
343 return CFormat(wxGetTranslation(m_label
)) %
344 a_brackets_b(CastItoXBytes(m_value
), CastItoXBytes(m_value
+ m_totalfunc()));
348 void CStatTreeItemUlDlCounter::AddECValues(CECTag
*tag
) const
350 CECTag
value(EC_TAG_STAT_NODE_VALUE
, m_value
);
351 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_BYTES
));
352 CECTag
tmp(EC_TAG_STAT_NODE_VALUE
, m_value
+ m_totalfunc());
353 tmp
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_BYTES
));
359 /* CStatTreeItemCounterMax */
362 wxString
CStatTreeItemCounterMax::GetDisplayString() const
364 return CFormat(wxGetTranslation(m_label
)) % m_value
;
368 void CStatTreeItemCounterMax::AddECValues(CECTag
*tag
) const
370 tag
->AddTag(CECTag(EC_TAG_STAT_NODE_VALUE
, (uint64
)m_value
));
374 /* CStatTreeItemPackets */
377 wxString
CStatTreeItemPackets::GetDisplayString() const
379 return CFormat(wxGetTranslation(m_label
)) %
380 a_brackets_b(CastItoXBytes(m_bytes
), CastItoIShort(m_packets
));
384 void CStatTreeItemPackets::AddECValues(CECTag
*tag
) const
386 CECTag
value(EC_TAG_STAT_NODE_VALUE
, m_bytes
);
387 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_BYTES
));
388 CECTag
tmp(EC_TAG_STAT_NODE_VALUE
, (uint64
)m_packets
);
389 tmp
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_ISHORT
));
395 /* CStatTreeItemPacketTotals */
398 wxString
CStatTreeItemPacketTotals::GetDisplayString() const
400 uint32_t tmp_packets
= m_packets
;
401 uint64_t tmp_bytes
= m_bytes
;
402 for (std::vector
<CStatTreeItemPackets
*>::const_iterator it
= m_counters
.begin();
403 it
!= m_counters
.end(); ++it
) {
404 tmp_packets
+= (*it
)->m_packets
;
405 tmp_bytes
+= (*it
)->m_bytes
;
408 return CFormat(wxGetTranslation(m_label
)) %
409 a_brackets_b(CastItoXBytes(tmp_bytes
), CastItoIShort(tmp_packets
));
413 void CStatTreeItemPacketTotals::AddECValues(CECTag
*tag
) const
415 uint32_t tmp_packets
= m_packets
;
416 uint64_t tmp_bytes
= m_bytes
;
417 for (std::vector
<CStatTreeItemPackets
*>::const_iterator it
= m_counters
.begin();
418 it
!= m_counters
.end(); ++it
) {
419 tmp_packets
+= (*it
)->m_packets
;
420 tmp_bytes
+= (*it
)->m_bytes
;
423 CECTag
value(EC_TAG_STAT_NODE_VALUE
, tmp_bytes
);
424 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_BYTES
));
425 CECTag
tmp(EC_TAG_STAT_NODE_VALUE
, (uint64
)tmp_packets
);
426 tmp
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_ISHORT
));
432 /* CStatTreeItemTimer */
435 wxString
CStatTreeItemTimer::GetDisplayString() const
437 return CFormat(wxGetTranslation(m_label
)) %
438 CastSecondsToHM(m_value
? GetTimerSeconds() : 0);
442 void CStatTreeItemTimer::AddECValues(CECTag
*tag
) const
444 CECTag
value(EC_TAG_STAT_NODE_VALUE
,
445 m_value
? (uint32
)GetTimerSeconds() : (uint32
)0);
446 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_TIME
));
451 /* CStatTreeItemAverage */
454 wxString
CStatTreeItemAverage::GetDisplayString() const
456 if ((*m_divisor
) != 0) {
457 switch (m_displaymode
) {
459 return CFormat(wxGetTranslation(m_label
)) %
460 CastItoXBytes((*m_dividend
)/(*m_divisor
));
462 return CFormat(wxGetTranslation(m_label
)) %
463 CastSecondsToHM((*m_dividend
)/(*m_divisor
));
465 return CFormat(wxGetTranslation(m_label
)) %
466 (CFormat(wxT("%u")) % ((uint64
)(*m_dividend
)/(*m_divisor
))).GetString();
469 return CFormat(wxGetTranslation(m_label
)) % wxT("-");
474 void CStatTreeItemAverage::AddECValues(CECTag
*tag
) const
476 if ((*m_divisor
) != 0) {
477 uint64 data
= (*m_dividend
)/(*m_divisor
);
478 if (m_displaymode
== dmTime
) {
479 CECTag
value(EC_TAG_STAT_NODE_VALUE
, (uint32
)data
);
480 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_TIME
));
483 CECTag
value(EC_TAG_STAT_NODE_VALUE
, data
);
484 if (m_displaymode
== dmBytes
) {
485 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_BYTES
));
490 CECTag
value(EC_TAG_STAT_NODE_VALUE
, wxString(wxT("-")));
491 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_STRING
));
497 /* CStatTreeItemAverageSpeed */
500 wxString
CStatTreeItemAverageSpeed::GetDisplayString() const
502 uint64 time
= m_timer
->GetTimerSeconds();
504 return CFormat(wxGetTranslation(m_label
)) % CastItoSpeed((*m_counter
)/time
);
506 return CFormat(wxGetTranslation(m_label
)) % CastItoSpeed(0);
511 void CStatTreeItemAverageSpeed::AddECValues(CECTag
*tag
) const
513 uint64 time
= m_timer
->GetTimerSeconds();
515 CECTag
value(EC_TAG_STAT_NODE_VALUE
, (uint32
)((*m_counter
)/time
));
516 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_SPEED
));
519 CECTag
value(EC_TAG_STAT_NODE_VALUE
, (uint32
)0);
520 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_SPEED
));
526 /* CStatTreeItemRatio */
528 wxString
CStatTreeItemRatio::GetString() const
531 double v1
= m_counter1
->GetValue();
532 double v2
= m_counter2
->GetValue();
533 if (v1
> 0 && v2
> 0) {
535 ret
= CFormat(wxT("%.2f : 1")) % (v1
/ v2
);
537 ret
= CFormat(wxT("1 : %.2f")) % (v2
/ v1
);
540 if (m_totalfunc1
&& m_totalfunc2
) {
541 double t1
= m_totalfunc1() + v1
;
542 double t2
= m_totalfunc2() + v2
;
544 ret
+= CFormat(wxT(" (%.2f : 1)")) % (t1
/ t2
);
546 ret
+= CFormat(wxT(" (1 : %.2f)")) % (t2
/ t1
);
550 ret
= _("Not available");
556 wxString
CStatTreeItemRatio::GetDisplayString() const
558 return CFormat(wxGetTranslation(m_label
)) % GetString();
562 void CStatTreeItemRatio::AddECValues(CECTag
*tag
) const
564 CECTag
value(EC_TAG_STAT_NODE_VALUE
, GetString());
565 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_STRING
));
570 /* CStatTreeItemReconnects */
573 wxString
CStatTreeItemReconnects::GetDisplayString() const
575 return CFormat(wxGetTranslation(m_label
)) % (m_value
? m_value
- 1 : 0);
579 void CStatTreeItemReconnects::AddECValues(CECTag
*tag
) const
581 tag
->AddTag(CECTag(EC_TAG_STAT_NODE_VALUE
,
582 m_value
? (uint64
)(m_value
- 1) : (uint64
)0));
585 /* CStatTreeItemMaxConnLimitReached */
588 wxString
CStatTreeItemMaxConnLimitReached::GetDisplayString() const
591 return CFormat(wxGetTranslation(m_label
)) %
592 CFormat(wxT("%i : %s %s")) % m_count
% m_time
.FormatISODate() % m_time
.FormatISOTime();
594 return CFormat(wxGetTranslation(m_label
)) % _("Never");
599 void CStatTreeItemMaxConnLimitReached::AddECValues(CECTag
*tag
) const
603 result
= CFormat(wxT("%i : %s %s")) % m_count
% m_time
.FormatISODate() % m_time
.FormatISOTime();
605 result
= wxTRANSLATE("Never");
607 CECTag
value(EC_TAG_STAT_NODE_VALUE
, result
);
608 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_STRING
));
612 /* CStatTreeItemTotalClients */
615 wxString
CStatTreeItemTotalClients::GetDisplayString() const
617 return CFormat(wxGetTranslation(m_label
)) %
618 (m_known
->GetValue() + m_unknown
->GetValue()) %
623 void CStatTreeItemTotalClients::AddECValues(CECTag
*tag
) const
625 CECTag
value1(EC_TAG_STAT_NODE_VALUE
,
626 (uint64
)(m_known
->GetValue() + m_unknown
->GetValue()));
628 CECTag
value2(EC_TAG_STAT_NODE_VALUE
,
629 (uint64
)m_known
->GetValue());
633 #endif /* !CLIENT_GUI */
634 // File_checked_for_headers