status-desktop/monitoring/MonitorEntryPoint.qml

384 lines
14 KiB
QML

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import Monitoring 1.0
import Qt.labs.settings 1.0
import AppLayouts.Wallet.stores 1.0 as WalletStores
import shared.stores 1.0 as SharedStores
Component {
ColumnLayout {
spacing: 0
Settings {
property alias tabIndex: tabBar.currentIndex
property alias modelObjectName: objectNameTextFiled.text
property alias modelObjectRootName: rootTextField.text
}
TabBar {
id: tabBar
Layout.fillWidth: true
Layout.bottomMargin: 10
TabButton {
text: "Context properties inspection"
}
TabButton {
text: "Models inspection"
}
currentIndex: swipeView.currentIndex
}
StackLayout {
id: swipeView
currentIndex: tabBar.currentIndex
//anchors.fill: parent
Layout.fillWidth: true
Layout.fillHeight: true
SplitView {
id: root
ColumnLayout {
SplitView.fillHeight: true
SplitView.preferredWidth: 450
spacing: 5
Label {
Layout.fillWidth: true
Layout.margins: 5
text: "Context properties:"
font.bold: true
}
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: 5
model: Monitor.contexPropertiesModel
clip: true
spacing: 5
delegate: Item {
implicitWidth: delegateRow.implicitWidth
implicitHeight: delegateRow.implicitHeight
readonly property var contextPropertyValue:
MonitorUtils.contextPropertyBindingHelper(name, root).value
Row {
id: delegateRow
Label {
text: name
}
Label {
text: ` [${MonitorUtils.typeName(contextPropertyValue)}]`
color: "darkgreen"
}
Label {
text: ` (${MonitorUtils.valueToString(contextPropertyValue)})`
color: "darkred"
}
}
MouseArea {
anchors.fill: parent
onClicked: {
inspectionStackView.clear()
const props = {
name: name,
objectForInspection: contextPropertyValue
}
inspectionStackView.push(inspectionList, props)
}
}
}
}
}
Component {
id: modelInspectionComponent
ModelInspectionPane {}
}
Component {
id: inspectionList
Pane {
id: inspectionPanel
property var objectForInspection
property string name
onObjectForInspectionChanged: {
inspectionModel.clear()
if (!objectForInspection)
return
const items = []
for (const property in objectForInspection) {
const type = typeof objectForInspection[property]
if (type === "function") {
items.push({
name: property,
category: "functions",
isModel: false,
type: type
})
} else {
const value = objectForInspection[property]
const detailedType = MonitorUtils.typeName(value)
const isModel = Monitor.isModel(value)
items.push({
name: property,
type: detailedType,
category: isModel? "models" : "properties",
isModel: isModel
})
}
}
items.sort((a, b) => {
const nameA = a.category
const nameB = b.category
if (nameA === nameB)
return 0
if (nameA === "models")
return -1
if (nameB === "models")
return 1
if (nameA < nameB)
return -1
if (nameA > nameB)
return 1
})
inspectionModel.append(items)
}
ColumnLayout {
anchors.fill: parent
anchors.margins: 5
Label {
text: name
font.pixelSize: 20
font.bold: true
}
MenuSeparator {
Layout.fillWidth: true
}
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 5
clip: true
model: ListModel {
id: inspectionModel
}
delegate: Item {
implicitWidth: delegateRow.implicitWidth
implicitHeight: delegateRow.implicitHeight
Row {
id: delegateRow
readonly property var object: objectForInspection[name]
Label {
text: name
}
Loader {
active: type !== "function"
sourceComponent: Label {
text: ` [${type}]`
color: "darkgreen"
}
}
Loader {
active: type !== "function"
sourceComponent: Label {
text: ` (${MonitorUtils.valueToString(delegateRow.object)})`
color: "darkred"
}
}
Loader {
active: isModel
sourceComponent: Label {
text: `, ${delegateRow.object.rowCount()} items`
color: "darkred"
font.bold: true
}
}
}
MouseArea {
anchors.fill: parent
onClicked: {
if (!isModel)
return
const props = {
name: name,
model: objectForInspection[name]
}
inspectionStackView.push(modelInspectionComponent,
props, StackView.Immediate)
}
}
}
section.property: "category"
section.delegate: Pane {
leftPadding: 0
Label {
text: section
font.bold: true
}
}
}
}
}
}
StackView {
id: inspectionStackView
SplitView.fillHeight: true
SplitView.minimumWidth: 100
}
}
Item {
ColumnLayout {
anchors.fill: parent
Label {
Layout.fillWidth: true
wrapMode: Text.Wrap
text: "Note: 'applicationWindow' is good root object in"
+ " most cases. 'WalletStores.RootStore' and"
+ " `SharedStores.RootStore` are also exposed for"
+ " convenience for models created within those singletons. \n\n"
+ " Hack (see #15181): If you want to inspect a model that is not"
+ " from the root object (under a repeater), add objectName to a dummy object in AppMain.qml: \n"
+ " property var modelIWantToInspect: SortFilterProxyModel { \n"
+ " objectName: \"YYY\" \n"
+ " } \n"
+ " and inside your item add something like this: \n"
+ " Component.onCompleted: appMain.modelIWantToInspect.sourceModel = this.model \n"
+ " Then you can use 'YYY' as the object name in this search."
}
RowLayout {
Layout.fillHeight: false
Layout.fillWidth: true
Label {
text: "Model's object name:"
}
TextField {
id: objectNameTextFiled
selectByMouse: true
}
Label {
text: "Root:"
}
TextField {
id: rootTextField
text: "applicationWindow"
selectByMouse: true
}
Button {
text: "Search"
onClicked: {
let rootObj = null
try {
rootObj = eval(rootTextField.text)
} catch (error) {
objLabel.objStr = "Root object not found!"
return
}
const obj = Monitor.findChild(
rootObj, objectNameTextFiled.text)
objLabel.objStr = obj && Monitor.isModel(obj)
? obj.toString() : "Model not found!"
rolesModelContent.model = obj
}
}
}
Label {
id: objLabel
property string objStr
Layout.fillWidth: true
visible: objStr !== ""
text: "Object: " + objStr
}
ModelInspectionPane {
id: rolesModelContent
showControls: false
Layout.fillWidth: true
Layout.fillHeight: true
}
}
}
}
}
}