Bitcoin Core 28.99.0
P2P Digital Currency
trafficgraphwidget.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2022 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <interfaces/node.h>
7#include <qt/clientmodel.h>
8
9#include <QPainter>
10#include <QPainterPath>
11#include <QColor>
12#include <QTimer>
13
14#include <chrono>
15#include <cmath>
16
17#define DESIRED_SAMPLES 800
18
19#define XMARGIN 10
20#define YMARGIN 10
21
23 : QWidget(parent),
24 vSamplesIn(),
25 vSamplesOut()
26{
27 timer = new QTimer(this);
28 connect(timer, &QTimer::timeout, this, &TrafficGraphWidget::updateRates);
29}
30
32{
33 clientModel = model;
34 if(model) {
37 }
38}
39
40std::chrono::minutes TrafficGraphWidget::getGraphRange() const { return m_range; }
41
42void TrafficGraphWidget::paintPath(QPainterPath &path, QQueue<float> &samples)
43{
44 int sampleCount = samples.size();
45 if(sampleCount > 0) {
46 int h = height() - YMARGIN * 2, w = width() - XMARGIN * 2;
47 int x = XMARGIN + w;
48 path.moveTo(x, YMARGIN + h);
49 for(int i = 0; i < sampleCount; ++i) {
50 x = XMARGIN + w - w * i / DESIRED_SAMPLES;
51 int y = YMARGIN + h - (int)(h * samples.at(i) / fMax);
52 path.lineTo(x, y);
53 }
54 path.lineTo(x, YMARGIN + h);
55 }
56}
57
59{
60 QPainter painter(this);
61 painter.fillRect(rect(), Qt::black);
62
63 if(fMax <= 0.0f) return;
64
65 QColor axisCol(Qt::gray);
66 int h = height() - YMARGIN * 2;
67 painter.setPen(axisCol);
68 painter.drawLine(XMARGIN, YMARGIN + h, width() - XMARGIN, YMARGIN + h);
69
70 // decide what order of magnitude we are
71 int base = std::floor(std::log10(fMax));
72 float val = std::pow(10.0f, base);
73
74 const QString units = tr("kB/s");
75 const float yMarginText = 2.0;
76
77 // draw lines
78 painter.setPen(axisCol);
79 painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax-yMarginText, QString("%1 %2").arg(val).arg(units));
80 for(float y = val; y < fMax; y += val) {
81 int yy = YMARGIN + h - h * y / fMax;
82 painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
83 }
84 // if we drew 3 or fewer lines, break them up at the next lower order of magnitude
85 if(fMax / val <= 3.0f) {
86 axisCol = axisCol.darker();
87 val = pow(10.0f, base - 1);
88 painter.setPen(axisCol);
89 painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax-yMarginText, QString("%1 %2").arg(val).arg(units));
90 int count = 1;
91 for(float y = val; y < fMax; y += val, count++) {
92 // don't overwrite lines drawn above
93 if(count % 10 == 0)
94 continue;
95 int yy = YMARGIN + h - h * y / fMax;
96 painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
97 }
98 }
99
100 painter.setRenderHint(QPainter::Antialiasing);
101 if(!vSamplesIn.empty()) {
102 QPainterPath p;
104 painter.fillPath(p, QColor(0, 255, 0, 128));
105 painter.setPen(Qt::green);
106 painter.drawPath(p);
107 }
108 if(!vSamplesOut.empty()) {
109 QPainterPath p;
111 painter.fillPath(p, QColor(255, 0, 0, 128));
112 painter.setPen(Qt::red);
113 painter.drawPath(p);
114 }
115}
116
118{
119 if(!clientModel) return;
120
121 quint64 bytesIn = clientModel->node().getTotalBytesRecv(),
122 bytesOut = clientModel->node().getTotalBytesSent();
123 float in_rate_kilobytes_per_sec = static_cast<float>(bytesIn - nLastBytesIn) / timer->interval();
124 float out_rate_kilobytes_per_sec = static_cast<float>(bytesOut - nLastBytesOut) / timer->interval();
125 vSamplesIn.push_front(in_rate_kilobytes_per_sec);
126 vSamplesOut.push_front(out_rate_kilobytes_per_sec);
127 nLastBytesIn = bytesIn;
128 nLastBytesOut = bytesOut;
129
130 while(vSamplesIn.size() > DESIRED_SAMPLES) {
131 vSamplesIn.pop_back();
132 }
133 while(vSamplesOut.size() > DESIRED_SAMPLES) {
134 vSamplesOut.pop_back();
135 }
136
137 float tmax = 0.0f;
138 for (const float f : vSamplesIn) {
139 if(f > tmax) tmax = f;
140 }
141 for (const float f : vSamplesOut) {
142 if(f > tmax) tmax = f;
143 }
144 fMax = tmax;
145 update();
146}
147
148void TrafficGraphWidget::setGraphRange(std::chrono::minutes new_range)
149{
150 m_range = new_range;
151 const auto msecs_per_sample{std::chrono::duration_cast<std::chrono::milliseconds>(m_range) / DESIRED_SAMPLES};
152 timer->stop();
153 timer->setInterval(msecs_per_sample);
154
155 clear();
156}
157
159{
160 timer->stop();
161
162 vSamplesOut.clear();
163 vSamplesIn.clear();
164 fMax = 0.0f;
165
166 if(clientModel) {
169 }
170 timer->start();
171}
Model for Bitcoin network client.
Definition: clientmodel.h:57
interfaces::Node & node() const
Definition: clientmodel.h:66
std::chrono::minutes m_range
void paintEvent(QPaintEvent *) override
ClientModel * clientModel
TrafficGraphWidget(QWidget *parent=nullptr)
std::chrono::minutes getGraphRange() const
void setClientModel(ClientModel *model)
QQueue< float > vSamplesOut
void paintPath(QPainterPath &path, QQueue< float > &samples)
void setGraphRange(std::chrono::minutes new_range)
QQueue< float > vSamplesIn
virtual int64_t getTotalBytesRecv()=0
Get total bytes recv.
virtual int64_t getTotalBytesSent()=0
Get total bytes sent.
static int count
#define YMARGIN
#define XMARGIN
#define DESIRED_SAMPLES