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@gatech.edu>
17  */
18 
19 #include "routingstatsscene.h"
20 #include "textbubble.h"
21 #include "statisticsconstants.h"
22 #include "statsmode.h"
23 #include "animatormode.h"
24 #include "timevalue.h"
25 
26 namespace netanim
27 {
28 
29 RoutingStatsScene * pRoutingStatsScene = 0;
30 
RoutingStatsScene()31 RoutingStatsScene::RoutingStatsScene ():QGraphicsScene (0, 0, STATSSCENE_WIDTH_DEFAULT, STATSSCENE_HEIGHT_DEFAULT)
32 {
33   m_lastX = 0;
34   m_lastY = 0;
35   m_lastTime = -1;
36   m_infoWidget = addWidget (new TextBubble ("Info:", "No data available\nDid you load the XML file?"));
37   showInfoWidget ();
38 }
39 
40 RoutingStatsScene *
getInstance()41 RoutingStatsScene::getInstance ()
42 {
43   if (!pRoutingStatsScene)
44     {
45       pRoutingStatsScene = new RoutingStatsScene;
46     }
47   return pRoutingStatsScene;
48 }
49 
50 
51 void
addToProxyWidgetsMap(uint32_t nodeId,QString title,QString content)52 RoutingStatsScene::addToProxyWidgetsMap (uint32_t nodeId, QString title, QString content)
53 {
54 
55   if (m_nodeIdProxyWidgets.find (nodeId) == m_nodeIdProxyWidgets.end ())
56     {
57       TextBubble * tb = new TextBubble (title, content);
58       QFont f (tb->font ());
59       f.setPointSizeF (StatsMode::getInstance ()->getCurrentFontSize ());
60       tb->setFont (f);
61       QGraphicsProxyWidget * pw = addWidget (tb);
62 
63 
64       QFontMetrics fm (f);
65       pw->setMaximumHeight (fm.height () * tb->text ().count ("\n"));
66       pw->adjustSize ();
67       showInfoWidget (false);
68       m_nodeIdProxyWidgets[nodeId] = pw;
69       qreal newX = m_lastX + pw->widget ()->width ();
70       if (newX >= sceneRect ().right ())
71         {
72           m_lastX = 0;
73           m_lastY += pw->widget ()->height () + INTERSTATS_SPACE;
74         }
75       pw->setPos (m_lastX, m_lastY);
76 
77       m_lastX = pw->pos ().x () + pw->widget ()->width () + INTERSTATS_SPACE;
78       m_lastY = pw->pos ().y ();
79       m_bottomY = m_lastY + pw->widget ()->height ();
80       //qDebug (QString ("Last X" + QString::number (m_lastX) + " w:" + QString::number (pw->widget ()->width ())));
81       adjustRect ();
82       return;
83     }
84 
85 }
86 
87 uint32_t
getNodeCount()88 RoutingStatsScene::getNodeCount ()
89 {
90   return m_nodeIdProxyWidgets.size ();
91 }
92 
93 void
add(uint32_t nodeId,qreal time,QString rt)94 RoutingStatsScene::add (uint32_t nodeId, qreal time, QString rt)
95 {
96   if (m_nodeIdTimeValues.find (nodeId) == m_nodeIdTimeValues.end ())
97     {
98       TimeValue <QString> tv;
99       tv.add (time, rt);
100       m_nodeIdTimeValues[nodeId] = tv;
101       addToProxyWidgetsMap (nodeId, "", rt);
102       return;
103     }
104   TimeValue <QString> & tv = m_nodeIdTimeValues[nodeId];
105   tv.add (time, rt);
106 
107 }
108 
109 void
addRp(uint32_t nodeId,QString destination,qreal time,RoutePathElementsVector_t elements)110 RoutingStatsScene::addRp (uint32_t nodeId, QString destination, qreal time, RoutePathElementsVector_t elements)
111 {
112   NodeIdDest_t nd = { nodeId, destination };
113   if (m_rps.find (nd) == m_rps.end ())
114     {
115       TimeValue <RoutePathElementsVector_t> tv;
116       tv.add (time, elements);
117       m_rps[nd] = tv;
118       return;
119     }
120   TimeValue <RoutePathElementsVector_t> & tv = m_rps[nd];
121   tv.add (time, elements);
122 }
123 
124 RoutePathVector_t
getRoutePaths(qreal currentTime)125 RoutingStatsScene::getRoutePaths (qreal currentTime)
126 {
127   RoutePathVector_t routePaths;
128   for (NodeIdDestRPMap_t::const_iterator i = m_rps.begin ();
129       i != m_rps.end ();
130       ++i)
131     {
132       NodeIdDest_t nd = i->first;
133       TimeValue <RoutePathElementsVector_t> & v = m_rps[nd];
134       v.setCurrentTime (currentTime);
135       RoutePath_t rp = { nd, v.getCurrent () };
136       routePaths.push_back (rp);
137     }
138   return routePaths;
139 }
140 
141 void
clearProxyWidgetsMap()142 RoutingStatsScene::clearProxyWidgetsMap ()
143 {
144   showInfoWidget ();
145   for (NodeIdProxyWidgetMap_t::const_iterator i = m_nodeIdProxyWidgets.begin ();
146       i != m_nodeIdProxyWidgets.end ();
147       ++i)
148     {
149 
150       removeItem (i->second);
151       delete (i->second);
152 
153     }
154   m_nodeIdProxyWidgets.clear ();
155 }
156 
157 void
adjustRect()158 RoutingStatsScene::adjustRect ()
159 {
160   QRectF currentRect = sceneRect ();
161   QRectF newRect = QRectF (currentRect.topLeft (), QPointF (currentRect.bottomRight ().x (), m_bottomY));
162   setSceneRect (newRect);
163 }
164 
165 void
test()166 RoutingStatsScene::test ()
167 {
168   for (uint32_t i=0; i < 100; ++i)
169     {
170       //qDebug (sceneRect (), "Scene Rect");
171       //add (i, "10.1.1.1~00:00:00:00:00:06", i+1, "10.1.1.1~00:00:00:00:00:06", "lp.linkDescription");
172     }
173 }
174 
175 void
systemReset()176 RoutingStatsScene::systemReset ()
177 {
178   m_lastX = 0;
179   m_lastY = 0;
180   m_bottomY = 0;
181   clearProxyWidgetsMap ();
182   clearNodeIdTimeValues ();
183 }
184 
185 void
clearNodeIdTimeValues()186 RoutingStatsScene::clearNodeIdTimeValues ()
187 {
188   m_nodeIdTimeValues.clear ();
189 }
190 
191 void
showInfoWidget(bool show)192 RoutingStatsScene::showInfoWidget (bool show)
193 {
194   m_infoWidget->setVisible (show);
195   m_infoWidget->setPos (sceneRect ().width ()/2, sceneRect ().height ()/2);
196 }
197 
198 void
updateContent(uint32_t nodeId,QGraphicsProxyWidget * pw)199 RoutingStatsScene::updateContent (uint32_t nodeId, QGraphicsProxyWidget *pw)
200 {
201   //qDebug ("Updating for :" + QString::number (nodeId));
202   TimeValue <QString> & v = m_nodeIdTimeValues[nodeId];
203   v.setCurrentTime (StatsMode::getInstance ()->getCurrentTime ());
204   TextBubble * tb = ( (TextBubble *)pw->widget ());
205   QFont f (tb->font ());
206   f.setPointSizeF (StatsMode::getInstance ()->getCurrentFontSize ());
207   tb->setFont (f);
208   QFontMetrics fm (f);
209   pw->setMaximumHeight (fm.height () * tb->text ().count ("\n"));
210   pw->adjustSize ();
211   tb->setText (v.getCurrent ());
212 }
213 
214 void
reloadContent(bool force)215 RoutingStatsScene::reloadContent (bool force)
216 {
217   if (m_nodeIdProxyWidgets.empty ())
218     {
219       return;
220     }
221 
222   m_lastX = 0;
223   m_lastY = 0;
224   m_bottomY = 0;
225   qreal currentTime = StatsMode::getInstance ()->getCurrentTime ();
226 
227   qreal currentMaxHeight = 0;
228   for (NodeIdProxyWidgetMap_t::const_iterator i = m_nodeIdProxyWidgets.begin ();
229       i != m_nodeIdProxyWidgets.end ();
230       ++i)
231     {
232       QGraphicsProxyWidget * pw = i->second;
233 
234       if ((force) || (!m_lastTime) || (m_lastTime != currentTime))
235         {
236           updateContent (i->first, pw);
237         }
238 
239 
240       bool nodeIsActive = StatsMode::getInstance ()->isNodeActive (i->first);
241       pw->setVisible (nodeIsActive);
242       if (nodeIsActive)
243         {
244           qreal newX = m_lastX + pw->size ().width ();
245           currentMaxHeight = qMax (currentMaxHeight, pw->size ().height ());
246           if (newX >= sceneRect ().right ())
247             {
248               m_lastX = 0;
249               m_lastY += currentMaxHeight + INTERSTATS_SPACE;
250               currentMaxHeight = 0;
251             }
252           pw->setPos (m_lastX, m_lastY);
253           m_lastX = pw->pos ().x () + pw->size ().width () + INTERSTATS_SPACE;
254           m_lastY = pw->pos ().y ();
255           m_bottomY = m_lastY + currentMaxHeight;
256           adjustRect ();
257         }
258 
259     }
260 
261   m_lastTime = currentTime;
262 
263 
264 }
265 
266 } // namespace netanim
267