ApplicationDetails.qml 8.14 KB
Newer Older
1
2
3
4
5
6
/*
 * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
 *
 * SPDX-License-Identifier: LGPL-2.0-or-later
 */

7
8
9
10
import QtQuick 2.12
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.2

11
12
import Qt.labs.qmlmodels 1.0

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import org.kde.kirigami 2.4 as Kirigami

import org.kde.kitemmodels 1.0 as KItemModels
import org.kde.quickcharts 1.0 as Charts

import org.kde.ksysguard.formatter 1.0 as Formatter
import org.kde.ksysguard.process 1.0 as Process
import org.kde.ksysguard.sensors 1.0 as Sensors
import org.kde.ksysguard.table 1.0 as Table

Page {
    id: root

    property var applications: []

    readonly property var firstApplication: applications.length > 0 ? applications[0] : null

    property real headerHeight: Kirigami.Units.gridUnit

    signal close()

    Kirigami.Theme.colorSet: Kirigami.Theme.View

36
37
38
39
40
    background: Rectangle {
        Kirigami.Theme.inherit: false
        Kirigami.Theme.colorSet: Kirigami.Theme.View
        color: Kirigami.Theme.backgroundColor
    }
41
42
43
44
45
46

    header: ToolBar {
        implicitHeight: root.headerHeight
        Kirigami.Theme.inherit: false
        Kirigami.Theme.colorSet: Kirigami.Theme.Window

47
48
49
50
        Label {
            anchors.left: parent.left
            text: i18nc("@title:window", "Details")
        }
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

        ToolButton {
            anchors.right: parent.right
            anchors.verticalCenter: parent.verticalCenter
            height: Math.min(root.headerHeight, implicitHeight)
            width: height
            icon.name: "dialog-close"
            onClicked: root.close()
        }
    }

    ColumnLayout {
        visible: root.firstApplication != null

        anchors {
            fill: parent
            leftMargin: Kirigami.Units.largeSpacing
            rightMargin: Kirigami.Units.largeSpacing
            topMargin: Kirigami.Units.smallSpacing
        }

        Label {
73
            text: i18nc("@title:group", "CPU")
74
75
76
77
78
79
80
81
82
83
84
85
        }

        LineChartCard {
            Layout.fillHeight: false
            Layout.preferredHeight: Kirigami.Units.gridUnit * 3

            yRange { from: 0; to: 100; automatic: false }
            xRange { from: 0; to: 50 }
            unit: Formatter.Units.UnitPercent

            colorSource: Charts.SingleValueSource { value: Kirigami.Theme.negativeTextColor }
            valueSources: [
86
                Charts.HistoryProxySource {
87
                    id: cpuHistory
88
89
90
                    source: Charts.SingleValueSource {
                        value: root.firstApplication ? root.firstApplication.cpu / cpuCountSensor.value : 0
                    }
91
                    maximumHistory: 50
92
                    interval: 2000
93
94
                }
            ]
95
96

            Sensors.Sensor { id: cpuCountSensor; sensorId: "system/cores/cores" }
97
98
        }
        Label {
99
            text: i18nc("@title:group", "Memory")
100
101
102
103
104
        }
        LineChartCard {
            Layout.fillHeight: false
            Layout.preferredHeight: Kirigami.Units.gridUnit * 3

105
            yRange { from: 0; to: totalMemorySensor.value ? totalMemorySensor.value : 0; automatic: false }
106
107
108
109
110
            xRange { from: 0; to: 50 }
            unit: totalMemorySensor.unit

            colorSource: Charts.SingleValueSource { value: Kirigami.Theme.positiveTextColor }
            valueSources: [
111
                Charts.HistoryProxySource {
112
                    id: memoryHistory
113
114
115
116
                    source: Charts.SingleValueSource {
                        // ProcessDataModel memory is in KiB but our y range is in B so convert memory correctly.
                        value: root.firstApplication ? root.firstApplication.memory * 1024 : 0
                    }
117
                    maximumHistory: 50
118
                    interval: 2000
119
120
121
                }
            ]

122
            Sensors.Sensor { id: totalMemorySensor; sensorId: "memory/physical/total" }
123
124
        }
        Label {
125
            text: i18nc("@title:group", "Network")
126
127
128
129
130
131
132
133
134
        }
        LineChartCard {
            Layout.fillHeight: false
            Layout.preferredHeight: Kirigami.Units.gridUnit * 3

            xRange { from: 0; to: 50 }
            unit: Formatter.Units.UnitKiloByteRate

            valueSources: [
135
                Charts.HistoryProxySource {
136
                    id: netInboundHistory
137
                    source: Charts.SingleValueSource { value: root.firstApplication ? root.firstApplication.netInbound : 0; }
138
                    maximumHistory: 50
139
                    interval: 2000
140
                },
141
                Charts.HistoryProxySource {
142
                    id: netOutboundHistory
143
                    source: Charts.SingleValueSource { value: root.firstApplication ? root.firstApplication.netOutbound : 0; }
144
                    maximumHistory: 50
145
                    interval: 2000
146
147
148
149
                }
            ]
        }
        Label {
150
            text: i18nc("@title:group", "Disk")
151
152
153
154
155
156
157
158
159
160
161
162
163
        }
        LineChartCard {
            Layout.fillHeight: false
            Layout.preferredHeight: Kirigami.Units.gridUnit * 3

            xRange { from: 0; to: 50 }
            unit: Formatter.Units.UnitKiloByteRate

            valueSources: [
                Charts.ValueHistorySource {
                    id: diskReadHistory
                    value: root.firstApplication ? root.firstApplication.diskRead : 0;
                    maximumHistory: 50
164
                    interval: 2000
165
166
167
168
169
                },
                Charts.ValueHistorySource {
                    id: diskWriteHistory
                    value: root.firstApplication ? root.firstApplication.diskWrite : 0;
                    maximumHistory: 50
170
                    interval: 2000
171
172
173
174
                }
            ]
        }

175
176
177
        Label {
            text: i18nc("@title:group", "Processes: %1", processTable.rows || " ")
        }
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

        Rectangle {
            Layout.fillWidth: true
            Layout.fillHeight: true
            Layout.leftMargin: -Kirigami.Units.largeSpacing;
            Layout.rightMargin: -Kirigami.Units.largeSpacing;

            color: Kirigami.Theme.backgroundColor
            Kirigami.Theme.colorSet: Kirigami.Theme.View

            Table.BaseTableView {
                id: processTable

                anchors.fill: parent

                columnWidths: [0.5, 0.25, 0.25]
                sortName: "name"
                idRole: Process.ProcessDataModel.Attribute

197
                onSort: sortFilter.sort(column, order)
198

199
200
                model: Table.ProcessSortFilterModel {
                    id: sortFilter
201
                    sourceModel: processModel
202
203
                    hiddenAttributes: ["pid"]
                    filterPids: root.firstApplication ? root.firstApplication.pids : []
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
                }

                Process.ProcessDataModel {
                    id: processModel

                    enabled: root.visible && root.firstApplication != null

                    enabledAttributes: [
                        "name",
                        "usage",
                        "vmPSS",
                        "pid",
                    ]
                }

219
220
221
222
223
224
225
226
227
228
                delegate: DelegateChooser {
                    role: "Attribute"
                    DelegateChoice {
                        roleValue: "usage"
                        Table.BasicCellDelegate {
                            text: Formatter.Formatter.formatValue(parseInt(model.Value) / model.Maximum * 100, model.Unit)
                        }
                    }
                    DelegateChoice { Table.BasicCellDelegate { } }
                }
229
230
231
232
233
234
235
236
237
            }

            Kirigami.Separator { anchors.bottom: processTable.top; width: parent.width }
        }
    }

    Label {
        anchors.fill: parent
        anchors.margins: Kirigami.Units.largeSpacing
238
        text: i18nc("@info:placeholder", "Select an application to see its details.")
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignVCenter
        wrapMode: Text.WordWrap
        visible: root.firstApplication == null
    }

    onApplicationsChanged: {
        cpuHistory.clear()
        memoryHistory.clear()
        netInboundHistory.clear()
        netOutboundHistory.clear()
        diskReadHistory.clear()
        diskWriteHistory.clear()
    }
    onFirstApplicationChanged: {
        sortFilter.invalidate()
    }
}