diff --git a/rbkit-charts/examples/demo.js b/rbkit-charts/examples/demo.js
index 0dd4bde..c3a022d 100644
--- a/rbkit-charts/examples/demo.js
+++ b/rbkit-charts/examples/demo.js
@@ -19,8 +19,9 @@ var heapRandomData = function () {
};
};
+var heapTimeout;
var heapCharts = function() {
- setTimeout(heapCharts, 1000);
+ heapTimeout = setTimeout(heapCharts, 1000);
Rbkit.updateLiveObjectsChart(heapRandomData());
Rbkit.updateHeapChart(heapRandomData());
@@ -32,14 +33,16 @@ heapCharts();
// =============================== code for gc charts ==============================
// assuming max gc time is 10s
+var gcStartTimeout;
var gcChartStart = function () {
- setTimeout(gcChartEnd, _.random(0, 10) * 1000);
+ gcStartTimeout = setTimeout(gcChartEnd, _.random(0, 10) * 1000);
Rbkit.gcStarted(new Date());
};
+var gcEndTimeout;
var gcChartEnd = function () {
- setTimeout(gcChartStart, 5000);
+ gcEndTimeout = setTimeout(gcChartStart, 5000);
Rbkit.gcEnded(new Date());
};
@@ -108,10 +111,28 @@ var gcRandomStats = function () {
};
};
+var gcStatsTimeout;
var gcStatsTable = function () {
- setTimeout(gcStatsTable, 5000);
+ gcStatsTimeout = setTimeout(gcStatsTable, 5000);
Rbkit.updateGcStats(gcRandomStats());
};
gcStatsTable();
+
+var reset = function() {
+ clearTimeout(heapTimeout);
+ clearTimeout(gcEndTimeout);
+ clearTimeout(gcStartTimeout);
+ clearTimeout(gcStatsTimeout);
+
+ Rbkit.reset();
+
+ setTimeout(function() {
+ heapCharts();
+ gcChartStart();
+ gcStatsTable();
+ }, 2000);
+};
+
+document.getElementById("reset").addEventListener("click", reset);
diff --git a/rbkit-charts/examples/index.html b/rbkit-charts/examples/index.html
index 1bcfac3..3d123d4 100644
--- a/rbkit-charts/examples/index.html
+++ b/rbkit-charts/examples/index.html
@@ -43,6 +43,9 @@
GC Stats
+
+
+
diff --git a/rbkit-charts/src/rbcharts.js b/rbkit-charts/src/rbcharts.js
index ee610b8..7b0f39e 100644
--- a/rbkit-charts/src/rbcharts.js
+++ b/rbkit-charts/src/rbcharts.js
@@ -90,7 +90,6 @@ var Rbkit = {
// function to record gc end time
gcEnded: function (timestamp) {
if (!this.gcStartTime) {
- console.info("not sure why gc start time is not set");
return;
}
@@ -155,6 +154,11 @@ var Rbkit = {
},
updateGcStats: function (gcStats) {
+ if (Object.keys(gcStats).length === 0) {
+ document.getElementById('gc-stats-table').lastElementChild.innerHTML = '';
+ return;
+ }
+
var gcStatsKeys = Object.keys(this.gcStatsImportantFields);
for (var iter = 0; iter != gcStatsKeys.length; ++iter) {
var token = gcStatsKeys[iter];
@@ -231,6 +235,7 @@ var Rbkit = {
insertLegend: function (chart, canvasDiv) {
var chartLegend = chart.generateLegend();
var node = this.stringToNode(chartLegend);
+ canvasDiv.parentNode.lastChild.remove();
canvasDiv.parentNode.appendChild(node);
},
@@ -300,7 +305,14 @@ var Rbkit = {
this.updateLiveObjectsChart(data.payload);
this.updateHeapChart(data.payload);
break;
+ case "disconnected":
+ this.reset();
+ break;
}
+ },
+
+ reset: function() {
+ location.reload();
}
};
diff --git a/rbkit-charts/vendor/chart.js b/rbkit-charts/vendor/chart.js
index ac77f74..e34e08a 100644
--- a/rbkit-charts/vendor/chart.js
+++ b/rbkit-charts/vendor/chart.js
@@ -1,10 +1,9 @@
-
/*!
* Chart.js
* http://chartjs.org/
- * Version: 1.0.1-beta.4
+ * Version: 1.0.1
*
- * Copyright 2014 Nick Downie
+ * Copyright 2015 Nick Downie
* Released under the MIT license
* https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
*/
@@ -93,12 +92,15 @@
// Boolean - whether or not the chart should be responsive and resize when the browser does.
responsive: false,
- // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
- maintainAspectRatio: true,
+ // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
+ maintainAspectRatio: true,
// Boolean - Determines whether to draw tooltips on the canvas or not - attaches events to touchmove & mousemove
showTooltips: true,
+ // Boolean - Determines whether to draw built-in tooltip or call custom tooltip function
+ customTooltips: false,
+
// Array - Array of string names to attach tooltip events
tooltipEvents: ["mousemove", "touchstart", "touchmove", "mouseout"],
@@ -239,7 +241,7 @@
if (filterCallback(currentItem)){
return currentItem;
}
- };
+ }
},
findPreviousWhere = helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex){
// Default to end of the array
@@ -251,7 +253,7 @@
if (filterCallback(currentItem)){
return currentItem;
}
- };
+ }
},
inherits = helpers.inherits = function(extensions){
//Basic javascript inheritance based on the model created in Backbone.js
@@ -442,7 +444,9 @@
//Templating methods
//Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/
template = helpers.template = function(templateString, valuesObject){
- // If templateString is function rather than string-template - call the function for valuesObject
+
+ // If templateString is function rather than string-template - call the function for valuesObject
+
if(templateString instanceof Function){
return templateString(valuesObject);
}
@@ -831,7 +835,7 @@
newHeight = this.options.maintainAspectRatio ? newWidth / this.chart.aspectRatio : getMaximumHeight(this.chart.canvas);
canvas.width = this.chart.width = newWidth;
- canvas.height = this.chart.height = newHeight;
+ canvas.height = this.chart.height = newHeight;
retinaScale(this.chart);
@@ -867,6 +871,21 @@
destroy : function(){
this.clear();
unbindEvents(this, this.events);
+ var canvas = this.chart.canvas;
+
+ // Reset canvas height/width attributes starts a fresh with the canvas context
+ canvas.width = this.chart.width;
+ canvas.height = this.chart.height;
+
+ // < IE9 doesn't support removeProperty
+ if (canvas.style.removeProperty) {
+ canvas.style.removeProperty('width');
+ canvas.style.removeProperty('height');
+ } else {
+ canvas.style.removeAttribute('width');
+ canvas.style.removeAttribute('height');
+ }
+
delete Chart.instances[this.id];
},
showTooltip : function(ChartElements, forceRedraw){
@@ -896,6 +915,9 @@
this.activeElements = ChartElements;
}
this.draw();
+ if(this.options.customTooltips){
+ this.options.customTooltips(false);
+ }
if (ChartElements.length > 0){
// If we have multiple datasets, show a MultiTooltip for all of the data points at that index
if (this.datasets && this.datasets.length > 1) {
@@ -976,7 +998,8 @@
legendColorBackground : this.options.multiTooltipKeyBackground,
title: ChartElements[0].label,
chart: this.chart,
- ctx: this.chart.ctx
+ ctx: this.chart.ctx,
+ custom: this.options.customTooltips
}).draw();
} else {
@@ -995,7 +1018,8 @@
caretHeight: this.options.tooltipCaretSize,
cornerRadius: this.options.tooltipCornerRadius,
text: template(this.options.tooltipTemplate, Element),
- chart: this.chart
+ chart: this.chart,
+ custom: this.options.customTooltips
}).draw();
}, this);
}
@@ -1251,7 +1275,7 @@
this.yAlign = "above";
//Distance between the actual element.y position and the start of the tooltip caret
- var caretPadding = 2;
+ var caretPadding = this.caretPadding = 2;
var tooltipWidth = ctx.measureText(this.text).width + 2*this.xPadding,
tooltipRectHeight = this.fontSize + 2*this.yPadding,
@@ -1273,47 +1297,53 @@
ctx.fillStyle = this.fillColor;
- switch(this.yAlign)
- {
- case "above":
- //Draw a caret above the x/y
- ctx.beginPath();
- ctx.moveTo(this.x,this.y - caretPadding);
- ctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight));
- ctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight));
- ctx.closePath();
- ctx.fill();
- break;
- case "below":
- tooltipY = this.y + caretPadding + this.caretHeight;
- //Draw a caret below the x/y
- ctx.beginPath();
- ctx.moveTo(this.x, this.y + caretPadding);
- ctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight);
- ctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight);
- ctx.closePath();
- ctx.fill();
- break;
+ // Custom Tooltips
+ if(this.custom){
+ this.custom(this);
}
+ else{
+ switch(this.yAlign)
+ {
+ case "above":
+ //Draw a caret above the x/y
+ ctx.beginPath();
+ ctx.moveTo(this.x,this.y - caretPadding);
+ ctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight));
+ ctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight));
+ ctx.closePath();
+ ctx.fill();
+ break;
+ case "below":
+ tooltipY = this.y + caretPadding + this.caretHeight;
+ //Draw a caret below the x/y
+ ctx.beginPath();
+ ctx.moveTo(this.x, this.y + caretPadding);
+ ctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight);
+ ctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight);
+ ctx.closePath();
+ ctx.fill();
+ break;
+ }
- switch(this.xAlign)
- {
- case "left":
- tooltipX = this.x - tooltipWidth + (this.cornerRadius + this.caretHeight);
- break;
- case "right":
- tooltipX = this.x - (this.cornerRadius + this.caretHeight);
- break;
- }
+ switch(this.xAlign)
+ {
+ case "left":
+ tooltipX = this.x - tooltipWidth + (this.cornerRadius + this.caretHeight);
+ break;
+ case "right":
+ tooltipX = this.x - (this.cornerRadius + this.caretHeight);
+ break;
+ }
- drawRoundedRectangle(ctx,tooltipX,tooltipY,tooltipWidth,tooltipRectHeight,this.cornerRadius);
+ drawRoundedRectangle(ctx,tooltipX,tooltipY,tooltipWidth,tooltipRectHeight,this.cornerRadius);
- ctx.fill();
+ ctx.fill();
- ctx.fillStyle = this.textColor;
- ctx.textAlign = "center";
- ctx.textBaseline = "middle";
- ctx.fillText(this.text, tooltipX + tooltipWidth/2, tooltipY + tooltipRectHeight/2);
+ ctx.fillStyle = this.textColor;
+ ctx.textAlign = "center";
+ ctx.textBaseline = "middle";
+ ctx.fillText(this.text, tooltipX + tooltipWidth/2, tooltipY + tooltipRectHeight/2);
+ }
}
});
@@ -1367,36 +1397,42 @@
},
draw : function(){
- drawRoundedRectangle(this.ctx,this.x,this.y - this.height/2,this.width,this.height,this.cornerRadius);
- var ctx = this.ctx;
- ctx.fillStyle = this.fillColor;
- ctx.fill();
- ctx.closePath();
+ // Custom Tooltips
+ if(this.custom){
+ this.custom(this);
+ }
+ else{
+ drawRoundedRectangle(this.ctx,this.x,this.y - this.height/2,this.width,this.height,this.cornerRadius);
+ var ctx = this.ctx;
+ ctx.fillStyle = this.fillColor;
+ ctx.fill();
+ ctx.closePath();
- ctx.textAlign = "left";
- ctx.textBaseline = "middle";
- ctx.fillStyle = this.titleTextColor;
- ctx.font = this.titleFont;
+ ctx.textAlign = "left";
+ ctx.textBaseline = "middle";
+ ctx.fillStyle = this.titleTextColor;
+ ctx.font = this.titleFont;
- ctx.fillText(this.title,this.x + this.xPadding, this.getLineHeight(0));
+ ctx.fillText(this.title,this.x + this.xPadding, this.getLineHeight(0));
- ctx.font = this.font;
- helpers.each(this.labels,function(label,index){
- ctx.fillStyle = this.textColor;
- ctx.fillText(label,this.x + this.xPadding + this.fontSize + 3, this.getLineHeight(index + 1));
+ ctx.font = this.font;
+ helpers.each(this.labels,function(label,index){
+ ctx.fillStyle = this.textColor;
+ ctx.fillText(label,this.x + this.xPadding + this.fontSize + 3, this.getLineHeight(index + 1));
- //A bit gnarly, but clearing this rectangle breaks when using explorercanvas (clears whole canvas)
- //ctx.clearRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
- //Instead we'll make a white filled block to put the legendColour palette over.
+ //A bit gnarly, but clearing this rectangle breaks when using explorercanvas (clears whole canvas)
+ //ctx.clearRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
+ //Instead we'll make a white filled block to put the legendColour palette over.
- ctx.fillStyle = this.legendColorBackground;
- ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
+ ctx.fillStyle = this.legendColorBackground;
+ ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
- ctx.fillStyle = this.legendColors[index].fill;
- ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
+ ctx.fillStyle = this.legendColors[index].fill;
+ ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
- },this);
+ },this);
+ }
}
});
@@ -1561,14 +1597,24 @@
ctx.font = this.font;
each(this.yLabels,function(labelString,index){
var yLabelCenter = this.endPoint - (yLabelGap * index),
- linePositionY = Math.round(yLabelCenter);
+ linePositionY = Math.round(yLabelCenter),
+ drawHorizontalLine = this.showHorizontalLines;
ctx.textAlign = "right";
ctx.textBaseline = "middle";
if (this.showLabels){
ctx.fillText(labelString,xStart - 10,yLabelCenter);
}
- ctx.beginPath();
+
+ // This is X axis, so draw it
+ if (index === 0 && !drawHorizontalLine){
+ drawHorizontalLine = true;
+ }
+
+ if (drawHorizontalLine){
+ ctx.beginPath();
+ }
+
if (index > 0){
// This is a grid line in the centre, so drop that
ctx.lineWidth = this.gridLineWidth;
@@ -1581,10 +1627,12 @@
linePositionY += helpers.aliasPixel(ctx.lineWidth);
- ctx.moveTo(xStart, linePositionY);
- ctx.lineTo(this.width, linePositionY);
- ctx.stroke();
- ctx.closePath();
+ if(drawHorizontalLine){
+ ctx.moveTo(xStart, linePositionY);
+ ctx.lineTo(this.width, linePositionY);
+ ctx.stroke();
+ ctx.closePath();
+ }
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.lineColor;
@@ -1600,9 +1648,17 @@
var xPos = this.calculateX(index) + aliasPixel(this.lineWidth),
// Check to see if line/bar here and decide where to place the line
linePos = this.calculateX(index - (this.offsetGridLines ? 0.5 : 0)) + aliasPixel(this.lineWidth),
- isRotated = (this.xLabelRotation > 0);
+ isRotated = (this.xLabelRotation > 0),
+ drawVerticalLine = this.showVerticalLines;
- ctx.beginPath();
+ // This is Y axis, so draw it
+ if (index === 0 && !drawVerticalLine){
+ drawVerticalLine = true;
+ }
+
+ if (drawVerticalLine){
+ ctx.beginPath();
+ }
if (index > 0){
// This is a grid line in the centre, so drop that
@@ -1613,10 +1669,13 @@
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.lineColor;
}
- ctx.moveTo(linePos,this.endPoint);
- ctx.lineTo(linePos,this.startPoint - 3);
- ctx.stroke();
- ctx.closePath();
+
+ if (drawVerticalLine){
+ ctx.moveTo(linePos,this.endPoint);
+ ctx.lineTo(linePos,this.startPoint - 3);
+ ctx.stroke();
+ ctx.closePath();
+ }
ctx.lineWidth = this.lineWidth;
@@ -1964,6 +2023,12 @@
//Number - Width of the grid lines
scaleGridLineWidth : 1,
+ //Boolean - Whether to show horizontal lines (except X axis)
+ scaleShowHorizontalLines: true,
+
+ //Boolean - Whether to show vertical lines (except Y axis)
+ scaleShowVerticalLines: true,
+
//Boolean - If there is a stroke on each bar
barShowStroke : true,
@@ -2151,6 +2216,8 @@
font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
lineWidth : this.options.scaleLineWidth,
lineColor : this.options.scaleLineColor,
+ showHorizontalLines : this.options.scaleShowHorizontalLines,
+ showVerticalLines : this.options.scaleShowVerticalLines,
gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
padding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0,
@@ -2237,6 +2304,7 @@
}).call(this);
+
(function(){
"use strict";
@@ -2439,6 +2507,12 @@
//Number - Width of the grid lines
scaleGridLineWidth : 1,
+ //Boolean - Whether to show horizontal lines (except X axis)
+ scaleShowHorizontalLines: true,
+
+ //Boolean - Whether to show vertical lines (except Y axis)
+ scaleShowVerticalLines: true,
+
//Boolean - Whether the line is curved between points
bezierCurve : true,
@@ -2613,6 +2687,8 @@
font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
lineWidth : this.options.scaleLineWidth,
lineColor : this.options.scaleLineColor,
+ showHorizontalLines : this.options.scaleShowHorizontalLines,
+ showVerticalLines : this.options.scaleShowVerticalLines,
gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth,
@@ -2787,6 +2863,7 @@
}).call(this);
+
(function(){
"use strict";
@@ -3377,4 +3454,4 @@
-}).call(this);
+}).call(this);
\ No newline at end of file
diff --git a/rbkit-lib/model/heapdatamodel.cpp b/rbkit-lib/model/heapdatamodel.cpp
index 9950f55..5c90911 100644
--- a/rbkit-lib/model/heapdatamodel.cpp
+++ b/rbkit-lib/model/heapdatamodel.cpp
@@ -17,12 +17,17 @@ QVariant HeapDataModel::data(const QModelIndex &index, int role) const
return QVariant();
}
- if (role != Qt::DisplayRole) {
+ BaseHeapItem *item = static_cast(index.internalPointer());
+ switch(role) {
+ case Qt::DisplayRole:
+ return item->data(index.column());
+ break;
+ case Qt::ToolTipRole:
+ return QVariant(item->leadingIdentifier());
+ break;
+ default:
return QVariant();
}
- BaseHeapItem *item = static_cast(index.internalPointer());
-
- return item->data(index.column());
}
Qt::ItemFlags HeapDataModel::flags(const QModelIndex &index) const
diff --git a/rbkit-lib/sqlconnectionpool.cpp b/rbkit-lib/sqlconnectionpool.cpp
index 5d92c2a..a156116 100644
--- a/rbkit-lib/sqlconnectionpool.cpp
+++ b/rbkit-lib/sqlconnectionpool.cpp
@@ -28,7 +28,8 @@ void SqlConnectionPool::setupDatabase()
file.remove();
}
database = QSqlDatabase::addDatabase("QSQLITE");
- database.setDatabaseName(":memory:");
+ database.setDatabaseName("/tmp/rbkit.db");
+ currentVersion = 0;
if (!database.open()) {
qDebug() << query.lastError();
@@ -38,6 +39,12 @@ void SqlConnectionPool::setupDatabase()
qDebug() << "Setting up database done";
}
+void SqlConnectionPool::closeDatabase()
+{
+ database.close();
+ database.removeDatabase("/tmp/rbkit.db");
+}
+
void SqlConnectionPool::prepareTables()
{
QVector objectCreation;
diff --git a/rbkit-lib/sqlconnectionpool.h b/rbkit-lib/sqlconnectionpool.h
index 815f314..533d97a 100644
--- a/rbkit-lib/sqlconnectionpool.h
+++ b/rbkit-lib/sqlconnectionpool.h
@@ -25,6 +25,7 @@ class SqlConnectionPool
public:
static SqlConnectionPool* getInstance();
void setupDatabase();
+ void closeDatabase();
void prepareTables();
void loadSnapshot(ObjectStore *objectStore);
HeapItem *rootOfSnapshot(int snapShotVersion);
diff --git a/rbkit-lib/subscriber.cpp b/rbkit-lib/subscriber.cpp
index 430e206..674cf60 100644
--- a/rbkit-lib/subscriber.cpp
+++ b/rbkit-lib/subscriber.cpp
@@ -136,6 +136,9 @@ void Subscriber::stop()
commandSocket->sendCommand(stopCmd);
}
objectStore->reset();
+ static const QString eventName("disconnected");
+ QVariantMap map;
+ jsBridge->sendMapToJs(eventName, QDateTime(), map);
qDebug() << "stopped";
}
diff --git a/rbkit-lib/ui/rbkitmainwindow.cpp b/rbkit-lib/ui/rbkitmainwindow.cpp
index 859dd65..c16cc8e 100644
--- a/rbkit-lib/ui/rbkitmainwindow.cpp
+++ b/rbkit-lib/ui/rbkitmainwindow.cpp
@@ -14,7 +14,6 @@ RbkitMainWindow::RbkitMainWindow(QWidget *parent) :
ui(new Ui::RbkitMainWindow)
{
Q_INIT_RESOURCE(tool_icons);
- RBKit::SqlConnectionPool::getInstance()->setupDatabase();
ui->setupUi(this);
actionToolbar = new ActionToolbar(ui);
setupToolbarStyle();
@@ -177,12 +176,16 @@ void RbkitMainWindow::disconnectedFromSocket()
ui->statusbar->showMessage("Not connected to any Ruby application");
actionToolbar->disableProfileActions();
memoryView->processDetail->disconnectedFromProcess();
+ snapShotState->reset();
+ RBKit::SqlConnectionPool::getInstance()->closeDatabase();
+ RBKit::SqlConnectionPool::getInstance()->setupDatabase();
connectionInProgress = false;
}
void RbkitMainWindow::connectedToSocket()
{
+ RBKit::SqlConnectionPool::getInstance()->setupDatabase();
actionToolbar->enableProfileActions();
ui->action_Connect->setText(tr("&Disconnect"));
ui->action_Connect->setIcon(QIcon(":/icons/disconnect-32.png"));