1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation;
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 *
16 * Author: John Abraham <john.abraham.in@gmail.com>
17 */
18
19 #include "countertablesscene.h"
20 #include "statisticsconstants.h"
21 #include "animnode.h"
22 #include "animatormode.h"
23 #include "statsview.h"
24
25 namespace netanim
26 {
27
28 NS_LOG_COMPONENT_DEFINE ("CounterTablesScene");
29 CounterTablesScene * pCounterTablesScene = 0;
30
CounterTablesScene()31 CounterTablesScene::CounterTablesScene ():
32 QGraphicsScene (100, 0, STATSSCENE_WIDTH_DEFAULT, 6 * STATSSCENE_HEIGHT_DEFAULT),
33 m_plot (0),
34 m_plotItem (0),
35 m_showChart (true)
36 {
37 m_table = new Table ();
38 m_tableItem = new QGraphicsProxyWidget;
39 m_tableItem->setWidget (m_table);
40 addItem (m_tableItem);
41
42 }
43
44 CounterTablesScene *
getInstance()45 CounterTablesScene::getInstance ()
46 {
47 if (!pCounterTablesScene)
48 {
49 pCounterTablesScene = new CounterTablesScene;
50 }
51 return pCounterTablesScene;
52 }
53
54
55 void
setCurrentCounterName(QString name)56 CounterTablesScene::setCurrentCounterName (QString name)
57 {
58 m_currentCounterName = name;
59 reloadContent ();
60 }
61
62 uint32_t
getIndexForNode(uint32_t nodeId)63 CounterTablesScene::getIndexForNode (uint32_t nodeId)
64 {
65 int index = 0;
66 for (int i = 0; i < m_allowedNodes.count (); ++i)
67 {
68 if (i == static_cast <int> (nodeId))
69 return index;
70 ++index;
71 }
72 return index;
73 }
74
75 bool
isAllowedNode(uint32_t nodeId)76 CounterTablesScene::isAllowedNode (uint32_t nodeId)
77 {
78 for (int i = 0; i < m_allowedNodes.count (); ++i)
79 {
80 if (m_allowedNodes[i] == nodeId)
81 return true;
82 }
83 return false;
84 }
85
86 void
reloadContent(bool force)87 CounterTablesScene::reloadContent (bool force)
88 {
89 Q_UNUSED (force);
90
91 if (m_plotItem)
92 {
93 removeItem (m_plotItem);
94 delete m_plot;
95 m_plot = 0;
96 m_plotItem = 0;
97 }
98
99 typedef QVector<double> valueVector_t;
100 typedef std::map <uint32_t, valueVector_t> nodeValueMap_t;
101 nodeValueMap_t nodeTimes;
102 nodeValueMap_t nodeCounterValues;
103 qreal minCounter = uint32_t(-1);
104 qreal maxCounter = 0;
105 qreal maxTime = 0;
106
107
108 m_table->clear ();
109 QStringList headerList;
110 headerList << "Time";
111 for (QVector <uint32_t>::const_iterator i = m_allowedNodes.begin ();
112 i != m_allowedNodes.end ();
113 ++i)
114 {
115 headerList << QString::number (*i);
116 }
117 m_table->setHeaderList (headerList);
118
119 bool result = false;
120 AnimNode::CounterType_t counterType;
121 uint32_t counterId = AnimNodeMgr::getInstance ()->getCounterIdForName (m_currentCounterName, result, counterType);
122 if (!result)
123 return;
124
125
126
127 TimeValue <AnimEvent *> * events = AnimatorMode::getInstance ()->getEvents ();
128 for (TimeValue<AnimEvent *>::TimeValue_t::const_iterator i = events->Begin ();
129 i != events->End ();
130 ++i)
131 {
132 AnimEvent * ev = i->second;
133 if (ev->m_type == AnimEvent::UPDATE_NODE_COUNTER_EVENT)
134 {
135 AnimNodeCounterUpdateEvent * updateEvent = static_cast<AnimNodeCounterUpdateEvent *> (ev);
136
137 if (!isAllowedNode (updateEvent->m_nodeId))
138 continue;
139 if (updateEvent->m_counterId != counterId)
140 continue;
141 m_table->incrRowCount ();
142
143 if (nodeTimes.find (updateEvent->m_nodeId) == nodeTimes.end ())
144 {
145 valueVector_t newVec;
146 nodeTimes[updateEvent->m_nodeId] = newVec;
147 nodeCounterValues[updateEvent->m_nodeId] = newVec;
148 }
149 valueVector_t & timeVec = nodeTimes[updateEvent->m_nodeId];
150 timeVec.push_back (i->first);
151 maxTime = qMax (maxTime, i->first);
152 //NS_LOG_DEBUG ("TimeVec Count:" << timeVec.count());
153
154 m_table->addCell (0, QString::number (i->first));
155 //NS_LOG_DEBUG ("T:" << i->first);
156 if (counterType == AnimNode::DOUBLE_COUNTER)
157 {
158 qreal value = updateEvent->m_counterValue;
159 m_table->addCell (getIndexForNode (updateEvent->m_nodeId)+1, QString::number (value));
160 //NS_LOG_DEBUG ("Val:" << value);
161 valueVector_t & counterVec = nodeCounterValues[updateEvent->m_nodeId];
162 counterVec.push_back (value);
163 minCounter = qMin (minCounter, value);
164 maxCounter = qMax (maxCounter, value);
165
166
167 }
168 else if (counterType == AnimNode::UINT32_COUNTER)
169 {
170 uint32_t value = static_cast <uint32_t> (updateEvent->m_counterValue);
171 m_table->addCell (getIndexForNode (updateEvent->m_nodeId)+1, QString::number (value));
172 valueVector_t & counterVec = nodeCounterValues[updateEvent->m_nodeId];
173 counterVec.push_back (value);
174 minCounter = qMin (minCounter, (double) value);
175 maxCounter = qMax (maxCounter, (double) value);
176 }
177
178 }
179 }
180 m_tableItem->setMinimumWidth (sceneRect ().width ());
181 m_tableItem->setMinimumHeight (sceneRect ().height ());
182 m_table->adjust ();
183
184
185 if (nodeTimes.empty ())
186 return;
187
188 QVector<QCPScatterStyle::ScatterShape> shapes;
189 shapes << QCPScatterStyle::ssCross;
190 shapes << QCPScatterStyle::ssPlus;
191 shapes << QCPScatterStyle::ssCircle;
192 shapes << QCPScatterStyle::ssDisc;
193 shapes << QCPScatterStyle::ssSquare;
194 shapes << QCPScatterStyle::ssDiamond;
195 shapes << QCPScatterStyle::ssStar;
196 shapes << QCPScatterStyle::ssTriangle;
197 shapes << QCPScatterStyle::ssTriangleInverted;
198 shapes << QCPScatterStyle::ssCrossSquare;
199 shapes << QCPScatterStyle::ssPlusSquare;
200 shapes << QCPScatterStyle::ssCrossCircle;
201 shapes << QCPScatterStyle::ssPlusCircle;
202 shapes << QCPScatterStyle::ssPeace;
203 shapes << QCPScatterStyle::ssCustom;
204
205
206
207 m_plot = new QCustomPlot;
208 m_plotItem = new QGraphicsProxyWidget;
209 m_plotItem->setWidget (m_plot);
210 addItem (m_plotItem);
211
212 uint32_t chartIndex = 0;
213 QPen pen;
214 for (nodeValueMap_t::const_iterator i = nodeTimes.begin ();
215 i != nodeTimes.end ();
216 ++i)
217 {
218 m_plot->addGraph ()->setName ("Node "+ QString::number (i->first));
219 m_plot->graph (chartIndex)->setPen (pen);
220 m_plot->graph (chartIndex)->setScatterStyle (QCPScatterStyle(shapes.at (chartIndex % shapes.count ()), 10));
221 m_plot->graph (chartIndex)->setData (nodeTimes[i->first], nodeCounterValues[i->first]);
222 pen.setColor(QColor(sin(chartIndex*0.3)*100+100, sin(chartIndex*0.6+0.7)*100+100, sin(chartIndex*0.4+0.6)*100+100));
223
224 //NS_LOG_DEBUG ("NodeTime Count:" << nodeTimes[0].count());
225 //NS_LOG_DEBUG ("NodeCounter Count:" << nodeCounterValues[0].count());
226 ++chartIndex;
227 }
228 m_plot->xAxis->setLabel("Time");
229 m_plot->yAxis->setLabel(m_currentCounterName);
230 m_plot->xAxis->setRange (0, maxTime);
231 m_plot->yAxis->setRange (minCounter, maxCounter);
232 m_plot->legend->setVisible (true);
233 m_plot->legend->setFont(QFont ("Helvetica",9));
234
235
236 //m_plot->setMinimumWidth(500);
237 //m_plot->setMinimumHeight(500);
238 QRectF viewRect = StatsView::getInstance ()->viewport ()->rect ();
239 viewRect.setWidth (viewRect.width () * 0.9);
240 m_plotItem->setMinimumWidth (viewRect.width ());
241 m_plotItem->setMinimumHeight (viewRect.height ());
242 m_tableItem->setVisible (!m_showChart);
243 m_plotItem->setVisible (m_showChart);
244
245 }
246
247 void
showChart(bool show)248 CounterTablesScene::showChart (bool show)
249 {
250 m_showChart = show;
251 m_tableItem->setVisible (!m_showChart);
252 m_plotItem->setVisible (m_showChart);
253 }
254
255 void
setAllowedNodesVector(QVector<uint32_t> allowedNodes)256 CounterTablesScene::setAllowedNodesVector (QVector<uint32_t> allowedNodes)
257 {
258 m_allowedNodes = allowedNodes;
259 }
260
261 }
262