Fixed problem in the CFile write_safe concept
[amule.git] / src / StatisticsDlg.cpp
blob42af87be68608e3020b2d3742461cc3ba77c231c
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net )
6 //
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
9 // respective authors.
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.
20 //
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
27 #include <cmath> // Needed for std::ceil
29 #include "ColorFrameCtrl.h" // Needed for CColorFrameCtrl
30 #include "OtherFunctions.h" // Needed for CastChild()
31 #include "OScopeCtrl.h" // Needed for COScopeCtrl
32 #include "Preferences.h" // Needed for thePrefs
33 #include "muuli_wdr.h" // Needed for statsDlg()
34 #include "StatisticsDlg.h" // Interface declarations
35 #include "Statistics.h"
38 class CTreeItemData : public wxTreeItemData
40 public:
41 explicit CTreeItemData(uint32_t uniqueid)
42 : m_uniqueid(uniqueid)
45 uint32_t GetUniqueId() const throw() { return m_uniqueid; }
46 void SetUniqueId(uint32_t val) throw() { m_uniqueid = val; }
48 private:
49 uint32_t m_uniqueid;
53 // CStatisticsDlg panel
55 const wxColour& CStatisticsDlg::getColors(unsigned num)
57 wxCHECK(num < 15, *wxBLACK);
59 return acrStat[num];
62 CStatisticsDlg::CStatisticsDlg(wxWindow* pParent, CStatistics* stats)
63 : wxPanel(pParent, -1)
65 wxSizer* content=statsDlg(this,TRUE);
66 content->Show(this,TRUE);
68 pscopeDL = CastChild( wxT("dloadScope"), COScopeCtrl );
69 pscopeDL->graph_type = GRAPH_DOWN;
70 pscopeUL = CastChild( wxT("uloadScope"), COScopeCtrl );
71 pscopeUL->graph_type = GRAPH_UP;
72 pscopeConn = CastChild( wxT("otherScope"), COScopeCtrl );
73 pscopeConn->graph_type = GRAPH_CONN;
74 stattree = CastChild( wxT("statTree"), wxTreeCtrl );
76 m_stats = stats;
81 CStatisticsDlg::~CStatisticsDlg()
86 void CStatisticsDlg::Init()
88 InitGraphs();
89 InitTree();
93 void CStatisticsDlg::InitGraphs()
95 // called after preferences get initialised
96 for (int index=0; index<=10; ++index) {
97 ApplyStatsColor(index);
100 pscopeDL->SetRanges(0.0, (float)(thePrefs::GetMaxGraphDownloadRate()+4));
101 pscopeDL->SetYUnits(_("kB/s"));
102 pscopeUL->SetRanges(0.0, (float)(thePrefs::GetMaxGraphUploadRate()+4));
103 pscopeUL->SetYUnits(_("kB/s"));
104 pscopeConn->SetRanges(0.0, (float)(thePrefs::GetStatsMax()));
105 pscopeConn->SetYUnits(wxEmptyString);
107 SetUpdatePeriod(thePrefs::GetTrafficOMeterInterval());
111 // this array is now used to store the current color settings and to define the defaults
112 wxColour CStatisticsDlg::acrStat[cntStatColors] =
114 wxColour(0,0,64), wxColour(192,192,255), wxColour(128, 255, 128), wxColour(0, 210, 0),
115 wxColour(0, 128, 0), wxColour(255, 128, 128), wxColour(200, 0, 0), wxColour(140, 0, 0),
116 wxColour(150, 150, 255), wxColour(192, 0, 192), wxColour(255, 255, 128), wxColour(0, 0, 0),
117 wxColour(128, 255, 128), wxColour(0, 210, 0), wxColour(0, 128, 0)
120 void CStatisticsDlg::ApplyStatsColor(int index)
122 static char aTrend[] = { 0,0, 2, 1, 0, 2, 1, 0, 1, 2, 0 };
123 static int aRes[] = { 0,0, IDC_C0,IDC_C0_3,IDC_C0_2, IDC_C1,IDC_C1_3,IDC_C1_2, IDC_S0,IDC_S3,IDC_S1 };
124 static COScopeCtrl** apscope[] = { NULL, NULL, &pscopeDL,&pscopeDL,&pscopeDL, &pscopeUL,&pscopeUL,&pscopeUL, &pscopeConn,&pscopeConn,&pscopeConn };
126 const wxColour& cr = acrStat[index];
128 int iRes = aRes[index];
129 int iTrend = aTrend[index];
130 COScopeCtrl** ppscope = apscope[index];
131 CColorFrameCtrl* ctrl;
132 switch (index) {
133 case 0:
134 pscopeDL->SetBackgroundColor(cr);
135 pscopeUL->SetBackgroundColor(cr);
136 pscopeConn->SetBackgroundColor(cr);
137 break;
138 case 1:
139 pscopeDL->SetGridColor(cr);
140 pscopeUL->SetGridColor(cr);
141 pscopeConn->SetGridColor(cr);
142 break;
143 case 2: case 3: case 4:
144 case 5: case 6: case 7:
145 case 8: case 9: case 10:
146 (*ppscope)->SetPlotColor(cr, iTrend);
147 if ((ctrl = CastChild(iRes, CColorFrameCtrl)) == NULL) {
148 throw wxString(CFormat(wxT("CStatisticsDlg::ApplyStatsColor: control missing (%d)\n")) % iRes);
150 ctrl->SetBackgroundBrushColour(cr);
151 ctrl->SetFrameBrushColour(*wxBLACK);
152 break;
153 default:
154 break; // ignore unknown index, like SysTray speedbar color
158 void CStatisticsDlg::UpdateStatGraphs(const uint32 peakconnections, const GraphUpdateInfo& update)
161 std::vector<float *> v1(3);
162 v1[0] = const_cast<float *>(&update.downloads[0]);
163 v1[1] = const_cast<float *>(&update.downloads[1]);
164 v1[2] = const_cast<float *>(&update.downloads[2]);
165 const std::vector<float *> &apfDown(v1);
166 std::vector<float *> v2(3);
167 v2[0] = const_cast<float *>(&update.uploads[0]);
168 v2[1] = const_cast<float *>(&update.uploads[1]);
169 v2[2] = const_cast<float *>(&update.uploads[2]);
170 const std::vector<float *> &apfUp(v2);
171 std::vector<float *> v3(3);
172 v3[0] = const_cast<float *>(&update.connections[0]);
173 v3[1] = const_cast<float *>(&update.connections[1]);
174 v3[2] = const_cast<float *>(&update.connections[2]);
175 const std::vector<float *> &apfConn(v3);
177 if (!IsShownOnScreen()) {
178 pscopeDL->DelayPoints();
179 pscopeUL->DelayPoints();
180 pscopeConn->DelayPoints();
183 static unsigned nScalePrev=1;
184 unsigned nScale = (unsigned)std::ceil((float)peakconnections / pscopeConn->GetUpperLimit());
185 if (nScale != nScalePrev) {
186 nScalePrev = nScale;
187 wxStaticText* label = CastChild( ID_ACTIVEC, wxStaticText );
189 label->SetLabel(CFormat(_("Active connections (1:%u)")) % nScale);
190 label->GetParent()->Layout();
192 pscopeConn->SetRange(0.0, (float)nScale*pscopeConn->GetUpperLimit(), 1);
195 if (!IsShownOnScreen()) {
196 return;
199 pscopeDL->AppendPoints(update.timestamp, apfDown);
200 pscopeUL->AppendPoints(update.timestamp, apfUp);
201 pscopeConn->AppendPoints(update.timestamp, apfConn);
205 void CStatisticsDlg::SetUpdatePeriod(int step)
207 // this gets called after the value in Preferences/Statistics/Update delay has been changed
208 if (step == 0) {
209 pscopeDL->Stop();
210 pscopeUL->Stop();
211 pscopeConn->Stop();
212 } else {
213 pscopeDL->Reset(step);
214 pscopeUL->Reset(step);
215 pscopeConn->Reset(step);
220 void CStatisticsDlg::ResetAveragingTime()
222 // this gets called after the value in Preferences/Statistics/time for running avg has been changed
223 pscopeDL->InvalidateGraph();
224 pscopeUL->InvalidateGraph();
228 void CStatisticsDlg::SetARange(bool SetDownload,int maxValue)
230 if ( SetDownload ) {
231 pscopeDL->SetRanges( 0, maxValue + 4 );
232 } else {
233 pscopeUL->SetRanges( 0, maxValue + 4 );
238 void CStatisticsDlg::InitTree()
240 #ifndef CLIENT_GUI
241 wxTreeItemId root =
242 #endif
243 stattree->AddRoot(theStats::GetTreeRoot()->GetDisplayString());
245 ShowStatistics(true);
247 #ifndef CLIENT_GUI
248 // Expand root
249 stattree->Expand(root);
251 // Expand main items
252 wxTreeItemIdValue cookie;
253 wxTreeItemId expand_it = stattree->GetFirstChild(root,cookie);
255 while(expand_it.IsOk()) {
256 stattree->Expand(expand_it);
257 // Next on this level
258 expand_it = stattree->GetNextSibling(expand_it);
260 #endif
263 void CStatisticsDlg::GetExpandedNodes(NodeIdSet& nodeset, const wxTreeItemId& root)
265 wxTreeItemIdValue cookie;
266 wxTreeItemId temp_it = stattree->GetFirstChild(root,cookie);
268 while (temp_it.IsOk()) {
269 if (stattree->IsExpanded(temp_it)) {
270 nodeset.insert(dynamic_cast<CTreeItemData*>(stattree->GetItemData(temp_it))->GetUniqueId());
272 if (stattree->ItemHasChildren(temp_it)) {
273 GetExpandedNodes(nodeset, temp_it);
275 temp_it = stattree->GetNextSibling(temp_it);
279 void CStatisticsDlg::ShowStatistics(bool init)
281 NodeIdSet ExpandedNodes;
283 // If it's not the first initialization of the tree, i.e. application startup
284 if (!init) {
285 GetExpandedNodes(ExpandedNodes, stattree->GetRootItem());
286 // Update sorting / get tree via EC
287 m_stats->UpdateStatsTree();
290 CStatTreeItemBase* treeRoot = theStats::GetTreeRoot();
291 wxTreeItemId root = stattree->GetRootItem();
292 FillTree(treeRoot, root, ExpandedNodes);
293 #ifdef CLIENT_GUI
294 if (!init) {
295 static bool firstUpdate = true;
296 if (firstUpdate) {
297 // Expand root
298 root = stattree->GetRootItem();
299 stattree->Expand(root);
301 // Expand main items
302 wxTreeItemIdValue cookie;
303 wxTreeItemId expand_it = stattree->GetFirstChild(root,cookie);
305 while(expand_it.IsOk()) {
306 stattree->Expand(expand_it);
307 // Next on this level
308 expand_it = stattree->GetNextSibling(expand_it);
310 firstUpdate = false;
313 #endif
317 #ifdef CLIENT_GUI
318 void CStatisticsDlg::RebuildStatTreeRemote(const CECTag * tag)
320 m_stats->RebuildStatTreeRemote(tag);
322 #endif
325 void CStatisticsDlg::FillTree(CStatTreeItemBase* statssubtree, wxTreeItemId& StatsGUITree, const NodeIdSet& expandednodes)
327 wxMutexLocker lock(statssubtree->GetLock());
329 #ifndef CLIENT_GUI
330 StatTreeItemIterator temp_it = statssubtree->GetFirstVisibleChild(thePrefs::GetMaxClientVersions());
331 #else
332 StatTreeItemIterator temp_it = statssubtree->GetFirstVisibleChild();
333 #endif
335 wxTreeItemIdValue cookie;
336 wxTreeItemId temp_GUI_it = stattree->GetFirstChild(StatsGUITree,cookie);
338 while (!statssubtree->IsAtEndOfList(temp_it)) {
339 wxTreeItemId temp_item;
340 if (temp_GUI_it.IsOk()) {
341 // There's already a child there, update it.
342 stattree->SetItemText(temp_GUI_it, (*temp_it)->GetDisplayString());
343 temp_item = temp_GUI_it;
344 uint32_t uid = (*temp_it)->GetUniqueId();
345 dynamic_cast<CTreeItemData*>(stattree->GetItemData(temp_GUI_it))->SetUniqueId(uid);
346 if (expandednodes.find(uid) != expandednodes.end()) {
347 stattree->Expand(temp_GUI_it);
348 } else {
349 stattree->Collapse(temp_GUI_it);
351 temp_GUI_it = stattree->GetNextSibling(temp_GUI_it);
352 } else {
353 // No more child on GUI, add them.
354 temp_item = stattree->AppendItem(StatsGUITree,(*temp_it)->GetDisplayString());
355 stattree->SetItemData(temp_item, new CTreeItemData((*temp_it)->GetUniqueId()));
357 // Has childs?
358 if ((*temp_it)->HasVisibleChildren()) {
359 FillTree((*temp_it), temp_item, expandednodes);
360 } else {
361 stattree->DeleteChildren(temp_item);
363 statssubtree->GetNextVisibleChild(temp_it);
366 // What if GUI has more items than tree?
367 // Delete the extra items.
368 while (temp_GUI_it.IsOk()) {
369 wxTreeItemId backup_node = stattree->GetNextSibling(temp_GUI_it);
370 stattree->DeleteChildren(temp_GUI_it);
371 stattree->Delete(temp_GUI_it);
372 temp_GUI_it = backup_node;
375 // File_checked_for_headers