2019-12-30 10:39:22 +01:00
|
|
|
// Copyright (c) 2011-2019 The Bitcoin Core developers
|
2014-12-13 05:09:33 +01:00
|
|
|
// Distributed under the MIT software license, see the accompanying
|
2013-11-04 16:20:43 +01:00
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
2018-04-07 09:42:02 +02:00
|
|
|
#include <interfaces/node.h>
|
2017-11-10 01:57:53 +01:00
|
|
|
#include <qt/trafficgraphwidget.h>
|
|
|
|
#include <qt/clientmodel.h>
|
2013-08-22 18:09:32 +02:00
|
|
|
|
|
|
|
#include <QPainter>
|
2020-05-28 20:56:47 +02:00
|
|
|
#include <QPainterPath>
|
2013-08-22 18:09:32 +02:00
|
|
|
#include <QColor>
|
|
|
|
#include <QTimer>
|
|
|
|
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
#define DESIRED_SAMPLES 800
|
|
|
|
|
|
|
|
#define XMARGIN 10
|
|
|
|
#define YMARGIN 10
|
|
|
|
|
|
|
|
TrafficGraphWidget::TrafficGraphWidget(QWidget *parent) :
|
|
|
|
QWidget(parent),
|
2018-07-30 12:37:09 +02:00
|
|
|
timer(nullptr),
|
2013-08-22 18:09:32 +02:00
|
|
|
fMax(0.0f),
|
|
|
|
nMins(0),
|
|
|
|
vSamplesIn(),
|
|
|
|
vSamplesOut(),
|
|
|
|
nLastBytesIn(0),
|
|
|
|
nLastBytesOut(0),
|
2018-07-30 12:37:09 +02:00
|
|
|
clientModel(nullptr)
|
2013-08-22 18:09:32 +02:00
|
|
|
{
|
|
|
|
timer = new QTimer(this);
|
2018-06-24 17:18:22 +02:00
|
|
|
connect(timer, &QTimer::timeout, this, &TrafficGraphWidget::updateRates);
|
2013-08-22 18:09:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void TrafficGraphWidget::setClientModel(ClientModel *model)
|
|
|
|
{
|
|
|
|
clientModel = model;
|
|
|
|
if(model) {
|
2017-04-17 21:37:36 +02:00
|
|
|
nLastBytesIn = model->node().getTotalBytesRecv();
|
|
|
|
nLastBytesOut = model->node().getTotalBytesSent();
|
2013-08-22 18:09:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int TrafficGraphWidget::getGraphRangeMins() const
|
|
|
|
{
|
|
|
|
return nMins;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrafficGraphWidget::paintPath(QPainterPath &path, QQueue<float> &samples)
|
|
|
|
{
|
2017-06-04 22:45:22 +02:00
|
|
|
int sampleCount = samples.size();
|
2013-08-22 18:09:32 +02:00
|
|
|
if(sampleCount > 0) {
|
2017-06-04 22:45:22 +02:00
|
|
|
int h = height() - YMARGIN * 2, w = width() - XMARGIN * 2;
|
|
|
|
int x = XMARGIN + w;
|
2013-08-22 18:09:32 +02:00
|
|
|
path.moveTo(x, YMARGIN + h);
|
|
|
|
for(int i = 0; i < sampleCount; ++i) {
|
|
|
|
x = XMARGIN + w - w * i / DESIRED_SAMPLES;
|
2017-06-04 22:45:22 +02:00
|
|
|
int y = YMARGIN + h - (int)(h * samples.at(i) / fMax);
|
2013-08-22 18:09:32 +02:00
|
|
|
path.lineTo(x, y);
|
|
|
|
}
|
|
|
|
path.lineTo(x, YMARGIN + h);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrafficGraphWidget::paintEvent(QPaintEvent *)
|
|
|
|
{
|
|
|
|
QPainter painter(this);
|
|
|
|
painter.fillRect(rect(), Qt::black);
|
|
|
|
|
|
|
|
if(fMax <= 0.0f) return;
|
|
|
|
|
|
|
|
QColor axisCol(Qt::gray);
|
|
|
|
int h = height() - YMARGIN * 2;
|
|
|
|
painter.setPen(axisCol);
|
|
|
|
painter.drawLine(XMARGIN, YMARGIN + h, width() - XMARGIN, YMARGIN + h);
|
|
|
|
|
|
|
|
// decide what order of magnitude we are
|
|
|
|
int base = floor(log10(fMax));
|
|
|
|
float val = pow(10.0f, base);
|
|
|
|
|
2014-11-05 11:39:47 +01:00
|
|
|
const QString units = tr("KB/s");
|
|
|
|
const float yMarginText = 2.0;
|
2018-07-24 17:59:49 +02:00
|
|
|
|
2013-08-22 18:09:32 +02:00
|
|
|
// draw lines
|
|
|
|
painter.setPen(axisCol);
|
2014-11-05 11:39:47 +01:00
|
|
|
painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax-yMarginText, QString("%1 %2").arg(val).arg(units));
|
2013-08-22 18:09:32 +02:00
|
|
|
for(float y = val; y < fMax; y += val) {
|
|
|
|
int yy = YMARGIN + h - h * y / fMax;
|
|
|
|
painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
|
|
|
|
}
|
|
|
|
// if we drew 3 or fewer lines, break them up at the next lower order of magnitude
|
|
|
|
if(fMax / val <= 3.0f) {
|
|
|
|
axisCol = axisCol.darker();
|
|
|
|
val = pow(10.0f, base - 1);
|
|
|
|
painter.setPen(axisCol);
|
2014-11-05 11:39:47 +01:00
|
|
|
painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax-yMarginText, QString("%1 %2").arg(val).arg(units));
|
2013-08-22 18:09:32 +02:00
|
|
|
int count = 1;
|
|
|
|
for(float y = val; y < fMax; y += val, count++) {
|
|
|
|
// don't overwrite lines drawn above
|
|
|
|
if(count % 10 == 0)
|
|
|
|
continue;
|
|
|
|
int yy = YMARGIN + h - h * y / fMax;
|
|
|
|
painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-05 18:43:59 +02:00
|
|
|
painter.setRenderHint(QPainter::Antialiasing);
|
2013-08-22 18:09:32 +02:00
|
|
|
if(!vSamplesIn.empty()) {
|
|
|
|
QPainterPath p;
|
|
|
|
paintPath(p, vSamplesIn);
|
|
|
|
painter.fillPath(p, QColor(0, 255, 0, 128));
|
|
|
|
painter.setPen(Qt::green);
|
|
|
|
painter.drawPath(p);
|
|
|
|
}
|
|
|
|
if(!vSamplesOut.empty()) {
|
|
|
|
QPainterPath p;
|
|
|
|
paintPath(p, vSamplesOut);
|
|
|
|
painter.fillPath(p, QColor(255, 0, 0, 128));
|
|
|
|
painter.setPen(Qt::red);
|
|
|
|
painter.drawPath(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrafficGraphWidget::updateRates()
|
|
|
|
{
|
|
|
|
if(!clientModel) return;
|
|
|
|
|
2017-04-17 21:37:36 +02:00
|
|
|
quint64 bytesIn = clientModel->node().getTotalBytesRecv(),
|
|
|
|
bytesOut = clientModel->node().getTotalBytesSent();
|
2013-08-22 18:09:32 +02:00
|
|
|
float inRate = (bytesIn - nLastBytesIn) / 1024.0f * 1000 / timer->interval();
|
|
|
|
float outRate = (bytesOut - nLastBytesOut) / 1024.0f * 1000 / timer->interval();
|
|
|
|
vSamplesIn.push_front(inRate);
|
|
|
|
vSamplesOut.push_front(outRate);
|
|
|
|
nLastBytesIn = bytesIn;
|
|
|
|
nLastBytesOut = bytesOut;
|
|
|
|
|
|
|
|
while(vSamplesIn.size() > DESIRED_SAMPLES) {
|
|
|
|
vSamplesIn.pop_back();
|
|
|
|
}
|
|
|
|
while(vSamplesOut.size() > DESIRED_SAMPLES) {
|
|
|
|
vSamplesOut.pop_back();
|
|
|
|
}
|
|
|
|
|
|
|
|
float tmax = 0.0f;
|
2018-06-18 07:58:28 +02:00
|
|
|
for (const float f : vSamplesIn) {
|
2013-08-22 18:09:32 +02:00
|
|
|
if(f > tmax) tmax = f;
|
|
|
|
}
|
2018-06-18 07:58:28 +02:00
|
|
|
for (const float f : vSamplesOut) {
|
2013-08-22 18:09:32 +02:00
|
|
|
if(f > tmax) tmax = f;
|
|
|
|
}
|
|
|
|
fMax = tmax;
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrafficGraphWidget::setGraphRangeMins(int mins)
|
|
|
|
{
|
|
|
|
nMins = mins;
|
|
|
|
int msecsPerSample = nMins * 60 * 1000 / DESIRED_SAMPLES;
|
|
|
|
timer->stop();
|
|
|
|
timer->setInterval(msecsPerSample);
|
|
|
|
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrafficGraphWidget::clear()
|
|
|
|
{
|
|
|
|
timer->stop();
|
|
|
|
|
|
|
|
vSamplesOut.clear();
|
|
|
|
vSamplesIn.clear();
|
|
|
|
fMax = 0.0f;
|
|
|
|
|
|
|
|
if(clientModel) {
|
2017-04-17 21:37:36 +02:00
|
|
|
nLastBytesIn = clientModel->node().getTotalBytesRecv();
|
|
|
|
nLastBytesOut = clientModel->node().getTotalBytesSent();
|
2013-08-22 18:09:32 +02:00
|
|
|
}
|
|
|
|
timer->start();
|
|
|
|
}
|