summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authorChristiaan Janssen <christiaan.janssen@nokia.com>2011-10-26 11:32:01 +0200
committerChristiaan Janssen <christiaan.janssen@nokia.com>2011-11-02 10:14:09 +0100
commitbf4dfd5e74ed42af5bd6b4047813cb93682b5b10 (patch)
tree43e3db06f59460905eda7f523ca184c2d8b6f5e5 /src/plugins
parent38ad15a7728de7691087d255d76e50d6df2e9efd (diff)
downloadqt-creator-bf4dfd5e74ed42af5bd6b4047813cb93682b5b10.tar.gz
QmlProfiler: optimized timeline display
Change-Id: I0d7cf110356ef5f805b81a5fc39dca3870765ea3 Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/qmlprofiler/qml/Label.qml74
-rw-r--r--src/plugins/qmlprofiler/qml/MainView.qml295
-rw-r--r--src/plugins/qmlprofiler/qml/RangeDetails.qml29
-rw-r--r--src/plugins/qmlprofiler/qml/TimeMarks.qml14
-rw-r--r--src/plugins/qmlprofiler/qml/arrow_down.pngbin0 -> 208 bytes
-rw-r--r--src/plugins/qmlprofiler/qml/arrow_right.pngbin0 -> 209 bytes
-rw-r--r--src/plugins/qmlprofiler/qml/arrow_select.pngbin0 -> 609 bytes
-rw-r--r--src/plugins/qmlprofiler/qml/qmlprofiler.qrc3
-rw-r--r--src/plugins/qmlprofiler/timelineview.cpp419
-rw-r--r--src/plugins/qmlprofiler/timelineview.h138
-rw-r--r--src/plugins/qmlprofiler/tracewindow.cpp26
-rw-r--r--src/plugins/qmlprofiler/tracewindow.h4
12 files changed, 584 insertions, 418 deletions
diff --git a/src/plugins/qmlprofiler/qml/Label.qml b/src/plugins/qmlprofiler/qml/Label.qml
index abe28391bb..a9f3594ad1 100644
--- a/src/plugins/qmlprofiler/qml/Label.qml
+++ b/src/plugins/qmlprofiler/qml/Label.qml
@@ -34,12 +34,53 @@ import QtQuick 1.0
Item {
property alias text: txt.text
+ property bool expanded: false
+ property int typeIndex: index
- height: 50
- width: 150 //### required, or ignored by positioner
+ property variant descriptions: [text]
+
+ height: root.singleRowHeight
+ width: 150
+
+ onExpandedChanged: {
+ var rE = labels.rowExpanded;
+ rE[typeIndex] = expanded;
+ labels.rowExpanded = rE;
+ backgroundMarks.requestPaint();
+ view.rowExpanded(typeIndex, expanded);
+ updateHeight();
+ }
+
+ Component.onCompleted: {
+ updateHeight();
+ }
+
+ function updateHeight() {
+ height = root.singleRowHeight *
+ (expanded ? qmlEventList.uniqueEventsOfType(typeIndex) : qmlEventList.maxNestingForType(typeIndex));
+ }
+
+ Connections {
+ target: qmlEventList
+ onDataReady: {
+ var desc=[];
+ for (var i=0; i<qmlEventList.uniqueEventsOfType(typeIndex); i++)
+ desc[i] = qmlEventList.eventTextForType(typeIndex, i);
+ // special case: empty
+ if (desc.length == 1 && desc[0]=="")
+ desc[0] = text;
+ descriptions = desc;
+ updateHeight();
+ }
+ onDataClear: {
+ descriptions = [text];
+ updateHeight();
+ }
+ }
Text {
- id: txt;
+ id: txt
+ visible: !expanded
x: 5
font.pixelSize: 12
color: "#232323"
@@ -52,4 +93,31 @@ Item {
color: "#cccccc"
anchors.bottom: parent.bottom
}
+
+ Column {
+ visible: expanded
+ Repeater {
+ model: descriptions.length
+ Text {
+ height: root.singleRowHeight
+ x: 5
+ width: 140
+ text: descriptions[index]
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+ }
+ }
+
+ Image {
+ source: expanded ? "arrow_down.png" : "arrow_right.png"
+ x: parent.width - 12
+ y: 2
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ expanded = !expanded;
+ }
+ }
+ }
}
diff --git a/src/plugins/qmlprofiler/qml/MainView.qml b/src/plugins/qmlprofiler/qml/MainView.qml
index cbdab441c4..1ba891631e 100644
--- a/src/plugins/qmlprofiler/qml/MainView.qml
+++ b/src/plugins/qmlprofiler/qml/MainView.qml
@@ -39,13 +39,17 @@ Rectangle {
// ***** properties
property int candidateHeight: 0
- height: Math.max( candidateHeight, labels.rowCount * 50 + 2 )
+ height: Math.max( candidateHeight, labels.height + 2 )
+
+ property int singleRowHeight: 30
property bool dataAvailable: true
property int eventCount: 0
property real progress: 0
- property bool mouseOverSelection : true
+ property alias selectionLocked : view.selectionLocked
+ signal updateLockButton
+ property alias selectedItem: view.selectedItem
property variant names: [ qsTr("Painting"), qsTr("Compiling"), qsTr("Creating"), qsTr("Binding"), qsTr("Handling Signal")]
property variant colors : [ "#99CCB3", "#99CCCC", "#99B3CC", "#9999CC", "#CC99B3", "#CC99CC", "#CCCC99", "#CCB399" ]
@@ -56,9 +60,6 @@ Rectangle {
property string fileName: ""
property int lineNumber: -1
- property int selectedEventIndex : -1
- property bool mouseTracking: false
-
property real elapsedTime
signal updateTimer
@@ -107,7 +108,11 @@ Rectangle {
onDataReady: {
if (eventCount > 0) {
view.clearData();
- view.rebuildCache();
+ progress = 1.0;
+ dataAvailable = true;
+ view.visible = true;
+ view.requestPaint();
+ zoomControl.setRange(0, qmlEventList.traceEndTime()/10);
}
}
}
@@ -128,7 +133,6 @@ Rectangle {
function clearDisplay() {
clearData();
- selectedEventIndex = -1;
view.visible = false;
}
@@ -139,19 +143,11 @@ Rectangle {
}
function nextEvent() {
- if (eventCount > 0) {
- ++selectedEventIndex;
- if (selectedEventIndex >= eventCount)
- selectedEventIndex = 0;
- }
+ view.selectNext();
}
function prevEvent() {
- if (eventCount > 0) {
- --selectedEventIndex;
- if (selectedEventIndex < 0)
- selectedEventIndex = eventCount - 1;
- }
+ view.selectPrev();
}
function updateWindowLength(absoluteFactor) {
@@ -179,9 +175,9 @@ Rectangle {
}
var fixedPoint = (view.startTime + view.endTime) / 2;
- if (root.selectedEventIndex !== -1) {
+ if (view.selectedItem !== -1) {
// center on selected item if it's inside the current screen
- var newFixedPoint = qmlEventList.getStartTime(selectedEventIndex);
+ var newFixedPoint = qmlEventList.getStartTime(view.selectedItem);
if (newFixedPoint >= view.startTime && newFixedPoint < view.endTime)
fixedPoint = newFixedPoint;
}
@@ -242,37 +238,18 @@ Rectangle {
rangeDetails.type = "";
rangeDetails.file = "";
rangeDetails.line = -1;
-
- root.mouseOverSelection = true;
- selectionHighlight.visible = false;
}
// ***** slots
- onSelectedEventIndexChanged: {
- if ((!mouseTracking) && eventCount > 0
- && selectedEventIndex > -1 && selectedEventIndex < eventCount) {
- var windowLength = view.endTime - view.startTime;
-
- var eventStartTime = qmlEventList.getStartTime(selectedEventIndex);
- var eventEndTime = eventStartTime + qmlEventList.getDuration(selectedEventIndex);
-
- if (eventEndTime < view.startTime || eventStartTime > view.endTime) {
- var center = (eventStartTime + eventEndTime)/2;
- var from = Math.min(qmlEventList.traceEndTime()-windowLength,
- Math.max(0, Math.floor(center - windowLength/2)));
-
- zoomControl.setRange(from, from + windowLength);
- }
- }
- if (selectedEventIndex === -1)
- selectionHighlight.visible = false;
- }
-
onSelectionRangeModeChanged: {
selectionRangeControl.enabled = selectionRangeMode;
selectionRange.reset(selectionRangeMode);
}
+ onSelectionLockedChanged: {
+ updateLockButton();
+ }
+
// ***** child items
Timer {
id: elapsedTimer
@@ -312,7 +289,7 @@ Rectangle {
anchors.left: labels.right
height: root.height
contentWidth: 0;
- contentHeight: labels.rowCount * 50
+ contentHeight: labels.height
flickableDirection: Flickable.HorizontalFlick
onContentXChanged: {
@@ -322,13 +299,43 @@ Rectangle {
clip:true
+ MouseArea {
+ id: selectionRangeDrag
+ enabled: selectionRange.ready
+ anchors.fill: selectionRange
+ drag.target: selectionRange
+ drag.axis: "XAxis"
+ drag.minimumX: 0
+ drag.maximumX: flick.contentWidth - selectionRange.width
+ onPressed: {
+ selectionRange.isDragging = true;
+ }
+ onReleased: {
+ selectionRange.isDragging = false;
+ }
+ onDoubleClicked: {
+ zoomControl.setRange(selectionRange.startTime, selectionRange.startTime + selectionRange.duration);
+ root.selectionRangeMode = false;
+ root.updateRangeButton();
+ }
+ }
+
+
+ SelectionRange {
+ id: selectionRange
+ visible: root.selectionRangeMode
+ height: root.height
+ z: 2
+ }
+
TimelineView {
id: view
eventList: qmlEventList
+ x: flick.contentX
width: flick.width
- height: flick.contentHeight
+ height: root.height
property variant startX: 0
onStartXChanged: {
@@ -349,178 +356,65 @@ Rectangle {
var newStartX = startTime * flick.width / (endTime-startTime);
if (Math.abs(newStartX - startX) >= 1)
startX = newStartX;
- updateTimeline();
}
}
- property real timeSpan: endTime - startTime
- onTimeSpanChanged: {
- if (selectedEventIndex !== -1 && selectionHighlight.visible) {
- var spacing = flick.width / timeSpan;
- selectionHighlight.x = (qmlEventList.getStartTime(selectedEventIndex) - qmlEventList.traceStartTime()) * spacing;
- selectionHighlight.width = qmlEventList.getDuration(selectedEventIndex) * spacing;
- }
- }
-
- onCachedProgressChanged: {
- root.progress = 0.5 + cachedProgress * 0.5;
- }
-
- onCacheReady: {
- root.progress = 1.0;
- root.dataAvailable = true;
- if (root.eventCount > 0) {
- view.visible = true;
- view.updateTimeline();
- zoomControl.setRange(0, qmlEventList.traceEndTime()/10);
- }
- }
-
- delegate: Rectangle {
- id: obj
- property color myColor: root.colors[type]
-
- function conditionalHide() {
- if (!mouseArea.containsMouse)
- mouseArea.exited()
- }
-
- property int baseY: type * view.height / labels.rowCount
- property int baseHeight: view.height / labels.rowCount
- y: baseY + (nestingLevel-1)*(baseHeight / nestingDepth)
- height: baseHeight / nestingDepth
- gradient: Gradient {
- GradientStop { position: 0.0; color: myColor }
- GradientStop { position: 0.5; color: Qt.darker(myColor, 1.1) }
- GradientStop { position: 1.0; color: myColor }
- }
- smooth: true
-
- property bool componentIsCompleted: false
- Component.onCompleted: {
- componentIsCompleted = true;
- updateDetails();
- }
-
- property bool isSelected: root.selectedEventIndex == index;
- onIsSelectedChanged: {
- updateDetails();
- }
-
- function updateDetails() {
- if (!root.mouseTracking && componentIsCompleted) {
- if (isSelected) {
- enableSelected(0, 0);
- }
- }
- }
-
- function enableSelected(x,y) {
- rangeDetails.duration = qmlEventList.getDuration(index)/1000.0;
- rangeDetails.label = qmlEventList.getDetails(index);
- rangeDetails.file = qmlEventList.getFilename(index);
- rangeDetails.line = qmlEventList.getLine(index);
- rangeDetails.type = root.names[type];
+ onSelectedItemChanged: {
+ if (selectedItem !== -1) {
+ // display details
+ rangeDetails.duration = qmlEventList.getDuration(selectedItem)/1000.0;
+ rangeDetails.label = qmlEventList.getDetails(selectedItem);
+ rangeDetails.file = qmlEventList.getFilename(selectedItem);
+ rangeDetails.line = qmlEventList.getLine(selectedItem);
+ rangeDetails.type = root.names[qmlEventList.getType(selectedItem)];
rangeDetails.visible = true;
- selectionHighlight.x = obj.x;
- selectionHighlight.y = obj.y;
- selectionHighlight.width = width;
- selectionHighlight.height = height;
- selectionHighlight.visible = true;
- }
+ // center view
+ var windowLength = view.endTime - view.startTime;
+ var eventStartTime = qmlEventList.getStartTime(selectedItem);
+ var eventEndTime = eventStartTime + qmlEventList.getDuration(selectedItem);
- MouseArea {
- id: mouseArea
- anchors.fill: parent
- hoverEnabled: true
- onEntered: {
- if (root.mouseOverSelection) {
- root.mouseTracking = true;
- root.selectedEventIndex = index;
- enableSelected(mouseX, y);
- root.mouseTracking = false;
- }
- }
-
- onPressed: {
- root.mouseTracking = true;
- root.selectedEventIndex = index;
- enableSelected(mouseX, y);
- root.mouseTracking = false;
+ if (eventEndTime < view.startTime || eventStartTime > view.endTime) {
+ var center = (eventStartTime + eventEndTime)/2;
+ var from = Math.min(qmlEventList.traceEndTime()-windowLength,
+ Math.max(0, Math.floor(center - windowLength/2)));
- root.mouseOverSelection = false;
- root.gotoSourceLocation(rangeDetails.file, rangeDetails.line);
+ zoomControl.setRange(from, from + windowLength);
}
- }
- }
-
- Rectangle {
- id: selectionHighlight
- color:"transparent"
- border.width: 2
- border.color: "blue"
- z: 1
- radius: 2
- visible: false
- }
-
- MouseArea {
- width: parent.width
- height: parent.height
- x: flick.contentX
- onClicked: {
+ } else {
root.hideRangeDetails();
}
}
- MouseArea {
- id: selectionRangeControl
- enabled: false
- width: flick.width
- height: root.height
- x: flick.contentX
- hoverEnabled: enabled
- z: 2
-
- onReleased: {
- selectionRange.releasedOnCreation();
- }
- onPressed: {
- selectionRange.pressedOnCreation();
- }
- onMousePositionChanged: {
- selectionRange.movedOnCreation();
+ onItemPressed: {
+ if (pressedItem !== -1) {
+ root.gotoSourceLocation(qmlEventList.getFilename(pressedItem), qmlEventList.getLine(pressedItem));
}
}
- SelectionRange {
- id: selectionRange
- visible: root.selectionRangeMode
- height: root.height
- z: 2
- }
+ // hack to pass mouse events to the other mousearea if enabled
+ startDragArea: selectionRangeDrag.enabled ? selectionRangeDrag.x : -flick.contentX
+ endDragArea: selectionRangeDrag.enabled ?
+ selectionRangeDrag.x + selectionRangeDrag.width : -flick.contentX-1
+ }
+ MouseArea {
+ id: selectionRangeControl
+ enabled: false
+ width: flick.width
+ height: root.height
+ x: flick.contentX
+ hoverEnabled: enabled
+ z: 2
- MouseArea {
- id: selectionRangeDrag
- enabled: selectionRange.ready
- anchors.fill: selectionRange
- drag.target: selectionRange
- drag.axis: "XAxis"
- drag.minimumX: 0
- drag.maximumX: flick.contentWidth - selectionRange.width
- onPressed: {
- selectionRange.isDragging = true;
- }
- onReleased: {
- selectionRange.isDragging = false;
- }
- onDoubleClicked: {
- zoomControl.setRange(selectionRange.startTime, selectionRange.startTime + selectionRange.duration);
- root.selectionRangeMode = false;
- root.updateRangeButton();
- }
+ onReleased: {
+ selectionRange.releasedOnCreation();
+ }
+ onPressed: {
+ selectionRange.pressedOnCreation();
+ }
+ onMousePositionChanged: {
+ selectionRange.movedOnCreation();
}
}
}
@@ -542,9 +436,10 @@ Rectangle {
id: labels
width: 150
color: "#dcdcdc"
- height: flick.contentHeight
+ height: col.height
property int rowCount: 5
+ property variant rowExpanded: [false,false,false,false,false];
Column {
id: col
diff --git a/src/plugins/qmlprofiler/qml/RangeDetails.qml b/src/plugins/qmlprofiler/qml/RangeDetails.qml
index d044fc0ed5..0b3b58d7f0 100644
--- a/src/plugins/qmlprofiler/qml/RangeDetails.qml
+++ b/src/plugins/qmlprofiler/qml/RangeDetails.qml
@@ -36,13 +36,13 @@ import Monitor 1.0
BorderImage {
id: rangeDetails
- property string duration //###int?
+ property string duration
property string label
property string type
property string file
property int line
- property bool locked: !root.mouseOverSelection
+ property bool locked: view.selectionLocked
source: "popup_green.png"
border {
@@ -107,6 +107,15 @@ BorderImage {
}
}
+ MouseArea {
+ width: col.width + 30
+ height: col.height + typeTitle.height + 30
+ drag.target: parent
+ onClicked: {
+ root.gotoSourceLocation(file, line);
+ }
+ }
+
Image {
id: lockIcon
source: locked?"lock_closed.png" : "lock_open.png"
@@ -118,7 +127,7 @@ BorderImage {
MouseArea {
anchors.fill: parent
onClicked: {
- root.mouseOverSelection = !root.mouseOverSelection;
+ root.selectionLocked = !root.selectionLocked;
}
}
}
@@ -132,20 +141,10 @@ BorderImage {
anchors.fill: parent
onClicked: {
root.hideRangeDetails();
+ view.selectedItem = -1;
}
}
}
- MouseArea {
- width: col.width
- height: col.height + typeTitle.height + 30
- drag.target: parent
- onClicked: {
- // force reload of selected item
- var selectedItem = root.selectedEventIndex;
- root.selectedEventIndex = -1;
- root.selectedEventIndex = selectedItem;
- root.gotoSourceLocation(file, line);
- }
- }
+
}
diff --git a/src/plugins/qmlprofiler/qml/TimeMarks.qml b/src/plugins/qmlprofiler/qml/TimeMarks.qml
index 8639f4d85c..eb378a79aa 100644
--- a/src/plugins/qmlprofiler/qml/TimeMarks.qml
+++ b/src/plugins/qmlprofiler/qml/TimeMarks.qml
@@ -107,13 +107,17 @@ TiledCanvas {
}
function drawBackgroundBars( ctxt, region ) {
- var barHeight = Math.round(labels.height / labels.rowCount);
+ var cumulatedHeight = 0;
for (var i=0; i<labels.rowCount; i++) {
- ctxt.fillStyle = i%2 ? "#f3f3f3" : "white"
- ctxt.strokeStyle = i%2 ? "#f3f3f3" : "white"
- ctxt.fillRect(0, i * barHeight, width, barHeight);
+ var barHeight = labels.rowExpanded[i] ?
+ qmlEventList.uniqueEventsOfType(i) * root.singleRowHeight :
+ qmlEventList.maxNestingForType(i) * root.singleRowHeight;
+ ctxt.fillStyle = i%2 ? "#f0f0f0" : "white"
+ ctxt.strokeStyle = i%2 ? "#f0f0f0" : "white"
+ ctxt.fillRect(0, cumulatedHeight, width, barHeight);
+ cumulatedHeight += barHeight;
}
- ctxt.fillStyle = "white";
+ ctxt.fillStyle = "#f5f5f5";
ctxt.fillRect(0, labels.height, width, height - labels.height);
}
}
diff --git a/src/plugins/qmlprofiler/qml/arrow_down.png b/src/plugins/qmlprofiler/qml/arrow_down.png
new file mode 100644
index 0000000000..8d66b0a623
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/arrow_down.png
Binary files differ
diff --git a/src/plugins/qmlprofiler/qml/arrow_right.png b/src/plugins/qmlprofiler/qml/arrow_right.png
new file mode 100644
index 0000000000..228529f0ff
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/arrow_right.png
Binary files differ
diff --git a/src/plugins/qmlprofiler/qml/arrow_select.png b/src/plugins/qmlprofiler/qml/arrow_select.png
new file mode 100644
index 0000000000..e1e2d4a5b1
--- /dev/null
+++ b/src/plugins/qmlprofiler/qml/arrow_select.png
Binary files differ
diff --git a/src/plugins/qmlprofiler/qml/qmlprofiler.qrc b/src/plugins/qmlprofiler/qml/qmlprofiler.qrc
index 0b1ffce54a..daf2b78b42 100644
--- a/src/plugins/qmlprofiler/qml/qmlprofiler.qrc
+++ b/src/plugins/qmlprofiler/qml/qmlprofiler.qrc
@@ -24,5 +24,8 @@
<file>SelectionRange.qml</file>
<file>SelectionRangeDetails.qml</file>
<file>magnifier.png</file>
+ <file>arrow_down.png</file>
+ <file>arrow_right.png</file>
+ <file>arrow_select.png</file>
</qresource>
</RCC>
diff --git a/src/plugins/qmlprofiler/timelineview.cpp b/src/plugins/qmlprofiler/timelineview.cpp
index 7dc44045c9..56eaa70f3c 100644
--- a/src/plugins/qmlprofiler/timelineview.cpp
+++ b/src/plugins/qmlprofiler/timelineview.cpp
@@ -35,223 +35,274 @@
#include <qdeclarativecontext.h>
#include <qdeclarativeproperty.h>
#include <QtCore/QTimer>
+#include <QtGui/QPixmap>
+#include <QtGui/QPainter>
+#include <QtGui/QGraphicsSceneMouseEvent>
+
+#include <math.h>
using namespace QmlProfiler::Internal;
-#define CACHE_ENABLED true
-#define CACHE_UPDATEDELAY 10
-#define CACHE_STEP 200
+const int DefaultRowHeight = 30;
TimelineView::TimelineView(QDeclarativeItem *parent) :
- QDeclarativeItem(parent), m_delegate(0), m_itemCount(0), m_startTime(0), m_endTime(0), m_spacing(0),
- prevMin(0), prevMax(0), m_eventList(0), m_totalWidth(0), m_lastCachedIndex(0), m_creatingCache(false), m_oldCacheSize(0)
+ QDeclarativeItem(parent), m_startTime(0), m_endTime(0), m_spacing(0),
+ m_lastStartTime(0), m_lastEndTime(0), m_eventList(0)
{
+ clearData();
+ setFlag(QGraphicsItem::ItemHasNoContents, false);
+ setAcceptedMouseButtons(Qt::LeftButton);
+ setAcceptHoverEvents(true);
+ for (int i=0; i<QmlJsDebugClient::MaximumQmlEventType; i++)
+ m_rowsExpanded << false;
}
void TimelineView::componentComplete()
{
+ const QMetaObject *metaObject = this->metaObject();
+ int propertyCount = metaObject->propertyCount();
+ int requestPaintMethod = metaObject->indexOfMethod("requestPaint()");
+ for (int ii = TimelineView::staticMetaObject.propertyCount(); ii < propertyCount; ++ii) {
+ QMetaProperty p = metaObject->property(ii);
+ if (p.hasNotifySignal())
+ QMetaObject::connect(this, p.notifySignalIndex(), this, requestPaintMethod, 0, 0);
+ }
QDeclarativeItem::componentComplete();
}
-void TimelineView::clearData()
+void TimelineView::requestPaint()
{
- if (CACHE_ENABLED)
- foreach (QDeclarativeItem *item, m_items.values())
- item->setVisible(false);
- else
- foreach (QDeclarativeItem *item, m_items.values())
- delete m_items.take(m_items.key(item));
-
- m_startTime = 0;
- m_endTime = 0;
- prevMin = 0;
- prevMax = 0;
- m_totalWidth = 0;
- m_lastCachedIndex = 0;
+ update();
}
-void TimelineView::updateTimeline()
+void TimelineView::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
{
- if (!m_delegate)
- return;
-
- if (!m_eventList)
+ qint64 windowDuration = m_endTime - m_startTime;
+ if (windowDuration <= 0)
return;
- qreal totalRange = m_eventList->traceEndTime() - m_eventList->traceStartTime();
- qreal window = m_endTime - m_startTime;
+ m_spacing = qreal(width()) / windowDuration;
- if (window == 0) //###
- return;
+ m_rowWidths.clear();
+ for (int i=0; i<QmlJsDebugClient::MaximumQmlEventType; i++) {
+ m_rowWidths << (m_rowsExpanded[i] ? m_eventList->uniqueEventsOfType(i) : m_eventList->maxNestingForType(i));
+ }
- qreal newSpacing = width() / window;
- bool spacingChanged = (newSpacing != m_spacing);
- m_spacing = newSpacing;
+ // event rows
+ m_rowStarts.clear();
+ int pos = 0;
+ for (int i=0; i<QmlJsDebugClient::MaximumQmlEventType; i++) {
+ m_rowStarts << pos;
+ pos += DefaultRowHeight * m_rowWidths[i];
+ }
- qreal oldtw = m_totalWidth;
- m_totalWidth = totalRange * m_spacing;
+ p->setPen(Qt::transparent);
+ // speedup: don't draw overlapping events, just skip them
+ m_rowLastX.clear();
+ for (int i=0; i<QmlJsDebugClient::MaximumQmlEventType; i++)
+ for (int j=0; j<m_rowWidths[i]; j++)
+ m_rowLastX << -m_startTime * m_spacing;
- int minsample = m_eventList->findFirstIndex(m_startTime + m_eventList->traceStartTime());
- int maxsample = m_eventList->findLastIndex(m_endTime + m_eventList->traceStartTime());
+ int firstIndex = m_eventList->findFirstIndex(m_startTime);
+ int lastIndex = m_eventList->findLastIndex(m_endTime);
+ drawItemsToPainter(p, firstIndex, lastIndex);
- //### emitting this before startXChanged was causing issues
- if (m_totalWidth != oldtw)
- emit totalWidthChanged(m_totalWidth);
+ drawSelectionBoxes(p);
+ m_lastStartTime = m_startTime;
+ m_lastEndTime = m_endTime;
+}
- // the next loops have to be modified with the new implementation of the cache
+QColor TimelineView::colorForItem(int itemIndex)
+{
+ int ndx = m_eventList->getHash(itemIndex);
+ return QColor::fromHsl((ndx*25)%360, 76, 166);
+}
- // hide items that are not visible any more
- if (maxsample < prevMin || minsample > prevMax) {
- for (int i = prevMin; i <= prevMax; ++i)
- if (m_items.contains(i)) {
- if (CACHE_ENABLED)
- m_items.value(i)->setVisible(false);
- else
- delete m_items.take(i);
- }
- } else {
- if (minsample > prevMin && minsample <= prevMax)
- for (int i = prevMin; i < minsample; ++i)
- if (m_items.contains(i)) {
- if (CACHE_ENABLED)
- m_items.value(i)->setVisible(false);
- else
- delete m_items.take(i);
- }
-
- if (maxsample >= prevMin && maxsample < prevMax)
- for (int i = maxsample + 1; i <= prevMax; ++i)
- if (m_items.contains(i)) {
- if (CACHE_ENABLED)
- m_items.value(i)->setVisible(false);
- else
- delete m_items.take(i);
- }
+QLinearGradient *TimelineView::gradientForItem(int itemIndex)
+{
+ int ndx = m_eventList->getHash(itemIndex);
+ if (!m_hashedGradients.contains(ndx)) {
+ QLinearGradient *linearGrad = new QLinearGradient(0,0,0,DefaultRowHeight);
+ linearGrad->setColorAt(0, colorForItem(itemIndex));
+ linearGrad->setColorAt(0.5, colorForItem(itemIndex).darker(115));
+ linearGrad->setColorAt(1, colorForItem(itemIndex));
+ m_hashedGradients[ndx] = linearGrad;
}
+ return m_hashedGradients[ndx];
+}
- // Update visible items
- for (int i = minsample; i <= maxsample; ++i) {
- if (!m_items.contains(i)) {
- createItem(i);
- m_items.value(i)->setVisible(true);
- }
+void TimelineView::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex)
+{
+ int x,y,width,rowNumber, eventType;
+ for (int i = fromIndex; i <= toIndex; i++) {
+ x = (m_eventList->getStartTime(i) - m_startTime) * m_spacing;
+ eventType = m_eventList->getType(i);
+ if (m_rowsExpanded[eventType])
+ y = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->eventPosInType(i);
else
- if (spacingChanged || !m_items.value(i)->isVisible()) {
- m_items.value(i)->setVisible(true);
- updateItemPosition(i);
- }
- }
+ y = m_rowStarts[eventType] + DefaultRowHeight*(m_eventList->getNestingLevel(i)-1);
+
+ width = m_eventList->getDuration(i)*m_spacing;
+ if (width<1)
+ width = 1;
- prevMin = minsample;
- prevMax = maxsample;
+ rowNumber = y/DefaultRowHeight;
+ if (m_rowLastX[rowNumber] > x+width)
+ continue;
+ m_rowLastX[rowNumber] = x+width;
+ p->setBrush(*gradientForItem(i));
+ p->drawRect(x,y,width,DefaultRowHeight);
+ }
}
-void TimelineView::createItem(int itemIndex)
+void TimelineView::drawSelectionBoxes(QPainter *p)
{
- QDeclarativeContext *ctxt = new QDeclarativeContext(qmlContext(this));
- QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(m_delegate->beginCreate(ctxt));
- m_items.insert(itemIndex, item);
+ if (m_selectedItem == -1)
+ return;
- ctxt->setParent(item); //### QDeclarative_setParent_noEvent(ctxt, item); instead?
- ctxt->setContextProperty("index", itemIndex);
- ctxt->setContextProperty("type", m_eventList->getType(itemIndex));
- ctxt->setContextProperty("nestingLevel", m_eventList->getNestingLevel(itemIndex));
- ctxt->setContextProperty("nestingDepth", m_eventList->getNestingDepth(itemIndex));
+ int fromIndex = m_eventList->findFirstIndex(m_startTime);
+ int toIndex = m_eventList->findLastIndex(m_endTime);
+ int id = m_eventList->getHash(m_selectedItem);
- updateItemPosition(itemIndex);
+ p->setBrush(Qt::transparent);
+ QPen strongPen(QBrush(Qt::blue), 3);
+ QPen lightPen(QBrush(QColor(Qt::blue).lighter(130)), 2);
+ p->setPen(lightPen);
+
+ int x,y,width,rowNumber,eventType;
+ for (int i = fromIndex; i <= toIndex; i++) {
+ if (m_eventList->getHash(i) != id)
+ continue;
+
+ if (i == m_selectedItem)
+ p->setPen(strongPen);
+ else
+ p->setPen(lightPen);
+
+ x = (m_eventList->getStartTime(i) - m_startTime) * m_spacing;
+ eventType = m_eventList->getType(i);
+ if (m_rowsExpanded[eventType])
+ y = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->eventPosInType(i);
+ else
+ y = m_rowStarts[eventType] + DefaultRowHeight*(m_eventList->getNestingLevel(i)-1);
- item->setVisible(false);
+ width = m_eventList->getDuration(i)*m_spacing;
+ if (width<1)
+ width = 1;
- item->setParentItem(this);
- m_delegate->completeCreate();
- m_itemCount++;
+ rowNumber = y/DefaultRowHeight;
+ p->drawRect(x,y,width,DefaultRowHeight);
+ }
}
-void TimelineView::updateItemPosition(int itemIndex)
+void TimelineView::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
- QDeclarativeItem *item = m_items.value(itemIndex);
- if (item) {
- qreal itemStartPos = (m_eventList->getStartTime(itemIndex) - m_eventList->traceStartTime()) * m_spacing;
- item->setX(itemStartPos);
- qreal width = (m_eventList->getEndTime(itemIndex) - m_eventList->getStartTime(itemIndex)) * m_spacing;
- item->setWidth(width > 1 ? width : 1);
- }
+ // special case: if there is a drag area below me, don't accept the
+ // events unless I'm actually clicking inside an item
+ if (m_currentSelection.eventIndex == -1 &&
+ event->pos().x()+x() >= m_startDragArea &&
+ event->pos().x()+x() <= m_endDragArea)
+ event->setAccepted(false);
+
}
-void TimelineView::rebuildCache()
+void TimelineView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
- if (CACHE_ENABLED) {
- m_lastCachedIndex = 0;
- m_creatingCache = false;
- m_oldCacheSize = m_items.count();
- emit cachedProgressChanged();
- QTimer::singleShot(CACHE_UPDATEDELAY, this, SLOT(purgeCache()));
- } else {
- m_creatingCache = true;
- m_lastCachedIndex = m_eventList->count();
- emit cacheReady();
- }
+ Q_UNUSED(event);
+ manageClicked();
}
-qreal TimelineView::cachedProgress() const
+void TimelineView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
- qreal progress;
- if (!m_creatingCache) {
- if (m_oldCacheSize == 0)
- progress = 0.5;
- else
- progress = (m_lastCachedIndex * 0.5) / m_oldCacheSize;
- }
- else
- progress = 0.5 + (m_lastCachedIndex * 0.5) / m_eventList->count();
+ event->setAccepted(false);
+}
- return progress;
+
+void TimelineView::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
+{
+ Q_UNUSED(event);
+ manageHovered(event->pos().x(), event->pos().y());
+ if (m_currentSelection.eventIndex == -1)
+ event->setAccepted(false);
}
-void TimelineView::increaseCache()
+void TimelineView::manageClicked()
{
- int totalCount = m_eventList->count();
- if (m_lastCachedIndex >= totalCount) {
- emit cacheReady();
- return;
+ if (m_currentSelection.eventIndex != -1) {
+ if (m_currentSelection.eventIndex == m_selectedItem)
+ setSelectionLocked(!m_selectionLocked);
+ else
+ setSelectionLocked(true);
+ emit itemPressed(m_currentSelection.eventIndex);
+ } else {
+// setSelectionLocked(false);
}
+ setSelectedItem(m_currentSelection.eventIndex);
+}
- for (int i = 0; i < CACHE_STEP; i++) {
- createItem(m_lastCachedIndex);
- m_lastCachedIndex++;
- if (m_lastCachedIndex >= totalCount)
- break;
- }
+void TimelineView::manageHovered(int x, int y)
+{
+ if (m_endTime - m_startTime <=0)
+ return;
- emit cachedProgressChanged();
+ qint64 time = x * (m_endTime - m_startTime) / width() + m_startTime;
+ int row = y / DefaultRowHeight;
- QTimer::singleShot(CACHE_UPDATEDELAY, this, SLOT(increaseCache()));
-}
+ // already covered? nothing to do
+ if (m_currentSelection.eventIndex != -1 && time >= m_currentSelection.startTime && time <= m_currentSelection.endTime && row == m_currentSelection.row) {
+ return;
+ }
-void TimelineView::purgeCache()
-{
- if (m_items.isEmpty()) {
- m_creatingCache = true;
- m_lastCachedIndex = 0;
- QTimer::singleShot(CACHE_UPDATEDELAY, this, SLOT(increaseCache()));
+ // find if there's items in the time range
+ int eventFrom = m_eventList->findFirstIndex(time);
+ int eventTo = m_eventList->findLastIndex(time);
+ if (eventTo < eventFrom) {
+ m_currentSelection.eventIndex = -1;
return;
}
- for (int i=0; i < CACHE_STEP; i++)
- {
- if (m_items.contains(m_lastCachedIndex))
- delete m_items.take(m_lastCachedIndex);
+ // find if we are in the right column
+ int itemRow, eventType;
+ for (int i=eventTo; i>=eventFrom; --i) {
+ if (ceil(m_eventList->getEndTime(i)*m_spacing) < floor(time*m_spacing))
+ continue;
- m_lastCachedIndex++;
- if (m_items.isEmpty())
- break;
+ eventType = m_eventList->getType(i);
+ if (m_rowsExpanded[eventType])
+ itemRow = m_rowStarts[eventType]/DefaultRowHeight + m_eventList->eventPosInType(i);
+ else
+ itemRow = m_rowStarts[eventType]/DefaultRowHeight + m_eventList->getNestingLevel(i)-1;
+ if (itemRow == row) {
+ // match
+ m_currentSelection.eventIndex = i;
+ m_currentSelection.startTime = m_eventList->getStartTime(i);
+ m_currentSelection.endTime = m_eventList->getEndTime(i);
+ m_currentSelection.row = row;
+ if (!m_selectionLocked)
+ setSelectedItem(i);
+ return;
+ }
}
- emit cachedProgressChanged();
- QTimer::singleShot(CACHE_UPDATEDELAY, this, SLOT(purgeCache()));
+ m_currentSelection.eventIndex = -1;
+ return;
+}
+
+void TimelineView::clearData()
+{
+ m_startTime = 0;
+ m_endTime = 0;
+ m_lastStartTime = 0;
+ m_lastEndTime = 0;
+ m_currentSelection.startTime = -1;
+ m_currentSelection.endTime = -1;
+ m_currentSelection.row = -1;
+ m_currentSelection.eventIndex = -1;
+ m_selectedItem = -1;
+ m_selectionLocked = true;
}
qint64 TimelineView::getDuration(int index) const
@@ -277,3 +328,65 @@ QString TimelineView::getDetails(int index) const
Q_ASSERT(m_eventList);
return m_eventList->getDetails(index);
}
+
+void TimelineView::rowExpanded(int rowIndex, bool expanded)
+{
+ m_rowsExpanded[rowIndex] = expanded;
+ update();
+}
+
+void TimelineView::selectNext()
+{
+ if (m_eventList->count() == 0)
+ return;
+
+ if (m_selectionLocked && m_selectedItem !=-1 ) {
+ // find next item with same hashId
+ int hashId = m_eventList->getHash(m_selectedItem);
+ int i = m_selectedItem+1;
+ while (i<m_eventList->count() && m_eventList->getHash(i) != hashId)
+ i++;
+ if (i == m_eventList->count()) {
+ i = 0;
+ while (i<m_selectedItem && m_eventList->getHash(i) != hashId)
+ i++;
+ }
+ setSelectedItem(i);
+ } else {
+ // select next in view or after
+ int newIndex = m_selectedItem+1;
+ if (newIndex >= m_eventList->count())
+ newIndex = 0;
+ if (m_eventList->getEndTime(newIndex) < m_startTime)
+ newIndex = m_eventList->findFirstIndexNoParents(m_startTime);
+ setSelectedItem(newIndex);
+ }
+}
+
+void TimelineView::selectPrev()
+{
+ if (m_eventList->count() == 0)
+ return;
+
+ if (m_selectionLocked && m_selectedItem !=-1) {
+ // find previous item with same hashId
+ int hashId = m_eventList->getHash(m_selectedItem);
+ int i = m_selectedItem-1;
+ while (i>-1 && m_eventList->getHash(i) != hashId)
+ i--;
+ if (i == -1) {
+ i = m_eventList->count()-1;
+ while (i>m_selectedItem && m_eventList->getHash(i) != hashId)
+ i--;
+ }
+ setSelectedItem(i);
+ } else {
+ // select last in view or before
+ int newIndex = m_selectedItem-1;
+ if (newIndex < 0)
+ newIndex = m_eventList->count()-1;
+ if (m_eventList->getStartTime(newIndex) > m_endTime)
+ newIndex = m_eventList->findLastIndex(m_endTime);
+ setSelectedItem(newIndex);
+ }
+}
diff --git a/src/plugins/qmlprofiler/timelineview.h b/src/plugins/qmlprofiler/timelineview.h
index 1979c4c1b9..2830b503f7 100644
--- a/src/plugins/qmlprofiler/timelineview.h
+++ b/src/plugins/qmlprofiler/timelineview.h
@@ -43,21 +43,17 @@ namespace Internal {
class TimelineView : public QDeclarativeItem
{
Q_OBJECT
- Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
Q_PROPERTY(qint64 startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
Q_PROPERTY(qint64 endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged)
- Q_PROPERTY(qreal totalWidth READ totalWidth NOTIFY totalWidthChanged)
Q_PROPERTY(QObject* eventList READ eventList WRITE setEventList NOTIFY eventListChanged)
- Q_PROPERTY(qreal cachedProgress READ cachedProgress NOTIFY cachedProgressChanged)
+ Q_PROPERTY(bool selectionLocked READ selectionLocked WRITE setSelectionLocked NOTIFY selectionLockedChanged)
+ Q_PROPERTY(int selectedItem READ selectedItem WRITE setSelectedItem NOTIFY selectedItemChanged)
+ Q_PROPERTY(int startDragArea READ startDragArea WRITE setStartDragArea NOTIFY startDragAreaChanged)
+ Q_PROPERTY(int endDragArea READ endDragArea WRITE setEndDragArea NOTIFY endDragAreaChanged)
public:
explicit TimelineView(QDeclarativeItem *parent = 0);
- QDeclarativeComponent * delegate() const
- {
- return m_delegate;
- }
-
qint64 startTime() const
{
return m_startTime;
@@ -68,12 +64,25 @@ public:
return m_endTime;
}
- qreal totalWidth() const
+ bool selectionLocked() const
+ {
+ return m_selectionLocked;
+ }
+
+ int selectedItem() const
+ {
+ return m_selectedItem;
+ }
+
+ int startDragArea() const
{
- return m_totalWidth;
+ return m_startDragArea;
}
- qreal cachedProgress() const;
+ int endDragArea() const
+ {
+ return m_endDragArea;
+ }
QmlJsDebugClient::QmlProfilerEventList *eventList() const { return m_eventList; }
void setEventList(QObject *eventList)
@@ -82,33 +91,30 @@ public:
emit eventListChanged(m_eventList);
}
+ Q_INVOKABLE void selectNext();
+ Q_INVOKABLE void selectPrev();
+
+ Q_INVOKABLE void rowExpanded(int rowIndex, bool expanded);
+
Q_INVOKABLE qint64 getDuration(int index) const;
Q_INVOKABLE QString getFilename(int index) const;
Q_INVOKABLE int getLine(int index) const;
Q_INVOKABLE QString getDetails(int index) const;
- Q_INVOKABLE void rebuildCache();
signals:
- void delegateChanged(QDeclarativeComponent * arg);
void startTimeChanged(qint64 arg);
void endTimeChanged(qint64 arg);
- void totalWidthChanged(qreal arg);
void eventListChanged(QmlJsDebugClient::QmlProfilerEventList *list);
-
- void cachedProgressChanged();
- void cacheReady();
+ void selectionLockedChanged(bool locked);
+ void selectedItemChanged(int itemIndex);
+ void startDragAreaChanged(int startDragArea);
+ void endDragAreaChanged(int endDragArea);
+ void itemPressed(int pressedItem);
public slots:
void clearData();
- void updateTimeline();
+ void requestPaint();
- void setDelegate(QDeclarativeComponent * arg)
- {
- if (m_delegate != arg) {
- m_delegate = arg;
- emit delegateChanged(arg);
- }
- }
void setStartTime(qint64 arg)
{
@@ -126,34 +132,82 @@ public slots:
}
}
+ void setSelectionLocked(bool locked)
+ {
+ if (m_selectionLocked != locked) {
+ m_selectionLocked = locked;
+ emit selectionLockedChanged(locked);
+ }
+ }
+
+ void setSelectedItem(int itemIndex)
+ {
+ if (m_selectedItem != itemIndex) {
+ m_selectedItem = itemIndex;
+ update();
+ emit selectedItemChanged(itemIndex);
+ }
+ }
+
+ void setStartDragArea(int startDragArea)
+ {
+ if (m_startDragArea != startDragArea) {
+ m_startDragArea = startDragArea;
+ emit startDragAreaChanged(startDragArea);
+ }
+ }
+
+ void setEndDragArea(int endDragArea)
+ {
+ if (m_endDragArea != endDragArea) {
+ m_endDragArea = endDragArea;
+ emit endDragAreaChanged(endDragArea);
+ }
+ }
+
protected:
- void componentComplete();
+ virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
+ virtual void componentComplete();
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
private:
- void createItem(int itemIndex);
- void updateItemPosition(int itemIndex);
+ QColor colorForItem(int itemIndex);
+ QLinearGradient *gradientForItem(int itemIndex);
+ void drawItemsToPainter(QPainter *p, int fromIndex, int toIndex);
+ void drawSelectionBoxes(QPainter *p);
-public slots:
- void increaseCache();
- void purgeCache();
+ void manageClicked();
+ void manageHovered(int x, int y);
private:
- QDeclarativeComponent * m_delegate;
- QHash<int,QDeclarativeItem*> m_items;
- qint64 m_itemCount;
qint64 m_startTime;
qint64 m_endTime;
qreal m_spacing;
- int prevMin;
- int prevMax;
+ qint64 m_lastStartTime;
+ qint64 m_lastEndTime;
QmlJsDebugClient::QmlProfilerEventList *m_eventList;
-
- qreal m_totalWidth;
- int m_lastCachedIndex;
- bool m_creatingCache;
- int m_oldCacheSize;
-
+ QHash<int, QLinearGradient*> m_hashedGradients;
+
+ QList<int> m_rowLastX;
+ QList<int> m_rowStarts;
+ QList<int> m_rowWidths;
+ QList<bool> m_rowsExpanded;
+
+ struct {
+ qint64 startTime;
+ qint64 endTime;
+ int row;
+ int eventIndex;
+ } m_currentSelection;
+
+ int m_selectedItem;
+ bool m_selectionLocked;
+ int m_startDragArea;
+ int m_endDragArea;
};
} // namespace Internal
diff --git a/src/plugins/qmlprofiler/tracewindow.cpp b/src/plugins/qmlprofiler/tracewindow.cpp
index f201ffe069..406590a557 100644
--- a/src/plugins/qmlprofiler/tracewindow.cpp
+++ b/src/plugins/qmlprofiler/tracewindow.cpp
@@ -174,6 +174,16 @@ QWidget *TraceWindow::createToolbar()
connect(this, SIGNAL(enableToolbar(bool)), m_buttonRange, SLOT(setEnabled(bool)));
connect(this, SIGNAL(rangeModeChanged(bool)), m_buttonRange, SLOT(setChecked(bool)));
+ m_buttonLock = new QToolButton;
+ m_buttonLock->setIcon(QIcon(":/qmlprofiler/arrow_select.png"));
+ m_buttonLock->setToolTip(tr("View event information on mouseover"));
+ m_buttonLock->setCheckable(true);
+ m_buttonLock->setChecked(false);
+ connect(m_buttonLock, SIGNAL(clicked(bool)), this, SLOT(toggleLockMode(bool)));
+ connect(this, SIGNAL(enableToolbar(bool)), m_buttonLock, SLOT(setEnabled(bool)));
+ connect(this, SIGNAL(lockModeChanged(bool)), m_buttonLock, SLOT(setChecked(bool)));
+
+ toolBarLayout->addWidget(m_buttonLock);
toolBarLayout->addWidget(buttonPrev);
toolBarLayout->addWidget(buttonNext);
toolBarLayout->addWidget(buttonZoomControls);
@@ -264,6 +274,7 @@ void TraceWindow::reset(QDeclarativeDebugConnection *conn)
connect(m_mainView->rootObject(), SIGNAL(updateCursorPosition()), this, SLOT(updateCursorPosition()));
connect(m_mainView->rootObject(), SIGNAL(updateTimer()), this, SLOT(updateTimer()));
connect(m_mainView->rootObject(), SIGNAL(updateRangeButton()), this, SLOT(updateRangeButton()));
+ connect(m_mainView->rootObject(), SIGNAL(updateLockButton()), this, SLOT(updateLockButton()));
connect(m_eventList, SIGNAL(countChanged()), this, SLOT(updateToolbar()));
connect(this, SIGNAL(jumpToPrev()), m_mainView->rootObject(), SLOT(prevEvent()));
connect(this, SIGNAL(jumpToNext()), m_mainView->rootObject(), SLOT(nextEvent()));
@@ -340,6 +351,21 @@ void TraceWindow::updateRangeButton()
emit rangeModeChanged(rangeMode);
}
+void TraceWindow::toggleLockMode(bool active)
+{
+ bool lockMode = !m_mainView->rootObject()->property("selectionLocked").toBool();
+ if (active != lockMode) {
+ m_mainView->rootObject()->setProperty("selectionLocked", QVariant(!active));
+ m_mainView->rootObject()->setProperty("selectedItem", QVariant(-1));
+ }
+}
+
+void TraceWindow::updateLockButton()
+{
+ bool lockMode = !m_mainView->rootObject()->property("selectionLocked").toBool();
+ emit lockModeChanged(lockMode);
+}
+
void TraceWindow::setRecording(bool recording)
{
if (recording) {
diff --git a/src/plugins/qmlprofiler/tracewindow.h b/src/plugins/qmlprofiler/tracewindow.h
index a0a9f74546..3ae9b017d2 100644
--- a/src/plugins/qmlprofiler/tracewindow.h
+++ b/src/plugins/qmlprofiler/tracewindow.h
@@ -103,7 +103,9 @@ public slots:
void clearDisplay();
void updateToolbar();
void toggleRangeMode(bool);
+ void toggleLockMode(bool);
void updateRangeButton();
+ void updateLockButton();
void setZoomLevel(int zoomLevel);
void updateRange();
void mouseWheelMoved(int x, int y, int delta);
@@ -124,6 +126,7 @@ signals:
void jumpToPrev();
void jumpToNext();
void rangeModeChanged(bool);
+ void lockModeChanged(bool);
void enableToolbar(bool);
void zoomLevelChanged(int);
void updateViewZoom(QVariant zoomLevel);
@@ -155,6 +158,7 @@ private:
QWeakPointer<ZoomControl> m_zoomControl;
QToolButton *m_buttonRange;
+ QToolButton *m_buttonLock;
QWidget *m_zoomToolbar;
int m_currentZoomLevel;
};