From bcc62b6f72ef441c6a82cb69e921e7a5fb0acf75 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 28 Jun 2019 11:33:06 +0200 Subject: Tracing: port to QtQuickControls2 Controls1 is deprecated. Also, we can easily show tooltips for all buttons this way. Change-Id: I08c3e49139aa31f83e6c7585d8e33ee0140ce5b0 Reviewed-by: Milian Wolff --- src/libs/tracing/qml/ButtonsBar.qml | 30 ++-- src/libs/tracing/qml/CategoryLabel.qml | 15 +- src/libs/tracing/qml/FlameGraphView.qml | 6 +- src/libs/tracing/qml/ImageToolButton.qml | 20 +-- src/libs/tracing/qml/MainView.qml | 28 +-- src/libs/tracing/qml/RangeDetails.qml | 5 + src/libs/tracing/qml/RowLabel.qml | 36 ++-- src/libs/tracing/qml/SelectionRangeDetails.qml | 3 + src/libs/tracing/qml/TimelineContent.qml | 240 ++++++++++++------------- 9 files changed, 183 insertions(+), 200 deletions(-) (limited to 'src/libs') diff --git a/src/libs/tracing/qml/ButtonsBar.qml b/src/libs/tracing/qml/ButtonsBar.qml index a151eb9f91..32111daa57 100644 --- a/src/libs/tracing/qml/ButtonsBar.qml +++ b/src/libs/tracing/qml/ButtonsBar.qml @@ -24,9 +24,8 @@ ****************************************************************************/ import QtQuick 2.1 -import QtQuick.Controls 1.0 -import QtQuick.Layouts 1.0 -import QtQuick.Controls.Styles 1.2 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.3 import TimelineTheme 1.0 @@ -55,19 +54,12 @@ ToolBar { return rangeButton.checked } - style: ToolBarStyle { - padding { - left: 0 - right: 0 - top: 0 - bottom: 0 - } - background: Rectangle { - anchors.fill: parent - color: Theme.color(Theme.PanelStatusBarBackgroundColor) - } + background: Rectangle { + anchors.fill: parent + color: Theme.color(Theme.PanelStatusBarBackgroundColor) } + RowLayout { spacing: 0 anchors.fill: parent @@ -77,7 +69,7 @@ ToolBar { Layout.fillHeight: true imageSource: "image://icons/prev" - tooltip: qsTr("Jump to previous event.") + ToolTip.text: qsTr("Jump to previous event.") onClicked: buttons.jumpToPrev() } @@ -86,7 +78,7 @@ ToolBar { Layout.fillHeight: true imageSource: "image://icons/next" - tooltip: qsTr("Jump to next event.") + ToolTip.text: qsTr("Jump to next event.") onClicked: buttons.jumpToNext() } @@ -95,7 +87,7 @@ ToolBar { Layout.fillHeight: true imageSource: "image://icons/zoom" - tooltip: qsTr("Show zoom slider.") + ToolTip.text: qsTr("Show zoom slider.") checkable: true checked: false onCheckedChanged: buttons.zoomControlChanged() @@ -106,7 +98,7 @@ ToolBar { Layout.fillHeight: true imageSource: "image://icons/" + (checked ? "rangeselected" : "rangeselection"); - tooltip: qsTr("Select range.") + ToolTip.text: qsTr("Select range.") checkable: true checked: false onCheckedChanged: buttons.rangeSelectChanged() @@ -117,7 +109,7 @@ ToolBar { Layout.fillHeight: true imageSource: "image://icons/selectionmode" - tooltip: qsTr("View event information on mouseover.") + ToolTip.text: qsTr("View event information on mouseover.") checkable: true checked: false onCheckedChanged: buttons.lockChanged() diff --git a/src/libs/tracing/qml/CategoryLabel.qml b/src/libs/tracing/qml/CategoryLabel.qml index e06aa7ec95..4994d3b962 100644 --- a/src/libs/tracing/qml/CategoryLabel.qml +++ b/src/libs/tracing/qml/CategoryLabel.qml @@ -24,8 +24,7 @@ ****************************************************************************/ import QtQuick 2.1 -import QtQuick.Controls 1.2 -import QtQuick.Controls.Styles 1.2 +import QtQuick.Controls 2.2 import TimelineTheme 1.0 @@ -57,10 +56,10 @@ Item { Button { // dummy button to display a tooltip anchors.fill: txt - tooltip: labelContainer.text - style: ButtonStyle { - background: Item {} - } + ToolTip.text: labelContainer.text + ToolTip.visible: enabled && hovered + ToolTip.delay: 1000 + background: Item {} } MouseArea { @@ -170,7 +169,7 @@ Item { visible: eventIds.length > 0 imageSource: "image://icons/note" - tooltip: texts.join("\n"); + ToolTip.text: texts.join("\n"); onClicked: { if (++currentNote >= eventIds.length) currentNote = 0; @@ -185,7 +184,7 @@ Item { implicitHeight: txt.height - 1 enabled: expanded || (model && !model.empty) imageSource: expanded ? "image://icons/close_split" : "image://icons/split" - tooltip: expanded ? qsTr("Collapse category") : qsTr("Expand category") + ToolTip.text: expanded ? qsTr("Collapse category") : qsTr("Expand category") onClicked: model.expanded = !expanded } diff --git a/src/libs/tracing/qml/FlameGraphView.qml b/src/libs/tracing/qml/FlameGraphView.qml index 9712b91cd5..621569e8bb 100644 --- a/src/libs/tracing/qml/FlameGraphView.qml +++ b/src/libs/tracing/qml/FlameGraphView.qml @@ -28,7 +28,7 @@ import TimelineTheme 1.0 import QtQml 2.2 import QtQuick 2.9 -import QtQuick.Controls 1.3 +import QtQuick.Controls 2.3 ScrollView { id: root @@ -322,9 +322,11 @@ ScrollView { width: implicitWidth + 20 text: qsTr("Visualize %1").arg(trRoleNames[root.sizeRole]) + onClicked: modesMenu.open() - menu: Menu { + Menu { id: modesMenu + y: parent.height Instantiator { model: root.modes MenuItem { diff --git a/src/libs/tracing/qml/ImageToolButton.qml b/src/libs/tracing/qml/ImageToolButton.qml index 353e38f122..686fd2db88 100644 --- a/src/libs/tracing/qml/ImageToolButton.qml +++ b/src/libs/tracing/qml/ImageToolButton.qml @@ -24,8 +24,7 @@ ****************************************************************************/ import QtQuick 2.1 -import QtQuick.Controls 1.0 -import QtQuick.Controls.Styles 1.2 +import QtQuick.Controls 2.0 import TimelineTheme 1.0 @@ -34,6 +33,9 @@ ToolButton { property string imageSource + ToolTip.visible: enabled && hovered + ToolTip.delay: 1000 + Image { source: parent.enabled ? parent.imageSource : parent.imageSource + "/disabled" width: 16 @@ -42,13 +44,11 @@ ToolButton { smooth: false } - style: ButtonStyle { - background: Rectangle { - color: (control.checked || control.pressed) - ? Theme.color(Theme.FancyToolButtonSelectedColor) - : control.hovered - ? Theme.color(Theme.FancyToolButtonHoverColor) - : "#00000000" - } + background: Rectangle { + color: (parent.checked || parent.pressed) + ? Theme.color(Theme.FancyToolButtonSelectedColor) + : parent.hovered + ? Theme.color(Theme.FancyToolButtonHoverColor) + : "#00000000" } } diff --git a/src/libs/tracing/qml/MainView.qml b/src/libs/tracing/qml/MainView.qml index 2e1f97a3ba..30eb7c3c3f 100644 --- a/src/libs/tracing/qml/MainView.qml +++ b/src/libs/tracing/qml/MainView.qml @@ -24,8 +24,7 @@ ****************************************************************************/ import QtQuick 2.1 -import QtQuick.Controls 1.0 -import QtQuick.Controls.Styles 1.0 +import QtQuick.Controls 2.0 import TimelineTheme 1.0 @@ -73,7 +72,7 @@ Rectangle { rangeDetails.hide(); selectionRangeMode = false; zoomSlider.externalUpdate = true; - zoomSlider.value = zoomSlider.minimumValue; + zoomSlider.value = zoomSlider.from; } // This is called from outside to synchronize the timeline to other views @@ -192,6 +191,7 @@ Rectangle { TimelineContent { id: content + anchors.left: buttonsBar.right anchors.top: buttonsBar.bottom anchors.bottom: overview.top @@ -255,13 +255,13 @@ Rectangle { onReleased: { if (selectionRange.creationState === selectionRange.creationSecondLimit) { - content.stayInteractive = true; + content.interactive = true; selectionRange.creationState = selectionRange.creationFinished; } } onPressed: { if (selectionRange.creationState === selectionRange.creationFirstLimit) { - content.stayInteractive = false; + content.interactive = false; selectionRange.setPos(selectionRangeControl.mouseX + content.contentX); selectionRange.creationState = selectionRange.creationSecondLimit; } @@ -281,12 +281,12 @@ Rectangle { flickableDirection: Flickable.HorizontalFlick clip: true interactive: false - x: content.x + content.flickableItem.x - y: content.y + content.flickableItem.y + x: content.x + y: content.y height: (selectionRangeMode && selectionRange.creationState !== selectionRange.creationInactive) ? - content.flickableItem.height : 0 - width: content.flickableItem.width + content.height : 0 + width: content.width contentX: content.contentX contentWidth: content.contentWidth @@ -320,11 +320,11 @@ Rectangle { } TimelineRulers { - contentX: buttonsBar.width - content.x - content.flickableItem.x + content.contentX + contentX: buttonsBar.width + content.contentX anchors.left: buttonsBar.right anchors.right: parent.right anchors.top: parent.top - height: content.flickableItem.height + buttonsBar.height + height: content.height + buttonsBar.height windowStart: zoomControl.windowStart viewTimePerPixel: selectionRange.viewTimePerPixel scaleHeight: buttonsBar.height @@ -458,8 +458,8 @@ Rectangle { Slider { id: zoomSlider anchors.fill: parent - minimumValue: 1 - maximumValue: 10000 + from: 1 + to: 10000 stepSize: 100 property int exponent: 3 @@ -478,7 +478,7 @@ Rectangle { } var windowLength = Math.max( - Math.pow(value / maximumValue, exponent) * zoomControl.windowDuration, + Math.pow(value / to, exponent) * zoomControl.windowDuration, minWindowLength); var startTime = Math.max(zoomControl.windowStart, fixedPoint - windowLength / 2) diff --git a/src/libs/tracing/qml/RangeDetails.qml b/src/libs/tracing/qml/RangeDetails.qml index ccb86a5c3c..cb99479ca4 100644 --- a/src/libs/tracing/qml/RangeDetails.qml +++ b/src/libs/tracing/qml/RangeDetails.qml @@ -24,6 +24,8 @@ ****************************************************************************/ import QtQuick 2.9 +import QtQuick.Controls 2.0 + import TimelineTheme 1.0 Item { @@ -108,6 +110,7 @@ Item { implicitHeight: typeTitle.height visible: !rangeDetails.noteReadonly onClicked: noteEdit.focus = true + ToolTip.text: qsTr("Edit note") } ImageToolButton { @@ -117,6 +120,7 @@ Item { anchors.right: closeIcon.left implicitHeight: typeTitle.height onClicked: locked = !locked + ToolTip.text: qsTr("View event information on mouseover.") } ImageToolButton { @@ -126,6 +130,7 @@ Item { implicitHeight: typeTitle.height imageSource: "image://icons/close_window" onClicked: rangeDetails.clearSelection() + ToolTip.text: qsTr("Close") } } diff --git a/src/libs/tracing/qml/RowLabel.qml b/src/libs/tracing/qml/RowLabel.qml index be394b5e7e..e73d51b291 100644 --- a/src/libs/tracing/qml/RowLabel.qml +++ b/src/libs/tracing/qml/RowLabel.qml @@ -24,8 +24,7 @@ ****************************************************************************/ import QtQuick 2.0 -import QtQuick.Controls 1.2 -import QtQuick.Controls.Styles 1.2 +import QtQuick.Controls 2.2 import TimelineTheme 1.0 Button { @@ -38,25 +37,26 @@ Button { signal setRowHeight(int newHeight) property string labelText: label.description ? label.description : qsTr("[unknown]") - action: Action { - onTriggered: button.selectBySelectionId(); - tooltip: button.labelText + (label.displayName ? (" (" + label.displayName + ")") : "") + + onPressed: selectBySelectionId(); + ToolTip.text: labelText + (label.displayName ? (" (" + label.displayName + ")") : "") + ToolTip.visible: hovered + ToolTip.delay: 1000 + + background: Rectangle { + border.width: 1 + border.color: Theme.color(Theme.Timeline_DividerColor) + color: Theme.color(Theme.PanelStatusBarBackgroundColor) } - style: ButtonStyle { - background: Rectangle { - border.width: 1 - border.color: Theme.color(Theme.Timeline_DividerColor) - color: Theme.color(Theme.PanelStatusBarBackgroundColor) - } - label: TimelineText { - text: button.labelText - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignLeft - elide: Text.ElideRight - color: Theme.color(Theme.PanelTextColorLight) - } + contentItem: TimelineText { + text: button.labelText + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + elide: Text.ElideRight + color: Theme.color(Theme.PanelTextColorLight) } + MouseArea { hoverEnabled: true property bool resizing: false diff --git a/src/libs/tracing/qml/SelectionRangeDetails.qml b/src/libs/tracing/qml/SelectionRangeDetails.qml index 458e5cf7ad..288ac7693c 100644 --- a/src/libs/tracing/qml/SelectionRangeDetails.qml +++ b/src/libs/tracing/qml/SelectionRangeDetails.qml @@ -24,6 +24,8 @@ ****************************************************************************/ import QtQuick 2.1 +import QtQuick.Controls 2.0 + import TimelineTheme 1.0 import TimelineTimeFormatter 1.0 @@ -133,5 +135,6 @@ Item { anchors.top: selectionRangeDetails.top implicitHeight: typeTitle.height onClicked: selectionRangeDetails.close() + ToolTip.text: qsTr("Close") } } diff --git a/src/libs/tracing/qml/TimelineContent.qml b/src/libs/tracing/qml/TimelineContent.qml index 636d707356..5eb667822f 100644 --- a/src/libs/tracing/qml/TimelineContent.qml +++ b/src/libs/tracing/qml/TimelineContent.qml @@ -24,20 +24,26 @@ ****************************************************************************/ import QtQuick 2.0 -import QtQuick.Controls 1.2 +import QtQuick.Controls 2.2 import TimelineRenderer 1.0 import QtQml.Models 2.1 -ScrollView { - id: scroller +Flickable { + id: flick + clip: true + contentHeight: timelineView.height + height + flickableDirection: Flickable.HorizontalAndVerticalFlick + boundsBehavior: Flickable.StopAtBounds + pixelAligned: true + + ScrollBar.horizontal: ScrollBar {} + ScrollBar.vertical: ScrollBar {} + + property bool recursionGuard: false 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 @@ -58,146 +64,122 @@ ScrollView { timelineModel.items.move(sourceIndex, targetIndex) } - function scroll() - { - flick.scroll(); + + function guarded(operation) { + if (recursionGuard) + return; + recursionGuard = true; + operation(); + recursionGuard = false; } - // 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 - - function guarded(operation) { - if (recursionGuard) - return; - recursionGuard = true; - operation(); - recursionGuard = false; + // Logically we should bind to flick.width above as we use flick.width in scroll(). + // However, this width changes before flick.width when the window is resized and if we + // don't explicitly set contentX here, for some reason an automatic change in contentX is + // triggered after this width has changed, but before flick.width changes. This would be + // indistinguishabe from a manual flick by the user and thus changes the range position. We + // don't want to change the range position on resizing the window. Therefore we bind to this + // width. + onWidthChanged: scroll() + + // Update the zoom control on scrolling. + onContentXChanged: guarded(function() { + var newStartTime = contentX * zoomer.rangeDuration / width + zoomer.windowStart; + if (isFinite(newStartTime) && Math.abs(newStartTime - zoomer.rangeStart) >= 1) { + var newEndTime = (contentX + width) * zoomer.rangeDuration / width + zoomer.windowStart; + if (isFinite(newEndTime)) + zoomer.setRange(newStartTime, newEndTime); } - - // Logically we should bind to scroller.width above as we use scroller.width in scroll(). - // However, this width changes before scroller.width when the window is resized and if we - // don't explicitly set contentX here, for some reason an automatic change in contentX is - // triggered after this width has changed, but before scroller.width changes. This would be - // indistinguishabe from a manual flick by the user and thus changes the range position. We - // don't want to change the range position on resizing the window. Therefore we bind to this - // width. - onWidthChanged: scroll() - - // Update the zoom control on scrolling. - onContentXChanged: guarded(function() { - 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); + }); + + // Scroll when the zoom control is updated + function scroll() { + guarded(function() { + if (zoomer.rangeDuration <= 0) { + contentWidth = 0; + contentX = 0; + } else { + var newWidth = zoomer.windowDuration * width / zoomer.rangeDuration; + if (isFinite(newWidth) && Math.abs(newWidth - contentWidth) >= 1) + contentWidth = newWidth; + var newStartX = (zoomer.rangeStart - zoomer.windowStart) * width / + zoomer.rangeDuration; + if (isFinite(newStartX) && Math.abs(newStartX - contentX) >= 1) + contentX = newStartX; } }); + } - // Scroll when the zoom control is updated - function scroll() { - guarded(function() { - if (zoomer.rangeDuration <= 0) { - contentWidth = 0; - contentX = 0; - } else { - 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; - } - }); - } - - 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(); - } + 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: flick.zoomer + selectionLocked: flick.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(); } } + } - function recenter() { - if (modelData.endTime(selectedItem) < zoomer.rangeStart || - modelData.startTime(selectedItem) > zoomer.rangeEnd) { - - var newStart = Math.max((modelData.startTime(selectedItem) + - modelData.endTime(selectedItem) - - zoomer.rangeDuration) / 2, zoomer.traceStart); - zoomer.setRange(newStart, - Math.min(newStart + zoomer.rangeDuration, zoomer.traceEnd)); - } + function recenter() { + if (modelData.endTime(selectedItem) < zoomer.rangeStart || + modelData.startTime(selectedItem) > zoomer.rangeEnd) { - 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; + var newStart = Math.max((modelData.startTime(selectedItem) + + modelData.endTime(selectedItem) - + zoomer.rangeDuration) / 2, zoomer.traceStart); + zoomer.setRange(newStart, + Math.min(newStart + zoomer.rangeDuration, zoomer.traceEnd)); } - onSelectedItemChanged: scroller.propagateSelection(index, selectedItem); + var row = modelData.row(selectedItem); + var rowStart = modelData.rowOffset(row) + y; + var rowEnd = rowStart + modelData.rowHeight(row); + if (rowStart < flick.contentY || rowEnd - flick.height > flick.contentY) + flick.contentY = (rowStart + rowEnd - flick.height) / 2; + } + + onSelectedItemChanged: flick.propagateSelection(index, selectedItem); - Connections { - target: model - onDetailsChanged: { - if (selectedItem != -1) { - scroller.propagateSelection(-1, -1); - scroller.propagateSelection(index, selectedItem); - } + Connections { + target: model + onDetailsChanged: { + if (selectedItem != -1) { + flick.propagateSelection(-1, -1); + flick.propagateSelection(index, selectedItem); } } } } + } - Repeater { - id: repeater - model: timelineModel - } + Repeater { + id: repeater + model: timelineModel } } } -- cgit v1.2.3