commit f64298fbeb7cc576f43bb00f3c0b6715dc63d385 Author: Tomás Touceda chiiph@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@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@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@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@buildGUI"); + return this.tab; + }, + + toggleHistory: function(toggle) { + this.grpBandwidth.setVisible(toggle); + }, + + toggleSettings: function(toggle) { + this.frmSettings.setVisible(toggle); + }, + + stop: function() { + vdebug("Bwhistory@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>
tor-commits@lists.torproject.org