2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2011-03-25 09:25:17 +01:00
|
|
|
**
|
2016-01-15 14:58:39 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2011-03-25 09:25:17 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2011-03-25 09:25:17 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** 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
|
2016-01-15 14:58:39 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2011-03-25 09:25:17 +01:00
|
|
|
**
|
2016-01-15 14:58:39 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2011-03-25 09:25:17 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2011-03-25 09:25:17 +01:00
|
|
|
|
2013-09-03 12:53:48 +02:00
|
|
|
import QtQuick 2.1
|
2013-11-12 12:44:54 +01:00
|
|
|
import QtQuick.Controls 1.0
|
2015-04-14 17:00:51 +02:00
|
|
|
import QtQuick.Controls.Styles 1.0
|
2011-03-11 12:22:57 +01:00
|
|
|
|
2016-12-13 11:44:49 +01:00
|
|
|
import TimelineTheme 1.0
|
|
|
|
|
|
2011-03-11 12:22:57 +01:00
|
|
|
Rectangle {
|
|
|
|
|
id: root
|
|
|
|
|
|
2011-10-11 17:52:39 +02:00
|
|
|
// ***** properties
|
|
|
|
|
|
2011-11-09 12:57:41 +01:00
|
|
|
property bool lockItemSelection : false
|
2011-09-23 15:58:41 +02:00
|
|
|
|
2011-03-11 12:22:57 +01:00
|
|
|
signal updateCursorPosition
|
|
|
|
|
property string fileName: ""
|
|
|
|
|
property int lineNumber: -1
|
2012-01-12 16:36:40 +01:00
|
|
|
property int columnNumber: 0
|
2014-10-30 14:57:49 +01:00
|
|
|
property int selectedModel: -1
|
|
|
|
|
property int selectedItem: -1
|
2011-10-11 17:52:39 +02:00
|
|
|
|
2011-10-19 14:28:21 +02:00
|
|
|
property bool selectionRangeMode: false
|
2011-11-08 16:54:23 +01:00
|
|
|
property bool selectionRangeReady: selectionRange.ready
|
2014-12-05 16:00:03 +01:00
|
|
|
property int typeId: content.typeId
|
2017-03-22 16:31:12 +01:00
|
|
|
onWidthChanged: zoomSliderToolBar.updateZoomLevel();
|
2014-12-05 16:00:03 +01:00
|
|
|
|
2016-12-13 11:44:49 +01:00
|
|
|
color: Theme.color(Theme.Timeline_BackgroundColor1)
|
2014-02-27 12:14:45 +01:00
|
|
|
|
2011-10-11 17:52:39 +02:00
|
|
|
// ***** connections with external objects
|
|
|
|
|
Connections {
|
|
|
|
|
target: zoomControl
|
|
|
|
|
onRangeChanged: {
|
2014-10-14 16:44:45 +02:00
|
|
|
zoomSliderToolBar.updateZoomLevel();
|
2014-12-05 16:00:03 +01:00
|
|
|
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;
|
|
|
|
|
}
|
2014-03-28 16:11:16 +01:00
|
|
|
}
|
|
|
|
|
onWindowChanged: {
|
2014-12-05 16:00:03 +01:00
|
|
|
content.scroll();
|
2011-10-11 17:52:39 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-05 16:00:03 +01:00
|
|
|
onSelectionRangeModeChanged: {
|
|
|
|
|
selectionRange.reset();
|
|
|
|
|
buttonsBar.updateRangeButton(selectionRangeMode);
|
2014-10-30 14:57:49 +01:00
|
|
|
}
|
|
|
|
|
|
2014-12-05 16:00:03 +01:00
|
|
|
// ***** functions
|
2014-03-25 17:10:25 +01:00
|
|
|
function clear() {
|
2014-12-05 16:00:03 +01:00
|
|
|
content.clearChildren();
|
2014-09-25 12:50:10 +02:00
|
|
|
rangeDetails.hide();
|
2011-11-16 16:08:05 +01:00
|
|
|
selectionRangeMode = false;
|
2014-03-25 17:10:25 +01:00
|
|
|
zoomSlider.externalUpdate = true;
|
|
|
|
|
zoomSlider.value = zoomSlider.minimumValue;
|
2011-06-24 18:19:08 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-11 11:41:58 +01:00
|
|
|
// This is called from outside to synchronize the timeline to other views
|
2014-10-28 12:56:53 +01:00
|
|
|
function selectByTypeId(typeId)
|
2011-11-09 12:57:41 +01:00
|
|
|
{
|
2014-10-28 12:56:53 +01:00
|
|
|
if (lockItemSelection || typeId === -1)
|
2014-04-03 11:15:56 +02:00
|
|
|
return;
|
|
|
|
|
|
2014-10-28 12:56:53 +01:00
|
|
|
var itemIndex = -1;
|
|
|
|
|
var modelIndex = -1;
|
2014-12-16 10:46:10 +01:00
|
|
|
|
|
|
|
|
var notesModel = timelineModelAggregator.notes;
|
|
|
|
|
var notes = notesModel ? notesModel.byTypeId(typeId) : [];
|
2014-10-28 12:56:53 +01:00
|
|
|
if (notes.length !== 0) {
|
2014-12-16 10:46:10 +01:00
|
|
|
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;
|
|
|
|
|
}
|
2014-10-28 12:56:53 +01:00
|
|
|
} else {
|
2014-12-08 17:38:10 +01:00
|
|
|
for (modelIndex = 0; modelIndex < timelineModelAggregator.models.length; ++modelIndex) {
|
2014-10-30 14:57:49 +01:00
|
|
|
if (modelIndex === selectedModel && selectedItem !== -1 &&
|
2014-12-08 17:38:10 +01:00
|
|
|
typeId === timelineModelAggregator.models[modelIndex].typeId(selectedItem))
|
2014-10-28 12:56:53 +01:00
|
|
|
break;
|
|
|
|
|
|
2014-12-08 17:38:10 +01:00
|
|
|
if (!timelineModelAggregator.models[modelIndex].handlesTypeId(typeId))
|
2014-10-28 12:56:53 +01:00
|
|
|
continue;
|
|
|
|
|
|
2014-12-08 17:38:10 +01:00
|
|
|
itemIndex = timelineModelAggregator.models[modelIndex].nextItemByTypeId(typeId,
|
2014-10-30 14:57:49 +01:00
|
|
|
zoomControl.rangeStart, selectedItem);
|
2014-10-28 12:56:53 +01:00
|
|
|
if (itemIndex !== -1)
|
|
|
|
|
break;
|
2014-09-29 18:20:26 +02:00
|
|
|
}
|
2014-10-28 12:56:53 +01:00
|
|
|
}
|
2014-09-29 18:20:26 +02:00
|
|
|
|
2014-12-16 10:46:10 +01:00
|
|
|
if (modelIndex !== -1 && modelIndex < timelineModelAggregator.models.length &&
|
|
|
|
|
itemIndex !== -1) {
|
2011-11-09 12:57:41 +01:00
|
|
|
// select an item, lock to it, and recenter if necessary
|
2015-11-11 11:41:58 +01:00
|
|
|
|
|
|
|
|
// set this here, so that propagateSelection doesn't trigger updateCursorPosition()
|
|
|
|
|
content.typeId = typeId;
|
2014-12-05 16:00:03 +01:00
|
|
|
content.select(modelIndex, itemIndex);
|
|
|
|
|
content.selectionLocked = true;
|
2011-11-09 12:57:41 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-11 11:41:58 +01:00
|
|
|
// This is called from outside to synchronize the timeline to other views
|
2015-01-30 16:52:11 +01:00
|
|
|
function selectByIndices(modelIndex, eventIndex)
|
|
|
|
|
{
|
2015-11-11 11:41:58 +01:00
|
|
|
if (modelIndex >= 0 && modelIndex < timelineModelAggregator.models.length &&
|
|
|
|
|
selectedItem !== -1) {
|
|
|
|
|
// set this here, so that propagateSelection doesn't trigger updateCursorPosition()
|
|
|
|
|
content.typeId = timelineModelAggregator.models[modelIndex].typeId(eventIndex);
|
|
|
|
|
}
|
2015-01-30 16:52:11 +01:00
|
|
|
content.select(modelIndex, eventIndex);
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-23 15:46:40 +02:00
|
|
|
focus: true
|
|
|
|
|
property bool shiftPressed: false;
|
|
|
|
|
Keys.onPressed: shiftPressed = (event.key === Qt.Key_Shift);
|
|
|
|
|
Keys.onReleased: shiftPressed = false;
|
|
|
|
|
|
2014-12-05 16:00:03 +01:00
|
|
|
TimelineLabels {
|
2014-11-07 18:13:31 +01:00
|
|
|
id: categories
|
2014-06-04 18:23:07 +02:00
|
|
|
anchors.top: buttonsBar.bottom
|
|
|
|
|
anchors.bottom: overview.top
|
2014-02-27 12:14:45 +01:00
|
|
|
anchors.left: parent.left
|
2014-11-07 18:13:31 +01:00
|
|
|
anchors.right: parent.right
|
2014-12-05 16:00:03 +01:00
|
|
|
contentY: content.contentY
|
|
|
|
|
selectedModel: root.selectedModel
|
|
|
|
|
selectedItem: root.selectedItem
|
2016-12-13 11:44:49 +01:00
|
|
|
color: Theme.color(Theme.PanelStatusBarBackgroundColor)
|
2014-12-08 17:38:10 +01:00
|
|
|
modelProxy: timelineModelAggregator
|
2014-12-05 16:00:03 +01:00
|
|
|
zoomer: zoomControl
|
|
|
|
|
reverseSelect: shiftPressed
|
2014-11-07 18:13:31 +01:00
|
|
|
|
2014-12-05 16:00:03 +01:00
|
|
|
onMoveCategories: content.moveCategories(sourceIndex, targetIndex)
|
|
|
|
|
onSelectItem: content.select(modelIndex, eventIndex)
|
2014-02-27 12:14:45 +01:00
|
|
|
}
|
|
|
|
|
|
2014-11-07 18:13:31 +01:00
|
|
|
TimeDisplay {
|
|
|
|
|
id: timeDisplay
|
2014-02-27 12:14:45 +01:00
|
|
|
anchors.top: parent.top
|
2014-11-07 18:13:31 +01:00
|
|
|
anchors.left: buttonsBar.right
|
|
|
|
|
anchors.right: parent.right
|
2014-06-04 18:23:07 +02:00
|
|
|
anchors.bottom: overview.top
|
2014-12-10 11:21:53 +01:00
|
|
|
windowStart: zoomControl.windowStart
|
2015-07-01 18:58:05 +02:00
|
|
|
rangeDuration: zoomControl.rangeDuration
|
2014-12-05 16:00:03 +01:00
|
|
|
contentX: content.contentX
|
2014-02-27 12:14:45 +01:00
|
|
|
}
|
|
|
|
|
|
2014-06-04 18:23:07 +02:00
|
|
|
ButtonsBar {
|
|
|
|
|
id: buttonsBar
|
2015-04-14 16:07:38 +02:00
|
|
|
enabled: zoomControl.traceDuration > 0
|
2014-06-04 18:23:07 +02:00
|
|
|
anchors.top: parent.top
|
|
|
|
|
anchors.left: parent.left
|
|
|
|
|
width: 150
|
|
|
|
|
height: 24
|
|
|
|
|
onZoomControlChanged: zoomSliderToolBar.visible = !zoomSliderToolBar.visible
|
2014-11-04 12:54:27 +01:00
|
|
|
onJumpToNext: {
|
2014-12-08 17:38:10 +01:00
|
|
|
var next = timelineModelAggregator.nextItem(root.selectedModel, root.selectedItem,
|
2014-11-04 12:54:27 +01:00
|
|
|
zoomControl.rangeStart);
|
2014-12-05 16:00:03 +01:00
|
|
|
content.select(next.model, next.item);
|
2014-11-04 12:54:27 +01:00
|
|
|
}
|
|
|
|
|
onJumpToPrev: {
|
2014-12-08 17:38:10 +01:00
|
|
|
var prev = timelineModelAggregator.prevItem(root.selectedModel, root.selectedItem,
|
2014-11-04 12:54:27 +01:00
|
|
|
zoomControl.rangeEnd);
|
2014-12-05 16:00:03 +01:00
|
|
|
content.select(prev.model, prev.item);
|
2014-11-04 12:54:27 +01:00
|
|
|
}
|
2014-10-30 14:57:49 +01:00
|
|
|
|
2014-06-04 18:23:07 +02:00
|
|
|
onRangeSelectChanged: selectionRangeMode = rangeButtonChecked();
|
2014-12-05 16:00:03 +01:00
|
|
|
onLockChanged: content.selectionLocked = !lockButtonChecked();
|
2014-06-04 18:23:07 +02:00
|
|
|
}
|
|
|
|
|
|
2014-12-05 16:00:03 +01:00
|
|
|
TimelineContent {
|
|
|
|
|
id: content
|
|
|
|
|
anchors.left: buttonsBar.right
|
|
|
|
|
anchors.top: buttonsBar.bottom
|
|
|
|
|
anchors.bottom: overview.top
|
|
|
|
|
anchors.right: parent.right
|
|
|
|
|
selectionLocked: true
|
|
|
|
|
zoomer: zoomControl
|
2014-12-08 17:38:10 +01:00
|
|
|
modelProxy: timelineModelAggregator
|
2014-11-26 16:53:42 +01:00
|
|
|
|
2014-12-05 16:00:03 +01:00
|
|
|
onSelectionLockedChanged: {
|
|
|
|
|
buttonsBar.updateLockButton(selectionLocked);
|
|
|
|
|
}
|
2011-10-11 17:52:39 +02:00
|
|
|
|
2014-12-05 16:00:03 +01:00
|
|
|
onPropagateSelection: {
|
|
|
|
|
if (lockItemSelection || (newModel === selectedModel && newItem === selectedItem))
|
2014-10-30 14:57:49 +01:00
|
|
|
return;
|
2011-09-23 15:58:41 +02:00
|
|
|
|
2014-12-05 16:00:03 +01:00
|
|
|
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
|
2014-12-08 17:38:10 +01:00
|
|
|
var model = timelineModelAggregator.models[selectedModel];
|
2014-12-05 16:00:03 +01:00
|
|
|
var eventLocation = model.location(selectedItem);
|
2015-11-11 11:39:34 +01:00
|
|
|
if (eventLocation.file !== undefined) {
|
|
|
|
|
root.fileName = eventLocation.file;
|
|
|
|
|
root.lineNumber = eventLocation.line;
|
|
|
|
|
root.columnNumber = eventLocation.column;
|
|
|
|
|
}
|
2015-11-11 11:41:58 +01:00
|
|
|
var newTypeId = model.typeId(selectedItem);
|
|
|
|
|
if (newTypeId !== typeId) {
|
|
|
|
|
typeId = newTypeId;
|
2016-02-19 12:22:02 +01:00
|
|
|
root.updateCursorPosition();
|
2015-11-11 11:41:58 +01:00
|
|
|
}
|
2014-12-05 16:00:03 +01:00
|
|
|
} else {
|
2016-05-17 12:20:52 +02:00
|
|
|
selectedModel = -1;
|
2014-12-05 16:00:03 +01:00
|
|
|
rangeDetails.hide();
|
2014-10-30 14:57:49 +01:00
|
|
|
}
|
2014-12-05 16:00:03 +01:00
|
|
|
lockItemSelection = false;
|
2014-10-30 14:57:49 +01:00
|
|
|
}
|
2014-12-05 16:00:03 +01:00
|
|
|
}
|
2011-10-19 14:28:21 +02:00
|
|
|
|
2014-12-05 16:00:03 +01:00
|
|
|
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;
|
2014-10-14 16:44:45 +02:00
|
|
|
|
2014-12-05 16:00:03 +01:00
|
|
|
if (selectionRangeControl.pressed ||
|
|
|
|
|
selectionRange.creationState !== selectionRange.creationFinished)
|
|
|
|
|
selectionRange.setPos(selectionRangeControl.mouseX + content.contentX);
|
2014-10-30 14:57:49 +01:00
|
|
|
}
|
2014-12-05 16:00:03 +01:00
|
|
|
onCanceled: pressed()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Flickable {
|
|
|
|
|
flickableDirection: Flickable.HorizontalFlick
|
|
|
|
|
clip: true
|
|
|
|
|
interactive: false
|
|
|
|
|
x: content.x + content.flickableItem.x
|
|
|
|
|
y: content.y + content.flickableItem.y
|
2015-08-31 15:53:22 +02:00
|
|
|
height: (selectionRangeMode &&
|
|
|
|
|
selectionRange.creationState !== selectionRange.creationInactive) ?
|
|
|
|
|
content.flickableItem.height : 0
|
2014-12-05 16:00:03 +01:00
|
|
|
width: content.flickableItem.width
|
|
|
|
|
contentX: content.contentX
|
|
|
|
|
contentWidth: content.contentWidth
|
2014-03-03 14:04:50 +01:00
|
|
|
|
2014-10-30 14:57:49 +01:00
|
|
|
SelectionRange {
|
|
|
|
|
id: selectionRange
|
2014-12-05 16:00:03 +01:00
|
|
|
zoomer: zoomControl
|
2014-10-14 16:44:45 +02:00
|
|
|
|
2014-12-05 16:00:03 +01:00
|
|
|
onRangeDoubleClicked: {
|
2015-11-19 09:45:11 +01:00
|
|
|
var diff = zoomer.minimumRangeLength - zoomer.selectionDuration;
|
2015-03-23 18:50:47 +01:00
|
|
|
if (diff > 0)
|
|
|
|
|
zoomControl.setRange(zoomer.selectionStart - diff / 2,
|
|
|
|
|
zoomer.selectionEnd + diff / 2);
|
|
|
|
|
else
|
|
|
|
|
zoomControl.setRange(zoomer.selectionStart, zoomer.selectionEnd);
|
2014-12-05 16:00:03 +01:00
|
|
|
root.selectionRangeMode = false;
|
2011-10-11 17:52:39 +02:00
|
|
|
}
|
2011-07-11 16:05:37 +02:00
|
|
|
|
2011-11-16 16:08:05 +01:00
|
|
|
}
|
|
|
|
|
}
|
2016-09-09 13:51:19 +02:00
|
|
|
|
|
|
|
|
TimelineRulers {
|
|
|
|
|
contentX: buttonsBar.width - content.x - content.flickableItem.x + content.contentX
|
|
|
|
|
anchors.left: buttonsBar.right
|
|
|
|
|
anchors.right: parent.right
|
|
|
|
|
anchors.top: parent.top
|
|
|
|
|
height: content.flickableItem.height + buttonsBar.height
|
|
|
|
|
windowStart: zoomControl.windowStart
|
|
|
|
|
viewTimePerPixel: selectionRange.viewTimePerPixel
|
|
|
|
|
scaleHeight: buttonsBar.height
|
|
|
|
|
}
|
2013-11-08 12:05:18 +01:00
|
|
|
|
|
|
|
|
SelectionRangeDetails {
|
2015-02-26 15:13:41 +01:00
|
|
|
z: 3
|
2014-12-05 16:00:03 +01:00
|
|
|
x: 200
|
|
|
|
|
y: 125
|
|
|
|
|
|
2015-08-28 16:12:57 +02:00
|
|
|
clip: true
|
2013-11-08 12:05:18 +01:00
|
|
|
id: selectionRangeDetails
|
2015-03-23 18:50:47 +01:00
|
|
|
startTime: zoomControl.selectionStart
|
|
|
|
|
duration: zoomControl.selectionDuration
|
|
|
|
|
endTime: zoomControl.selectionEnd
|
2016-12-19 11:29:40 +01:00
|
|
|
referenceDuration: zoomControl.rangeDuration
|
2014-07-08 14:46:17 +02:00
|
|
|
showDuration: selectionRange.rangeWidth > 1
|
2015-08-31 15:53:22 +02:00
|
|
|
hasContents: selectionRangeMode &&
|
|
|
|
|
selectionRange.creationState !== selectionRange.creationInactive
|
2014-12-05 16:00:03 +01:00
|
|
|
|
|
|
|
|
onRecenter: {
|
2015-03-23 18:50:47 +01:00
|
|
|
if ((zoomControl.selectionStart < zoomControl.rangeStart) ^
|
|
|
|
|
(zoomControl.selectionEnd > zoomControl.rangeEnd)) {
|
|
|
|
|
var center = (zoomControl.selectionStart + zoomControl.selectionEnd) / 2;
|
|
|
|
|
var halfDuration = Math.max(zoomControl.selectionDuration,
|
|
|
|
|
zoomControl.rangeDuration) / 2;
|
2014-12-05 16:00:03 +01:00
|
|
|
zoomControl.setRange(center - halfDuration, center + halfDuration);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onClose: selectionRangeMode = false;
|
2013-11-08 12:05:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RangeDetails {
|
|
|
|
|
id: rangeDetails
|
2014-12-05 16:00:03 +01:00
|
|
|
|
2015-02-26 15:13:41 +01:00
|
|
|
z: 3
|
2014-12-05 16:00:03 +01:00
|
|
|
x: 200
|
|
|
|
|
y: 25
|
|
|
|
|
|
2015-08-28 16:12:57 +02:00
|
|
|
clip: true
|
2014-12-16 11:19:33 +01:00
|
|
|
locked: content.selectionLocked
|
2014-12-08 17:38:10 +01:00
|
|
|
models: timelineModelAggregator.models
|
|
|
|
|
notes: timelineModelAggregator.notes
|
2015-08-31 15:53:22 +02:00
|
|
|
hasContents: false
|
2014-12-05 16:00:03 +01:00
|
|
|
onRecenterOnItem: {
|
|
|
|
|
content.select(selectedModel, selectedItem)
|
|
|
|
|
}
|
|
|
|
|
onToggleSelectionLocked: {
|
|
|
|
|
content.selectionLocked = !content.selectionLocked;
|
|
|
|
|
}
|
|
|
|
|
onClearSelection: {
|
|
|
|
|
content.propagateSelection(-1, -1);
|
|
|
|
|
}
|
2013-11-08 12:05:18 +01:00
|
|
|
}
|
2011-11-16 16:08:05 +01:00
|
|
|
|
2013-11-12 12:44:54 +01:00
|
|
|
Rectangle {
|
2014-06-04 18:23:07 +02:00
|
|
|
id: zoomSliderToolBar
|
2013-11-12 12:44:54 +01:00
|
|
|
objectName: "zoomSliderToolBar"
|
2016-12-13 11:44:49 +01:00
|
|
|
color: Theme.color(Theme.Timeline_PanelBackgroundColor)
|
2014-06-04 18:23:07 +02:00
|
|
|
enabled: buttonsBar.enabled
|
2013-11-12 12:44:54 +01:00
|
|
|
visible: false
|
2014-12-05 16:00:03 +01:00
|
|
|
width: buttonsBar.width
|
2014-09-11 11:44:27 +02:00
|
|
|
height: buttonsBar.height
|
2014-06-04 18:23:07 +02:00
|
|
|
anchors.left: parent.left
|
|
|
|
|
anchors.top: buttonsBar.bottom
|
2013-11-12 12:44:54 +01:00
|
|
|
|
2013-11-12 16:12:43 +01:00
|
|
|
function updateZoomLevel() {
|
2015-12-03 13:04:41 +01:00
|
|
|
var newValue = Math.round(Math.pow(zoomControl.rangeDuration /
|
|
|
|
|
Math.max(1, zoomControl.windowDuration),
|
|
|
|
|
1 / zoomSlider.exponent) * zoomSlider.maximumValue);
|
|
|
|
|
if (newValue !== zoomSlider.value) {
|
|
|
|
|
zoomSlider.externalUpdate = true;
|
|
|
|
|
zoomSlider.value = newValue;
|
|
|
|
|
}
|
2013-11-12 16:12:43 +01:00
|
|
|
}
|
|
|
|
|
|
2013-11-12 12:44:54 +01:00
|
|
|
Slider {
|
|
|
|
|
id: zoomSlider
|
|
|
|
|
anchors.fill: parent
|
|
|
|
|
minimumValue: 1
|
|
|
|
|
maximumValue: 10000
|
|
|
|
|
stepSize: 100
|
|
|
|
|
|
2013-11-12 16:12:43 +01:00
|
|
|
property int exponent: 3
|
|
|
|
|
property bool externalUpdate: false
|
|
|
|
|
property int minWindowLength: 1e5 // 0.1 ms
|
2015-12-03 12:52:29 +01:00
|
|
|
property double fixedPoint: 0
|
|
|
|
|
onPressedChanged: fixedPoint = (zoomControl.rangeStart + zoomControl.rangeEnd) / 2;
|
2013-11-12 16:12:43 +01:00
|
|
|
|
|
|
|
|
onValueChanged: {
|
2014-10-14 16:44:45 +02:00
|
|
|
if (externalUpdate || zoomControl.windowEnd <= zoomControl.windowStart) {
|
2013-11-12 16:12:43 +01:00
|
|
|
// 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(
|
2014-10-14 16:44:45 +02:00
|
|
|
Math.pow(value / maximumValue, exponent) * zoomControl.windowDuration,
|
2013-11-12 16:12:43 +01:00
|
|
|
minWindowLength);
|
|
|
|
|
|
2014-10-14 16:44:45 +02:00
|
|
|
var startTime = Math.max(zoomControl.windowStart, fixedPoint - windowLength / 2)
|
2013-11-12 16:12:43 +01:00
|
|
|
zoomControl.setRange(startTime, startTime + windowLength);
|
|
|
|
|
}
|
2013-11-12 12:44:54 +01:00
|
|
|
}
|
|
|
|
|
}
|
2014-06-04 18:23:07 +02:00
|
|
|
|
|
|
|
|
Overview {
|
|
|
|
|
id: overview
|
|
|
|
|
height: 50
|
|
|
|
|
anchors.bottom: parent.bottom
|
|
|
|
|
anchors.right: parent.right
|
|
|
|
|
anchors.left: parent.left
|
2014-12-08 17:38:10 +01:00
|
|
|
modelProxy: timelineModelAggregator
|
2014-12-05 16:00:03 +01:00
|
|
|
zoomer: zoomControl
|
2014-06-04 18:23:07 +02:00
|
|
|
}
|
2015-02-10 20:29:54 +01:00
|
|
|
|
|
|
|
|
Rectangle {
|
|
|
|
|
// Opal glass pane for visualizing the "disabled" state.
|
|
|
|
|
anchors.fill: parent
|
|
|
|
|
z: 10
|
|
|
|
|
color: parent.color
|
|
|
|
|
opacity: 0.5
|
|
|
|
|
visible: !parent.enabled
|
|
|
|
|
}
|
2011-03-11 12:22:57 +01:00
|
|
|
}
|