- hide all wallpaper settings if feature is disabled - hide wallpaper selector if feature is disabled - hide quick access wallpaper if feature is disabled
368 lines
10 KiB
QML
368 lines
10 KiB
QML
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Layouts
|
|
import Quickshell
|
|
import Quickshell.Wayland
|
|
import qs.Modules.SettingsPanel.Tabs as Tabs
|
|
import qs.Commons
|
|
import qs.Services
|
|
import qs.Widgets
|
|
|
|
NPanel {
|
|
id: root
|
|
|
|
panelWidth: {
|
|
var w = Math.round(Math.max(screen?.width * 0.4, 1000) * scaling)
|
|
w = Math.min(w, screen?.width - Style.marginL * 2)
|
|
return w
|
|
}
|
|
panelHeight: {
|
|
var h = Math.round(Math.max(screen?.height * 0.75, 800) * scaling)
|
|
h = Math.min(h, screen?.height - Style.barHeight * scaling - Style.marginL * 2)
|
|
return h
|
|
}
|
|
panelAnchorHorizontalCenter: true
|
|
panelAnchorVerticalCenter: true
|
|
|
|
// Enable keyboard focus for settings panel
|
|
panelKeyboardFocus: true
|
|
|
|
// Tabs enumeration, order is NOT relevant
|
|
enum Tab {
|
|
About,
|
|
AudioService,
|
|
Bar,
|
|
Launcher,
|
|
Brightness,
|
|
ColorScheme,
|
|
Display,
|
|
General,
|
|
Network,
|
|
ScreenRecorder,
|
|
TimeWeather,
|
|
Wallpaper,
|
|
WallpaperSelector
|
|
}
|
|
|
|
property int requestedTab: SettingsPanel.Tab.General
|
|
property int currentTabIndex: 0
|
|
property var tabsModel: []
|
|
|
|
Connections {
|
|
target: Settings.data.wallpaper
|
|
function onEnabledChanged() {
|
|
updateTabsModel()
|
|
}
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
updateTabsModel()
|
|
}
|
|
|
|
Component {
|
|
id: generalTab
|
|
Tabs.GeneralTab {}
|
|
}
|
|
Component {
|
|
id: launcherTab
|
|
Tabs.LauncherTab {}
|
|
}
|
|
Component {
|
|
id: barTab
|
|
Tabs.BarTab {}
|
|
}
|
|
|
|
Component {
|
|
id: audioTab
|
|
Tabs.AudioTab {}
|
|
}
|
|
Component {
|
|
id: brightnessTab
|
|
Tabs.BrightnessTab {}
|
|
}
|
|
Component {
|
|
id: displayTab
|
|
Tabs.DisplayTab {}
|
|
}
|
|
Component {
|
|
id: networkTab
|
|
Tabs.NetworkTab {}
|
|
}
|
|
Component {
|
|
id: timeWeatherTab
|
|
Tabs.TimeWeatherTab {}
|
|
}
|
|
Component {
|
|
id: colorSchemeTab
|
|
Tabs.ColorSchemeTab {}
|
|
}
|
|
Component {
|
|
id: wallpaperTab
|
|
Tabs.WallpaperTab {}
|
|
}
|
|
Component {
|
|
id: wallpaperSelectorTab
|
|
Tabs.WallpaperSelectorTab {}
|
|
}
|
|
Component {
|
|
id: screenRecorderTab
|
|
Tabs.ScreenRecorderTab {}
|
|
}
|
|
Component {
|
|
id: aboutTab
|
|
Tabs.AboutTab {}
|
|
}
|
|
|
|
// Order *DOES* matter
|
|
function updateTabsModel() {
|
|
let newTabs = [{
|
|
"id": SettingsPanel.Tab.General,
|
|
"label": "General",
|
|
"icon": "tune",
|
|
"source": generalTab
|
|
}, {
|
|
"id": SettingsPanel.Tab.Bar,
|
|
"label": "Bar",
|
|
"icon": "web_asset",
|
|
"source": barTab
|
|
}, {
|
|
"id": SettingsPanel.Tab.Launcher,
|
|
"label": "Launcher",
|
|
"icon": "apps",
|
|
"source": launcherTab
|
|
}, {
|
|
"id": SettingsPanel.Tab.AudioService,
|
|
"label": "Audio",
|
|
"icon": "volume_up",
|
|
"source": audioTab
|
|
}, {
|
|
"id": SettingsPanel.Tab.Display,
|
|
"label": "Display",
|
|
"icon": "monitor",
|
|
"source": displayTab
|
|
}, {
|
|
"id": SettingsPanel.Tab.Network,
|
|
"label": "Network",
|
|
"icon": "lan",
|
|
"source": networkTab
|
|
}, {
|
|
"id": SettingsPanel.Tab.Brightness,
|
|
"label": "Brightness",
|
|
"icon": "brightness_6",
|
|
"source": brightnessTab
|
|
}, {
|
|
"id": SettingsPanel.Tab.TimeWeather,
|
|
"label": "Time & Weather",
|
|
"icon": "schedule",
|
|
"source": timeWeatherTab
|
|
}, {
|
|
"id": SettingsPanel.Tab.ColorScheme,
|
|
"label": "Color Scheme",
|
|
"icon": "palette",
|
|
"source": colorSchemeTab
|
|
}, {
|
|
"id": SettingsPanel.Tab.Wallpaper,
|
|
"label": "Wallpaper",
|
|
"icon": "image",
|
|
"source": wallpaperTab
|
|
}]
|
|
|
|
// Only add the Wallpaper Selector tab if the feature is enabled
|
|
if (Settings.data.wallpaper.enabled) {
|
|
newTabs.push({
|
|
"id": SettingsPanel.Tab.WallpaperSelector,
|
|
"label": "Wallpaper Selector",
|
|
"icon": "wallpaper_slideshow",
|
|
"source": wallpaperSelectorTab
|
|
})
|
|
}
|
|
|
|
newTabs.push({
|
|
"id": SettingsPanel.Tab.ScreenRecorder,
|
|
"label": "Screen Recorder",
|
|
"icon": "videocam",
|
|
"source": screenRecorderTab
|
|
}, {
|
|
"id": SettingsPanel.Tab.About,
|
|
"label": "About",
|
|
"icon": "info",
|
|
"source": aboutTab
|
|
})
|
|
|
|
root.tabsModel = newTabs // Assign the generated list to the model
|
|
}
|
|
// When the panel opens, choose the appropriate tab
|
|
onOpened: {
|
|
updateTabsModel()
|
|
|
|
var initialIndex = SettingsPanel.Tab.General
|
|
if (root.requestedTab !== null) {
|
|
for (var i = 0; i < root.tabsModel.length; i++) {
|
|
if (root.tabsModel[i].id === root.requestedTab) {
|
|
initialIndex = i
|
|
break
|
|
}
|
|
}
|
|
}
|
|
// Now that the UI is settled, set the current tab index.
|
|
root.currentTabIndex = initialIndex
|
|
}
|
|
|
|
panelContent: Rectangle {
|
|
anchors.fill: parent
|
|
anchors.margins: Style.marginL * scaling
|
|
color: Color.transparent
|
|
|
|
RowLayout {
|
|
anchors.fill: parent
|
|
spacing: Style.marginM * scaling
|
|
|
|
Rectangle {
|
|
id: sidebar
|
|
Layout.preferredWidth: 220 * scaling
|
|
Layout.fillHeight: true
|
|
color: Color.mSurfaceVariant
|
|
border.color: Color.mOutline
|
|
border.width: Math.max(1, Style.borderS * scaling)
|
|
radius: Style.radiusM * scaling
|
|
|
|
Column {
|
|
anchors.fill: parent
|
|
anchors.margins: Style.marginS * scaling
|
|
spacing: Style.marginXS * 1.5 * scaling
|
|
|
|
Repeater {
|
|
id: sections
|
|
model: root.tabsModel
|
|
delegate: Rectangle {
|
|
id: tabItem
|
|
width: parent.width
|
|
height: 32 * scaling
|
|
radius: Style.radiusS * scaling
|
|
color: selected ? Color.mPrimary : (tabItem.hovering ? Color.mTertiary : Color.transparent)
|
|
readonly property bool selected: index === currentTabIndex
|
|
property bool hovering: false
|
|
property color tabTextColor: selected ? Color.mOnPrimary : (tabItem.hovering ? Color.mOnTertiary : Color.mOnSurface)
|
|
|
|
Behavior on color {
|
|
ColorAnimation {
|
|
duration: Style.animationFast
|
|
}
|
|
}
|
|
|
|
Behavior on tabTextColor {
|
|
ColorAnimation {
|
|
duration: Style.animationFast
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
anchors.fill: parent
|
|
anchors.leftMargin: Style.marginS * scaling
|
|
anchors.rightMargin: Style.marginS * scaling
|
|
spacing: Style.marginS * scaling
|
|
// Tab icon on the left side
|
|
NIcon {
|
|
text: modelData.icon
|
|
color: tabTextColor
|
|
font.pointSize: Style.fontSizeL * scaling
|
|
}
|
|
// Tab label on the left side
|
|
NText {
|
|
text: modelData.label
|
|
color: tabTextColor
|
|
font.pointSize: Style.fontSizeM * scaling
|
|
font.weight: Style.fontWeightBold
|
|
Layout.fillWidth: true
|
|
}
|
|
}
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
acceptedButtons: Qt.LeftButton
|
|
onEntered: tabItem.hovering = true
|
|
onExited: tabItem.hovering = false
|
|
onCanceled: tabItem.hovering = false
|
|
onClicked: currentTabIndex = index
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Content
|
|
Rectangle {
|
|
id: contentPane
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
radius: Style.radiusM * scaling
|
|
color: Color.mSurfaceVariant
|
|
border.color: Color.mOutline
|
|
border.width: Math.max(1, Style.borderS * scaling)
|
|
clip: true
|
|
|
|
ColumnLayout {
|
|
id: contentLayout
|
|
anchors.fill: parent
|
|
anchors.margins: Style.marginL * scaling
|
|
spacing: Style.marginS * scaling
|
|
|
|
RowLayout {
|
|
id: headerRow
|
|
Layout.fillWidth: true
|
|
spacing: Style.marginS * scaling
|
|
|
|
// Tab label on the main right side
|
|
NText {
|
|
text: root.tabsModel[currentTabIndex].label
|
|
font.pointSize: Style.fontSizeXL * scaling
|
|
font.weight: Style.fontWeightBold
|
|
color: Color.mPrimary
|
|
Layout.fillWidth: true
|
|
}
|
|
NIconButton {
|
|
icon: "close"
|
|
tooltipText: "Close"
|
|
Layout.alignment: Qt.AlignVCenter
|
|
onClicked: root.close()
|
|
}
|
|
}
|
|
|
|
NDivider {
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
Item {
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
|
|
Repeater {
|
|
model: root.tabsModel
|
|
delegate: Loader {
|
|
anchors.fill: parent
|
|
active: index === root.currentTabIndex
|
|
sourceComponent: ColumnLayout {
|
|
ScrollView {
|
|
id: scrollView
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
|
ScrollBar.vertical.policy: ScrollBar.AsNeeded
|
|
padding: Style.marginL * scaling
|
|
clip: true
|
|
|
|
Loader {
|
|
active: true
|
|
sourceComponent: root.tabsModel[index].source
|
|
width: scrollView.availableWidth
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|