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