forked from qt-creator/qt-creator
Unify flame graph and timeline details windows
They are mostly the same. Change-Id: I41be570989ecc58cf2ae33f692c89946b55a0e1d Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -57,7 +57,7 @@ Item {
|
||||
anchors.right: flamegraphItem.right
|
||||
anchors.bottom: flamegraphItem.bottom
|
||||
|
||||
FlameGraphText {
|
||||
TimelineText {
|
||||
id: text
|
||||
visible: textVisible
|
||||
anchors.fill: parent
|
||||
|
||||
@@ -1,234 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** 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 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.
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
Item {
|
||||
id: rangeDetails
|
||||
|
||||
property color titleBarColor: "#55a3b8"
|
||||
property color titleBarTextColor: "white"
|
||||
property color contentColor: "white"
|
||||
property color contentTextColor: "black"
|
||||
property color borderColor: "#a0a0a0"
|
||||
property color noteTextColor: "orange"
|
||||
property color buttonSelectedColor: titleBarColor
|
||||
property color buttonHoveredColor: titleBarColor
|
||||
|
||||
property real titleBarHeight: 20
|
||||
property real borderWidth: 1
|
||||
property real outerMargin: 10
|
||||
property real innerMargin: 5
|
||||
property real minimumInnerWidth: 150
|
||||
property real initialWidth: 300
|
||||
|
||||
property real minimumX
|
||||
property real maximumX
|
||||
property real minimumY
|
||||
property real maximumY
|
||||
|
||||
property string dialogTitle
|
||||
property var model
|
||||
property string note
|
||||
|
||||
signal clearSelection
|
||||
|
||||
visible: dialogTitle.length > 0 || model.length > 0
|
||||
|
||||
width: dragHandle.x + dragHandle.width
|
||||
height: contentArea.height + titleBar.height
|
||||
|
||||
onMinimumXChanged: x = Math.max(x, minimumX)
|
||||
onMaximumXChanged: x = Math.min(x, Math.max(minimumX, maximumX - width))
|
||||
onMinimumYChanged: y = Math.max(y, minimumY)
|
||||
onMaximumYChanged: y = Math.min(y, Math.max(minimumY, maximumY - height))
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
drag.target: parent
|
||||
drag.minimumX: parent.minimumX
|
||||
drag.maximumX: parent.maximumX - rangeDetails.width
|
||||
drag.minimumY: parent.minimumY
|
||||
drag.maximumY: parent.maximumY - rangeDetails.height
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: titleBar
|
||||
width: parent.width
|
||||
height: titleBarHeight
|
||||
color: titleBarColor
|
||||
border.width: borderWidth
|
||||
border.color: borderColor
|
||||
|
||||
FlameGraphText {
|
||||
id: typeTitle
|
||||
text: rangeDetails.dialogTitle
|
||||
font.bold: true
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
anchors.left: parent.left
|
||||
anchors.right: closeIcon.left
|
||||
anchors.leftMargin: outerMargin
|
||||
anchors.rightMargin: innerMargin
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
color: titleBarTextColor
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: closeIcon
|
||||
|
||||
implicitWidth: 30
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
onClicked: rangeDetails.clearSelection()
|
||||
|
||||
Image {
|
||||
id: image
|
||||
source: "image://icons/close_window" + (parent.enabled ? "" : "/disabled")
|
||||
width: 16
|
||||
height: 16
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
style: ButtonStyle {
|
||||
background: Rectangle {
|
||||
color: (control.checked || control.pressed)
|
||||
? buttonSelectedColor
|
||||
: control.hovered
|
||||
? buttonHoveredColor
|
||||
: "#00000000"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: contentArea
|
||||
color: contentColor
|
||||
|
||||
anchors.top: titleBar.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: dragHandle.bottom
|
||||
|
||||
border.width: borderWidth
|
||||
border.color: borderColor
|
||||
}
|
||||
|
||||
Grid {
|
||||
id: col
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.top: titleBar.bottom
|
||||
anchors.topMargin: innerMargin
|
||||
anchors.leftMargin: outerMargin
|
||||
anchors.rightMargin: outerMargin
|
||||
|
||||
spacing: innerMargin
|
||||
columns: 2
|
||||
property int minimumWidth: {
|
||||
// max(width of longest label * 2, minimumInnerWidth)
|
||||
var result = minimumInnerWidth;
|
||||
for (var i = 0; i < children.length; ++i) {
|
||||
if (children[i].isLabel)
|
||||
result = Math.max(children[i].implicitWidth * 2 + innerMargin, result);
|
||||
}
|
||||
|
||||
return result + 2 * outerMargin;
|
||||
}
|
||||
|
||||
property int labelWidth: (minimumWidth - innerMargin) / 2 - outerMargin
|
||||
property int valueWidth: dragHandle.x - labelWidth - innerMargin - outerMargin
|
||||
|
||||
onMinimumWidthChanged: {
|
||||
if (dragHandle.x < minimumWidth - outerMargin)
|
||||
dragHandle.x = minimumWidth - outerMargin;
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: rangeDetails.model
|
||||
FlameGraphText {
|
||||
property bool isLabel: index % 2 === 0
|
||||
font.bold: isLabel
|
||||
elide: Text.ElideRight
|
||||
width: isLabel ? col.labelWidth : col.valueWidth
|
||||
text: isLabel ? (modelData + ":") : modelData
|
||||
color: contentTextColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TextEdit {
|
||||
id: noteEdit
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: outerMargin
|
||||
anchors.rightMargin: outerMargin
|
||||
anchors.topMargin: visible ? innerMargin : 0
|
||||
anchors.top: col.bottom
|
||||
height: visible ? implicitHeight : 0
|
||||
|
||||
readOnly: true
|
||||
visible: text.length > 0
|
||||
text: note
|
||||
wrapMode: Text.Wrap
|
||||
color: noteTextColor
|
||||
font.italic: true
|
||||
font.pixelSize: typeTitle.font.pixelSize
|
||||
font.family: typeTitle.font.family
|
||||
renderType: typeTitle.renderType
|
||||
selectByMouse: true
|
||||
}
|
||||
|
||||
Item {
|
||||
id: dragHandle
|
||||
width: outerMargin
|
||||
height: outerMargin
|
||||
x: initialWidth
|
||||
anchors.top: noteEdit.bottom
|
||||
clip: true
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
drag.target: parent
|
||||
drag.minimumX: col.minimumWidth - outerMargin
|
||||
drag.axis: Drag.XAxis
|
||||
cursorShape: Qt.SizeHorCursor
|
||||
}
|
||||
Rectangle {
|
||||
color: titleBarColor
|
||||
rotation: 45
|
||||
width: parent.width * Math.SQRT2
|
||||
height: parent.height * Math.SQRT2
|
||||
x: parent.width - width / 2
|
||||
y: parent.height - height / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** 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 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.
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.0
|
||||
|
||||
Text {
|
||||
font.pixelSize: 12
|
||||
font.family: "sans-serif"
|
||||
textFormat: Text.PlainText
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
@@ -265,21 +265,15 @@ ScrollView {
|
||||
}
|
||||
}
|
||||
|
||||
FlameGraphDetails {
|
||||
RangeDetails {
|
||||
id: tooltip
|
||||
|
||||
minimumX: 0
|
||||
maximumX: flickable.width
|
||||
minimumY: flickable.contentY
|
||||
maximumY: flickable.contentY + flickable.height
|
||||
noteReadonly: true
|
||||
|
||||
titleBarColor: Theme.color(Theme.Timeline_PanelHeaderColor)
|
||||
titleBarTextColor: Theme.color(Theme.PanelTextColorLight)
|
||||
contentColor: Theme.color(Theme.Timeline_PanelBackgroundColor)
|
||||
contentTextColor: Theme.color(Theme.Timeline_TextColor)
|
||||
noteTextColor: Theme.color(Theme.Timeline_HighlightColor)
|
||||
buttonHoveredColor: Theme.color(Theme.FancyToolButtonHoverColor)
|
||||
buttonSelectedColor: Theme.color(Theme.FancyToolButtonSelectedColor)
|
||||
borderWidth: 0
|
||||
|
||||
property var hoveredNode: null;
|
||||
@@ -310,7 +304,7 @@ ScrollView {
|
||||
}
|
||||
|
||||
model: currentNode ? currentNode.details() : []
|
||||
note: currentNode ? currentNode.note() : ""
|
||||
noteText: currentNode ? currentNode.note() : ""
|
||||
|
||||
Connections {
|
||||
target: root.model
|
||||
|
||||
@@ -224,11 +224,12 @@ Rectangle {
|
||||
if (selectedModel !== -1 && selectedModel !== newModel)
|
||||
select(selectedModel, -1);
|
||||
|
||||
rangeDetails.saveNote();
|
||||
selectedItem = newItem
|
||||
selectedModel = newModel
|
||||
if (selectedItem !== -1) {
|
||||
// display details
|
||||
rangeDetails.showInfo(selectedModel, selectedItem);
|
||||
rangeDetails.showInfo();
|
||||
|
||||
// update in other views
|
||||
var model = timelineModelAggregator.models[selectedModel];
|
||||
@@ -362,20 +363,73 @@ Rectangle {
|
||||
x: 200
|
||||
y: 25
|
||||
|
||||
noteReadonly: false
|
||||
clip: true
|
||||
locked: content.selectionLocked
|
||||
models: timelineModelAggregator.models
|
||||
notes: timelineModelAggregator.notes
|
||||
hasContents: false
|
||||
|
||||
onRecenterOnItem: {
|
||||
content.select(selectedModel, selectedItem)
|
||||
}
|
||||
|
||||
onToggleSelectionLocked: {
|
||||
content.selectionLocked = !content.selectionLocked;
|
||||
}
|
||||
|
||||
onClearSelection: {
|
||||
content.propagateSelection(-1, -1);
|
||||
}
|
||||
|
||||
onUpdateNote: {
|
||||
if (timelineModelAggregator.notes && selectedModel != -1 && selectedItem != -1) {
|
||||
timelineModelAggregator.notes.setText(
|
||||
timelineModelAggregator.models[selectedModel].modelId,
|
||||
selectedItem, text);
|
||||
}
|
||||
}
|
||||
|
||||
function hide() {
|
||||
model = [];
|
||||
file = "";
|
||||
line = -1;
|
||||
column = 0;
|
||||
noteText = "";
|
||||
dialogTitle = "";
|
||||
}
|
||||
|
||||
function saveNote() {
|
||||
noteFocus = false;
|
||||
}
|
||||
|
||||
function showInfo() {
|
||||
var timelineModel = timelineModelAggregator.models[selectedModel];
|
||||
var eventData = timelineModel.details(selectedItem)
|
||||
var content = [];
|
||||
for (var k in eventData) {
|
||||
if (k === "displayName") {
|
||||
dialogTitle = eventData[k];
|
||||
} else {
|
||||
content.push(k);
|
||||
content.push(eventData[k]);
|
||||
}
|
||||
}
|
||||
rangeDetails.model = content;
|
||||
|
||||
var location = timelineModel.location(selectedItem)
|
||||
if (location.hasOwnProperty("file")) { // not empty
|
||||
rangeDetails.file = location.file;
|
||||
rangeDetails.line = location.line;
|
||||
rangeDetails.column = location.column;
|
||||
} else {
|
||||
// reset to default values
|
||||
rangeDetails.file = "";
|
||||
rangeDetails.line = 0;
|
||||
rangeDetails.column = -1;
|
||||
}
|
||||
|
||||
var notes = timelineModelAggregator.notes;
|
||||
var noteId = notes ? notes.get(timelineModel.modelId, selectedItem) : -1;
|
||||
rangeDetails.noteText = (noteId !== -1) ? notes.text(noteId) : "";
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
||||
@@ -29,272 +29,213 @@ import TimelineTheme 1.0
|
||||
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 bool hasContents
|
||||
property real titleBarHeight: 20
|
||||
property real borderWidth: 1
|
||||
property real outerMargin: 10
|
||||
property real innerMargin: 5
|
||||
property real minimumInnerWidth: 150
|
||||
property real initialWidth: 300
|
||||
|
||||
property int selectedModel: -1
|
||||
property int selectedItem: -1
|
||||
property real minimumX: 0
|
||||
property real maximumX: parent.width
|
||||
property real minimumY: 0
|
||||
property real maximumY: parent.height
|
||||
|
||||
property bool locked
|
||||
property string dialogTitle: ""
|
||||
property string file: ""
|
||||
property int line: -1
|
||||
property int column: -1
|
||||
|
||||
property var models
|
||||
property var notes
|
||||
property bool locked: false
|
||||
property var model: []
|
||||
|
||||
property alias noteText: noteEdit.text
|
||||
property alias noteFocus: noteEdit.focus
|
||||
property alias noteReadonly: noteEdit.readOnly
|
||||
|
||||
signal recenterOnItem
|
||||
signal toggleSelectionLocked
|
||||
signal clearSelection
|
||||
signal updateNote(string text)
|
||||
|
||||
width: col.width + 20
|
||||
height: hasContents ? contentArea.height + titleBar.height : 0
|
||||
visible: dialogTitle.length > 0 || model.length > 0
|
||||
|
||||
function hide() {
|
||||
noteEdit.focus = false;
|
||||
hasContents = false;
|
||||
selectedModel = selectedItem = -1;
|
||||
noteEdit.text = "";
|
||||
duration = "";
|
||||
label = "";
|
||||
file = "";
|
||||
line = -1;
|
||||
column = 0;
|
||||
isBindingLoop = false;
|
||||
}
|
||||
width: dragHandle.x + dragHandle.width
|
||||
height: contentArea.height + titleBar.height
|
||||
|
||||
Connections {
|
||||
target: rangeDetails.parent
|
||||
// keep inside view
|
||||
onWidthChanged: fitInView();
|
||||
onHeightChanged: fitInView();
|
||||
}
|
||||
onMinimumXChanged: x = Math.max(x, minimumX)
|
||||
onMaximumXChanged: x = Math.min(x, Math.max(minimumX, maximumX - width))
|
||||
onMinimumYChanged: y = Math.max(y, minimumY)
|
||||
onMaximumYChanged: y = Math.min(y, Math.max(minimumY, maximumY - height))
|
||||
|
||||
QtObject {
|
||||
id: eventInfo
|
||||
property bool ready: false
|
||||
property var content: []
|
||||
}
|
||||
|
||||
function showInfo(model, item) {
|
||||
eventInfo.ready = false;
|
||||
// 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.content = [];
|
||||
for (var k in eventData) {
|
||||
if (k === "displayName") {
|
||||
dialogTitle = eventData[k];
|
||||
} else {
|
||||
eventInfo.content.push(k);
|
||||
eventInfo.content.push(eventData[k]);
|
||||
}
|
||||
}
|
||||
eventInfo.ready = true;
|
||||
hasContents = eventInfo.content.length > 0;
|
||||
|
||||
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 ? notes.get(timelineModel.modelId, selectedItem) : -1;
|
||||
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;
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
drag.target: parent
|
||||
drag.minimumX: parent.minimumX
|
||||
drag.maximumX: parent.maximumX - rangeDetails.width
|
||||
drag.minimumY: parent.minimumY
|
||||
drag.maximumY: parent.maximumY - rangeDetails.height
|
||||
onClicked: rangeDetails.recenterOnItem()
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: titleBar
|
||||
width: parent.width
|
||||
height: 20
|
||||
height: titleBarHeight
|
||||
color: Theme.color(Theme.Timeline_PanelHeaderColor)
|
||||
}
|
||||
Item {
|
||||
width: parent.width+1
|
||||
height: 11
|
||||
y: 10
|
||||
clip: true
|
||||
Rectangle {
|
||||
width: parent.width-1
|
||||
height: 15
|
||||
y: -5
|
||||
color: Theme.color(Theme.Timeline_PanelHeaderColor)
|
||||
border.width: borderWidth
|
||||
border.color: Theme.color(Theme.PanelTextColorMid)
|
||||
|
||||
TimelineText {
|
||||
id: typeTitle
|
||||
text: rangeDetails.dialogTitle
|
||||
font.bold: true
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
anchors.left: parent.left
|
||||
anchors.right: closeIcon.left
|
||||
anchors.leftMargin: outerMargin
|
||||
anchors.rightMargin: innerMargin
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
color: Theme.color(Theme.PanelTextColorLight)
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
ImageToolButton {
|
||||
id: editIcon
|
||||
imageSource: "image://icons/edit"
|
||||
anchors.top: parent.top
|
||||
anchors.right: lockIcon.left
|
||||
implicitHeight: typeTitle.height
|
||||
visible: !rangeDetails.noteReadonly
|
||||
onClicked: noteEdit.focus = true
|
||||
}
|
||||
|
||||
ImageToolButton {
|
||||
id: lockIcon
|
||||
imageSource: "image://icons/lock_" + (locked ? "closed" : "open")
|
||||
anchors.top: closeIcon.top
|
||||
anchors.right: closeIcon.left
|
||||
implicitHeight: typeTitle.height
|
||||
onClicked: rangeDetails.toggleSelectionLocked()
|
||||
}
|
||||
|
||||
ImageToolButton {
|
||||
id: closeIcon
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
implicitHeight: typeTitle.height
|
||||
imageSource: "image://icons/close_window"
|
||||
onClicked: rangeDetails.clearSelection()
|
||||
}
|
||||
}
|
||||
|
||||
//title
|
||||
TimelineText {
|
||||
id: typeTitle
|
||||
text: " "+rangeDetails.dialogTitle
|
||||
font.bold: true
|
||||
height: 20
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
anchors.left: parent.left
|
||||
anchors.right: editIcon.left
|
||||
elide: Text.ElideRight
|
||||
color: Theme.color(Theme.PanelTextColorLight)
|
||||
}
|
||||
|
||||
// Details area
|
||||
Rectangle {
|
||||
id: contentArea
|
||||
color: Theme.color(Theme.Timeline_PanelBackgroundColor)
|
||||
width: parent.width
|
||||
height: 10 + col.height + (noteEdit.visible ? (noteEdit.height + 5) : 0)
|
||||
y: 20
|
||||
|
||||
//details
|
||||
Grid {
|
||||
property int outerMargin: 10
|
||||
property int minimumWidth: 150
|
||||
property int labelWidth: (minimumWidth - spacing) / 2 - outerMargin
|
||||
property int valueWidth: dragHandle.x - labelWidth - spacing - outerMargin
|
||||
|
||||
id: col
|
||||
x: outerMargin
|
||||
y: 5
|
||||
spacing: 5
|
||||
columns: 2
|
||||
|
||||
onChildrenChanged: {
|
||||
// max(width of longest label * 2, 150)
|
||||
var result = 150;
|
||||
for (var i = 0; i < children.length; ++i) {
|
||||
if (children[i].isLabel)
|
||||
result = Math.max(children[i].implicitWidth * 2 + spacing, result);
|
||||
}
|
||||
|
||||
minimumWidth = result + 2 * outerMargin;
|
||||
if (dragHandle.x < minimumWidth - outerMargin)
|
||||
dragHandle.x = minimumWidth - outerMargin;
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: eventInfo.ready ? eventInfo.content : 0
|
||||
Detail {
|
||||
labelWidth: col.labelWidth
|
||||
valueWidth: col.valueWidth
|
||||
isLabel: index % 2 === 0
|
||||
text: isLabel ? (modelData + ":") : modelData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TextEdit {
|
||||
id: noteEdit
|
||||
x: 10
|
||||
anchors.topMargin: 5
|
||||
anchors.bottomMargin: 5
|
||||
anchors.top: col.bottom
|
||||
|
||||
visible: notes && (text.length > 0 || focus)
|
||||
width: col.width
|
||||
wrapMode: Text.Wrap
|
||||
color: Theme.color(Theme.Timeline_HighlightColor)
|
||||
font.italic: true
|
||||
font.pixelSize: typeTitle.font.pixelSize
|
||||
font.family: typeTitle.font.family
|
||||
renderType: typeTitle.renderType
|
||||
selectByMouse: true
|
||||
onTextChanged: saveTimer.restart()
|
||||
onFocusChanged: {
|
||||
if (!focus && selectedModel != -1 && selectedItem != -1) {
|
||||
saveTimer.stop();
|
||||
if (notes)
|
||||
notes.setText(models[selectedModel].modelId, selectedItem, text);
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: saveTimer
|
||||
onTriggered: {
|
||||
if (notes && 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()
|
||||
}
|
||||
|
||||
ImageToolButton {
|
||||
id: editIcon
|
||||
imageSource: "image://icons/edit"
|
||||
anchors.top: closeIcon.top
|
||||
anchors.right: lockIcon.left
|
||||
implicitHeight: typeTitle.height
|
||||
visible: notes
|
||||
onClicked: noteEdit.focus = true
|
||||
}
|
||||
|
||||
ImageToolButton {
|
||||
id: lockIcon
|
||||
imageSource: "image://icons/lock_" + (locked ? "closed" : "open")
|
||||
anchors.top: closeIcon.top
|
||||
anchors.right: closeIcon.left
|
||||
implicitHeight: typeTitle.height
|
||||
onClicked: rangeDetails.toggleSelectionLocked()
|
||||
}
|
||||
|
||||
ImageToolButton {
|
||||
id: closeIcon
|
||||
anchors.top: titleBar.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
implicitHeight: typeTitle.height
|
||||
imageSource: "image://icons/close_window"
|
||||
onClicked: rangeDetails.clearSelection()
|
||||
anchors.bottom: dragHandle.bottom
|
||||
|
||||
border.width: borderWidth
|
||||
border.color: Theme.color(Theme.PanelTextColorMid)
|
||||
}
|
||||
|
||||
Grid {
|
||||
id: col
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.top: titleBar.bottom
|
||||
anchors.topMargin: innerMargin
|
||||
anchors.leftMargin: outerMargin
|
||||
anchors.rightMargin: outerMargin
|
||||
|
||||
spacing: innerMargin
|
||||
columns: 2
|
||||
property int minimumWidth: {
|
||||
// max(width of longest label * 2, minimumInnerWidth)
|
||||
var result = minimumInnerWidth;
|
||||
for (var i = 0; i < children.length; ++i) {
|
||||
if (children[i].isLabel)
|
||||
result = Math.max(children[i].implicitWidth * 2 + innerMargin, result);
|
||||
}
|
||||
|
||||
return result + 2 * outerMargin;
|
||||
}
|
||||
|
||||
property int labelWidth: (minimumWidth - innerMargin) / 2 - outerMargin
|
||||
property int valueWidth: dragHandle.x - labelWidth - innerMargin - outerMargin
|
||||
|
||||
onMinimumWidthChanged: {
|
||||
if (dragHandle.x < minimumWidth - outerMargin)
|
||||
dragHandle.x = minimumWidth - outerMargin;
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: rangeDetails.model
|
||||
Detail {
|
||||
labelWidth: col.labelWidth
|
||||
valueWidth: col.valueWidth
|
||||
isLabel: index % 2 === 0
|
||||
text: isLabel ? (modelData + ":") : modelData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TextEdit {
|
||||
id: noteEdit
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: outerMargin
|
||||
anchors.rightMargin: outerMargin
|
||||
anchors.topMargin: visible ? innerMargin : 0
|
||||
anchors.top: col.bottom
|
||||
height: visible ? implicitHeight : 0
|
||||
|
||||
readOnly: rangeDetails.noteReadonly
|
||||
visible: (text.length > 0 || focus)
|
||||
wrapMode: Text.Wrap
|
||||
color: Theme.color(Theme.Timeline_HighlightColor)
|
||||
font.italic: true
|
||||
font.pixelSize: typeTitle.font.pixelSize
|
||||
font.family: typeTitle.font.family
|
||||
renderType: typeTitle.renderType
|
||||
selectByMouse: true
|
||||
onTextChanged: saveTimer.restart()
|
||||
onFocusChanged: {
|
||||
if (!focus) {
|
||||
saveTimer.stop();
|
||||
if (!readOnly)
|
||||
rangeDetails.updateNote(text);
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: saveTimer
|
||||
onTriggered: {
|
||||
if (!rangeDetails.readOnly)
|
||||
rangeDetails.updateNote(noteEdit.text);
|
||||
}
|
||||
interval: 1000
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Item {
|
||||
id: dragHandle
|
||||
width: 10
|
||||
height: 10
|
||||
x: 300
|
||||
anchors.bottom: parent.bottom
|
||||
width: outerMargin
|
||||
height: outerMargin
|
||||
x: initialWidth
|
||||
anchors.top: noteEdit.bottom
|
||||
clip: true
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
drag.target: parent
|
||||
drag.minimumX: col.minimumWidth - col.outerMargin
|
||||
drag.minimumX: col.minimumWidth - outerMargin
|
||||
drag.axis: Drag.XAxis
|
||||
cursorShape: Qt.SizeHorCursor
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
<file>CategoryLabel.qml</file>
|
||||
<file>Detail.qml</file>
|
||||
<file>FlameGraphDelegate.qml</file>
|
||||
<file>FlameGraphDetails.qml</file>
|
||||
<file>FlameGraphText.qml</file>
|
||||
<file>FlameGraphView.qml</file>
|
||||
<file>ico_edit.png</file>
|
||||
<file>ico_edit@2x.png</file>
|
||||
|
||||
Reference in New Issue
Block a user