diff --git a/src/libs/qmljsdebugclient/qmlprofilereventlist.cpp b/src/libs/qmljsdebugclient/qmlprofilereventlist.cpp index df9e5dfb71d..5c5714ca5c8 100644 --- a/src/libs/qmljsdebugclient/qmlprofilereventlist.cpp +++ b/src/libs/qmljsdebugclient/qmlprofilereventlist.cpp @@ -1184,13 +1184,13 @@ int QmlProfilerEventList::getEventId(int index) const { int QmlProfilerEventList::uniqueEventsOfType(int type) const { if (!d->m_typeCounts.contains(type)) - return 1; + return 0; return d->m_typeCounts[type]->eventIds.count(); } int QmlProfilerEventList::maxNestingForType(int type) const { if (!d->m_typeCounts.contains(type)) - return 1; + return 0; return d->m_typeCounts[type]->nestingCount; } diff --git a/src/plugins/qmlprofiler/qml/Detail.qml b/src/plugins/qmlprofiler/qml/Detail.qml index b8fd301769a..509b8c353bd 100644 --- a/src/plugins/qmlprofiler/qml/Detail.qml +++ b/src/plugins/qmlprofiler/qml/Detail.qml @@ -39,7 +39,7 @@ Item { property string content signal linkActivated(string url) - height: childrenRect.height + height: childrenRect.height+2 width: childrenRect.width Item { id: guideline @@ -47,6 +47,7 @@ Item { width: 5 } Text { + y: 1 id: lbl text: label font.pixelSize: 12 diff --git a/src/plugins/qmlprofiler/qml/Label.qml b/src/plugins/qmlprofiler/qml/Label.qml index 575e52948eb..6f3f9d8705f 100644 --- a/src/plugins/qmlprofiler/qml/Label.qml +++ b/src/plugins/qmlprofiler/qml/Label.qml @@ -33,11 +33,12 @@ import QtQuick 1.0 Item { + id: labelContainer property alias text: txt.text property bool expanded: false property int typeIndex: index - property variant descriptions: [text] + property variant descriptions: [] height: root.singleRowHeight width: 150 @@ -56,8 +57,8 @@ Item { } function updateHeight() { - height = root.singleRowHeight * - (expanded ? qmlEventList.uniqueEventsOfType(typeIndex) : qmlEventList.maxNestingForType(typeIndex)); + height = root.singleRowHeight * (1 + + (expanded ? qmlEventList.uniqueEventsOfType(typeIndex) : qmlEventList.maxNestingForType(typeIndex))); } Connections { @@ -66,55 +67,67 @@ Item { var desc=[]; for (var i=0; i 0 source: expanded ? "arrow_down.png" : "arrow_right.png" x: parent.width - 12 - y: 2 + y: root.singleRowHeight / 2 - height / 2 MouseArea { anchors.fill: parent + anchors.rightMargin: -10 + anchors.leftMargin: -10 + anchors.topMargin: -10 + anchors.bottomMargin: -10 onClicked: { expanded = !expanded; } diff --git a/src/plugins/qmlprofiler/qml/MainView.qml b/src/plugins/qmlprofiler/qml/MainView.qml index e682aeff056..7f04b793491 100644 --- a/src/plugins/qmlprofiler/qml/MainView.qml +++ b/src/plugins/qmlprofiler/qml/MainView.qml @@ -39,6 +39,7 @@ Rectangle { // ***** properties property int candidateHeight: 0 + property int scrollY: 0 height: Math.max( candidateHeight, labels.height + 2 ) property int singleRowHeight: 30 @@ -132,9 +133,12 @@ Rectangle { function clearData() { view.clearData(); - root.dataAvailable = false; - root.eventCount = 0; + dataAvailable = false; + eventCount = 0; hideRangeDetails(); + selectionRangeMode = false; + updateRangeButton(); + zoomControl.setRange(0,0); } function clearDisplay() { @@ -493,14 +497,6 @@ Rectangle { } } } - - //right border divider - Rectangle { - width: 1 - height: parent.height - anchors.right: parent.right - color: "#cccccc" - } } Rectangle { @@ -516,4 +512,52 @@ Rectangle { anchors.verticalCenter: labels.verticalCenter z:3 } + + // Gradient borders + Item { + anchors.left: labels.right + width: 6 + anchors.top: root.top + anchors.bottom: root.bottom + Rectangle { + x: parent.width + transformOrigin: Item.TopLeft + rotation: 90 + width: parent.height + height: parent.width + gradient: Gradient { + GradientStop { position: 0.0; color: "#00A0A0A0"; } + GradientStop { position: 1.0; color: "#FFA0A0A0"; } + } + } + } + + Item { + anchors.right: root.right + width: 6 + anchors.top: root.top + anchors.bottom: root.bottom + Rectangle { + x: parent.width + transformOrigin: Item.TopLeft + rotation: 90 + width: parent.height + height: parent.width + gradient: Gradient { + GradientStop { position: 0.0; color: "#FFA0A0A0"; } + GradientStop { position: 1.0; color: "#00A0A0A0"; } + } + } + } + + Rectangle { + y: root.scrollY + root.candidateHeight - height + height: 6 + width: root.width + x: 0 + gradient: Gradient { + GradientStop { position: 0.0; color: "#00A0A0A0"; } + GradientStop { position: 1.0; color: "#FFA0A0A0"; } + } + } } diff --git a/src/plugins/qmlprofiler/qml/Overview.js b/src/plugins/qmlprofiler/qml/Overview.js index 4bec74179bf..5cfe715bf1e 100644 --- a/src/plugins/qmlprofiler/qml/Overview.js +++ b/src/plugins/qmlprofiler/qml/Overview.js @@ -37,11 +37,7 @@ var qmlEventList = 0; //draw background of the graph function drawGraph(canvas, ctxt, region) { - var grad = ctxt.createLinearGradient(0, 0, 0, canvas.height); - grad.addColorStop(0, '#fff'); - grad.addColorStop(1, '#ccc'); - ctxt.fillStyle = grad; - + ctxt.fillStyle = "#eaeaea"; ctxt.fillRect(0, 0, canvas.width, canvas.height); } @@ -51,40 +47,106 @@ function drawData(canvas, ctxt, region) if ((!qmlEventList) || qmlEventList.count() == 0) return; + var typeCount = 5; var width = canvas.width; - var height = canvas.height; + var bump = 10; + var height = canvas.height - bump; + var blockHeight = height / typeCount; var spacing = width / qmlEventList.traceDuration(); - ctxt.fillStyle = "rgba(0,0,0,1)"; - var highest = [0,0,0,0,0]; + var highest = [0,0,0,0,0]; // note: change if typeCount changes - // 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; if (xx > region.x + region.width) continue; - var size = qmlEventList.getDuration(ii) * spacing; - if (xx + size < region.x) + var eventWidth = qmlEventList.getDuration(ii) * spacing; + if (xx + eventWidth < region.x) continue; - if (size < 0.5) - size = 0.5; + if (eventWidth < 1) + eventWidth = 1; xx = Math.round(xx); var ty = qmlEventList.getType(ii); - if (xx + size > highest[ty]) { - ctxt.fillRect(xx, ty*10, size, 10); - highest[ty] = xx+size; + if (xx + eventWidth > highest[ty]) { + var hue = ( qmlEventList.getEventId(ii) * 25 ) % 360; + ctxt.fillStyle = "hsl("+(hue/360.0+0.001)+",0.3,0.65)"; + ctxt.fillRect(xx, bump + ty*blockHeight, eventWidth, blockHeight); + highest[ty] = xx+eventWidth; } } } +function drawTimeBar(canvas, ctxt, region) +{ + var width = canvas.width; + var height = 10; + var startTime = qmlEventList.traceStartTime(); + var endTime = qmlEventList.traceEndTime(); + + var totalTime = qmlEventList.traceDuration(); + var spacing = width / totalTime; + + var initialBlockLength = 120; + var timePerBlock = Math.pow(2, Math.floor( Math.log( totalTime / width * initialBlockLength ) / Math.LN2 ) ); + var pixelsPerBlock = timePerBlock * spacing; + var pixelsPerSection = pixelsPerBlock / 5; + var blockCount = width / pixelsPerBlock; + + var realStartTime = Math.floor(startTime/timePerBlock) * timePerBlock; + var realStartPos = (startTime-realStartTime) * spacing; + + var timePerPixel = timePerBlock/pixelsPerBlock; + + ctxt.fillStyle = "#000000"; + ctxt.font = "6px sans-serif"; + + ctxt.fillStyle = "#cccccc"; + ctxt.fillRect(0, 0, width, height); + for (var ii = 0; ii < blockCount+1; ii++) { + var x = Math.floor(ii*pixelsPerBlock - realStartPos); + + // block boundary + ctxt.strokeStyle = "#525252"; + ctxt.beginPath(); + ctxt.moveTo(x, height/2); + ctxt.lineTo(x, height); + ctxt.stroke(); + + // block time label + ctxt.fillStyle = "#000000"; + var timeString = prettyPrintTime((ii+0.5)*timePerBlock + realStartTime); + ctxt.textAlign = "center"; + ctxt.fillText(timeString, x + pixelsPerBlock/2, height/2 + 3); + } + + ctxt.fillStyle = "#808080"; + ctxt.fillRect(0, height-1, width, 1); +} + +function prettyPrintTime( t ) +{ + if (t <= 0) return "0"; + if (t<1000) return t+" ns"; + t = t/1000; + if (t<1000) return t+" μs"; + t = Math.floor(t/100)/10; + if (t<1000) return t+" ms"; + t = Math.floor(t)/1000; + if (t<60) return t+" s"; + var m = Math.floor(t/60); + t = Math.floor(t - m*60); + return m+"m"+t+"s"; +} + function plot(canvas, ctxt, region) { drawGraph(canvas, ctxt, region); drawData(canvas, ctxt, region); + drawTimeBar(canvas, ctxt, region); + } diff --git a/src/plugins/qmlprofiler/qml/Overview.qml b/src/plugins/qmlprofiler/qml/Overview.qml index 83ac454087c..54b89f463e5 100644 --- a/src/plugins/qmlprofiler/qml/Overview.qml +++ b/src/plugins/qmlprofiler/qml/Overview.qml @@ -124,6 +124,6 @@ Canvas2D { Rectangle { height: 1 width: parent.width - color: "#cccccc" + color: "#858585" } } diff --git a/src/plugins/qmlprofiler/qml/RangeDetails.qml b/src/plugins/qmlprofiler/qml/RangeDetails.qml index b2b24a4dc4c..9e3d574a789 100644 --- a/src/plugins/qmlprofiler/qml/RangeDetails.qml +++ b/src/plugins/qmlprofiler/qml/RangeDetails.qml @@ -33,7 +33,7 @@ import QtQuick 1.0 import Monitor 1.0 -BorderImage { +Item { id: rangeDetails property string duration @@ -44,72 +44,115 @@ BorderImage { property bool locked: view.selectionLocked - source: "popup_green.png" - border { - left: 10; top: 10 - right: 20; bottom: 20 - } - width: col.width + 45 - height: childrenRect.height + height: col.height + 30 z: 1 visible: false x: 200 y: 25 + // shadow + BorderImage { + property int px: 4 + source: "dialog_shadow.png" + + border { + left: px; top: px + right: px; bottom: px + } + width: parent.width + 2*px - 1 + height: parent.height + x: -px + 1 + y: px + 1 + } + + // title bar + Rectangle { + width: parent.width + height: 20 + color: "#55a3b8" + radius: 5 + border.width: 1 + border.color: "#a0a0a0" + } + Item { + width: parent.width+1 + height: 11 + y: 10 + clip: true + Rectangle { + width: parent.width-1 + height: 15 + y: -5 + color: "#55a3b8" + border.width: 1 + border.color: "#a0a0a0" + } + } + //title Text { id: typeTitle - text: rangeDetails.type + text: " "+rangeDetails.type font.bold: true - y: 10 - anchors.horizontalCenter: parent.horizontalCenter - anchors.horizontalCenterOffset: -5 + height: 18 + y: 2 + verticalAlignment: Text.AlignVCenter + width: parent.width + color: "white" } - //details - Column { - id: col - anchors.top: typeTitle.bottom - x: 2 - Detail { - label: qsTr("Duration") - content: rangeDetails.duration < 1000 ? - rangeDetails.duration + "μs" : - Math.floor(rangeDetails.duration/10)/100 + "ms" - } - Detail { - opacity: content.length !== 0 ? 1 : 0 - label: qsTr("Details") - content: { - var inputString = rangeDetails.label; - if (inputString.length > 7 && inputString.substring(0,7) == "file://") { - var pos = inputString.lastIndexOf("/"); - return inputString.substr(pos+1); - } - var maxLen = 40; - if (inputString.length > maxLen) - inputString = inputString.substring(0,maxLen)+"..."; + // Details area + Rectangle { + color: "white" + width: parent.width + height: col.height + 10 + y: 20 + border.width: 1 + border.color: "#a0a0a0" - return inputString; + //details + Column { + id: col + x: 10 + y: 5 + Detail { + label: qsTr("Duration:") + content: rangeDetails.duration < 1000 ? rangeDetails.duration + "μs" : Math.floor(rangeDetails.duration/10)/100 + "ms" } - } - Detail { - opacity: content.length !== 0 ? 1 : 0 - label: qsTr("Location") - content: { - var file = rangeDetails.file; - var pos = file.lastIndexOf("/"); - if (pos != -1) - file = file.substr(pos+1); - return (file.length !== 0) ? (file + ":" + rangeDetails.line) : ""; + Detail { + opacity: content.length !== 0 ? 1 : 0 + label: qsTr("Details:") + content: { + var inputString = rangeDetails.label; + if (inputString.length > 7 && inputString.substring(0,7) == "file://") { + var pos = inputString.lastIndexOf("/"); + return inputString.substr(pos+1); + } + var maxLen = 40; + if (inputString.length > maxLen) + inputString = inputString.substring(0,maxLen)+"..."; + + return inputString; + } + } + Detail { + opacity: content.length !== 0 ? 1 : 0 + label: qsTr("Location:") + content: { + var file = rangeDetails.file; + var pos = file.lastIndexOf("/"); + if (pos != -1) + file = file.substr(pos+1); + return (file.length !== 0) ? (file + ":" + rangeDetails.line) : ""; + } } } } MouseArea { - width: col.width + 30 - height: col.height + typeTitle.height + 30 + width: col.width + 45 + height: col.height + 30 drag.target: parent onClicked: { root.gotoSourceLocation(file, line); @@ -133,11 +176,13 @@ BorderImage { } } + Text { id: closeIcon - x: col.width + 20 - y: 10 + x: col.width + 30 + y: 4 text:"X" + color: "white" MouseArea { anchors.fill: parent onClicked: { @@ -147,5 +192,4 @@ BorderImage { } } - } diff --git a/src/plugins/qmlprofiler/qml/RangeMover.qml b/src/plugins/qmlprofiler/qml/RangeMover.qml index 9cfff4ba903..39cebfda1c2 100644 --- a/src/plugins/qmlprofiler/qml/RangeMover.qml +++ b/src/plugins/qmlprofiler/qml/RangeMover.qml @@ -36,14 +36,13 @@ Rectangle { id: rangeMover - property color lighterColor:"#cc80b2f6" - property color darkerColor:"#cc6da1e8" - property color gapColor: "#666da1e8" - property color hardBorderColor: "blue" + property color rangeColor:"#444a64b8" + property color borderColor:"#cc4a64b8" + property color dragMarkerColor: "#4a64b8" width: 20 height: 50 - color: lighterColor + color: rangeColor property bool dragStarted: false onXChanged: { @@ -74,16 +73,30 @@ Rectangle { x: 0 height: parent.height width: 1 - color: darkerColor - border.color: hardBorderColor - border.width: 0 + color: borderColor + + Rectangle { + id: leftBorderHandle + height: parent.height + x: -width + width: 7 + color: "#869cd1" + visible: false + Image { + source: "range_handle.png" + x: 2 + width: 4 + height: 9 + fillMode: Image.Tile + y: rangeMover.height / 2 - 4 + } + } states: State { name: "highlighted" PropertyChanges { - target: leftRange - width: 3 - border.width: 2 + target: leftBorderHandle + visible: true } } @@ -97,8 +110,8 @@ Rectangle { } MouseArea { - x: -3 - width: 7 + x: -10 + width: 13 y: 0 height: parent.height @@ -131,16 +144,30 @@ Rectangle { x: rangeMover.width height: parent.height width: 1 - color: darkerColor - border.color: hardBorderColor - border.width: 0 + color: borderColor + + Rectangle { + id: rightBorderHandle + height: parent.height + x: 1 + width: 7 + color: "#869cd1" + visible: false + Image { + source: "range_handle.png" + x: 2 + width: 4 + height: 9 + fillMode: Image.Tile + y: rangeMover.height / 2 - 4 + } + } states: State { name: "highlighted" PropertyChanges { - target: rightRange - width: 3 - border.width: 2 + target: rightBorderHandle + visible: true } } @@ -153,7 +180,7 @@ Rectangle { MouseArea { x: -3 - width: 7 + width: 13 y: 0 height: parent.height diff --git a/src/plugins/qmlprofiler/qml/SelectionRange.qml b/src/plugins/qmlprofiler/qml/SelectionRange.qml index 6c9a9b9c833..9565f2256b7 100644 --- a/src/plugins/qmlprofiler/qml/SelectionRange.qml +++ b/src/plugins/qmlprofiler/qml/SelectionRange.qml @@ -40,11 +40,11 @@ Rectangle { property bool ready: visible && creationState === 3 - property color lighterColor:"#6680b2f6" - property color darkerColor:"#666da1e8" - property color gapColor: "#336da1e8" - property color hardBorderColor: "#aa6da1e8" - property color thinColor: "blue" + property color rangeColor:"#444a64b8" + property color pressedColor:"#664a64b8" + property color borderColor:"#aa4a64b8" + property color dragMarkerColor: "#4a64b8" + property color singleLineColor: "#4a64b8" property string startTimeString: detailedPrintTime(startTime) property string endTimeString: detailedPrintTime(startTime+duration) @@ -77,16 +77,16 @@ Rectangle { onCreationStateChanged: { switch (creationState) { case 0: color = "transparent"; break; - case 1: color = thinColor; break; - default: color = lighterColor; break; + case 1: color = singleLineColor; break; + default: color = rangeColor; break; } } onIsDraggingChanged: { if (isDragging) - color = darkerColor; + color = pressedColor; else - color = lighterColor; + color = rangeColor; } function reset(setVisible) { @@ -172,16 +172,30 @@ Rectangle { x: 0 height: parent.height width: 1 - color: darkerColor - border.color: hardBorderColor - border.width: 0 + color: borderColor + + Rectangle { + id: leftBorderHandle + height: parent.height + x: -width + width: 9 + color: "#869cd1" + visible: false + Image { + source: "range_handle.png" + x: 4 + width: 4 + height: 63 + fillMode: Image.Tile + y: root.scrollY + root.candidateHeight / 2 - 32 + } + } states: State { name: "highlighted" PropertyChanges { - target: leftBorder - width: 3 - border.width: 2 + target: leftBorderHandle + visible: true } } @@ -192,8 +206,8 @@ Rectangle { } MouseArea { - x: -3 - width: 7 + x: -12 + width: 15 y: 0 height: parent.height @@ -226,16 +240,30 @@ Rectangle { x: selectionRange.width height: parent.height width: 1 - color: darkerColor - border.color: hardBorderColor - border.width: 0 + color: borderColor + + Rectangle { + id: rightBorderHandle + height: parent.height + x: 1 + width: 9 + color: "#869cd1" + visible: false + Image { + source: "range_handle.png" + x: 2 + width: 4 + height: 63 + fillMode: Image.Tile + y: root.scrollY + root.candidateHeight / 2 - 32 + } + } states: State { name: "highlighted" PropertyChanges { - target: rightBorder - width: 3 - border.width: 2 + target: rightBorderHandle + visible: true } } @@ -247,7 +275,7 @@ Rectangle { MouseArea { x: -3 - width: 7 + width: 15 y: 0 height: parent.height diff --git a/src/plugins/qmlprofiler/qml/SelectionRangeDetails.qml b/src/plugins/qmlprofiler/qml/SelectionRangeDetails.qml index c3bc2d2e75c..f337825e3a1 100644 --- a/src/plugins/qmlprofiler/qml/SelectionRangeDetails.qml +++ b/src/plugins/qmlprofiler/qml/SelectionRangeDetails.qml @@ -33,7 +33,7 @@ import QtQuick 1.0 import Monitor 1.0 -BorderImage { +Item { id: selectionRangeDetails property string startTime @@ -41,55 +41,110 @@ BorderImage { property string duration property bool showDuration - source: "popup_orange.png" - border { - left: 10; top: 10 - right: 20; bottom: 20 - } - width: 170 - height: childrenRect.height + height: col.height + 30 z: 1 visible: false x: 200 y: 125 + // shadow + BorderImage { + property int px: 4 + source: "dialog_shadow.png" + + border { + left: px; top: px + right: px; bottom: px + } + width: parent.width + 2*px - 1 + height: parent.height + x: -px + 1 + y: px + 1 + } + + // title bar + Rectangle { + width: parent.width + height: 20 + color: "#4a64b8" + radius: 5 + border.width: 1 + border.color: "#a0a0a0" + } + Item { + width: parent.width+1 + height: 11 + y: 10 + clip: true + Rectangle { + width: parent.width-1 + height: 15 + y: -5 + color: "#4a64b8" + border.width: 1 + border.color: "#a0a0a0" + } + } + //title Text { id: typeTitle - text: qsTr("Selection") + text: " "+qsTr("Selection") font.bold: true - y: 10 - anchors.horizontalCenter: parent.horizontalCenter - anchors.horizontalCenterOffset: -5 + height: 18 + y: 2 + verticalAlignment: Text.AlignVCenter + width: parent.width + color: "white" } - //details - Column { - id: col - anchors.top: typeTitle.bottom - x: 2 - Detail { - label: qsTr("Start") - content: selectionRangeDetails.startTime + // Details area + Rectangle { + color: "white" + width: parent.width + height: col.height + 10 + y: 20 + border.width: 1 + border.color: "#a0a0a0" + Column { + id: col + x: 10 + y: 5 + Detail { + label: qsTr("Start") + content: selectionRangeDetails.startTime + } + Detail { + label: qsTr("End") + visible: selectionRangeDetails.showDuration + content: selectionRangeDetails.endTime + } + Detail { + label: qsTr("Duration") + visible: selectionRangeDetails.showDuration + content: selectionRangeDetails.duration + } } - Detail { - label: qsTr("End") - visible: selectionRangeDetails.showDuration - content: selectionRangeDetails.endTime - } - Detail { - label: qsTr("Duration") - visible: selectionRangeDetails.showDuration - content: selectionRangeDetails.duration + } + + MouseArea { + width: col.width + 45 + height: col.height + 30 + drag.target: parent + onClicked: { + if ((selectionRange.x < flick.contentX) ^ (selectionRange.x+selectionRange.width > flick.contentX + flick.width)) { + root.recenter(selectionRange.startTime + selectionRange.duration/2); + } } } Text { id: closeIcon - x: selectionRangeDetails.width - 24 - y: 10 + x: selectionRangeDetails.width - 14 + y: 4 text:"X" + color: "white" MouseArea { anchors.fill: parent anchors.leftMargin: -8 @@ -100,14 +155,4 @@ BorderImage { } } - MouseArea { - width: col.width - height: col.height + typeTitle.height + 30 - drag.target: parent - onClicked: { - if ((selectionRange.x < flick.contentX) ^ (selectionRange.x+selectionRange.width > flick.contentX + flick.width)) { - root.recenter(selectionRange.startTime + selectionRange.duration/2); - } - } - } } diff --git a/src/plugins/qmlprofiler/qml/TimeDisplay.qml b/src/plugins/qmlprofiler/qml/TimeDisplay.qml index 3b8c9987517..0efba45bdda 100644 --- a/src/plugins/qmlprofiler/qml/TimeDisplay.qml +++ b/src/plugins/qmlprofiler/qml/TimeDisplay.qml @@ -78,19 +78,52 @@ Canvas2D { timePerPixel = timePerBlock/pixelsPerBlock; + var initialColor = Math.floor(realStartTime/timePerBlock) % 2; ctxt.fillStyle = "#000000"; ctxt.font = "8px sans-serif"; for (var ii = 0; ii < blockCount+1; ii++) { var x = Math.floor(ii*pixelsPerBlock - realStartPos); - ctxt.strokeStyle = "#C0C0C0"; + + ctxt.fillStyle = (ii+initialColor)%2 ? "#E6E6E6":"white"; + ctxt.fillRect(x, 0, pixelsPerBlock, height); + + ctxt.strokeStyle = "#B0B0B0"; ctxt.beginPath(); ctxt.moveTo(x, 0); ctxt.lineTo(x, height); ctxt.stroke(); - ctxt.fillText(prettyPrintTime(ii*timePerBlock + realStartTime), x + 5, height/2 + 4); + ctxt.fillStyle = "#000000"; + ctxt.fillText(prettyPrintTime(ii*timePerBlock + realStartTime), x + 5, height/2 + 5); } + + ctxt.strokeStyle = "#525252"; + ctxt.beginPath(); + ctxt.moveTo(0, height-1); + ctxt.lineTo(width, height-1); + ctxt.stroke(); + + // gradient borders + var gradientDark = "rgba(160, 160, 160, 1)"; + var gradientClear = "rgba(160, 160, 160, 0)"; + var grad = ctxt.createLinearGradient(0, 0, 0, 6); + grad.addColorStop(0,gradientDark); + grad.addColorStop(1,gradientClear); + ctxt.fillStyle = grad; + ctxt.fillRect(0, 0, width, 6); + + grad = ctxt.createLinearGradient(0, 0, 6, 0); + grad.addColorStop(0,gradientDark); + grad.addColorStop(1,gradientClear); + ctxt.fillStyle = grad; + ctxt.fillRect(0, 0, 6, height); + + grad = ctxt.createLinearGradient(width, 0, width-6, 0); + grad.addColorStop(0,gradientDark); + grad.addColorStop(1,gradientClear); + ctxt.fillStyle = grad; + ctxt.fillRect(width-6, 0, 6, height); } function prettyPrintTime( t ) diff --git a/src/plugins/qmlprofiler/qml/TimeMarks.qml b/src/plugins/qmlprofiler/qml/TimeMarks.qml index d8a72b0ee2c..5d05a209a2a 100644 --- a/src/plugins/qmlprofiler/qml/TimeMarks.qml +++ b/src/plugins/qmlprofiler/qml/TimeMarks.qml @@ -73,13 +73,13 @@ Canvas2D { ctxt.font = "8px sans-serif"; for (var ii = 0; ii < blockCount+1; ii++) { var x = Math.floor(ii*pixelsPerBlock - realStartPos); - ctxt.strokeStyle = "#C0C0C0"; + ctxt.strokeStyle = "#B0B0B0"; ctxt.beginPath(); ctxt.moveTo(x, 0); ctxt.lineTo(x, height); ctxt.stroke(); - ctxt.strokeStyle = "#E0E0E0"; + ctxt.strokeStyle = "#CCCCCC"; for (var jj=1; jj < 5; jj++) { var xx = Math.floor(ii*pixelsPerBlock + jj*pixelsPerSection - realStartPos); ctxt.beginPath(); @@ -113,16 +113,30 @@ Canvas2D { } function drawBackgroundBars( ctxt, region ) { + var colorIndex = true; + // row background + for (var y=0; y < labels.height; y+= root.singleRowHeight) { + ctxt.fillStyle = colorIndex ? "#f0f0f0" : "white"; + ctxt.strokeStyle = colorIndex ? "#f0f0f0" : "white"; + ctxt.fillRect(0, y, width, root.singleRowHeight); + colorIndex = !colorIndex; + } + + // separators var cumulatedHeight = 0; for (var i=0; iDetail.qml Label.qml MainView.qml - popup_green.png - popup_orange.png RangeDetails.qml RangeMover.qml TimeDisplay.qml clean_pane_small.png - prev.png - next.png recordOff.png recordOn.png StatusDisplay.qml @@ -19,13 +15,17 @@ TimeMarks.qml Overview.qml Overview.js - range.png - range_pressed.png SelectionRange.qml SelectionRangeDetails.qml - magnifier.png arrow_down.png arrow_right.png - arrow_select.png + dialog_shadow.png + range_handle.png + ico_selectionmode.png + ico_zoom.png + ico_prev.png + ico_next.png + ico_rangeselection.png + ico_rangeselected.png diff --git a/src/plugins/qmlprofiler/qml/range.png b/src/plugins/qmlprofiler/qml/range.png deleted file mode 100644 index 756318d556a..00000000000 Binary files a/src/plugins/qmlprofiler/qml/range.png and /dev/null differ diff --git a/src/plugins/qmlprofiler/qml/range_handle.png b/src/plugins/qmlprofiler/qml/range_handle.png new file mode 100644 index 00000000000..f44fb3337ff Binary files /dev/null and b/src/plugins/qmlprofiler/qml/range_handle.png differ diff --git a/src/plugins/qmlprofiler/qml/range_pressed.png b/src/plugins/qmlprofiler/qml/range_pressed.png deleted file mode 100644 index 53c49ab3aef..00000000000 Binary files a/src/plugins/qmlprofiler/qml/range_pressed.png and /dev/null differ diff --git a/src/plugins/qmlprofiler/qml/recordOff.png b/src/plugins/qmlprofiler/qml/recordOff.png index 66f4e3b36b1..d50c0183c09 100644 Binary files a/src/plugins/qmlprofiler/qml/recordOff.png and b/src/plugins/qmlprofiler/qml/recordOff.png differ diff --git a/src/plugins/qmlprofiler/qml/recordOn.png b/src/plugins/qmlprofiler/qml/recordOn.png index 5d4b77f0f26..ed5e8912c3d 100644 Binary files a/src/plugins/qmlprofiler/qml/recordOn.png and b/src/plugins/qmlprofiler/qml/recordOn.png differ diff --git a/src/plugins/qmlprofiler/timelineview.cpp b/src/plugins/qmlprofiler/timelineview.cpp index 3d1550032dc..fb5a43ba47c 100644 --- a/src/plugins/qmlprofiler/timelineview.cpp +++ b/src/plugins/qmlprofiler/timelineview.cpp @@ -84,8 +84,9 @@ void TimelineView::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget m_spacing = qreal(width()) / windowDuration; m_rowWidths.clear(); + // The "1+" is because the reference screenshot features an empty row per type, in order to leave space for the title for (int i=0; iuniqueEventsOfType(i) : m_eventList->maxNestingForType(i)); + m_rowWidths << 1 + (m_rowsExpanded[i] ? m_eventList->uniqueEventsOfType(i) : m_eventList->maxNestingForType(i)); } // event rows @@ -120,19 +121,6 @@ QColor TimelineView::colorForItem(int itemIndex) return QColor::fromHsl((ndx*25)%360, 76, 166); } -QLinearGradient *TimelineView::gradientForItem(int itemIndex) -{ - int ndx = m_eventList->getEventId(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]; -} - void TimelineView::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex) { int x,y,width,rowNumber, eventType; @@ -140,9 +128,9 @@ void TimelineView::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex) 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); + y = m_rowStarts[eventType] + DefaultRowHeight*(m_eventList->eventPosInType(i) + 1); else - y = m_rowStarts[eventType] + DefaultRowHeight*(m_eventList->getNestingLevel(i)-1); + y = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->getNestingLevel(i); width = m_eventList->getDuration(i)*m_spacing; if (width<1) @@ -153,7 +141,7 @@ void TimelineView::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex) continue; m_rowLastX[rowNumber] = x+width; - p->setBrush(*gradientForItem(i)); + p->setBrush(colorForItem(i)); p->drawRect(x,y,width,DefaultRowHeight); } } @@ -168,8 +156,11 @@ void TimelineView::drawSelectionBoxes(QPainter *p) int id = m_eventList->getEventId(m_selectedItem); p->setBrush(Qt::transparent); - QPen strongPen(QBrush(Qt::blue), 3); - QPen lightPen(QBrush(QColor(Qt::blue).lighter(130)), 2); + QColor selectionColor = Qt::blue; + if (m_selectionLocked) + selectionColor = QColor(96,0,255); + QPen strongPen(selectionColor, 3); + QPen lightPen(QBrush(selectionColor.lighter(130)), 2); p->setPen(lightPen); int x, y, width, eventType; @@ -185,9 +176,9 @@ void TimelineView::drawSelectionBoxes(QPainter *p) 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); + y = m_rowStarts[eventType] + DefaultRowHeight*(m_eventList->eventPosInType(i) + 1); else - y = m_rowStarts[eventType] + DefaultRowHeight*(m_eventList->getNestingLevel(i)-1); + y = m_rowStarts[eventType] + DefaultRowHeight*m_eventList->getNestingLevel(i); width = m_eventList->getDuration(i)*m_spacing; if (width<1) @@ -271,9 +262,9 @@ void TimelineView::manageHovered(int x, int y) eventType = m_eventList->getType(i); if (m_rowsExpanded[eventType]) - itemRow = m_rowStarts[eventType]/DefaultRowHeight + m_eventList->eventPosInType(i); + itemRow = m_rowStarts[eventType]/DefaultRowHeight + m_eventList->eventPosInType(i) + 1; else - itemRow = m_rowStarts[eventType]/DefaultRowHeight + m_eventList->getNestingLevel(i)-1; + itemRow = m_rowStarts[eventType]/DefaultRowHeight + m_eventList->getNestingLevel(i); if (itemRow == row) { // match m_currentSelection.eventIndex = i; @@ -341,7 +332,7 @@ int TimelineView::nextItemFromId(int eventId) const do { if (m_eventList->getEventId(ndx) == eventId) return ndx; - ndx = (ndx+1) % m_eventList->count(); + ndx = (ndx + 1) % m_eventList->count(); } while (ndx != startIndex); return -1; } @@ -360,7 +351,7 @@ void TimelineView::selectNext() if (m_selectionLocked && m_selectedItem !=-1 ) { // find next item with same eventId int eventId = m_eventList->getEventId(m_selectedItem); - int i = m_selectedItem+1; + int i = m_selectedItem + 1; while (icount() && m_eventList->getEventId(i) != eventId) i++; if (i == m_eventList->count()) { @@ -371,7 +362,7 @@ void TimelineView::selectNext() setSelectedItem(i); } else { // select next in view or after - int newIndex = m_selectedItem+1; + int newIndex = m_selectedItem + 1; if (newIndex >= m_eventList->count()) newIndex = 0; if (m_eventList->getEndTime(newIndex) < m_startTime) diff --git a/src/plugins/qmlprofiler/timelineview.h b/src/plugins/qmlprofiler/timelineview.h index c71d7de8c50..1fbddb1c0c4 100644 --- a/src/plugins/qmlprofiler/timelineview.h +++ b/src/plugins/qmlprofiler/timelineview.h @@ -138,6 +138,7 @@ public slots: { if (m_selectionLocked != locked) { m_selectionLocked = locked; + update(); emit selectionLockedChanged(locked); } } @@ -177,7 +178,6 @@ protected: private: QColor colorForItem(int itemIndex); - QLinearGradient *gradientForItem(int itemIndex); void drawItemsToPainter(QPainter *p, int fromIndex, int toIndex); void drawSelectionBoxes(QPainter *p); @@ -192,7 +192,6 @@ private: qint64 m_lastEndTime; QmlJsDebugClient::QmlProfilerEventList *m_eventList; - QHash m_hashedGradients; QList m_rowLastX; QList m_rowStarts; diff --git a/src/plugins/qmlprofiler/tracewindow.cpp b/src/plugins/qmlprofiler/tracewindow.cpp index 245a25bd0d6..2fd3b4986f2 100644 --- a/src/plugins/qmlprofiler/tracewindow.cpp +++ b/src/plugins/qmlprofiler/tracewindow.cpp @@ -66,6 +66,25 @@ void ZoomControl::setRange(qint64 startTime, qint64 endTime) } } +ScrollableDeclarativeView::ScrollableDeclarativeView(QWidget *parent) + : QDeclarativeView(parent) +{ +} + +ScrollableDeclarativeView::~ScrollableDeclarativeView() +{ +} + +void ScrollableDeclarativeView::scrollContentsBy(int dx, int dy) +{ + // special workaround to track the scrollbar + if (rootObject()) { + int scrollY = rootObject()->property("scrollY").toInt(); + rootObject()->setProperty("scrollY", QVariant(scrollY - dy)); + } + QDeclarativeView::scrollContentsBy(dx,dy); +} + TraceWindow::TraceWindow(QWidget *parent) : QWidget(parent) { @@ -78,7 +97,7 @@ TraceWindow::TraceWindow(QWidget *parent) groupLayout->setContentsMargins(0, 0, 0, 0); groupLayout->setSpacing(0); - m_mainView = new QDeclarativeView(this); + m_mainView = new ScrollableDeclarativeView(this); m_mainView->setResizeMode(QDeclarativeView::SizeViewToRootObject); m_mainView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); m_mainView->setBackgroundBrush(QBrush(Qt::white)); @@ -147,19 +166,19 @@ QWidget *TraceWindow::createToolbar() toolBarLayout->setSpacing(0); QToolButton *buttonPrev= new QToolButton; - buttonPrev->setIcon(QIcon(":/qmlprofiler/prev.png")); + buttonPrev->setIcon(QIcon(":/qmlprofiler/ico_prev.png")); buttonPrev->setToolTip(tr("Jump to previous event")); connect(buttonPrev, SIGNAL(clicked()), this, SIGNAL(jumpToPrev())); connect(this, SIGNAL(enableToolbar(bool)), buttonPrev, SLOT(setEnabled(bool))); QToolButton *buttonNext= new QToolButton; - buttonNext->setIcon(QIcon(":/qmlprofiler/next.png")); + buttonNext->setIcon(QIcon(":/qmlprofiler/ico_next.png")); buttonNext->setToolTip(tr("Jump to next event")); connect(buttonNext, SIGNAL(clicked()), this, SIGNAL(jumpToNext())); connect(this, SIGNAL(enableToolbar(bool)), buttonNext, SLOT(setEnabled(bool))); QToolButton *buttonZoomControls = new QToolButton; - buttonZoomControls->setIcon(QIcon(":/qmlprofiler/magnifier.png")); + buttonZoomControls->setIcon(QIcon(":/qmlprofiler/ico_zoom.png")); buttonZoomControls->setToolTip(tr("Show zoom slider")); buttonZoomControls->setCheckable(true); buttonZoomControls->setChecked(false); @@ -167,7 +186,7 @@ QWidget *TraceWindow::createToolbar() connect(this, SIGNAL(enableToolbar(bool)), buttonZoomControls, SLOT(setEnabled(bool))); m_buttonRange = new QToolButton; - m_buttonRange->setIcon(QIcon(":/qmlprofiler/range.png")); + m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png")); m_buttonRange->setToolTip(tr("Select range")); m_buttonRange->setCheckable(true); m_buttonRange->setChecked(false); @@ -176,7 +195,7 @@ QWidget *TraceWindow::createToolbar() connect(this, SIGNAL(rangeModeChanged(bool)), m_buttonRange, SLOT(setChecked(bool))); m_buttonLock = new QToolButton; - m_buttonLock->setIcon(QIcon(":/qmlprofiler/arrow_select.png")); + m_buttonLock->setIcon(QIcon(":/qmlprofiler/ico_selectionmode.png")); m_buttonLock->setToolTip(tr("View event information on mouseover")); m_buttonLock->setCheckable(true); m_buttonLock->setChecked(false); @@ -184,11 +203,13 @@ QWidget *TraceWindow::createToolbar() 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(new Utils::StyledSeparator()); toolBarLayout->addWidget(buttonZoomControls); + toolBarLayout->addWidget(new Utils::StyledSeparator()); toolBarLayout->addWidget(m_buttonRange); + toolBarLayout->addWidget(m_buttonLock); return bar; } @@ -220,9 +241,6 @@ QWidget *TraceWindow::createZoomToolbar() height: 20px;\ margin: 0px 0px 0px 0px;\ }\ - QSlider::groove:horizontal {\ - position: absolute;\ - }\ QSlider::add-page:horizontal {\ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\ border: 1px #313131;\ @@ -343,9 +361,9 @@ void TraceWindow::toggleRangeMode(bool active) bool rangeMode = m_mainView->rootObject()->property("selectionRangeMode").toBool(); if (active != rangeMode) { if (active) - m_buttonRange->setIcon(QIcon(":/qmlprofiler/range_pressed.png")); + m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselected.png")); else - m_buttonRange->setIcon(QIcon(":/qmlprofiler/range.png")); + m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png")); m_mainView->rootObject()->setProperty("selectionRangeMode", QVariant(active)); } } @@ -354,9 +372,9 @@ void TraceWindow::updateRangeButton() { bool rangeMode = m_mainView->rootObject()->property("selectionRangeMode").toBool(); if (rangeMode) - m_buttonRange->setIcon(QIcon(":/qmlprofiler/range_pressed.png")); + m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselected.png")); else - m_buttonRange->setIcon(QIcon(":/qmlprofiler/range.png")); + m_buttonRange->setIcon(QIcon(":/qmlprofiler/ico_rangeselection.png")); emit rangeModeChanged(rangeMode); } diff --git a/src/plugins/qmlprofiler/tracewindow.h b/src/plugins/qmlprofiler/tracewindow.h index 3f9f0c02272..e1e401e4169 100644 --- a/src/plugins/qmlprofiler/tracewindow.h +++ b/src/plugins/qmlprofiler/tracewindow.h @@ -43,10 +43,7 @@ #include #include - -QT_BEGIN_NAMESPACE -class QDeclarativeView; -QT_END_NAMESPACE +#include namespace QmlProfiler { namespace Internal { @@ -80,6 +77,16 @@ private: qint64 m_endTime; }; +class ScrollableDeclarativeView : public QDeclarativeView +{ + Q_OBJECT +public: + explicit ScrollableDeclarativeView(QWidget *parent = 0); + ~ScrollableDeclarativeView(); +protected: + void scrollContentsBy(int dx, int dy); +}; + class TraceWindow : public QWidget { Q_OBJECT @@ -156,7 +163,7 @@ private: QWeakPointer m_v8plugin; QSize m_sizeHint; - QDeclarativeView *m_mainView; + ScrollableDeclarativeView *m_mainView; QDeclarativeView *m_timebar; QDeclarativeView *m_overview; QmlJsDebugClient::QmlProfilerEventList *m_eventList;