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"
34 #include <common/Format.h> // Needed for CFormat
36 #define a_brackets_b(a,b) (a + wxT(" (") + b + wxT(")"))
38 #endif /* !AMULE_DAEMON */
40 #endif /* !EC_REMOTE */
42 #include <ec/cpp/ECTag.h> // Needed for CECTag
45 #include <ec/cpp/ECSpecialTags.h> // Needed for CEC_StatTree_Node_Tag
50 uint32_t NewStatTreeItemId()
52 static uint32_t lastid
= 0;
58 /* CStatTreeItemBase */
61 CStatTreeItemBase::CStatTreeItemBase(const CECTag
*tag
)
62 : m_label(((CEC_StatTree_Node_Tag
*)tag
)->GetDisplayString())
63 , m_uniqueid(tag
->GetTagByNameSafe(EC_TAG_STATTREE_NODEID
)->GetInt())
65 wxASSERT(tag
->GetTagName() == EC_TAG_STATTREE_NODE
);
67 for (int i
= 0; i
< tag
->GetTagCount(); ++i
) {
68 const CECTag
*tmp
= tag
->GetTagByIndex(i
);
69 if (tmp
->GetTagName() == EC_TAG_STATTREE_NODE
) {
70 m_children
.push_back(new CStatTreeItemBase(tmp
));
74 #endif /* EC_REMOTE */
76 CStatTreeItemBase::~CStatTreeItemBase()
78 for (std::list
<CStatTreeItemBase
*>::iterator it
= m_children
.begin();
79 it
!= m_children
.end(); ++it
) {
86 CStatTreeItemBase
* CStatTreeItemBase::AddChild(
87 CStatTreeItemBase
* child
,
91 wxMutexLocker
lock(m_lock
);
94 child
->m_parent
= m_parent
;
96 child
->m_parent
= this;
100 if (m_flags
& stSortChildren
) {
101 std::list
<CStatTreeItemBase
*>::iterator it
= m_children
.begin();
102 while (it
!= m_children
.end() && id
< (*it
)->m_id
) {
105 m_children
.insert(it
, child
);
107 m_children
.push_back(child
);
111 #endif /* !EC_REMOTE */
113 bool CStatTreeItemBase::HasVisibleChildren()
115 wxMutexLocker
lock(m_lock
);
117 for (std::list
<CStatTreeItemBase
*>::const_iterator it
= m_children
.begin();
118 it
!= m_children
.end(); ++it
) {
119 if ((*it
)->IsVisible()) {
127 bool CStatTreeItemBase::HasChildWithId(uint32_t id
)
129 wxMutexLocker
lock(m_lock
);
131 for (std::list
<CStatTreeItemBase
*>::const_iterator it
= m_children
.begin();
132 it
!= m_children
.end(); ++it
) {
133 if ((*it
)->m_id
== id
) {
140 CStatTreeItemBase
* CStatTreeItemBase::GetChildById(uint32_t id
)
142 wxMutexLocker
lock(m_lock
);
144 for (std::list
<CStatTreeItemBase
*>::const_iterator it
= m_children
.begin();
145 it
!= m_children
.end(); ++it
) {
146 if ((*it
)->m_id
== id
) {
152 #endif /* !EC_REMOTE */
154 // Note: these functions do not lock the list, because it is already locked at the time they're called
156 StatTreeItemIterator
CStatTreeItemBase::GetFirstVisibleChild(uint32_t max_children
)
158 StatTreeItemIterator it
= m_children
.begin();
159 m_visible_counter
= --max_children
;
160 while (it
!= m_children
.end() && !(*it
)->IsVisible()) ++it
;
164 void CStatTreeItemBase::GetNextVisibleChild(StatTreeItemIterator
& it
)
166 if (m_flags
& stCapChildren
) {
167 if (m_visible_counter
== 0) {
168 it
= m_children
.end();
174 if (it
!= m_children
.end()) ++it
;
175 while (it
!= m_children
.end() && !(*it
)->IsVisible()) ++it
;
180 // Anything below is only for core.
184 bool CStatTreeItemBase::ValueSort(CStatTreeItemBase
* a
, CStatTreeItemBase
* b
)
186 if (a
->m_id
< 0x00000100 || a
->m_id
> 0x7fffffff || b
->m_id
< 0x00000100 || b
->m_id
> 0x7fffffff) {
187 return a
->m_id
> b
->m_id
;
189 return ((CStatTreeItemCounter
*)a
)->GetValue() > ((CStatTreeItemCounter
*)b
)->GetValue();
194 wxString
CStatTreeItemBase::GetDisplayString() const
196 return wxGetTranslation(m_label
);
200 CECTag
*CStatTreeItemBase::CreateECTag(uint32_t max_children
)
203 wxMutexLocker
lock(m_lock
);
204 CECTag
*tag
= new CECTag(EC_TAG_STATTREE_NODE
, m_label
);
205 tag
->AddTag(CECTag(EC_TAG_STATTREE_NODEID
, m_uniqueid
));
207 m_visible_counter
= max_children
- 1;
208 for (std::list
<CStatTreeItemBase
*>::const_iterator it
= m_children
.begin();
209 it
!= m_children
.end(); ++it
) {
210 CECTag
*tmp
= (*it
)->CreateECTag(max_children
);
214 if (m_flags
& stCapChildren
) {
215 if (m_visible_counter
== 0) {
230 /* CStatTreeItemSimple */
233 wxString
CStatTreeItemSimple::GetDisplayString() const
235 switch (m_valuetype
) {
237 switch (m_displaymode
) {
238 case dmTime
: return CFormat(wxGetTranslation(m_label
)) % CastSecondsToHM(m_intvalue
);
239 case dmBytes
: return CFormat(wxGetTranslation(m_label
)) % CastItoXBytes(m_intvalue
);
240 default: return CFormat(wxGetTranslation(m_label
)) % m_intvalue
;
242 case vtFloat
: return wxString::Format(wxGetTranslation(m_label
), m_floatvalue
);
243 case vtString
: return CFormat(wxGetTranslation(m_label
)) % m_stringvalue
;
244 default: return wxGetTranslation(m_label
);
249 bool CStatTreeItemSimple::IsVisible() const
251 if (m_flags
& stHideIfZero
) {
252 switch (m_valuetype
) {
253 case vtInteger
: return m_intvalue
!= 0;
254 case vtFloat
: return m_floatvalue
!= 0.0;
255 case vtString
: return !m_stringvalue
.IsEmpty();
256 default: return false;
262 void CStatTreeItemSimple::AddECValues(CECTag
*tag
) const
264 switch (m_valuetype
) {
266 if (m_displaymode
== dmTime
) {
267 CECTag
value(EC_TAG_STAT_NODE_VALUE
, (uint32
)m_intvalue
);
268 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_TIME
));
271 CECTag
value(EC_TAG_STAT_NODE_VALUE
, (uint64
)m_intvalue
);
272 if (m_displaymode
== dmBytes
) {
273 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_BYTES
));
280 CECTag
value(EC_TAG_STAT_NODE_VALUE
, m_floatvalue
);
281 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_DOUBLE
));
286 CECTag
value(EC_TAG_STAT_NODE_VALUE
, m_stringvalue
);
287 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_STRING
));
297 /* CStatTreeItemCounterTmpl */
300 template<typename _Tp
>
301 wxString CStatTreeItemCounterTmpl
<_Tp
>::GetDisplayString() const
303 wxString my_label
= wxGetTranslation(m_label
);
304 // This is needed for client names, for example
305 if (my_label
== m_label
) {
306 if (m_label
.Right(4) == wxT(": %s")) {
307 my_label
= wxGetTranslation(
308 m_label
.Mid(0, m_label
.Length() - 4)) +
309 wxString(wxT(": %s"));
312 CFormat
label(my_label
);
313 if (m_displaymode
== dmBytes
) {
314 return label
% CastItoXBytes(m_value
);
316 wxString result
= CFormat(wxT("%u")) % m_value
;
317 if ((m_flags
& stShowPercent
) && m_parent
) {
318 result
.append(wxString::Format(wxT(" (%.2f%%)"),
319 ((double)m_value
/ ((CStatTreeItemCounterTmpl
<_Tp
>*)m_parent
)->m_value
) * 100.0));
321 return label
% result
;
325 template wxString
CStatTreeItemCounter::GetDisplayString() const;
326 template wxString
CStatTreeItemNativeCounter::GetDisplayString() const;
330 template<typename _Tp
>
331 void CStatTreeItemCounterTmpl
<_Tp
>::AddECValues(CECTag
*tag
) const
333 CECTag
value(EC_TAG_STAT_NODE_VALUE
, (uint64
)m_value
);
334 if (m_displaymode
== dmBytes
) {
335 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_BYTES
));
337 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_ISTRING
));
338 if ((m_flags
& stShowPercent
) && m_parent
) {
339 CECTag
tmp(EC_TAG_STAT_NODE_VALUE
,
340 ((double)m_value
/ ((CStatTreeItemCounterTmpl
<_Tp
>*)m_parent
)->m_value
) * 100.0);
341 tmp
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_DOUBLE
));
348 template void CStatTreeItemCounter::AddECValues(CECTag
*tag
) const;
349 template void CStatTreeItemNativeCounter::AddECValues(CECTag
*tag
) const;
351 /* CStatTreeItemUlDlCounter */
354 wxString
CStatTreeItemUlDlCounter::GetDisplayString() const
356 return CFormat(wxGetTranslation(m_label
)) %
357 a_brackets_b(CastItoXBytes(m_value
), CastItoXBytes(m_value
+ m_totalfunc()));
361 void CStatTreeItemUlDlCounter::AddECValues(CECTag
*tag
) const
363 CECTag
value(EC_TAG_STAT_NODE_VALUE
, m_value
);
364 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_BYTES
));
365 CECTag
tmp(EC_TAG_STAT_NODE_VALUE
, m_value
+ m_totalfunc());
366 tmp
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_BYTES
));
372 /* CStatTreeItemCounterMax */
375 wxString
CStatTreeItemCounterMax::GetDisplayString() const
377 return wxString::Format(wxGetTranslation(m_label
), m_value
);
381 void CStatTreeItemCounterMax::AddECValues(CECTag
*tag
) const
383 tag
->AddTag(CECTag(EC_TAG_STAT_NODE_VALUE
, (uint64
)m_value
));
387 /* CStatTreeItemPackets */
390 wxString
CStatTreeItemPackets::GetDisplayString() const
392 return CFormat(wxGetTranslation(m_label
)) %
393 a_brackets_b(CastItoXBytes(m_bytes
), CastItoIShort(m_packets
));
397 void CStatTreeItemPackets::AddECValues(CECTag
*tag
) const
399 CECTag
value(EC_TAG_STAT_NODE_VALUE
, m_bytes
);
400 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_BYTES
));
401 CECTag
tmp(EC_TAG_STAT_NODE_VALUE
, (uint64
)m_packets
);
402 tmp
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_ISHORT
));
408 /* CStatTreeItemPacketTotals */
411 wxString
CStatTreeItemPacketTotals::GetDisplayString() const
413 uint32_t tmp_packets
= m_packets
;
414 uint64_t tmp_bytes
= m_bytes
;
415 for (std::vector
<CStatTreeItemPackets
*>::const_iterator it
= m_counters
.begin();
416 it
!= m_counters
.end(); ++it
) {
417 tmp_packets
+= (*it
)->m_packets
;
418 tmp_bytes
+= (*it
)->m_bytes
;
421 return CFormat(wxGetTranslation(m_label
)) %
422 a_brackets_b(CastItoXBytes(tmp_bytes
), CastItoIShort(tmp_packets
));
426 void CStatTreeItemPacketTotals::AddECValues(CECTag
*tag
) const
428 uint32_t tmp_packets
= m_packets
;
429 uint64_t tmp_bytes
= m_bytes
;
430 for (std::vector
<CStatTreeItemPackets
*>::const_iterator it
= m_counters
.begin();
431 it
!= m_counters
.end(); ++it
) {
432 tmp_packets
+= (*it
)->m_packets
;
433 tmp_bytes
+= (*it
)->m_bytes
;
436 CECTag
value(EC_TAG_STAT_NODE_VALUE
, tmp_bytes
);
437 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_BYTES
));
438 CECTag
tmp(EC_TAG_STAT_NODE_VALUE
, (uint64
)tmp_packets
);
439 tmp
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_ISHORT
));
445 /* CStatTreeItemTimer */
448 wxString
CStatTreeItemTimer::GetDisplayString() const
450 return CFormat(wxGetTranslation(m_label
)) %
451 CastSecondsToHM(m_value
? GetTimerSeconds() : 0);
455 void CStatTreeItemTimer::AddECValues(CECTag
*tag
) const
457 CECTag
value(EC_TAG_STAT_NODE_VALUE
,
458 m_value
? (uint32
)GetTimerSeconds() : (uint32
)0);
459 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_TIME
));
464 /* CStatTreeItemAverage */
467 wxString
CStatTreeItemAverage::GetDisplayString() const
469 if ((*m_divisor
) != 0) {
470 switch (m_displaymode
) {
472 return CFormat(wxGetTranslation(m_label
)) %
473 CastItoXBytes((*m_dividend
)/(*m_divisor
));
475 return CFormat(wxGetTranslation(m_label
)) %
476 CastSecondsToHM((*m_dividend
)/(*m_divisor
));
478 return CFormat(wxGetTranslation(m_label
)) %
479 (CFormat(wxT("%u")) % ((uint64
)(*m_dividend
)/(*m_divisor
))).GetString();
482 return CFormat(wxGetTranslation(m_label
)) % wxT("-");
487 void CStatTreeItemAverage::AddECValues(CECTag
*tag
) const
489 if ((*m_divisor
) != 0) {
490 uint64 data
= (*m_dividend
)/(*m_divisor
);
491 if (m_displaymode
== dmTime
) {
492 CECTag
value(EC_TAG_STAT_NODE_VALUE
, (uint32
)data
);
493 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_TIME
));
496 CECTag
value(EC_TAG_STAT_NODE_VALUE
, data
);
497 if (m_displaymode
== dmBytes
) {
498 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_BYTES
));
503 CECTag
value(EC_TAG_STAT_NODE_VALUE
, wxString(wxT("-")));
504 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_STRING
));
510 /* CStatTreeItemAverageSpeed */
513 wxString
CStatTreeItemAverageSpeed::GetDisplayString() const
515 uint64 time
= m_timer
->GetTimerSeconds();
517 return CFormat(wxGetTranslation(m_label
)) % CastItoSpeed((*m_counter
)/time
);
519 return CFormat(wxGetTranslation(m_label
)) % CastItoSpeed(0);
524 void CStatTreeItemAverageSpeed::AddECValues(CECTag
*tag
) const
526 uint64 time
= m_timer
->GetTimerSeconds();
528 CECTag
value(EC_TAG_STAT_NODE_VALUE
, (uint32
)((*m_counter
)/time
));
529 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_SPEED
));
532 CECTag
value(EC_TAG_STAT_NODE_VALUE
, (uint32
)0);
533 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_SPEED
));
539 /* CStatTreeItemRatio */
542 wxString
CStatTreeItemRatio::GetDisplayString() const
544 if (m_counter1
->GetValue() && m_counter2
->GetValue()) {
545 if ((*m_counter2
) < (*m_counter1
)) {
546 return CFormat(wxGetTranslation(m_label
)) %
547 wxString::Format(wxT("%.2f : 1"),
548 (float)(*m_counter1
)/(*m_counter2
));
550 return CFormat(wxGetTranslation(m_label
)) %
551 wxString::Format(wxT("1 : %.2f"),
552 (float)(*m_counter2
)/(*m_counter1
));
555 return CFormat(wxGetTranslation(m_label
)) % _("Not available");
560 void CStatTreeItemRatio::AddECValues(CECTag
*tag
) const
563 if (m_counter1
->GetValue() && m_counter2
->GetValue()) {
564 if ((*m_counter2
) < (*m_counter1
)) {
565 result
= wxString::Format(wxT("%.2f : 1"), (float)(*m_counter1
)/(*m_counter2
));
567 result
= wxString::Format(wxT("1 : %.2f"), (float)(*m_counter2
)/(*m_counter1
));
570 result
= wxTRANSLATE("Not available");
573 CECTag
value(EC_TAG_STAT_NODE_VALUE
, result
);
574 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_STRING
));
579 /* CStatTreeItemReconnects */
582 wxString
CStatTreeItemReconnects::GetDisplayString() const
584 return CFormat(wxGetTranslation(m_label
)) % (m_value
? m_value
- 1 : 0);
588 void CStatTreeItemReconnects::AddECValues(CECTag
*tag
) const
590 tag
->AddTag(CECTag(EC_TAG_STAT_NODE_VALUE
,
591 m_value
? (uint64
)(m_value
- 1) : (uint64
)0));
594 /* CStatTreeItemMaxConnLimitReached */
597 wxString
CStatTreeItemMaxConnLimitReached::GetDisplayString() const
600 return CFormat(wxGetTranslation(m_label
)) %
601 (wxString::Format(wxT("%i : "), m_count
) +
602 m_time
.FormatISODate() +
604 m_time
.FormatISOTime());
606 return CFormat(wxGetTranslation(m_label
)) % _("Never");
611 void CStatTreeItemMaxConnLimitReached::AddECValues(CECTag
*tag
) const
615 result
= wxString::Format(wxT("%i : "), m_count
) +
616 m_time
.FormatISODate() +
618 m_time
.FormatISOTime();
620 result
= wxTRANSLATE("Never");
622 CECTag
value(EC_TAG_STAT_NODE_VALUE
, result
);
623 value
.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE
, (uint8
)EC_VALUE_STRING
));
627 /* CStatTreeItemTotalClients */
630 wxString
CStatTreeItemTotalClients::GetDisplayString() const
632 return CFormat(wxGetTranslation(m_label
)) %
633 (m_known
->GetValue() + m_unknown
->GetValue()) %
638 void CStatTreeItemTotalClients::AddECValues(CECTag
*tag
) const
640 CECTag
value1(EC_TAG_STAT_NODE_VALUE
,
641 (uint64
)(m_known
->GetValue() + m_unknown
->GetValue()));
643 CECTag
value2(EC_TAG_STAT_NODE_VALUE
,
644 (uint64
)m_known
->GetValue());
648 #endif /* !EC_REMOTE */
649 // File_checked_for_headers