Timeline: Create new library from contents of QmlProfiler

Change-Id: I964b2f149e237eb25a08600e8dab8968e8bc0cb9
Reviewed-by: Kai Koehne <kai.koehne@theqtcompany.com>
This commit is contained in:
Ulf Hermann
2014-12-10 12:53:49 +01:00
parent acc4d1a412
commit c40d9e9d17
90 changed files with 307 additions and 198 deletions

View File

@@ -1,155 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.2
ToolBar {
id: buttons
readonly property int buttonWidth: 25
signal jumpToPrev()
signal jumpToNext()
signal zoomControlChanged()
signal filterMenuChanged()
signal rangeSelectChanged()
signal lockChanged()
function updateLockButton(locked) {
lockButton.checked = !locked;
}
function lockButtonChecked() {
return lockButton.checked;
}
function updateRangeButton(rangeMode) {
rangeButton.checked = rangeMode;
}
function rangeButtonChecked() {
return rangeButton.checked
}
style: ToolBarStyle {
padding {
left: 0
right: 0
top: 0
bottom: 0
}
background: Rectangle {
anchors.fill: parent
color: "#9B9B9B"
}
}
RowLayout {
spacing: 0
anchors.fill: parent
ToolButton {
id: jumpToPrevButton
anchors.top: parent.top
anchors.bottom: parent.bottom
implicitWidth: buttonWidth
iconSource: "qrc:/qmlprofiler/ico_prev.png"
tooltip: qsTr("Jump to previous event.")
onClicked: buttons.jumpToPrev()
}
ToolButton {
id: jumpToNextButton
anchors.top: parent.top
anchors.bottom: parent.bottom
implicitWidth: buttonWidth
iconSource: "qrc:/qmlprofiler/ico_next.png"
tooltip: qsTr("Jump to next event.")
onClicked: buttons.jumpToNext()
}
ToolButton {
id: zoomControlButton
anchors.top: parent.top
anchors.bottom: parent.bottom
implicitWidth: buttonWidth
iconSource: "qrc:/qmlprofiler/ico_zoom.png"
tooltip: qsTr("Show zoom slider.")
checkable: true
checked: false
onCheckedChanged: buttons.zoomControlChanged()
}
ToolButton {
id: filterButton
anchors.top: parent.top
anchors.bottom: parent.bottom
implicitWidth: buttonWidth
iconSource: "qrc:/qmlprofiler/ico_filter.png"
tooltip: qsTr("Filter Categories")
checkable: true
onCheckedChanged: buttons.filterMenuChanged()
}
ToolButton {
id: rangeButton
anchors.top: parent.top
anchors.bottom: parent.bottom
implicitWidth: buttonWidth
iconSource: checked ? "qrc:/qmlprofiler/ico_rangeselected.png" :
"qrc:/qmlprofiler/ico_rangeselection.png"
tooltip: qsTr("Select range.")
checkable: true
checked: false
onCheckedChanged: buttons.rangeSelectChanged()
}
ToolButton {
id: lockButton
anchors.top: parent.top
anchors.bottom: parent.bottom
implicitWidth: buttonWidth
iconSource: "qrc:/qmlprofiler/ico_selectionmode.png"
tooltip: qsTr("View event information on mouseover.")
checkable: true
checked: false
onCheckedChanged: buttons.lockChanged()
}
}
}

View File

@@ -1,301 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
import QtQuick 2.1
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
Item {
id: labelContainer
property QtObject model
property QtObject notesModel
property bool mockup
property string text: model ? model.displayName : ""
property bool expanded: model && model.expanded
property var descriptions: []
property var extdescriptions: []
property var selectionIds: []
property bool dragging
property int visualIndex
property int dragOffset
property Item draggerParent
signal dragStarted;
signal dragStopped;
signal dropped(int sourceIndex, int targetIndex)
signal selectById(int eventId)
signal selectNextBySelectionId(int selectionId)
signal selectPrevBySelectionId(int selectionId)
readonly property int dragHeight: 5
property bool reverseSelect: false
visible: model && (mockup || (!model.hidden && !model.empty))
height: model ? Math.max(txt.height, model.height) : 0
width: 150
function updateDescriptions() {
var desc=[];
var ids=[];
var extdesc=[];
var labelList = model.labels;
for (var i = 0; i < labelList.length; i++ ) {
extdesc[i] = desc[i] = (labelList[i].description || qsTr("<bytecode>"));
ids[i] = labelList[i].id;
if (labelList[i].displayName !== undefined)
extdesc[i] += " (" + labelList[i].displayName + ")";
}
descriptions = desc;
selectionIds = ids;
extdescriptions = extdesc;
}
Connections {
target: model
onLabelsChanged: updateDescriptions()
}
MouseArea {
id: dragArea
anchors.fill: txt
drag.target: dragger
cursorShape: dragging ? Qt.ClosedHandCursor : Qt.OpenHandCursor
drag.minimumY: dragging ? 0 : -dragOffset // Account for parent change below
drag.maximumY: draggerParent.height - (dragging ? 0 : dragOffset)
}
DropArea {
id: dropArea
onPositionChanged: {
var sourceIndex = drag.source.visualIndex;
if (drag.source.y === 0) {
// special case for first position: Always swap, no matter if upper border touched.
if (sourceIndex > visualIndex)
labelContainer.dropped(sourceIndex, visualIndex);
} else if (sourceIndex !== visualIndex && sourceIndex !== visualIndex + 1) {
labelContainer.dropped(sourceIndex, sourceIndex > visualIndex ? visualIndex + 1 :
visualIndex);
}
}
anchors.fill: parent
}
Text {
id: txt
x: 5
font.pixelSize: 12
text: labelContainer.text
color: "#232323"
height: model ? model.defaultRowHeight : 0
width: 140
verticalAlignment: Text.AlignVCenter
renderType: Text.NativeRendering
}
Column {
id: column
property QtObject parentModel: model
anchors.top: txt.bottom
visible: expanded
Repeater {
model: descriptions.length
Button {
width: labelContainer.width
height: column.parentModel ? column.parentModel.rowHeight(index + 1) : 0
action: Action {
onTriggered: {
if (reverseSelect)
labelContainer.selectPrevBySelectionId(selectionIds[index]);
else
labelContainer.selectNextBySelectionId(selectionIds[index]);
}
tooltip: extdescriptions[index]
}
style: ButtonStyle {
background: Rectangle {
border.width: 1
border.color: "#c8c8c8"
color: "#eaeaea"
}
label: Text {
text: descriptions[index]
textFormat: Text.PlainText
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
elide: Text.ElideRight
renderType: Text.NativeRendering
}
}
MouseArea {
hoverEnabled: true
property bool resizing: false
onPressed: resizing = true
onReleased: resizing = false
height: dragHeight
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
cursorShape: Qt.SizeVerCursor
onMouseYChanged: {
if (resizing) {
column.parentModel.setExpandedRowHeight(index + 1, y + mouseY);
parent.height = column.parentModel.rowHeight(index + 1);
}
}
}
}
}
}
ToolButton {
id: notesButton
anchors.verticalCenter: txt.verticalCenter
anchors.right: expandButton.left
implicitWidth: 17
implicitHeight: txt.height - 1
property var eventIds: []
property var texts: []
property int currentNote: -1
Connections {
target: notesModel
onChanged: {
if (arguments[1] === -1 || arguments[1] === model.modelId)
notesButton.updateNotes();
}
}
function updateNotes() {
var notes = notesModel.byTimelineModel(model.modelId);
var newTexts = [];
var newEventIds = [];
for (var i in notes) {
newTexts.push(notesModel.text(notes[i]))
newEventIds.push(notesModel.timelineIndex(notes[i]));
}
// Bindings are only triggered when assigning the whole array.
eventIds = newEventIds;
texts = newTexts;
}
visible: eventIds.length > 0
iconSource: "ico_note.png"
tooltip: texts.join("\n");
onClicked: {
if (++currentNote >= eventIds.length)
currentNote = 0;
labelContainer.selectById(eventIds[currentNote]);
}
}
ToolButton {
id: expandButton
anchors.verticalCenter: txt.verticalCenter
anchors.right: parent.right
implicitWidth: 17
implicitHeight: txt.height - 1
enabled: expanded || (model && !model.empty)
iconSource: expanded ? "arrow_down.png" : "arrow_right.png"
tooltip: expanded ? qsTr("Collapse category") : qsTr("Expand category.")
onClicked: model.expanded = !expanded
}
Rectangle {
id: dragger
property int visualIndex: labelContainer.visualIndex
width: labelContainer.width
height: 0
color: "black"
opacity: 0.5
anchors.left: parent.left
// anchor to top so that it reliably snaps back after dragging
anchors.top: parent.top
Drag.active: dragArea.drag.active
Drag.onActiveChanged: {
// We don't want height or text to be changed when reordering occurs, so we don't make
// them properties.
draggerText.text = txt.text;
if (Drag.active) {
height = labelContainer.height;
labelContainer.dragStarted();
} else {
height = 0;
labelContainer.dragStopped();
}
}
states: [
State {
when: dragger.Drag.active
ParentChange {
target: dragger
parent: draggerParent
}
PropertyChanges {
target: dragger
anchors.top: undefined
}
}
]
Text {
id: draggerText
visible: parent.Drag.active
x: txt.x
font.pixelSize: txt.font.pixelSize
color: "white"
width: txt.width
height: txt.height
verticalAlignment: txt.verticalAlignment
renderType: txt.renderType
}
}
MouseArea {
anchors.top: dragArea.bottom
anchors.bottom: labelContainer.dragging ? labelContainer.bottom : dragArea.bottom
anchors.left: labelContainer.left
anchors.right: labelContainer.right
cursorShape: dragArea.cursorShape
}
}

View File

@@ -1,41 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
import QtQuick 2.1
Text {
property bool isLabel: false
font.pixelSize: 12
font.bold: isLabel
textFormat: Text.PlainText
renderType: Text.NativeRendering
elide: Text.ElideRight
width: text === "" ? 0 : (isLabel ? 85 : 170)
}

View File

@@ -1,472 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
import QtQuick 2.1
import QtQuick.Controls 1.0
Rectangle {
id: root
// ***** properties
property bool lockItemSelection : false
signal updateCursorPosition
property string fileName: ""
property int lineNumber: -1
property int columnNumber: 0
property int selectedModel: -1
property int selectedItem: -1
property bool selectionRangeMode: false
property bool selectionRangeReady: selectionRange.ready
property real selectionRangeStart: selectionRange.startTime
property real selectionRangeEnd: selectionRange.startTime + selectionRange.duration
property int typeId: content.typeId
onTypeIdChanged: updateCursorPosition()
color: "#dcdcdc"
// ***** connections with external objects
Connections {
target: zoomControl
onRangeChanged: {
zoomSliderToolBar.updateZoomLevel();
content.scroll();
// If you select something in the main view and then resize the current range by some
// other means, the selection should stay where it was.
var oldTimePerPixel = selectionRange.viewTimePerPixel;
selectionRange.viewTimePerPixel = zoomControl.rangeDuration / content.width;
if (selectionRange.creationState === selectionRange.creationFinished &&
oldTimePerPixel != selectionRange.viewTimePerPixel) {
var newWidth = selectionRange.rangeWidth * oldTimePerPixel /
selectionRange.viewTimePerPixel;
selectionRange.rangeLeft = selectionRange.rangeLeft * oldTimePerPixel /
selectionRange.viewTimePerPixel;
selectionRange.rangeRight = selectionRange.rangeLeft + newWidth;
}
}
onWindowChanged: {
content.scroll();
}
}
Connections {
target: timelineModelAggregator
onDataAvailable: {
content.clearChildren();
zoomControl.setRange(zoomControl.traceStart,
zoomControl.traceStart + zoomControl.traceDuration / 10);
}
}
onSelectionRangeModeChanged: {
selectionRange.reset();
buttonsBar.updateRangeButton(selectionRangeMode);
}
// ***** functions
function clear() {
content.clearChildren();
rangeDetails.hide();
selectionRangeMode = false;
zoomSlider.externalUpdate = true;
zoomSlider.value = zoomSlider.minimumValue;
}
function enableButtonsBar(enable) {
buttonsBar.enabled = enable;
}
function selectByTypeId(typeId)
{
if (lockItemSelection || typeId === -1)
return;
var itemIndex = -1;
var modelIndex = -1;
var notesModel = timelineModelAggregator.notes;
var notes = notesModel ? notesModel.byTypeId(typeId) : [];
if (notes.length !== 0) {
itemIndex = notesModel.timelineIndex(notes[0]);
var modelId = notesModel.timelineModel(notes[0]);
for (modelIndex = 0; modelIndex < timelineModelAggregator.models.length;
++modelIndex) {
if (timelineModelAggregator.models[modelIndex].modelId === modelId)
break;
}
} else {
for (modelIndex = 0; modelIndex < timelineModelAggregator.models.length; ++modelIndex) {
if (modelIndex === selectedModel && selectedItem !== -1 &&
typeId === timelineModelAggregator.models[modelIndex].typeId(selectedItem))
break;
if (!timelineModelAggregator.models[modelIndex].handlesTypeId(typeId))
continue;
itemIndex = timelineModelAggregator.models[modelIndex].nextItemByTypeId(typeId,
zoomControl.rangeStart, selectedItem);
if (itemIndex !== -1)
break;
}
}
if (modelIndex !== -1 && modelIndex < timelineModelAggregator.models.length &&
itemIndex !== -1) {
// select an item, lock to it, and recenter if necessary
content.select(modelIndex, itemIndex);
content.selectionLocked = true;
}
}
focus: true
property bool shiftPressed: false;
Keys.onPressed: shiftPressed = (event.key === Qt.Key_Shift);
Keys.onReleased: shiftPressed = false;
TimelineLabels {
id: categories
anchors.top: buttonsBar.bottom
anchors.bottom: overview.top
anchors.left: parent.left
anchors.right: parent.right
contentY: content.contentY
selectedModel: root.selectedModel
selectedItem: root.selectedItem
color: root.color
modelProxy: timelineModelAggregator
zoomer: zoomControl
reverseSelect: shiftPressed
onMoveCategories: content.moveCategories(sourceIndex, targetIndex)
onSelectItem: content.select(modelIndex, eventIndex)
}
TimeDisplay {
id: timeDisplay
anchors.top: parent.top
anchors.left: buttonsBar.right
anchors.right: parent.right
anchors.bottom: overview.top
windowStart: zoomControl.windowStart
rangeDuration: Math.max(1, Math.round(zoomControl.rangeDuration))
contentX: content.contentX
clip: true
}
ButtonsBar {
id: buttonsBar
enabled: timelineModelAggregator.height > 0
anchors.top: parent.top
anchors.left: parent.left
width: 150
height: 24
onZoomControlChanged: zoomSliderToolBar.visible = !zoomSliderToolBar.visible
onFilterMenuChanged: filterMenu.visible = !filterMenu.visible
onJumpToNext: {
var next = timelineModelAggregator.nextItem(root.selectedModel, root.selectedItem,
zoomControl.rangeStart);
content.select(next.model, next.item);
}
onJumpToPrev: {
var prev = timelineModelAggregator.prevItem(root.selectedModel, root.selectedItem,
zoomControl.rangeEnd);
content.select(prev.model, prev.item);
}
onRangeSelectChanged: selectionRangeMode = rangeButtonChecked();
onLockChanged: content.selectionLocked = !lockButtonChecked();
}
TimelineContent {
id: content
anchors.left: buttonsBar.right
anchors.top: buttonsBar.bottom
anchors.bottom: overview.top
anchors.right: parent.right
selectionLocked: true
zoomer: zoomControl
modelProxy: timelineModelAggregator
onSelectionLockedChanged: {
buttonsBar.updateLockButton(selectionLocked);
}
onPropagateSelection: {
if (lockItemSelection || (newModel === selectedModel && newItem === selectedItem))
return;
lockItemSelection = true;
if (selectedModel !== -1 && selectedModel !== newModel)
select(selectedModel, -1);
selectedItem = newItem
selectedModel = newModel
if (selectedItem !== -1) {
// display details
rangeDetails.showInfo(selectedModel, selectedItem);
// update in other views
var model = timelineModelAggregator.models[selectedModel];
var eventLocation = model.location(selectedItem);
gotoSourceLocation(eventLocation.file, eventLocation.line,
eventLocation.column);
typeId = model.typeId(selectedItem);
} else {
rangeDetails.hide();
}
lockItemSelection = false;
}
onGotoSourceLocation: {
if (file !== undefined) {
root.fileName = file;
root.lineNumber = line;
root.columnNumber = column;
}
}
}
MouseArea {
id: selectionRangeControl
enabled: selectionRangeMode &&
selectionRange.creationState !== selectionRange.creationFinished
anchors.right: content.right
anchors.left: buttonsBar.right
anchors.top: content.top
anchors.bottom: content.bottom
hoverEnabled: enabled
z: 2
onReleased: {
if (selectionRange.creationState === selectionRange.creationSecondLimit) {
content.stayInteractive = true;
selectionRange.creationState = selectionRange.creationFinished;
}
}
onPressed: {
if (selectionRange.creationState === selectionRange.creationFirstLimit) {
content.stayInteractive = false;
selectionRange.setPos(selectionRangeControl.mouseX + content.contentX);
selectionRange.creationState = selectionRange.creationSecondLimit;
}
}
onPositionChanged: {
if (selectionRange.creationState === selectionRange.creationInactive)
selectionRange.creationState = selectionRange.creationFirstLimit;
if (selectionRangeControl.pressed ||
selectionRange.creationState !== selectionRange.creationFinished)
selectionRange.setPos(selectionRangeControl.mouseX + content.contentX);
}
onCanceled: pressed()
}
Flickable {
flickableDirection: Flickable.HorizontalFlick
clip: true
visible: selectionRangeMode &&
selectionRange.creationState !== selectionRange.creationInactive
interactive: false
x: content.x + content.flickableItem.x
y: content.y + content.flickableItem.y
height: content.flickableItem.height
width: content.flickableItem.width
contentX: content.contentX
contentWidth: content.contentWidth
SelectionRange {
id: selectionRange
zoomer: zoomControl
visible: parent.visible
onRangeDoubleClicked: {
zoomControl.setRange(startTime, endTime);
root.selectionRangeMode = false;
}
}
}
SelectionRangeDetails {
z: 1
x: 200
y: 125
id: selectionRangeDetails
visible: selectionRange.visible
startTime: selectionRange.startTime
duration: selectionRange.duration
endTime: selectionRange.endTime
showDuration: selectionRange.rangeWidth > 1
onRecenter: {
if ((selectionRange.startTime < zoomControl.rangeStart) ^
(selectionRange.endTime > zoomControl.rangeEnd)) {
var center = selectionRange.startTime + selectionRange.duration / 2;
var halfDuration = Math.max(selectionRange.duration, zoomControl.rangeDuration / 2);
zoomControl.setRange(center - halfDuration, center + halfDuration);
}
}
onClose: selectionRangeMode = false;
}
RangeDetails {
id: rangeDetails
z: 1
visible: false
x: 200
y: 25
locked: content.selectionLocked
models: timelineModelAggregator.models
notes: timelineModelAggregator.notes
onRecenterOnItem: {
content.gotoSourceLocation(file, line, column);
content.select(selectedModel, selectedItem)
}
onToggleSelectionLocked: {
content.selectionLocked = !content.selectionLocked;
}
onClearSelection: {
content.propagateSelection(-1, -1);
}
}
Rectangle {
anchors.left: buttonsBar.right
anchors.bottom: overview.top
anchors.top: parent.top
width: 1
color: "#B0B0B0"
}
Rectangle {
id: filterMenu
color: "#9b9b9b"
enabled: buttonsBar.enabled
visible: false
width: buttonsBar.width
anchors.left: parent.left
anchors.top: buttonsBar.bottom
height: timelineModelAggregator.models.length * buttonsBar.height
Repeater {
id: filterMenuInner
model: timelineModelAggregator.models
CheckBox {
anchors.left: filterMenu.left
anchors.right: filterMenu.right
height: buttonsBar.height
y: index * height
text: modelData.displayName
enabled: !modelData.empty
checked: enabled && !modelData.hidden
onCheckedChanged: modelData.hidden = !checked
}
}
}
Rectangle {
id: zoomSliderToolBar
objectName: "zoomSliderToolBar"
color: "#9b9b9b"
enabled: buttonsBar.enabled
visible: false
width: buttonsBar.width
height: buttonsBar.height
anchors.left: parent.left
anchors.top: buttonsBar.bottom
function updateZoomLevel() {
zoomSlider.externalUpdate = true;
zoomSlider.value = Math.pow(zoomControl.rangeDuration /
Math.max(1, zoomControl.windowDuration),
1 / zoomSlider.exponent) * zoomSlider.maximumValue;
}
Slider {
id: zoomSlider
anchors.fill: parent
minimumValue: 1
maximumValue: 10000
stepSize: 100
property int exponent: 3
property bool externalUpdate: false
property int minWindowLength: 1e5 // 0.1 ms
onValueChanged: {
if (externalUpdate || zoomControl.windowEnd <= zoomControl.windowStart) {
// Zoom range is independently updated. We shouldn't mess
// with it here as otherwise we might introduce rounding
// or arithmetic errors.
externalUpdate = false;
return;
}
var windowLength = Math.max(
Math.pow(value / maximumValue, exponent) * zoomControl.windowDuration,
minWindowLength);
var fixedPoint = (zoomControl.rangeStart + zoomControl.rangeEnd) / 2;
if (root.selectedItem !== -1) {
// center on selected item if it's inside the current screen
var model = timelineModelAggregator.models[root.selectedModel]
var newFixedPoint = (model.startTime(root.selectedItem) +
model.endTime(root.selectedItem)) / 2;
if (newFixedPoint >= zoomControl.rangeStart &&
newFixedPoint < zoomControl.rangeEnd)
fixedPoint = newFixedPoint;
}
var startTime = Math.max(zoomControl.windowStart, fixedPoint - windowLength / 2)
zoomControl.setRange(startTime, startTime + windowLength);
}
}
}
Overview {
id: overview
height: 50
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.left: parent.left
modelProxy: timelineModelAggregator
zoomer: zoomControl
}
}

View File

@@ -1,197 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
import QtQuick 2.1
import TimelineOverviewRenderer 1.0
Rectangle {
id: overview
objectName: "Overview"
color: parent.color
property QtObject modelProxy
property QtObject zoomer
property bool recursionGuard: false
function updateRange() {
if (recursionGuard)
return;
recursionGuard = true;
var newStartTime = rangeMover.rangeLeft * zoomer.traceDuration / width +
zoomer.traceStart;
var newEndTime = rangeMover.rangeRight * zoomer.traceDuration / width +
zoomer.traceStart;
if (isFinite(newStartTime) && isFinite(newEndTime) && newEndTime - newStartTime > 500)
zoomer.setRange(newStartTime, newEndTime);
recursionGuard = false;
}
Connections {
target: zoomer
onRangeChanged: {
if (recursionGuard)
return;
recursionGuard = true;
var newRangeX = (zoomer.rangeStart - zoomer.traceStart) * width /
zoomer.traceDuration;
var newWidth = zoomer.rangeDuration * width / zoomer.traceDuration;
var widthChanged = Math.abs(newWidth - rangeMover.rangeWidth) > 1;
var leftChanged = Math.abs(newRangeX - rangeMover.rangeLeft) > 1;
if (leftChanged)
rangeMover.rangeLeft = newRangeX;
if (leftChanged || widthChanged)
rangeMover.rangeRight = newRangeX + newWidth;
recursionGuard = false;
}
}
TimeDisplay {
id: timebar
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
textMargin: 2
bottomBorderHeight: 0
topBorderHeight: 1
height: 10
fontSize: 6
labelsHeight: 10
color1: "#cccccc"
color2: "#cccccc"
windowStart: zoomer.traceStart
alignedWindowStart: zoomer.traceStart
rangeDuration: zoomer.traceDuration
contentX: 0
offsetX: 0
}
Column {
anchors.top: timebar.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
id: column
Repeater {
model: modelProxy.models
TimelineOverviewRenderer {
model: modelData
zoomer: overview.zoomer
notes: modelProxy.notes
width: column.width
height: column.height / modelProxy.models.length
}
}
}
Repeater {
id: noteSigns
property var modelsById: modelProxy.models.reduce(function(prev, model) {
prev[model.modelId] = model;
return prev;
}, {});
property int vertSpace: column.height / 7
property color noteColor: "orange"
readonly property double spacing: parent.width / zoomer.traceDuration
model: modelProxy.notes.count
Item {
property int timelineIndex: modelProxy.notes.timelineIndex(index)
property int timelineModel: modelProxy.notes.timelineModel(index)
property double startTime: noteSigns.modelsById[timelineModel].startTime(timelineIndex)
property double endTime: noteSigns.modelsById[timelineModel].endTime(timelineIndex)
x: ((startTime + endTime) / 2 - zoomer.traceStart) * noteSigns.spacing
y: timebar.height + noteSigns.vertSpace
height: noteSigns.vertSpace * 5
width: 2
Rectangle {
color: noteSigns.noteColor
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
height: noteSigns.vertSpace * 3
}
Rectangle {
color: noteSigns.noteColor
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: noteSigns.vertSpace
}
}
}
// ***** child items
MouseArea {
anchors.fill: parent
function jumpTo(posX) {
var newX = posX - rangeMover.rangeWidth / 2;
if (newX < 0)
newX = 0;
if (newX + rangeMover.rangeWidth > overview.width)
newX = overview.width - rangeMover.rangeWidth;
if (newX < rangeMover.rangeLeft) {
// Changing left border will change width, so precompute right border here.
var right = newX + rangeMover.rangeWidth;
rangeMover.rangeLeft = newX;
rangeMover.rangeRight = right;
} else if (newX > rangeMover.rangeLeft) {
rangeMover.rangeRight = newX + rangeMover.rangeWidth;
rangeMover.rangeLeft = newX;
}
}
onPressed: {
jumpTo(mouse.x);
}
onPositionChanged: {
jumpTo(mouse.x);
}
}
RangeMover {
id: rangeMover
visible: modelProxy.height > 0
onRangeLeftChanged: overview.updateRange()
onRangeRightChanged: overview.updateRange()
}
Rectangle {
height: 1
width: parent.width
color: "#858585"
}
}

View File

@@ -1,299 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
import QtQuick 2.1
Item {
id: rangeDetails
property string duration
property string label
property string dialogTitle
property string file
property int line
property int column
property bool isBindingLoop
property int selectedModel: -1
property int selectedItem: -1
property bool locked
property var models
property var notes
signal recenterOnItem
signal toggleSelectionLocked
signal clearSelection
width: col.width + 25
height: col.height + 30
function hide() {
noteEdit.focus = false;
visible = false;
selectedModel = selectedItem = -1;
noteEdit.text = "";
duration = "";
label = "";
file = "";
line = -1;
column = 0;
isBindingLoop = false;
}
Connections {
target: rangeDetails.parent
// keep inside view
onWidthChanged: fitInView();
onHeightChanged: fitInView();
}
ListModel {
id: eventInfo
}
function showInfo(model, item) {
// make sure we don't accidentally save the old text for the new event
noteEdit.focus = false;
selectedModel = model;
selectedItem = item;
var timelineModel = models[selectedModel];
var eventData = timelineModel.details(selectedItem)
eventInfo.clear();
for (var k in eventData) {
if (k === "displayName") {
dialogTitle = eventData[k];
} else if (eventData[k].length > 0) {
eventInfo.append({content : k});
eventInfo.append({content : eventData[k]});
}
}
rangeDetails.visible = true;
var location = timelineModel.location(selectedItem)
if (location.hasOwnProperty("file")) { // not empty
file = location.file;
line = location.line;
column = location.column;
} else {
// reset to default values
file = "";
line = 0;
column = -1;
}
noteEdit.focus = false;
var noteId = notes.get(timelineModel.modelId, selectedItem);
noteEdit.text = (noteId !== -1) ? notes.text(noteId) : "";
}
function fitInView() {
// don't reposition if it does not fit
if (parent.width < width || parent.height < height)
return;
if (x + width > parent.width)
x = parent.width - width;
if (x < 0)
x = 0;
if (y + height > parent.height)
y = parent.height - height;
if (y < 0)
y = 0;
}
// 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.dialogTitle
font.bold: true
height: 18
y: 2
verticalAlignment: Text.AlignVCenter
width: parent.width
color: "white"
renderType: Text.NativeRendering
elide: Text.ElideRight
}
// Details area
Rectangle {
color: "white"
width: parent.width
height: 10 + col.height + (noteEdit.visible ? (noteEdit.height + 5) : 0)
y: 20
border.width: 1
border.color: "#a0a0a0"
//details
Grid {
id: col
x: 10
y: 5
spacing: 5
columns: 2
Repeater {
model: eventInfo
Detail {
isLabel: index % 2 === 0
text: (content === undefined) ? "" : (isLabel ? (content + ":") : content)
}
}
}
TextEdit {
id: noteEdit
x: 10
anchors.topMargin: 5
anchors.bottomMargin: 5
anchors.top: col.bottom
visible: text.length > 0 || focus
width: col.width
wrapMode: Text.Wrap
color: "orange"
font.italic: true
renderType: Text.NativeRendering
selectByMouse: true
onTextChanged: saveTimer.restart()
onFocusChanged: {
if (!focus && selectedModel != -1 && selectedItem != -1) {
saveTimer.stop();
notes.setText(models[selectedModel].modelId, selectedItem, text);
}
}
Timer {
id: saveTimer
onTriggered: {
if (selectedModel != -1 && selectedItem != -1)
notes.setText(models[selectedModel].modelId, selectedItem, noteEdit.text);
}
interval: 1000
}
}
}
MouseArea {
anchors.fill: parent
drag.target: parent
drag.minimumX: 0
drag.maximumX: rangeDetails.parent.width - rangeDetails.width
drag.minimumY: 0
drag.maximumY: rangeDetails.parent.height - rangeDetails.height
onClicked: rangeDetails.recenterOnItem()
}
Image {
id: editIcon
source: "ico_edit.png"
anchors.top: closeIcon.top
anchors.right: lockIcon.left
anchors.rightMargin: 4
width: 8
height: 12
MouseArea {
anchors.fill: parent
onClicked: noteEdit.focus = true
}
}
Image {
id: lockIcon
source: locked?"lock_closed.png" : "lock_open.png"
anchors.top: closeIcon.top
anchors.right: closeIcon.left
anchors.rightMargin: 4
width: 8
height: 12
MouseArea {
anchors.fill: parent
onClicked: rangeDetails.toggleSelectionLocked()
}
}
Text {
id: closeIcon
x: col.width + 10
y: 4
text:"X"
color: "white"
renderType: Text.NativeRendering
MouseArea {
anchors.fill: parent
onClicked: rangeDetails.clearSelection()
}
}
}

View File

@@ -1,189 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
import QtQuick 2.1
Rectangle {
id: rangeMover
anchors.fill: parent
color: "transparent"
signal rangeDoubleClicked()
property color handleColor: "#869cd1"
property color rangeColor:"#444a64b8"
property color dragColor:"#664a64b8"
property color borderColor:"#cc4a64b8"
property color dragMarkerColor: "#4a64b8"
property color singleLineColor: "#4a64b8"
property alias rangeLeft: leftRange.x
property alias rangeRight: rightRange.x
readonly property alias rangeWidth: selectedRange.width
Rectangle {
id: selectedRange
x: leftRange.x
width: rightRange.x - leftRange.x
height: parent.height
color: width > 1 ? (dragArea.pressed ? dragColor : rangeColor) : singleLineColor
}
Rectangle {
id: leftRange
onXChanged: {
if (dragArea.drag.active)
rightRange.x = x + dragArea.origWidth;
}
x: 0
height: parent.height
width: 1
color: borderColor
Rectangle {
id: leftBorderHandle
height: parent.height
anchors.right: parent.left
width: 7
color: handleColor
visible: false
Image {
source: "range_handle.png"
x: 2
width: 4
height: 9
fillMode: Image.Tile
y: parent.height / 2 - 4
}
}
states: State {
name: "highlighted"
PropertyChanges {
target: leftBorderHandle
visible: true
}
}
MouseArea {
anchors.fill: leftBorderHandle
drag.target: leftRange
drag.axis: "XAxis"
drag.minimumX: 0
drag.maximumX: rangeMover.width
drag.onActiveChanged: drag.maximumX = rightRange.x
hoverEnabled: true
onEntered: {
parent.state = "highlighted";
}
onExited: {
if (!pressed) parent.state = "";
}
onReleased: {
if (!containsMouse) parent.state = "";
}
}
}
Rectangle {
id: rightRange
x: 1
height: parent.height
width: 1
color: borderColor
Rectangle {
id: rightBorderHandle
height: parent.height
anchors.left: parent.right
width: 7
color: handleColor
visible: false
Image {
source: "range_handle.png"
x: 2
width: 4
height: 9
fillMode: Image.Tile
y: parent.height / 2 - 4
}
}
states: State {
name: "highlighted"
PropertyChanges {
target: rightBorderHandle
visible: true
}
}
MouseArea {
anchors.fill: rightBorderHandle
drag.target: rightRange
drag.axis: "XAxis"
drag.minimumX: 0
drag.maximumX: rangeMover.width
drag.onActiveChanged: drag.minimumX = leftRange.x
hoverEnabled: true
onEntered: {
parent.state = "highlighted";
}
onExited: {
if (!pressed) parent.state = "";
}
onReleased: {
if (!containsMouse) parent.state = "";
}
}
}
MouseArea {
id: dragArea
property double origWidth: 0
anchors.fill: selectedRange
drag.target: leftRange
drag.axis: "XAxis"
drag.minimumX: 0
drag.maximumX: rangeMover.width - origWidth
drag.onActiveChanged: origWidth = selectedRange.width
onDoubleClicked: parent.rangeDoubleClicked()
}
}

View File

@@ -1,81 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
import QtQuick 2.1
RangeMover {
id: selectionRange
property QtObject zoomer;
readonly property int creationInactive: 0
readonly property int creationFirstLimit: 1
readonly property int creationSecondLimit: 2
readonly property int creationFinished: 3
property bool ready: visible && creationState === creationFinished
property double startTime: rangeLeft * viewTimePerPixel + zoomer.windowStart
property double duration: Math.max(rangeWidth * viewTimePerPixel, 500)
property double endTime: startTime + duration
property double viewTimePerPixel: 1
property double creationReference : 0
property int creationState : creationInactive
function reset() {
rangeRight = rangeLeft + 1;
creationState = creationInactive;
creationReference = 0;
}
function setPos(pos) {
if (pos < 0)
pos = 0;
else if (pos > width)
pos = width;
switch (creationState) {
case creationFirstLimit:
creationReference = pos;
rangeLeft = pos;
rangeRight = pos + 1;
break;
case creationSecondLimit:
if (pos > creationReference) {
rangeLeft = creationReference;
rangeRight = pos;
} else if (pos < creationReference) {
rangeLeft = pos;
rangeRight = creationReference;
}
break;
}
}
}

View File

@@ -1,186 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
import QtQuick 2.1
Item {
id: selectionRangeDetails
signal recenter
signal close
property string startTime
property string endTime
property string duration
property bool showDuration
width: Math.max(150, col.width + 25)
height: col.height + 30
// keep inside view
Connections {
target: selectionRangeDetails.parent
onWidthChanged: fitInView();
onHeightChanged: fitInView();
}
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";
}
function fitInView() {
// don't reposition if it does not fit
if (parent.width < width || parent.height < height)
return;
if (x + width > parent.width)
x = parent.width - width;
if (x < 0)
x = 0;
if (y + height > parent.height)
y = parent.height - height;
if (y < 0)
y = 0;
}
// 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")
font.bold: true
height: 18
y: 2
verticalAlignment: Text.AlignVCenter
width: parent.width
color: "white"
renderType: Text.NativeRendering
}
// Details area
Rectangle {
color: "white"
width: parent.width
height: col.height + 10
y: 20
border.width: 1
border.color: "#a0a0a0"
Grid {
id: col
x: 10
y: 5
spacing: 5
columns: 2
Repeater {
model: [
qsTr("Start") + ":",
detailedPrintTime(startTime),
showDuration ? (qsTr("End") + ":") : "",
showDuration ? detailedPrintTime(endTime) : "",
showDuration ? (qsTr("Duration") + ":") : "",
showDuration ? detailedPrintTime(duration) : ""
]
Detail {
isLabel: index % 2 === 0
text: modelData
}
}
}
}
MouseArea {
anchors.fill: parent
drag.target: parent
drag.minimumX: 0
drag.maximumX: selectionRangeDetails.parent.width - width
drag.minimumY: 0
drag.maximumY: selectionRangeDetails.parent.height - height
onClicked: selectionRangeDetails.recenter()
}
Text {
id: closeIcon
x: selectionRangeDetails.width - 14
y: 4
text:"X"
color: "white"
renderType: Text.NativeRendering
MouseArea {
anchors.fill: parent
anchors.leftMargin: -8
onClicked: selectionRangeDetails.close()
}
}
}

View File

@@ -1,187 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
import QtQuick 2.1
Item {
id: timeDisplay
property double windowStart
property double rangeDuration
property int topBorderHeight: 2
property int bottomBorderHeight: 1
property int textMargin: 5
property int labelsHeight: 24
property int fontSize: 8
property color color1: "#E6E6E6"
property color color2: "white"
property int initialBlockLength: 120
property double spacing: width / rangeDuration
property double timePerBlock: Math.pow(2, Math.floor(Math.log(initialBlockLength / spacing) /
Math.LN2))
property double alignedWindowStart: Math.round(windowStart - (windowStart % timePerBlock))
property double pixelsPerBlock: timeDisplay.timePerBlock * timeDisplay.spacing
property double pixelsPerSection: pixelsPerBlock / 5
property int contentX
property int offsetX: contentX + Math.round((windowStart % timePerBlock) * spacing)
readonly property var timeUnits: ["μs", "ms", "s"]
function prettyPrintTime(t, rangeDuration) {
var round = 1;
var barrier = 1;
for (var i = 0; i < timeUnits.length; ++i) {
barrier *= 1000;
if (rangeDuration < barrier)
round *= 1000;
else if (rangeDuration < barrier * 10)
round *= 100;
else if (rangeDuration < barrier * 100)
round *= 10;
if (t < barrier * 1000)
return Math.floor(t / (barrier / round)) / round + timeUnits[i];
}
t /= barrier;
var m = Math.floor(t / 60);
var s = Math.floor((t - m * 60) * round) / round;
return m + "m" + s + "s";
}
Item {
x: Math.floor(firstBlock * timeDisplay.pixelsPerBlock - timeDisplay.offsetX)
y: 0
id: row
property int firstBlock: timeDisplay.offsetX / timeDisplay.pixelsPerBlock
property int offset: firstBlock % repeater.model
Repeater {
id: repeater
model: Math.floor(timeDisplay.width / timeDisplay.initialBlockLength * 2 + 2)
Item {
id: column
// Changing the text in text nodes is expensive. We minimize the number of changes
// by rotating the nodes during scrolling.
property int stableIndex: row.offset > index ? repeater.model - row.offset + index :
index - row.offset
height: timeDisplay.height
y: 0
x: width * stableIndex
width: timeDisplay.pixelsPerBlock
// Manually control this. We don't want it to happen when firstBlock
// changes before stableIndex changes.
onStableIndexChanged: block = row.firstBlock + stableIndex
property int block: -1
property double blockStartTime: block * timeDisplay.timePerBlock +
timeDisplay.alignedWindowStart
Rectangle {
id: timeLabel
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: timeDisplay.labelsHeight
color: (Math.round(column.block + timeDisplay.alignedWindowStart /
timeDisplay.timePerBlock) % 2) ? color1 : color2;
Text {
id: labelText
renderType: Text.NativeRendering
font.pixelSize: timeDisplay.fontSize
font.family: "sans-serif"
anchors.fill: parent
anchors.leftMargin: timeDisplay.textMargin
anchors.bottomMargin: timeDisplay.textMargin
verticalAlignment: Text.AlignBottom
text: prettyPrintTime(column.blockStartTime, timeDisplay.rangeDuration)
}
}
Row {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: timeLabel.bottom
anchors.bottom: parent.bottom
Repeater {
model: 4
Item {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: timeDisplay.pixelsPerSection
Rectangle {
color: "#CCCCCC"
width: 1
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
}
}
}
}
Rectangle {
color: "#B0B0B0"
width: 1
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
}
}
}
}
Rectangle {
height: topBorderHeight
anchors.left: parent.left
anchors.right: parent.right
y: labelsHeight - topBorderHeight
color: "#B0B0B0"
}
Rectangle {
height: bottomBorderHeight
anchors.left: parent.left
anchors.right: parent.right
anchors.top: row.bottom
color: "#B0B0B0"
}
}

View File

@@ -1,147 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
import QtQuick 2.1
Item {
id: timeMarks
visible: model && (mockup || (!model.hidden && !model.empty))
property QtObject model
property bool startOdd
property bool mockup
readonly property int scaleMinHeight: 60
readonly property int scaleStepping: 30
readonly property string units: " kMGT"
property int rowCount: model ? model.rowCount : 0
function prettyPrintScale(amount) {
var unitOffset = 0;
for (unitOffset = 0; amount > (1 << ((unitOffset + 1) * 10)); ++unitOffset) {}
var result = (amount >> (unitOffset * 10));
if (result < 100) {
var comma = Math.round(((amount >> ((unitOffset - 1) * 10)) & 1023) *
(result < 10 ? 100 : 10) / 1024);
if (comma < 10 && result < 10)
return result + ".0" + comma + units[unitOffset];
else
return result + "." + comma + units[unitOffset];
} else {
return result + units[unitOffset];
}
}
Connections {
target: model
onExpandedRowHeightChanged: {
if (model && model.expanded && row >= 0)
rowRepeater.itemAt(row).height = height;
}
}
Column {
id: rows
anchors.left: parent.left
anchors.right: parent.right
Repeater {
id: rowRepeater
model: timeMarks.rowCount
Rectangle {
id: row
color: ((index + (startOdd ? 1 : 0)) % 2) ? "#f0f0f0" : "white"
anchors.left: rows.left
anchors.right: rows.right
height: timeMarks.model ? timeMarks.model.rowHeight(index) : 0
property int minVal: timeMarks.model ? timeMarks.model.rowMinValue(index) : 0
property int maxVal: timeMarks.model ? timeMarks.model.rowMaxValue(index) : 0
property int valDiff: maxVal - minVal
property bool scaleVisible: timeMarks.model && timeMarks.model.expanded &&
height > scaleMinHeight && valDiff > 0
property int stepVal: {
var ret = 1;
var ugly = Math.ceil(valDiff / Math.floor(height / scaleStepping));
while (isFinite(ugly) && ugly > 1) {
ugly >>= 1;
ret <<= 1;
}
return ret;
}
Text {
id: scaleTopLabel
renderType: Text.NativeRendering
visible: parent.scaleVisible
color: "#B0B0B0"
font.pixelSize: 8
anchors.top: parent.top
anchors.leftMargin: 2
anchors.topMargin: 2
anchors.left: parent.left
text: prettyPrintScale(row.maxVal)
}
Repeater {
model: parent.scaleVisible ? row.valDiff / row.stepVal : 0
Item {
anchors.left: row.left
anchors.right: row.right
height: row.stepVal * row.height / row.valDiff
y: row.height - (index + 1) * height
visible: y > scaleTopLabel.height
Text {
renderType: Text.NativeRendering
color: "#B0B0B0"
font.pixelSize: 8
anchors.bottom: parent.bottom
anchors.bottomMargin: 2
anchors.leftMargin: 2
anchors.left: parent.left
text: prettyPrintScale(index * row.stepVal)
}
Rectangle {
height: 1
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
color: "#B0B0B0"
}
}
}
}
}
}
}

View File

@@ -1,215 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
import QtQuick 2.0
import QtQuick.Controls 1.2
import TimelineRenderer 1.0
import QtQml.Models 2.1
ScrollView {
id: scroller
property QtObject zoomer
property QtObject modelProxy
property int contentX: flick.contentX
property int contentY: flick.contentY
property int contentWidth: flick.contentWidth
property int contentHeight: flick.contentHeight
property bool selectionLocked
property int typeId
signal propagateSelection(int newModel, int newItem)
signal gotoSourceLocation(string file, int line, int column)
function clearChildren()
{
timelineView.clearChildren();
}
function select(modelIndex, eventIndex)
{
timelineView.select(modelIndex, eventIndex);
}
function moveCategories(sourceIndex, targetIndex)
{
timelineModel.items.move(sourceIndex, targetIndex)
}
function scroll()
{
flick.scroll();
}
// ScrollView will try to deinteractivate it. We don't want that
// as the horizontal flickable is interactive, too. We do occasionally
// switch to non-interactive ourselves, though.
property bool stayInteractive: true
onStayInteractiveChanged: flick.interactive = stayInteractive
Flickable {
id: flick
contentHeight: timelineView.height + height
flickableDirection: Flickable.HorizontalAndVerticalFlick
boundsBehavior: Flickable.StopAtBounds
pixelAligned: true
onInteractiveChanged: interactive = stayInteractive
property bool recursionGuard: false
// Update the zoom control on srolling.
onContentXChanged: {
if (recursionGuard)
return;
recursionGuard = true;
var newStartTime = contentX * zoomer.rangeDuration / scroller.width +
zoomer.windowStart;
if (isFinite(newStartTime) && Math.abs(newStartTime - zoomer.rangeStart) >= 1) {
var newEndTime = (contentX + scroller.width) * zoomer.rangeDuration /
scroller.width + zoomer.windowStart;
if (isFinite(newEndTime))
zoomer.setRange(newStartTime, newEndTime);
}
recursionGuard = false;
}
// Scroll when the zoom control is updated
function scroll() {
if (recursionGuard || zoomer.rangeDuration <= 0)
return;
recursionGuard = true;
var newWidth = zoomer.windowDuration * scroller.width / zoomer.rangeDuration;
if (isFinite(newWidth) && Math.abs(newWidth - contentWidth) >= 1)
contentWidth = newWidth;
var newStartX = (zoomer.rangeStart - zoomer.windowStart) * scroller.width /
zoomer.rangeDuration;
if (isFinite(newStartX) && Math.abs(newStartX - contentX) >= 1)
contentX = newStartX;
recursionGuard = false;
}
Column {
id: timelineView
signal clearChildren
signal select(int modelIndex, int eventIndex)
DelegateModel {
id: timelineModel
model: modelProxy.models
delegate: TimelineRenderer {
id: renderer
model: modelData
notes: modelProxy.notes
zoomer: scroller.zoomer
selectionLocked: scroller.selectionLocked
x: 0
height: modelData.height
property int visualIndex: DelegateModel.itemsIndex
// paint "under" the vertical scrollbar, so that it always matches with the
// timemarks
width: flick.contentWidth
Connections {
target: timelineView
onClearChildren: renderer.clearData()
onSelect: {
if (modelIndex === index || modelIndex === -1) {
renderer.selectedItem = eventIndex;
if (eventIndex !== -1)
renderer.recenter();
}
}
}
Connections {
target: scroller
onSelectionLockedChanged: {
renderer.selectionLocked = scroller.selectionLocked;
}
}
onSelectionLockedChanged: {
scroller.selectionLocked = renderer.selectionLocked;
}
function recenter() {
if (modelData.endTime(selectedItem) < zoomer.rangeStart ||
modelData.startTime(selectedItem) > zoomer.rangeEnd) {
var newStart = (modelData.startTime(selectedItem) +
modelData.endTime(selectedItem) -
zoomer.rangeDuration) / 2;
zoomer.setRange(Math.max(newStart, zoomer.traceStart),
Math.min(newStart + zoomer.rangeDuration,
zoomer.traceEnd));
}
var row = modelData.row(selectedItem);
var rowStart = modelData.rowOffset(row) + y;
var rowEnd = rowStart + modelData.rowHeight(row);
if (rowStart < flick.contentY || rowEnd - scroller.height > flick.contentY)
flick.contentY = (rowStart + rowEnd - scroller.height) / 2;
}
onSelectedItemChanged: {
scroller.propagateSelection(index, selectedItem);
}
onItemPressed: {
if (pressedItem === -1) {
// User clicked on empty space. Remove selection.
scroller.propagateSelection(-1, -1);
} else {
var location = model.location(pressedItem);
if (location.hasOwnProperty("file")) // not empty
scroller.gotoSourceLocation(location.file, location.line,
location.column);
scroller.typeId = model.typeId(pressedItem);
}
}
}
}
Repeater {
id: repeater
model: timelineModel
}
}
}
}

View File

@@ -1,165 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
import QtQuick 2.0
import QtQml.Models 2.1
Flickable {
id: categories
flickableDirection: Flickable.VerticalFlick
interactive: false
property color color
property int selectedModel
property int selectedItem
property bool reverseSelect
property QtObject modelProxy
property QtObject zoomer
signal selectItem(int modelIndex, int eventIndex)
signal moveCategories(int sourceIndex, int targetIndex)
// reserve some more space than needed to prevent weird effects when resizing
contentHeight: categoryContent.height + height
// Dispatch the cursor shape to all labels. When dragging the DropArea receiving
// the drag events is not necessarily related to the MouseArea receiving the mouse
// events, so we can't use the drag events to determine the cursor shape.
property bool dragging: false
Column {
id: categoryContent
anchors.left: parent.left
anchors.right: parent.right
DelegateModel {
id: labelsModel
// As we cannot retrieve items by visible index we keep an array of row counts here,
// for the time marks to draw the row backgrounds in the right colors.
property var rowCounts: new Array(modelProxy.models.length)
function updateRowCount(visualIndex, rowCount) {
if (rowCounts[visualIndex] !== rowCount) {
rowCounts[visualIndex] = rowCount;
// Array don't "change" if entries change. We have to signal manually.
rowCountsChanged();
}
}
model: modelProxy.models
delegate: Rectangle {
color: categories.color
anchors.left: parent.left
anchors.right: parent.right
property int visualIndex: DelegateModel.itemsIndex
height: label.visible ? label.height : 0
CategoryLabel {
id: label
model: modelData
mockup: modelProxy.height === 0
notesModel: modelProxy.notes
visualIndex: parent.visualIndex
dragging: categories.dragging
reverseSelect: categories.reverseSelect
onDragStarted: categories.dragging = true
onDragStopped: categories.dragging = false
draggerParent: categories
width: 150
dragOffset: parent.y
onDropped: {
categories.moveCategories(sourceIndex, targetIndex);
labelsModel.items.move(sourceIndex, targetIndex);
}
onSelectById: {
categories.selectItem(index, eventId)
}
onSelectNextBySelectionId: {
categories.selectItem(index, modelData.nextItemBySelectionId(selectionId,
zoomer.rangeStart,
categories.selectedModel === index ? categories.selectedItem : -1));
}
onSelectPrevBySelectionId: {
categories.selectItem(index, modelData.prevItemBySelectionId(selectionId,
zoomer.rangeStart,
categories.selectedModel === index ? categories.selectedItem : -1));
}
}
TimeMarks {
id: timeMarks
model: modelData
mockup: modelProxy.height === 0
anchors.right: parent.right
anchors.left: label.right
anchors.top: parent.top
anchors.bottom: parent.bottom
property int visualIndex: parent.visualIndex
// Quite a mouthful, but works fine: Add up all the row counts up to the one
// for this visual index and check if the result is even or odd.
startOdd: (labelsModel.rowCounts.slice(0, visualIndex).reduce(
function(prev, rows) {return prev + rows}, 0) % 2) === 0
onRowCountChanged: labelsModel.updateRowCount(visualIndex, rowCount)
onVisualIndexChanged: labelsModel.updateRowCount(visualIndex, rowCount)
}
Rectangle {
visible: label.visible
opacity: parent.y == 0 ? 0 : 1
color: "#B0B0B0"
height: 1
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
}
}
}
Repeater {
model: labelsModel
}
}
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: categoryContent.bottom
height: 1
color: "#B0B0B0"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 664 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 715 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 745 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 265 B

View File

@@ -1,37 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
vec4 orange = vec4(1.0, 165.0 / 255.0, 0.0, 1.0);
varying float d;
void main()
{
gl_FragColor = orange * float(d < (2.0 / 3.0) || d > (5.0 / 6.0));
}

View File

@@ -1,43 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
attribute vec4 vertexCoord;
attribute float distanceFromTop;
uniform mat4 matrix;
varying float d;
void main()
{
gl_Position = matrix * vertexCoord;
gl_Position.z -= 0.1;
gl_Position.w = 1.0;
d = distanceFromTop;
}

View File

@@ -1,41 +1,9 @@
<RCC>
<qresource prefix="/qmlprofiler">
<file>Detail.qml</file>
<file>CategoryLabel.qml</file>
<file>MainView.qml</file>
<file>RangeDetails.qml</file>
<file>RangeMover.qml</file>
<file>TimeDisplay.qml</file>
<file>clean_pane_small.png</file>
<file>recordOff.png</file>
<file>recordOn.png</file>
<file>lock_closed.png</file>
<file>lock_open.png</file>
<file>ico_edit.png</file>
<file>TimeMarks.qml</file>
<file>Overview.qml</file>
<file>SelectionRange.qml</file>
<file>SelectionRangeDetails.qml</file>
<file>arrow_down.png</file>
<file>arrow_right.png</file>
<file>dialog_shadow.png</file>
<file>range_handle.png</file>
<file>ico_selectionmode.png</file>
<file>ico_zoom.png</file>
<file>ico_prev.png</file>
<file>ico_next.png</file>
<file>ico_rangeselection.png</file>
<file>ico_rangeselected.png</file>
<file>ico_note.png</file>
<file>ButtonsBar.qml</file>
<file>ico_filter.png</file>
<file>timelineitems.vert</file>
<file>timelineitems.frag</file>
<file>bindingloops.vert</file>
<file>bindingloops.frag</file>
<file>notes.vert</file>
<file>notes.frag</file>
<file>TimelineLabels.qml</file>
<file>TimelineContent.qml</file>
</qresource>
</RCC>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

View File

@@ -1,46 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
varying lowp vec3 edgeColor;
varying lowp vec3 color;
varying lowp vec2 barycentric;
vec4 zero = vec4(0.0);
void main()
{
vec2 d = fwidth(barycentric) * 5.0;
vec4 edge_closeness = smoothstep(zero, vec4(d.x, d.y, d.x, d.y),
vec4(barycentric.x, barycentric.y, 1.0 - barycentric.x, 1.0 - barycentric.y));
float total = min(min(edge_closeness[0], edge_closeness[1]),
min(edge_closeness[2], edge_closeness[3]));
// square to make lines sharper
total = total > 0.5 ? (1.0 - (1.0 - total) * (1.0 - total) * 2.0) : total * total * 2.0;
gl_FragColor.rgb = mix(edgeColor, color, total);
}

View File

@@ -1,64 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
attribute vec4 vertexCoord;
attribute vec2 rectSize;
attribute float selectionId;
attribute vec4 vertexColor;
uniform vec2 scale;
uniform mat4 matrix;
uniform vec4 selectionColor;
uniform float selectedItem;
varying vec3 color;
varying vec3 edgeColor;
varying vec2 barycentric;
void main()
{
gl_Position = matrix * vertexCoord;
// Make very narrow events somewhat wider so that they don't collapse into 0 pixels
highp float scaledWidth = scale.x * rectSize.x;
highp float shift = sign(scaledWidth) * max(0, 3.0 - abs(scaledWidth)) * 0.0005;
gl_Position.x += shift;
// Ditto for events with very small height
highp float scaledHeight = scale.y * rectSize.y;
gl_Position.y += float(rectSize.y > 0.0) * max(0, 3.0 - scaledHeight) * 0.003;
barycentric = vec2(rectSize.x > 0.0 ? 1.0 : 0.0, rectSize.y > 0.0 ? 1.0 : 0.0);
color = vertexColor.rgb;
float selected = min(1.0, abs(selectionId - selectedItem));
edgeColor = mix(selectionColor.rgb, vertexColor.rgb, selected);
gl_Position.z += mix(0.0, (shift + 0.0015) / 10.0, selected);
gl_Position.w = 1.0;
}

View File

@@ -9,6 +9,7 @@ SOURCES += \
qmlprofileranimationsmodel.cpp \
qmlprofilerattachdialog.cpp \
qmlprofilerbasemodel.cpp \
qmlprofilerbindingloopsrenderpass.cpp \
qmlprofilerclientmanager.cpp \
qmlprofilerdatamodel.cpp \
qmlprofilerdetailsrewriter.cpp \
@@ -30,20 +31,7 @@ SOURCES += \
qmlprofilertreeview.cpp \
qmlprofilerviewmanager.cpp \
qv8profilerdatamodel.cpp \
qv8profilereventview.cpp \
timelinemodel.cpp \
timelinemodelaggregator.cpp \
timelinerenderer.cpp \
timelinezoomcontrol.cpp \
timelineitemsrenderpass.cpp \
qmlprofilerbindingloopsrenderpass.cpp \
timelineselectionrenderpass.cpp \
timelinenotesrenderpass.cpp \
timelinerenderpass.cpp \
timelinerenderstate.cpp \
timelinenotesmodel.cpp \
timelineabstractrenderer.cpp \
timelineoverviewrenderer.cpp
qv8profilereventview.cpp
HEADERS += \
abstractqmlprofilerrunner.h \
@@ -53,6 +41,7 @@ HEADERS += \
qmlprofilerattachdialog.h \
qmlprofilerbasemodel.h \
qmlprofilerbasemodel_p.h \
qmlprofilerbindingloopsrenderpass.h \
qmlprofilerclientmanager.h \
qmlprofilerconstants.h \
qmlprofilerdatamodel.h \
@@ -75,47 +64,11 @@ HEADERS += \
qmlprofilertreeview.h \
qmlprofilerviewmanager.h \
qv8profilerdatamodel.h \
qv8profilereventview.h \
timelinemodel.h \
timelinemodel_p.h \
timelinemodelaggregator.h \
timelinerenderer.h \
timelinezoomcontrol.h \
timelineitemsrenderpass.h \
qmlprofilerbindingloopsrenderpass.h \
timelineselectionrenderpass.h \
timelinenotesrenderpass.h \
timelinerenderpass.h \
timelinerenderstate.h \
timelinenotesmodel.h \
timelinenotesmodel_p.h \
timelinerenderer_p.h \
timelinerenderstate_p.h \
timelineabstractrenderer.h \
timelineabstractrenderer_p.h \
timelineoverviewrenderer_p.h \
timelineoverviewrenderer.h
qv8profilereventview.h
RESOURCES += \
qml/qmlprofiler.qrc
DISTFILES += \
qml/ButtonsBar.qml \
qml/Detail.qml \
qml/CategoryLabel.qml \
qml/MainView.qml \
qml/RangeDetails.qml \
qml/RangeMover.qml \
qml/TimeDisplay.qml \
qml/TimelineContent.qml \
qml/TimelineLabels.qml \
qml/TimeMarks.qml \
qml/SelectionRange.qml \
qml/SelectionRangeDetails.qml \
qml/Overview.qml \
qml/timelineitems.frag \
qml/timelineitems.vert \
qml/bindingloops.frag \
qml/bindingloops.vert \
qml/notes.frag \
qml/notes.vert
qml/bindingloops.vert

View File

@@ -3,13 +3,13 @@ import qbs 1.0
QtcPlugin {
name: "QmlProfiler"
Depends { name: "Qt"; submodules: ["widgets", "network"] }
Depends { name: "Qt.quick"; condition: product.condition; }
Depends { name: "Qt"; submodules: ["widgets", "network", "quick"] }
Depends { name: "Aggregation" }
Depends { name: "QmlJS" }
Depends { name: "QmlDebug" }
Depends { name: "QtcSsh" }
Depends { name: "Utils" }
Depends { name: "Timeline" }
Depends { name: "Core" }
Depends { name: "AnalyzerBase" }
@@ -50,49 +50,12 @@ QtcPlugin {
"qmlprofilerviewmanager.cpp", "qmlprofilerviewmanager.h",
"qv8profilerdatamodel.cpp", "qv8profilerdatamodel.h",
"qv8profilereventview.h", "qv8profilereventview.cpp",
"timelineabstractrenderer.cpp", "timelineabstractrenderer.h",
"timelineabstractrenderer_p.h",
"timelineitemsrenderpass.cpp", "timelineitemsrenderpass.h",
"timelinemodel.cpp", "timelinemodel.h", "timelinemodel_p.h",
"timelinemodelaggregator.cpp", "timelinemodelaggregator.h",
"timelinenotesmodel.cpp", "timelinenotesmodel.h", "timelinenotesmodel_p.h",
"timelinenotesrenderpass.cpp", "timelinenotesrenderpass.h",
"timelineoverviewrenderer.cpp", "timelineoverviewrenderer.h",
"timelineoverviewrenderer_p.h",
"timelinerenderer.cpp", "timelinerenderer.h", "timelinerenderer_p.h",
"timelinerenderpass.cpp", "timelinerenderpass.h",
"timelinerenderstate.cpp", "timelinerenderstate.h", "timelinerenderstate_p.h",
"timelineselectionrenderpass.cpp", "timelineselectionrenderpass.h",
"timelinezoomcontrol.cpp", "timelinezoomcontrol.h"
]
}
Group {
name: "QML"
prefix: "qml/"
files: [
"ButtonsBar.qml",
"Detail.qml",
"CategoryLabel.qml",
"MainView.qml",
"Overview.qml",
"RangeDetails.qml",
"RangeMover.qml",
"SelectionRange.qml",
"SelectionRangeDetails.qml",
"TimeDisplay.qml",
"TimelineContent.qml",
"TimelineLabels.qml",
"TimeMarks.qml",
"qmlprofiler.qrc",
"bindingloops.frag",
"bindingloops.vert",
"notes.frag",
"notes.vert",
"timelineitems.frag",
"timelineitems.vert"
]
files: ["qmlprofiler.qrc"]
}
}

View File

@@ -5,6 +5,7 @@ QTC_LIB_DEPENDS += \
qmldebug \
qmljs \
ssh \
timeline \
utils
QTC_PLUGIN_DEPENDS += \
analyzerbase \

View File

@@ -308,8 +308,7 @@ BindingLoopMaterialShader::BindingLoopMaterialShader()
: QSGMaterialShader()
{
setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qmlprofiler/bindingloops.vert"));
setShaderSourceFile(QOpenGLShader::Fragment,
QStringLiteral(":/qmlprofiler/bindingloops.frag"));
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qmlprofiler/bindingloops.frag"));
}
void BindingLoopMaterialShader::updateState(const RenderState &state, QSGMaterial *, QSGMaterial *)

View File

@@ -31,9 +31,9 @@
#ifndef QMLPROFILERBINDINGLOOPSRENDERPASS_H
#define QMLPROFILERBINDINGLOOPSRENDERPASS_H
#include "timelineabstractrenderer.h"
#include "timelinerenderpass.h"
#include "timelinerenderstate.h"
#include "timeline/timelineabstractrenderer.h"
#include "timeline/timelinerenderpass.h"
#include "timeline/timelinerenderstate.h"
#include "qmlprofilerrangemodel.h"
#include <QSGMaterial>

View File

@@ -29,6 +29,7 @@
****************************************************************************/
#include "qmlprofilernotesmodel.h"
#include "qmlprofilerdatamodel.h"
namespace QmlProfiler {

View File

@@ -32,7 +32,7 @@
#define QMLPROFILERNOTESMODEL_H
#include "qmlprofilermodelmanager.h"
#include "timelinenotesmodel.h"
#include "timeline/timelinenotesmodel.h"
#include <QList>
#include <QHash>

View File

@@ -32,9 +32,9 @@
#include "qmlprofilermodelmanager.h"
#include "qmlprofilerdatamodel.h"
#include "qmlprofilerbindingloopsrenderpass.h"
#include "timelinenotesrenderpass.h"
#include "timelineitemsrenderpass.h"
#include "timelineselectionrenderpass.h"
#include "timeline/timelinenotesrenderpass.h"
#include "timeline/timelineitemsrenderpass.h"
#include "timeline/timelineselectionrenderpass.h"
#include <QCoreApplication>
#include <QVector>

View File

@@ -71,7 +71,7 @@ QmlProfilerStateWidget::QmlProfilerStateWidget(QmlProfilerStateManager *stateMan
QVBoxLayout *layout = new QVBoxLayout(this);
resize(200,70);
d->shadowPic.load(QLatin1String(":/qmlprofiler/dialog_shadow.png"));
d->shadowPic.load(QLatin1String(":/timeline/dialog_shadow.png"));
d->text = new QLabel(this);
d->text->setAlignment(Qt::AlignCenter);

View File

@@ -31,7 +31,10 @@
#ifndef QMLPROFILERTIMELINEMODEL_H
#define QMLPROFILERTIMELINEMODEL_H
#include "timelinemodel.h"
#include "qmlprofiler_global.h"
#include "qmlprofilermodelmanager.h"
#include "qmlprofilerdatamodel.h"
#include "timeline/timelinemodel.h"
namespace QmlProfiler {

View File

@@ -37,7 +37,6 @@
#include "qmlprofilerclientmanager.h"
#include "qmlprofilermodelmanager.h"
#include "qmlprofilerdetailsrewriter.h"
#include "timelinerenderer.h"
#include "qmlprofilernotesmodel.h"
#include <analyzerbase/analyzermanager.h>

View File

@@ -32,19 +32,21 @@
#include "qmlprofilertool.h"
#include "qmlprofilerstatemanager.h"
#include "qmlprofilermodelmanager.h"
#include "timelinemodelaggregator.h"
#include "qmlprofilernotesmodel.h"
#include "qmlprofileranimationsmodel.h"
#include "qmlprofilerrangemodel.h"
#include "qmlprofilerplugin.h"
#include "timelineoverviewrenderer.h"
// Needed for the load&save actions in the context menu
#include <analyzerbase/ianalyzertool.h>
// Communication with the other views (limit events to range)
#include "qmlprofilerviewmanager.h"
#include "timelinezoomcontrol.h"
#include "timeline/timelinezoomcontrol.h"
#include "timeline/timelinemodelaggregator.h"
#include "timeline/timelinerenderer.h"
#include "timeline/timelineoverviewrenderer.h"
// Needed for the load&save actions in the context menu
#include <analyzerbase/ianalyzertool.h>
#include <utils/styledbar.h>
@@ -148,7 +150,7 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerT
d->m_modelProxy);
d->m_mainView->rootContext()->setContextProperty(QLatin1String("zoomControl"),
d->m_zoomControl);
d->m_mainView->setSource(QUrl(QLatin1String("qrc:/qmlprofiler/MainView.qml")));
d->m_mainView->setSource(QUrl(QLatin1String("qrc:/timeline/MainView.qml")));
QQuickItem *rootObject = d->m_mainView->rootObject();
connect(rootObject, SIGNAL(updateCursorPosition()), this, SLOT(updateCursorPosition()));

View File

@@ -1,200 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "timelineabstractrenderer_p.h"
namespace Timeline {
TimelineAbstractRenderer::TimelineAbstractRendererPrivate::TimelineAbstractRendererPrivate() :
selectedItem(-1), selectionLocked(true), model(0), notes(0), zoomer(0), modelDirty(false),
rowHeightsDirty(false)
{
}
TimelineAbstractRenderer::TimelineAbstractRenderer(TimelineAbstractRendererPrivate &dd,
QQuickItem *parent) :
QQuickItem(parent), d_ptr(&dd)
{
}
int TimelineAbstractRenderer::selectedItem() const
{
Q_D(const TimelineAbstractRenderer);
return d->selectedItem;
}
void TimelineAbstractRenderer::setSelectedItem(int itemIndex)
{
Q_D(TimelineAbstractRenderer);
if (d->selectedItem != itemIndex) {
d->selectedItem = itemIndex;
update();
emit selectedItemChanged(itemIndex);
}
}
bool TimelineAbstractRenderer::selectionLocked() const
{
Q_D(const TimelineAbstractRenderer);
return d->selectionLocked;
}
void TimelineAbstractRenderer::setSelectionLocked(bool locked)
{
Q_D(TimelineAbstractRenderer);
if (d->selectionLocked != locked) {
d->selectionLocked = locked;
update();
emit selectionLockedChanged(locked);
}
}
TimelineModel *TimelineAbstractRenderer::model() const
{
Q_D(const TimelineAbstractRenderer);
return d->model;
}
void TimelineAbstractRenderer::setModel(TimelineModel *model)
{
Q_D(TimelineAbstractRenderer);
if (d->model == model)
return;
if (d->model) {
disconnect(d->model, &TimelineModel::expandedChanged, this, &QQuickItem::update);
disconnect(d->model, &TimelineModel::hiddenChanged, this, &QQuickItem::update);
disconnect(d->model, &TimelineModel::expandedRowHeightChanged,
this, &TimelineAbstractRenderer::setRowHeightsDirty);
disconnect(d->model, &TimelineModel::emptyChanged,
this, &TimelineAbstractRenderer::setModelDirty);
}
d->model = model;
if (d->model) {
connect(d->model, &TimelineModel::expandedChanged, this, &QQuickItem::update);
connect(d->model, &TimelineModel::hiddenChanged, this, &QQuickItem::update);
connect(d->model, &TimelineModel::expandedRowHeightChanged,
this, &TimelineAbstractRenderer::setRowHeightsDirty);
connect(d->model, &TimelineModel::emptyChanged,
this, &TimelineAbstractRenderer::setModelDirty);
d->renderPasses = d->model->supportedRenderPasses();
}
setModelDirty();
emit modelChanged(d->model);
}
TimelineNotesModel *TimelineAbstractRenderer::notes() const
{
Q_D(const TimelineAbstractRenderer);
return d->notes;
}
void TimelineAbstractRenderer::setNotes(TimelineNotesModel *notes)
{
Q_D(TimelineAbstractRenderer);
if (d->notes == notes)
return;
if (d->notes)
disconnect(d->notes, &TimelineNotesModel::changed,
this, &TimelineAbstractRenderer::setNotesDirty);
d->notes = notes;
if (d->notes)
connect(d->notes, &TimelineNotesModel::changed,
this, &TimelineAbstractRenderer::setNotesDirty);
emit notesChanged(d->notes);
update();
}
TimelineZoomControl *TimelineAbstractRenderer::zoomer() const
{
Q_D(const TimelineAbstractRenderer);
return d->zoomer;
}
void TimelineAbstractRenderer::setZoomer(TimelineZoomControl *zoomer)
{
Q_D(TimelineAbstractRenderer);
if (zoomer != d->zoomer) {
if (d->zoomer != 0)
disconnect(d->zoomer, SIGNAL(windowChanged(qint64,qint64)), this, SLOT(update()));
d->zoomer = zoomer;
if (d->zoomer != 0)
connect(d->zoomer, SIGNAL(windowChanged(qint64,qint64)), this, SLOT(update()));
emit zoomerChanged(zoomer);
update();
}
}
bool TimelineAbstractRenderer::modelDirty() const
{
Q_D(const TimelineAbstractRenderer);
return d->modelDirty;
}
bool TimelineAbstractRenderer::notesDirty() const
{
Q_D(const TimelineAbstractRenderer);
return d->notesDirty;
}
bool TimelineAbstractRenderer::rowHeightsDirty() const
{
Q_D(const TimelineAbstractRenderer);
return d->rowHeightsDirty;
}
void TimelineAbstractRenderer::setModelDirty()
{
Q_D(TimelineAbstractRenderer);
d->modelDirty = true;
update();
}
void TimelineAbstractRenderer::setRowHeightsDirty()
{
Q_D(TimelineAbstractRenderer);
d->rowHeightsDirty = true;
update();
}
void TimelineAbstractRenderer::setNotesDirty()
{
Q_D(TimelineAbstractRenderer);
d->notesDirty = true;
update();
}
} // namespace Timeline

View File

@@ -1,99 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINEABSTRACTRENDERER_H
#define TIMELINEABSTRACTRENDERER_H
#include <QQuickItem>
#include <QSGTransformNode>
#include <QQuickItem>
#include "timelinezoomcontrol.h"
#include "timelinemodel.h"
#include "timelinenotesmodel.h"
#include "timelinerenderpass.h"
namespace Timeline {
class TimelineRenderPass;
class TimelineRenderState;
class TimelineAbstractRenderer : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(Timeline::TimelineModel *model READ model WRITE setModel NOTIFY modelChanged)
Q_PROPERTY(Timeline::TimelineNotesModel *notes READ notes WRITE setNotes NOTIFY notesChanged)
Q_PROPERTY(Timeline::TimelineZoomControl *zoomer READ zoomer WRITE setZoomer NOTIFY zoomerChanged)
Q_PROPERTY(bool selectionLocked READ selectionLocked WRITE setSelectionLocked NOTIFY selectionLockedChanged)
Q_PROPERTY(int selectedItem READ selectedItem WRITE setSelectedItem NOTIFY selectedItemChanged)
public:
bool selectionLocked() const;
int selectedItem() const;
TimelineModel *model() const;
void setModel(TimelineModel *model);
TimelineNotesModel *notes() const;
void setNotes(TimelineNotesModel *notes);
TimelineZoomControl *zoomer() const;
void setZoomer(TimelineZoomControl *zoomer);
bool modelDirty() const;
bool notesDirty() const;
bool rowHeightsDirty() const;
signals:
void modelChanged(const TimelineModel *model);
void notesChanged(TimelineNotesModel *notes);
void zoomerChanged(TimelineZoomControl *zoomer);
void selectionLockedChanged(bool locked);
void selectedItemChanged(int itemIndex);
public slots:
void setSelectedItem(int itemIndex);
void setSelectionLocked(bool locked);
void setModelDirty();
void setNotesDirty();
void setRowHeightsDirty();
protected:
class TimelineAbstractRendererPrivate;
TimelineAbstractRenderer(TimelineAbstractRendererPrivate &dd, QQuickItem *parent = 0);
TimelineAbstractRendererPrivate *d_ptr;
Q_DECLARE_PRIVATE(TimelineAbstractRenderer)
};
} // namespace Timeline
#endif // TIMELINEABSTRACTRENDERER_H

View File

@@ -1,60 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINEABSTRACTRENDERER_P_H
#define TIMELINEABSTRACTRENDERER_P_H
#include "timelineabstractrenderer.h"
namespace Timeline {
class TimelineAbstractRenderer::TimelineAbstractRendererPrivate {
public:
TimelineAbstractRendererPrivate();
int selectedItem;
bool selectionLocked;
TimelineModel *model;
TimelineNotesModel *notes;
TimelineZoomControl *zoomer;
bool modelDirty;
bool rowHeightsDirty;
bool notesDirty;
QList<const TimelineRenderPass *> renderPasses;
};
}
#endif // TIMELINEABSTRACTRENDERER_P_H

View File

@@ -1,461 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "timelineitemsrenderpass.h"
#include "timelinerenderstate.h"
#include <QSGSimpleRectNode>
#include <QSGVertexColorMaterial>
#include <QtAlgorithms>
namespace Timeline {
class TimelineItemsMaterial : public QSGMaterial {
public:
TimelineItemsMaterial();
QVector2D scale() const;
void setScale(QVector2D scale);
float selectedItem() const;
void setSelectedItem(float selectedItem);
QColor selectionColor() const;
void setSelectionColor(QColor selectionColor);
QSGMaterialType *type() const;
QSGMaterialShader *createShader() const;
private:
QVector2D m_scale;
float m_selectedItem;
QColor m_selectionColor;
};
struct TimelineItemsRenderPassState : public TimelineRenderPass::State {
TimelineItemsRenderPassState() : indexFrom(std::numeric_limits<int>::max()), indexTo(-1) {}
int indexFrom;
int indexTo;
TimelineItemsMaterial collapsedRowMaterial;
QVector<QSGNode *> m_expandedRows;
QVector<QSGNode *> m_collapsedRows;
const QVector<QSGNode *> &expandedRows() const { return m_expandedRows; }
const QVector<QSGNode *> &collapsedRows() const { return m_collapsedRows; }
};
struct OpaqueColoredPoint2DWithSize {
float x, y, w, h, id;
unsigned char r, g, b, a;
void set(float nx, float ny, float nw, float nh, float nid, uchar nr, uchar ng, uchar nb);
};
struct TimelineItemsGeometry {
// Alternating nodes with with 7 and 4 vertices; and vertex indices are 16bit
static const int maxEventsPerNode = 0xffff * 2 / (7 + 4);
static const QSGGeometry::AttributeSet &opaqueColoredPoint2DWithSize();
TimelineItemsGeometry() : allocatedVertices(0), usedVertices(0), currentY(0), node(0) {}
uint allocatedVertices;
uint usedVertices;
float currentY;
QSGGeometryNode *node;
OpaqueColoredPoint2DWithSize *vertexData();
void allocate(QSGMaterial *material);
void addVertices(float itemTop);
void addEvent(float itemLeft, float itemTop, float itemWidth, float selectionId, uchar red,
uchar green, uchar blue);
};
void TimelineItemsGeometry::addEvent(float itemLeft, float itemTop, float itemWidth,
float selectionId, uchar red, uchar green,
uchar blue)
{
float rowHeight = TimelineModel::defaultRowHeight();
float itemHeight = rowHeight - itemTop;
OpaqueColoredPoint2DWithSize *v = vertexData();
if (currentY == rowHeight) {
// "Z" form, bottom to top
v[usedVertices++].set(itemLeft, rowHeight, -itemWidth, -itemHeight, selectionId, red, green,
blue);
v[usedVertices++].set(itemLeft + itemWidth, rowHeight, itemWidth, -itemHeight, selectionId,
red, green, blue);
v[usedVertices++].set(itemLeft, itemTop, -itemWidth, itemHeight, selectionId, red, green,
blue);
v[usedVertices++].set(itemLeft + itemWidth, itemTop, itemWidth, itemHeight, selectionId,
red, green, blue);
currentY = itemTop;
} else {
if (currentY != itemTop) {
// 3 extra vertices to degenerate the surplus triangles
v[usedVertices++].set(itemLeft, currentY, -itemWidth, rowHeight - currentY, selectionId,
red, green, blue);
v[usedVertices++].set(itemLeft, currentY, -itemWidth, rowHeight - currentY, selectionId,
red, green, blue);
v[usedVertices++].set(itemLeft, itemTop, -itemWidth, itemHeight, selectionId, red,
green, blue);
}
// "Z" form, top to bottom
v[usedVertices++].set(itemLeft, itemTop, -itemWidth, itemHeight, selectionId, red, green,
blue);
v[usedVertices++].set(itemLeft + itemWidth, itemTop, itemWidth, itemHeight, selectionId,
red, green, blue);
v[usedVertices++].set(itemLeft, rowHeight, - itemWidth, -itemHeight, selectionId, red,
green, blue);
v[usedVertices++].set(itemLeft + itemWidth, rowHeight, itemWidth, -itemHeight, selectionId,
red, green, blue);
currentY = rowHeight;
}
}
OpaqueColoredPoint2DWithSize *TimelineItemsGeometry::vertexData()
{
QSGGeometry *geometry = node->geometry();
Q_ASSERT(geometry->attributeCount() == 4);
Q_ASSERT(geometry->sizeOfVertex() == sizeof(OpaqueColoredPoint2DWithSize));
const QSGGeometry::Attribute *attributes = geometry->attributes();
Q_ASSERT(attributes[0].position == 0);
Q_ASSERT(attributes[0].tupleSize == 2);
Q_ASSERT(attributes[0].type == GL_FLOAT);
Q_ASSERT(attributes[1].position == 1);
Q_ASSERT(attributes[1].tupleSize == 2);
Q_ASSERT(attributes[1].type == GL_FLOAT);
Q_ASSERT(attributes[2].position == 2);
Q_ASSERT(attributes[2].tupleSize == 1);
Q_ASSERT(attributes[2].type == GL_FLOAT);
Q_ASSERT(attributes[3].position == 3);
Q_ASSERT(attributes[3].tupleSize == 4);
Q_ASSERT(attributes[3].type == GL_UNSIGNED_BYTE);
return static_cast<OpaqueColoredPoint2DWithSize *>(node->geometry()->vertexData());
}
void TimelineItemsGeometry::allocate(QSGMaterial *material)
{
QSGGeometry *geometry = new QSGGeometry(opaqueColoredPoint2DWithSize(), usedVertices);
geometry->setIndexDataPattern(QSGGeometry::StaticPattern);
geometry->setVertexDataPattern(QSGGeometry::StaticPattern);
node = new QSGGeometryNode;
node->setGeometry(geometry);
node->setFlag(QSGNode::OwnsGeometry, true);
node->setMaterial(material);
allocatedVertices = usedVertices;
usedVertices = 0;
currentY = 0;
}
void TimelineItemsGeometry::addVertices(float itemTop)
{
if (currentY == TimelineModel::defaultRowHeight()) {
usedVertices += 4;
currentY = itemTop;
} else {
usedVertices += (currentY != itemTop ? 7 : 4);
currentY = TimelineModel::defaultRowHeight();
}
}
class TimelineExpandedRowNode : public QSGNode {
public:
TimelineItemsMaterial material;
virtual ~TimelineExpandedRowNode() {}
};
static void updateNodes(int from, int to, const TimelineModel *model,
const TimelineRenderState *parentState, TimelineItemsRenderPassState *state)
{
float defaultRowHeight = TimelineModel::defaultRowHeight();
QVector<TimelineItemsGeometry> expandedPerRow(model->expandedRowCount());
QVector<TimelineItemsGeometry> collapsedPerRow(model->collapsedRowCount());
for (int i = from; i < to; ++i) {
qint64 start = qMax(parentState->start(), model->startTime(i));
qint64 end = qMin(parentState->end(), model->startTime(i) + model->duration(i));
if (start > end)
continue;
float itemTop = (1.0 - model->relativeHeight(i)) * defaultRowHeight;
expandedPerRow[model->expandedRow(i)].addVertices(itemTop);
collapsedPerRow[model->collapsedRow(i)].addVertices(itemTop);
}
for (int i = 0; i < model->expandedRowCount(); ++i) {
TimelineItemsGeometry &row = expandedPerRow[i];
if (row.usedVertices > 0) {
row.allocate(&static_cast<TimelineExpandedRowNode *>(
state->m_expandedRows[i])->material);
state->m_expandedRows[i]->appendChildNode(row.node);
}
}
for (int i = 0; i < model->collapsedRowCount(); ++i) {
TimelineItemsGeometry &row = collapsedPerRow[i];
if (row.usedVertices > 0) {
row.allocate(&state->collapsedRowMaterial);
state->m_collapsedRows[i]->appendChildNode(row.node);
}
}
for (int i = from; i < to; ++i) {
qint64 start = qMax(parentState->start(), model->startTime(i));
qint64 end = qMin(parentState->end(), model->startTime(i) + model->duration(i));
if (start > end)
continue;
QColor color = model->color(i);
uchar red = color.red();
uchar green = color.green();
uchar blue = color.blue();
float itemWidth = (end - start) * parentState->scale();
float itemLeft = (start - parentState->start()) * parentState->scale();
// This has to be the exact same expression as above, to guarantee determinism.
float itemTop = (1.0 - model->relativeHeight(i)) * defaultRowHeight;
float selectionId = model->selectionId(i);
expandedPerRow[model->expandedRow(i)].addEvent(itemLeft, itemTop, itemWidth, selectionId,
red, green, blue);
collapsedPerRow[model->collapsedRow(i)].addEvent(itemLeft, itemTop, itemWidth, selectionId,
red, green, blue);
}
}
const QSGGeometry::AttributeSet &TimelineItemsGeometry::opaqueColoredPoint2DWithSize()
{
static QSGGeometry::Attribute data[] = {
QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true),
QSGGeometry::Attribute::create(1, 2, GL_FLOAT),
QSGGeometry::Attribute::create(2, 1, GL_FLOAT),
QSGGeometry::Attribute::create(3, 4, GL_UNSIGNED_BYTE)
};
static QSGGeometry::AttributeSet attrs = {
4,
sizeof(OpaqueColoredPoint2DWithSize),
data
};
return attrs;
}
const TimelineItemsRenderPass *TimelineItemsRenderPass::instance()
{
static const TimelineItemsRenderPass pass;
return &pass;
}
TimelineRenderPass::State *TimelineItemsRenderPass::update(const TimelineAbstractRenderer *renderer,
const TimelineRenderState *parentState,
State *oldState, int indexFrom,
int indexTo, bool stateChanged,
qreal spacing) const
{
Q_UNUSED(stateChanged);
const TimelineModel *model = renderer->model();
if (!model || indexFrom < 0 || indexTo > model->count())
return oldState;
QColor selectionColor = (renderer->selectionLocked() ? QColor(96,0,255) :
QColor(Qt::blue)).lighter(130);
TimelineItemsRenderPassState *state;
if (oldState == 0)
state = new TimelineItemsRenderPassState;
else
state = static_cast<TimelineItemsRenderPassState *>(oldState);
float selectedItem = renderer->selectedItem() == -1 ? -1 :
model->selectionId(renderer->selectedItem());
state->collapsedRowMaterial.setScale(QVector2D(spacing / parentState->scale(), 1));
state->collapsedRowMaterial.setSelectedItem(selectedItem);
state->collapsedRowMaterial.setSelectionColor(selectionColor);
if (state->m_expandedRows.isEmpty()) {
state->m_expandedRows.reserve(model->expandedRowCount());
state->m_collapsedRows.reserve(model->collapsedRowCount());
for (int i = 0; i < model->expandedRowCount(); ++i)
state->m_expandedRows << new TimelineExpandedRowNode;
for (int i = 0; i < model->collapsedRowCount(); ++i)
state->m_collapsedRows << new QSGNode;
}
if (state->indexFrom < state->indexTo) {
if (indexFrom < state->indexFrom) {
for (int i = indexFrom; i < state->indexFrom;
i+= TimelineItemsGeometry::maxEventsPerNode)
updateNodes(i, qMin(i + TimelineItemsGeometry::maxEventsPerNode, state->indexFrom),
model, parentState, state);
}
if (indexTo > state->indexTo) {
for (int i = state->indexTo; i < indexTo; i+= TimelineItemsGeometry::maxEventsPerNode)
updateNodes(i, qMin(i + TimelineItemsGeometry::maxEventsPerNode, indexTo), model,
parentState, state);
}
} else {
for (int i = indexFrom; i < indexTo; i+= TimelineItemsGeometry::maxEventsPerNode)
updateNodes(i, qMin(i + TimelineItemsGeometry::maxEventsPerNode, indexTo), model,
parentState, state);
}
if (model->expanded()) {
for (int row = 0; row < model->expandedRowCount(); ++row) {
TimelineExpandedRowNode *rowNode = static_cast<TimelineExpandedRowNode *>(
state->m_expandedRows[row]);
rowNode->material.setScale(
QVector2D(spacing / parentState->scale(),
static_cast<qreal>(model->expandedRowHeight(row))) /
static_cast<qreal>(TimelineModel::defaultRowHeight()));
rowNode->material.setSelectedItem(selectedItem);
rowNode->material.setSelectionColor(selectionColor);
}
}
state->indexFrom = qMin(state->indexFrom, indexFrom);
state->indexTo = qMax(state->indexTo, indexTo);
return state;
}
TimelineItemsRenderPass::TimelineItemsRenderPass()
{
}
class TimelineItemsMaterialShader : public QSGMaterialShader
{
public:
TimelineItemsMaterialShader();
virtual void updateState(const RenderState &state, QSGMaterial *newEffect,
QSGMaterial *oldEffect);
virtual char const *const *attributeNames() const;
private:
virtual void initialize();
int m_matrix_id;
int m_scale_id;
int m_selection_color_id;
int m_selected_item_id;
int m_z_range_id;
};
TimelineItemsMaterialShader::TimelineItemsMaterialShader()
: QSGMaterialShader()
{
setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qmlprofiler/timelineitems.vert"));
setShaderSourceFile(QOpenGLShader::Fragment,
QStringLiteral(":/qmlprofiler/timelineitems.frag"));
}
void TimelineItemsMaterialShader::updateState(const RenderState &state, QSGMaterial *newMaterial,
QSGMaterial *)
{
if (state.isMatrixDirty()) {
TimelineItemsMaterial *material = static_cast<TimelineItemsMaterial *>(newMaterial);
program()->setUniformValue(m_matrix_id, state.combinedMatrix());
program()->setUniformValue(m_scale_id, material->scale());
program()->setUniformValue(m_selection_color_id, material->selectionColor());
program()->setUniformValue(m_selected_item_id, material->selectedItem());
program()->setUniformValue(m_z_range_id, GLfloat(1.0));
}
}
char const *const *TimelineItemsMaterialShader::attributeNames() const
{
static const char *const attr[] = {"vertexCoord", "rectSize", "selectionId", "vertexColor", 0};
return attr;
}
void TimelineItemsMaterialShader::initialize()
{
m_matrix_id = program()->uniformLocation("matrix");
m_scale_id = program()->uniformLocation("scale");
m_selection_color_id = program()->uniformLocation("selectionColor");
m_selected_item_id = program()->uniformLocation("selectedItem");
m_z_range_id = program()->uniformLocation("_qt_zRange");
}
TimelineItemsMaterial::TimelineItemsMaterial() : m_selectedItem(-1)
{
setFlag(QSGMaterial::Blending, false);
}
QVector2D TimelineItemsMaterial::scale() const
{
return m_scale;
}
void TimelineItemsMaterial::setScale(QVector2D scale)
{
m_scale = scale;
}
float TimelineItemsMaterial::selectedItem() const
{
return m_selectedItem;
}
void TimelineItemsMaterial::setSelectedItem(float selectedItem)
{
m_selectedItem = selectedItem;
}
QColor TimelineItemsMaterial::selectionColor() const
{
return m_selectionColor;
}
void TimelineItemsMaterial::setSelectionColor(QColor selectionColor)
{
m_selectionColor = selectionColor;
}
QSGMaterialType *TimelineItemsMaterial::type() const
{
static QSGMaterialType type;
return &type;
}
QSGMaterialShader *TimelineItemsMaterial::createShader() const
{
return new TimelineItemsMaterialShader;
}
void OpaqueColoredPoint2DWithSize::set(float nx, float ny, float nw, float nh, float nid,
uchar nr, uchar ng, uchar nb) {
x = nx; y = ny; w = nw; h = nh; id = nid;
r = nr; g = ng, b = nb; a = 255;
}
} // namespace Timeline

View File

@@ -1,53 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINEITEMSRENDERPASS_H
#define TIMELINEITEMSRENDERPASS_H
#include "timelineabstractrenderer.h"
#include "timelinerenderpass.h"
#include <QSGMaterial>
namespace Timeline {
class TimelineItemsRenderPass : public TimelineRenderPass
{
public:
static const TimelineItemsRenderPass *instance();
State *update(const TimelineAbstractRenderer *renderer, const TimelineRenderState *parentState,
State *state, int firstIndex, int lastIndex, bool stateChanged,
qreal spacing) const;
protected:
TimelineItemsRenderPass();
};
} // namespace Timeline
#endif // TIMELINEITEMSRENDERPASS_H

View File

@@ -1,623 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "timelinemodel.h"
#include "timelinemodel_p.h"
#include "timelineitemsrenderpass.h"
#include "timelineselectionrenderpass.h"
#include "timelinenotesrenderpass.h"
#include <utils/qtcassert.h>
#include <QLinkedList>
namespace Timeline {
/*!
\class QmlProfiler::TimelineModel
\brief The TimelineModel class provides a sorted model for timeline data.
The TimelineModel lets you keep range data sorted by both start and end times, so that
visible ranges can easily be computed. The only precondition for that to work is that the ranges
must be perfectly nested. A "parent" range of a range R is defined as a range for which the
start time is earlier than R's start time and the end time is later than R's end time. A set
of ranges is perfectly nested if all parent ranges of any given range have a common parent
range. Mind that you can always make that happen by defining a range that spans the whole
available time span. That, however, will make any code that uses firstIndex() and lastIndex()
for selecting subsets of the model always select all of it.
\note Indices returned from the various methods are only valid until a new range is inserted
before them. Inserting a new range before a given index moves the range pointed to by the
index by one. Incrementing the index by one will make it point to the item again.
*/
/*!
Compute all ranges' parents.
\sa firstIndex()
*/
void TimelineModel::computeNesting()
{
Q_D(TimelineModel);
QLinkedList<int> parents;
for (int range = 0; range != count(); ++range) {
TimelineModelPrivate::Range &current = d->ranges[range];
for (QLinkedList<int>::iterator parentIt = parents.begin();;) {
if (parentIt == parents.end()) {
parents.append(range);
break;
}
TimelineModelPrivate::Range &parent = d->ranges[*parentIt];
qint64 parentEnd = parent.start + parent.duration;
if (parentEnd < current.start) {
// We've completely passed the parent. Remove it.
parentIt = parents.erase(parentIt);
} else if (parentEnd >= current.start + current.duration) {
// Current range is completely inside the parent range: no need to insert
current.parent = *parentIt;
break;
} else if (parent.start == current.start) {
// The parent range starts at the same time but ends before the current range.
// We need to switch them.
QTC_CHECK(parent.parent == -1);
parent.parent = range;
*parentIt = range;
break;
} else {
++parentIt;
}
}
}
}
int TimelineModel::collapsedRowCount() const
{
Q_D(const TimelineModel);
return d->collapsedRowCount;
}
void TimelineModel::setCollapsedRowCount(int rows)
{
Q_D(TimelineModel);
if (d->collapsedRowCount != rows) {
d->collapsedRowCount = rows;
emit collapsedRowCountChanged();
if (!d->expanded)
emit rowCountChanged();
}
}
int TimelineModel::expandedRowCount() const
{
Q_D(const TimelineModel);
return d->expandedRowCount;
}
void TimelineModel::setExpandedRowCount(int rows)
{
Q_D(TimelineModel);
if (d->expandedRowCount != rows) {
d->expandedRowCount = rows;
emit expandedRowCountChanged();
if (d->expanded)
emit rowCountChanged();
}
}
int TimelineModel::row(int index) const
{
return expanded() ? expandedRow(index) : collapsedRow(index);
}
TimelineModel::TimelineModelPrivate::TimelineModelPrivate(int modelId, const QString &displayName) :
modelId(modelId), displayName(displayName), expanded(false), hidden(false),
expandedRowCount(1), collapsedRowCount(1), q_ptr(0)
{
}
void TimelineModel::TimelineModelPrivate::init(TimelineModel *q)
{
q_ptr = q;
connect(q,SIGNAL(expandedChanged()),q,SIGNAL(heightChanged()));
connect(q,SIGNAL(hiddenChanged()),q,SIGNAL(heightChanged()));
connect(q,SIGNAL(emptyChanged()),q,SIGNAL(heightChanged()));
}
TimelineModel::TimelineModel(TimelineModelPrivate &dd, QObject *parent) :
QObject(parent), d_ptr(&dd)
{
d_ptr->init(this);
}
TimelineModel::TimelineModel(int modelId, const QString &displayName, QObject *parent) :
QObject(parent), d_ptr(new TimelineModelPrivate(modelId, displayName))
{
d_ptr->init(this);
}
TimelineModel::~TimelineModel()
{
Q_D(TimelineModel);
delete d;
}
bool TimelineModel::isEmpty() const
{
return count() == 0;
}
int TimelineModel::modelId() const
{
Q_D(const TimelineModel);
return d->modelId;
}
int TimelineModel::collapsedRowHeight(int rowNumber) const
{
Q_UNUSED(rowNumber);
return TimelineModelPrivate::DefaultRowHeight;
}
int TimelineModel::collapsedRowOffset(int rowNumber) const
{
return rowNumber * TimelineModelPrivate::DefaultRowHeight;
}
int TimelineModel::expandedRowHeight(int rowNumber) const
{
Q_D(const TimelineModel);
if (d->rowOffsets.size() > rowNumber)
return d->rowOffsets[rowNumber] - (rowNumber > 0 ? d->rowOffsets[rowNumber - 1] : 0);
return TimelineModelPrivate::DefaultRowHeight;
}
int TimelineModel::expandedRowOffset(int rowNumber) const
{
Q_D(const TimelineModel);
if (rowNumber == 0)
return 0;
if (d->rowOffsets.size() >= rowNumber)
return d->rowOffsets[rowNumber - 1];
if (!d->rowOffsets.empty())
return d->rowOffsets.last() + (rowNumber - d->rowOffsets.size()) *
TimelineModelPrivate::DefaultRowHeight;
return rowNumber * TimelineModelPrivate::DefaultRowHeight;
}
void TimelineModel::setExpandedRowHeight(int rowNumber, int height)
{
Q_D(TimelineModel);
if (height < TimelineModelPrivate::DefaultRowHeight)
height = TimelineModelPrivate::DefaultRowHeight;
int nextOffset = d->rowOffsets.empty() ? 0 : d->rowOffsets.last();
while (d->rowOffsets.size() <= rowNumber)
d->rowOffsets << (nextOffset += TimelineModelPrivate::DefaultRowHeight);
int difference = height - d->rowOffsets[rowNumber] +
(rowNumber > 0 ? d->rowOffsets[rowNumber - 1] : 0);
if (difference != 0) {
for (int offsetRow = rowNumber; offsetRow < d->rowOffsets.size(); ++offsetRow) {
d->rowOffsets[offsetRow] += difference;
}
emit expandedRowHeightChanged(rowNumber, height);
if (d->expanded)
emit heightChanged();
}
}
int TimelineModel::rowOffset(int rowNumber) const
{
return expanded() ? expandedRowOffset(rowNumber) : collapsedRowOffset(rowNumber);
}
int TimelineModel::rowHeight(int rowNumber) const
{
return expanded() ? expandedRowHeight(rowNumber) : collapsedRowHeight(rowNumber);
}
int TimelineModel::height() const
{
Q_D(const TimelineModel);
if (d->hidden || isEmpty())
return 0;
if (!d->expanded)
return collapsedRowCount() * TimelineModelPrivate::DefaultRowHeight;
if (d->rowOffsets.empty())
return expandedRowCount() * TimelineModelPrivate::DefaultRowHeight;
return d->rowOffsets.last() + (expandedRowCount() - d->rowOffsets.size()) *
TimelineModelPrivate::DefaultRowHeight;
}
/*!
Returns the number of ranges in the model.
*/
int TimelineModel::count() const
{
Q_D(const TimelineModel);
return d->ranges.count();
}
qint64 TimelineModel::duration(int index) const
{
Q_D(const TimelineModel);
return d->ranges[index].duration;
}
qint64 TimelineModel::startTime(int index) const
{
Q_D(const TimelineModel);
return d->ranges[index].start;
}
qint64 TimelineModel::endTime(int index) const
{
Q_D(const TimelineModel);
return d->ranges[index].start + d->ranges[index].duration;
}
/*!
Returns the type ID of the event with event ID \a index. The type ID is a globally valid ID
which can be used to communicate meta information about events to other parts of the program. By
default it is -1, which means there is no global type information about the event.
*/
int TimelineModel::typeId(int index) const
{
Q_UNUSED(index)
return -1;
}
/*!
Looks up the first range with an end time later than the given time and
returns its parent's index. If no such range is found, it returns -1. If there
is no parent, it returns the found range's index. The parent of a range is the
range with the earliest start time that completely covers the child range.
"Completely covers" means:
parent.startTime <= child.startTime && parent.endTime >= child.endTime
*/
int TimelineModel::firstIndex(qint64 startTime) const
{
Q_D(const TimelineModel);
int index = d->firstIndexNoParents(startTime);
if (index == -1)
return -1;
int parent = d->ranges[index].parent;
return parent == -1 ? index : parent;
}
/*!
Looks up the first range with an end time later than the specified \a startTime and
returns its index. If no such range is found, it returns -1.
*/
int TimelineModel::TimelineModelPrivate::firstIndexNoParents(qint64 startTime) const
{
// in the "endtime" list, find the first event that ends after startTime
if (endTimes.isEmpty())
return -1;
if (endTimes.count() == 1 || endTimes.first().end > startTime)
return endTimes.first().startIndex;
if (endTimes.last().end <= startTime)
return -1;
return endTimes[lowerBound(endTimes, startTime) + 1].startIndex;
}
/*!
Looks up the last range with a start time earlier than the specified \a endTime and
returns its index. If no such range is found, it returns -1.
*/
int TimelineModel::lastIndex(qint64 endTime) const
{
Q_D(const TimelineModel);
// in the "starttime" list, find the last event that starts before endtime
if (d->ranges.isEmpty() || d->ranges.first().start >= endTime)
return -1;
if (d->ranges.count() == 1)
return 0;
if (d->ranges.last().start < endTime)
return d->ranges.count() - 1;
return d->lowerBound(d->ranges, endTime);
}
QVariantMap TimelineModel::location(int index) const
{
Q_UNUSED(index);
QVariantMap map;
return map;
}
/*!
Returns \c true if this model can contain events of global type ID \a typeIndex. Otherwise
returns \c false. The base model does not know anything about type IDs and always returns
\c false. You should override this method if you implement \l typeId().
*/
bool TimelineModel::handlesTypeId(int typeIndex) const
{
Q_UNUSED(typeIndex);
return false;
}
int TimelineModel::selectionIdForLocation(const QString &filename, int line, int column) const
{
Q_UNUSED(filename);
Q_UNUSED(line);
Q_UNUSED(column);
return -1;
}
float TimelineModel::relativeHeight(int index) const
{
Q_UNUSED(index);
return 1.0f;
}
int TimelineModel::rowMinValue(int rowNumber) const
{
Q_UNUSED(rowNumber);
return 0;
}
int TimelineModel::rowMaxValue(int rowNumber) const
{
Q_UNUSED(rowNumber);
return 0;
}
int TimelineModel::defaultRowHeight()
{
return TimelineModelPrivate::DefaultRowHeight;
}
QList<const TimelineRenderPass *> TimelineModel::supportedRenderPasses() const
{
QList<const TimelineRenderPass *> passes;
passes << TimelineItemsRenderPass::instance()
<< TimelineSelectionRenderPass::instance()
<< TimelineNotesRenderPass::instance();
return passes;
}
QColor TimelineModel::colorBySelectionId(int index) const
{
return colorByHue(selectionId(index) * TimelineModelPrivate::SelectionIdHueMultiplier);
}
QColor TimelineModel::colorByFraction(double fraction) const
{
return colorByHue(fraction * TimelineModelPrivate::FractionHueMultiplier +
TimelineModelPrivate::FractionHueMininimum);
}
QColor TimelineModel::colorByHue(int hue) const
{
return QColor::fromHsl(hue % 360, TimelineModelPrivate::Saturation,
TimelineModelPrivate::Lightness);
}
/*!
Inserts the range defined by \a duration and \a selectionId at the specified \a startTime and
returns its index. The \a selectionId determines the selection group the new event belongs to.
\sa selectionId()
*/
int TimelineModel::insert(qint64 startTime, qint64 duration, int selectionId)
{
Q_D(TimelineModel);
/* Doing insert-sort here is preferable as most of the time the times will actually be
* presorted in the right way. So usually this will just result in appending. */
int index = d->insertSorted(d->ranges,
TimelineModelPrivate::Range(startTime, duration, selectionId));
if (index < d->ranges.size() - 1)
d->incrementStartIndices(index);
d->insertSorted(d->endTimes, TimelineModelPrivate::RangeEnd(index, startTime + duration));
return index;
}
/*!
Inserts the specified \a selectionId as range start at the specified \a startTime and returns
its index. The range end is not set. The \a selectionId determines the selection group the new
event belongs to.
\sa selectionId()
*/
int TimelineModel::insertStart(qint64 startTime, int selectionId)
{
Q_D(TimelineModel);
int index = d->insertSorted(d->ranges, TimelineModelPrivate::Range(startTime, 0, selectionId));
if (index < d->ranges.size() - 1)
d->incrementStartIndices(index);
return index;
}
/*!
Adds the range \a duration at the specified start \a index.
*/
void TimelineModel::insertEnd(int index, qint64 duration)
{
Q_D(TimelineModel);
d->ranges[index].duration = duration;
d->insertSorted(d->endTimes, TimelineModelPrivate::RangeEnd(index,
d->ranges[index].start + duration));
}
bool TimelineModel::expanded() const
{
Q_D(const TimelineModel);
return d->expanded;
}
void TimelineModel::setExpanded(bool expanded)
{
Q_D(TimelineModel);
if (expanded != d->expanded) {
d->expanded = expanded;
emit expandedChanged();
if (d->collapsedRowCount != d->expandedRowCount)
emit rowCountChanged();
}
}
bool TimelineModel::hidden() const
{
Q_D(const TimelineModel);
return d->hidden;
}
void TimelineModel::setHidden(bool hidden)
{
Q_D(TimelineModel);
if (hidden != d->hidden) {
d->hidden = hidden;
emit hiddenChanged();
}
}
QString TimelineModel::displayName() const
{
Q_D(const TimelineModel);
return d->displayName;
}
int TimelineModel::rowCount() const
{
Q_D(const TimelineModel);
return d->expanded ? d->expandedRowCount : d->collapsedRowCount;
}
/*!
Returns the ID of the selection group the event with event ID \a index belongs to. Selection
groups are local to the model and the model can arbitrarily assign events to selection groups
when inserting them.
If one event from a selection group is selected, all visible other events from the same
selection group are highlighted. Rows are expected to correspond to selection IDs when the view
is expanded.
*/
int TimelineModel::selectionId(int index) const
{
Q_D(const TimelineModel);
return d->ranges[index].selectionId;
}
void TimelineModel::clear()
{
Q_D(TimelineModel);
bool hadRowHeights = !d->rowOffsets.empty();
bool wasEmpty = isEmpty();
setExpandedRowCount(1);
setCollapsedRowCount(1);
setExpanded(false);
setHidden(false);
d->rowOffsets.clear();
d->ranges.clear();
d->endTimes.clear();
if (hadRowHeights)
emit expandedRowHeightChanged(-1, -1);
if (!wasEmpty)
emit emptyChanged();
}
int TimelineModel::nextItemBySelectionId(int selectionId, qint64 time, int currentItem) const
{
Q_D(const TimelineModel);
return d->nextItemById(TimelineModelPrivate::SelectionId, selectionId, time, currentItem);
}
int TimelineModel::nextItemByTypeId(int typeId, qint64 time, int currentItem) const
{
Q_D(const TimelineModel);
return d->nextItemById(TimelineModelPrivate::TypeId, typeId, time, currentItem);
}
int TimelineModel::prevItemBySelectionId(int selectionId, qint64 time, int currentItem) const
{
Q_D(const TimelineModel);
return d->prevItemById(TimelineModelPrivate::SelectionId, selectionId, time, currentItem);
}
int TimelineModel::prevItemByTypeId(int typeId, qint64 time, int currentItem) const
{
Q_D(const TimelineModel);
return d->prevItemById(TimelineModelPrivate::TypeId, typeId, time, currentItem);
}
int TimelineModel::TimelineModelPrivate::nextItemById(IdType idType, int id, qint64 time,
int currentItem) const
{
Q_Q(const TimelineModel);
if (ranges.empty())
return -1;
int ndx = -1;
if (currentItem == -1)
ndx = firstIndexNoParents(time);
else
ndx = currentItem + 1;
if (ndx < 0 || ndx >= ranges.count())
ndx = 0;
int startIndex = ndx;
do {
if ((idType == TypeId && q->typeId(ndx) == id) ||
(idType == SelectionId && ranges[ndx].selectionId == id))
return ndx;
ndx = (ndx + 1) % ranges.count();
} while (ndx != startIndex);
return -1;
}
int TimelineModel::TimelineModelPrivate::prevItemById(IdType idType, int id, qint64 time,
int currentItem) const
{
Q_Q(const TimelineModel);
if (ranges.empty())
return -1;
int ndx = -1;
if (currentItem == -1)
ndx = firstIndexNoParents(time);
else
ndx = currentItem - 1;
if (ndx < 0)
ndx = ranges.count() - 1;
int startIndex = ndx;
do {
if ((idType == TypeId && q->typeId(ndx) == id) ||
(idType == SelectionId && ranges[ndx].selectionId == id))
return ndx;
if (--ndx < 0)
ndx = ranges.count()-1;
} while (ndx != startIndex);
return -1;
}
} // namespace Timeline
#include "moc_timelinemodel.cpp"

View File

@@ -1,160 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINEMODEL_H
#define TIMELINEMODEL_H
#include "qmlprofiler_global.h"
#include "qmlprofilermodelmanager.h"
#include "qmlprofilerdatamodel.h"
#include "timelinerenderpass.h"
#include <QVariant>
#include <QColor>
namespace Timeline {
class QMLPROFILER_EXPORT TimelineModel : public QObject
{
Q_OBJECT
Q_PROPERTY(int modelId READ modelId CONSTANT)
Q_PROPERTY(QString displayName READ displayName CONSTANT)
Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged)
Q_PROPERTY(bool hidden READ hidden WRITE setHidden NOTIFY hiddenChanged)
Q_PROPERTY(bool expanded READ expanded WRITE setExpanded NOTIFY expandedChanged)
Q_PROPERTY(int height READ height NOTIFY heightChanged)
Q_PROPERTY(int expandedRowCount READ expandedRowCount NOTIFY expandedRowCountChanged)
Q_PROPERTY(int collapsedRowCount READ collapsedRowCount NOTIFY collapsedRowCountChanged)
Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
Q_PROPERTY(QVariantList labels READ labels NOTIFY labelsChanged)
Q_PROPERTY(int count READ count NOTIFY emptyChanged)
Q_PROPERTY(int defaultRowHeight READ defaultRowHeight CONSTANT)
public:
class TimelineModelPrivate;
TimelineModel(int modelId, const QString &displayName, QObject *parent);
~TimelineModel();
// Methods implemented by the abstract model itself
bool isEmpty() const;
int modelId() const;
Q_INVOKABLE int collapsedRowHeight(int rowNumber) const;
Q_INVOKABLE int expandedRowHeight(int rowNumber) const;
Q_INVOKABLE int rowHeight(int rowNumber) const;
Q_INVOKABLE void setExpandedRowHeight(int rowNumber, int height);
Q_INVOKABLE int collapsedRowOffset(int rowNumber) const;
Q_INVOKABLE int expandedRowOffset(int rowNumber) const;
Q_INVOKABLE int rowOffset(int rowNumber) const;
int height() const;
int count() const;
Q_INVOKABLE qint64 duration(int index) const;
Q_INVOKABLE qint64 startTime(int index) const;
Q_INVOKABLE qint64 endTime(int index) const;
Q_INVOKABLE int selectionId(int index) const;
int firstIndex(qint64 startTime) const;
int lastIndex(qint64 endTime) const;
bool expanded() const;
bool hidden() const;
void setExpanded(bool expanded);
void setHidden(bool hidden);
QString displayName() const;
int expandedRowCount() const;
int collapsedRowCount() const;
int rowCount() const;
// Methods that have to be implemented by child models
Q_INVOKABLE virtual QColor color(int index) const = 0;
virtual QVariantList labels() const = 0;
Q_INVOKABLE virtual QVariantMap details(int index) const = 0;
Q_INVOKABLE virtual int expandedRow(int index) const = 0;
Q_INVOKABLE virtual int collapsedRow(int index) const = 0;
Q_INVOKABLE int row(int index) const;
// Methods which can optionally be implemented by child models.
// returned map should contain "file", "line", "column" properties, or be empty
Q_INVOKABLE virtual QVariantMap location(int index) const;
Q_INVOKABLE virtual int typeId(int index) const;
Q_INVOKABLE virtual bool handlesTypeId(int typeId) const;
Q_INVOKABLE virtual int selectionIdForLocation(const QString &filename, int line,
int column) const;
Q_INVOKABLE virtual float relativeHeight(int index) const;
Q_INVOKABLE virtual int rowMinValue(int rowNumber) const;
Q_INVOKABLE virtual int rowMaxValue(int rowNumber) const;
Q_INVOKABLE int nextItemBySelectionId(int selectionId, qint64 time, int currentItem) const;
Q_INVOKABLE int nextItemByTypeId(int typeId, qint64 time, int currentItem) const;
Q_INVOKABLE int prevItemBySelectionId(int selectionId, qint64 time, int currentItem) const;
Q_INVOKABLE int prevItemByTypeId(int typeId, qint64 time, int currentItem) const;
static int defaultRowHeight();
virtual QList<const TimelineRenderPass *> supportedRenderPasses() const;
signals:
void expandedChanged();
void hiddenChanged();
void expandedRowHeightChanged(int row, int height);
void emptyChanged();
void heightChanged();
void expandedRowCountChanged();
void collapsedRowCountChanged();
void rowCountChanged();
void labelsChanged();
protected:
QColor colorBySelectionId(int index) const;
QColor colorByFraction(double fraction) const;
QColor colorByHue(int hue) const;
int insert(qint64 startTime, qint64 duration, int selectionId);
int insertStart(qint64 startTime, int selectionId);
void insertEnd(int index, qint64 duration);
void computeNesting();
void setCollapsedRowCount(int rows);
void setExpandedRowCount(int rows);
virtual void clear();
explicit TimelineModel(TimelineModelPrivate &dd, QObject *parent);
TimelineModelPrivate *d_ptr;
private:
Q_DECLARE_PRIVATE(TimelineModel)
};
} // namespace Timeline
#endif // TIMELINEMODEL_H

View File

@@ -1,140 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINEMODEL_P_H
#define TIMELINEMODEL_P_H
#include "timelinemodel.h"
namespace Timeline {
class QMLPROFILER_EXPORT TimelineModel::TimelineModelPrivate {
public:
static const int DefaultRowHeight = 30;
enum IdType { SelectionId, TypeId };
enum BoxColorProperties {
SelectionIdHueMultiplier = 25,
FractionHueMultiplier = 96,
FractionHueMininimum = 10,
Saturation = 150,
Lightness = 166
};
struct Range {
Range() : start(-1), duration(-1), selectionId(-1), parent(-1) {}
Range(qint64 start, qint64 duration, int selectionId) :
start(start), duration(duration), selectionId(selectionId), parent(-1) {}
qint64 start;
qint64 duration;
int selectionId;
int parent;
inline qint64 timestamp() const {return start;}
};
struct RangeEnd {
RangeEnd() : startIndex(-1), end(-1) {}
RangeEnd(int startIndex, qint64 end) :
startIndex(startIndex), end(end) {}
int startIndex;
qint64 end;
inline qint64 timestamp() const {return end;}
};
TimelineModelPrivate(int modelId, const QString &displayName);
void init(TimelineModel *q);
int firstIndexNoParents(qint64 startTime) const;
void incrementStartIndices(int index)
{
for (int i = 0; i < endTimes.size(); ++i) {
if (endTimes[i].startIndex >= index)
endTimes[i].startIndex++;
}
}
template<typename RangeDelimiter>
static inline int insertSorted(QVector<RangeDelimiter> &container, const RangeDelimiter &item)
{
for (int i = container.count();;) {
if (i == 0) {
container.prepend(item);
return 0;
}
if (container[--i].timestamp() <= item.timestamp()) {
container.insert(++i, item);
return i;
}
}
}
template<typename RangeDelimiter>
static inline int lowerBound(const QVector<RangeDelimiter> &container, qint64 time)
{
int fromIndex = 0;
int toIndex = container.count() - 1;
while (toIndex - fromIndex > 1) {
int midIndex = (fromIndex + toIndex)/2;
if (container[midIndex].timestamp() < time)
fromIndex = midIndex;
else
toIndex = midIndex;
}
return fromIndex;
}
int prevItemById(IdType idType, int id, qint64 time, int currentSelected) const;
int nextItemById(IdType idType, int id, qint64 time, int currentSelected) const;
QVector<Range> ranges;
QVector<RangeEnd> endTimes;
QVector<int> rowOffsets;
const int modelId;
const QString displayName;
bool expanded;
bool hidden;
int expandedRowCount;
int collapsedRowCount;
protected:
TimelineModel *q_ptr;
private:
Q_DECLARE_PUBLIC(TimelineModel)
};
} // namespace Timeline
#endif // TIMELINEMODEL_P_H

View File

@@ -1,229 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "timelinemodelaggregator.h"
#include "qmlprofilerrangemodel.h"
#include "qmlprofileranimationsmodel.h"
#include "qmlprofilerplugin.h"
#include "qmlprofilernotesmodel.h"
#include <QStringList>
#include <QVariant>
namespace Timeline {
class TimelineModelAggregator::TimelineModelAggregatorPrivate {
public:
TimelineModelAggregatorPrivate(TimelineModelAggregator *qq):q(qq) {}
~TimelineModelAggregatorPrivate() {}
TimelineModelAggregator *q;
QList <TimelineModel *> modelList;
TimelineNotesModel *notesModel;
};
TimelineModelAggregator::TimelineModelAggregator(TimelineNotesModel *notes, QObject *parent)
: QObject(parent), d(new TimelineModelAggregatorPrivate(this))
{
d->notesModel = notes;
connect(this,SIGNAL(modelsChanged()),this,SIGNAL(heightChanged()));
connect(this,SIGNAL(stateChanged()),this,SIGNAL(heightChanged()));
}
TimelineModelAggregator::~TimelineModelAggregator()
{
delete d;
}
int TimelineModelAggregator::height() const
{
return modelOffset(d->modelList.length());
}
void TimelineModelAggregator::addModel(TimelineModel *m)
{
d->modelList << m;
connect(m,SIGNAL(heightChanged()),this,SIGNAL(heightChanged()));
d->notesModel->addTimelineModel(m);
emit modelsChanged();
}
const TimelineModel *TimelineModelAggregator::model(int modelIndex) const
{
return d->modelList[modelIndex];
}
QVariantList TimelineModelAggregator::models() const
{
QVariantList ret;
foreach (TimelineModel *model, d->modelList)
ret << QVariant::fromValue(model);
return ret;
}
TimelineNotesModel *TimelineModelAggregator::notes() const
{
return d->notesModel;
}
void TimelineModelAggregator::clear()
{
qDeleteAll(d->modelList);
d->modelList.clear();
if (d->notesModel)
d->notesModel->clear();
emit modelsChanged();
}
int TimelineModelAggregator::modelOffset(int modelIndex) const
{
int ret = 0;
for (int i = 0; i < modelIndex; ++i)
ret += d->modelList[i]->height();
return ret;
}
int TimelineModelAggregator::modelCount() const
{
return d->modelList.count();
}
QVariantMap TimelineModelAggregator::nextItem(int selectedModel, int selectedItem,
qint64 time) const
{
if (selectedItem != -1)
time = model(selectedModel)->startTime(selectedItem);
QVarLengthArray<int> itemIndexes(modelCount());
for (int i = 0; i < modelCount(); i++) {
const TimelineModel *currentModel = model(i);
if (currentModel->count() > 0) {
if (selectedModel == i) {
itemIndexes[i] = (selectedItem + 1) % currentModel->count();
} else {
if (currentModel->startTime(0) > time)
itemIndexes[i] = 0;
else
itemIndexes[i] = (currentModel->lastIndex(time) + 1) % currentModel->count();
}
} else {
itemIndexes[i] = -1;
}
}
int candidateModelIndex = -1;
qint64 candidateStartTime = std::numeric_limits<qint64>::max();
for (int i = 0; i < modelCount(); i++) {
if (itemIndexes[i] == -1)
continue;
qint64 newStartTime = model(i)->startTime(itemIndexes[i]);
if (newStartTime > time && newStartTime < candidateStartTime) {
candidateStartTime = newStartTime;
candidateModelIndex = i;
}
}
int itemIndex;
if (candidateModelIndex != -1) {
itemIndex = itemIndexes[candidateModelIndex];
} else {
itemIndex = -1;
candidateStartTime = std::numeric_limits<qint64>::max();
for (int i = 0; i < modelCount(); i++) {
const TimelineModel *currentModel = model(i);
if (currentModel->count() > 0 && currentModel->startTime(0) < candidateStartTime) {
candidateModelIndex = i;
itemIndex = 0;
candidateStartTime = currentModel->startTime(0);
}
}
}
QVariantMap ret;
ret.insert(QLatin1String("model"), candidateModelIndex);
ret.insert(QLatin1String("item"), itemIndex);
return ret;
}
QVariantMap TimelineModelAggregator::prevItem(int selectedModel, int selectedItem,
qint64 time) const
{
if (selectedItem != -1)
time = model(selectedModel)->startTime(selectedItem);
QVarLengthArray<int> itemIndexes(modelCount());
for (int i = 0; i < modelCount(); i++) {
if (selectedModel == i) {
itemIndexes[i] = selectedItem - 1;
if (itemIndexes[i] < 0)
itemIndexes[i] = model(selectedModel)->count() -1;
}
else
itemIndexes[i] = model(i)->lastIndex(time);
}
int candidateModelIndex = -1;
qint64 candidateStartTime = std::numeric_limits<qint64>::min();
for (int i = 0; i < modelCount(); i++) {
const TimelineModel *currentModel = model(i);
if (itemIndexes[i] == -1 || itemIndexes[i] >= currentModel->count())
continue;
qint64 newStartTime = currentModel->startTime(itemIndexes[i]);
if (newStartTime < time && newStartTime > candidateStartTime) {
candidateStartTime = newStartTime;
candidateModelIndex = i;
}
}
int itemIndex = -1;
if (candidateModelIndex != -1) {
itemIndex = itemIndexes[candidateModelIndex];
} else {
candidateStartTime = std::numeric_limits<qint64>::min();
for (int i = 0; i < modelCount(); i++) {
const TimelineModel *currentModel = model(i);
if (currentModel->count() > 0 &&
currentModel->startTime(currentModel->count() - 1) > candidateStartTime) {
candidateModelIndex = i;
itemIndex = currentModel->count() - 1;
candidateStartTime = currentModel->startTime(itemIndex);
}
}
}
QVariantMap ret;
ret.insert(QLatin1String("model"), candidateModelIndex);
ret.insert(QLatin1String("item"), itemIndex);
return ret;
}
} // namespace Timeline

View File

@@ -1,78 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINEMODELAGGREGATOR_H
#define TIMELINEMODELAGGREGATOR_H
#include "qmlprofilertimelinemodel.h"
#include "qmlprofilermodelmanager.h"
#include "timelinerenderer.h"
namespace Timeline {
class TimelineModelAggregator : public QObject
{
Q_OBJECT
Q_PROPERTY(int height READ height NOTIFY heightChanged)
Q_PROPERTY(QVariantList models READ models NOTIFY modelsChanged)
Q_PROPERTY(Timeline::TimelineNotesModel *notes READ notes CONSTANT)
public:
TimelineModelAggregator(TimelineNotesModel *notes, QObject *parent = 0);
~TimelineModelAggregator();
int height() const;
void addModel(TimelineModel *m);
const TimelineModel *model(int modelIndex) const;
QVariantList models() const;
TimelineNotesModel *notes() const;
void clear();
int modelCount() const;
Q_INVOKABLE int modelOffset(int modelIndex) const;
Q_INVOKABLE QVariantMap nextItem(int selectedModel, int selectedItem, qint64 time) const;
Q_INVOKABLE QVariantMap prevItem(int selectedModel, int selectedItem, qint64 time) const;
signals:
void dataAvailable();
void stateChanged();
void modelsChanged();
void heightChanged();
private:
class TimelineModelAggregatorPrivate;
TimelineModelAggregatorPrivate *d;
};
} // namespace Timeline
#endif // TIMELINEMODELAGGREGATOR_H

View File

@@ -1,225 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "timelinenotesmodel_p.h"
namespace Timeline {
TimelineNotesModel::TimelineNotesModelPrivate::TimelineNotesModelPrivate(TimelineNotesModel *q) :
modified(false), q_ptr(q)
{
}
TimelineNotesModel::TimelineNotesModel(QObject *parent) : QObject(parent),
d_ptr(new TimelineNotesModelPrivate(this))
{
}
TimelineNotesModel::~TimelineNotesModel()
{
Q_D(TimelineNotesModel);
delete d;
}
int TimelineNotesModel::count() const
{
Q_D(const TimelineNotesModel);
return d->data.count();
}
void TimelineNotesModel::addTimelineModel(const TimelineModel *timelineModel)
{
Q_D(TimelineNotesModel);
connect(timelineModel, SIGNAL(destroyed(QObject*)),
this, SLOT(_q_removeTimelineModel(QObject*)));
d->timelineModels.insert(timelineModel->modelId(), timelineModel);
}
const TimelineModel *TimelineNotesModel::timelineModelByModelId(int timelineModel) const
{
Q_D(const TimelineNotesModel);
auto it = d->timelineModels.find(timelineModel);
return it == d->timelineModels.end() ? 0 : it.value();
}
QList<const TimelineModel *> TimelineNotesModel::timelineModels() const
{
Q_D(const TimelineNotesModel);
return d->timelineModels.values();
}
int TimelineNotesModel::typeId(int index) const
{
Q_D(const TimelineNotesModel);
const TimelineNotesModelPrivate::Note &note = d->data[index];
const TimelineModel *model = timelineModelByModelId(note.timelineModel);
if (!model)
return -1; // This can happen if one of the timeline models has been removed
return model->typeId(note.timelineIndex);
}
QString TimelineNotesModel::text(int index) const
{
Q_D(const TimelineNotesModel);
return d->data[index].text;
}
int TimelineNotesModel::timelineModel(int index) const
{
Q_D(const TimelineNotesModel);
return d->data[index].timelineModel;
}
int TimelineNotesModel::timelineIndex(int index) const
{
Q_D(const TimelineNotesModel);
return d->data[index].timelineIndex;
}
QVariantList TimelineNotesModel::byTypeId(int selectedType) const
{
QVariantList ret;
for (int noteId = 0; noteId < count(); ++noteId) {
if (selectedType == typeId(noteId))
ret << noteId;
}
return ret;
}
QVariantList TimelineNotesModel::byTimelineModel(int timelineModel) const
{
Q_D(const TimelineNotesModel);
QVariantList ret;
for (int noteId = 0; noteId < count(); ++noteId) {
if (d->data[noteId].timelineModel == timelineModel)
ret << noteId;
}
return ret;
}
int TimelineNotesModel::get(int timelineModel, int timelineIndex) const
{
Q_D(const TimelineNotesModel);
for (int noteId = 0; noteId < count(); ++noteId) {
const TimelineNotesModelPrivate::Note &note = d->data[noteId];
if (note.timelineModel == timelineModel && note.timelineIndex == timelineIndex)
return noteId;
}
return -1;
}
int TimelineNotesModel::add(int timelineModel, int timelineIndex, const QString &text)
{
Q_D(TimelineNotesModel);
const TimelineModel *model = d->timelineModels[timelineModel];
int typeId = model->typeId(timelineIndex);
TimelineNotesModelPrivate::Note note = { text, timelineModel, timelineIndex };
d->data << note;
d->modified = true;
emit changed(typeId, timelineModel, timelineIndex);
return d->data.count() - 1;
}
void TimelineNotesModel::update(int index, const QString &text)
{
Q_D(TimelineNotesModel);
TimelineNotesModelPrivate::Note &note = d->data[index];
if (text != note.text) {
note.text = text;
d->modified = true;
emit changed(typeId(index), note.timelineModel, note.timelineIndex);
}
}
void TimelineNotesModel::remove(int index)
{
Q_D(TimelineNotesModel);
TimelineNotesModelPrivate::Note &note = d->data[index];
int noteType = typeId(index);
int timelineModel = note.timelineModel;
int timelineIndex = note.timelineIndex;
d->data.removeAt(index);
d->modified = true;
emit changed(noteType, timelineModel, timelineIndex);
}
bool TimelineNotesModel::isModified() const
{
Q_D(const TimelineNotesModel);
return d->modified;
}
void TimelineNotesModel::resetModified()
{
Q_D(TimelineNotesModel);
d->modified = false;
}
void TimelineNotesModel::TimelineNotesModelPrivate::_q_removeTimelineModel(QObject *timelineModel)
{
for (auto i = timelineModels.begin(); i != timelineModels.end();) {
if (i.value() == timelineModel)
i = timelineModels.erase(i);
else
++i;
}
}
void TimelineNotesModel::setText(int noteId, const QString &text)
{
if (text.length() > 0)
update(noteId, text);
else
remove(noteId);
}
void TimelineNotesModel::setText(int modelIndex, int index, const QString &text)
{
int noteId = get(modelIndex, index);
if (noteId == -1) {
if (text.length() > 0)
add(modelIndex, index, text);
} else {
setText(noteId, text);
}
}
void TimelineNotesModel::clear()
{
Q_D(TimelineNotesModel);
d->data.clear();
d->modified = false;
emit changed(-1, -1, -1);
}
} // namespace Timeline
#include "moc_timelinenotesmodel.cpp"

View File

@@ -1,85 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINENOTESMODEL_H
#define TIMELINENOTESMODEL_H
#include "timelinemodel.h"
namespace Timeline {
class QMLPROFILER_EXPORT TimelineNotesModel : public QObject
{
Q_OBJECT
Q_PROPERTY(int count READ count NOTIFY changed)
public:
TimelineNotesModel(QObject *parent);
~TimelineNotesModel();
int count() const;
void addTimelineModel(const TimelineModel *timelineModel);
const TimelineModel *timelineModelByModelId(int timelineModel) const;
QList<const TimelineModel *> timelineModels() const;
Q_INVOKABLE int typeId(int index) const;
Q_INVOKABLE QString text(int index) const;
Q_INVOKABLE int timelineModel(int index) const;
Q_INVOKABLE int timelineIndex(int index) const;
Q_INVOKABLE QVariantList byTypeId(int typeId) const;
Q_INVOKABLE QVariantList byTimelineModel(int timelineModel) const;
Q_INVOKABLE int get(int timelineModel, int timelineIndex) const;
Q_INVOKABLE int add(int timelineModel, int timelineIndex, const QString &text);
Q_INVOKABLE void update(int index, const QString &text);
Q_INVOKABLE void remove(int index);
Q_INVOKABLE void setText(int noteId, const QString &text);
Q_INVOKABLE void setText(int modelIndex, int index, const QString &text);
bool isModified() const;
void resetModified();
void clear();
signals:
void changed(int typeId, int timelineModel, int timelineIndex);
private:
class TimelineNotesModelPrivate;
TimelineNotesModelPrivate *d_ptr;
Q_DECLARE_PRIVATE(TimelineNotesModel)
Q_PRIVATE_SLOT(d_ptr, void _q_removeTimelineModel(QObject *timelineModel))
};
} // namespace Timeline
#endif // TIMELINENOTESMODEL_H

View File

@@ -1,65 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINENOTESMODEL_P_H
#define TIMELINENOTESMODEL_P_H
#include "timelinenotesmodel.h"
namespace Timeline {
class TimelineNotesModel::TimelineNotesModelPrivate {
public:
TimelineNotesModelPrivate(TimelineNotesModel *q);
struct Note {
// Saved properties
QString text;
// Cache, created on loading
int timelineModel;
int timelineIndex;
};
QList<Note> data;
QHash<int, const TimelineModel *> timelineModels;
bool modified;
void _q_removeTimelineModel(QObject *model);
private:
TimelineNotesModel *q_ptr;
Q_DECLARE_PUBLIC(TimelineNotesModel)
};
} // namespace Timeline
#endif // TIMELINENOTESMODEL_P_H

View File

@@ -1,265 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "timelinenotesrenderpass.h"
#include "timelinerenderstate.h"
#include "qmlprofilernotesmodel.h"
namespace Timeline {
struct Point2DWithDistanceFromTop {
float x, y, d;
void set(float nx, float ny, float nd);
};
class NotesMaterial : public QSGMaterial
{
public:
QSGMaterialType *type() const;
QSGMaterialShader *createShader() const;
};
struct NotesGeometry
{
static const int maxNotes;
static const QSGGeometry::AttributeSet &point2DWithDistanceFromTop();
static QSGGeometry *createGeometry(QVector<int> &ids, const TimelineModel *model,
const TimelineRenderState *parentState, bool collapsed);
};
const int NotesGeometry::maxNotes = 0xffff / 2;
struct TimelineNotesRenderPassState : public TimelineRenderPass::State
{
TimelineNotesRenderPassState(int expandedRows);
QSGGeometryNode *createNode();
NotesMaterial material;
QSGGeometry nullGeometry;
QSGGeometryNode *m_collapsedOverlay;
QVector<QSGNode *> m_expandedRows;
QSGNode *collapsedOverlay() const { return m_collapsedOverlay; }
const QVector<QSGNode *> &expandedRows() const { return m_expandedRows; }
};
const QSGGeometry::AttributeSet &NotesGeometry::point2DWithDistanceFromTop()
{
static QSGGeometry::Attribute data[] = {
QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true),
QSGGeometry::Attribute::create(1, 1, GL_FLOAT),
};
static QSGGeometry::AttributeSet attrs = {
2,
sizeof(Point2DWithDistanceFromTop),
data
};
return attrs;
}
const TimelineNotesRenderPass *TimelineNotesRenderPass::instance()
{
static const TimelineNotesRenderPass pass;
return &pass;
}
TimelineNotesRenderPass::TimelineNotesRenderPass()
{
}
TimelineRenderPass::State *TimelineNotesRenderPass::update(const TimelineAbstractRenderer *renderer,
const TimelineRenderState *parentState,
State *oldState, int firstIndex,
int lastIndex, bool stateChanged,
qreal spacing) const
{
Q_UNUSED(firstIndex);
Q_UNUSED(lastIndex);
Q_UNUSED(spacing);
const TimelineNotesModel *notes = renderer->notes();
const TimelineModel *model = renderer->model();
if (!model || !notes)
return oldState;
TimelineNotesRenderPassState *state;
if (oldState == 0) {
state = new TimelineNotesRenderPassState(model->expandedRowCount());
} else {
if (!stateChanged && !renderer->notesDirty())
return oldState;
state = static_cast<TimelineNotesRenderPassState *>(oldState);
}
QVector<QVector<int> > expanded(model->expandedRowCount());
QVector<int> collapsed;
for (int i = 0; i < qMin(notes->count(), NotesGeometry::maxNotes); ++i) {
if (notes->timelineModel(i) != model->modelId())
continue;
int timelineIndex = notes->timelineIndex(i);
if (model->startTime(timelineIndex) > parentState->end() ||
model->endTime(timelineIndex) < parentState->start())
continue;
expanded[model->expandedRow(timelineIndex)] << timelineIndex;
collapsed << timelineIndex;
}
QSGGeometryNode *collapsedNode = state->m_collapsedOverlay;
if (collapsed.count() > 0) {
collapsedNode->setGeometry(NotesGeometry::createGeometry(collapsed, model, parentState,
true));
collapsedNode->setFlag(QSGGeometryNode::OwnsGeometry, true);
} else {
collapsedNode->setGeometry(&state->nullGeometry);
collapsedNode->setFlag(QSGGeometryNode::OwnsGeometry, false);
}
for (int row = 0; row < model->expandedRowCount(); ++row) {
QSGGeometryNode *rowNode = static_cast<QSGGeometryNode *>(state->m_expandedRows[row]);
if (expanded[row].isEmpty()) {
rowNode->setGeometry(&state->nullGeometry);
rowNode->setFlag(QSGGeometryNode::OwnsGeometry, false);
} else {
rowNode->setGeometry(NotesGeometry::createGeometry(expanded[row], model, parentState,
false));
collapsedNode->setFlag(QSGGeometryNode::OwnsGeometry, true);
}
}
return state;
}
TimelineNotesRenderPassState::TimelineNotesRenderPassState(int numExpandedRows) :
nullGeometry(NotesGeometry::point2DWithDistanceFromTop(), 0)
{
material.setFlag(QSGMaterial::Blending, true);
m_expandedRows.reserve(numExpandedRows);
for (int i = 0; i < numExpandedRows; ++i)
m_expandedRows << createNode();
m_collapsedOverlay = createNode();
}
QSGGeometryNode *TimelineNotesRenderPassState::createNode()
{
QSGGeometryNode *node = new QSGGeometryNode;
node->setGeometry(&nullGeometry);
node->setMaterial(&material);
return node;
}
QSGGeometry *NotesGeometry::createGeometry(QVector<int> &ids, const TimelineModel *model,
const TimelineRenderState *parentState, bool collapsed)
{
float rowHeight = TimelineModel::defaultRowHeight();
QSGGeometry *geometry = new QSGGeometry(point2DWithDistanceFromTop(),
ids.count() * 2);
geometry->setDrawingMode(GL_LINES);
geometry->setLineWidth(3);
Point2DWithDistanceFromTop *v =
static_cast<Point2DWithDistanceFromTop *>(geometry->vertexData());
for (int i = 0; i < ids.count(); ++i) {
int timelineIndex = ids[i];
float horizontalCenter = ((model->startTime(timelineIndex) +
model->endTime(timelineIndex)) / (qint64)2 -
parentState->start()) * parentState->scale();
float verticalStart = (collapsed ? (model->collapsedRow(timelineIndex) + 0.1) : 0.1) *
rowHeight;
float verticalEnd = verticalStart + 0.8 * rowHeight;
v[i * 2].set(horizontalCenter, verticalStart, 0);
v[i * 2 + 1].set(horizontalCenter, verticalEnd, 1);
}
return geometry;
}
class NotesMaterialShader : public QSGMaterialShader
{
public:
NotesMaterialShader();
virtual void updateState(const RenderState &state, QSGMaterial *newEffect,
QSGMaterial *oldEffect);
virtual char const *const *attributeNames() const;
private:
virtual void initialize();
int m_matrix_id;
int m_z_range_id;
};
NotesMaterialShader::NotesMaterialShader()
: QSGMaterialShader()
{
setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/qmlprofiler/notes.vert"));
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/qmlprofiler/notes.frag"));
}
void NotesMaterialShader::updateState(const RenderState &state, QSGMaterial *, QSGMaterial *)
{
if (state.isMatrixDirty()) {
program()->setUniformValue(m_matrix_id, state.combinedMatrix());
program()->setUniformValue(m_z_range_id, GLfloat(1.0));
}
}
char const *const *NotesMaterialShader::attributeNames() const
{
static const char *const attr[] = {"vertexCoord", "distanceFromTop", 0};
return attr;
}
void NotesMaterialShader::initialize()
{
m_matrix_id = program()->uniformLocation("matrix");
m_z_range_id = program()->uniformLocation("_qt_zRange");
}
QSGMaterialType *NotesMaterial::type() const
{
static QSGMaterialType type;
return &type;
}
QSGMaterialShader *NotesMaterial::createShader() const
{
return new NotesMaterialShader;
}
void Point2DWithDistanceFromTop::set(float nx, float ny, float nd)
{
x = nx; y = ny; d = nd;
}
} // namespace Timeline

View File

@@ -1,55 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINENOTESRENDERPASS_H
#define TIMELINENOTESRENDERPASS_H
#include "timelineabstractrenderer.h"
#include <QSGMaterial>
namespace Timeline {
class TimelineNotesRenderPass : public TimelineRenderPass
{
public:
static const TimelineNotesRenderPass *instance();
State *update(const TimelineAbstractRenderer *renderer, const TimelineRenderState *parentState,
State *oldState, int firstIndex, int lastIndex, bool stateChanged,
qreal spacing) const;
private:
TimelineNotesRenderPass();
};
} // namespace Timeline
#endif // TIMELINENOTESRENDERPASS_H

View File

@@ -1,91 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "timelineoverviewrenderer_p.h"
#include "timelinerenderstate.h"
namespace Timeline {
TimelineOverviewRenderer::TimelineOverviewRenderer(QQuickItem *parent) :
TimelineAbstractRenderer(*(new TimelineOverviewRendererPrivate), parent)
{
Q_D(TimelineOverviewRenderer);
setFlag(QQuickItem::ItemHasContents);
d->renderState = 0;
}
TimelineOverviewRenderer::~TimelineOverviewRenderer()
{
Q_D(TimelineOverviewRenderer);
delete d->renderState;
delete d;
}
QSGNode *TimelineOverviewRenderer::updatePaintNode(QSGNode *oldNode,
UpdatePaintNodeData *updatePaintNodeData)
{
Q_D(TimelineOverviewRenderer);
Q_UNUSED(updatePaintNodeData)
if (d->modelDirty) {
delete d->renderState;
d->renderState = 0;
d->modelDirty = false;
}
if (d->renderState == 0) {
d->renderState = new TimelineRenderState(d->zoomer->traceStart(), d->zoomer->traceEnd(),
1.0, d->renderPasses.size());
}
qreal xSpacing = width() / d->zoomer->traceDuration();
qreal ySpacing = height() / (d->model->collapsedRowCount() * TimelineModel::defaultRowHeight());
for (int i = 0; i < d->renderPasses.length(); ++i) {
d->renderState->setPassState(i, d->renderPasses[i]->update(this, d->renderState,
d->renderState->passState(i),
0, d->model->count(), true,
xSpacing));
}
if (d->renderState->isEmpty())
d->renderState->assembleNodeTree(d->model, d->model->height(), 0);
d->modelDirty = false;
d->notesDirty = false;
d->rowHeightsDirty = false;
QMatrix4x4 matrix;
matrix.scale(xSpacing, ySpacing, 1);
return d->renderState->finalize(oldNode, false, matrix);
}
}

View File

@@ -1,55 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINEOVERVIEWRENDERER_H
#define TIMELINEOVERVIEWRENDERER_H
#include "timelineabstractrenderer.h"
namespace Timeline {
class TimelineOverviewRenderer : public TimelineAbstractRenderer
{
public:
TimelineOverviewRenderer(QQuickItem *parent = 0);
~TimelineOverviewRenderer();
protected:
virtual QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData);
class TimelineOverviewRendererPrivate;
Q_DECLARE_PRIVATE(TimelineOverviewRenderer)
};
} // namespace Timeline
QML_DECLARE_TYPE(Timeline::TimelineOverviewRenderer)
#endif // TIMELINEOVERVIEWRENDERER_H

View File

@@ -1,49 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINEOVERVIEWRENDERER_P_H
#define TIMELINEOVERVIEWRENDERER_P_H
#include "timelineoverviewrenderer.h"
#include "timelineabstractrenderer_p.h"
namespace Timeline {
class TimelineOverviewRenderer::TimelineOverviewRendererPrivate :
public TimelineAbstractRenderer::TimelineAbstractRendererPrivate
{
public:
TimelineRenderState *renderState;
};
} // namespace Timeline
#endif // TIMELINEOVERVIEWRENDERER_P_H

View File

@@ -1,307 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "timelinerenderer_p.h"
#include "timelinerenderpass.h"
#include "qmlprofilernotesmodel.h"
#include "timelineitemsrenderpass.h"
#include "qmlprofilerbindingloopsrenderpass.h"
#include "timelineselectionrenderpass.h"
#include "timelinenotesrenderpass.h"
#include <QElapsedTimer>
#include <QQmlContext>
#include <QQmlProperty>
#include <QTimer>
#include <QPixmap>
#include <QGraphicsSceneMouseEvent>
#include <QVarLengthArray>
#include <QSGTransformNode>
#include <QSGSimpleRectNode>
#include <math.h>
namespace Timeline {
TimelineRenderer::TimelineRendererPrivate::TimelineRendererPrivate(TimelineRenderer *q) :
lastState(0), q_ptr(q)
{
resetCurrentSelection();
}
TimelineRenderer::TimelineRenderer(QQuickItem *parent) :
TimelineAbstractRenderer(*(new TimelineRendererPrivate(this)), parent)
{
setFlag(QQuickItem::ItemHasContents);
setAcceptedMouseButtons(Qt::LeftButton);
setAcceptHoverEvents(true);
}
void TimelineRenderer::TimelineRendererPrivate::resetCurrentSelection()
{
currentSelection.startTime = -1;
currentSelection.endTime = -1;
currentSelection.row = -1;
currentSelection.eventIndex = -1;
}
TimelineRenderState *TimelineRenderer::TimelineRendererPrivate::findRenderState()
{
int newLevel = 0;
int newOffset = 0;
int level;
int offset;
qint64 newStart = zoomer->traceStart();
qint64 newEnd = zoomer->traceEnd();
qint64 start;
qint64 end;
do {
level = newLevel;
offset = newOffset;
start = newStart;
end = newEnd;
newLevel = level + 1;
qint64 range = zoomer->traceDuration() >> newLevel;
newOffset = (zoomer->windowStart() - zoomer->traceStart() + range / 2) / range;
newStart = zoomer->traceStart() + newOffset * range - range / 2;
newEnd = newStart + range;
} while (newStart < zoomer->windowStart() && newEnd > zoomer->windowEnd());
if (renderStates.length() <= level)
renderStates.resize(level + 1);
if (renderStates[level].length() <= offset)
renderStates[level].resize(offset + 1);
TimelineRenderState *state = renderStates[level][offset];
if (state == 0) {
state = new TimelineRenderState(start, end, 1.0 / static_cast<qreal>(SafeFloatMax),
renderPasses.size());
renderStates[level][offset] = state;
}
return state;
}
QSGNode *TimelineRenderer::updatePaintNode(QSGNode *node, UpdatePaintNodeData *updatePaintNodeData)
{
Q_D(TimelineRenderer);
Q_UNUSED(updatePaintNodeData)
if (!d->model || d->model->hidden() || d->model->isEmpty() ||
d->zoomer->windowDuration() <= 0) {
delete node;
return 0;
}
qreal spacing = width() / d->zoomer->windowDuration();
if (d->modelDirty) {
if (node)
node->removeAllChildNodes();
foreach (QVector<TimelineRenderState *> stateVector, d->renderStates)
qDeleteAll(stateVector);
d->renderStates.clear();
d->lastState = 0;
}
TimelineRenderState *state = d->findRenderState();
int lastIndex = d->model->lastIndex(d->zoomer->windowEnd());
int firstIndex = d->model->firstIndex(d->zoomer->windowStart());
for (int i = 0; i < d->renderPasses.length(); ++i)
state->setPassState(i, d->renderPasses[i]->update(this, state, state->passState(i),
firstIndex, lastIndex + 1,
state != d->lastState, spacing));
if (state->isEmpty()) { // new state
state->assembleNodeTree(d->model, TimelineModel::defaultRowHeight(),
TimelineModel::defaultRowHeight());
} else if (d->rowHeightsDirty || state != d->lastState) {
state->updateExpandedRowHeights(d->model, TimelineModel::defaultRowHeight(),
TimelineModel::defaultRowHeight());
}
d->modelDirty = false;
d->notesDirty = false;
d->rowHeightsDirty = false;
d->lastState = state;
QMatrix4x4 matrix;
matrix.translate((state->start() - d->zoomer->windowStart()) * spacing, 0, 0);
matrix.scale(spacing / state->scale(), 1, 1);
return state->finalize(node, d->model->expanded(), matrix);
}
void TimelineRenderer::mousePressEvent(QMouseEvent *event)
{
Q_UNUSED(event);
}
int TimelineRenderer::TimelineRendererPrivate::rowFromPosition(int y) const
{
if (!model->expanded())
return y / TimelineModel::defaultRowHeight();
int ret = 0;
for (int row = 0; row < model->expandedRowCount(); ++row) {
y -= model->expandedRowHeight(row);
if (y <= 0) return ret;
++ret;
}
return ret;
}
void TimelineRenderer::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(TimelineRenderer);
Q_UNUSED(event);
if (!d->model->isEmpty())
d->manageClicked();
}
void TimelineRenderer::mouseMoveEvent(QMouseEvent *event)
{
event->setAccepted(false);
}
void TimelineRenderer::hoverMoveEvent(QHoverEvent *event)
{
Q_D(TimelineRenderer);
Q_UNUSED(event);
d->manageHovered(event->pos().x(), event->pos().y());
if (d->currentSelection.eventIndex == -1)
event->setAccepted(false);
}
void TimelineRenderer::TimelineRendererPrivate::manageClicked()
{
Q_Q(TimelineRenderer);
if (currentSelection.eventIndex != -1) {
if (currentSelection.eventIndex == selectedItem)
q->setSelectionLocked(!selectionLocked);
else
q->setSelectionLocked(true);
// itemPressed() will trigger an update of the events and JavaScript views. Make sure the
// correct event is already selected when that happens, to prevent confusion.
q->setSelectedItem(currentSelection.eventIndex);
emit q->itemPressed(currentSelection.eventIndex);
} else {
q->setSelectionLocked(false);
q->setSelectedItem(-1);
emit q->itemPressed(-1);
}
}
void TimelineRenderer::TimelineRendererPrivate::manageHovered(int mouseX, int mouseY)
{
Q_Q(TimelineRenderer);
qint64 duration = zoomer->windowDuration();
if (duration <= 0)
return;
// Make the "selected" area 3 pixels wide by adding/subtracting 1 to catch very narrow events.
qint64 startTime = (mouseX - 1) * duration / q->width() + zoomer->windowStart();
qint64 endTime = (mouseX + 1) * duration / q->width() + zoomer->windowStart();
qint64 exactTime = (startTime + endTime) / 2;
int row = rowFromPosition(mouseY);
// already covered? Only recheck selectionLocked and make sure d->selectedItem is correct.
if (currentSelection.eventIndex != -1 &&
exactTime >= currentSelection.startTime &&
exactTime < currentSelection.endTime &&
row == currentSelection.row) {
if (!selectionLocked)
q->setSelectedItem(currentSelection.eventIndex);
return;
}
// find if there's items in the time range
int eventFrom = model->firstIndex(startTime);
int eventTo = model->lastIndex(endTime);
currentSelection.eventIndex = -1;
if (eventFrom == -1 || eventTo < eventFrom || eventTo >= model->count())
return;
// find if we are in the right column
qint64 bestOffset = std::numeric_limits<qint64>::max();
for (int i=eventTo; i>=eventFrom; --i) {
if (model->row(i) == row) {
// There can be small events that don't reach the cursor position after large events
// that do but are in a different row.
qint64 itemEnd = model->endTime(i);
if (itemEnd < startTime)
continue;
qint64 itemStart = model->startTime(i);
qint64 offset = qAbs(itemEnd - exactTime) + qAbs(itemStart - exactTime);
if (offset < bestOffset) {
// match
currentSelection.eventIndex = i;
currentSelection.startTime = itemStart;
currentSelection.endTime = itemEnd;
currentSelection.row = row;
bestOffset = offset;
}
}
}
if (!selectionLocked && currentSelection.eventIndex != -1)
q->setSelectedItem(currentSelection.eventIndex);
}
void TimelineRenderer::clearData()
{
Q_D(TimelineRenderer);
d->resetCurrentSelection();
setSelectedItem(-1);
setSelectionLocked(true);
}
void TimelineRenderer::selectNextFromSelectionId(int selectionId)
{
Q_D(TimelineRenderer);
setSelectedItem(d->model->nextItemBySelectionId(selectionId, d->zoomer->rangeStart(),
d->selectedItem));
}
void TimelineRenderer::selectPrevFromSelectionId(int selectionId)
{
Q_D(TimelineRenderer);
setSelectedItem(d->model->prevItemBySelectionId(selectionId, d->zoomer->rangeStart(),
d->selectedItem));
}
} // namespace Timeline

View File

@@ -1,81 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINERENDERER_H
#define TIMELINERENDERER_H
#include <QSGTransformNode>
#include <QQuickItem>
#include "timelinezoomcontrol.h"
#include "timelinemodel.h"
#include "timelinenotesmodel.h"
#include "timelineabstractrenderer.h"
namespace Timeline {
class TimelineRenderPass;
class TimelineRenderState;
class TimelineRenderer : public TimelineAbstractRenderer
{
Q_OBJECT
public:
explicit TimelineRenderer(QQuickItem *parent = 0);
Q_INVOKABLE void selectNextFromSelectionId(int selectionId);
Q_INVOKABLE void selectPrevFromSelectionId(int selectionId);
// TODO: We could add some Q_INVOKABLE functions to enable or disable render passes when the the
// need arises.
signals:
void itemPressed(int pressedItem);
public slots:
void clearData();
protected:
virtual QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData);
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
virtual void mouseMoveEvent(QMouseEvent *event);
virtual void hoverMoveEvent(QHoverEvent *event);
private:
class TimelineRendererPrivate;
Q_DECLARE_PRIVATE(TimelineRenderer)
};
} // namespace Timeline
QML_DECLARE_TYPE(Timeline::TimelineRenderer)
#endif // TIMELINERENDERER_H

View File

@@ -1,73 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINERENDERER_P_H
#define TIMELINERENDERER_P_H
#include "timelinerenderer.h"
#include "timelineabstractrenderer_p.h"
namespace Timeline {
class TimelineRenderer::TimelineRendererPrivate :
TimelineAbstractRenderer::TimelineAbstractRendererPrivate {
public:
TimelineRendererPrivate(TimelineRenderer *q);
int rowFromPosition(int y) const;
void manageClicked();
void manageHovered(int mouseX, int mouseY);
static const int SafeFloatMax = 1 << 12;
void resetCurrentSelection();
TimelineRenderState *findRenderState();
struct {
qint64 startTime;
qint64 endTime;
int row;
int eventIndex;
} currentSelection;
QVector<QVector<TimelineRenderState *> > renderStates;
TimelineRenderState *lastState;
private:
TimelineRenderer *q_ptr;
Q_DECLARE_PUBLIC(TimelineRenderer)
};
} // namespace Timeline
#endif // TIMELINERENDERER_P_H

View File

@@ -1,59 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "timelinerenderpass.h"
namespace Timeline {
const QVector<QSGNode *> &TimelineRenderPass::State::expandedRows() const
{
static const QVector<QSGNode *> empty;
return empty;
}
const QVector<QSGNode *> &TimelineRenderPass::State::collapsedRows() const
{
static const QVector<QSGNode *> empty;
return empty;
}
QSGNode *TimelineRenderPass::State::expandedOverlay() const
{
return 0;
}
QSGNode *TimelineRenderPass::State::collapsedOverlay() const
{
return 0;
}
TimelineRenderPass::~TimelineRenderPass() {}
} // namespace Timeline

View File

@@ -1,61 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINERENDERPASS_H
#define TIMELINERENDERPASS_H
#include <QVector>
QT_FORWARD_DECLARE_CLASS(QSGNode)
namespace Timeline {
class TimelineAbstractRenderer;
class TimelineRenderState;
class TimelineRenderPass {
public:
class State {
public:
virtual const QVector<QSGNode *> &expandedRows() const;
virtual const QVector<QSGNode *> &collapsedRows() const;
virtual QSGNode *expandedOverlay() const;
virtual QSGNode *collapsedOverlay() const;
};
virtual ~TimelineRenderPass();
virtual State *update(const TimelineAbstractRenderer *renderer,
const TimelineRenderState *parentState,
State *state, int indexFrom, int indexTo, bool stateChanged,
qreal spacing) const = 0;
};
} // namespace Timeline
#endif // TIMELINERENDERPASS_H

View File

@@ -1,247 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "timelinerenderstate_p.h"
namespace Timeline {
TimelineRenderState::TimelineRenderState(qint64 start, qint64 end, qreal scale, int numPasses) :
d_ptr(new TimelineRenderStatePrivate)
{
Q_D(TimelineRenderState);
d->expandedRowRoot = new QSGNode;
d->collapsedRowRoot = new QSGNode;
d->expandedOverlayRoot = new QSGNode;
d->collapsedOverlayRoot = new QSGNode;
d->start = start;
d->end = end;
d->scale = scale;
d->passes.resize(numPasses);
d->expandedRowRoot->setFlag(QSGNode::OwnedByParent, false);
d->collapsedRowRoot->setFlag(QSGNode::OwnedByParent, false);
d->expandedOverlayRoot->setFlag(QSGNode::OwnedByParent, false);
d->collapsedOverlayRoot->setFlag(QSGNode::OwnedByParent, false);
}
TimelineRenderState::~TimelineRenderState()
{
Q_D(TimelineRenderState);
delete d->expandedRowRoot;
delete d->collapsedRowRoot;
delete d->expandedOverlayRoot;
delete d->collapsedOverlayRoot;
delete d;
}
qint64 TimelineRenderState::start() const
{
Q_D(const TimelineRenderState);
return d->start;
}
qint64 TimelineRenderState::end() const
{
Q_D(const TimelineRenderState);
return d->end;
}
qreal TimelineRenderState::scale() const
{
Q_D(const TimelineRenderState);
return d->scale;
}
const QSGNode *TimelineRenderState::expandedRowRoot() const
{
Q_D(const TimelineRenderState);
return d->expandedRowRoot;
}
const QSGNode *TimelineRenderState::collapsedRowRoot() const
{
Q_D(const TimelineRenderState);
return d->collapsedRowRoot;
}
const QSGNode *TimelineRenderState::expandedOverlayRoot() const
{
Q_D(const TimelineRenderState);
return d->expandedOverlayRoot;
}
const QSGNode *TimelineRenderState::collapsedOverlayRoot() const
{
Q_D(const TimelineRenderState);
return d->collapsedOverlayRoot;
}
QSGNode *TimelineRenderState::expandedRowRoot()
{
Q_D(TimelineRenderState);
return d->expandedRowRoot;
}
QSGNode *TimelineRenderState::collapsedRowRoot()
{
Q_D(TimelineRenderState);
return d->collapsedRowRoot;
}
QSGNode *TimelineRenderState::expandedOverlayRoot()
{
Q_D(TimelineRenderState);
return d->expandedOverlayRoot;
}
QSGNode *TimelineRenderState::collapsedOverlayRoot()
{
Q_D(TimelineRenderState);
return d->collapsedOverlayRoot;
}
bool TimelineRenderState::isEmpty() const
{
Q_D(const TimelineRenderState);
return d->collapsedRowRoot->childCount() == 0 && d->expandedRowRoot->childCount() == 0 &&
d->collapsedOverlayRoot->childCount() == 0 && d->expandedOverlayRoot->childCount() == 0;
}
void TimelineRenderState::assembleNodeTree(const TimelineModel *model, int defaultRowHeight,
int defaultRowOffset)
{
Q_D(TimelineRenderState);
for (int pass = 0; pass < d->passes.length(); ++pass) {
const TimelineRenderPass::State *passState = d->passes[pass];
if (!passState)
continue;
if (passState->expandedOverlay())
d->expandedOverlayRoot->appendChildNode(passState->expandedOverlay());
if (passState->collapsedOverlay())
d->collapsedOverlayRoot->appendChildNode(passState->collapsedOverlay());
}
int row = 0;
for (int i = 0; i < model->expandedRowCount(); ++i) {
QSGTransformNode *rowNode = new QSGTransformNode;
for (int pass = 0; pass < d->passes.length(); ++pass) {
const TimelineRenderPass::State *passState = d->passes[pass];
if (!passState)
continue;
const QVector<QSGNode *> &rows = passState->expandedRows();
if (rows.length() > row) {
QSGNode *rowChildNode = rows[row];
if (rowChildNode)
rowNode->appendChildNode(rowChildNode);
}
}
d->expandedRowRoot->appendChildNode(rowNode);
++row;
}
for (int row = 0; row < model->collapsedRowCount(); ++row) {
QSGTransformNode *rowNode = new QSGTransformNode;
QMatrix4x4 matrix;
matrix.translate(0, row * defaultRowOffset, 0);
matrix.scale(1.0, static_cast<float>(defaultRowHeight) /
static_cast<float>(TimelineModel::defaultRowHeight()), 1.0);
rowNode->setMatrix(matrix);
for (int pass = 0; pass < d->passes.length(); ++pass) {
const TimelineRenderPass::State *passState = d->passes[pass];
if (!passState)
continue;
const QVector<QSGNode *> &rows = passState->collapsedRows();
if (rows.length() > row) {
QSGNode *rowChildNode = rows[row];
if (rowChildNode)
rowNode->appendChildNode(rowChildNode);
}
}
d->collapsedRowRoot->appendChildNode(rowNode);
}
updateExpandedRowHeights(model, defaultRowHeight, defaultRowOffset);
}
void TimelineRenderState::updateExpandedRowHeights(const TimelineModel *model, int defaultRowHeight,
int defaultRowOffset)
{
Q_D(TimelineRenderState);
int row = 0;
qreal offset = 0;
for (QSGNode *rowNode = d->expandedRowRoot->firstChild(); rowNode != 0;
rowNode = rowNode->nextSibling()) {
qreal rowHeight = model->expandedRowHeight(row++);
QMatrix4x4 matrix;
matrix.translate(0, offset, 0);
matrix.scale(1, rowHeight / defaultRowHeight, 1);
offset += defaultRowOffset * rowHeight / defaultRowHeight;
static_cast<QSGTransformNode *>(rowNode)->setMatrix(matrix);
}
}
QSGTransformNode *TimelineRenderState::finalize(QSGNode *oldNode, bool expanded,
const QMatrix4x4 &transform)
{
Q_D(TimelineRenderState);
QSGNode *rowNode = expanded ? d->expandedRowRoot : d->collapsedRowRoot;
QSGNode *overlayNode = expanded ?d->expandedOverlayRoot : d->collapsedOverlayRoot;
QSGTransformNode *node = oldNode ? static_cast<QSGTransformNode *>(oldNode) :
new QSGTransformNode;
node->setMatrix(transform);
if (node->firstChild() != rowNode || node->lastChild() != overlayNode) {
node->removeAllChildNodes();
node->appendChildNode(rowNode);
node->appendChildNode(overlayNode);
}
return node;
}
TimelineRenderPass::State *TimelineRenderState::passState(int i)
{
Q_D(TimelineRenderState);
return d->passes[i];
}
const TimelineRenderPass::State *TimelineRenderState::passState(int i) const
{
Q_D(const TimelineRenderState);
return d->passes[i];
}
void TimelineRenderState::setPassState(int i, TimelineRenderPass::State *state)
{
Q_D(TimelineRenderState);
d->passes[i] = state;
}
} // namespace Timeline

View File

@@ -1,77 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINERENDERSTATE_H
#define TIMELINERENDERSTATE_H
#include <QSGNode>
#include "timelinerenderpass.h"
#include "timelinemodel.h"
namespace Timeline {
class TimelineRenderState {
public:
TimelineRenderState(qint64 start, qint64 end, qreal scale, int numPasses);
~TimelineRenderState();
qint64 start() const;
qint64 end() const;
qreal scale() const;
TimelineRenderPass::State *passState(int i);
const TimelineRenderPass::State *passState(int i) const;
void setPassState(int i, TimelineRenderPass::State *state);
const QSGNode *expandedRowRoot() const;
const QSGNode *collapsedRowRoot() const;
const QSGNode *expandedOverlayRoot() const;
const QSGNode *collapsedOverlayRoot() const;
QSGNode *expandedRowRoot();
QSGNode *collapsedRowRoot();
QSGNode *expandedOverlayRoot();
QSGNode *collapsedOverlayRoot();
bool isEmpty() const;
void assembleNodeTree(const TimelineModel *model, int defaultRowHeight, int defaultRowOffset);
void updateExpandedRowHeights(const TimelineModel *model, int defaultRowHeight,
int defaultRowOffset);
QSGTransformNode *finalize(QSGNode *oldNode, bool expanded, const QMatrix4x4 &transform);
private:
class TimelineRenderStatePrivate;
TimelineRenderStatePrivate *d_ptr;
Q_DECLARE_PRIVATE(TimelineRenderState)
};
} // namespace Timeline
#endif // TIMELINERENDERSTATE_H

View File

@@ -1,56 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINERENDERSTATE_P_H
#define TIMELINERENDERSTATE_P_H
#include "timelinerenderstate.h"
namespace Timeline {
class TimelineRenderState::TimelineRenderStatePrivate {
public:
QSGNode *expandedRowRoot;
QSGNode *collapsedRowRoot;
QSGNode *expandedOverlayRoot;
QSGNode *collapsedOverlayRoot;
qint64 start;
qint64 end;
qreal scale; // "native" scale, this stays the same through the life time of a state
QVector<TimelineRenderPass::State *> passes;
};
} // namespace Timeline
#endif // TIMELINERENDERSTATE_P_H

View File

@@ -1,150 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "timelineselectionrenderpass.h"
#include <QtMath>
#include <QSGSimpleRectNode>
namespace Timeline {
QSGSimpleRectNode *createSelectionNode()
{
QSGSimpleRectNode *selectionNode = new QSGSimpleRectNode;
selectionNode->material()->setFlag(QSGMaterial::Blending, false);
selectionNode->setRect(0, 0, 0, 0);
QSGSimpleRectNode *selectionChild = new QSGSimpleRectNode;
selectionChild->material()->setFlag(QSGMaterial::Blending, false);
selectionChild->setRect(0, 0, 0, 0);
selectionNode->appendChildNode(selectionChild);
return selectionNode;
}
struct TimelineSelectionRenderPassState : public TimelineRenderPass::State {
QSGSimpleRectNode *m_expandedOverlay;
QSGSimpleRectNode *m_collapsedOverlay;
QSGNode *expandedOverlay() const { return m_expandedOverlay; }
QSGNode *collapsedOverlay() const { return m_collapsedOverlay; }
};
TimelineRenderPass::State *TimelineSelectionRenderPass::update(
const TimelineAbstractRenderer *renderer, const TimelineRenderState *parentState,
State *oldState, int firstIndex, int lastIndex, bool stateChanged, qreal spacing) const
{
Q_UNUSED(stateChanged);
const TimelineModel *model = renderer->model();
if (!model)
return oldState;
TimelineSelectionRenderPassState *state;
if (oldState == 0) {
state = new TimelineSelectionRenderPassState;
state->m_expandedOverlay = createSelectionNode();
state->m_collapsedOverlay = createSelectionNode();
} else {
state = static_cast<TimelineSelectionRenderPassState *>(oldState);
}
QSGSimpleRectNode *selectionNode = static_cast<QSGSimpleRectNode *>(model->expanded() ?
state->m_expandedOverlay :
state->m_collapsedOverlay);
QSGSimpleRectNode *child = static_cast<QSGSimpleRectNode *>(selectionNode->firstChild());
int selectedItem = renderer->selectedItem();
if (selectedItem != -1 && selectedItem >= firstIndex && selectedItem < lastIndex) {
qreal top = 0;
qreal height = 0;
if (model->expanded()) {
int row = model->expandedRow(selectedItem);
int rowHeight = model->expandedRowHeight(row);
height = rowHeight * model->relativeHeight(selectedItem);
top = model->expandedRowOffset(row) - height + rowHeight;
} else {
int row = model->collapsedRow(selectedItem);
height = TimelineModel::defaultRowHeight() * model->relativeHeight(selectedItem);
top = TimelineModel::defaultRowHeight() * (row + 1) - height;
}
qreal left = qMax(model->startTime(selectedItem) - parentState->start(), (qint64)0);
qreal right = qMin(parentState->end() - parentState->start(),
model->endTime(selectedItem) - parentState->start());
// Construct from upper left and lower right for better precision. When constructing from
// left and width the error on the left border is inherited by the right border. Like this
// they're independent.
QRectF outer(QPointF(qFloor(left * parentState->scale()), top),
QPointF(qCeil(right * parentState->scale()), top + height));
float scaleConversion = parentState->scale() / spacing;
float missing = 3.0 - outer.width() / scaleConversion;
if (missing > 0.0) {
outer.setLeft(outer.left() - missing * scaleConversion / 2.0);
outer.setRight(outer.right() + missing * scaleConversion / 2.0);
}
missing = 3.0 - outer.height();
if (missing > 0.0)
outer.setTop(outer.top() - missing);
selectionNode->setRect(outer);
selectionNode->setColor(renderer->selectionLocked() ? QColor(96,0,255) : Qt::blue);
float childWidthThreshold = 6.0 * scaleConversion;
if (outer.width() > childWidthThreshold && outer.height() > 6.0) {
// Construct from upper left and lower right for better precision
child->setRect(QRectF(QPointF(outer.left() + childWidthThreshold / 2.0,
outer.top() + 3.0),
QPointF(outer.right() - childWidthThreshold / 2.0,
outer.bottom() - 3.0)));
child->setColor(model->color(selectedItem));
} else {
child->setRect(0, 0, 0, 0);
}
} else {
selectionNode->setRect(0, 0, 0, 0);
child->setRect(0, 0, 0, 0);
}
return state;
}
const TimelineSelectionRenderPass *TimelineSelectionRenderPass::instance()
{
static const TimelineSelectionRenderPass pass;
return &pass;
}
TimelineSelectionRenderPass::TimelineSelectionRenderPass()
{
}
} // namespace Timeline

View File

@@ -1,56 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINESELECTIONRENDERPASS_H
#define TIMELINESELECTIONRENDERPASS_H
#include "timelineabstractrenderer.h"
#include "timelinerenderpass.h"
#include "timelinerenderstate.h"
namespace Timeline {
class TimelineSelectionRenderPass : public TimelineRenderPass
{
public:
static const TimelineSelectionRenderPass *instance();
State *update(const TimelineAbstractRenderer *renderer, const TimelineRenderState *parentState,
State *state, int firstIndex, int lastIndex, bool stateChanged,
qreal spacing) const;
protected:
TimelineSelectionRenderPass();
};
} // namespace Timeline
#endif // TIMELINESELECTIONRENDERPASS_H

View File

@@ -1,173 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, 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, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "timelinezoomcontrol.h"
namespace Timeline {
TimelineZoomControl::TimelineZoomControl(QObject *parent) : QObject(parent), m_traceStart(-1), m_traceEnd(-1),
m_windowStart(-1), m_windowEnd(-1), m_rangeStart(-1), m_rangeEnd(-1), m_windowLocked(false)
{
connect(&m_timer, SIGNAL(timeout()), this, SLOT(moveWindow()));
}
void TimelineZoomControl::clear()
{
m_timer.stop();
setWindowLocked(false);
setRange(-1, -1);
setTrace(-1, -1);
}
void TimelineZoomControl::setTraceStart(qint64 start)
{
if (start != m_traceStart) {
if (m_traceEnd < start)
m_traceEnd = start;
m_traceStart = start;
emit traceChanged(start, m_traceEnd);
rebuildWindow();
}
}
void TimelineZoomControl::setTraceEnd(qint64 end)
{
if (end != m_traceEnd) {
if (m_traceStart > end)
m_traceStart = end;
m_traceEnd = end;
emit traceChanged(m_traceStart, end);
rebuildWindow();
}
}
void TimelineZoomControl::setTrace(qint64 start, qint64 end)
{
Q_ASSERT(start <= end);
if (start != m_traceStart || end != m_traceEnd) {
m_traceStart = start;
m_traceEnd = end;
emit traceChanged(start, end);
rebuildWindow();
}
}
void TimelineZoomControl::setRange(qint64 start, qint64 end)
{
Q_ASSERT(start <= end);
if (m_rangeStart != start || m_rangeEnd != end) {
m_timer.stop();
m_rangeStart = start;
m_rangeEnd = end;
rebuildWindow();
emit rangeChanged(start, end);
}
}
void TimelineZoomControl::setWindowLocked(bool windowLocked)
{
if (windowLocked != m_windowLocked) {
m_windowLocked = windowLocked;
emit windowLockedChanged(windowLocked);
}
}
void TimelineZoomControl::rebuildWindow()
{
qint64 minDuration = 1; // qMax needs equal data types, so literal 1 won't do
qint64 shownDuration = qMax(rangeDuration(), minDuration);
qint64 oldWindowStart = m_windowStart;
qint64 oldWindowEnd = m_windowEnd;
if (traceDuration() / shownDuration < MAX_ZOOM_FACTOR) {
m_windowStart = m_traceStart;
m_windowEnd = m_traceEnd;
} else if (windowDuration() / shownDuration > MAX_ZOOM_FACTOR ||
windowDuration() / shownDuration * 2 < MAX_ZOOM_FACTOR) {
qint64 keep = shownDuration * MAX_ZOOM_FACTOR / 2 - shownDuration;
m_windowStart = m_rangeStart - keep;
if (m_windowStart < m_traceStart) {
keep += m_traceStart - m_windowStart;
m_windowStart = m_traceStart;
}
m_windowEnd = m_rangeEnd + keep;
if (m_windowEnd > m_traceEnd) {
m_windowStart = qMax(m_traceStart, m_windowStart - m_windowEnd - m_traceEnd);
m_windowEnd = m_traceEnd;
}
} else {
m_timer.start(500);
}
if (oldWindowStart != m_windowStart || oldWindowEnd != m_windowEnd) {
clampRangeToWindow();
emit windowChanged(m_windowStart, m_windowEnd);
}
}
void TimelineZoomControl::moveWindow()
{
if (m_windowLocked)
return;
m_timer.stop();
qint64 offset = (m_rangeEnd - m_windowEnd + m_rangeStart - m_windowStart) / 2;
if (offset == 0 || (offset < 0 && m_windowStart == m_traceStart) ||
(offset > 0 && m_windowEnd == m_traceEnd)) {
return;
} else if (offset > rangeDuration()) {
offset = (offset + rangeDuration()) / 2;
} else if (offset < -rangeDuration()) {
offset = (offset - rangeDuration()) / 2;
}
m_windowStart += offset;
if (m_windowStart < m_traceStart) {
m_windowEnd += m_traceStart - m_windowStart;
m_windowStart = m_traceStart;
}
m_windowEnd += offset;
if (m_windowEnd > m_traceEnd) {
m_windowStart -= m_windowEnd - m_traceEnd;
m_windowEnd = m_traceEnd;
}
clampRangeToWindow();
emit windowChanged(m_windowStart, m_windowEnd);
m_timer.start(100);
}
void TimelineZoomControl::clampRangeToWindow()
{
qint64 rangeStart = qMin(qMax(m_rangeStart, m_windowStart), m_windowEnd);
qint64 rangeEnd = qMin(qMax(rangeStart, m_rangeEnd), m_windowEnd);
if (rangeStart != m_rangeStart || rangeEnd != m_rangeEnd)
setRange(rangeStart, rangeEnd);
}
} // namespace Timeline

View File

@@ -1,107 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef TIMELINEZOOMCONTROL_H
#define TIMELINEZOOMCONTROL_H
#include <QTimer>
namespace Timeline {
class TimelineZoomControl : public QObject {
Q_OBJECT
Q_PROPERTY(qint64 traceStart READ traceStart WRITE setTraceStart NOTIFY traceChanged)
Q_PROPERTY(qint64 traceEnd READ traceEnd WRITE setTraceEnd NOTIFY traceChanged)
Q_PROPERTY(qint64 traceDuration READ traceDuration NOTIFY traceChanged)
Q_PROPERTY(qint64 windowStart READ windowStart NOTIFY windowChanged)
Q_PROPERTY(qint64 windowEnd READ windowEnd NOTIFY windowChanged)
Q_PROPERTY(qint64 windowDuration READ windowDuration NOTIFY windowChanged)
Q_PROPERTY(qint64 rangeStart READ rangeStart NOTIFY rangeChanged)
Q_PROPERTY(qint64 rangeEnd READ rangeEnd NOTIFY rangeChanged)
Q_PROPERTY(qint64 rangeDuration READ rangeDuration NOTIFY rangeChanged)
Q_PROPERTY(bool windowLocked READ windowLocked WRITE setWindowLocked NOTIFY windowLockedChanged)
public:
static const qint64 MAX_ZOOM_FACTOR = 1 << 10;
TimelineZoomControl(QObject *parent = 0);
qint64 traceStart() const { return m_traceStart; }
qint64 traceEnd() const { return m_traceEnd; }
qint64 traceDuration() const { return m_traceEnd - m_traceStart; }
qint64 windowStart() const { return m_windowStart; }
qint64 windowEnd() const { return m_windowEnd; }
qint64 windowDuration() const { return m_windowEnd - m_windowStart; }
qint64 rangeStart() const { return m_rangeStart; }
qint64 rangeEnd() const { return m_rangeEnd; }
qint64 rangeDuration() const { return m_rangeEnd - m_rangeStart; }
bool windowLocked() const { return m_windowLocked; }
virtual void clear();
signals:
void traceChanged(qint64 start, qint64 end);
void windowChanged(qint64 start, qint64 end);
void rangeChanged(qint64 start, qint64 end);
void windowLockedChanged(bool windowLocked);
public slots:
void setTraceStart(qint64 start);
void setTraceEnd(qint64 end);
void setTrace(qint64 start, qint64 end);
void setRange(qint64 start, qint64 end);
void setWindowLocked(bool windowLocked);
protected slots:
void moveWindow();
protected:
qint64 m_traceStart;
qint64 m_traceEnd;
qint64 m_windowStart;
qint64 m_windowEnd;
qint64 m_rangeStart;
qint64 m_rangeEnd;
QTimer m_timer;
bool m_windowLocked;
void rebuildWindow();
void clampRangeToWindow();
};
} // namespace Timeline
#endif // TIMELINEZOOMCONTROL_H