dashboard: dynamic dashboard tabs + fix performance settings updating (#1253)
* [CI] chore: update flake * Dashboard perf settings save, visibility on none enabled * Dashboard heigh stutter fixed, persist current tab * restore binding * wrapper async=false * ScriptModel, centralized tabs/panes, individual toggle * fixes, missed mediaUpdateInterval, passing values --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
0d56db3b6c
commit
3e0360401b
8 changed files with 220 additions and 104 deletions
|
|
@ -258,7 +258,8 @@ Singleton {
|
|||
return {
|
||||
enabled: dashboard.enabled,
|
||||
showOnHover: dashboard.showOnHover,
|
||||
updateInterval: dashboard.updateInterval,
|
||||
mediaUpdateInterval: dashboard.mediaUpdateInterval,
|
||||
resourceUpdateInterval: dashboard.resourceUpdateInterval,
|
||||
dragThreshold: dashboard.dragThreshold,
|
||||
performance: {
|
||||
showBattery: dashboard.performance.showBattery,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ JsonObject {
|
|||
property int mediaUpdateInterval: 500
|
||||
property int resourceUpdateInterval: 1000
|
||||
property int dragThreshold: 50
|
||||
property bool showDashboard: true
|
||||
property bool showMedia: true
|
||||
property bool showPerformance: true
|
||||
property bool showWeather: true
|
||||
property Sizes sizes: Sizes {}
|
||||
property Performance performance: Performance {}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,15 +22,22 @@ Item {
|
|||
// General Settings
|
||||
property bool enabled: Config.dashboard.enabled ?? true
|
||||
property bool showOnHover: Config.dashboard.showOnHover ?? true
|
||||
property int updateInterval: Config.dashboard.updateInterval ?? 1000
|
||||
property int mediaUpdateInterval: Config.dashboard.mediaUpdateInterval ?? 1000
|
||||
property int resourceUpdateInterval: Config.dashboard.resourceUpdateInterval ?? 1000
|
||||
property int dragThreshold: Config.dashboard.dragThreshold ?? 50
|
||||
|
||||
|
||||
// Dashboard Tabs
|
||||
property bool showDashboard: Config.dashboard.showDashboard ?? true
|
||||
property bool showMedia: Config.dashboard.showMedia ?? true
|
||||
property bool showPerformance: Config.dashboard.showPerformance ?? true
|
||||
property bool showWeather: Config.dashboard.showWeather ?? true
|
||||
|
||||
// Performance Resources
|
||||
property bool showBattery: Config.dashboard.performance.showBattery ?? false
|
||||
property bool showGpu: Config.dashboard.performance.showGpu ?? true
|
||||
property bool showCpu: Config.dashboard.performance.showCpu ?? true
|
||||
property bool showMemory: Config.dashboard.performance.showMemory ?? true
|
||||
property bool showStorage: Config.dashboard.performance.showStorage ?? true
|
||||
property bool showStorage: Config.dashboard.performance.showStorage ?? true
|
||||
property bool showNetwork: Config.dashboard.performance.showNetwork ?? true
|
||||
|
||||
anchors.fill: parent
|
||||
|
|
@ -38,8 +45,13 @@ Item {
|
|||
function saveConfig() {
|
||||
Config.dashboard.enabled = root.enabled;
|
||||
Config.dashboard.showOnHover = root.showOnHover;
|
||||
Config.dashboard.updateInterval = root.updateInterval;
|
||||
Config.dashboard.mediaUpdateInterval = root.mediaUpdateInterval;
|
||||
Config.dashboard.resourceUpdateInterval = root.resourceUpdateInterval;
|
||||
Config.dashboard.dragThreshold = root.dragThreshold;
|
||||
Config.dashboard.showDashboard = root.showDashboard;
|
||||
Config.dashboard.showMedia = root.showMedia;
|
||||
Config.dashboard.showPerformance = root.showPerformance;
|
||||
Config.dashboard.showWeather = root.showWeather;
|
||||
Config.dashboard.performance.showBattery = root.showBattery;
|
||||
Config.dashboard.performance.showGpu = root.showGpu;
|
||||
Config.dashboard.performance.showCpu = root.showCpu;
|
||||
|
|
|
|||
|
|
@ -38,44 +38,91 @@ SectionContainer {
|
|||
}
|
||||
}
|
||||
|
||||
SectionContainer {
|
||||
contentSpacing: Appearance.spacing.normal
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Appearance.spacing.normal
|
||||
|
||||
SliderInput {
|
||||
SwitchRow {
|
||||
Layout.fillWidth: true
|
||||
|
||||
label: qsTr("Update interval")
|
||||
value: root.rootItem.updateInterval
|
||||
from: 100
|
||||
to: 10000
|
||||
stepSize: 100
|
||||
suffix: "ms"
|
||||
validator: IntValidator { bottom: 100; top: 10000 }
|
||||
formatValueFunction: (val) => Math.round(val).toString()
|
||||
parseValueFunction: (text) => parseInt(text)
|
||||
|
||||
onValueModified: (newValue) => {
|
||||
root.rootItem.updateInterval = Math.round(newValue);
|
||||
label: qsTr("Show Dashboard tab")
|
||||
checked: root.rootItem.showDashboard
|
||||
onToggled: checked => {
|
||||
root.rootItem.showDashboard = checked;
|
||||
root.rootItem.saveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
SliderInput {
|
||||
SwitchRow {
|
||||
Layout.fillWidth: true
|
||||
|
||||
label: qsTr("Drag threshold")
|
||||
value: root.rootItem.dragThreshold
|
||||
from: 0
|
||||
to: 100
|
||||
suffix: "px"
|
||||
validator: IntValidator { bottom: 0; top: 100 }
|
||||
formatValueFunction: (val) => Math.round(val).toString()
|
||||
parseValueFunction: (text) => parseInt(text)
|
||||
|
||||
onValueModified: (newValue) => {
|
||||
root.rootItem.dragThreshold = Math.round(newValue);
|
||||
label: qsTr("Show Media tab")
|
||||
checked: root.rootItem.showMedia
|
||||
onToggled: checked => {
|
||||
root.rootItem.showMedia = checked;
|
||||
root.rootItem.saveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
SwitchRow {
|
||||
Layout.fillWidth: true
|
||||
label: qsTr("Show Performance tab")
|
||||
checked: root.rootItem.showPerformance
|
||||
onToggled: checked => {
|
||||
root.rootItem.showPerformance = checked;
|
||||
root.rootItem.saveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
SwitchRow {
|
||||
Layout.fillWidth: true
|
||||
label: qsTr("Show Weather tab")
|
||||
checked: root.rootItem.showWeather
|
||||
onToggled: checked => {
|
||||
root.rootItem.showWeather = checked;
|
||||
root.rootItem.saveConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SliderInput {
|
||||
Layout.fillWidth: true
|
||||
|
||||
label: qsTr("Media update interval")
|
||||
value: root.rootItem.mediaUpdateInterval
|
||||
from: 100
|
||||
to: 10000
|
||||
stepSize: 100
|
||||
suffix: "ms"
|
||||
validator: IntValidator {
|
||||
bottom: 100
|
||||
top: 10000
|
||||
}
|
||||
formatValueFunction: val => Math.round(val).toString()
|
||||
parseValueFunction: text => parseInt(text)
|
||||
|
||||
onValueModified: newValue => {
|
||||
root.rootItem.mediaUpdateInterval = Math.round(newValue);
|
||||
root.rootItem.saveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
SliderInput {
|
||||
Layout.fillWidth: true
|
||||
|
||||
label: qsTr("Drag threshold")
|
||||
value: root.rootItem.dragThreshold
|
||||
from: 0
|
||||
to: 100
|
||||
suffix: "px"
|
||||
validator: IntValidator {
|
||||
bottom: 0
|
||||
top: 100
|
||||
}
|
||||
formatValueFunction: val => Math.round(val).toString()
|
||||
parseValueFunction: text => parseInt(text)
|
||||
|
||||
onValueModified: newValue => {
|
||||
root.rootItem.dragThreshold = Math.round(newValue);
|
||||
root.rootItem.saveConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ SectionContainer {
|
|||
opts.push({
|
||||
"label": qsTr("Battery"),
|
||||
"propertyName": "showBattery",
|
||||
"onToggled": function(checked) {
|
||||
"onToggled": function (checked) {
|
||||
root.rootItem.showBattery = checked;
|
||||
root.rootItem.saveConfig();
|
||||
}
|
||||
|
|
@ -41,39 +41,39 @@ SectionContainer {
|
|||
|
||||
if (root.gpuAvailable)
|
||||
opts.push({
|
||||
"label": qsTr("GPU"),
|
||||
"propertyName": "showGpu",
|
||||
"onToggled": function(checked) {
|
||||
root.rootItem.showGpu = checked;
|
||||
root.rootItem.saveConfig();
|
||||
}
|
||||
});
|
||||
"label": qsTr("GPU"),
|
||||
"propertyName": "showGpu",
|
||||
"onToggled": function (checked) {
|
||||
root.rootItem.showGpu = checked;
|
||||
root.rootItem.saveConfig();
|
||||
}
|
||||
});
|
||||
|
||||
opts.push({
|
||||
"label": qsTr("CPU"),
|
||||
"propertyName": "showCpu",
|
||||
"onToggled": function(checked) {
|
||||
"onToggled": function (checked) {
|
||||
root.rootItem.showCpu = checked;
|
||||
root.rootItem.saveConfig();
|
||||
}
|
||||
}, {
|
||||
"label": qsTr("Memory"),
|
||||
"propertyName": "showMemory",
|
||||
"onToggled": function(checked) {
|
||||
"onToggled": function (checked) {
|
||||
root.rootItem.showMemory = checked;
|
||||
root.rootItem.saveConfig();
|
||||
}
|
||||
}, {
|
||||
"label": qsTr("Storage"),
|
||||
"propertyName": "showStorage",
|
||||
"onToggled": function(checked) {
|
||||
"onToggled": function (checked) {
|
||||
root.rootItem.showStorage = checked;
|
||||
root.rootItem.saveConfig();
|
||||
}
|
||||
}, {
|
||||
"label": qsTr("Network"),
|
||||
"propertyName": "showNetwork",
|
||||
"onToggled": function(checked) {
|
||||
"onToggled": function (checked) {
|
||||
root.rootItem.showNetwork = checked;
|
||||
root.rootItem.saveConfig();
|
||||
}
|
||||
|
|
@ -82,4 +82,25 @@ SectionContainer {
|
|||
}
|
||||
}
|
||||
|
||||
SliderInput {
|
||||
Layout.fillWidth: true
|
||||
|
||||
label: qsTr("Resource update interval")
|
||||
value: root.rootItem.resourceUpdateInterval
|
||||
from: 100
|
||||
to: 10000
|
||||
stepSize: 100
|
||||
suffix: "ms"
|
||||
validator: IntValidator {
|
||||
bottom: 100
|
||||
top: 10000
|
||||
}
|
||||
formatValueFunction: val => Math.round(val).toString()
|
||||
parseValueFunction: text => parseInt(text)
|
||||
|
||||
onValueModified: newValue => {
|
||||
root.rootItem.resourceUpdateInterval = Math.round(newValue);
|
||||
root.rootItem.saveConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,37 @@ Item {
|
|||
required property PersistentProperties visibilities
|
||||
required property PersistentProperties state
|
||||
required property FileDialog facePicker
|
||||
|
||||
readonly property var dashboardTabs: {
|
||||
const allTabs = [
|
||||
{
|
||||
component: dashComponent,
|
||||
iconName: "dashboard",
|
||||
text: qsTr("Dashboard"),
|
||||
enabled: Config.dashboard.showDashboard
|
||||
},
|
||||
{
|
||||
component: mediaComponent,
|
||||
iconName: "queue_music",
|
||||
text: qsTr("Media"),
|
||||
enabled: Config.dashboard.showMedia
|
||||
},
|
||||
{
|
||||
component: performanceComponent,
|
||||
iconName: "speed",
|
||||
text: qsTr("Performance"),
|
||||
enabled: Config.dashboard.showPerformance && (Config.dashboard.performance.showCpu || Config.dashboard.performance.showGpu || Config.dashboard.performance.showMemory || Config.dashboard.performance.showStorage || Config.dashboard.performance.showNetwork || Config.dashboard.performance.showBattery)
|
||||
},
|
||||
{
|
||||
component: weatherComponent,
|
||||
iconName: "cloud",
|
||||
text: qsTr("Weather"),
|
||||
enabled: Config.dashboard.showWeather
|
||||
}
|
||||
];
|
||||
return allTabs.filter(tab => tab.enabled);
|
||||
}
|
||||
|
||||
readonly property real nonAnimWidth: view.implicitWidth + viewWrapper.anchors.margins * 2
|
||||
readonly property real nonAnimHeight: tabs.implicitHeight + tabs.anchors.topMargin + view.implicitHeight + viewWrapper.anchors.margins * 2
|
||||
|
||||
|
|
@ -31,6 +62,7 @@ Item {
|
|||
|
||||
nonAnimWidth: root.nonAnimWidth - anchors.margins * 2
|
||||
state: root.state
|
||||
tabs: root.dashboardTabs
|
||||
}
|
||||
|
||||
ClippingRectangle {
|
||||
|
|
@ -86,31 +118,56 @@ Item {
|
|||
RowLayout {
|
||||
id: row
|
||||
|
||||
Pane {
|
||||
index: 0
|
||||
sourceComponent: Dash {
|
||||
visibilities: root.visibilities
|
||||
state: root.state
|
||||
facePicker: root.facePicker
|
||||
Repeater {
|
||||
model: ScriptModel {
|
||||
values: root.dashboardTabs
|
||||
}
|
||||
|
||||
delegate: Loader {
|
||||
id: paneLoader
|
||||
|
||||
required property int index
|
||||
required property var modelData
|
||||
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
||||
sourceComponent: modelData.component
|
||||
|
||||
Component.onCompleted: active = Qt.binding(() => {
|
||||
if (index === view.currentIndex)
|
||||
return true;
|
||||
const vx = Math.floor(view.visibleArea.xPosition * view.contentWidth);
|
||||
const vex = Math.floor(vx + view.visibleArea.widthRatio * view.contentWidth);
|
||||
return (vx >= x && vx <= x + implicitWidth) || (vex >= x && vex <= x + implicitWidth);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
index: 1
|
||||
sourceComponent: Media {
|
||||
visibilities: root.visibilities
|
||||
}
|
||||
Component {
|
||||
id: dashComponent
|
||||
Dash {
|
||||
visibilities: root.visibilities
|
||||
state: root.state
|
||||
facePicker: root.facePicker
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
index: 2
|
||||
sourceComponent: Performance {}
|
||||
Component {
|
||||
id: mediaComponent
|
||||
Media {
|
||||
visibilities: root.visibilities
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
index: 3
|
||||
sourceComponent: Weather {}
|
||||
}
|
||||
Component {
|
||||
id: performanceComponent
|
||||
Performance {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: weatherComponent
|
||||
Weather {}
|
||||
}
|
||||
|
||||
Behavior on contentX {
|
||||
|
|
@ -132,21 +189,4 @@ Item {
|
|||
easing.bezierCurve: Appearance.anim.curves.emphasized
|
||||
}
|
||||
}
|
||||
|
||||
component Pane: Loader {
|
||||
id: pane
|
||||
|
||||
required property int index
|
||||
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
||||
Component.onCompleted: active = Qt.binding(() => {
|
||||
// Always keep current tab loaded
|
||||
if (pane.index === view.currentIndex)
|
||||
return true;
|
||||
const vx = Math.floor(view.visibleArea.xPosition * view.contentWidth);
|
||||
const vex = Math.floor(vx + view.visibleArea.widthRatio * view.contentWidth);
|
||||
return (vx >= x && vx <= x + implicitWidth) || (vex >= x && vex <= x + implicitWidth);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ Item {
|
|||
|
||||
required property real nonAnimWidth
|
||||
required property PersistentProperties state
|
||||
required property var tabs
|
||||
|
||||
readonly property alias count: bar.count
|
||||
|
||||
implicitHeight: bar.implicitHeight + indicator.implicitHeight + indicator.anchors.topMargin + separator.implicitHeight
|
||||
|
|
@ -30,30 +32,18 @@ Item {
|
|||
|
||||
onCurrentIndexChanged: root.state.currentTab = currentIndex
|
||||
|
||||
Tab {
|
||||
iconName: "dashboard"
|
||||
text: qsTr("Dashboard")
|
||||
}
|
||||
Repeater {
|
||||
model: ScriptModel {
|
||||
values: root.tabs
|
||||
}
|
||||
|
||||
Tab {
|
||||
iconName: "queue_music"
|
||||
text: qsTr("Media")
|
||||
}
|
||||
delegate: Tab {
|
||||
required property var modelData
|
||||
|
||||
Tab {
|
||||
iconName: "speed"
|
||||
text: qsTr("Performance")
|
||||
iconName: modelData.iconName
|
||||
text: modelData.text
|
||||
}
|
||||
}
|
||||
|
||||
Tab {
|
||||
iconName: "cloud"
|
||||
text: qsTr("Weather")
|
||||
}
|
||||
|
||||
// Tab {
|
||||
// iconName: "workspaces"
|
||||
// text: qsTr("Workspaces")
|
||||
// }
|
||||
}
|
||||
|
||||
Item {
|
||||
|
|
@ -62,11 +52,13 @@ Item {
|
|||
anchors.top: bar.bottom
|
||||
anchors.topMargin: 5
|
||||
|
||||
implicitWidth: bar.currentItem.implicitWidth
|
||||
implicitWidth: bar.currentItem?.implicitWidth ?? 0
|
||||
implicitHeight: 3
|
||||
|
||||
x: {
|
||||
const tab = bar.currentItem;
|
||||
if (!tab)
|
||||
return 0;
|
||||
const width = (root.nonAnimWidth - bar.spacing * (bar.count - 1)) / bar.count;
|
||||
return width * tab.TabBar.index + (width - tab.implicitWidth) / 2;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ Item {
|
|||
running: true
|
||||
interval: Appearance.anim.durations.extraLarge
|
||||
onTriggered: {
|
||||
content.active = Qt.binding(() => (root.visibilities.dashboard && Config.dashboard.enabled) || root.visible);
|
||||
content.visible = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue