mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-08-03 08:48:40 +02:00
[ui] NodeEditor: refactor ChunksList and add global stats
This commit is contained in:
parent
bd5d447d12
commit
831443c29d
9 changed files with 415 additions and 307 deletions
|
@ -10,57 +10,87 @@ import "common.js" as Common
|
|||
/**
|
||||
* ChunkListView
|
||||
*/
|
||||
ListView {
|
||||
id: chunksLV
|
||||
ColumnLayout {
|
||||
id: root
|
||||
property variant chunks
|
||||
property int currentIndex: 0
|
||||
property variant currentChunk: (chunks && currentIndex >= 0) ? chunks.at(currentIndex) : undefined
|
||||
|
||||
// model: node.chunks
|
||||
onChunksChanged: {
|
||||
// When the list changes, ensure the current index is in the new range
|
||||
if(currentIndex >= chunks.count)
|
||||
currentIndex = chunks.count-1
|
||||
}
|
||||
|
||||
property variant currentChunk: currentItem ? currentItem.chunk : undefined
|
||||
// chunksSummary is in sync with allChunks button (but not directly accessible as it is in a Component)
|
||||
property bool chunksSummary: (currentIndex === -1)
|
||||
|
||||
width: 60
|
||||
Layout.fillHeight: true
|
||||
highlightFollowsCurrentItem: true
|
||||
keyNavigationEnabled: true
|
||||
focus: true
|
||||
currentIndex: 0
|
||||
|
||||
signal changeCurrentChunk(int chunkIndex)
|
||||
ListView {
|
||||
id: chunksLV
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
header: Component {
|
||||
Label {
|
||||
width: chunksLV.width
|
||||
elide: Label.ElideRight
|
||||
text: "Chunks"
|
||||
padding: 4
|
||||
z: 10
|
||||
background: Rectangle { color: parent.palette.window }
|
||||
model: root.chunks
|
||||
|
||||
highlightFollowsCurrentItem: (root.chunksSummary === false)
|
||||
keyNavigationEnabled: true
|
||||
focus: true
|
||||
currentIndex: root.currentIndex
|
||||
onCurrentIndexChanged: {
|
||||
if(chunksLV.currentIndex !== root.currentIndex)
|
||||
{
|
||||
// When the list is resized, the currentIndex is reset to 0.
|
||||
// So here we force it to keep the binding.
|
||||
chunksLV.currentIndex = Qt.binding(function() { return root.currentIndex })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
highlight: Component {
|
||||
Rectangle {
|
||||
color: activePalette.highlight
|
||||
opacity: 0.3
|
||||
z: 2
|
||||
header: Component {
|
||||
Button {
|
||||
id: allChunks
|
||||
text: "Chunks"
|
||||
width: parent.width
|
||||
flat: true
|
||||
checkable: true
|
||||
property bool summaryEnabled: root.chunksSummary
|
||||
checked: summaryEnabled
|
||||
onSummaryEnabledChanged: {
|
||||
checked = summaryEnabled
|
||||
}
|
||||
onClicked: {
|
||||
root.currentIndex = -1
|
||||
checked = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
highlightMoveDuration: 0
|
||||
highlightResizeDuration: 0
|
||||
highlight: Component {
|
||||
Rectangle {
|
||||
visible: true // !root.chunksSummary
|
||||
color: activePalette.highlight
|
||||
opacity: 0.3
|
||||
z: 2
|
||||
}
|
||||
}
|
||||
highlightMoveDuration: 0
|
||||
highlightResizeDuration: 0
|
||||
|
||||
delegate: ItemDelegate {
|
||||
id: chunkDelegate
|
||||
property var chunk: object
|
||||
text: index
|
||||
width: parent.width
|
||||
leftPadding: 8
|
||||
onClicked: {
|
||||
chunksLV.forceActiveFocus()
|
||||
chunksLV.changeCurrentChunk(index)
|
||||
}
|
||||
Rectangle {
|
||||
width: 4
|
||||
height: parent.height
|
||||
color: Common.getChunkColor(parent.chunk)
|
||||
delegate: ItemDelegate {
|
||||
id: chunkDelegate
|
||||
property var chunk: object
|
||||
text: index
|
||||
width: parent.width
|
||||
leftPadding: 8
|
||||
onClicked: {
|
||||
chunksLV.forceActiveFocus()
|
||||
root.currentIndex = index
|
||||
}
|
||||
Rectangle {
|
||||
width: 4
|
||||
height: parent.height
|
||||
color: Common.getChunkColor(parent.chunk)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.4
|
||||
import QtQuick.Controls 1.4 as Controls1 // SplitView
|
||||
import QtQuick.Layouts 1.3
|
||||
import MaterialIcons 2.2
|
||||
import Controls 1.0
|
||||
|
@ -19,15 +20,6 @@ Panel {
|
|||
signal attributeDoubleClicked(var mouse, var attribute)
|
||||
signal upgradeRequest()
|
||||
|
||||
Item {
|
||||
id: m
|
||||
property int chunkCurrentIndex: 0
|
||||
}
|
||||
|
||||
onNodeChanged: {
|
||||
m.chunkCurrentIndex = 0 // Needed to avoid invalid state of ChunksListView
|
||||
}
|
||||
|
||||
title: "Node" + (node !== null ? " - <b>" + node.label + "</b>" : "")
|
||||
icon: MaterialLabel { text: MaterialIcons.tune }
|
||||
|
||||
|
@ -114,7 +106,16 @@ Panel {
|
|||
Component {
|
||||
id: editor_component
|
||||
|
||||
ColumnLayout {
|
||||
Controls1.SplitView {
|
||||
anchors.fill: parent
|
||||
|
||||
// The list of chunks
|
||||
ChunksListView {
|
||||
id: chunksLV
|
||||
visible: (tabBar.currentIndex >= 1 && tabBar.currentIndex <= 3)
|
||||
chunks: root.node.chunks
|
||||
}
|
||||
|
||||
StackLayout {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
|
@ -122,35 +123,65 @@ Panel {
|
|||
currentIndex: tabBar.currentIndex
|
||||
|
||||
AttributeEditor {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
model: root.node.attributes
|
||||
readOnly: root.readOnly || root.isCompatibilityNode
|
||||
onAttributeDoubleClicked: root.attributeDoubleClicked(mouse, attribute)
|
||||
onUpgradeRequest: root.upgradeRequest()
|
||||
}
|
||||
|
||||
NodeLog {
|
||||
id: nodeLog
|
||||
node: root.node
|
||||
chunkCurrentIndex: m.chunkCurrentIndex
|
||||
onChangeCurrentChunk: { m.chunkCurrentIndex = chunkIndex }
|
||||
Loader {
|
||||
active: (tabBar.currentIndex === 1)
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
sourceComponent: NodeLog {
|
||||
// anchors.fill: parent
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
id: nodeLog
|
||||
node: root.node
|
||||
currentChunkIndex: chunksLV.currentIndex
|
||||
currentChunk: chunksLV.currentChunk
|
||||
}
|
||||
}
|
||||
|
||||
NodeStatistics {
|
||||
id: nodeStatistics
|
||||
node: root.node
|
||||
chunkCurrentIndex: m.chunkCurrentIndex
|
||||
onChangeCurrentChunk: { m.chunkCurrentIndex = chunkIndex }
|
||||
Loader {
|
||||
active: (tabBar.currentIndex === 2)
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
sourceComponent: NodeStatistics {
|
||||
id: nodeStatistics
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
node: root.node
|
||||
currentChunkIndex: chunksLV.currentIndex
|
||||
currentChunk: chunksLV.currentChunk
|
||||
}
|
||||
}
|
||||
|
||||
NodeStatus {
|
||||
id: nodeStatus
|
||||
node: root.node
|
||||
chunkCurrentIndex: m.chunkCurrentIndex
|
||||
onChangeCurrentChunk: { m.chunkCurrentIndex = chunkIndex }
|
||||
Loader {
|
||||
active: (tabBar.currentIndex === 3)
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
sourceComponent: NodeStatus {
|
||||
id: nodeStatus
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
node: root.node
|
||||
currentChunkIndex: chunksLV.currentIndex
|
||||
currentChunk: chunksLV.currentChunk
|
||||
}
|
||||
}
|
||||
|
||||
NodeDocumentation {
|
||||
id: nodeDocumentation
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
node: root.node
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import QtQuick 2.11
|
||||
import QtQuick.Controls 2.3
|
||||
import QtQuick.Controls 1.4 as Controls1 // SplitView
|
||||
import QtQuick.Layouts 1.3
|
||||
import MaterialIcons 2.2
|
||||
import Controls 1.0
|
||||
|
@ -16,53 +15,34 @@ import "common.js" as Common
|
|||
FocusScope {
|
||||
id: root
|
||||
property variant node
|
||||
property alias chunkCurrentIndex: chunksLV.currentIndex
|
||||
signal changeCurrentChunk(int chunkIndex)
|
||||
property int currentChunkIndex
|
||||
property variant currentChunk
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
SystemPalette { id: activePalette }
|
||||
|
||||
Controls1.SplitView {
|
||||
Loader {
|
||||
id: componentLoader
|
||||
clip: true
|
||||
anchors.fill: parent
|
||||
|
||||
// The list of chunks
|
||||
ChunksListView {
|
||||
id: chunksLV
|
||||
Layout.fillHeight: true
|
||||
model: node.chunks
|
||||
onChangeCurrentChunk: root.changeCurrentChunk(chunkIndex)
|
||||
}
|
||||
property string currentFile: (root.currentChunkIndex >= 0 && root.currentChunk) ? root.currentChunk["logFile"] : ""
|
||||
property url source: Filepath.stringToUrl(currentFile)
|
||||
|
||||
Loader {
|
||||
id: componentLoader
|
||||
clip: true
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
property url source
|
||||
sourceComponent: textFileViewerComponent
|
||||
}
|
||||
|
||||
property string currentFile: chunksLV.currentChunk ? chunksLV.currentChunk["logFile"] : ""
|
||||
onCurrentFileChanged: {
|
||||
// only set text file viewer source when ListView is fully ready
|
||||
// (either empty or fully populated with a valid currentChunk)
|
||||
// to avoid going through an empty url when switching between two nodes
|
||||
Component {
|
||||
id: textFileViewerComponent
|
||||
|
||||
if(!chunksLV.count || chunksLV.currentChunk)
|
||||
componentLoader.source = Filepath.stringToUrl(currentFile);
|
||||
|
||||
}
|
||||
|
||||
sourceComponent: textFileViewerComponent
|
||||
}
|
||||
|
||||
Component {
|
||||
id: textFileViewerComponent
|
||||
TextFileViewer {
|
||||
id: textFileViewer
|
||||
source: componentLoader.source
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
autoReload: chunksLV.currentChunk !== undefined && chunksLV.currentChunk.statusName === "RUNNING"
|
||||
// source is set in fileSelector
|
||||
}
|
||||
TextFileViewer {
|
||||
id: textFileViewer
|
||||
anchors.fill: parent
|
||||
source: componentLoader.source
|
||||
autoReload: root.currentChunk !== undefined && root.currentChunk.statusName === "RUNNING"
|
||||
// source is set in fileSelector
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import QtQuick.Controls 1.4 as Controls1 // SplitView
|
|||
import QtQuick.Layouts 1.3
|
||||
import MaterialIcons 2.2
|
||||
import Controls 1.0
|
||||
import Utils 1.0
|
||||
|
||||
import "common.js" as Common
|
||||
|
||||
|
@ -15,50 +16,44 @@ import "common.js" as Common
|
|||
*/
|
||||
FocusScope {
|
||||
id: root
|
||||
|
||||
property variant node
|
||||
property alias chunkCurrentIndex: chunksLV.currentIndex
|
||||
signal changeCurrentChunk(int chunkIndex)
|
||||
property variant currentChunkIndex
|
||||
property variant currentChunk
|
||||
|
||||
SystemPalette { id: activePalette }
|
||||
|
||||
Controls1.SplitView {
|
||||
Loader {
|
||||
id: componentLoader
|
||||
clip: true
|
||||
anchors.fill: parent
|
||||
property string currentFile: currentChunk ? currentChunk["statisticsFile"] : ""
|
||||
property url source: Filepath.stringToUrl(currentFile)
|
||||
|
||||
// The list of chunks
|
||||
ChunksListView {
|
||||
id: chunksLV
|
||||
Layout.fillHeight: true
|
||||
model: node.chunks
|
||||
onChangeCurrentChunk: root.changeCurrentChunk(chunkIndex)
|
||||
sourceComponent: chunksLV.chunksSummary ? statViewerComponent : chunkStatViewerComponent
|
||||
}
|
||||
|
||||
Component {
|
||||
id: chunkStatViewerComponent
|
||||
StatViewer {
|
||||
id: statViewer
|
||||
anchors.fill: parent
|
||||
source: componentLoader.source
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: componentLoader
|
||||
clip: true
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
property url source
|
||||
Component {
|
||||
id: statViewerComponent
|
||||
|
||||
property string currentFile: chunksLV.currentChunk ? chunksLV.currentChunk["statisticsFile"] : ""
|
||||
onCurrentFileChanged: {
|
||||
// only set text file viewer source when ListView is fully ready
|
||||
// (either empty or fully populated with a valid currentChunk)
|
||||
// to avoid going through an empty url when switching between two nodes
|
||||
|
||||
if(!chunksLV.count || chunksLV.currentChunk)
|
||||
componentLoader.source = Filepath.stringToUrl(currentFile);
|
||||
Column {
|
||||
spacing: 2
|
||||
KeyValue {
|
||||
key: "Time"
|
||||
value: Format.sec2time(node.elapsedTime)
|
||||
}
|
||||
|
||||
sourceComponent: statViewerComponent
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statViewerComponent
|
||||
StatViewer {
|
||||
id: statViewer
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
source: componentLoader.source
|
||||
KeyValue {
|
||||
key: "Cumulated Time"
|
||||
value: Format.sec2time(node.recursiveElapsedTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import QtQuick 2.11
|
||||
import QtQuick.Controls 2.3
|
||||
import QtQuick.Controls 1.4 as Controls1 // SplitView
|
||||
import QtQuick.Layouts 1.3
|
||||
import MaterialIcons 2.2
|
||||
import Controls 1.0
|
||||
|
@ -16,169 +15,148 @@ import "common.js" as Common
|
|||
FocusScope {
|
||||
id: root
|
||||
property variant node
|
||||
property alias chunkCurrentIndex: chunksLV.currentIndex
|
||||
signal changeCurrentChunk(int chunkIndex)
|
||||
property variant currentChunkIndex
|
||||
property variant currentChunk
|
||||
|
||||
SystemPalette { id: activePalette }
|
||||
|
||||
Controls1.SplitView {
|
||||
Loader {
|
||||
id: componentLoader
|
||||
clip: true
|
||||
anchors.fill: parent
|
||||
|
||||
// The list of chunks
|
||||
ChunksListView {
|
||||
id: chunksLV
|
||||
Layout.fillHeight: true
|
||||
model: node.chunks
|
||||
onChangeCurrentChunk: root.changeCurrentChunk(chunkIndex)
|
||||
}
|
||||
property string currentFile: (root.currentChunkIndex >= 0) ? root.currentChunk["statusFile"] : ""
|
||||
property url source: Filepath.stringToUrl(currentFile)
|
||||
|
||||
Loader {
|
||||
id: componentLoader
|
||||
clip: true
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
property url source
|
||||
sourceComponent: statViewerComponent
|
||||
}
|
||||
|
||||
property string currentFile: chunksLV.currentChunk ? chunksLV.currentChunk["statusFile"] : ""
|
||||
onCurrentFileChanged: {
|
||||
// only set text file viewer source when ListView is fully ready
|
||||
// (either empty or fully populated with a valid currentChunk)
|
||||
// to avoid going through an empty url when switching between two nodes
|
||||
Component {
|
||||
id: statViewerComponent
|
||||
Item {
|
||||
id: statusViewer
|
||||
property url source: componentLoader.source
|
||||
property var lastModified: undefined
|
||||
|
||||
if(!chunksLV.count || chunksLV.currentChunk)
|
||||
componentLoader.source = Filepath.stringToUrl(currentFile);
|
||||
onSourceChanged: {
|
||||
statusListModel.readSourceFile()
|
||||
}
|
||||
|
||||
sourceComponent: statViewerComponent
|
||||
}
|
||||
ListModel {
|
||||
id: statusListModel
|
||||
|
||||
Component {
|
||||
id: statViewerComponent
|
||||
Item {
|
||||
id: statusViewer
|
||||
property url source: componentLoader.source
|
||||
property var lastModified: undefined
|
||||
function readSourceFile() {
|
||||
// make sure we are trying to load a statistics file
|
||||
if(!Filepath.urlToString(source).endsWith("status"))
|
||||
return;
|
||||
|
||||
onSourceChanged: {
|
||||
statusListModel.readSourceFile()
|
||||
}
|
||||
var xhr = new XMLHttpRequest;
|
||||
xhr.open("GET", source);
|
||||
|
||||
ListModel {
|
||||
id: statusListModel
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
|
||||
// console.warn("StatusListModel: read valid file")
|
||||
if(lastModified === undefined || lastModified !== xhr.getResponseHeader('Last-Modified')) {
|
||||
lastModified = xhr.getResponseHeader('Last-Modified')
|
||||
try {
|
||||
var jsonObject = JSON.parse(xhr.responseText);
|
||||
|
||||
function readSourceFile() {
|
||||
// make sure we are trying to load a statistics file
|
||||
if(!Filepath.urlToString(source).endsWith("status"))
|
||||
return;
|
||||
|
||||
var xhr = new XMLHttpRequest;
|
||||
xhr.open("GET", source);
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
|
||||
// console.warn("StatusListModel: read valid file")
|
||||
if(lastModified === undefined || lastModified !== xhr.getResponseHeader('Last-Modified')) {
|
||||
lastModified = xhr.getResponseHeader('Last-Modified')
|
||||
try {
|
||||
var jsonObject = JSON.parse(xhr.responseText);
|
||||
|
||||
var entries = [];
|
||||
// prepare data to populate the ListModel from the input json object
|
||||
for(var key in jsonObject)
|
||||
{
|
||||
var entry = {};
|
||||
entry["key"] = key;
|
||||
entry["value"] = String(jsonObject[key]);
|
||||
entries.push(entry);
|
||||
}
|
||||
// reset the model with prepared data (limit to one update event)
|
||||
statusListModel.clear();
|
||||
statusListModel.append(entries);
|
||||
}
|
||||
catch(exc)
|
||||
var entries = [];
|
||||
// prepare data to populate the ListModel from the input json object
|
||||
for(var key in jsonObject)
|
||||
{
|
||||
// console.warn("StatusListModel: failed to read file")
|
||||
lastModified = undefined;
|
||||
statusListModel.clear();
|
||||
var entry = {};
|
||||
entry["key"] = key;
|
||||
entry["value"] = String(jsonObject[key]);
|
||||
entries.push(entry);
|
||||
}
|
||||
// reset the model with prepared data (limit to one update event)
|
||||
statusListModel.clear();
|
||||
statusListModel.append(entries);
|
||||
}
|
||||
catch(exc)
|
||||
{
|
||||
// console.warn("StatusListModel: failed to read file")
|
||||
lastModified = undefined;
|
||||
statusListModel.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// console.warn("StatusListModel: invalid file")
|
||||
lastModified = undefined;
|
||||
statusListModel.clear();
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// console.warn("StatusListModel: invalid file")
|
||||
lastModified = undefined;
|
||||
statusListModel.clear();
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: statusListView
|
||||
anchors.fill: parent
|
||||
spacing: 3
|
||||
model: statusListModel
|
||||
ListView {
|
||||
id: statusListView
|
||||
anchors.fill: parent
|
||||
spacing: 3
|
||||
model: statusListModel
|
||||
|
||||
delegate: Rectangle {
|
||||
color: activePalette.window
|
||||
delegate: Rectangle {
|
||||
color: activePalette.window
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
RowLayout {
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
RowLayout {
|
||||
width: parent.width
|
||||
Rectangle {
|
||||
id: statusKey
|
||||
anchors.margins: 2
|
||||
// height: statusValue.height
|
||||
color: Qt.darker(activePalette.window, 1.1)
|
||||
Layout.preferredWidth: sizeHandle.x
|
||||
Layout.minimumWidth: 10.0 * Qt.application.font.pixelSize
|
||||
Layout.maximumWidth: 15.0 * Qt.application.font.pixelSize
|
||||
Layout.fillWidth: false
|
||||
Layout.fillHeight: true
|
||||
Label {
|
||||
text: key
|
||||
anchors.fill: parent
|
||||
anchors.top: parent.top
|
||||
topPadding: 4
|
||||
leftPadding: 6
|
||||
verticalAlignment: TextEdit.AlignTop
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
Rectangle {
|
||||
id: statusKey
|
||||
anchors.margins: 2
|
||||
// height: statusValue.height
|
||||
color: Qt.darker(activePalette.window, 1.1)
|
||||
Layout.preferredWidth: sizeHandle.x
|
||||
Layout.minimumWidth: 10.0 * Qt.application.font.pixelSize
|
||||
Layout.maximumWidth: 15.0 * Qt.application.font.pixelSize
|
||||
Layout.fillWidth: false
|
||||
Layout.fillHeight: true
|
||||
Label {
|
||||
text: key
|
||||
anchors.fill: parent
|
||||
anchors.top: parent.top
|
||||
topPadding: 4
|
||||
leftPadding: 6
|
||||
verticalAlignment: TextEdit.AlignTop
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
TextArea {
|
||||
id: statusValue
|
||||
text: value
|
||||
anchors.margins: 2
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Label.WrapAtWordBoundaryOrAnywhere
|
||||
textFormat: TextEdit.PlainText
|
||||
}
|
||||
TextArea {
|
||||
id: statusValue
|
||||
text: value
|
||||
anchors.margins: 2
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Label.WrapAtWordBoundaryOrAnywhere
|
||||
textFormat: TextEdit.PlainText
|
||||
|
||||
readOnly: true
|
||||
selectByMouse: true
|
||||
background: Rectangle { anchors.fill: parent; color: Qt.darker(activePalette.window, 1.05) }
|
||||
}
|
||||
readOnly: true
|
||||
selectByMouse: true
|
||||
background: Rectangle { anchors.fill: parent; color: Qt.darker(activePalette.window, 1.05) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Categories resize handle
|
||||
Rectangle {
|
||||
id: sizeHandle
|
||||
height: parent.contentHeight
|
||||
width: 1
|
||||
x: parent.width * 0.2
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
anchors.margins: -4
|
||||
cursorShape: Qt.SizeHorCursor
|
||||
drag {
|
||||
target: parent
|
||||
axis: Drag.XAxis
|
||||
threshold: 0
|
||||
minimumX: statusListView.width * 0.2
|
||||
maximumX: statusListView.width * 0.8
|
||||
}
|
||||
// Categories resize handle
|
||||
Rectangle {
|
||||
id: sizeHandle
|
||||
height: parent.contentHeight
|
||||
width: 1
|
||||
x: parent.width * 0.2
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
anchors.margins: -4
|
||||
cursorShape: Qt.SizeHorCursor
|
||||
drag {
|
||||
target: parent
|
||||
axis: Drag.XAxis
|
||||
threshold: 0
|
||||
minimumX: statusListView.width * 0.2
|
||||
maximumX: statusListView.width * 0.8
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue