[tor-commits] [vidalia-plugins/master] Add bandwidth graph implementation as a plugin
chiiph at torproject.org
chiiph at torproject.org
Fri Jul 20 23:46:40 UTC 2012
commit f64298fbeb7cc576f43bb00f3c0b6715dc63d385
Author: Tomás Touceda <chiiph at torproject.org>
Date: Fri Jul 20 15:14:26 2012 -0300
Add bandwidth graph implementation as a plugin
---
bwgraph/bwgraph.js | 149 +++++++++++++++
bwgraph/bwgraph.ui | 485 +++++++++++++++++++++++++++++++++++++++++++++++++
bwgraph/graphframe.js | 297 ++++++++++++++++++++++++++++++
bwgraph/info.xml | 11 +
4 files changed, 942 insertions(+), 0 deletions(-)
diff --git a/bwgraph/bwgraph.js b/bwgraph/bwgraph.js
new file mode 100644
index 0000000..565d6a0
--- /dev/null
+++ b/bwgraph/bwgraph.js
@@ -0,0 +1,149 @@
+importExtension("qt");
+importExtension("qt.core");
+importExtension("qt.gui");
+importExtension("qt.uitools");
+
+var bwgraph = {
+ From: "From",
+ Sent: "Sent",
+ Recv: "Recv",
+
+ SETTING_DORECV: "DoRecv",
+ SETTING_DOSEND: "DoSend",
+ SETTING_ALWAYS_ON_TOP: "AlwaysOnTop",
+ SETTING_STYLE: "GraphStyle",
+
+ start: function() {
+ vdebug("Bwhistory at start");
+ torControl["bandwidthUpdate(quint64, quint64)"].connect(this, this.saveBandwidth);
+ this.createGUI();
+ this.loadSettings();
+
+ this.recv = parseInt(this.tab.getSetting(this.Sent, 0));
+ this.sent = parseInt(this.tab.getSetting(this.Recv, 0));
+ this.from = this.tab.getSetting(this.From, "");
+
+ if(this.from.length == 0)
+ this.from = QDateTime.currentDateTime().toString();
+ },
+
+ saveBandwidth: function(recv, sent) {
+ this.recv += recv;
+ this.sent += sent;
+
+ this.tab.saveSetting(this.Recv, this.recv.toString());
+ this.tab.saveSetting(this.Sent, this.sent.toString());
+ this.tab.saveSetting(this.From, this.from);
+
+ this.lblFrom.text = this.from;
+ this.lblSent.text = (this.sent/1024/1024).toFixed(4).toString() + " <b>Mb/s</b>";
+ this.lblRecv.text = (this.recv/1024/1024).toFixed(4).toString() + " <b>Mb/s</b>";
+ this.frame.addPoints(recv/1024.0, sent/1024.0);
+ },
+
+ resetCounters: function() {
+ this.recv = 0;
+ this.sent = 0;
+ this.from = QDateTime.currentDateTime().toString();
+ this.saveBandwidth(0,0);
+ },
+
+ createGUI: function() {
+ this.tab = new VidaliaTab("Bandwidth Graph", "BandwidthGraph");
+
+ var file = new QFile(pluginPath+"/bwgraph/bwgraph.ui");
+ var loader = new QUiLoader(this.tab);
+ file.open(QIODevice.ReadOnly);
+ this.widget = loader.load(file);
+ var layout = new QVBoxLayout(this.tab);
+ vdebug(layout);
+ layout.sizeConstraint = QLayout.SetMinAndMaxSize;
+ layout.addWidget(this.widget, 100, Qt.AlignCenter);
+ this.tab.setLayout(layout);
+ file.close();
+
+ this.grpBandwidth = this.widget.children()[findWidget(this.widget, "grpBandwidth")];
+
+ var graphFrame = this.widget.children()[findWidget(this.widget, "graphFrame")];
+ var graphLayout = graphFrame.children()[findWidget(graphFrame, "graphLayout")];
+
+ this.frame = new GraphFrame();
+ graphLayout.addWidget(this.frame, 1000, Qt.AlignLeft);
+
+ this.btnHistory = this.widget.children()[findWidget(this.widget, "btnHistory")];
+ this.btnSettings = this.widget.children()[findWidget(this.widget, "btnSettings")];
+ this.btnReset = this.widget.children()[findWidget(this.widget, "btnReset")];
+
+ this.frmSettings = this.widget.children()[findWidget(this.widget, "frmSettings")];
+ this.btnSaveSettings = this.frmSettings.children()[findWidget(this.frmSettings, "btnSaveSettings")];
+ this.btnCancelSettings = this.frmSettings.children()[findWidget(this.frmSettings, "btnCancelSettings")];
+ this.cmbGraphStyle = this.frmSettings.children()[findWidget(this.frmSettings, "cmbGraphStyle")];
+ this.chkReceiveRate = this.frmSettings.children()[findWidget(this.frmSettings, "chkReceiveRate")];
+ this.chkSendRate = this.frmSettings.children()[findWidget(this.frmSettings, "chkSendRate")];
+ this.chkAlwaysOnTop = this.frmSettings.children()[findWidget(this.frmSettings, "chkAlwaysOnTop")];
+
+ this.lblFrom = this.grpBandwidth.children()[findWidget(this.grpBandwidth, "lblFrom")];
+ this.lblSent = this.grpBandwidth.children()[findWidget(this.grpBandwidth, "lblSent")];
+ this.lblRecv = this.grpBandwidth.children()[findWidget(this.grpBandwidth, "lblRecv")];
+ this.btnResetHistory = this.grpBandwidth.children()[findWidget(this.grpBandwidth, "btnResetHistory")];
+
+ this.lblFrom.text = this.from;
+ this.lblSent.text = (this.sent/1024/1024).toFixed(4).toString() + " <b>Mb/s</b>";
+ this.lblRecv.text = (this.recv/1024/1024).toFixed(4).toString() + " <b>Mb/s</b>";
+
+ this.btnResetHistory["clicked()"].connect(this, this.resetCounters);
+
+ this.btnHistory["toggled(bool)"].connect(this, this.toggleHistory);
+ this.btnSettings["toggled(bool)"].connect(this, this.toggleSettings);
+ this.toggleHistory(false);
+ this.toggleSettings(false);
+
+ this.btnReset["clicked()"].connect(this.frame, this.frame.resetGraph);
+ this.btnSaveSettings["clicked()"].connect(this, this.saveSettings);
+ },
+
+ saveSettings: function() {
+ vdebug("Bwhistory at saveSettings");
+ this.tab.saveSetting(this.SETTING_DORECV, (this.chkReceiveRate.checkState() == Qt.Checked) ? "true" : "false");
+ this.tab.saveSetting(this.SETTING_DOSEND, (this.chkSendRate.checkState() == Qt.Checked) ? "true" : "false");
+ this.tab.saveSetting(this.SETTING_STYLE, this.cmbGraphStyle.currentIndex);
+ this.tab.saveSetting(this.SETTING_ALWAYS_ON_TOP, (this.chkAlwaysOnTop.checkState() == Qt.Checked) ? "true" : "false");
+ this.frame.graphStyle = this.cmbGraphStyle.currentIndex;
+ this.frame.showRecv = (this.chkReceiveRate.checkState() == Qt.Checked);
+ this.frame.showSend = (this.chkSendRate.checkState() == Qt.Checked);
+ this.toggleSettings(false);
+ },
+
+ loadSettings: function() {
+ vdebug("Bwhistory at loadSettings");
+ var dorecv = this.tab.getSetting(this.SETTING_DORECV, "true") != "false";
+ var dosend = this.tab.getSetting(this.SETTING_DOSEND, "true") != "false";
+ this.frame.graphStyle = this.tab.getSetting(this.SETTING_STYLE, 0);
+ var alwaysontop = this.tab.getSetting(this.SETTING_ALWAYS_ON_TOP, "false") != "false";
+
+ this.chkReceiveRate.setCheckState(dorecv ? Qt.Checked : Qt.Unchecked);
+ this.chkSendRate.setCheckState(dosend ? Qt.Checked : Qt.Unchecked);
+ this.chkAlwaysOnTop.setCheckState(alwaysontop ? Qt.Checked : Qt.Unchecked);
+ this.cmbGraphStyle.currentIndex = this.frame.graphStyle;
+ this.frame.showRecv = dorecv;
+ this.frame.showSend = dosend;
+ },
+
+ buildGUI: function() {
+ vdebug("Bwhistory at buildGUI");
+ return this.tab;
+ },
+
+ toggleHistory: function(toggle) {
+ this.grpBandwidth.setVisible(toggle);
+ },
+
+ toggleSettings: function(toggle) {
+ this.frmSettings.setVisible(toggle);
+ },
+
+ stop: function() {
+ vdebug("Bwhistory at stop");
+ this.saveBandwidth(0,0);
+ },
+};
diff --git a/bwgraph/bwgraph.ui b/bwgraph/bwgraph.ui
new file mode 100644
index 0000000..967ceda
--- /dev/null
+++ b/bwgraph/bwgraph.ui
@@ -0,0 +1,485 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>548</width>
+ <height>499</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="3" column="0">
+ <widget class="QGroupBox" name="grpBandwidth">
+ <property name="title">
+ <string>Bandwidth history</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="2" column="1" colspan="2">
+ <widget class="QLabel" name="lblSent">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="lblSentLabel">
+ <property name="text">
+ <string><b>Data Sent:</b></string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" colspan="2">
+ <widget class="QLabel" name="lblRecv">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="lblFromLabel">
+ <property name="text">
+ <string><b>Since:</b></string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="lblSentLabel_2">
+ <property name="text">
+ <string><b>Data Recieved:</b></string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="2">
+ <widget class="QPushButton" name="btnResetHistory">
+ <property name="text">
+ <string>Reset history</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" colspan="2">
+ <widget class="QLabel" name="lblFrom">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="3">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Maximum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>1000</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="5" column="0" colspan="2">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QFrame" name="frmSettings">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <property name="horizontalSpacing">
+ <number>10</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>5</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="chkReceiveRate">
+ <property name="contextMenuPolicy">
+ <enum>Qt::NoContextMenu</enum>
+ </property>
+ <property name="toolTip">
+ <string/>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::RightToLeft</enum>
+ </property>
+ <property name="text">
+ <string>Receive Rate</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="chkSendRate">
+ <property name="contextMenuPolicy">
+ <enum>Qt::NoContextMenu</enum>
+ </property>
+ <property name="toolTip">
+ <string/>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::RightToLeft</enum>
+ </property>
+ <property name="text">
+ <string>Send Rate</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QCheckBox" name="chkAlwaysOnTop">
+ <property name="layoutDirection">
+ <enum>Qt::RightToLeft</enum>
+ </property>
+ <property name="text">
+ <string>Always on Top</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="3">
+ <widget class="QLabel" name="lblGraphStyle">
+ <property name="text">
+ <string>Style</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="4">
+ <widget class="QComboBox" name="cmbGraphStyle">
+ <item>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../../vidalia/src/vidalia/res/vidalia.qrc">
+ <normaloff>:/images/16x16/graph-line.png</normaloff>:/images/16x16/graph-line.png</iconset>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../../vidalia/src/vidalia/res/vidalia.qrc">
+ <normaloff>:/images/16x16/graph-area.png</normaloff>:/images/16x16/graph-area.png</iconset>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="3" column="6">
+ <widget class="QPushButton" name="btnCancelSettings">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="6">
+ <widget class="QPushButton" name="btnSaveSettings">
+ <property name="text">
+ <string>Save</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="5">
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1" rowspan="2" colspan="4">
+ <widget class="QFrame" name="frmOpacity">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <layout class="QGridLayout" name="gridLayout3">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>-1</number>
+ </property>
+ <item row="0" column="0" colspan="4">
+ <widget class="QSlider" name="sldrOpacity">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="contextMenuPolicy">
+ <enum>Qt::NoContextMenu</enum>
+ </property>
+ <property name="toolTip">
+ <string>Changes the transparency of the Bandwidth Graph</string>
+ </property>
+ <property name="minimum">
+ <number>30</number>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="sliderPosition">
+ <number>100</number>
+ </property>
+ <property name="tracking">
+ <bool>false</bool>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="invertedAppearance">
+ <bool>false</bool>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::NoTicks</enum>
+ </property>
+ <property name="tickInterval">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="lblPercentOpacity">
+ <property name="minimumSize">
+ <size>
+ <width>25</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="contextMenuPolicy">
+ <enum>Qt::NoContextMenu</enum>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::RightToLeft</enum>
+ </property>
+ <property name="text">
+ <string>100</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="label">
+ <property name="font">
+ <font>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ <property name="contextMenuPolicy">
+ <enum>Qt::NoContextMenu</enum>
+ </property>
+ <property name="text">
+ <string>% Opaque</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0">
+ <spacer name="horizontalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QFrame" name="graphFrame">
+ <property name="minimumSize">
+ <size>
+ <width>128</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QVBoxLayout" name="graphLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>10000</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QPushButton" name="btnHistory">
+ <property name="text">
+ <string>Show History</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnSettings">
+ <property name="text">
+ <string>Show Settings</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnReset">
+ <property name="text">
+ <string>Reset</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="1">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>700</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../../vidalia/src/vidalia/res/vidalia.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/bwgraph/graphframe.js b/bwgraph/graphframe.js
new file mode 100644
index 0000000..c9e8c14
--- /dev/null
+++ b/bwgraph/graphframe.js
@@ -0,0 +1,297 @@
+importExtension("qt");
+importExtension("qt.core");
+importExtension("qt.gui");
+
+HOR_SPC = 2; /** Space between data points */
+MIN_SCALE = 10; /** 10 kB/s is the minimum scale */
+SCROLL_STEP = 4; /** Horizontal change on graph update */
+
+BACK_COLOR = new QColor(Qt.black);
+SCALE_COLOR = new QColor(Qt.green);
+GRID_COLOR = new QColor(Qt.darkGreen);
+RECV_COLOR = new QColor(Qt.cyan);
+SEND_COLOR = new QColor(Qt.yellow);
+
+FONT_SIZE = 11;
+
+SolidLine = 0;
+AreaGraph = 1;
+
+// TODO: support translations
+function tr(s) { return s; }
+
+function GraphFrame(parent)
+{
+ QFrame.call(this, parent);
+
+ /* Create Graph Frame related objects */
+ this.recvData = [];
+ this.sendData = [];
+ this.painter = new QPainter();
+ this.graphStyle = AreaGraph;
+
+ /* Initialize graph values */
+ this.recvData.unshift(0);
+ this.sendData.unshift(0);
+ this.maxPoints = this.getNumPoints();
+ this.maxPosition = 0;
+ this.showRecv = true;
+ this.showSend = true;
+ this.maxValue = MIN_SCALE;
+ this.scaleWidth = 0;
+ this.totalSend = 0;
+ this.totalRecv = 0;
+}
+
+GraphFrame.prototype = new QFrame();
+
+/** Gets the width of the desktop, which is the maximum number of points
+ * we can plot in the graph. */
+GraphFrame.prototype.getNumPoints = function()
+{
+ return this.size - this.scaleWidth;
+}
+
+/** Adds new data points to the graph. */
+GraphFrame.prototype.addPoints = function(recv, send)
+{
+ /* If maximum number of points plotted, remove oldest */
+ if (this.sendData.length == this.maxPoints) {
+ this.sendData.pop();
+ this.recvData.pop();
+ }
+
+ /* Update the displayed maximum */
+ if (this.maxPosition >= this.maxPoints) {
+ this.maxValue = MIN_SCALE;
+ for(send in this.sendData) {
+ if(send > this.maxValue)
+ this.maxValue = send;
+ }
+ for(recv in this.recvData) {
+ if(recv > this.maxValue)
+ this.maxValue = recv;
+ }
+ this.maxPosition = 0;
+ }
+
+ /* Add the points to their respective lists */
+ this.sendData.unshift(send);
+ this.recvData.unshift(recv);
+
+ /* Add to the total counters */
+ this.totalSend += send;
+ this.totalRecv += recv;
+
+ var maxUpdated = false;
+ /* Check for a new maximum value */
+ if (send > this.maxValue) {
+ this.maxValue = send;
+ maxUpdated = true;
+ }
+
+ if (recv > this.maxValue) {
+ this.maxValue = recv;
+ maxUpdated = true;
+ }
+
+ if (maxUpdated) {
+ this.maxPosition = 0;
+ } else {
+ this.maxPosition++;
+ }
+
+ this.update();
+}
+
+/** Clears the graph. */
+GraphFrame.prototype.resetGraph = function()
+{
+ this.recvData = [];
+ this.sendData = [];
+ this.recvData.unshift(0);
+ this.sendData.unshift(0);
+ this.maxValue = MIN_SCALE;
+ this.totalSend = 0;
+ this.totalRecv = 0;
+ this.update();
+}
+
+/** Toggles display of respective graph lines and counters. */
+GraphFrame.prototype.setShowCounters = function(showRecv, showSend)
+{
+ this.showRecv = showRecv;
+ this.showSend = showSend;
+}
+
+/** Returns a list of points on the bandwidth graph based on the supplied set
+ * of send or receive values. */
+GraphFrame.prototype.pointsFromData = function(list)
+{
+ var points = new Array();
+ var x = this.frameRect.width();
+ var y = this.frameRect.height();
+ var scale = (y - (y/10)) / this.maxValue;
+ var currValue = 0;
+
+ /* Translate all data points to points on the graph frame */
+ points.push(new QPointF(x, y));
+ for (var i = 0; i < list.length; i++) {
+ var item = list[i];
+ currValue = y - (item * scale);
+ if (x - SCROLL_STEP < this.scaleWidth) {
+ points.push(new QPointF(this.scaleWidth, currValue));
+ break;
+ }
+ points.push(new QPointF(x, currValue));
+ x -= SCROLL_STEP;
+ }
+ points.push(new QPointF(this.scaleWidth, y));
+ return points;
+}
+
+/** Returns the width in pixels of <b>label</b> using the current painter's
+ * font. */
+GraphFrame.prototype.labelWidth = function(label)
+{
+ var width = 0;
+ var fm = new QFontMetrics(this.font);
+
+ for (var i = 0; i < label.length; i++)
+ width += fm.charWidth(label, i);
+ return width;
+}
+
+GraphFrame.prototype.resizeEvent = function(ev)
+{
+ this.maxPoints = ev.size().width() - this.scaleWidth;
+ this.maxPoints /= SCROLL_STEP;
+ this.resize(this.parentWidget().size.width(), this.parentWidget().size.height());
+}
+
+GraphFrame.prototype.paintEvent = function(ev)
+{
+ this.painter.begin(this);
+
+ /** Filling */
+ this.painter.setRenderHint(QPainter.Antialiasing);
+ this.painter.setRenderHint(QPainter.TextAntialiasing);
+
+ /* Fill in the background */
+ this.painter.fillRect(this.frameRect, BACK_COLOR);
+
+ /** Paint Scale */
+ var label = new Array();
+ var width = new Array();
+ var top = this.frameRect.y();
+ var bottom = this.frameRect.height();
+ var scaleWidth = 0;
+ var pos = 0;
+ var markStep = this.maxValue * 0.25;
+ var paintStep = (bottom - (bottom/8)) / 4;
+
+ /* Compute each of the y-axis labels */
+ for (var i = 0; i < 4; i++) {
+ pos = bottom - ((i+1) * paintStep);
+ label[i] = (markStep*(i+1)).toFixed(2).toString() + "KB/s";
+ width[i] = this.labelWidth(label[i]);
+ scaleWidth = Math.max(scaleWidth, 2+width[i]);
+ }
+
+ /* Include a 5px margin between the y-axis and its labels */
+ this.scaleWidth = scaleWidth + 5;
+
+ /* Draw the y-axis labels and horizontal marks in their correctly scaled
+ * locations */
+ for (i = 0; i < 4; i++) {
+ pos = bottom - ((i+1) * paintStep);
+ this.painter.setPen(SCALE_COLOR);
+ this.painter.drawText(new QPointF(this.scaleWidth-width[i]-5, pos), String(label[i]));
+
+ this.painter.setPen(GRID_COLOR);
+ this.painter.drawLine(new QPointF(this.scaleWidth, pos),
+ new QPointF(this.frameRect.width(), pos));
+ }
+
+ /* Draw the y-axis */
+ this.painter.drawLine(this.scaleWidth, top, this.scaleWidth, bottom);
+
+ /**********************************************
+ * Paint data *********************************/
+ var recvPoints = [];
+ var sendPoints = [];
+
+ /* Convert the bandwidth data points to graph points */
+ recvPoints = this.pointsFromData(this.recvData);
+ sendPoints = this.pointsFromData(this.sendData);
+
+ if (this.graphStyle == AreaGraph) {
+ /* Plot the bandwidth data as area graphs */
+ if (this.showRecv)
+ {
+ var oldBrush = this.painter.brush();
+ RECV_COLOR.setAlphaF(0.6);
+ this.painter.setBrush(new QBrush(RECV_COLOR));
+ this.painter.drawPolygon(new QPolygonF(recvPoints), Qt.OddEvenFill);
+ this.painter.setBrush(oldBrush);
+ }
+ if (this.showSend)
+ {
+ var oldBrush = this.painter.brush();
+ SEND_COLOR.setAlphaF(0.4);
+ this.painter.setBrush(new QBrush(SEND_COLOR));
+ this.painter.drawPolygon(new QPolygonF(sendPoints), Qt.OddEvenFill);
+ this.painter.setBrush(oldBrush);
+ }
+ }
+
+ /* Plot the bandwidth as solid lines. If the graph style is currently an
+ * area graph, we end up outlining the integrals. */
+ if (this.showRecv)
+ {
+ var oldPen = this.painter.pen();
+ this.painter.setPen(RECV_COLOR);
+ this.painter.drawPolyline(new QPolygonF(recvPoints));
+ this.painter.setPen(oldPen);
+ }
+ if (this.showSend)
+ {
+ var oldPen = this.painter.pen();
+ this.painter.setPen(SEND_COLOR);
+ this.painter.drawPolyline(new QPolygonF(sendPoints));
+ this.painter.setPen(oldPen);
+ }
+
+ /************************************************
+ * Paint totals *********************************/
+ var x = this.scaleWidth + FONT_SIZE;
+ var y = 0;
+ var rowHeight = FONT_SIZE;
+
+ /* On Mac, we don't need vertical spacing between the text rows. */
+ // TODO: see how to use this in this case since we don't have preproc
+ rowHeight += 5;
+
+ /* If total received is selected */
+ if (this.showRecv) {
+ y = rowHeight;
+ this.painter.setPen(RECV_COLOR);
+ var total = Math.floor(this.totalRecv*100) / 100;
+ var count = Math.floor(this.recvData[0]*100) / 100;
+ this.painter.drawText(new QPoint(x, y),
+ tr("Recv:") + " " + total +
+ " (" + count + "KB/s)");
+ }
+
+ /* If total sent is selected */
+ if (this.showSend) {
+ y += rowHeight;
+ this.painter.setPen(SEND_COLOR);
+ var total = Math.floor(this.totalSend*100) / 100;
+ var count = Math.floor(this.sendData[0]*100) / 100;
+ this.painter.drawText(new QPoint(x, y),
+ tr("Sent:") + " " + total +
+ " (" + count + "KB/s)");
+ }
+ this.painter.end();
+}
diff --git a/bwgraph/info.xml b/bwgraph/info.xml
new file mode 100644
index 0000000..7d54654
--- /dev/null
+++ b/bwgraph/info.xml
@@ -0,0 +1,11 @@
+<VidaliaPlugin>
+ <name>Bandwidth Graph</name>
+ <date>11/06/2012</date>
+ <author>chiiph</author>
+ <type persistent="true" gui="true" />
+ <files>
+ <file>graphframe.js</file>
+ <file>bwgraph.js</file>
+ </files>
+ <namespace>bwgraph</namespace>
+</VidaliaPlugin>
More information about the tor-commits
mailing list