diff --git a/retroshare-gui/src/gui/common/RSGraphWidget.cpp b/retroshare-gui/src/gui/common/RSGraphWidget.cpp index 69a54c0f2..527e13183 100644 --- a/retroshare-gui/src/gui/common/RSGraphWidget.cpp +++ b/retroshare-gui/src/gui/common/RSGraphWidget.cpp @@ -26,6 +26,7 @@ #endif #include +#include #include #include #include @@ -39,6 +40,7 @@ RSGraphSource::RSGraphSource() _update_period_msecs = 1*1000 ; _time_orig_msecs = QDateTime::currentMSecsSinceEpoch() ; _timer = new QTimer ; + QObject::connect(_timer,SIGNAL(timeout()),this,SLOT(update())) ; } @@ -61,18 +63,31 @@ void RSGraphSource::start() _timer->start((int)(_update_period_msecs)) ; } +int RSGraphSource::n_values() const { return _points.size() ; } + void RSGraphSource::getDataPoints(int index,std::vector& pts) const { pts.clear() ; qint64 now = getTime() ; - for(std::list > >::const_iterator it = _points.begin();it!=_points.end();++it) - pts.push_back(QPointF( (now - (*it).first)/1000.0f,(*it).second[index])) ; + std::map > >::const_iterator it = _points.begin(); + + int n=0; + for(it = _points.begin();it!=_points.end() && n >::const_iterator it2=it->second.begin();it2!=it->second.end();++it2) + pts.push_back(QPointF( (now - (*it2).first)/1000.0f,(*it2).second)) ; } void RSGraphWidget::addSource(RSGraphSource *gs) { - _sources.push_back(gs) ; +if(_source != NULL) + delete _source ; + + _source = gs ; } qint64 RSGraphSource::getTime() const @@ -82,25 +97,39 @@ qint64 RSGraphSource::getTime() const void RSGraphSource::update() { - std::vector vals ; + std::map vals ; getValues(vals) ; qint64 ms = getTime() ; - _points.push_back(std::make_pair(ms,vals)) ; + for(std::map::iterator it=vals.begin();it!=vals.end();++it) + { + std::list >& lst(_points[it->first]) ; - //std::cerr << "RSGraphSource::update() Got new data for time " << ms/1000.0 << ", now=" << ms << std::endl; + lst.push_back(std::make_pair(ms,it->second)) ; - // eliminate measurements that stand beyond the time limit + for(std::list >::iterator it2=lst.begin();it2!=lst.end();) + if( ms - (*it2).first > _time_limit_msecs) + { + //std::cerr << " removing old value with time " << (*it).first/1000.0f << std::endl; + it2 = lst.erase(it2) ; + } + else + break ; + } - for(std::list > >::iterator it=_points.begin();it!=_points.end();) - if( ms - (*it).first > _time_limit_msecs) - { - //std::cerr << " removing old value with time " << (*it).first/1000.0f << std::endl; - it = _points.erase(it) ; - } + // remove empty lists + + for(std::map > >::iterator it=_points.begin();it!=_points.end();) + if(it->second.empty()) + { + std::map > >::iterator tmp(it) ; + ++tmp; + _points.erase(it) ; + it=tmp ; + } else - break ; + ++it ; } void RSGraphSource::setCollectionTimeLimit(qint64 s) { _time_limit_msecs = s ; } @@ -115,6 +144,7 @@ void RSGraphWidget::setTimeScale(float pixels_per_second) RSGraphWidget::RSGraphWidget(QWidget *parent) : QFrame(parent) { + _source =NULL; _painter = new QPainter(); _graphStyle = AreaGraph; @@ -122,20 +152,20 @@ RSGraphWidget::RSGraphWidget(QWidget *parent) _maxPoints = getNumPoints(); _maxValue = MINUSER_SCALE; + _flags = 0; _time_scale = 5.0f ; // in pixels per second. _timer = new QTimer ; QObject::connect(_timer,SIGNAL(timeout()),this,SLOT(update())) ; + _y_scale = 1.0f ; _timer->start(1000); } /** Default destructor */ RSGraphWidget::~RSGraphWidget() { - delete _painter; - - for(uint32_t i=0;i<_sources.size();++i) - delete _sources[i] ; + delete _painter; + delete _source ; } /** Gets the width of the desktop, which is the maximum number of points @@ -203,85 +233,112 @@ void RSGraphWidget::paintEvent(QPaintEvent *) void RSGraphWidget::paintData() { /* Convert the bandwidth data points to graph points */ - QVector points ; - pointsFromData(points) ; - /* Plot the bandwidth data as area graphs */ - if (_graphStyle == AreaGraph) - paintIntegral(points, RSDHT_COLOR, 0.6); + if(_source == NULL) + return ; - /* Plot the bandwidth as solid lines. If the graph style is currently an + const RSGraphSource& source(*_source) ; + _maxValue = 0.0f ; + + for(int i=0;i values ; + source.getDataPoints(i,values) ; + + QVector points ; + pointsFromData(values,points) ; + + /* Plot the bandwidth data as area graphs */ + if (_graphStyle == AreaGraph) + paintIntegral(points, RSDHT_COLOR, 0.6); + + /* Plot the bandwidth as solid lines. If the graph style is currently an * area graph, we end up outlining the integrals. */ - paintLine(points, RSDHT_COLOR); + paintLine(points, RSDHT_COLOR); + } + if(_maxValue > 0.0f) + if(_flags & RSGRAPH_FLAGS_LOG_SCALE_Y) + _y_scale = _rec.height()*0.8 / log(_maxValue) ; + else + _y_scale = _rec.height()*0.8/_maxValue ; } /** Returns a list of points on the bandwidth graph based on the supplied set * of rsdht or alldht values. */ -void RSGraphWidget::pointsFromData(QVector& points) +void RSGraphWidget::pointsFromData(const std::vector& values,QVector& points) { points.clear(); - int x = _rec.width(); - int y = _rec.height(); - qreal scale = (y - (y/10)) / _maxValue; - qreal currValue; + int x = _rec.width(); + int y = _rec.height(); - if(_sources.empty()) - return ; + float time_step = 1.0f ; // number of seconds per pixel - const RSGraphSource& source(*_sources.front()) ; + /* Translate all data points to points on the graph frame */ - float time_step = 1.0f ; // number of seconds per pixel + float last = values.back().x() ; - /* Translate all data points to points on the graph frame */ + //std::cerr << "Got " << values.size() << " values for index 0" << std::endl; - std::vector values ; + float last_px = SCALE_WIDTH ; + float last_py = 0.0f ; - source.getDataPoints(0,values) ; - float last = values.back().x() ; - - //std::cerr << "Got " << values.size() << " values for index 0" << std::endl; - - float last_px = SCALE_WIDTH ; - float last_py = 0.0f ; - - for (int i = 0; i < values.size(); ++i) - { - //std::cerr << "Value: (" << values[i].x() << " , " << values[i].y() << ")" << std::endl; - - // compute point in pixels - - float px = x - (values[i].x()-last)*_time_scale ; - float py = y - values[i].y()*scale ; - - if(px >= SCALE_WIDTH && last_px < SCALE_WIDTH) + for (uint i = 0; i < values.size(); ++i) { - float alpha = (SCALE_WIDTH - last_px)/(px - last_px) ; - float ipx = SCALE_WIDTH ; - float ipy = (1-alpha)*last_py + alpha*py ; + //std::cerr << "Value: (" << values[i].x() << " , " << values[i].y() << ")" << std::endl; - points << QPointF(ipx,y) ; - points << QPointF(ipx,ipy) ; + // compute point in pixels + + qreal px = x - (values[i].x()-last)*_time_scale ; + qreal py = y - valueToPixels(values[i].y()) ; + + _maxValue = std::max(_maxValue,values[i].y()) ; + + if(px >= SCALE_WIDTH && last_px < SCALE_WIDTH) + { + float alpha = (SCALE_WIDTH - last_px)/(px - last_px) ; + float ipx = SCALE_WIDTH ; + float ipy = (1-alpha)*last_py + alpha*py ; + + points << QPointF(ipx,y) ; + points << QPointF(ipx,ipy) ; + } + else if(i==0) + points << QPointF(px,y) ; + + last_px = px ; + last_py = py ; + + if(px < SCALE_WIDTH) + continue ; + + // remove midle point when 3 consecutive points have the same value. + + if(points.size() > 1 && points[points.size()-2].y() == points.back().y() && points.back().y() == py) + points.pop_back() ; + + points << QPointF(px,py) ; + + if(i==values.size()-1) + points << QPointF(px,y) ; } - else if(i==0) - points << QPointF(px,y) ; - last_px = px ; - last_py = py ; +} - if(px < SCALE_WIDTH) - continue ; +qreal RSGraphWidget::valueToPixels(qreal val) +{ + if(_flags & RSGRAPH_FLAGS_LOG_SCALE_Y) + return log(std::max((qreal)1.0,val))*_y_scale ; + else + return val*_y_scale ; +} - // remove midle point when 3 consecutive points have the same value. - - if(points.size() > 1 && points[points.size()-2].y() == points.back().y() && points.back().y() == py) - points.pop_back() ; - - points << QPointF(px,py) ; - - if(i==values.size()-1) - points << QPointF(px,y) ; - } +qreal RSGraphWidget::pixelsToValue(qreal val) +{ + if(_flags & RSGRAPH_FLAGS_LOG_SCALE_Y) + return exp(val / _y_scale) ; + else + return val/_y_scale ; } /** Plots an integral using the data points in points. The area will be @@ -346,7 +403,7 @@ QString RSGraphWidget::totalToStr(qreal total) /** Paints the scale on the graph. */ void RSGraphWidget::paintScale() { - qreal markStep = _maxValue * .25; + qreal markStep = valueToPixels(_maxValue) * .25; // in pixels int top = _rec.y(); int bottom = _rec.height(); qreal paintStep = (bottom - (bottom/10)) / 4; @@ -354,15 +411,22 @@ void RSGraphWidget::paintScale() /* Draw the other marks in their correctly scaled locations */ qreal scale; qreal pos; - for (int i = 1; i < 5; i++) { - pos = bottom - (i * paintStep); - scale = i * markStep; - _painter->setPen(SCALE_COLOR); - _painter->drawText(QPointF(5, pos+FONT_SIZE), - tr("%1 Users").arg(scale, 0, 'f', 0)); - _painter->setPen(GRID_COLOR); - _painter->drawLine(QPointF(SCALE_WIDTH, pos), - QPointF(_rec.width(), pos)); + + if(_source == NULL) + return ; + + QString unit_name = _source->unitName() ; + + for (int i = 1; i < 5; i++) + { + pos = bottom - (i * paintStep); + + scale = pixelsToValue(i * markStep); + + _painter->setPen(SCALE_COLOR); + _painter->drawText(QPointF(5, pos+FONT_SIZE), tr("%1 %2").arg(scale, 0, 'f', 0).arg(unit_name)); + _painter->setPen(GRID_COLOR); + _painter->drawLine(QPointF(SCALE_WIDTH, pos), QPointF(_rec.width(), pos)); } /* Draw vertical separator */ diff --git a/retroshare-gui/src/gui/common/RSGraphWidget.h b/retroshare-gui/src/gui/common/RSGraphWidget.h index 111fadd25..cbc7e1981 100644 --- a/retroshare-gui/src/gui/common/RSGraphWidget.h +++ b/retroshare-gui/src/gui/common/RSGraphWidget.h @@ -23,6 +23,8 @@ #pragma once +#include + #include #include #include @@ -57,7 +59,7 @@ public: void stop() ; void clear() ; - virtual int n_values() const =0; // Method to overload in your own class + virtual int n_values() const ; // Returns the n^th interpolated value at the given time in floating point seconds backward. virtual void getDataPoints(int index, std::vector& pts) const ; @@ -68,16 +70,21 @@ public: // Sets the time period for collecting new values. Units=milliseconds. void setCollectionTimePeriod(qint64 msecs) ; + virtual QString unitName() const =0;// overload to give your own unit name (KB/s, Users, etc) + protected slots: - // Calls the internal source for a new data points; called by the timer. + // Calls the internal source for a new data points; called by the timer. You might want to overload this + // if the collection system needs it. Otherwise, the default method will call getValues() void update() ; protected: - virtual void getValues(std::vector& values) const = 0 ; // overload this in your own class to fill in the values you want to display. + virtual void getValues(std::map& values) const = 0 ;// overload this in your own class to fill in the values you want to display. - qint64 getTime() const ; // returns time in ms since RS has started + qint64 getTime() const ; // returns time in ms since RS has started - std::list > > _points ; + // Storage of collected events. The string is any string used to represent the collected data. + + std::map > > _points ; QTimer *_timer ; @@ -122,6 +129,8 @@ class RSGraphWidget: public QFrame /** Sets the graph style used to display bandwidth data. */ void setGraphStyle(GraphStyle style) { _graphStyle = style; } + void setFlags(uint32_t flag) { _flags |= flag ; } + void resetFlags(uint32_t flag) { _flags &= ~flag ; } protected: /** Overloaded QWidget::paintEvent() */ void paintEvent(QPaintEvent *event); @@ -144,7 +153,7 @@ class RSGraphWidget: public QFrame QString totalToStr(qreal total); /** Returns a list of points on the bandwidth graph based on the supplied set * of rsdht or alldht values. */ - void pointsFromData(QVector & ) ; + void pointsFromData(const std::vector& values, QVector &points ) ; /** Paints a line with the data in points. */ void paintLine(const QVector& points, QColor color, @@ -160,8 +169,12 @@ class RSGraphWidget: public QFrame QRect _rec; /** The maximum data value plotted. */ qreal _maxValue; - /** The maximum number of points to store. */ - int _maxPoints; + /** The maximum number of points to store. */ + qreal _y_scale ; + + qreal pixelsToValue(qreal) ; + qreal valueToPixels(qreal) ; + int _maxPoints; qreal _time_scale ; // horizontal scale in pixels per sec. @@ -172,6 +185,6 @@ class RSGraphWidget: public QFrame uint32_t _flags ; QTimer *_timer ; - std::vector _sources ; + RSGraphSource *_source ; }; diff --git a/retroshare-gui/src/gui/statistics/RttStatistics.cpp b/retroshare-gui/src/gui/statistics/RttStatistics.cpp index d340ae0ce..df5d6f52a 100644 --- a/retroshare-gui/src/gui/statistics/RttStatistics.cpp +++ b/retroshare-gui/src/gui/statistics/RttStatistics.cpp @@ -168,13 +168,12 @@ class RttPlot }; RttStatistics::RttStatistics(QWidget *parent) - : RsAutoUpdatePage(2000,parent) { setupUi(this) ; m_bProcessSettings = false; - _tunnel_statistics_F->setWidget( _tst_CW = new RttStatisticsWidget() ) ; + _tunnel_statistics_F->setWidget( _tst_CW = new RttStatisticsGraph() ) ; _tunnel_statistics_F->setWidgetResizable(true); _tunnel_statistics_F->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); _tunnel_statistics_F->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); @@ -218,63 +217,78 @@ void RttStatistics::processSettings(bool bLoad) } - -void RttStatistics::updateDisplay() +void RttGraphSource::getValues(std::map& vals) { - std::map > info; + std::list idList; + rsPeers->getOnlineList(idList); - if (!rsRtt) - { - return; - } + vals.clear() ; + std::list results ; - std::list idList; - std::list::iterator it; + for(std::list::const_iterator it(idList.begin());it!=idList.end();++it) + { + rsRtt->getPongResults(*it, 1, results); - rsPeers->getOnlineList(idList); - - time_t now = time(NULL); - time_t minTS = now; - time_t maxTS = 0; - double maxRTT = 0; - - for(it = idList.begin(); it != idList.end(); it++) - { - std::list results; - std::list::iterator rit; - -#define MAX_RESULTS 60 - rsRtt->getPongResults(*it, MAX_RESULTS, results); - - for(rit = results.begin(); rit != results.end(); rit++) - { - /* only want maxRTT to include plotted bit */ - double dt = now - rit->mTS; - if (dt < MAX_DISPLAY_PERIOD) - { - if (maxRTT < rit->mRTT) - { - maxRTT = rit->mRTT; - } - } - if (minTS > rit->mTS) - { - minTS = rit->mTS; - } - if (maxTS < rit->mTS) - { - maxTS = rit->mTS; - } - } - - info[*it] = results; - } - - - _tst_CW->updateRttStatistics(info, maxRTT, minTS, maxTS); - _tst_CW->update(); + vals[(*it).toStdString()] = results.front().mRTT ; + } } +//void RttStatistics::updateDisplay() +//{ +// std::map > info; +// +// if (!rsRtt) +// { +// return; +// } +// +// std::list idList; +// std::list::iterator it; +// +// rsPeers->getOnlineList(idList); +// +// time_t now = time(NULL); +// time_t minTS = now; +// time_t maxTS = 0; +// double maxRTT = 0; +// +// for(it = idList.begin(); it != idList.end(); it++) +// { +// std::list results; +// std::list::iterator rit; +// +//#define MAX_RESULTS 60 +// rsRtt->getPongResults(*it, MAX_RESULTS, results); +// +// for(rit = results.begin(); rit != results.end(); rit++) +// { +// /* only want maxRTT to include plotted bit */ +// double dt = now - rit->mTS; +// if (dt < MAX_DISPLAY_PERIOD) +// { +// if (maxRTT < rit->mRTT) +// { +// maxRTT = rit->mRTT; +// } +// } +// if (minTS > rit->mTS) +// { +// minTS = rit->mTS; +// } +// if (maxTS < rit->mTS) +// { +// maxTS = rit->mTS; +// } +// } +// +// info[*it] = results; +// } +// +// +// _tst_CW->updateRttStatistics(info, maxRTT, minTS, maxTS); +// _tst_CW->update(); +//} + QString RttStatistics::getPeerName(const RsPeerId& peer_id) { static std::map names ; diff --git a/retroshare-gui/src/gui/statistics/RttStatistics.h b/retroshare-gui/src/gui/statistics/RttStatistics.h index 72bce7289..6bfdedf81 100644 --- a/retroshare-gui/src/gui/statistics/RttStatistics.h +++ b/retroshare-gui/src/gui/statistics/RttStatistics.h @@ -25,10 +25,27 @@ #include #include "ui_RttStatistics.h" #include "RsAutoUpdatePage.h" +#include class RttStatisticsWidget ; -class RttStatistics: public RsAutoUpdatePage, public Ui::RttStatistics +class RttGraphSource: public RSGraphSource +{ +public: + RttGraphSource() ; + + virtual void getValues(std::map& vals) ; +}; + +class RttStatisticsGraph: public RSGraphWidget +{ + public: + RttStatisticsGraph() + { + } +}; + +class RttStatistics: public MainPage, public Ui::RttStatistics { public: RttStatistics(QWidget *parent = NULL) ; @@ -42,9 +59,7 @@ class RttStatistics: public RsAutoUpdatePage, public Ui::RttStatistics void processSettings(bool bLoad); bool m_bProcessSettings; - virtual void updateDisplay() ; - - RttStatisticsWidget *_tst_CW ; + RttStatisticsGraph *_tst_CW ; } ; class RttStatisticsWidget: public QWidget @@ -66,3 +81,6 @@ class RttStatisticsWidget: public QWidget int maxWidth,maxHeight ; }; + + + diff --git a/retroshare-gui/src/gui/statistics/StatisticsWindow.cpp b/retroshare-gui/src/gui/statistics/StatisticsWindow.cpp index 879c36da5..50381ec30 100644 --- a/retroshare-gui/src/gui/statistics/StatisticsWindow.cpp +++ b/retroshare-gui/src/gui/statistics/StatisticsWindow.cpp @@ -136,11 +136,8 @@ void StatisticsWindow::initStackedPage() ui->stackPages->add(grsdlg = new GlobalRouterStatistics(ui->stackPages), action = createPageAction(QIcon(IMAGE_GLOBALROUTER), tr("Global Router"), grp)); -#ifdef SHOW_RTT_STATISTICS - - ui->stackPages->add(rttdlg = new RttStatistics(ui->stackPages), - action = createPageAction(QIcon(IMAGE_RTT), tr("RTT Statistics"), grp)); -#endif + ui->stackPages->add(rttdlg = new RttStatistics(ui->stackPages), + action = createPageAction(QIcon(IMAGE_RTT), tr("RTT Statistics"), grp)); /*std::cerr << "Looking for interfaces in existing plugins:" << std::endl; for(int i = 0;inbPlugins();++i) diff --git a/retroshare-gui/src/gui/statistics/dhtgraph.cpp b/retroshare-gui/src/gui/statistics/dhtgraph.cpp index ad6061289..56a11e499 100644 --- a/retroshare-gui/src/gui/statistics/dhtgraph.cpp +++ b/retroshare-gui/src/gui/statistics/dhtgraph.cpp @@ -33,24 +33,26 @@ class DHTGraphSource: public RSGraphSource public: virtual int n_values() const { - return 2 ; + return 1 ; } - virtual void getValues(std::vector& values) const + virtual void getValues(std::map& values) const { RsConfigNetStatus config; rsConfig->getConfigNetStatus(config); if (config.DHTActive && config.netDhtOk) { - values.push_back(config.netDhtRsNetSize) ; - values.push_back(config.netDhtNetSize) ; + values.insert(std::make_pair(std::string("RS Net size"),(float)config.netDhtRsNetSize)) ; + //values.insert(std::make_pair(std::string("GLobal Net size"),(float)config.netDhtNetSize)) ; } else { - values.push_back(0.0f) ; - values.push_back(0.0f) ; + values.insert(std::make_pair(std::string("RS Net size"),0.0f)) ; + //values.insert(std::make_pair(std::string("GLobal Net size"),0.0f)) ; } } + + virtual QString unitName() const { return tr("users"); } }; /** Default contructor */ @@ -65,7 +67,8 @@ DhtGraph::DhtGraph(QWidget *parent) addSource(src) ; - setTimeScale(10.0f) ; + setTimeScale(1.0f) ; // 1 pixels per second of time. + resetFlags(RSGRAPH_FLAGS_LOG_SCALE_Y) ; }