diff --git a/src/plugins/qmlprofiler/canvas/qdeclarativetiledcanvas.cpp b/src/plugins/qmlprofiler/canvas/qdeclarativetiledcanvas.cpp index e0c06133cee..ce971a5404b 100644 --- a/src/plugins/qmlprofiler/canvas/qdeclarativetiledcanvas.cpp +++ b/src/plugins/qmlprofiler/canvas/qdeclarativetiledcanvas.cpp @@ -145,7 +145,6 @@ void TiledCanvas::componentComplete() void TiledCanvas::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_UNUSED(event); - qWarning("MPE"); } QPixmap TiledCanvas::getTile(int xx, int yy) diff --git a/src/plugins/qmlprofiler/qml/Detail.qml b/src/plugins/qmlprofiler/qml/Detail.qml index c0ec386b846..1b4e1c4192a 100644 --- a/src/plugins/qmlprofiler/qml/Detail.qml +++ b/src/plugins/qmlprofiler/qml/Detail.qml @@ -32,7 +32,6 @@ import QtQuick 1.0 import Monitor 1.0 -import "MainView.js" as Plotter Item { id: detail diff --git a/src/plugins/qmlprofiler/qml/MainView.qml b/src/plugins/qmlprofiler/qml/MainView.qml index 9ce00ae917d..a3e30a1a49f 100644 --- a/src/plugins/qmlprofiler/qml/MainView.qml +++ b/src/plugins/qmlprofiler/qml/MainView.qml @@ -32,21 +32,84 @@ import QtQuick 1.0 import Monitor 1.0 -import "MainView.js" as Plotter Rectangle { id: root - property bool dataAvailable: true; - property int eventCount: 0; - property real progress: 0; + // ***** properties + + property int candidateHeight: 0 + height: Math.max( candidateHeight, labels.rowCount * 50 + 2 ) + + property bool dataAvailable: true + property int eventCount: 0 + property real progress: 0 property bool mouseOverSelection : true - // move the cursor in the editor + 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" ] + + property variant mainviewTimePerPixel : 0 + signal updateCursorPosition property string fileName: "" property int lineNumber: -1 + + property int selectedEventIndex : -1 + property bool mouseTracking: false + + property real elapsedTime + signal updateTimer + + // ***** connections with external objects + Connections { + target: zoomControl + onRangeChanged: { + var startTime = zoomControl.startTime(); + var endTime = zoomControl.endTime(); + var duration = Math.abs(endTime - startTime); + + mainviewTimePerPixel = duration / root.width; + + backgroundMarks.updateMarks(startTime, endTime); + view.updateFlickRange(startTime, endTime); + if (duration > 0) { + var candidateWidth = qmlEventList.traceEndTime() * flick.width / duration; + if (flick.contentWidth !== candidateWidth) + flick.contentWidth = candidateWidth; + } + + } + } + + Connections { + target: qmlEventList + onCountChanged: { + eventCount = qmlEventList.count(); + if (eventCount === 0) + root.clearAll(); + if (eventCount > 1) { + root.progress = Math.min(1.0, + (qmlEventList.lastTimeMark() - qmlEventList.traceStartTime()) / root.elapsedTime * 1e-9 ) * 0.5; + } else { + root.progress = 0; + } + } + + onParsingStatusChanged: { + root.dataAvailable = false; + } + + onDataReady: { + if (eventCount > 0) { + view.clearData(); + view.rebuildCache(); + } + } + } + + // ***** functions function gotoSourceLocation(file,line) { root.fileName = file; root.lineNumber = line; @@ -54,19 +117,15 @@ Rectangle { } function clearData() { - Plotter.reset(); view.clearData(); root.dataAvailable = false; root.eventCount = 0; - rangeMover.x = 2 - rangeMover.opacity = 0 hideRangeDetails(); } function clearDisplay() { clearData(); selectedEventIndex = -1; - canvas.requestPaint(); view.visible = false; } @@ -76,30 +135,6 @@ Rectangle { root.updateTimer(); } - property int selectedEventIndex : -1; - property bool mouseTracking: false; - - onSelectedEventIndexChanged: { - if ((!mouseTracking) && eventCount > 0 - && selectedEventIndex > -1 && selectedEventIndex < eventCount) { - // re-center flickable if necessary - var xs = Plotter.xScale(canvas); - var startTime = qmlEventList.traceStartTime(); - var eventStartTime = qmlEventList.getStartTime(selectedEventIndex); - var eventDuration = qmlEventList.getDuration(selectedEventIndex); - if (rangeMover.value + startTime > eventStartTime) { - rangeMover.x = Math.max(0, - Math.floor((eventStartTime - startTime) / xs - canvas.canvasWindow.x - rangeMover.zoomWidth/2) ); - } else if (rangeMover.value + startTime + rangeMover.zoomWidth * xs < eventStartTime + eventDuration) { - rangeMover.x = Math.floor((eventStartTime + eventDuration - startTime) / xs - canvas.canvasWindow.x - rangeMover.zoomWidth/2); - } - } - - if (selectedEventIndex == -1) { - selectionHighlight.visible = false; - } - } - function nextEvent() { if (eventCount > 0) { ++selectedEventIndex; @@ -117,169 +152,190 @@ Rectangle { } function zoomIn() { - // 10% - var newZoom = rangeMover.zoomWidth / 1.1; - - // 0.1 ms minimum zoom - if (newZoom * Plotter.xScale(canvas) > 100000) { - rangeMover.zoomWidth = newZoom - rangeMover.updateZoomControls(); - } + updateZoom( 1/1.1 ); } function zoomOut() { - // 10% - var newZoom = rangeMover.zoomWidth * 1.1; - if (newZoom > canvas.width) - newZoom = canvas.width; - if (newZoom + rangeMover.x > canvas.width) - rangeMover.x = canvas.width - newZoom; - rangeMover.zoomWidth = newZoom; - rangeMover.updateZoomControls(); + updateZoom( 1.1 ); } - Connections { - target: qmlEventList - onCountChanged: { - eventCount = qmlEventList.count(); - if (eventCount == 0) - root.clearAll(); - if (eventCount > 1) { - root.progress = Math.min(1.0, - (qmlEventList.traceEndTime() - qmlEventList.traceStartTime()) / root.elapsedTime * 1e-9 ) * 0.5; - } else - root.progress = 0; + function updateZoom(factor) { + var min_length = 1e5; // 0.1 ms + var windowLength = view.endTime - view.startTime; + if (windowLength < min_length) + windowLength = min_length; + var newWindowLength = windowLength * factor; + + if (newWindowLength > qmlEventList.traceEndTime()) { + newWindowLength = qmlEventList.traceEndTime(); + factor = newWindowLength / windowLength; + } + if (newWindowLength < min_length) { + newWindowLength = min_length; + factor = newWindowLength / windowLength; } - onParsingStatusChanged: { - root.dataAvailable = false; + var fixedPoint = (view.startTime + view.endTime) / 2; + if (root.selectedEventIndex !== -1) { + // center on selected item if it's inside the current screen + var newFixedPoint = qmlEventList.getStartTime(selectedEventIndex); + if (newFixedPoint >= view.startTime && newFixedPoint < view.endTime) + fixedPoint = newFixedPoint; } - onDataReady: { - if (eventCount > 0) { - view.clearData(); - view.rebuildCache(); + var startTime = fixedPoint - factor*(fixedPoint - view.startTime); + zoomControl.setRange(startTime, startTime + newWindowLength); + } + + function hideRangeDetails() { + rangeDetails.visible = false; + rangeDetails.duration = ""; + rangeDetails.label = ""; + 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; } - // Elapsed - property real elapsedTime; - signal updateTimer; + // ***** child items Timer { id: elapsedTimer property date startDate property bool reset: true running: connection.recording repeat: true - onRunningChanged: if (running) reset = true + onRunningChanged: { + if (running) reset = true; + } interval: 100 triggeredOnStart: true onTriggered: { if (reset) { - startDate = new Date() - reset = false + startDate = new Date(); + reset = false; } - var time = (new Date() - startDate)/1000 + var time = (new Date() - startDate)/1000; root.elapsedTime = time.toFixed(1); root.updateTimer(); } } - // time markers - TimeDisplay { - height: flick.height + labels.y + TimeMarks { + id: backgroundMarks + y: labels.y + height: flick.height anchors.left: flick.left anchors.right: flick.right - startTime: rangeMover.x * Plotter.xScale(canvas) + qmlEventList.traceStartTime(); - endTime: (rangeMover.x + rangeMover.zoomWidth) * Plotter.xScale(canvas) + qmlEventList.traceStartTime(); } - function hideRangeDetails() { - rangeDetails.visible = false - rangeDetails.duration = "" - rangeDetails.label = "" - rangeDetails.type = "" - rangeDetails.file = "" - rangeDetails.line = -1 - - root.mouseOverSelection = true; - selectionHighlight.visible = false; - } - - //our main interaction view Flickable { id: flick anchors.top: parent.top anchors.topMargin: labels.y anchors.right: parent.right anchors.left: labels.right - anchors.bottom: canvas.top - contentWidth: view.totalWidth - contentHeight: height + height: root.height + contentWidth: 0; + contentHeight: labels.rowCount * 50 flickableDirection: Flickable.HorizontalFlick + onContentXChanged: { + if (Math.round(view.startX) !== contentX) + view.startX = contentX; + } + clip:true TimelineView { id: view - eventList: qmlEventList; - onEventListChanged: Plotter.qmlEventList = qmlEventList; + eventList: qmlEventList - width: flick.width; - height: flick.contentHeight; + width: flick.width + height: flick.contentHeight - startX: flick.contentX + property variant startX: 0 onStartXChanged: { - var newX = startTime / Plotter.xScale(canvas) - canvas.canvasWindow.x; - if (Math.abs(rangeMover.x - newX) > .01) - rangeMover.x = newX - if (Math.abs(startX - flick.contentX) > .01) - flick.contentX = startX + var newStartTime = Math.round(startX * (endTime - startTime) / flick.width); + if (Math.abs(newStartTime - startTime) > 1) { + var newEndTime = Math.round((startX+flick.width)* (endTime - startTime) / flick.width); + zoomControl.setRange(newStartTime, newEndTime); + } + + if (Math.round(startX) !== flick.contentX) + flick.contentX = startX; } - startTime: rangeMover.value - endTime: startTime + (rangeMover.zoomWidth*Plotter.xScale(canvas)) - onEndTimeChanged: { - updateTimeline(); + + function updateFlickRange(start, end) { + if (start !== startTime || end !== endTime) { + startTime = start; + endTime = end; + 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) { + if (selectedEventIndex !== -1 && selectionHighlight.visible) { var spacing = flick.width / timeSpan; - selectionHighlight.x = (qmlEventList.getStartTime(selectedEventIndex) - qmlEventList.firstTimeMark()) * spacing; + selectionHighlight.x = (qmlEventList.getStartTime(selectedEventIndex) - qmlEventList.traceStartTime()) * spacing; selectionHighlight.width = qmlEventList.getDuration(selectedEventIndex) * spacing; } } - onCachedProgressChanged: root.progress = 0.5 + cachedProgress * 0.5; + 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(); - canvas.requestPaint(); - rangeMover.x = 1 //### hack to get view to display things immediately - rangeMover.x = 0 - rangeMover.opacity = 1 + zoomControl.setRange(0, qmlEventList.traceEndTime()/10); } } delegate: Rectangle { id: obj - property color myColor: Plotter.colors[type] + property color myColor: root.colors[type] function conditionalHide() { if (!mouseArea.containsMouse) mouseArea.exited() } - property int baseY: type * view.height / labels.rowCount; + property int baseY: type * view.height / labels.rowCount property int baseHeight: view.height / labels.rowCount - y: baseY + (nestingLevel-1)*(baseHeight / nestingDepth); - height: baseHeight / nestingDepth; + 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) } @@ -294,7 +350,10 @@ Rectangle { } property bool isSelected: root.selectedEventIndex == index; - onIsSelectedChanged: updateDetails(); + onIsSelectedChanged: { + updateDetails(); + } + function updateDetails() { if (!root.mouseTracking && componentIsCompleted) { if (isSelected) { @@ -308,9 +367,9 @@ Rectangle { rangeDetails.label = qmlEventList.getDetails(index); rangeDetails.file = qmlEventList.getFilename(index); rangeDetails.line = qmlEventList.getLine(index); - rangeDetails.type = Plotter.names[type] + rangeDetails.type = root.names[type]; - rangeDetails.visible = true + rangeDetails.visible = true; selectionHighlight.x = obj.x; selectionHighlight.y = obj.y; @@ -358,11 +417,13 @@ Rectangle { width: parent.width height: parent.height x: flick.contentX - onClicked: root.hideRangeDetails(); + onClicked: { + root.hideRangeDetails(); + } } } } - //popup showing the details for the hovered range + RangeDetails { id: rangeDetails } @@ -371,19 +432,19 @@ Rectangle { id: labels width: 150 color: "#dcdcdc" - y: 24 - height: flick.height + height: flick.contentHeight property int rowCount: 5 Column { id: col - //### change to use Repeater + Plotter.names? - Label { text: qsTr("Painting"); height: labels.height/labels.rowCount} - Label { text: qsTr("Compiling"); height: labels.height/labels.rowCount } - Label { text: qsTr("Creating"); height: labels.height/labels.rowCount } - Label { text: qsTr("Binding"); height: labels.height/labels.rowCount } - Label { text: qsTr("Signal Handler"); height: labels.height/labels.rowCount } + Repeater { + model: labels.rowCount + delegate: Label { + text: root.names[index] + height: labels.height/labels.rowCount + } + } } //right border divider @@ -395,112 +456,17 @@ Rectangle { } } - //bottom border divider Rectangle { - height: 1 - width: parent.width - anchors.bottom: canvas.top - color: "#cccccc" - } - - //"overview" graph at the bottom - TiledCanvas { - id: canvas - - anchors.bottom: parent.bottom - width: parent.width; height: 50 - - property int canvasWidth: width - - canvasSize { - width: canvasWidth - height: canvas.height - } - - tileSize.width: width - tileSize.height: height - - canvasWindow.width: width - canvasWindow.height: height - - onDrawRegion: { - if (root.dataAvailable) - Plotter.plot(canvas, ctxt, region); - else - Plotter.drawGraph(canvas, ctxt, region) //just draw the background - } - } - - //moves the range mover to the position of a click - MouseArea { - anchors.fill: canvas - //### ideally we could press to position then immediately drag - onPressed: rangeMover.x = mouse.x - rangeMover.zoomWidth/2 - } - - RangeMover { - id: rangeMover - opacity: 0 - anchors.top: canvas.top - } - - // the next elements are here because I want them rendered on top of the other - Rectangle { - id: timeDisplayLabel - color: "lightsteelblue" - border.color: Qt.darker(color) - border.width: 1 - radius: 2 - height: Math.max(labels.y-2, timeDisplayText.height); - y: timeDisplayEnd.visible ? flick.height - 1 : 1 - width: timeDisplayText.width + 10 + ( timeDisplayEnd.visible ? timeDisplayCloseControl.width + 10 : 0 ) - visible: false - - function hideAll() { - timeDisplayBegin.visible = false; - timeDisplayEnd.visible = false; - timeDisplayLabel.visible = false; - } - Text { - id: timeDisplayText - x: 5 - y: parent.height/2 - height/2 + 1 - font.pointSize: 8 - } - - Text { - id: timeDisplayCloseControl - text:"X" - anchors.right: parent.right - anchors.rightMargin: 3 - y: parent.height/2 - height/2 + 1 - visible: timeDisplayEnd.visible - MouseArea { - anchors.fill: parent - onClicked: { - timeDisplayLabel.hideAll(); - } - } - } - } - - Rectangle { - id: timeDisplayBegin - width: 1 - color: Qt.rgba(0,0,64,0.7); - height: flick.height + labels.y - visible: false - } - - Rectangle { - id: timeDisplayEnd - width: 1 - color: Qt.rgba(0,0,64,0.7); - height: flick.height + labels.y - visible: false + id: labelsTail + anchors.top: labels.bottom + anchors.bottom: root.bottom + width: labels.width + color: labels.color } StatusDisplay { - anchors.centerIn: flick + anchors.horizontalCenter: flick.horizontalCenter + anchors.verticalCenter: labels.verticalCenter + z:3 } } diff --git a/src/plugins/qmlprofiler/qml/MainView.js b/src/plugins/qmlprofiler/qml/Overview.js similarity index 69% rename from src/plugins/qmlprofiler/qml/MainView.js rename to src/plugins/qmlprofiler/qml/Overview.js index 4d881b0cfed..7c2ad698dc8 100644 --- a/src/plugins/qmlprofiler/qml/MainView.js +++ b/src/plugins/qmlprofiler/qml/Overview.js @@ -32,22 +32,8 @@ .pragma library -var xmargin = 0; -var ymargin = 0; var qmlEventList = 0; -var names = [ qsTr("Painting"), qsTr("Compiling"), qsTr("Creating"), qsTr("Binding"), qsTr("Handling Signal")] -//### need better way to manipulate color from QML. In the meantime, these need to be kept in sync. -var colors = [ "#99CCB3", "#99CCCC", "#99B3CC", "#9999CC", "#CC99B3", "#CC99CC", "#CCCC99", "#CCB399" ]; -var origColors = [ "#99CCB3", "#99CCCC", "#99B3CC", "#9999CC", "#CC99B3", "#CC99CC", "#CCCC99", "#CCB399" ]; -var xRayColors = [ "#6699CCB3", "#6699CCCC", "#6699B3CC", "#669999CC", "#66CC99B3", "#66CC99CC", "#66CCCC99", "#66CCB399" ]; - -function reset() -{ - xmargin = 0; - ymargin = 0; -} - //draw background of the graph function drawGraph(canvas, ctxt, region) { @@ -56,7 +42,7 @@ function drawGraph(canvas, ctxt, region) grad.addColorStop(1, '#ccc'); ctxt.fillStyle = grad; - ctxt.fillRect(0, 0, canvas.canvasSize.width + xmargin, canvas.canvasSize.height - ymargin); + ctxt.fillRect(0, 0, canvas.canvasSize.width, canvas.canvasSize.height); } //draw the actual data to be graphed @@ -65,8 +51,8 @@ function drawData(canvas, ctxt, region) if ((!qmlEventList) || qmlEventList.count() == 0) return; - var width = canvas.canvasSize.width - xmargin; - var height = canvas.height - ymargin; + var width = canvas.canvasSize.width; + var height = canvas.height; var sumValue = qmlEventList.traceEndTime() - qmlEventList.traceStartTime(); var spacing = width / sumValue; @@ -74,10 +60,11 @@ function drawData(canvas, ctxt, region) ctxt.fillStyle = "rgba(0,0,0,1)"; var highest = [0,0,0,0,0]; + // todo: use "region" in the timemarks? //### only draw those in range for (var ii = 0; ii < qmlEventList.count(); ++ii) { - var xx = (qmlEventList.getStartTime(ii) - qmlEventList.traceStartTime()) * spacing + xmargin; + var xx = (qmlEventList.getStartTime(ii) - qmlEventList.traceStartTime()) * spacing; if (xx > region.x + region.width) continue; @@ -102,15 +89,3 @@ function plot(canvas, ctxt, region) drawGraph(canvas, ctxt, region); drawData(canvas, ctxt, region); } - -function xScale(canvas) -{ - if ((!qmlEventList) || qmlEventList.count() == 0) - return; - - var width = canvas.canvasSize.width - xmargin; - - var sumValue = qmlEventList.traceEndTime() - qmlEventList.traceStartTime(); - var spacing = sumValue / width; - return spacing; -} diff --git a/src/plugins/qmlprofiler/qml/Overview.qml b/src/plugins/qmlprofiler/qml/Overview.qml new file mode 100644 index 00000000000..c98bcdbfde1 --- /dev/null +++ b/src/plugins/qmlprofiler/qml/Overview.qml @@ -0,0 +1,138 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +import QtQuick 1.0 +import Monitor 1.0 +import "Overview.js" as Plotter + +TiledCanvas { + id: canvas + + // ***** properties + height: 50 + property bool dataAvailable: false + property variant startTime : 0 + property variant endTime : 0 + + canvasSize.width: canvas.width + canvasSize.height: canvas.height + + tileSize.width: width + tileSize.height: height + + canvasWindow.width: width + canvasWindow.height: height + + // ***** functions + function clearDisplay() + { + dataAvailable = false; + requestPaint(); + } + + function updateRange() { + var newStartTime = Math.round(rangeMover.x * qmlEventList.traceEndTime() / width); + var newEndTime = Math.round((rangeMover.x + rangeMover.width) * qmlEventList.traceEndTime() / width); + if (startTime !== newStartTime || endTime !== newEndTime) { + zoomControl.setRange(newStartTime, newEndTime); + } + } + + // ***** connections to external objects + Connections { + target: zoomControl + onRangeChanged: { + if (qmlEventList) { + startTime = zoomControl.startTime(); + endTime = zoomControl.endTime(); + var newRangeX = startTime * width / qmlEventList.traceEndTime(); + if (rangeMover.x !== newRangeX) + rangeMover.x = newRangeX; + var newWidth = (endTime-startTime) * width / qmlEventList.traceEndTime(); + if (rangeMover.width !== newWidth) + rangeMover.width = newWidth; + } + } + } + + Connections { + target: qmlEventList + onDataReady: { + if (qmlEventList.count() > 0) { + dataAvailable = true; + requestPaint(); + } + } + } + + // ***** slots + onDrawRegion: { + if (dataAvailable) + Plotter.plot(canvas, ctxt, region); + else { + Plotter.qmlEventList = qmlEventList; + Plotter.drawGraph(canvas, ctxt, region) //just draw the background + } + } + + // ***** child items + MouseArea { + anchors.fill: canvas + function jumpTo(posX) { + var newX = posX - rangeMover.width/2; + if (newX < 0) + newX = 0; + if (newX + rangeMover.width > canvas.width) + newX = canvas.width - rangeMover.width; + rangeMover.x = newX; + updateRange(); + } + + onPressed: { + jumpTo(mouse.x); + } + onMousePositionChanged: { + jumpTo(mouse.x); + } + } + + RangeMover { + id: rangeMover + visible: dataAvailable + } + + Rectangle { + height: 1 + width: parent.width + color: "#cccccc" + } +} diff --git a/src/plugins/qmlprofiler/qml/RangeDetails.qml b/src/plugins/qmlprofiler/qml/RangeDetails.qml index 91d9be162e3..306fa4e76e0 100644 --- a/src/plugins/qmlprofiler/qml/RangeDetails.qml +++ b/src/plugins/qmlprofiler/qml/RangeDetails.qml @@ -32,7 +32,6 @@ import QtQuick 1.0 import Monitor 1.0 -import "MainView.js" as Plotter BorderImage { id: rangeDetails @@ -56,7 +55,7 @@ BorderImage { z: 1 visible: false x: 200 - y: 200 + y: 25 //title Text { @@ -99,13 +98,12 @@ BorderImage { opacity: content.length !== 0 ? 1 : 0 label: qsTr("Location") content: { - var file = rangeDetails.file - var pos = file.lastIndexOf("/") + var file = rangeDetails.file; + var pos = file.lastIndexOf("/"); if (pos != -1) - file = file.substr(pos+1) + file = file.substr(pos+1); return (file.length !== 0) ? (file + ":" + rangeDetails.line) : ""; } - onLinkActivated: Qt.openUrlExternally(url) } } @@ -119,7 +117,9 @@ BorderImage { height: 12 MouseArea { anchors.fill: parent - onClicked: root.mouseOverSelection = !root.mouseOverSelection; + onClicked: { + root.mouseOverSelection = !root.mouseOverSelection; + } } } @@ -130,7 +130,9 @@ BorderImage { text:"X" MouseArea { anchors.fill: parent - onClicked: root.hideRangeDetails(); + onClicked: { + root.hideRangeDetails(); + } } } diff --git a/src/plugins/qmlprofiler/qml/RangeMover.qml b/src/plugins/qmlprofiler/qml/RangeMover.qml index 9366a00daea..e9407186405 100644 --- a/src/plugins/qmlprofiler/qml/RangeMover.qml +++ b/src/plugins/qmlprofiler/qml/RangeMover.qml @@ -30,124 +30,148 @@ ** **************************************************************************/ -import "MainView.js" as Plotter import QtQuick 1.0 -import Monitor 1.0 -Item { +Rectangle { id: rangeMover property color lighterColor:"#cc80b2f6" property color darkerColor:"#cc6da1e8" property color gapColor: "#666da1e8" - property real value: (canvas.canvasWindow.x + x) * Plotter.xScale(canvas) - property real zoomWidth: 20 - onZoomWidthChanged: timeDisplayLabel.hideAll(); + property color hardBorderColor: "blue" + width: 20 + height: 50 - function updateZoomControls() { - rightRange.x = rangeMover.width; + color: lighterColor + + property bool dragStarted: false + onXChanged: { + if (dragStarted) canvas.updateRange() } - onXChanged: updateZoomControls(); - - width: Math.max(rangeMover.zoomWidth, 20); height: 50 MouseArea { anchors.fill: parent drag.target: rangeMover drag.axis: "XAxis" drag.minimumX: 0 - drag.maximumX: canvas.width - rangeMover.zoomWidth //### - } - - Rectangle { - id: frame - color:"transparent" - anchors.fill: parent - anchors.rightMargin: 1 - anchors.bottomMargin: 1 - } - - Rectangle { - id: rect - color: lighterColor - width: parent.zoomWidth - height: parent.height - } - - Rectangle { - id: gapRect - color: gapColor - anchors.left: rect.right - anchors.right: rightRange.left - height: parent.height + drag.maximumX: canvas.width - rangeMover.width + onPressed: { + parent.dragStarted = true; + } + onReleased: { + parent.dragStarted = false; + } } Rectangle { id: leftRange - property int currentX: rangeMover.x - property int currentWidth : rangeMover.zoomWidth + // used for dragging the borders + property real initialX: 0 + property real initialWidth: 0 - x: -width + x: 0 height: parent.height - width: 15 + width: 1 color: darkerColor + border.color: hardBorderColor + border.width: 0 - Text { - anchors.centerIn: parent - text:"<" + states: State { + name: "highlighted" + PropertyChanges { + target: leftRange + width: 3 + border.width: 2 + } + } + + onXChanged: { + if (x !== 0) { + rangeMover.width = initialWidth - x; + rangeMover.x = initialX + x; + x = 0; + canvas.updateRange(); + } } MouseArea { - anchors.fill: parent + x: -3 + width: 7 + y: 0 + height: parent.height + drag.target: leftRange drag.axis: "XAxis" - drag.minimumX: -parent.currentX - drag.maximumX: parent.currentWidth - width - 1 - onPressed: { - parent.currentX = rangeMover.x; - parent.currentWidth = rangeMover.zoomWidth; + drag.minimumX: -parent.initialX + drag.maximumX: parent.initialWidth - 2 + + hoverEnabled: true + + onEntered: { + parent.state = "highlighted"; } - } - onXChanged: { - if (x + width != 0) { - rangeMover.zoomWidth = currentWidth - x - width; - rangeMover.x = currentX + x + width; - x = -width; + onExited: { + if (!pressed) parent.state = ""; + } + onReleased: { + if (!containsMouse) parent.state = ""; + } + onPressed: { + parent.initialX = rangeMover.x; + parent.initialWidth = rangeMover.width; } } } Rectangle { id: rightRange - property int currentX: rangeMover.x - property int widthSpace: rangeMover.width - rangeMover.zoomWidth - height: parent.height - width: 15 x: rangeMover.width - color: darkerColor; + height: parent.height + width: 1 + color: darkerColor + border.color: hardBorderColor + border.width: 0 - Text { - anchors.centerIn: parent - text:">" + states: State { + name: "highlighted" + PropertyChanges { + target: rightRange + width: 3 + border.width: 2 + } } + + onXChanged: { + if (x!=rangeMover.width) { + rangeMover.width = x; + canvas.updateRange(); + } + } + MouseArea { - anchors.fill: parent + x: -3 + width: 7 + y: 0 + height: parent.height + drag.target: rightRange drag.axis: "XAxis" - drag.minimumX: 1 + parent.widthSpace - drag.maximumX: canvas.width - parent.currentX; - onPressed: { - parent.currentX = rangeMover.x; - parent.widthSpace = rangeMover.width - rangeMover.zoomWidth; + drag.minimumX: 1 + drag.maximumX: canvas.width - rangeMover.x + + hoverEnabled: true + + onEntered: { + parent.state = "highlighted"; } - onReleased: rightRange.x = rangeMover.width; - } - onXChanged: { - if (x != rangeMover.width) { - rangeMover.zoomWidth = x - widthSpace; + onExited: { + if (!pressed) parent.state = ""; + } + onReleased: { + if (!containsMouse) parent.state = ""; } } } diff --git a/src/plugins/qmlprofiler/qml/StatusDisplay.qml b/src/plugins/qmlprofiler/qml/StatusDisplay.qml index 9bd33e0b61a..c969b968978 100644 --- a/src/plugins/qmlprofiler/qml/StatusDisplay.qml +++ b/src/plugins/qmlprofiler/qml/StatusDisplay.qml @@ -1,19 +1,18 @@ import QtQuick 1.0 -import "MainView.js" as Plotter Rectangle { id: statusDisplay property real percentage : root.progress - width: Math.max(200, statusText.width+20); + width: Math.max(200, statusText.width+20) height: displayColumn.height + 20 visible: false; color: "#CCD0CC" border.width: 1 - border.color: "#AAAEAA"; + border.color: "#AAAEAA" radius: 4 Column { @@ -42,7 +41,7 @@ Rectangle { x: 1 y: 1 width: (parent.width-1) * statusDisplay.percentage - color: Qt.rgba(0.37 + 0.2*(1 - statusDisplay.percentage), 0.58, 0.37, 1); + color: Qt.rgba(0.37 + 0.2*(1 - statusDisplay.percentage), 0.58, 0.37, 1) height: parent.height-1 } } @@ -51,7 +50,7 @@ Rectangle { states: [ // no data available State { - when: (root.eventCount == 0) && !elapsedTimer.running; + when: (root.eventCount == 0) && !elapsedTimer.running PropertyChanges { target: statusDisplay visible: true @@ -59,13 +58,15 @@ Rectangle { PropertyChanges { target: statusText - text: qsTr("No QML events recorded"); + text: qsTr("No QML events recorded") + } + onCompleted: { + root.clearDisplay(); } - onCompleted: root.clearDisplay(); }, // running app State { - when: elapsedTimer.running; + when: elapsedTimer.running PropertyChanges { target: statusDisplay visible: true @@ -73,13 +74,13 @@ Rectangle { PropertyChanges { target: statusText - text: qsTr("Profiling application"); + text: qsTr("Profiling application") } }, // loading data State { name: "loading" - when: (!root.dataAvailable) && (root.eventCount > 0); + when: (!root.dataAvailable) && (root.eventCount > 0) PropertyChanges { target: statusDisplay visible: true @@ -87,7 +88,7 @@ Rectangle { PropertyChanges { target: statusText - text: qsTr("Loading data"); + text: qsTr("Loading data") } PropertyChanges { diff --git a/src/plugins/qmlprofiler/qml/TimeDisplay.qml b/src/plugins/qmlprofiler/qml/TimeDisplay.qml index 06c84a70b06..b96740d9b56 100644 --- a/src/plugins/qmlprofiler/qml/TimeDisplay.qml +++ b/src/plugins/qmlprofiler/qml/TimeDisplay.qml @@ -32,37 +32,43 @@ import QtQuick 1.0 import Monitor 1.0 -import "MainView.js" as Plotter TiledCanvas { id: timeDisplay - canvasSize { - width: timeDisplay.width - height: timeDisplay.height - } + property variant startTime : 0 + property variant endTime : 0 + property variant timePerPixel: 0 + + canvasSize.width: timeDisplay.width + canvasSize.height: timeDisplay.height tileSize.width: width tileSize.height: height canvasWindow.width: width canvasWindow.height: height + Connections { + target: zoomControl + onRangeChanged: { + startTime = zoomControl.startTime(); + endTime = zoomControl.endTime(); + requestPaint(); + } + } Component.onCompleted: { requestPaint(); } - - property variant startTime; - property variant endTime; - - onStartTimeChanged: requestPaint(); - onEndTimeChanged: requestPaint(); - onWidthChanged: requestPaint(); - onHeightChanged: requestPaint(); - - property variant timePerPixel; + onWidthChanged: { + requestPaint(); + } + onHeightChanged: { + requestPaint(); + } onDrawRegion: { - drawBackgroundBars( ctxt, region ); + ctxt.fillStyle = "white"; + ctxt.fillRect(0, 0, width, height); var totalTime = endTime - startTime; var spacing = width / totalTime; @@ -89,32 +95,10 @@ TiledCanvas { ctxt.lineTo(x, height); ctxt.stroke(); - ctxt.strokeStyle = "#C0C0C0"; - for (var jj=1; jj < 5; jj++) { - var xx = Math.floor(ii*pixelsPerBlock + jj*pixelsPerSection - realStartPos); - ctxt.beginPath(); - ctxt.moveTo(xx, labels.y); - ctxt.lineTo(xx, height); - ctxt.stroke(); - } - - ctxt.fillText(prettyPrintTime(ii*timePerBlock + realStartTime), x + 5, 5 + labels.y/2); + ctxt.fillText(prettyPrintTime(ii*timePerBlock + realStartTime), x + 5, height/2 + 4); } } - function drawBackgroundBars( ctxt, region ) { - var barHeight = Math.round(labels.height / labels.rowCount); - var originY = labels.y - for (var i=0; i Detail.qml Label.qml - MainView.js MainView.qml popup.png RangeDetails.qml @@ -18,5 +17,8 @@ StatusDisplay.qml lock_closed.png lock_open.png + TimeMarks.qml + Overview.qml + Overview.js diff --git a/src/plugins/qmlprofiler/qmlprofiler.pro b/src/plugins/qmlprofiler/qmlprofiler.pro index 107acdcfc5a..c800387f086 100644 --- a/src/plugins/qmlprofiler/qmlprofiler.pro +++ b/src/plugins/qmlprofiler/qmlprofiler.pro @@ -46,7 +46,7 @@ HEADERS += \ qmlprofilerruncontrolfactory.h RESOURCES += \ - qml/qml.qrc + qml/qmlprofiler.qrc OTHER_FILES += \ qml/Detail.qml \ @@ -55,9 +55,11 @@ OTHER_FILES += \ qml/MainView.qml \ qml/RangeDetails.qml \ qml/RangeMover.qml \ - qml/MainView.js \ qml/TimeDisplay.qml \ - qml/StatusDisplay.qml + qml/TimeMarks.qml \ + qml/StatusDisplay.qml \ + qml/Overview.qml \ + qml/Overview.js FORMS += \ qmlprofilerattachdialog.ui diff --git a/src/plugins/qmlprofiler/timelineview.cpp b/src/plugins/qmlprofiler/timelineview.cpp index 0ea826d2bab..7dc44045c99 100644 --- a/src/plugins/qmlprofiler/timelineview.cpp +++ b/src/plugins/qmlprofiler/timelineview.cpp @@ -43,7 +43,7 @@ using namespace QmlProfiler::Internal; #define CACHE_STEP 200 TimelineView::TimelineView(QDeclarativeItem *parent) : - QDeclarativeItem(parent), m_delegate(0), m_itemCount(0), m_startTime(0), m_endTime(0), m_startX(0), m_spacing(0), + 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) { } @@ -64,32 +64,13 @@ void TimelineView::clearData() m_startTime = 0; m_endTime = 0; - m_startX = 0; prevMin = 0; prevMax = 0; m_totalWidth = 0; m_lastCachedIndex = 0; } -void TimelineView::setStartX(qreal arg) -{ - if (arg == m_startX) - return; - - qreal window = m_endTime - m_startTime; - if (window == 0) //### - return; - qreal spacing = width() / window; - qreal oldStart = m_startTime; - m_startTime = arg / spacing; - m_endTime += m_startTime - oldStart; - - updateTimeline(false); - m_startX = arg; - emit startXChanged(m_startX); -} - -void TimelineView::updateTimeline(bool updateStartX) +void TimelineView::updateTimeline() { if (!m_delegate) return; @@ -114,14 +95,6 @@ void TimelineView::updateTimeline(bool updateStartX) int minsample = m_eventList->findFirstIndex(m_startTime + m_eventList->traceStartTime()); int maxsample = m_eventList->findLastIndex(m_endTime + m_eventList->traceStartTime()); - if (updateStartX) { - qreal oldStartX = m_startX; - m_startX = qRound(m_startTime * m_spacing); - if (m_startX != oldStartX) { - emit startXChanged(m_startX); - } - } - //### emitting this before startXChanged was causing issues if (m_totalWidth != oldtw) emit totalWidthChanged(m_totalWidth); diff --git a/src/plugins/qmlprofiler/timelineview.h b/src/plugins/qmlprofiler/timelineview.h index fd892ab31bb..1979c4c1b93 100644 --- a/src/plugins/qmlprofiler/timelineview.h +++ b/src/plugins/qmlprofiler/timelineview.h @@ -46,7 +46,6 @@ class TimelineView : public QDeclarativeItem 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 startX READ startX WRITE setStartX NOTIFY startXChanged) 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) @@ -69,11 +68,6 @@ public: return m_endTime; } - qreal startX() const - { - return m_startX; - } - qreal totalWidth() const { return m_totalWidth; @@ -98,7 +92,6 @@ signals: void delegateChanged(QDeclarativeComponent * arg); void startTimeChanged(qint64 arg); void endTimeChanged(qint64 arg); - void startXChanged(qreal arg); void totalWidthChanged(qreal arg); void eventListChanged(QmlJsDebugClient::QmlProfilerEventList *list); @@ -107,7 +100,7 @@ signals: public slots: void clearData(); - void updateTimeline(bool updateStartX = true); + void updateTimeline(); void setDelegate(QDeclarativeComponent * arg) { @@ -133,8 +126,6 @@ public slots: } } - void setStartX(qreal arg); - protected: void componentComplete(); @@ -152,7 +143,6 @@ private: qint64 m_itemCount; qint64 m_startTime; qint64 m_endTime; - qreal m_startX; qreal m_spacing; int prevMin; int prevMax; diff --git a/src/plugins/qmlprofiler/tracewindow.cpp b/src/plugins/qmlprofiler/tracewindow.cpp index 26d4a3851c5..d426657a34d 100644 --- a/src/plugins/qmlprofiler/tracewindow.cpp +++ b/src/plugins/qmlprofiler/tracewindow.cpp @@ -44,6 +44,8 @@ #include #include #include +#include +#include using namespace QmlJsDebugClient; @@ -59,16 +61,63 @@ TraceWindow::TraceWindow(QWidget *parent) groupLayout->setContentsMargins(0, 0, 0, 0); groupLayout->setSpacing(0); - m_view = new QDeclarativeView(this); + m_mainView = new QDeclarativeView(this); + m_mainView->setResizeMode(QDeclarativeView::SizeViewToRootObject); + m_mainView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + m_mainView->setBackgroundBrush(QBrush(Qt::white)); + m_mainView->setAlignment(Qt::AlignLeft | Qt::AlignTop); + m_mainView->setFocus(); - if (QmlProfilerPlugin::debugOutput) { - //new QmlJSDebugger::JSDebuggerAgent(m_view->engine()); - //new QmlJSDebugger::QDeclarativeViewObserver(m_view, m_view); - } + QHBoxLayout *toolsLayout = new QHBoxLayout; + m_timebar = new QDeclarativeView(this); + m_timebar->setResizeMode(QDeclarativeView::SizeRootObjectToView); + m_timebar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + m_timebar->setMaximumHeight(24); + + m_overview = new QDeclarativeView(this); + m_overview->setResizeMode(QDeclarativeView::SizeRootObjectToView); + m_overview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + m_overview->setMaximumHeight(50); + + toolsLayout->addWidget(createToolbar()); + toolsLayout->addWidget(m_timebar); + + groupLayout->addLayout(toolsLayout); + groupLayout->addWidget(m_mainView); + groupLayout->addWidget(m_overview); + + setLayout(groupLayout); + + m_eventList = new QmlProfilerEventList(this); + connect(this,SIGNAL(range(int,qint64,qint64,QStringList,QString,int)), m_eventList, SLOT(addRangedEvent(int,qint64,qint64,QStringList,QString,int))); + connect(this, SIGNAL(traceFinished(qint64)), m_eventList, SLOT(setTraceEndTime(qint64))); + connect(this,SIGNAL(viewUpdated()), m_eventList, SLOT(complete())); + m_mainView->rootContext()->setContextProperty("qmlEventList", m_eventList); + m_overview->rootContext()->setContextProperty("qmlEventList", m_eventList); + + connect(this, SIGNAL(v8range(int,QString,QString,int,double,double)), m_eventList, SLOT(addV8Event(int,QString,QString,int,double,double))); + + // Minimum height: 5 rows of 20 pixels + scrollbar of 50 pixels + 20 pixels margin + setMinimumHeight(170); + + m_zoomControl = new ZoomControl(); +} + +TraceWindow::~TraceWindow() +{ + delete m_plugin.data(); + delete m_v8plugin.data(); + delete m_zoomControl.data(); +} + +QWidget *TraceWindow::createToolbar() +{ Utils::StyledBar *bar = new Utils::StyledBar(this); bar->setSingleRow(true); bar->setMinimumWidth(150); + bar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + bar->resize(150, 24); QHBoxLayout *toolBarLayout = new QHBoxLayout(bar); toolBarLayout->setMargin(0); toolBarLayout->setSpacing(0); @@ -98,28 +147,7 @@ TraceWindow::TraceWindow(QWidget *parent) toolBarLayout->addWidget(buttonZoomIn); toolBarLayout->addWidget(buttonZoomOut); - m_view->setResizeMode(QDeclarativeView::SizeRootObjectToView); - m_view->setFocus(); - groupLayout->addWidget(m_view); - - setLayout(groupLayout); - - m_eventList = new QmlProfilerEventList(this); - connect(this,SIGNAL(range(int,qint64,qint64,QStringList,QString,int)), m_eventList, SLOT(addRangedEvent(int,qint64,qint64,QStringList,QString,int))); - connect(this, SIGNAL(traceFinished(qint64)), m_eventList, SLOT(setTraceEndTime(qint64))); - connect(this,SIGNAL(viewUpdated()), m_eventList, SLOT(complete())); - m_view->rootContext()->setContextProperty("qmlEventList", m_eventList); - - connect(this, SIGNAL(v8range(int,QString,QString,int,double,double)), m_eventList, SLOT(addV8Event(int,QString,QString,int,double,double))); - - // Minimum height: 5 rows of 20 pixels + scrollbar of 50 pixels + 20 pixels margin - setMinimumHeight(170); -} - -TraceWindow::~TraceWindow() -{ - delete m_plugin.data(); - delete m_v8plugin.data(); + return bar; } void TraceWindow::reset(QDeclarativeDebugConnection *conn) @@ -142,20 +170,30 @@ void TraceWindow::reset(QDeclarativeDebugConnection *conn) connect(m_v8plugin.data(), SIGNAL(v8range(int,QString,QString,int,double,double)), this, SIGNAL(v8range(int,QString,QString,int,double,double))); connect(m_plugin.data(), SIGNAL(traceFinished(qint64)), this, SIGNAL(traceFinished(qint64))); - m_view->rootContext()->setContextProperty("connection", m_plugin.data()); - m_view->setSource(QUrl("qrc:/qmlprofiler/MainView.qml")); + m_mainView->rootContext()->setContextProperty("connection", m_plugin.data()); + m_mainView->rootContext()->setContextProperty("zoomControl", m_zoomControl.data()); + m_timebar->rootContext()->setContextProperty("zoomControl", m_zoomControl.data()); + m_overview->rootContext()->setContextProperty("zoomControl", m_zoomControl.data()); + + m_timebar->setSource(QUrl("qrc:/qmlprofiler/TimeDisplay.qml")); + m_overview->setSource(QUrl("qrc:/qmlprofiler/Overview.qml")); + + m_mainView->setSource(QUrl("qrc:/qmlprofiler/MainView.qml")); + m_mainView->rootObject()->setProperty("width", QVariant(width())); + m_mainView->rootObject()->setProperty("candidateHeight", QVariant(height() - m_timebar->height() - m_overview->height())); updateToolbar(); - connect(m_view->rootObject(), SIGNAL(updateCursorPosition()), this, SLOT(updateCursorPosition())); - connect(m_view->rootObject(), SIGNAL(updateTimer()), this, SLOT(updateTimer())); + connect(m_mainView->rootObject(), SIGNAL(updateCursorPosition()), this, SLOT(updateCursorPosition())); + connect(m_mainView->rootObject(), SIGNAL(updateTimer()), this, SLOT(updateTimer())); connect(m_eventList, SIGNAL(countChanged()), this, SLOT(updateToolbar())); - connect(this, SIGNAL(jumpToPrev()), m_view->rootObject(), SLOT(prevEvent())); - connect(this, SIGNAL(jumpToNext()), m_view->rootObject(), SLOT(nextEvent())); - connect(this, SIGNAL(zoomIn()), m_view->rootObject(), SLOT(zoomIn())); - connect(this, SIGNAL(zoomOut()), m_view->rootObject(), SLOT(zoomOut())); + connect(this, SIGNAL(jumpToPrev()), m_mainView->rootObject(), SLOT(prevEvent())); + connect(this, SIGNAL(jumpToNext()), m_mainView->rootObject(), SLOT(nextEvent())); + connect(this, SIGNAL(zoomIn()), m_mainView->rootObject(), SLOT(zoomIn())); + connect(this, SIGNAL(zoomOut()), m_mainView->rootObject(), SLOT(zoomOut())); - connect(this, SIGNAL(internalClearDisplay()), m_view->rootObject(), SLOT(clearAll())); + connect(this, SIGNAL(internalClearDisplay()), m_mainView->rootObject(), SLOT(clearAll())); + connect(this,SIGNAL(internalClearDisplay()), m_overview->rootObject(), SLOT(clearDisplay())); m_v8DataReady = false; m_qmlDataReady = false; @@ -173,13 +211,13 @@ void TraceWindow::contextMenuEvent(QContextMenuEvent *ev) void TraceWindow::updateCursorPosition() { - emit gotoSourceLocation(m_view->rootObject()->property("fileName").toString(), - m_view->rootObject()->property("lineNumber").toInt()); + emit gotoSourceLocation(m_mainView->rootObject()->property("fileName").toString(), + m_mainView->rootObject()->property("lineNumber").toInt()); } void TraceWindow::updateTimer() { - emit timeChanged(m_view->rootObject()->property("elapsedTime").toDouble()); + emit timeChanged(m_mainView->rootObject()->property("elapsedTime").toDouble()); } void TraceWindow::clearDisplay() @@ -191,6 +229,8 @@ void TraceWindow::clearDisplay() if (m_v8plugin) m_v8plugin.data()->clearData(); + m_zoomControl.data()->setRange(0,0); + emit internalClearDisplay(); } @@ -231,5 +271,14 @@ void TraceWindow::v8Complete() emit viewUpdated(); } +void TraceWindow::resizeEvent(QResizeEvent *event) +{ + if (m_mainView->rootObject()) { + m_mainView->rootObject()->setProperty("width", QVariant(event->size().width())); + int newHeight = event->size().height() - m_timebar->height() - m_overview->height(); + m_mainView->rootObject()->setProperty("candidateHeight", QVariant(newHeight)); + } +} + } // namespace Internal } // namespace QmlProfiler diff --git a/src/plugins/qmlprofiler/tracewindow.h b/src/plugins/qmlprofiler/tracewindow.h index 21d5d0ce579..42b404c8212 100644 --- a/src/plugins/qmlprofiler/tracewindow.h +++ b/src/plugins/qmlprofiler/tracewindow.h @@ -48,6 +48,31 @@ QT_END_NAMESPACE namespace QmlProfiler { namespace Internal { +// centralized zoom control +class ZoomControl : public QObject { + Q_OBJECT +public: + ZoomControl(QObject *parent=0):QObject(parent),m_startTime(0),m_endTime(0) {} + ~ZoomControl(){} + + Q_INVOKABLE void setRange(qint64 startTime, qint64 endTime) { + if (m_startTime != startTime || m_endTime != endTime) { + m_startTime = startTime; + m_endTime = endTime; + emit rangeChanged(); + } + } + Q_INVOKABLE qint64 startTime() { return m_startTime; } + Q_INVOKABLE qint64 endTime() { return m_endTime; } + +signals: + void rangeChanged(); + +private: + qint64 m_startTime; + qint64 m_endTime; +}; + class TraceWindow : public QWidget { Q_OBJECT @@ -93,16 +118,24 @@ signals: private: void contextMenuEvent(QContextMenuEvent *); + QWidget *createToolbar(); + +protected: + virtual void resizeEvent(QResizeEvent *event); private: QWeakPointer m_plugin; QWeakPointer m_v8plugin; QSize m_sizeHint; - QDeclarativeView *m_view; + QDeclarativeView *m_mainView; + QDeclarativeView *m_timebar; + QDeclarativeView *m_overview; QmlJsDebugClient::QmlProfilerEventList *m_eventList; bool m_qmlDataReady; bool m_v8DataReady; + + QWeakPointer m_zoomControl; }; } // namespace Internal