QmlProfiler: Selection Range

Change-Id: Ifa39de4762c05dc859cbd764a10760a82821d74f
Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
This commit is contained in:
Christiaan Janssen
2011-10-19 14:28:21 +02:00
parent c937f52929
commit 267b96e18e
12 changed files with 513 additions and 8 deletions

View File

@@ -62,6 +62,9 @@ Rectangle {
property real elapsedTime
signal updateTimer
signal updateRangeButton
property bool selectionRangeMode: false
// ***** connections with external objects
Connections {
target: zoomControl
@@ -187,6 +190,16 @@ Rectangle {
zoomControl.setRange(startTime, startTime + newWindowLength);
}
function recenter( centerPoint ) {
var windowLength = view.endTime - view.startTime;
var newStart = Math.floor(centerPoint - windowLength/2);
if (newStart < 0)
newStart = 0;
if (newStart + windowLength > qmlEventList.traceEndTime())
newStart = qmlEventList.traceEndTime() - windowLength;
zoomControl.setRange(newStart, newStart + windowLength);
}
function hideRangeDetails() {
rangeDetails.visible = false;
rangeDetails.duration = "";
@@ -220,6 +233,11 @@ Rectangle {
selectionHighlight.visible = false;
}
onSelectionRangeModeChanged: {
selectionRangeControl.enabled = selectionRangeMode;
selectionRange.reset(selectionRangeMode);
}
// ***** child items
Timer {
id: elapsedTimer
@@ -408,9 +426,9 @@ Rectangle {
color:"transparent"
border.width: 2
border.color: "blue"
z: 1
radius: 2
visible: false
z:1
}
MouseArea {
@@ -421,9 +439,66 @@ Rectangle {
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();
}
}
SelectionRange {
id: selectionRange
visible: root.selectionRangeMode
height: root.height
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();
}
}
}
}
SelectionRangeDetails {
id: selectionRangeDetails
visible: root.selectionRangeMode
startTime: selectionRange.startTimeString
duration: selectionRange.durationString
endTime: selectionRange.endTimeString
showDuration: selectionRange.width > 1
}
RangeDetails {
id: rangeDetails
}

View File

@@ -44,7 +44,7 @@ BorderImage {
property bool locked: !root.mouseOverSelection
source: "popup.png"
source: "popup_green.png"
border {
left: 10; top: 10
right: 20; bottom: 20

View File

@@ -0,0 +1,272 @@
/**************************************************************************
**
** 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
Rectangle {
id: selectionRange
width: 1
color: "transparent"
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 string startTimeString: detailedPrintTime(startTime)
property string endTimeString: detailedPrintTime(startTime+duration)
property string durationString: detailedPrintTime(duration)
property variant startTime: x * selectionRange.viewTimePerPixel
property variant duration: width * selectionRange.viewTimePerPixel
property variant viewTimePerPixel: 1
property variant creationState : 0
property variant x1
property variant x2
property variant x3: Math.min(x1, x2)
property variant x4: Math.max(x1, x2)
property bool isDragging: false
Connections {
target: zoomControl
onRangeChanged: {
var oldTimePerPixel = selectionRange.viewTimePerPixel;
selectionRange.viewTimePerPixel = Math.abs(zoomControl.endTime() - zoomControl.startTime()) / flick.width;
if (creationState === 3 && oldTimePerPixel != selectionRange.viewTimePerPixel) {
selectionRange.x = x * oldTimePerPixel / selectionRange.viewTimePerPixel;
selectionRange.width = width * oldTimePerPixel / selectionRange.viewTimePerPixel;
}
}
}
onCreationStateChanged: {
switch (creationState) {
case 0: color = "transparent"; break;
case 1: color = thinColor; break;
default: color = lighterColor; break;
}
}
onIsDraggingChanged: {
if (isDragging)
color = darkerColor;
else
color = lighterColor;
}
function reset(setVisible) {
width = 1;
creationState = 0;
visible = setVisible;
}
function setPos(pos) {
switch (creationState) {
case 1: {
width = 1;
x1 = pos;
x2 = pos;
x = pos;
break;
}
case 2: {
x2 = pos;
x = x3;
width = x4-x3;
break;
}
default: return;
}
}
function detailedPrintTime( t )
{
if (t <= 0) return "0";
if (t<1000) return t+" ns";
t = Math.floor(t/1000);
if (t<1000) return t+" μs";
if (t<1e6) return (t/1000) + " ms";
return (t/1e6) + " s";
}
// creation control
function releasedOnCreation() {
if (selectionRange.creationState === 2) {
flick.interactive = true;
selectionRange.creationState = 3;
selectionRangeControl.enabled = false;
}
}
function pressedOnCreation() {
if (selectionRange.creationState === 1) {
flick.interactive = false;
selectionRange.setPos(selectionRangeControl.mouseX + flick.contentX);
selectionRange.creationState = 2;
}
}
function movedOnCreation() {
if (selectionRange.creationState === 0) {
selectionRange.creationState = 1;
}
if (!root.eventCount)
return;
if (!selectionRangeControl.pressed && selectionRange.creationState==3)
return;
if (selectionRangeControl.pressed) {
selectionRange.setPos(selectionRangeControl.mouseX + flick.contentX);
} else {
selectionRange.setPos(selectionRangeControl.mouseX + flick.contentX);
}
}
Rectangle {
id: leftBorder
visible: selectionRange.creationState === 3
// used for dragging the borders
property real initialX: 0
property real initialWidth: 0
x: 0
height: parent.height
width: 1
color: darkerColor
border.color: hardBorderColor
border.width: 0
states: State {
name: "highlighted"
PropertyChanges {
target: leftBorder
width: 3
border.width: 2
}
}
onXChanged: if (x != 0) {
selectionRange.width = initialWidth - x;
selectionRange.x = initialX + x;
x = 0;
}
MouseArea {
x: -3
width: 7
y: 0
height: parent.height
drag.target: leftBorder
drag.axis: "XAxis"
drag.minimumX: -parent.initialX
drag.maximumX: parent.initialWidth - 2
hoverEnabled: true
onEntered: parent.state = "highlighted"
onExited: {
if (!pressed) parent.state = "";
}
onReleased: {
if (!containsMouse) parent.state = "" ;
}
onPressed: {
parent.initialX = selectionRange.x;
parent.initialWidth = selectionRange.width;
}
}
}
Rectangle {
id: rightBorder
visible: selectionRange.creationState === 3
x: selectionRange.width
height: parent.height
width: 1
color: darkerColor
border.color: hardBorderColor
border.width: 0
states: State {
name: "highlighted"
PropertyChanges {
target: rightBorder
width: 3
border.width: 2
}
}
onXChanged: {
if (x != selectionRange.width) {
selectionRange.width = x;
}
}
MouseArea {
x: -3
width: 7
y: 0
height: parent.height
drag.target: rightBorder
drag.axis: "XAxis"
drag.minimumX: 1
drag.maximumX: flick.contentWidth - selectionRange.x
hoverEnabled: true
onEntered: {
parent.state = "highlighted";
}
onExited: {
if (!pressed) parent.state = "";
}
onReleased: {
if (!containsMouse) parent.state = "";
}
}
}
}

View File

@@ -0,0 +1,113 @@
/**************************************************************************
**
** 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
BorderImage {
id: selectionRangeDetails
property string startTime
property string endTime
property string duration
property bool showDuration
source: "popup_orange.png"
border {
left: 10; top: 10
right: 20; bottom: 20
}
width: 170
height: childrenRect.height
z: 1
visible: false
x: 200
y: 125
//title
Text {
id: typeTitle
text: qsTr("Selection")
font.bold: true
y: 10
anchors.horizontalCenter: parent.horizontalCenter
anchors.horizontalCenterOffset: -5
}
//details
Column {
id: col
anchors.top: typeTitle.bottom
x: 2
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
}
}
Text {
id: closeIcon
x: selectionRangeDetails.width - 24
y: 10
text:"X"
MouseArea {
anchors.fill: parent
anchors.leftMargin: -8
onClicked: {
root.selectionRangeMode = false;
root.updateRangeButton();
}
}
}
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);
}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -3,7 +3,8 @@
<file>Detail.qml</file>
<file>Label.qml</file>
<file>MainView.qml</file>
<file>popup.png</file>
<file>popup_green.png</file>
<file>popup_orange.png</file>
<file>RangeDetails.qml</file>
<file>RangeMover.qml</file>
<file>TimeDisplay.qml</file>
@@ -20,5 +21,9 @@
<file>TimeMarks.qml</file>
<file>Overview.qml</file>
<file>Overview.js</file>
<file>range.png</file>
<file>range_pressed.png</file>
<file>SelectionRange.qml</file>
<file>SelectionRangeDetails.qml</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

View File

@@ -58,6 +58,8 @@ OTHER_FILES += \
qml/TimeDisplay.qml \
qml/TimeMarks.qml \
qml/StatusDisplay.qml \
qml/SelectionRange.qml \
qml/SelectionRangeDetails.qml \
qml/Overview.qml \
qml/Overview.js

View File

@@ -41,7 +41,6 @@
#include <QtDeclarative/QDeclarativeView>
#include <QtDeclarative/QDeclarativeContext>
#include <QtGui/QVBoxLayout>
#include <QtGui/QToolButton>
#include <QtGui/QGraphicsObject>
#include <QtGui/QContextMenuEvent>
#include <QtGui/QScrollBar>
@@ -73,7 +72,7 @@ TraceWindow::TraceWindow(QWidget *parent)
m_timebar = new QDeclarativeView(this);
m_timebar->setResizeMode(QDeclarativeView::SizeRootObjectToView);
m_timebar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
m_timebar->setMaximumHeight(24);
m_timebar->setFixedHeight(24);
m_overview = new QDeclarativeView(this);
m_overview->setResizeMode(QDeclarativeView::SizeRootObjectToView);
@@ -115,9 +114,9 @@ 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);
bar->setFixedWidth(150);
bar->setFixedHeight(24);
QHBoxLayout *toolBarLayout = new QHBoxLayout(bar);
toolBarLayout->setMargin(0);
toolBarLayout->setSpacing(0);
@@ -141,11 +140,20 @@ QWidget *TraceWindow::createToolbar()
buttonZoomOut->setToolTip(tr("Zoom out 10%"));
connect(buttonZoomOut, SIGNAL(clicked()), this, SIGNAL(zoomOut()));
connect(this, SIGNAL(enableToolbar(bool)), buttonZoomOut, SLOT(setEnabled(bool)));
m_buttonRange = new QToolButton;
m_buttonRange->setIcon(QIcon(":/qmlprofiler/range.png"));
m_buttonRange->setToolTip(tr("Select range"));
m_buttonRange->setCheckable(true);
m_buttonRange->setChecked(false);
connect(m_buttonRange, SIGNAL(clicked(bool)), this, SLOT(toggleRangeMode(bool)));
connect(this, SIGNAL(enableToolbar(bool)), m_buttonRange, SLOT(setEnabled(bool)));
connect(this, SIGNAL(rangeModeChanged(bool)), m_buttonRange, SLOT(setChecked(bool)));
toolBarLayout->addWidget(buttonPrev);
toolBarLayout->addWidget(buttonNext);
toolBarLayout->addWidget(buttonZoomIn);
toolBarLayout->addWidget(buttonZoomOut);
toolBarLayout->addWidget(m_buttonRange);
return bar;
}
@@ -186,6 +194,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_eventList, SIGNAL(countChanged()), this, SLOT(updateToolbar()));
connect(this, SIGNAL(jumpToPrev()), m_mainView->rootObject(), SLOT(prevEvent()));
connect(this, SIGNAL(jumpToNext()), m_mainView->rootObject(), SLOT(nextEvent()));
@@ -239,6 +248,28 @@ void TraceWindow::updateToolbar()
emit enableToolbar(m_eventList && m_eventList->count()>0);
}
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"));
else
m_buttonRange->setIcon(QIcon(":/qmlprofiler/range.png"));
m_mainView->rootObject()->setProperty("selectionRangeMode", QVariant(active));
}
}
void TraceWindow::updateRangeButton()
{
bool rangeMode = m_mainView->rootObject()->property("selectionRangeMode").toBool();
if (rangeMode)
m_buttonRange->setIcon(QIcon(":/qmlprofiler/range_pressed.png"));
else
m_buttonRange->setIcon(QIcon(":/qmlprofiler/range.png"));
emit rangeModeChanged(rangeMode);
}
void TraceWindow::setRecording(bool recording)
{
if (recording) {

View File

@@ -40,6 +40,7 @@
#include <QtCore/QPointer>
#include <QtGui/QWidget>
#include <QtGui/QToolButton>
QT_BEGIN_NAMESPACE
class QDeclarativeView;
@@ -94,6 +95,9 @@ public slots:
void updateTimer();
void clearDisplay();
void updateToolbar();
void toggleRangeMode(bool);
void updateRangeButton();
void qmlComplete();
void v8Complete();
@@ -112,6 +116,7 @@ signals:
void jumpToNext();
void zoomIn();
void zoomOut();
void rangeModeChanged(bool);
void enableToolbar(bool);
void contextMenuRequested(const QPoint& position);
@@ -136,6 +141,8 @@ private:
bool m_v8DataReady;
QWeakPointer<ZoomControl> m_zoomControl;
QToolButton *m_buttonRange;
};
} // namespace Internal