mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-08-21 20:38:50 -04:00
moved code into separate directories
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@7244 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
44a1f6f6f3
commit
1e0ea41b4a
24 changed files with 263 additions and 19 deletions
|
@ -0,0 +1,55 @@
|
|||
#include <QFrame>
|
||||
#include <QObject>
|
||||
|
||||
#include "NetworkSimulatorGUI.h"
|
||||
#include "NetworkViewer.h"
|
||||
#include "TurtleRouterStatistics.h"
|
||||
|
||||
NetworkSimulatorGUI::NetworkSimulatorGUI(Network& net)
|
||||
{
|
||||
setupUi(this) ;
|
||||
tickTimerId = 0 ;
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(networkViewFrame) ;
|
||||
layout->addWidget(_viewer = new NetworkViewer(networkViewFrame,net)) ;
|
||||
|
||||
QObject::connect(_viewer,SIGNAL(nodeSelected(int)),this,SLOT(updateSelectedNode(int))) ;
|
||||
QObject::connect(flow_CB,SIGNAL(toggled(bool)),this,SLOT(toggleNetworkTraffic(bool))) ;
|
||||
|
||||
QVBoxLayout *layout2 = new QVBoxLayout(inspectorFrame) ;
|
||||
layout2->addWidget(_turtle_router_statistics = new TurtleRouterStatistics() ) ;
|
||||
}
|
||||
|
||||
void NetworkSimulatorGUI::updateSelectedNode(int node_id)
|
||||
{
|
||||
_turtle_router_statistics->setTurtleRouter( _viewer->network().node(node_id).turtle_service() ) ;
|
||||
}
|
||||
|
||||
void NetworkSimulatorGUI::toggleNetworkTraffic(bool b)
|
||||
{
|
||||
if(!b && tickTimerId > 0)
|
||||
{
|
||||
killTimer(tickTimerId) ;
|
||||
tickTimerId = 0 ;
|
||||
return ;
|
||||
}
|
||||
|
||||
if(b && tickTimerId == 0)
|
||||
{
|
||||
tickTimerId = startTimer(1000) ;
|
||||
return ;
|
||||
}
|
||||
|
||||
std::cerr << "ERROR !!" << std::endl;
|
||||
}
|
||||
|
||||
void NetworkSimulatorGUI::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
Q_UNUSED(event) ;
|
||||
|
||||
std::cerr << "timer event!" << std::endl;
|
||||
|
||||
_viewer->network().tick() ;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#include "ui_NetworkSimulatorGUI.h"
|
||||
|
||||
class TurtleRouterStatistics ;
|
||||
class NetworkViewer ;
|
||||
class Network ;
|
||||
|
||||
class NetworkSimulatorGUI: public QMainWindow, public Ui::NetworkSimulatorGUI
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NetworkSimulatorGUI(Network& net) ;
|
||||
|
||||
public slots:
|
||||
void updateSelectedNode(int) ;
|
||||
void toggleNetworkTraffic(bool) ;
|
||||
|
||||
virtual void timerEvent(QTimerEvent *e) ;
|
||||
|
||||
private:
|
||||
NetworkViewer *_viewer ;
|
||||
TurtleRouterStatistics *_turtle_router_statistics ;
|
||||
|
||||
int tickTimerId ;
|
||||
};
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NetworkSimulatorGUI</class>
|
||||
<widget class="QMainWindow" name="NetworkSimulatorGUI">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>901</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QFrame" name="networkViewFrame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="flow_CB">
|
||||
<property name="text">
|
||||
<string>flow</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="inspectorFrame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>901</width>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<addaction name="actionLoad_network"/>
|
||||
<addaction name="actionSave_network"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<action name="actionLoad_network">
|
||||
<property name="text">
|
||||
<string>Load network</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave_network">
|
||||
<property name="text">
|
||||
<string>Save network</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
602
libretroshare/src/tests/network_simulator/gui/NetworkViewer.cpp
Normal file
602
libretroshare/src/tests/network_simulator/gui/NetworkViewer.cpp
Normal file
|
@ -0,0 +1,602 @@
|
|||
#include <QMouseEvent>
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
|
||||
#include <retroshare/rsids.h>
|
||||
|
||||
#include "Network.h"
|
||||
#include "NetworkViewer.h"
|
||||
|
||||
NetworkViewer::NetworkViewer(QWidget *parent,Network&net)
|
||||
: QGLViewer(parent),_network(net) , timerId(0)
|
||||
{
|
||||
_current_selected_node = -1 ;
|
||||
_current_displayed_node = -1 ;
|
||||
_current_acted_node = -1 ;
|
||||
|
||||
_dragging = false ;
|
||||
_nodes_need_recomputing = true ;
|
||||
|
||||
_node_coords.resize(net.n_nodes()) ;
|
||||
_node_speeds.resize(net.n_nodes()) ;
|
||||
|
||||
for(int i=0;i<_node_coords.size();++i)
|
||||
{
|
||||
_node_coords[i].x = drand48()*width()*5;
|
||||
_node_coords[i].y = drand48()*height()*5 ;
|
||||
_node_speeds[i].x = 0 ;
|
||||
_node_speeds[i].y = 0 ;
|
||||
}
|
||||
|
||||
timerId = startTimer(1000/25) ;
|
||||
|
||||
connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenu(QPoint)));
|
||||
|
||||
action_ManageHash = new QAction(QString("Manage new random hash"),this) ;
|
||||
QObject::connect(action_ManageHash,SIGNAL(triggered()),this,SLOT(actionManageHash())) ;
|
||||
|
||||
setMouseTracking(true) ;
|
||||
}
|
||||
|
||||
void NetworkViewer::draw()
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST) ;
|
||||
glClear(GL_COLOR_BUFFER_BIT) ;
|
||||
|
||||
// for now, view is fixed.
|
||||
|
||||
glMatrixMode(GL_MODELVIEW) ;
|
||||
glPushMatrix() ;
|
||||
glLoadIdentity() ;
|
||||
glMatrixMode(GL_PROJECTION) ;
|
||||
glPushMatrix() ;
|
||||
glLoadIdentity() ;
|
||||
glOrtho(0,width(),0,height(),1,-1) ;
|
||||
|
||||
glEnable(GL_BLEND) ;
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA) ;
|
||||
|
||||
// Now, draw all edges
|
||||
|
||||
std::set<int> tunnel_nodes ;
|
||||
|
||||
glEnable(GL_LINE_SMOOTH) ;
|
||||
glBegin(GL_LINES) ;
|
||||
|
||||
for(uint32_t i=0;i<_network.n_nodes();++i)
|
||||
{
|
||||
PeerNode::NodeTrafficInfo traffic_info ;
|
||||
_network.node(i).getTrafficInfo(traffic_info) ;
|
||||
|
||||
const std::set<uint32_t>& neighs( _network.neighbors(i) ) ;
|
||||
|
||||
for(std::set<uint32_t>::const_iterator it(neighs.begin());it!=neighs.end();++it)
|
||||
{
|
||||
if(traffic_info.local_src.find(_network.node(*it).id().toStdString())!=traffic_info.local_src.end() || traffic_info.local_dst.find(_network.node(*it).id().toStdString())!=traffic_info.local_dst.end())
|
||||
{
|
||||
glColor3f(0.9f,0.4f,0.2f) ;
|
||||
tunnel_nodes.insert(i) ;
|
||||
tunnel_nodes.insert(*it) ;
|
||||
}
|
||||
else
|
||||
glColor3f(0.4f,0.4f,0.4f) ;
|
||||
|
||||
if( i < *it )
|
||||
{
|
||||
glVertex2f(_node_coords[ i].x, _node_coords[ i].y) ;
|
||||
glVertex2f(_node_coords[*it].x, _node_coords[*it].y) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glEnd() ;
|
||||
|
||||
// Draw all nodes.
|
||||
//
|
||||
glEnable(GL_POINT_SMOOTH) ;
|
||||
glPointSize(20.0f) ;
|
||||
glBegin(GL_POINTS) ;
|
||||
|
||||
if(_current_selected_node > -1)
|
||||
{
|
||||
glColor4f(1.0f,0.2f,0.1f,0.7f) ;
|
||||
glVertex2f(_node_coords[_current_selected_node].x, _node_coords[_current_selected_node].y) ;
|
||||
}
|
||||
glEnd() ;
|
||||
|
||||
glPointSize(10.0f) ;
|
||||
glBegin(GL_POINTS) ;
|
||||
|
||||
for(uint32_t i=0;i<_network.n_nodes();++i)
|
||||
{
|
||||
float r = 0.8 ;
|
||||
float g = 0.8 ;
|
||||
float b = 0.8 ;
|
||||
|
||||
if(!_network.node(i).providedHashes().empty())
|
||||
r *= 2.0, g /= 2.0, b /= 2.0f ;
|
||||
|
||||
if(!_network.node(i).managedHashes().empty())
|
||||
g *= 2.0, b /= 2.0, r /= 2.0f ;
|
||||
|
||||
if(tunnel_nodes.find(i) != tunnel_nodes.end() && r==0.8f && g==0.8f && b==0.8f)
|
||||
r = 0.9f, g=0.4f,b=0.2f ;
|
||||
|
||||
glColor3f(r,g,b) ;
|
||||
|
||||
glVertex2f(_node_coords[i].x, _node_coords[i].y) ;
|
||||
}
|
||||
|
||||
glEnd() ;
|
||||
|
||||
// Draw info about current node under mouse.
|
||||
//
|
||||
if(_current_displayed_node > -1)
|
||||
{
|
||||
const PeerNode& node(_network.node(_current_displayed_node)) ;
|
||||
int offset = 0 ;
|
||||
int text_height = 15 ;
|
||||
|
||||
drawText(10+_node_coords[_current_displayed_node].x,offset + height()-_node_coords[_current_displayed_node].y, "Node id = " + QString::fromStdString(node.id().toStdString())) ;
|
||||
offset += text_height ;
|
||||
|
||||
for(std::set<TurtleFileHash>::const_iterator it(node.providedHashes().begin());it!=node.providedHashes().end();++it)
|
||||
{
|
||||
drawText(10+_node_coords[_current_displayed_node].x,offset + height()-_node_coords[_current_displayed_node].y, "Server for hash " + QString::fromStdString((*it).toStdString()) );
|
||||
offset += text_height ;
|
||||
}
|
||||
|
||||
for(std::set<TurtleFileHash>::const_iterator it(node.managedHashes().begin());it!=node.managedHashes().end();++it)
|
||||
{
|
||||
drawText(10+_node_coords[_current_displayed_node].x,offset + height()-_node_coords[_current_displayed_node].y, "Client for hash " + QString::fromStdString((*it).toStdString()) ) ;
|
||||
offset += text_height ;
|
||||
}
|
||||
}
|
||||
|
||||
glMatrixMode(GL_MODELVIEW) ;
|
||||
glPopMatrix() ;
|
||||
glMatrixMode(GL_PROJECTION) ;
|
||||
glPopMatrix() ;
|
||||
}
|
||||
|
||||
#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
|
||||
|
||||
void fourn(double data[],unsigned long nn[],unsigned long ndim,int isign)
|
||||
{
|
||||
int i1,i2,i3,i2rev,i3rev,ip1,ip2,ip3,ifp1,ifp2;
|
||||
int ibit,idim,k1,k2,n,nprev,nrem,ntot;
|
||||
double tempi,tempr;
|
||||
double theta,wi,wpi,wpr,wr,wtemp;
|
||||
|
||||
ntot=1;
|
||||
for (idim=1;idim<=(long)ndim;idim++)
|
||||
ntot *= nn[idim];
|
||||
nprev=1;
|
||||
for (idim=ndim;idim>=1;idim--) {
|
||||
n=nn[idim];
|
||||
nrem=ntot/(n*nprev);
|
||||
ip1=nprev << 1;
|
||||
ip2=ip1*n;
|
||||
ip3=ip2*nrem;
|
||||
i2rev=1;
|
||||
for (i2=1;i2<=ip2;i2+=ip1) {
|
||||
if (i2 < i2rev) {
|
||||
for (i1=i2;i1<=i2+ip1-2;i1+=2) {
|
||||
for (i3=i1;i3<=ip3;i3+=ip2) {
|
||||
i3rev=i2rev+i3-i2;
|
||||
SWAP(data[i3],data[i3rev]);
|
||||
SWAP(data[i3+1],data[i3rev+1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
ibit=ip2 >> 1;
|
||||
while (ibit >= ip1 && i2rev > ibit) {
|
||||
i2rev -= ibit;
|
||||
ibit >>= 1;
|
||||
}
|
||||
i2rev += ibit;
|
||||
}
|
||||
ifp1=ip1;
|
||||
while (ifp1 < ip2) {
|
||||
ifp2=ifp1 << 1;
|
||||
theta=isign*6.28318530717959/(ifp2/ip1);
|
||||
wtemp=sin(0.5*theta);
|
||||
wpr = -2.0*wtemp*wtemp;
|
||||
wpi=sin(theta);
|
||||
wr=1.0;
|
||||
wi=0.0;
|
||||
for (i3=1;i3<=ifp1;i3+=ip1) {
|
||||
for (i1=i3;i1<=i3+ip1-2;i1+=2) {
|
||||
for (i2=i1;i2<=ip3;i2+=ifp2) {
|
||||
k1=i2;
|
||||
k2=k1+ifp1;
|
||||
tempr=wr*data[k2]-wi*data[k2+1];
|
||||
tempi=wr*data[k2+1]+wi*data[k2];
|
||||
data[k2]=data[k1]-tempr;
|
||||
data[k2+1]=data[k1+1]-tempi;
|
||||
data[k1] += tempr;
|
||||
data[k1+1] += tempi;
|
||||
}
|
||||
}
|
||||
wr=(wtemp=wr)*wpr-wi*wpi+wr;
|
||||
wi=wi*wpr+wtemp*wpi+wi;
|
||||
}
|
||||
ifp1=ifp2;
|
||||
}
|
||||
nprev *= n;
|
||||
}
|
||||
}
|
||||
|
||||
#undef SWAP
|
||||
|
||||
static void convolveWithGaussian(double *forceMap,int S,int /*s*/)
|
||||
{
|
||||
static double *bf = NULL ;
|
||||
|
||||
if(bf == NULL)
|
||||
{
|
||||
bf = new double[S*S*2] ;
|
||||
|
||||
for(int i=0;i<S;++i)
|
||||
for(int j=0;j<S;++j)
|
||||
{
|
||||
int x = (i<S/2)?i:(S-i) ;
|
||||
int y = (j<S/2)?j:(S-j) ;
|
||||
// int l=2*(x*x+y*y);
|
||||
bf[2*(i+S*j)] = log(sqrtf(0.1 + x*x+y*y)); // linear -> derivative is constant
|
||||
bf[2*(i+S*j)+1] = 0 ;
|
||||
}
|
||||
|
||||
unsigned long nn[2] = {S,S};
|
||||
fourn(&bf[-1],&nn[-1],2,1) ;
|
||||
}
|
||||
|
||||
unsigned long nn[2] = {S,S};
|
||||
fourn(&forceMap[-1],&nn[-1],2,1) ;
|
||||
|
||||
for(int i=0;i<S;++i)
|
||||
for(int j=0;j<S;++j)
|
||||
{
|
||||
float a = forceMap[2*(i+S*j)]*bf[2*(i+S*j)] - forceMap[2*(i+S*j)+1]*bf[2*(i+S*j)+1] ;
|
||||
float b = forceMap[2*(i+S*j)]*bf[2*(i+S*j)+1] + forceMap[2*(i+S*j)+1]*bf[2*(i+S*j)] ;
|
||||
|
||||
forceMap[2*(i+S*j)] = a ;
|
||||
forceMap[2*(i+S*j)+1] = b ;
|
||||
}
|
||||
|
||||
fourn(&forceMap[-1],&nn[-1],2,-1) ;
|
||||
|
||||
for(int i=0;i<S*S*2;++i)
|
||||
forceMap[i] /= S*S;
|
||||
}
|
||||
|
||||
void NetworkViewer::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
if(!isVisible())
|
||||
return ;
|
||||
|
||||
if(_nodes_need_recomputing)
|
||||
{
|
||||
std::cerr << "Updating forces..."<< std::endl;
|
||||
static const int S = 256 ;
|
||||
static double *forceMap = new double[2*S*S] ;
|
||||
|
||||
memset(forceMap,0,2*S*S*sizeof(double)) ;
|
||||
|
||||
for(uint32_t k=0;k<_network.n_nodes();++k)
|
||||
{
|
||||
float x = S*_node_coords[k].x/width() ;
|
||||
float y = S*_node_coords[k].y/height() ;
|
||||
|
||||
int i=(int)floor(x) ;
|
||||
int j=(int)floor(y) ;
|
||||
|
||||
float di = x-i ;
|
||||
float dj = y-j ;
|
||||
|
||||
if( i>=0 && i<S-1 && j>=0 && j<S-1)
|
||||
{
|
||||
forceMap[2*(i +S*(j ))] += (1-di)*(1-dj) ;
|
||||
forceMap[2*(i+1+S*(j ))] += di *(1-dj) ;
|
||||
forceMap[2*(i +S*(j+1))] += (1-di)*dj ;
|
||||
forceMap[2*(i+1+S*(j+1))] += di *dj ;
|
||||
}
|
||||
}
|
||||
|
||||
// compute convolution with 1/omega kernel.
|
||||
//
|
||||
convolveWithGaussian(forceMap,S,20) ;
|
||||
|
||||
static float speedf=1.0f;
|
||||
|
||||
std::vector<NodeCoord> new_coords(_node_coords) ;
|
||||
|
||||
for(uint32_t i=0;i<_network.n_nodes();++i)
|
||||
if(i != _current_selected_node || !_dragging)
|
||||
{
|
||||
float x = _node_coords[i].x ;
|
||||
float y = _node_coords[i].y ;
|
||||
|
||||
calculateForces(i,forceMap,S,S,x,y,speedf,new_coords[i].x,new_coords[i].y);
|
||||
}
|
||||
|
||||
bool itemsMoved = false;
|
||||
for(uint32_t i=0;i<_node_coords.size();++i)
|
||||
{
|
||||
if( fabsf(_node_coords[i].x - new_coords[i].x) > 1.0 || fabsf(_node_coords[i].y - new_coords[i].y) > 1.0)
|
||||
itemsMoved = true;
|
||||
|
||||
//std::cerr << "Old i = " << _node_coords[i].x << ", new = " << new_coords[i].x << std::endl;
|
||||
_node_coords[i] = new_coords[i] ;
|
||||
}
|
||||
|
||||
if (!itemsMoved) {
|
||||
// killTimer(timerId);
|
||||
//#ifdef DEBUG_ELASTIC
|
||||
std::cerr << "Killing timr" << std::endl ;
|
||||
_nodes_need_recomputing = false ;
|
||||
//#endif
|
||||
timerId = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
updateGL() ;
|
||||
usleep(2000) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
updateGL() ;
|
||||
|
||||
}
|
||||
|
||||
void NetworkViewer::mouseMoveEvent(QMouseEvent *e)
|
||||
{
|
||||
if(_dragging && _current_selected_node >= 0)
|
||||
{
|
||||
_node_coords[_current_selected_node].x = e->x() ;
|
||||
_node_coords[_current_selected_node].y = height() - e->y() ;
|
||||
|
||||
_nodes_need_recomputing = true ;
|
||||
|
||||
updateGL() ;
|
||||
}
|
||||
|
||||
float x = e->x() ;
|
||||
float y = height()-e->y() ;
|
||||
|
||||
_current_displayed_node = -1 ;
|
||||
|
||||
for(uint32_t i=0;i<_node_coords.size();++i)
|
||||
if( pow(_node_coords[i].x-x,2)+pow(_node_coords[i].y-y,2) < 5*5)
|
||||
{
|
||||
_current_displayed_node = i;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkViewer::mouseReleaseEvent(QMouseEvent *e)
|
||||
{
|
||||
_dragging = false ;
|
||||
}
|
||||
|
||||
void NetworkViewer::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
float x = e->x() ;
|
||||
float y = height() - e->y() ;
|
||||
|
||||
// find which node is selected
|
||||
|
||||
for(uint32_t i=0;i<_node_coords.size();++i)
|
||||
if( pow(_node_coords[i].x - x,2)+pow(_node_coords[i].y - y,2) < 10*10 )
|
||||
{
|
||||
if(e->button() == Qt::LeftButton)
|
||||
{
|
||||
_current_selected_node = i ;
|
||||
_dragging = true ;
|
||||
updateGL() ;
|
||||
emit nodeSelected(i) ;
|
||||
return ;
|
||||
}
|
||||
|
||||
if(e->button() == Qt::RightButton)
|
||||
{
|
||||
_current_acted_node = i ;
|
||||
emit customContextMenuRequested(QPoint(e->x(),e->y())) ;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
_dragging = false ;
|
||||
_current_selected_node = -1 ;
|
||||
}
|
||||
|
||||
void NetworkViewer::calculateForces(const Network::NodeId& node_id,const double *map,int W,int H,float x,float y,float /*speedf*/,float& new_x, float& new_y)
|
||||
{
|
||||
#ifdef A_FAIRE
|
||||
if (mouseGrabberItem() == this)
|
||||
{
|
||||
new_x = x ;
|
||||
new_y = y ;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sum up all forces pushing this item away
|
||||
qreal xforce = 0;
|
||||
qreal yforce = 0;
|
||||
|
||||
float dei=0.0f ;
|
||||
float dej=0.0f ;
|
||||
|
||||
static float *e = NULL ;
|
||||
static const int KS = 5 ;
|
||||
|
||||
if(e == NULL)
|
||||
{
|
||||
e = new float[(2*KS+1)*(2*KS+1)] ;
|
||||
|
||||
for(int i=-KS;i<=KS;++i)
|
||||
for(int j=-KS;j<=KS;++j)
|
||||
e[i+KS+(2*KS+1)*(j+KS)] = exp( -(i*i+j*j)/30.0 ) ; // can be precomputed
|
||||
}
|
||||
|
||||
for(int i=-KS;i<=KS;++i)
|
||||
for(int j=-KS;j<=KS;++j)
|
||||
{
|
||||
int X = std::min(W-1,std::max(0,(int)rint(x/(float)width()*W))) ;
|
||||
int Y = std::min(H-1,std::max(0,(int)rint(y/(float)height()*H))) ;
|
||||
|
||||
float val = map[2*((i+X+W)%W + W*((j+Y+H)%H))] ;
|
||||
|
||||
dei += i * e[i+KS+(2*KS+1)*(j+KS)] * val ;
|
||||
dej += j * e[i+KS+(2*KS+1)*(j+KS)] * val ;
|
||||
}
|
||||
|
||||
xforce = REPULSION_FACTOR * dei/25.0;
|
||||
yforce = REPULSION_FACTOR * dej/25.0;
|
||||
|
||||
// Now subtract all forces pulling items together
|
||||
//
|
||||
const std::set<Network::NodeId>& neighbs(_network.neighbors(node_id)) ;
|
||||
double weight = neighbs.size() + 1 ;
|
||||
|
||||
for(std::set<Network::NodeId>::const_iterator it(neighbs.begin());it!=neighbs.end();++it)
|
||||
{
|
||||
NodeCoord pos;
|
||||
double w2 ; // This factor makes the edge length depend on connectivity, so clusters of friends tend to stay in the
|
||||
// same location.
|
||||
//
|
||||
|
||||
pos.x = _node_coords[*it].x - x ; //mapFromItem(edge->destNode(), 0, 0);
|
||||
pos.y = _node_coords[*it].y - y ; //mapFromItem(edge->destNode(), 0, 0);
|
||||
|
||||
w2 = sqrtf(std::min(neighbs.size(),_network.neighbors(*it).size())) ;
|
||||
|
||||
float dist = sqrtf(pos.x*pos.x + pos.y*pos.y) ;
|
||||
float val = dist - NODE_DISTANCE * w2 ;
|
||||
|
||||
xforce += 0.01*pos.x * val / weight;
|
||||
yforce += 0.01*pos.y * val / weight;
|
||||
}
|
||||
|
||||
xforce -= FRICTION_FACTOR * _node_speeds[node_id].x ;
|
||||
yforce -= FRICTION_FACTOR * _node_speeds[node_id].y ;
|
||||
|
||||
// This term drags nodes away from the sides.
|
||||
//
|
||||
if(x < 15) xforce += 100.0/(x+0.1) ;
|
||||
if(y < 15) yforce += 100.0/(y+0.1) ;
|
||||
if(x > width()-15) xforce -= 100.0/(width()-x+0.1) ;
|
||||
if(y > height()-15) yforce -= 100.0/(height()-y+0.1) ;
|
||||
|
||||
// now time filter:
|
||||
|
||||
_node_speeds[node_id].x += xforce / MASS_FACTOR;
|
||||
_node_speeds[node_id].y += yforce / MASS_FACTOR;
|
||||
|
||||
if(_node_speeds[node_id].x > 10) _node_speeds[node_id].x = 10.0f ;
|
||||
if(_node_speeds[node_id].y > 10) _node_speeds[node_id].y = 10.0f ;
|
||||
if(_node_speeds[node_id].x <-10) _node_speeds[node_id].x =-10.0f ;
|
||||
if(_node_speeds[node_id].y <-10) _node_speeds[node_id].y =-10.0f ;
|
||||
|
||||
new_x = x + _node_speeds[node_id].x ;
|
||||
new_y = y + _node_speeds[node_id].y ;
|
||||
|
||||
new_x = std::min(std::max(new_x, 10.0f), width() - 10.0f);
|
||||
new_y = std::min(std::max(new_y, 10.0f), height() - 10.0f);
|
||||
}
|
||||
|
||||
void NetworkViewer::contextMenu(QPoint p)
|
||||
{
|
||||
std::cerr << "Context menu request at point " << p.x() << " " << p.y() << std::endl;
|
||||
|
||||
QMenu contextMnu ;//= ui.msgText->createStandardContextMenu(matrix.map(point));
|
||||
|
||||
contextMnu.addAction(action_ManageHash);
|
||||
|
||||
if(_current_acted_node == -1)
|
||||
return ;
|
||||
|
||||
std::cerr << "acting on node " << _network.node(_current_acted_node).id() << std::endl;
|
||||
|
||||
// make a list of hashes provided by all nodes except this one
|
||||
std::set<TurtleFileHash> managed_hashes ;
|
||||
std::set<TurtleFileHash> provided_hashes ;
|
||||
|
||||
for(uint32_t i=0;i<_network.n_nodes();++i)
|
||||
if(i != _current_acted_node)
|
||||
{
|
||||
managed_hashes.insert( _network.node(i).managedHashes().begin(), _network.node(i).managedHashes().end()) ;
|
||||
provided_hashes.insert( _network.node(i).providedHashes().begin(), _network.node(i).providedHashes().end()) ;
|
||||
}
|
||||
|
||||
if(!managed_hashes.empty())
|
||||
{
|
||||
QMenu *Mnu2 = contextMnu.addMenu("Provide hash") ;
|
||||
|
||||
for(std::set<TurtleFileHash>::const_iterator it(managed_hashes.begin());it!=managed_hashes.end();++it)
|
||||
{
|
||||
QAction* provide_hash_action = new QAction(QString::fromStdString((*it).toStdString()), Mnu2);
|
||||
connect(provide_hash_action, SIGNAL(triggered()), this, SLOT(actionProvideHash()));
|
||||
Mnu2->addAction(provide_hash_action);
|
||||
}
|
||||
}
|
||||
if(!provided_hashes.empty())
|
||||
{
|
||||
QMenu *Mnu2 = contextMnu.addMenu("Manage hash") ;
|
||||
|
||||
for(std::set<TurtleFileHash>::const_iterator it(provided_hashes.begin());it!=provided_hashes.end();++it)
|
||||
{
|
||||
QAction* manage_hash_action = new QAction(QString::fromStdString((*it).toStdString()), Mnu2);
|
||||
connect(manage_hash_action, SIGNAL(triggered()), this, SLOT(actionManageHash()));
|
||||
Mnu2->addAction(manage_hash_action);
|
||||
}
|
||||
}
|
||||
contextMnu.exec(mapToGlobal(p));
|
||||
}
|
||||
|
||||
void NetworkViewer::actionManageHash()
|
||||
{
|
||||
if(_current_acted_node < 0)
|
||||
return ;
|
||||
|
||||
RsFileHash hash ;
|
||||
|
||||
if(qobject_cast<QAction*>(sender())->text().length() == 40) //data().toString().toStdString();
|
||||
{
|
||||
hash = RsFileHash(qobject_cast<QAction*>(sender())->text().toStdString()) ;
|
||||
|
||||
std::cerr << "Managing existing hash " << hash << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Managing random hash..." << std::endl;
|
||||
|
||||
hash = RsFileHash::random() ;
|
||||
}
|
||||
|
||||
|
||||
std::cerr << " current node = " << _current_acted_node << std::endl ;
|
||||
std::cerr << " adding random hash = " << hash << std::endl;
|
||||
|
||||
_network.node(_current_acted_node).manageFileHash(hash) ;
|
||||
|
||||
updateGL() ;
|
||||
}
|
||||
|
||||
void NetworkViewer::actionProvideHash()
|
||||
{
|
||||
QString hash = qobject_cast<QAction*>(sender())->text() ;//data().toString().toStdString();
|
||||
|
||||
if(_current_acted_node < 0)
|
||||
return ;
|
||||
|
||||
std::cerr << "Providing hash " << hash.toStdString() << std::endl;
|
||||
_network.node(_current_acted_node).provideFileHash(RsFileHash(hash.toStdString())) ;
|
||||
|
||||
updateGL() ;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
#include <QPoint>
|
||||
#include <QGLViewer/qglviewer.h>
|
||||
|
||||
// The network simulator GUI has the following functionalities:
|
||||
//
|
||||
// 1 - show the network graph
|
||||
// * the graph should spread in space automatically. We should use the code from the NetworkView for that.
|
||||
// * each edge will be drawn with a color that displays used bandwidth along the edge, or TR sent to the edge, etc.
|
||||
// * individual tunnels should be shown, in order to see what shape they have
|
||||
//
|
||||
// 2 - show info about each node. One needs a node widget that gets updated with whatever is to be read from the current node
|
||||
//
|
||||
// 3 - buttons to re-initiate a new network, or reset the network.
|
||||
//
|
||||
// 4 - buttons to inject information into the network:
|
||||
// * shared files in some nodes. Should be handled by derivign the component that the turtle router accesses for local searches.
|
||||
// * file requests in other nodes. Eazy: one just needs to ask the turtle router of the node to handle the hash.
|
||||
//
|
||||
// 5 - perturbate the network
|
||||
// * change the load of each node, and the delay when forwarding requests.
|
||||
//
|
||||
#include "Network.h"
|
||||
|
||||
class NetworkViewer: public QGLViewer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NetworkViewer(QWidget *parent,Network& network) ;
|
||||
|
||||
virtual void draw() ;
|
||||
virtual void keyPressEvent(QKeyEvent *) {}
|
||||
virtual void mousePressEvent(QMouseEvent *) ;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *) ;
|
||||
virtual void mouseMoveEvent(QMouseEvent *) ;
|
||||
|
||||
const Network& network() const { return _network ; }
|
||||
Network& network() { return _network ; }
|
||||
|
||||
signals:
|
||||
void nodeSelected(int) ;
|
||||
|
||||
public slots:
|
||||
void timerEvent(QTimerEvent *) ;
|
||||
void contextMenu(QPoint) ;
|
||||
void actionManageHash() ;
|
||||
void actionProvideHash() ;
|
||||
|
||||
private:
|
||||
void calculateForces(const Network::NodeId& node_id,const double *map,int W,int H,float x,float y,float /*speedf*/,float& new_x, float& new_y) ;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x ;
|
||||
float y ;
|
||||
} NodeCoord ;
|
||||
|
||||
Network& _network ;
|
||||
|
||||
std::vector<NodeCoord> _node_coords ;
|
||||
std::vector<NodeCoord> _node_speeds ;
|
||||
|
||||
static const float MASS_FACTOR = 10 ;
|
||||
static const float FRICTION_FACTOR = 15.8 ;
|
||||
static const float REPULSION_FACTOR = 8 ;
|
||||
static const float NODE_DISTANCE = 30.0 ;
|
||||
|
||||
int timerId ;
|
||||
|
||||
int _current_selected_node ;
|
||||
int _current_displayed_node ;
|
||||
int _current_acted_node ;
|
||||
bool _dragging ;
|
||||
bool _nodes_need_recomputing ;
|
||||
|
||||
QAction *action_ManageHash ;
|
||||
QAction *action_ProvideHash ;
|
||||
};
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#include <QTimer>
|
||||
#include "RsAutoUpdatePage.h"
|
||||
|
||||
bool RsAutoUpdatePage::_locked = false ;
|
||||
|
||||
RsAutoUpdatePage::RsAutoUpdatePage(int ms_update_period, QWidget *parent, Qt::WindowFlags flags)
|
||||
: QWidget(parent, flags)
|
||||
{
|
||||
_timer = new QTimer ;
|
||||
_timer->setInterval(ms_update_period);
|
||||
_timer->setSingleShot(true);
|
||||
|
||||
QObject::connect(_timer,SIGNAL(timeout()),this,SLOT(timerUpdate())) ;
|
||||
|
||||
_timer->start() ;
|
||||
}
|
||||
|
||||
RsAutoUpdatePage::~RsAutoUpdatePage()
|
||||
{
|
||||
if(_timer != NULL)
|
||||
delete _timer ;
|
||||
|
||||
_timer = NULL ;
|
||||
}
|
||||
|
||||
void RsAutoUpdatePage::showEvent(QShowEvent */*event*/)
|
||||
{
|
||||
//std::cout << "RsAutoUpdatePage::showEvent() In show event !!" << std::endl ;
|
||||
if(!_locked)
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
void RsAutoUpdatePage::timerUpdate()
|
||||
{
|
||||
// only update when the widget is visible.
|
||||
//
|
||||
if(_locked == false && isVisible()) {
|
||||
updateDisplay();
|
||||
update() ; // Qt flush
|
||||
}
|
||||
|
||||
_timer->start() ;
|
||||
}
|
||||
|
||||
void RsAutoUpdatePage::lockAllEvents() { _locked = true ; }
|
||||
void RsAutoUpdatePage::unlockAllEvents() { _locked = false ; }
|
||||
bool RsAutoUpdatePage::eventsLocked() { return _locked ; }
|
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include <QApplication>
|
||||
#include <QWidget>
|
||||
|
||||
// This class implement a basic RS functionality which is that widgets displayign info
|
||||
// should update regularly. They also should update only when visible, to save CPU time.
|
||||
//
|
||||
// Using this class simply needs to derive your widget from RsAutoUpdateWidget
|
||||
// and oveload the update() function with the actual code that updates the
|
||||
// widget.
|
||||
//
|
||||
class QTimer ;
|
||||
|
||||
class RsAutoUpdatePage: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RsAutoUpdatePage(int ms_update_period = 1000, QWidget *parent = NULL, Qt::WindowFlags flags = 0) ;
|
||||
virtual ~RsAutoUpdatePage() ;
|
||||
|
||||
virtual void updateDisplay() {}
|
||||
|
||||
static void lockAllEvents() ;
|
||||
static void unlockAllEvents() ;
|
||||
static bool eventsLocked() ;
|
||||
|
||||
protected:
|
||||
virtual void showEvent(QShowEvent *e) ;
|
||||
|
||||
private slots:
|
||||
void timerUpdate() ;
|
||||
|
||||
private:
|
||||
QTimer *_timer ;
|
||||
|
||||
static bool _locked ;
|
||||
};
|
||||
|
|
@ -0,0 +1,318 @@
|
|||
/****************************************************************
|
||||
* RetroShare is distributed under the following license:
|
||||
*
|
||||
* Copyright (C) 20011, RetroShare Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
****************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <QTimer>
|
||||
#include <QObject>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QStylePainter>
|
||||
|
||||
#include <retroshare/rsturtle.h>
|
||||
#include <retroshare/rspeers.h>
|
||||
#include "TurtleRouterStatistics.h"
|
||||
|
||||
static const int MAX_TUNNEL_REQUESTS_DISPLAY = 10 ;
|
||||
|
||||
class TRHistogram
|
||||
{
|
||||
public:
|
||||
TRHistogram(const std::vector<TurtleRequestDisplayInfo >& info) :_infos(info) {}
|
||||
|
||||
QColor colorScale(float f)
|
||||
{
|
||||
if(f == 0)
|
||||
return QColor::fromHsv(0,0,192) ;
|
||||
else
|
||||
return QColor::fromHsv((int)((1.0-f)*280),200,255) ;
|
||||
}
|
||||
|
||||
virtual void draw(QPainter *painter,int& ox,int& oy,const QString& title)
|
||||
{
|
||||
static const int MaxTime = 61 ;
|
||||
static const int MaxDepth = 8 ;
|
||||
static const int cellx = 7 ;
|
||||
static const int celly = 12 ;
|
||||
|
||||
int save_ox = ox ;
|
||||
painter->setPen(QColor::fromRgb(0,0,0)) ;
|
||||
painter->drawText(2+ox,celly+oy,title) ;
|
||||
oy+=2+2*celly ;
|
||||
|
||||
if(_infos.empty())
|
||||
return ;
|
||||
|
||||
ox += 10 ;
|
||||
std::map<RsPeerId,std::vector<int> > hits ;
|
||||
std::map<RsPeerId,std::vector<int> > depths ;
|
||||
std::map<RsPeerId,std::vector<int> >::iterator it ;
|
||||
|
||||
int max_hits = 1;
|
||||
int max_depth = 1;
|
||||
|
||||
for(uint32_t i=0;i<_infos.size();++i)
|
||||
{
|
||||
std::vector<int>& h(hits[_infos[i].source_peer_id]) ;
|
||||
std::vector<int>& g(depths[_infos[i].source_peer_id]) ;
|
||||
|
||||
if(h.size() <= _infos[i].age)
|
||||
h.resize(MaxTime,0) ;
|
||||
|
||||
if(g.empty())
|
||||
g.resize(MaxDepth,0) ;
|
||||
|
||||
if(_infos[i].age < h.size())
|
||||
{
|
||||
h[_infos[i].age]++ ;
|
||||
if(h[_infos[i].age] > max_hits)
|
||||
max_hits = h[_infos[i].age] ;
|
||||
}
|
||||
if(_infos[i].depth < g.size())
|
||||
{
|
||||
g[_infos[i].depth]++ ;
|
||||
|
||||
if(g[_infos[i].depth] > max_depth)
|
||||
max_depth = g[_infos[i].depth] ;
|
||||
}
|
||||
}
|
||||
|
||||
int max_bi = std::max(max_hits,max_depth) ;
|
||||
int p=0 ;
|
||||
|
||||
for(it=depths.begin();it!=depths.end();++it,++p)
|
||||
for(int i=0;i<MaxDepth;++i)
|
||||
painter->fillRect(ox+MaxTime*cellx+20+i*cellx,oy+p*celly,cellx,celly,colorScale(it->second[i]/(float)max_bi)) ;
|
||||
|
||||
painter->setPen(QColor::fromRgb(0,0,0)) ;
|
||||
painter->drawRect(ox+MaxTime*cellx+20,oy,MaxDepth*cellx,p*celly) ;
|
||||
|
||||
for(int i=0;i<MaxTime;i+=5)
|
||||
painter->drawText(ox+i*cellx,oy+(p+1)*celly+4,QString::number(i)) ;
|
||||
|
||||
p=0 ;
|
||||
int great_total = 0 ;
|
||||
|
||||
for(it=hits.begin();it!=hits.end();++it,++p)
|
||||
{
|
||||
int total = 0 ;
|
||||
|
||||
for(int i=0;i<MaxTime;++i)
|
||||
{
|
||||
painter->fillRect(ox+i*cellx,oy+p*celly,cellx,celly,colorScale(it->second[i]/(float)max_bi)) ;
|
||||
total += it->second[i] ;
|
||||
}
|
||||
|
||||
painter->setPen(QColor::fromRgb(0,0,0)) ;
|
||||
painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx,oy+(p+1)*celly,TurtleRouterStatistics::getPeerName(it->first)) ;
|
||||
painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx+120,oy+(p+1)*celly,"("+QString::number(total)+")") ;
|
||||
great_total += total ;
|
||||
}
|
||||
|
||||
painter->drawRect(ox,oy,MaxTime*cellx,p*celly) ;
|
||||
|
||||
for(int i=0;i<MaxTime;i+=5)
|
||||
painter->drawText(ox+i*cellx,oy+(p+1)*celly+4,QString::number(i)) ;
|
||||
for(int i=0;i<MaxDepth;i++)
|
||||
painter->drawText(ox+MaxTime*cellx+20+i*cellx,oy+(p+1)*celly+4,QString::number(i)) ;
|
||||
painter->setPen(QColor::fromRgb(255,130,80)) ;
|
||||
painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx+120,oy+(p+1)*celly+4,"("+QString::number(great_total)+")");
|
||||
|
||||
oy += (p+1)*celly+6 ;
|
||||
|
||||
painter->setPen(QColor::fromRgb(0,0,0)) ;
|
||||
painter->drawText(ox,oy+celly,"("+QApplication::translate("TurtleRouterStatistics", "Age in seconds")+")");
|
||||
painter->drawText(ox+MaxTime*cellx+20,oy+celly,"("+QApplication::translate("TurtleRouterStatistics", "Depth")+")");
|
||||
|
||||
painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx+120,oy+celly,"("+QApplication::translate("TurtleRouterStatistics", "total")+")");
|
||||
|
||||
oy += 3*celly ;
|
||||
|
||||
// now, draw a scale
|
||||
|
||||
int last_hts = -1 ;
|
||||
int cellid = 0 ;
|
||||
|
||||
for(int i=0;i<=10;++i)
|
||||
{
|
||||
int hts = (int)(max_bi*i/10.0) ;
|
||||
|
||||
if(hts > last_hts)
|
||||
{
|
||||
painter->fillRect(ox+cellid*(cellx+22),oy,cellx,celly,colorScale(i/10.0f)) ;
|
||||
painter->setPen(QColor::fromRgb(0,0,0)) ;
|
||||
painter->drawRect(ox+cellid*(cellx+22),oy,cellx,celly) ;
|
||||
painter->drawText(ox+cellid*(cellx+22)+cellx+4,oy+celly,QString::number(hts)) ;
|
||||
last_hts = hts ;
|
||||
++cellid ;
|
||||
}
|
||||
}
|
||||
|
||||
oy += celly*2 ;
|
||||
|
||||
ox = save_ox ;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::vector<TurtleRequestDisplayInfo>& _infos ;
|
||||
};
|
||||
|
||||
TurtleRouterStatistics::TurtleRouterStatistics(QWidget *parent)
|
||||
: RsAutoUpdatePage(2000,parent)
|
||||
{
|
||||
setupUi(this) ;
|
||||
|
||||
_turtle = NULL ;
|
||||
|
||||
_tunnel_statistics_F->setWidget( _tst_CW = new TurtleRouterStatisticsWidget() ) ;
|
||||
_tunnel_statistics_F->setWidgetResizable(true);
|
||||
_tunnel_statistics_F->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
_tunnel_statistics_F->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
_tunnel_statistics_F->viewport()->setBackgroundRole(QPalette::NoRole);
|
||||
_tunnel_statistics_F->setFrameStyle(QFrame::NoFrame);
|
||||
_tunnel_statistics_F->setFocusPolicy(Qt::NoFocus);
|
||||
}
|
||||
|
||||
TurtleRouterStatistics::~TurtleRouterStatistics()
|
||||
{
|
||||
}
|
||||
|
||||
void TurtleRouterStatistics::updateDisplay()
|
||||
{
|
||||
if(_turtle == NULL)
|
||||
return ;
|
||||
|
||||
std::vector<std::vector<std::string> > hashes_info ;
|
||||
std::vector<std::vector<std::string> > tunnels_info ;
|
||||
std::vector<TurtleRequestDisplayInfo > search_reqs_info ;
|
||||
std::vector<TurtleRequestDisplayInfo > tunnel_reqs_info ;
|
||||
|
||||
_turtle->getInfo(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ;
|
||||
|
||||
//updateTunnelRequests(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ;
|
||||
_tst_CW->updateTunnelStatistics(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info,_turtle) ;
|
||||
_tst_CW->update();
|
||||
}
|
||||
|
||||
QString TurtleRouterStatistics::getPeerName(const RsPeerId& peer_id)
|
||||
{
|
||||
static std::map<RsPeerId, QString> names ;
|
||||
|
||||
std::map<RsPeerId,QString>::const_iterator it = names.find(peer_id) ;
|
||||
|
||||
if( it != names.end())
|
||||
return it->second ;
|
||||
else
|
||||
return (names[peer_id] = QString::fromStdString(peer_id.toStdString())) ;
|
||||
}
|
||||
|
||||
TurtleRouterStatisticsWidget::TurtleRouterStatisticsWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
maxWidth = 200 ;
|
||||
maxHeight = 0 ;
|
||||
}
|
||||
|
||||
void TurtleRouterStatisticsWidget::updateTunnelStatistics(const std::vector<std::vector<std::string> >& /*hashes_info*/,
|
||||
const std::vector<std::vector<std::string> >& /*tunnels_info*/,
|
||||
const std::vector<TurtleRequestDisplayInfo >& search_reqs_info,
|
||||
const std::vector<TurtleRequestDisplayInfo >& tunnel_reqs_info,
|
||||
const RsTurtle *turtle)
|
||||
|
||||
{
|
||||
static const int cellx = 6 ;
|
||||
static const int celly = 10+4 ;
|
||||
|
||||
QPixmap tmppixmap(maxWidth, maxHeight);
|
||||
tmppixmap.fill(this, 0, 0);
|
||||
setFixedHeight(maxHeight);
|
||||
|
||||
QPainter painter(&tmppixmap);
|
||||
painter.initFrom(this);
|
||||
|
||||
maxHeight = 500 ;
|
||||
|
||||
// std::cerr << "Drawing into pixmap of size " << maxWidth << "x" << maxHeight << std::endl;
|
||||
// draw...
|
||||
int ox=5,oy=5 ;
|
||||
|
||||
TRHistogram(search_reqs_info).draw(&painter,ox,oy,tr("Search requests repartition") + ":") ;
|
||||
|
||||
painter.setPen(QColor::fromRgb(70,70,70)) ;
|
||||
painter.drawLine(0,oy,maxWidth,oy) ;
|
||||
oy += celly ;
|
||||
|
||||
TRHistogram(tunnel_reqs_info).draw(&painter,ox,oy,tr("Tunnel requests repartition") + ":") ;
|
||||
|
||||
// now give information about turtle traffic.
|
||||
//
|
||||
TurtleTrafficStatisticsInfo info ;
|
||||
turtle->getTrafficStatistics(info) ;
|
||||
|
||||
painter.setPen(QColor::fromRgb(70,70,70)) ;
|
||||
painter.drawLine(0,oy,maxWidth,oy) ;
|
||||
oy += celly ;
|
||||
|
||||
painter.drawText(ox,oy+celly,tr("Turtle router traffic")+":") ; oy += celly*2 ;
|
||||
painter.drawText(ox+2*cellx,oy+celly,tr("Tunnel requests Up")+"\t: " + speedString(info.tr_up_Bps) ) ; oy += celly ;
|
||||
painter.drawText(ox+2*cellx,oy+celly,tr("Tunnel requests Dn")+"\t: " + speedString(info.tr_dn_Bps) ) ; oy += celly ;
|
||||
painter.drawText(ox+2*cellx,oy+celly,tr("Incoming file data")+"\t: " + speedString(info.data_dn_Bps) ) ; oy += celly ;
|
||||
painter.drawText(ox+2*cellx,oy+celly,tr("Outgoing file data")+"\t: " + speedString(info.data_up_Bps) ) ; oy += celly ;
|
||||
painter.drawText(ox+2*cellx,oy+celly,tr("Forwarded data ")+"\t: " + speedString(info.unknown_updn_Bps) ) ; oy += celly ;
|
||||
|
||||
QString prob_string ;
|
||||
|
||||
for(uint i=0;i<info.forward_probabilities.size();++i)
|
||||
prob_string += QString::number(info.forward_probabilities[i],'g',2) + " (" + QString::number(i) + ") " ;
|
||||
|
||||
painter.drawText(ox+2*cellx,oy+celly,tr("TR Forward probabilities")+"\t: " + prob_string ) ;
|
||||
oy += celly ;
|
||||
oy += celly ;
|
||||
|
||||
// update the pixmap
|
||||
//
|
||||
pixmap = tmppixmap;
|
||||
maxHeight = oy ;
|
||||
}
|
||||
|
||||
QString TurtleRouterStatisticsWidget::speedString(float f)
|
||||
{
|
||||
if(f < 1.0f)
|
||||
return QString("0 B/s") ;
|
||||
if(f < 1024.0f)
|
||||
return QString::number((int)f)+" B/s" ;
|
||||
|
||||
return QString::number(f/1024.0,'f',2) + " KB/s";
|
||||
}
|
||||
|
||||
void TurtleRouterStatisticsWidget::paintEvent(QPaintEvent */*event*/)
|
||||
{
|
||||
QStylePainter(this).drawPixmap(0, 0, pixmap);
|
||||
}
|
||||
|
||||
void TurtleRouterStatisticsWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QRect TaskGraphRect = geometry();
|
||||
maxWidth = TaskGraphRect.width();
|
||||
maxHeight = TaskGraphRect.height() ;
|
||||
|
||||
QWidget::resizeEvent(event);
|
||||
update();
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/****************************************************************
|
||||
* RetroShare is distributed under the following license:
|
||||
*
|
||||
* Copyright (C) 20011, RetroShare Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
****************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QPoint>
|
||||
#include <retroshare/rsturtle.h>
|
||||
#include "ui_TurtleRouterStatistics.h"
|
||||
#include "RsAutoUpdatePage.h"
|
||||
|
||||
class TurtleRouterStatisticsWidget ;
|
||||
|
||||
class TurtleRouterStatistics: public RsAutoUpdatePage, public Ui::TurtleRouterStatistics
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TurtleRouterStatistics(QWidget *parent = NULL) ;
|
||||
~TurtleRouterStatistics();
|
||||
|
||||
// Cache for peer names.
|
||||
static QString getPeerName(const RsPeerId& peer_id) ;
|
||||
|
||||
void setTurtleRouter(const RsTurtle *turtle) { _turtle = turtle ; }
|
||||
|
||||
private:
|
||||
|
||||
virtual void updateDisplay() ;
|
||||
|
||||
TurtleRouterStatisticsWidget *_tst_CW ;
|
||||
const RsTurtle *_turtle ;
|
||||
} ;
|
||||
|
||||
class TurtleRouterStatisticsWidget: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TurtleRouterStatisticsWidget(QWidget *parent = NULL) ;
|
||||
|
||||
virtual void paintEvent(QPaintEvent *event) ;
|
||||
virtual void resizeEvent(QResizeEvent *event);
|
||||
|
||||
void updateTunnelStatistics( const std::vector<std::vector<std::basic_string<char> > >&,
|
||||
const std::vector<std::vector<std::basic_string<char> > >&,
|
||||
const std::vector<TurtleRequestDisplayInfo >&,
|
||||
const std::vector<TurtleRequestDisplayInfo >&,
|
||||
const RsTurtle *turtle) ;
|
||||
|
||||
private:
|
||||
static QString speedString(float f) ;
|
||||
|
||||
QPixmap pixmap ;
|
||||
int maxWidth,maxHeight ;
|
||||
};
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TurtleRouterStatistics</class>
|
||||
<widget class="QWidget" name="TurtleRouterStatistics">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>611</width>
|
||||
<height>408</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Router Statistics</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/images/rstray3.png</normaloff>:/images/rstray3.png</iconset>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QScrollArea" name="_tunnel_statistics_F">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>593</width>
|
||||
<height>390</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
19
libretroshare/src/tests/network_simulator/gui/gui.pro
Normal file
19
libretroshare/src/tests/network_simulator/gui/gui.pro
Normal file
|
@ -0,0 +1,19 @@
|
|||
TEMPLATE = app
|
||||
|
||||
CONFIG *= qt qglviewer
|
||||
QT *= xml opengl
|
||||
|
||||
INCLUDEPATH *= ../.. ..
|
||||
|
||||
TARGET = NetworkSim
|
||||
DESTDIR = bin
|
||||
|
||||
SOURCES = main.cpp NetworkViewer.cpp NetworkSimulatorGUI.cpp \
|
||||
TurtleRouterStatistics.cpp RsAutoUpdatePage.cpp
|
||||
|
||||
HEADERS = NetworkViewer.h NetworkSimulatorGUI.h \
|
||||
TurtleRouterStatistics.h RsAutoUpdatePage.h
|
||||
|
||||
FORMS = NetworkSimulatorGUI.ui TurtleRouterStatistics.ui
|
||||
|
||||
LIBS *= ../../../lib/libretroshare.a ../../../../../libbitdht/src/lib/libbitdht.a ../../../../../../lib/sqlcipher/.libs/libsqlcipher.a ../../../../../openpgpsdk/src/lib/libops.a -lgnome-keyring -lupnp -lssl -lcrypto -lbz2 -lixml
|
58
libretroshare/src/tests/network_simulator/gui/main.cpp
Normal file
58
libretroshare/src/tests/network_simulator/gui/main.cpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
#include <fenv.h>
|
||||
|
||||
#include "Network.h"
|
||||
#include "NetworkSimulatorGUI.h"
|
||||
#include "MonitoredRsPeers.h"
|
||||
#include <QApplication>
|
||||
#include <util/argstream.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
feenableexcept(FE_INVALID) ;
|
||||
feenableexcept(FE_DIVBYZERO) ;
|
||||
|
||||
#ifndef DEBUG
|
||||
try
|
||||
{
|
||||
#endif
|
||||
argstream as(argc,argv) ;
|
||||
bool show_gui = false;
|
||||
int nb_nodes = 20 ;
|
||||
float connexion_probability = 0.2 ;
|
||||
|
||||
as >> option('i',"gui",show_gui,"show gui (vs. do the pipeline automatically)")
|
||||
>> parameter('n',"nodes",nb_nodes,"number of nodes in the network",false)
|
||||
>> parameter('p',"connexion probability",connexion_probability,"probability that two nodes are connected (exponential law)",false)
|
||||
>> help() ;
|
||||
|
||||
as.defaultErrorHandling() ;
|
||||
|
||||
// 2 - call the full pipeline
|
||||
|
||||
Network network ;
|
||||
|
||||
network.initRandom(nb_nodes,connexion_probability) ;
|
||||
|
||||
rsPeers = new MonitoredRsPeers(network) ;
|
||||
|
||||
if(show_gui)
|
||||
{
|
||||
QApplication app(argc,argv) ;
|
||||
|
||||
NetworkSimulatorGUI pgui(network);
|
||||
pgui.show() ;
|
||||
|
||||
return app.exec() ;
|
||||
}
|
||||
|
||||
return 0 ;
|
||||
#ifndef DEBUG
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
std::cerr << "Unhandled exception: " << e.what() << std::endl;
|
||||
return 1 ;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue