diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp index a7e7a184a17..4f2c14f2328 100644 --- a/src/plugins/ios/iosrunner.cpp +++ b/src/plugins/ios/iosrunner.cpp @@ -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); diff --git a/src/plugins/qmlprofiler/abstracttimelinemodel.cpp b/src/plugins/qmlprofiler/abstracttimelinemodel.cpp index 2f10e17e064..581b1708bb8 100644 --- a/src/plugins/qmlprofiler/abstracttimelinemodel.cpp +++ b/src/plugins/qmlprofiler/abstracttimelinemodel.cpp @@ -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 diff --git a/src/plugins/qmlprofiler/abstracttimelinemodel.h b/src/plugins/qmlprofiler/abstracttimelinemodel.h index 813384d989e..ea0486970a6 100644 --- a/src/plugins/qmlprofiler/abstracttimelinemodel.h +++ b/src/plugins/qmlprofiler/abstracttimelinemodel.h @@ -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 { diff --git a/src/plugins/qmlprofiler/abstracttimelinemodel_p.h b/src/plugins/qmlprofiler/abstracttimelinemodel_p.h index c8a70ada0f5..4cc42cd8eb6 100644 --- a/src/plugins/qmlprofiler/abstracttimelinemodel_p.h +++ b/src/plugins/qmlprofiler/abstracttimelinemodel_p.h @@ -47,6 +47,7 @@ public: virtual int findFirstIndexNoParents(qint64 startTime) const = 0; virtual int findLastIndex(qint64 endTime) const = 0; + QVector rowOffsets; QString name; QmlProfilerModelManager *modelManager; int modelId; diff --git a/src/plugins/qmlprofiler/qml/CategoryLabel.qml b/src/plugins/qmlprofiler/qml/CategoryLabel.qml index c3240352347..872483bb8e7 100644 --- a/src/plugins/qmlprofiler/qml/CategoryLabel.qml +++ b/src/plugins/qmlprofiler/qml/CategoryLabel.qml @@ -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; + readonly property int dragHeight: 5 - height: root.singleRowHeight + function trigger(i) { + return i * bindingTrigger * bindingTrigger; + } + + visible: trigger(qmlProfilerModelProxy.rowCount(modelIndex)) > 0 + + height: trigger(qmlProfilerModelProxy.height(modelIndex)) width: 150 - Component.onCompleted: { - updateHeight(); - } - - function updateHeight() { - height = root.singleRowHeight * qmlProfilerModelProxy.rowCount(modelIndex); - } - 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 diff --git a/src/plugins/qmlprofiler/qml/MainView.qml b/src/plugins/qmlprofiler/qml/MainView.qml index db38cab72f9..5d54cf5e923 100644 --- a/src/plugins/qmlprofiler/qml/MainView.qml +++ b/src/plugins/qmlprofiler/qml/MainView.qml @@ -36,8 +36,6 @@ Rectangle { // ***** properties - property int singleRowHeight: 30 - property alias selectionLocked : view.selectionLocked property bool lockItemSelection : false diff --git a/src/plugins/qmlprofiler/qml/TimeMarks.qml b/src/plugins/qmlprofiler/qml/TimeMarks.qml index b482023fd59..d3e9c6f66cc 100644 --- a/src/plugins/qmlprofiler/qml/TimeMarks.qml +++ b/src/plugins/qmlprofiler/qml/TimeMarks.qml @@ -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(); diff --git a/src/plugins/qmlprofiler/timelinemodelaggregator.cpp b/src/plugins/qmlprofiler/timelinemodelaggregator.cpp index 0d7bb543c2f..b696f7f4959 100644 --- a/src/plugins/qmlprofiler/timelinemodelaggregator.cpp +++ b/src/plugins/qmlprofiler/timelinemodelaggregator.cpp @@ -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); diff --git a/src/plugins/qmlprofiler/timelinemodelaggregator.h b/src/plugins/qmlprofiler/timelinemodelaggregator.h index 8e1a933cb9b..60a401b96a6 100644 --- a/src/plugins/qmlprofiler/timelinemodelaggregator.h +++ b/src/plugins/qmlprofiler/timelinemodelaggregator.h @@ -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(); diff --git a/src/plugins/qmlprofiler/timelinerenderer.cpp b/src/plugins/qmlprofiler/timelinerenderer.cpp index 356761a3c2e..13d7462ff4f 100644 --- a/src/plugins/qmlprofiler/timelinerenderer.cpp +++ b/src/plugins/qmlprofiler/timelinerenderer.cpp @@ -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(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); xfrom += width / 2; - yfrom = getYPosition(modelIndex, i) + DefaultRowHeight / 2 - y(); + yfrom = getYPosition(modelIndex, i) + + m_profilerModelProxy->rowHeight(modelIndex, i) / 2 - y(); // radius (derived from width of origin event) radius = 5; @@ -260,11 +269,29 @@ void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int modelIndex, int f p->restore(); } +int TimelineRenderer::rowFromPosition(int y) +{ + int ret = 0; + for (int modelIndex = 0; modelIndex < m_profilerModelProxy->modelCount(); modelIndex++) { + int modelHeight = m_profilerModelProxy->height(modelIndex); + if (y < modelHeight) { + for (int row = 0; row < m_profilerModelProxy->rowCount(modelIndex); ++row) { + y -= m_profilerModelProxy->rowHeight(modelIndex, row); + if (y < 0) return ret; + ++ret; + } + } else { + y -= modelHeight; + ret += m_profilerModelProxy->rowCount(modelIndex); + } + } + return ret; +} + int TimelineRenderer::modelFromPosition(int y) { - y = y / DefaultRowHeight; for (int modelIndex = 0; modelIndex < m_profilerModelProxy->modelCount(); modelIndex++) { - y -= m_profilerModelProxy->rowCount(modelIndex); + y -= m_profilerModelProxy->height(modelIndex); if (y < 0) return modelIndex; } @@ -328,7 +355,7 @@ void TimelineRenderer::manageHovered(int mouseX, int mouseY) // Make the "selected" area 3 pixels wide by adding/subtracting 1 to catch very narrow events. qint64 startTime = (mouseX - 1) * (m_endTime - m_startTime) / width() + m_startTime; qint64 endTime = (mouseX + 1) * (m_endTime - m_startTime) / width() + m_startTime; - int row = (mouseY + y()) / DefaultRowHeight; + int row = rowFromPosition(mouseY + y()); int modelIndex = modelFromPosition(mouseY + y()); // already covered? nothing to do @@ -404,10 +431,10 @@ int TimelineRenderer::getYPosition(int modelIndex, int index) const int modelRowStart = 0; for (int mi = 0; mi < modelIndex; mi++) - modelRowStart += m_profilerModelProxy->rowCount(mi); + modelRowStart += m_profilerModelProxy->height(mi); - int y = DefaultRowHeight * (modelRowStart + m_profilerModelProxy->getEventRow(modelIndex, index)); - return y; + return modelRowStart + m_profilerModelProxy->rowOffset(modelIndex, + m_profilerModelProxy->getEventRow(modelIndex, index)); } void TimelineRenderer::selectNext() diff --git a/src/plugins/qmlprofiler/timelinerenderer.h b/src/plugins/qmlprofiler/timelinerenderer.h index db6871462b3..587438f6044 100644 --- a/src/plugins/qmlprofiler/timelinerenderer.h +++ b/src/plugins/qmlprofiler/timelinerenderer.h @@ -172,6 +172,7 @@ private: void drawSelectionBoxes(QPainter *p, int modelIndex, int fromIndex, int toIndex); void drawBindingLoopMarkers(QPainter *p, int modelIndex, int fromIndex, int toIndex); int modelFromPosition(int y); + int rowFromPosition(int y); void manageClicked(); void manageHovered(int mouseX, int mouseY);