Timeline: Create new library from contents of QmlProfiler
Change-Id: I964b2f149e237eb25a08600e8dab8968e8bc0cb9 Reviewed-by: Kai Koehne <kai.koehne@theqtcompany.com>
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 140 B |
|
Before Width: | Height: | Size: 144 B |
|
Before Width: | Height: | Size: 664 B |
|
Before Width: | Height: | Size: 164 B |
|
Before Width: | Height: | Size: 335 B |
|
Before Width: | Height: | Size: 715 B |
|
Before Width: | Height: | Size: 117 B |
|
Before Width: | Height: | Size: 745 B |
|
Before Width: | Height: | Size: 233 B |
|
Before Width: | Height: | Size: 224 B |
|
Before Width: | Height: | Size: 328 B |
|
Before Width: | Height: | Size: 584 B |
|
Before Width: | Height: | Size: 276 B |
|
Before Width: | Height: | Size: 265 B |
@@ -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));
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
|
Before Width: | Height: | Size: 197 B |
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ QTC_LIB_DEPENDS += \
|
||||
qmldebug \
|
||||
qmljs \
|
||||
ssh \
|
||||
timeline \
|
||||
utils
|
||||
QTC_PLUGIN_DEPENDS += \
|
||||
analyzerbase \
|
||||
|
||||
@@ -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 *)
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "qmlprofilernotesmodel.h"
|
||||
#include "qmlprofilerdatamodel.h"
|
||||
|
||||
namespace QmlProfiler {
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#define QMLPROFILERNOTESMODEL_H
|
||||
|
||||
#include "qmlprofilermodelmanager.h"
|
||||
#include "timelinenotesmodel.h"
|
||||
#include "timeline/timelinenotesmodel.h"
|
||||
#include <QList>
|
||||
#include <QHash>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include "qmlprofilerclientmanager.h"
|
||||
#include "qmlprofilermodelmanager.h"
|
||||
#include "qmlprofilerdetailsrewriter.h"
|
||||
#include "timelinerenderer.h"
|
||||
#include "qmlprofilernotesmodel.h"
|
||||
|
||||
#include <analyzerbase/analyzermanager.h>
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 ¤t = 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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 ¬e = 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 ¬e = 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 ¬e = 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 ¬e = 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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||