Commit 84b00721 authored by Eike Ziller's avatar Eike Ziller
Browse files
parents 79bd453f 0d695617
......@@ -217,11 +217,11 @@ void IosRunner::handleErrorMsg(IosToolHandler *handler, const QString &msg)
TaskHub::addTask(Task::Warning,
tr("Run failed. The settings in the Organizer window of Xcode might be incorrect."),
ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT);
} else if (msg.contains(lockedErr)) {
} else if (res.contains(lockedErr)) {
QString message = tr("The device is locked, please unlock.");
TaskHub::addTask(Task::Error, message,
ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT);
res.replace(lockedErr, msg);
res.replace(lockedErr, message);
}
QRegExp qmlPortRe(QLatin1String("QML Debugger: Waiting for connection on port ([0-9]+)..."));
int index = qmlPortRe.indexIn(msg);
......
......@@ -32,6 +32,7 @@
namespace QmlProfiler {
static const int DefaultRowHeight = 30;
AbstractTimelineModel::AbstractTimelineModel(AbstractTimelineModelPrivate *dd,
const QString &name, const QString &label, QmlDebug::Message message,
......@@ -122,6 +123,63 @@ bool AbstractTimelineModel::isEmpty() const
return count() == 0;
}
int AbstractTimelineModel::rowHeight(int rowNumber) const
{
Q_D(const AbstractTimelineModel);
if (!expanded())
return DefaultRowHeight;
if (d->rowOffsets.length() > rowNumber)
return d->rowOffsets[rowNumber] - (rowNumber > 0 ? d->rowOffsets[rowNumber - 1] : 0);
return DefaultRowHeight;
}
int AbstractTimelineModel::rowOffset(int rowNumber) const
{
Q_D(const AbstractTimelineModel);
if (rowNumber == 0)
return 0;
if (!expanded())
return DefaultRowHeight * rowNumber;
if (d->rowOffsets.length() >= rowNumber)
return d->rowOffsets[rowNumber - 1];
if (!d->rowOffsets.empty())
return d->rowOffsets.last() + (rowNumber - 1 - d->rowOffsets.length()) * DefaultRowHeight;
return rowNumber * DefaultRowHeight;
}
void AbstractTimelineModel::setRowHeight(int rowNumber, int height)
{
Q_D(AbstractTimelineModel);
if (!expanded())
return;
if (height < DefaultRowHeight)
height = DefaultRowHeight;
int nextOffset = d->rowOffsets.empty() ? 0 : d->rowOffsets.last();
while (d->rowOffsets.length() <= rowNumber)
d->rowOffsets << (nextOffset += DefaultRowHeight);
int difference = height - d->rowOffsets[rowNumber] +
(rowNumber > 0 ? d->rowOffsets[rowNumber - 1] : 0);
if (difference != 0) {
for (; rowNumber < d->rowOffsets.length(); ++rowNumber) {
d->rowOffsets[rowNumber] += difference;
}
emit rowHeightChanged();
}
}
int AbstractTimelineModel::height() const
{
Q_D(const AbstractTimelineModel);
int depth = rowCount();
if (!expanded() || d->rowOffsets.empty())
return depth * DefaultRowHeight;
return d->rowOffsets.last() + (depth - d->rowOffsets.length()) * DefaultRowHeight;
}
qint64 AbstractTimelineModel::traceStartTime() const
{
Q_D(const AbstractTimelineModel);
......@@ -179,6 +237,18 @@ float AbstractTimelineModel::getHeight(int index) const
return 1.0f;
}
int AbstractTimelineModel::rowMinValue(int rowNumber) const
{
Q_UNUSED(rowNumber);
return 0;
}
int AbstractTimelineModel::rowMaxValue(int rowNumber) const
{
Q_UNUSED(rowNumber);
return 0;
}
void AbstractTimelineModel::dataChanged()
{
Q_D(AbstractTimelineModel);
......@@ -192,6 +262,8 @@ void AbstractTimelineModel::dataChanged()
default:
break;
}
d->rowOffsets.clear();
}
bool AbstractTimelineModel::eventAccepted(const QmlProfilerDataModel::QmlEventTypeData &event) const
......
......@@ -54,6 +54,11 @@ public:
bool isEmpty() const;
// Methods are directly passed on to the private model and relying on its virtual methods.
int rowHeight(int rowNumber) const;
int rowOffset(int rowNumber) const;
void setRowHeight(int rowNumber, int height);
int height() const;
Q_INVOKABLE qint64 lastTimeMark() const;
Q_INVOKABLE qint64 traceStartTime() const;
Q_INVOKABLE qint64 traceEndTime() const;
......@@ -88,9 +93,12 @@ public:
Q_INVOKABLE virtual int getEventIdForLocation(const QString &filename, int line, int column) const;
Q_INVOKABLE virtual int getBindingLoopDest(int index) const;
Q_INVOKABLE virtual float getHeight(int index) const;
virtual int rowMinValue(int rowNumber) const;
virtual int rowMaxValue(int rowNumber) const;
signals:
void expandedChanged();
void rowHeightChanged();
protected:
enum BoxColorProperties {
......
......@@ -47,6 +47,7 @@ public:
virtual int findFirstIndexNoParents(qint64 startTime) const = 0;
virtual int findLastIndex(qint64 endTime) const = 0;
QVector<int> rowOffsets;
QString name;
QmlProfilerModelManager *modelManager;
int modelId;
......
......@@ -32,30 +32,27 @@ import QtQuick 2.1
Item {
id: labelContainer
property string text: qmlProfilerModelProxy.title(modelIndex)
property bool expanded: false
property int modelIndex: index;
property bool expanded: trigger(qmlProfilerModelProxy.expanded(modelIndex))
property int modelIndex: index
property int bindingTrigger: 1
property var descriptions: []
property var extdescriptions: []
property var eventIds: []
visible: qmlProfilerModelProxy.rowCount(modelIndex) > 0;
height: root.singleRowHeight
width: 150
readonly property int dragHeight: 5
Component.onCompleted: {
updateHeight();
function trigger(i) {
return i * bindingTrigger * bindingTrigger;
}
function updateHeight() {
height = root.singleRowHeight * qmlProfilerModelProxy.rowCount(modelIndex);
}
visible: trigger(qmlProfilerModelProxy.rowCount(modelIndex)) > 0
height: trigger(qmlProfilerModelProxy.height(modelIndex))
width: 150
function getDescriptions() {
expanded = qmlProfilerModelProxy.expanded(modelIndex);
bindingTrigger = -bindingTrigger;
backgroundMarks.requestPaint();
visible = qmlProfilerModelProxy.rowCount(modelIndex) > 0;
if (!visible)
return;
......@@ -71,18 +68,13 @@ Item {
descriptions = desc;
eventIds = ids;
extdescriptions = extdesc;
updateHeight();
}
Connections {
target: qmlProfilerModelProxy
onExpandedChanged: {
getDescriptions();
}
onStateChanged: {
getDescriptions();
}
onExpandedChanged: getDescriptions();
onStateChanged: getDescriptions()
onRowHeightChanged: getDescriptions()
}
Text {
......@@ -91,7 +83,7 @@ Item {
font.pixelSize: 12
text: labelContainer.text
color: "#232323"
height: root.singleRowHeight
height: trigger(qmlProfilerModelProxy.rowHeight(modelIndex, 0))
width: 140
verticalAlignment: Text.AlignVCenter
}
......@@ -105,36 +97,49 @@ Item {
}
Column {
y: root.singleRowHeight
anchors.top: txt.bottom
visible: expanded
Repeater {
model: descriptions.length
Rectangle {
width: labelContainer.width
height: root.singleRowHeight
height: trigger(qmlProfilerModelProxy.rowHeight(modelIndex, index + 1))
color: "#eaeaea"
border.width: 1
border.color:"#c8c8c8"
Text {
height: root.singleRowHeight
x: 5
width: 140
anchors.fill: parent
anchors.leftMargin: 5
anchors.rightMargin: 5
text: descriptions[index]
textFormat: Text.PlainText
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
MouseArea {
property bool resizing: false
anchors.fill: parent
hoverEnabled: true
cursorShape: (resizing || height - mouseY < dragHeight) ? Qt.SizeVerCursor :
Qt.ArrowCursor;
onEntered: changeToolTip(extdescriptions[index]);
onExited: changeToolTip("");
onPressed: resizing = (height - mouseY < dragHeight);
onReleased: resizing = false;
onClicked: {
if (mouse.modifiers & Qt.ShiftModifier)
view.selectPrevFromId(modelIndex,eventIds[index]);
else
view.selectNextFromId(modelIndex,eventIds[index]);
}
onMouseYChanged: {
if (resizing)
qmlProfilerModelProxy.setRowHeight(modelIndex, index + 1, mouseY);
}
}
}
}
......@@ -143,7 +148,7 @@ Item {
Image {
source: expanded ? "arrow_down.png" : "arrow_right.png"
x: parent.width - 12
y: Math.floor((root.singleRowHeight - height) / 2)
y: 9
smooth: false
MouseArea {
anchors.fill: parent
......
......@@ -36,8 +36,6 @@ Rectangle {
// ***** properties
property int singleRowHeight: 30
property alias selectionLocked : view.selectionLocked
property bool lockItemSelection : false
......
......@@ -35,6 +35,10 @@ Canvas {
objectName: "TimeMarks"
contextType: "2d"
readonly property int scaleMinHeight: 60
readonly property int scaleStepping: 30
readonly property string units: " kMGT"
property real startTime
property real endTime
property real timePerPixel
......@@ -70,8 +74,6 @@ Canvas {
var lineStart = y < 0 ? -y : 0;
var lineEnd = Math.min(height, labels.height - y);
context.fillStyle = "#000000";
context.font = "8px sans-serif";
for (var ii = 0; ii < blockCount+1; ii++) {
var x = Math.floor(ii*pixelsPerBlock - realStartPos);
context.strokeStyle = "#B0B0B0";
......@@ -99,24 +101,85 @@ Canvas {
}
}
function prettyPrintScale(amount) {
var unitOffset = 0;
for (unitOffset = 0; amount > (1 << ((unitOffset + 1) * 10)); ++unitOffset) {}
var result = (amount >> (unitOffset * 10));
if (result < 100) {
var comma = Math.round(((amount >> ((unitOffset - 1) * 10)) & 1023) *
(result < 10 ? 100 : 10) / 1024);
if (comma < 10 && result < 10)
return result + ".0" + comma + units[unitOffset];
else
return result + "." + comma + units[unitOffset];
} else {
return result + units[unitOffset];
}
}
function drawBackgroundBars( context, region ) {
var colorIndex = true;
// row background
var backgroundOffset = y < 0 ? -y : -(y % (2 * root.singleRowHeight));
for (var currentY= backgroundOffset; currentY < Math.min(height, labels.height - y); currentY += root.singleRowHeight) {
context.fillStyle = colorIndex ? "#f0f0f0" : "white";
context.strokeStyle = colorIndex ? "#f0f0f0" : "white";
context.fillRect(0, currentY, width, root.singleRowHeight);
colorIndex = !colorIndex;
}
context.font = "8px sans-serif";
// separators
var cumulatedHeight = 0;
for (var modelIndex = 0; modelIndex < qmlProfilerModelProxy.modelCount() && cumulatedHeight < y + height; modelIndex++) {
cumulatedHeight += root.singleRowHeight * qmlProfilerModelProxy.rowCount(modelIndex);
if (cumulatedHeight < y)
var cumulatedHeight = y < 0 ? -y : 0;
for (var modelIndex = 0; modelIndex < qmlProfilerModelProxy.modelCount(); ++modelIndex) {
var modelHeight = qmlProfilerModelProxy.height(modelIndex);
if (cumulatedHeight + modelHeight < y) {
cumulatedHeight += modelHeight;
if (qmlProfilerModelProxy.rowCount(modelIndex) % 2 !== 0)
colorIndex = !colorIndex;
continue;
}
for (var row = 0; row < qmlProfilerModelProxy.rowCount(modelIndex); ++row) {
// row background
var rowHeight = qmlProfilerModelProxy.rowHeight(modelIndex, row)
cumulatedHeight += rowHeight;
colorIndex = !colorIndex;
if (cumulatedHeight < y - rowHeight)
continue;
context.strokeStyle = context.fillStyle = colorIndex ? "#f0f0f0" : "white";
context.fillRect(0, cumulatedHeight - rowHeight - y, width, rowHeight);
if (rowHeight >= scaleMinHeight) {
var minVal = qmlProfilerModelProxy.rowMinValue(modelIndex, row);
var maxVal = qmlProfilerModelProxy.rowMaxValue(modelIndex, row);
if (minVal !== maxVal) {
context.strokeStyle = context.fillStyle = "#B0B0B0";
var stepValUgly = Math.ceil((maxVal - minVal) /
Math.floor(rowHeight / scaleStepping));
// align to clean 2**x
var stepVal = 1;
while (stepValUgly >>= 1)
stepVal <<= 1;
var stepHeight = rowHeight / (maxVal - minVal);
for (var step = minVal; step <= maxVal - stepVal; step += stepVal) {
var offset = cumulatedHeight - step * stepHeight - y;
context.beginPath();
context.moveTo(0, offset);
context.lineTo(width, offset);
context.stroke();
context.fillText(prettyPrintScale(step), 5, offset - 2);
}
context.beginPath();
context.moveTo(0, cumulatedHeight - rowHeight - y);
context.lineTo(width, cumulatedHeight - rowHeight - y);
context.stroke();
context.fillText(prettyPrintScale(maxVal), 5,
cumulatedHeight - rowHeight - y + 8);
}
}
if (cumulatedHeight > y + height)
return;
}
context.strokeStyle = "#B0B0B0";
context.beginPath();
......
......@@ -91,6 +91,7 @@ void TimelineModelAggregator::addModel(AbstractTimelineModel *m)
{
d->modelList << m;
connect(m,SIGNAL(expandedChanged()),this,SIGNAL(expandedChanged()));
connect(m,SIGNAL(rowHeightChanged()),this,SIGNAL(rowHeightChanged()));
}
QStringList TimelineModelAggregator::categoryTitles() const
......@@ -141,6 +142,26 @@ qint64 TimelineModelAggregator::lastTimeMark() const
return mark;
}
int TimelineModelAggregator::height(int modelIndex) const
{
return d->modelList[modelIndex]->height();
}
int TimelineModelAggregator::rowHeight(int modelIndex, int row) const
{
return d->modelList[modelIndex]->rowHeight(row);
}
int TimelineModelAggregator::rowOffset(int modelIndex, int row) const
{
return d->modelList[modelIndex]->rowOffset(row);
}
void TimelineModelAggregator::setRowHeight(int modelIndex, int row, int height)
{
d->modelList[modelIndex]->setRowHeight(row, height);
}
bool TimelineModelAggregator::expanded(int modelIndex) const
{
return d->modelList[modelIndex]->expanded();
......@@ -161,6 +182,16 @@ const QString TimelineModelAggregator::title(int modelIndex) const
return d->modelList[modelIndex]->title();
}
int TimelineModelAggregator::rowMinValue(int modelIndex, int row) const
{
return d->modelList[modelIndex]->rowMinValue(row);
}
int TimelineModelAggregator::rowMaxValue(int modelIndex, int row) const
{
return d->modelList[modelIndex]->rowMaxValue(row);
}
int TimelineModelAggregator::findFirstIndex(int modelIndex, qint64 startTime) const
{
return d->modelList[modelIndex]->findFirstIndex(startTime);
......
......@@ -62,10 +62,16 @@ public:
Q_INVOKABLE qint64 lastTimeMark() const;
Q_INVOKABLE int height(int modelIndex) const;
Q_INVOKABLE int rowHeight(int modelIndex, int row) const;
Q_INVOKABLE void setRowHeight(int modelIndex, int row, int height);
Q_INVOKABLE int rowOffset(int modelIndex, int row) const;
Q_INVOKABLE bool expanded(int modelIndex) const;
Q_INVOKABLE void setExpanded(int modelIndex, bool expanded);
Q_INVOKABLE int rowCount(int modelIndex) const;
Q_INVOKABLE const QString title(int modelIndex) const;
Q_INVOKABLE int rowMinValue(int modelIndex, int row) const;
Q_INVOKABLE int rowMaxValue(int modelIndex, int row) const;
int findFirstIndex(int modelIndex, qint64 startTime) const;
int findFirstIndexNoParents(int modelIndex, qint64 startTime) const;
......@@ -93,6 +99,7 @@ signals:
void dataAvailable();
void stateChanged();
void expandedChanged();
void rowHeightChanged();
protected slots:
void dataChanged();
......
......@@ -41,8 +41,6 @@
using namespace QmlProfiler::Internal;
const int DefaultRowHeight = 30;
TimelineRenderer::TimelineRenderer(QQuickPaintedItem *parent) :
QQuickPaintedItem(parent), m_startTime(0), m_endTime(0), m_spacing(0), m_spacedDuration(0),
m_lastStartTime(0), m_lastEndTime(0)
......@@ -55,12 +53,16 @@ TimelineRenderer::TimelineRenderer(QQuickPaintedItem *parent) :
void TimelineRenderer::setProfilerModelProxy(QObject *profilerModelProxy)
{
if (m_profilerModelProxy)
if (m_profilerModelProxy) {
disconnect(m_profilerModelProxy, SIGNAL(expandedChanged()), this, SLOT(requestPaint()));
disconnect(m_profilerModelProxy, SIGNAL(rowHeightChanged()), this, SLOT(requestPaint()));
}
m_profilerModelProxy = qobject_cast<TimelineModelAggregator *>(profilerModelProxy);
if (m_profilerModelProxy)
if (m_profilerModelProxy) {
connect(m_profilerModelProxy, SIGNAL(expandedChanged()), this, SLOT(requestPaint()));
connect(m_profilerModelProxy, SIGNAL(rowHeightChanged()), this, SLOT(requestPaint()));
}
emit profilerModelProxyChanged(m_profilerModelProxy);
}
......@@ -130,18 +132,20 @@ void TimelineRenderer::drawItemsToPainter(QPainter *p, int modelIndex, int fromI
p->setPen(Qt::transparent);
int modelRowStart = 0;
for (int mi = 0; mi < modelIndex; mi++)
modelRowStart += m_profilerModelProxy->rowCount(mi);
modelRowStart += m_profilerModelProxy->height(mi);
for (int i = fromIndex; i <= toIndex; i++) {
int currentX, currentY, itemWidth, itemHeight;
int rowNumber = m_profilerModelProxy->getEventRow(modelIndex, i);
currentY = (modelRowStart + rowNumber) * DefaultRowHeight - y();
currentY = modelRowStart + m_profilerModelProxy->rowOffset(modelIndex, rowNumber) - y();
if (currentY >= height())
continue;
itemHeight = DefaultRowHeight * m_profilerModelProxy->getHeight(modelIndex, i);
currentY += DefaultRowHeight - itemHeight;
itemHeight = m_profilerModelProxy->rowHeight(modelIndex, rowNumber) *
m_profilerModelProxy->getHeight(modelIndex, i);
currentY += m_profilerModelProxy->rowHeight(modelIndex, rowNumber) - itemHeight;
if (currentY + itemHeight < 0)
continue;
......@@ -164,7 +168,7 @@ void TimelineRenderer::drawSelectionBoxes(QPainter *p, int modelIndex, int fromI
int modelRowStart = 0;
for (int mi = 0; mi < modelIndex; mi++)
modelRowStart += m_profilerModelProxy->rowCount(mi);
modelRowStart += m_profilerModelProxy->height(mi);
p->save();
......@@ -183,16 +187,19 @@ void TimelineRenderer::drawSelectionBoxes(QPainter *p, int modelIndex, int fromI
if (m_profilerModelProxy->getEventId(modelIndex, i) != id)
continue;
currentY = (modelRowStart + m_profilerModelProxy->getEventRow(modelIndex, i)) * DefaultRowHeight - y();
if (currentY + DefaultRowHeight < 0 || height() < currentY)
int row = m_profilerModelProxy->getEventRow(modelIndex, i);
int rowHeight = m_profilerModelProxy->rowHeight(modelIndex, row);
currentY = modelRowStart + m_profilerModelProxy->rowOffset(modelIndex, row) - y();
if (currentY + rowHeight < 0 || height() < currentY)
continue;
getItemXExtent(modelIndex, i, currentX, itemWidth);
if (i == m_selectedItem)
selectedItemRect = QRect(currentX, currentY - 1, itemWidth, DefaultRowHeight + 1);
selectedItemRect = QRect(currentX, currentY - 1, itemWidth, rowHeight + 1);
else
p->drawRect(currentX, currentY, itemWidth, DefaultRowHeight);
p->drawRect(currentX, currentY, itemWidth, rowHeight);
}
// draw the selected item rectangle the last, so that it's overlayed
......@@ -209,7 +216,7 @@ void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int modelIndex, int f
int destindex;
int xfrom, xto, width;
int yfrom, yto;
int radius = DefaultRowHeight / 3;
int radius = 10;
QPen shadowPen = QPen(QColor("grey"),2);
QPen markerPen = QPen(QColor("orange"),2);
QBrush shadowBrush = QBrush(QColor("grey"));
......@@ -222,12 +229,14 @@ void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int modelIndex, int f
// to
getItemXExtent(modelIndex, destindex, xto, width);
xto += width / 2;
yto = getYPosition(modelIndex, destindex) + DefaultRowHeight / 2 - y();
yto = getYPosition(modelIndex, destindex) +
m_profilerModelProxy->rowHeight(modelIndex, destindex) / 2 - y();
// from
getItemXExtent(modelIndex, i, xfrom, width);