/src/qt/trafficgraphwidget.cpp

https://gitlab.com/Ltaimao/bitcoin · C++ · 175 lines · 143 code · 25 blank · 7 comment · 17 complexity · 39ac9ca3c1cf900d087486efd8d2d998 MD5 · raw file

  1. // Copyright (c) 2011-2013 The Bitcoin developers
  2. // Distributed under the MIT/X11 software license, see the accompanying
  3. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4. #include "trafficgraphwidget.h"
  5. #include "clientmodel.h"
  6. #include <QPainter>
  7. #include <QColor>
  8. #include <QTimer>
  9. #include <cmath>
  10. #define DESIRED_SAMPLES 800
  11. #define XMARGIN 10
  12. #define YMARGIN 10
  13. TrafficGraphWidget::TrafficGraphWidget(QWidget *parent) :
  14. QWidget(parent),
  15. timer(0),
  16. fMax(0.0f),
  17. nMins(0),
  18. vSamplesIn(),
  19. vSamplesOut(),
  20. nLastBytesIn(0),
  21. nLastBytesOut(0),
  22. clientModel(0)
  23. {
  24. timer = new QTimer(this);
  25. connect(timer, SIGNAL(timeout()), SLOT(updateRates()));
  26. }
  27. void TrafficGraphWidget::setClientModel(ClientModel *model)
  28. {
  29. clientModel = model;
  30. if(model) {
  31. nLastBytesIn = model->getTotalBytesRecv();
  32. nLastBytesOut = model->getTotalBytesSent();
  33. }
  34. }
  35. int TrafficGraphWidget::getGraphRangeMins() const
  36. {
  37. return nMins;
  38. }
  39. void TrafficGraphWidget::paintPath(QPainterPath &path, QQueue<float> &samples)
  40. {
  41. int h = height() - YMARGIN * 2, w = width() - XMARGIN * 2;
  42. int sampleCount = samples.size(), x = XMARGIN + w, y;
  43. if(sampleCount > 0) {
  44. path.moveTo(x, YMARGIN + h);
  45. for(int i = 0; i < sampleCount; ++i) {
  46. x = XMARGIN + w - w * i / DESIRED_SAMPLES;
  47. y = YMARGIN + h - (int)(h * samples.at(i) / fMax);
  48. path.lineTo(x, y);
  49. }
  50. path.lineTo(x, YMARGIN + h);
  51. }
  52. }
  53. void TrafficGraphWidget::paintEvent(QPaintEvent *)
  54. {
  55. QPainter painter(this);
  56. painter.fillRect(rect(), Qt::black);
  57. if(fMax <= 0.0f) return;
  58. QColor axisCol(Qt::gray);
  59. int h = height() - YMARGIN * 2;
  60. painter.setPen(axisCol);
  61. painter.drawLine(XMARGIN, YMARGIN + h, width() - XMARGIN, YMARGIN + h);
  62. // decide what order of magnitude we are
  63. int base = floor(log10(fMax));
  64. float val = pow(10.0f, base);
  65. const QString units = tr("KB/s");
  66. const float yMarginText = 2.0;
  67. // draw lines
  68. painter.setPen(axisCol);
  69. painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax-yMarginText, QString("%1 %2").arg(val).arg(units));
  70. for(float y = val; y < fMax; y += val) {
  71. int yy = YMARGIN + h - h * y / fMax;
  72. painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
  73. }
  74. // if we drew 3 or fewer lines, break them up at the next lower order of magnitude
  75. if(fMax / val <= 3.0f) {
  76. axisCol = axisCol.darker();
  77. val = pow(10.0f, base - 1);
  78. painter.setPen(axisCol);
  79. painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax-yMarginText, QString("%1 %2").arg(val).arg(units));
  80. int count = 1;
  81. for(float y = val; y < fMax; y += val, count++) {
  82. // don't overwrite lines drawn above
  83. if(count % 10 == 0)
  84. continue;
  85. int yy = YMARGIN + h - h * y / fMax;
  86. painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
  87. }
  88. }
  89. if(!vSamplesIn.empty()) {
  90. QPainterPath p;
  91. paintPath(p, vSamplesIn);
  92. painter.fillPath(p, QColor(0, 255, 0, 128));
  93. painter.setPen(Qt::green);
  94. painter.drawPath(p);
  95. }
  96. if(!vSamplesOut.empty()) {
  97. QPainterPath p;
  98. paintPath(p, vSamplesOut);
  99. painter.fillPath(p, QColor(255, 0, 0, 128));
  100. painter.setPen(Qt::red);
  101. painter.drawPath(p);
  102. }
  103. }
  104. void TrafficGraphWidget::updateRates()
  105. {
  106. if(!clientModel) return;
  107. quint64 bytesIn = clientModel->getTotalBytesRecv(),
  108. bytesOut = clientModel->getTotalBytesSent();
  109. float inRate = (bytesIn - nLastBytesIn) / 1024.0f * 1000 / timer->interval();
  110. float outRate = (bytesOut - nLastBytesOut) / 1024.0f * 1000 / timer->interval();
  111. vSamplesIn.push_front(inRate);
  112. vSamplesOut.push_front(outRate);
  113. nLastBytesIn = bytesIn;
  114. nLastBytesOut = bytesOut;
  115. while(vSamplesIn.size() > DESIRED_SAMPLES) {
  116. vSamplesIn.pop_back();
  117. }
  118. while(vSamplesOut.size() > DESIRED_SAMPLES) {
  119. vSamplesOut.pop_back();
  120. }
  121. float tmax = 0.0f;
  122. foreach(float f, vSamplesIn) {
  123. if(f > tmax) tmax = f;
  124. }
  125. foreach(float f, vSamplesOut) {
  126. if(f > tmax) tmax = f;
  127. }
  128. fMax = tmax;
  129. update();
  130. }
  131. void TrafficGraphWidget::setGraphRangeMins(int mins)
  132. {
  133. nMins = mins;
  134. int msecsPerSample = nMins * 60 * 1000 / DESIRED_SAMPLES;
  135. timer->stop();
  136. timer->setInterval(msecsPerSample);
  137. clear();
  138. }
  139. void TrafficGraphWidget::clear()
  140. {
  141. timer->stop();
  142. vSamplesOut.clear();
  143. vSamplesIn.clear();
  144. fMax = 0.0f;
  145. if(clientModel) {
  146. nLastBytesIn = clientModel->getTotalBytesRecv();
  147. nLastBytesOut = clientModel->getTotalBytesSent();
  148. }
  149. timer->start();
  150. }