Add wallpaper tab

This commit is contained in:
Ly-sec 2025-08-05 22:17:47 +02:00
parent 69d84752f3
commit 61e852ed51
7 changed files with 1091 additions and 122 deletions

View file

@ -120,7 +120,7 @@ Item {
Column {
id: notificationColumn
anchors.right: parent.right
spacing: window.spacing
spacing: panelWindow.spacing
width: parent.width
clip: false

View file

@ -6,6 +6,7 @@ import QtQuick.Layouts
import QtQuick.Effects
import qs.Settings
import qs.Widgets.SettingsWindow.Tabs
import qs.Widgets.SettingsWindow.Tabs.Components
PanelWindow {
id: panelMain
@ -13,6 +14,8 @@ PanelWindow {
implicitWidth: screen.width / 2
color: "transparent"
property int activeTabIndex: 0
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
@ -56,6 +59,10 @@ PanelWindow {
Display {}
}
Component {
id: wallpaperSettings
Wallpaper {}
}
Rectangle {
id: background
@ -80,7 +87,7 @@ PanelWindow {
Rectangle {
id: settings
color: Theme.backgroundTertiary
color: Theme.backgroundPrimary
anchors {
left: tabs.right
top: parent.top
@ -110,13 +117,50 @@ PanelWindow {
Text {
id: tabName
text: "General"
text: wallpaperSelector.visible ? "Select Wallpaper" : (activeTabIndex === 0 ? "General" :
activeTabIndex === 1 ? "Bar" :
activeTabIndex === 2 ? "Time & Weather" :
activeTabIndex === 3 ? "Recording" :
activeTabIndex === 4 ? "Network" :
activeTabIndex === 5 ? "Display" :
activeTabIndex === 6 ? "Wallpaper" :
activeTabIndex === 7 ? "Misc" :
activeTabIndex === 8 ? "About" : "General")
font.pixelSize: 18
font.bold: true
color: Theme.textPrimary
Layout.fillWidth: true
}
// Wallpaper Selection Button (only visible on Wallpaper tab)
Rectangle {
width: 32
height: 32
radius: 16
color: wallpaperButtonArea.containsMouse ? Theme.accentPrimary : "transparent"
border.color: Theme.accentPrimary
border.width: 1
visible: activeTabIndex === 6 // Wallpaper tab index
Text {
anchors.centerIn: parent
text: "image"
font.family: wallpaperButtonArea.containsMouse ? "Material Symbols Rounded" : "Material Symbols Outlined"
font.pixelSize: 18
color: wallpaperButtonArea.containsMouse ? Theme.onAccent : Theme.accentPrimary
}
MouseArea {
id: wallpaperButtonArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
// Show the wallpaper selector
wallpaperSelector.show();
}
}
}
Rectangle {
width: 32
@ -199,6 +243,12 @@ PanelWindow {
}
}
}
// Wallpaper Selector Component
WallpaperSelector {
id: wallpaperSelector
anchors.fill: parent
}
}
}
@ -217,6 +267,7 @@ PanelWindow {
width: parent.width
spacing: 0
topPadding: 8
bottomPadding: 8
Repeater {
id: repeater
@ -227,140 +278,123 @@ PanelWindow {
{ icon: "photo_camera", text: "Recording" },
{ icon: "wifi", text: "Network" },
{ icon: "monitor", text: "Display" },
{ icon: "wallpaper", text: "Wallpaper" },
{ icon: "settings_suggest", text: "Misc" },
{ icon: "info", text: "About" }
]
delegate: Column {
delegate: Rectangle {
width: tabs.width
height: 40
height: 48
color: "transparent"
Item {
width: parent.width
height: 39
RowLayout {
anchors.fill: parent
spacing: 8
RowLayout {
anchors.fill: parent
spacing: 8
Rectangle {
id: activeIndicator
Layout.leftMargin: 8
Layout.preferredWidth: 3
Layout.preferredHeight: 24
Layout.alignment: Qt.AlignVCenter
radius: 2
color: Theme.accentPrimary
opacity: index === 0 ? 1 : 0
Behavior on opacity { NumberAnimation { duration: 200 } }
}
Label {
id: icon
text: modelData.icon
font.family: "Material Symbols Outlined"
font.pixelSize: 24
color: index === 0 ? Theme.accentPrimary : Theme.textPrimary
opacity: index === 0 ? 1 : 0.8
Layout.leftMargin: 20
Layout.preferredWidth: 24
Layout.preferredHeight: 24
Layout.alignment: Qt.AlignVCenter
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
Label {
id: label
text: modelData.text
font.pixelSize: 12
color: index === 0 ? Theme.accentPrimary : Theme.textSecondary
font.weight: index === 0 ? Font.DemiBold : Font.Normal
Layout.fillWidth: true
Layout.preferredHeight: 24
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.leftMargin: 4
Layout.rightMargin: 16
verticalAlignment: Text.AlignVCenter
}
Rectangle {
id: activeIndicator
Layout.leftMargin: 8
Layout.preferredWidth: 3
Layout.preferredHeight: 24
Layout.alignment: Qt.AlignVCenter
radius: 2
color: Theme.accentPrimary
opacity: index === activeTabIndex ? 1 : 0
Behavior on opacity { NumberAnimation { duration: 200 } }
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onClicked: {
const newComponent = {
0: generalSettings,
1: barSettings,
2: timeWeatherSettings,
3: recordingSettings,
4: networkSettings,
5: displaySettings,
6: miscSettings,
7: aboutSettings
}[index];
const tabNames = [
"General",
"Bar",
"Time & Weather",
"Recording",
"Network",
"Display",
"Misc",
"About"
];
tabName.text = tabNames[index];
if (settingsLoader.opacity === 1) {
settingsLoader2.sourceComponent = newComponent;
settingsLoader.opacity = 0;
settingsLoader2.opacity = 1;
} else {
settingsLoader.sourceComponent = newComponent;
settingsLoader2.opacity = 0;
settingsLoader.opacity = 1;
}
for (let i = 0; i < repeater.count; i++) {
let item = repeater.itemAt(i);
if (item) {
let containerItem = item.children[0];
let rowLayout = containerItem.children[0];
let indicator = rowLayout.children[0];
let icon = rowLayout.children[1];
let label = rowLayout.children[2];
indicator.opacity = i === index ? 1 : 0;
icon.color = i === index ? Theme.accentPrimary : Theme.textPrimary;
icon.opacity = i === index ? 1 : 0.8;
label.color = i === index ? Theme.accentPrimary : Theme.textSecondary;
label.font.weight = i === index ? Font.Bold : Font.Normal;
}
}
}
}
Label {
id: icon
text: modelData.icon
font.family: "Material Symbols Outlined"
font.pixelSize: 24
color: index === activeTabIndex ? Theme.accentPrimary : Theme.textPrimary
opacity: index === activeTabIndex ? 1 : 0.8
Layout.leftMargin: 20
Layout.preferredWidth: 24
Layout.preferredHeight: 24
Layout.alignment: Qt.AlignVCenter
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
Label {
id: label
text: modelData.text
font.pixelSize: 16
color: index === activeTabIndex ? Theme.accentPrimary :
(tabMouseArea.containsMouse ? Theme.accentPrimary : Theme.textSecondary)
font.weight: index === activeTabIndex ? Font.DemiBold :
(tabMouseArea.containsMouse ? Font.DemiBold : Font.Normal)
Layout.fillWidth: true
Layout.preferredHeight: 24
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.leftMargin: 4
Layout.rightMargin: 16
verticalAlignment: Text.AlignVCenter
}
}
MouseArea {
id: tabMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
activeTabIndex = index;
const newComponent = {
0: generalSettings,
1: barSettings,
2: timeWeatherSettings,
3: recordingSettings,
4: networkSettings,
5: displaySettings,
6: wallpaperSettings,
7: miscSettings,
8: aboutSettings
}[index];
const tabNames = [
"General",
"Bar",
"Time & Weather",
"Recording",
"Network",
"Display",
"Wallpaper",
"Misc",
"About"
];
tabName.text = tabNames[index];
if (settingsLoader.opacity === 1) {
settingsLoader2.sourceComponent = newComponent;
settingsLoader.opacity = 0;
settingsLoader2.opacity = 1;
} else {
settingsLoader.sourceComponent = newComponent;
settingsLoader2.opacity = 0;
settingsLoader.opacity = 1;
}
// Tab colors and indicators are now handled by property bindings
}
}
Rectangle {
width: parent.width
height: 1
color: Theme.outline
opacity: 0.6
visible: index < (repeater.count - 1)
anchors.bottom: parent.bottom
}
}
}

View file

@ -0,0 +1,118 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import qs.Settings
import qs.Components
import qs.Services
Rectangle {
id: wallpaperOverlay
anchors.fill: parent
color: Theme.backgroundPrimary
visible: false
z: 1000
// Click outside to close
MouseArea {
anchors.fill: parent
onClicked: {
wallpaperOverlay.visible = false;
}
}
// Content area that stops event propagation
MouseArea {
anchors.fill: parent
anchors.margins: 24
onClicked: {
// Stop event propagation
}
ColumnLayout {
anchors.fill: parent
spacing: 0
// Wallpaper Grid
Item {
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
ScrollView {
anchors.fill: parent
clip: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AsNeeded
GridView {
id: wallpaperGrid
anchors.fill: parent
cellWidth: Math.max(120, (parent.width / 3) - 12)
cellHeight: cellWidth * 0.6
model: WallpaperManager.wallpaperList
cacheBuffer: 64
leftMargin: 8
rightMargin: 8
topMargin: 8
bottomMargin: 8
delegate: Item {
width: wallpaperGrid.cellWidth - 8
height: wallpaperGrid.cellHeight - 8
Rectangle {
id: wallpaperItem
anchors.fill: parent
anchors.margins: 4
color: Theme.surface
radius: 12
border.color: Settings.settings.currentWallpaper === modelData ? Theme.accentPrimary : Theme.outline
border.width: 2
Image {
id: wallpaperImage
anchors.fill: parent
anchors.margins: 4
source: modelData
fillMode: Image.PreserveAspectCrop
asynchronous: true
cache: true
smooth: true
mipmap: true
sourceSize.width: Math.min(width, 480)
sourceSize.height: Math.min(height, 270)
opacity: (wallpaperImage.status == Image.Ready) ? 1.0 : 0.0
Behavior on opacity {
NumberAnimation {
duration: 300
easing.type: Easing.OutCubic
}
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
WallpaperManager.changeWallpaper(modelData);
wallpaperOverlay.visible = false;
}
}
}
}
}
}
}
}
}
// Function to show the overlay and load wallpapers
function show() {
// Ensure wallpapers are loaded
WallpaperManager.loadWallpapers();
wallpaperOverlay.visible = true;
}
}

View file

@ -0,0 +1,802 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import qs.Settings
import qs.Components
import qs.Services
ColumnLayout {
id: root
spacing: 0
anchors.fill: parent
anchors.margins: 0
ScrollView {
id: scrollView
Layout.fillWidth: true
Layout.fillHeight: true
padding: 0
rightPadding: 12
clip: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ColumnLayout {
width: scrollView.availableWidth
spacing: 0
Item {
Layout.fillWidth: true
Layout.preferredHeight: 0
}
ColumnLayout {
spacing: 4
Layout.fillWidth: true
Text {
text: "Wallpaper"
font.pixelSize: 16
font.bold: true
color: Theme.textPrimary
Layout.bottomMargin: 8
}
// Wallpaper Settings Category
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 16
Text {
text: "Wallpaper Settings"
font.pixelSize: 13
font.bold: true
color: Theme.textPrimary
}
// Wallpaper Folder
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Text {
text: "Wallpaper Folder"
font.pixelSize: 13
font.bold: true
color: Theme.textPrimary
}
Text {
text: "Path to your wallpaper folder"
font.pixelSize: 12
color: Theme.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
RowLayout {
spacing: 8
Layout.fillWidth: true
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 40
radius: 16
color: Theme.surfaceVariant
border.color: folderInput.activeFocus ? Theme.accentPrimary : Theme.outline
border.width: 1
TextInput {
id: folderInput
anchors.fill: parent
anchors.leftMargin: 12
anchors.rightMargin: 12
anchors.topMargin: 6
anchors.bottomMargin: 6
text: Settings.settings.wallpaperFolder !== undefined ? Settings.settings.wallpaperFolder : ""
font.family: Theme.fontFamily
font.pixelSize: 13
color: Theme.textPrimary
verticalAlignment: TextInput.AlignVCenter
clip: true
selectByMouse: true
activeFocusOnTab: true
inputMethodHints: Qt.ImhUrlCharactersOnly
onTextChanged: {
Settings.settings.wallpaperFolder = text;
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.IBeamCursor
onClicked: folderInput.forceActiveFocus()
}
}
}
}
}
ColumnLayout {
spacing: 4
Layout.fillWidth: true
Layout.topMargin: 58
Text {
text: "Automation"
font.pixelSize: 16
font.bold: true
color: Theme.textPrimary
Layout.bottomMargin: 8
}
// Random Wallpaper
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
RowLayout {
spacing: 8
Layout.fillWidth: true
ColumnLayout {
spacing: 4
Layout.fillWidth: true
Text {
text: "Random Wallpaper"
font.pixelSize: 13
font.bold: true
color: Theme.textPrimary
}
Text {
text: "Automatically select random wallpapers from the folder"
font.pixelSize: 12
color: Theme.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
}
Rectangle {
id: randomWallpaperSwitch
width: 52
height: 32
radius: 16
color: Settings.settings.randomWallpaper ? Theme.accentPrimary : Theme.surfaceVariant
border.color: Settings.settings.randomWallpaper ? Theme.accentPrimary : Theme.outline
border.width: 2
Rectangle {
id: randomWallpaperThumb
width: 28
height: 28
radius: 14
color: Theme.surface
border.color: Theme.outline
border.width: 1
y: 2
x: Settings.settings.randomWallpaper ? randomWallpaperSwitch.width - width - 2 : 2
Behavior on x {
NumberAnimation {
duration: 200
easing.type: Easing.OutCubic
}
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
Settings.settings.randomWallpaper = !Settings.settings.randomWallpaper;
}
}
}
}
}
// Use Wallpaper Theme
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
RowLayout {
spacing: 8
Layout.fillWidth: true
ColumnLayout {
spacing: 4
Layout.fillWidth: true
Text {
text: "Use Wallpaper Theme"
font.pixelSize: 13
font.bold: true
color: Theme.textPrimary
}
Text {
text: "Automatically adjust theme colors based on wallpaper"
font.pixelSize: 12
color: Theme.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
}
Rectangle {
id: wallpaperThemeSwitch
width: 52
height: 32
radius: 16
color: Settings.settings.useWallpaperTheme ? Theme.accentPrimary : Theme.surfaceVariant
border.color: Settings.settings.useWallpaperTheme ? Theme.accentPrimary : Theme.outline
border.width: 2
Rectangle {
id: wallpaperThemeThumb
width: 28
height: 28
radius: 14
color: Theme.surface
border.color: Theme.outline
border.width: 1
y: 2
x: Settings.settings.useWallpaperTheme ? wallpaperThemeSwitch.width - width - 2 : 2
Behavior on x {
NumberAnimation {
duration: 200
easing.type: Easing.OutCubic
}
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
Settings.settings.useWallpaperTheme = !Settings.settings.useWallpaperTheme;
}
}
}
}
}
// Wallpaper Interval
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
Text {
text: "Wallpaper Interval"
font.pixelSize: 13
font.bold: true
color: Theme.textPrimary
}
Text {
text: "How often to change wallpapers automatically (in seconds)"
font.pixelSize: 12
color: Theme.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
RowLayout {
Layout.fillWidth: true
Text {
text: Settings.settings.wallpaperInterval + " seconds"
font.pixelSize: 13
color: Theme.textPrimary
}
Item {
Layout.fillWidth: true
}
}
Slider {
id: intervalSlider
Layout.fillWidth: true
from: 10
to: 900
stepSize: 10
value: Settings.settings.wallpaperInterval
snapMode: Slider.SnapAlways
onMoved: {
Settings.settings.wallpaperInterval = Math.round(value);
}
background: Rectangle {
x: intervalSlider.leftPadding
y: intervalSlider.topPadding + intervalSlider.availableHeight / 2 - height / 2
implicitWidth: 200
implicitHeight: 4
width: intervalSlider.availableWidth
height: implicitHeight
radius: 2
color: Theme.surfaceVariant
Rectangle {
width: intervalSlider.visualPosition * parent.width
height: parent.height
color: Theme.accentPrimary
radius: 2
}
}
handle: Rectangle {
x: intervalSlider.leftPadding + intervalSlider.visualPosition * (intervalSlider.availableWidth - width)
y: intervalSlider.topPadding + intervalSlider.availableHeight / 2 - height / 2
implicitWidth: 20
implicitHeight: 20
radius: 10
color: intervalSlider.pressed ? Theme.surfaceVariant : Theme.surface
border.color: Theme.accentPrimary
border.width: 2
}
}
}
}
}
ColumnLayout {
spacing: 4
Layout.fillWidth: true
Layout.topMargin: 58
Text {
text: "SWWW"
font.pixelSize: 16
font.bold: true
color: Theme.textPrimary
Layout.bottomMargin: 8
}
// Use SWWW
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
RowLayout {
spacing: 8
Layout.fillWidth: true
ColumnLayout {
spacing: 4
Layout.fillWidth: true
Text {
text: "Use SWWW"
font.pixelSize: 13
font.bold: true
color: Theme.textPrimary
}
Text {
text: "Use SWWW daemon for advanced wallpaper management"
font.pixelSize: 12
color: Theme.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
}
Rectangle {
id: swwwSwitch
width: 52
height: 32
radius: 16
color: Settings.settings.useSWWW ? Theme.accentPrimary : Theme.surfaceVariant
border.color: Settings.settings.useSWWW ? Theme.accentPrimary : Theme.outline
border.width: 2
Rectangle {
id: swwwThumb
width: 28
height: 28
radius: 14
color: Theme.surface
border.color: Theme.outline
border.width: 1
y: 2
x: Settings.settings.useSWWW ? swwwSwitch.width - width - 2 : 2
Behavior on x {
NumberAnimation {
duration: 200
easing.type: Easing.OutCubic
}
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
Settings.settings.useSWWW = !Settings.settings.useSWWW;
}
}
}
}
}
// SWWW Settings (only visible when useSWWW is enabled)
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
visible: Settings.settings.useSWWW
// Resize Mode
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Text {
text: "Resize Mode"
font.pixelSize: 13
font.bold: true
color: Theme.textPrimary
}
Text {
text: "How SWWW should resize wallpapers to fit the screen"
font.pixelSize: 12
color: Theme.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 40
radius: 16
color: Theme.surfaceVariant
border.color: resizeComboBox.activeFocus ? Theme.accentPrimary : Theme.outline
border.width: 1
ComboBox {
id: resizeComboBox
anchors.fill: parent
anchors.leftMargin: 12
anchors.rightMargin: 12
anchors.topMargin: 6
anchors.bottomMargin: 6
model: ["no", "crop", "fit", "stretch"]
currentIndex: model.indexOf(Settings.settings.wallpaperResize)
onActivated: {
Settings.settings.wallpaperResize = model[index];
}
background: Rectangle {
color: "transparent"
}
contentItem: Text {
text: resizeComboBox.displayText
font: resizeComboBox.font
color: Theme.textPrimary
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
}
popup: Popup {
y: resizeComboBox.height
width: resizeComboBox.width
implicitHeight: contentItem.implicitHeight
padding: 1
contentItem: ListView {
clip: true
implicitHeight: contentHeight
model: resizeComboBox.popup.visible ? resizeComboBox.delegateModel : null
currentIndex: resizeComboBox.highlightedIndex
ScrollIndicator.vertical: ScrollIndicator { }
}
background: Rectangle {
color: Theme.surface
border.color: Theme.outline
border.width: 1
radius: 8
}
}
delegate: ItemDelegate {
width: resizeComboBox.width
contentItem: Text {
text: modelData
color: Theme.textPrimary
font: resizeComboBox.font
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
}
highlighted: resizeComboBox.highlightedIndex === index
background: Rectangle {
color: parent.highlighted ? Theme.accentPrimary : "transparent"
}
}
}
}
}
// Transition Type
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
Text {
text: "Transition Type"
font.pixelSize: 13
font.bold: true
color: Theme.textPrimary
}
Text {
text: "Animation type when switching between wallpapers"
font.pixelSize: 12
color: Theme.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 40
radius: 16
color: Theme.surfaceVariant
border.color: transitionTypeComboBox.activeFocus ? Theme.accentPrimary : Theme.outline
border.width: 1
ComboBox {
id: transitionTypeComboBox
anchors.fill: parent
anchors.leftMargin: 12
anchors.rightMargin: 12
anchors.topMargin: 6
anchors.bottomMargin: 6
model: ["none", "simple", "fade", "left", "right", "top", "bottom", "wipe", "wave", "grow", "center", "any", "outer", "random"]
currentIndex: model.indexOf(Settings.settings.transitionType)
onActivated: {
Settings.settings.transitionType = model[index];
}
background: Rectangle {
color: "transparent"
}
contentItem: Text {
text: transitionTypeComboBox.displayText
font: transitionTypeComboBox.font
color: Theme.textPrimary
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
}
popup: Popup {
y: transitionTypeComboBox.height
width: transitionTypeComboBox.width
implicitHeight: contentItem.implicitHeight
padding: 1
contentItem: ListView {
clip: true
implicitHeight: contentHeight
model: transitionTypeComboBox.popup.visible ? transitionTypeComboBox.delegateModel : null
currentIndex: transitionTypeComboBox.highlightedIndex
ScrollIndicator.vertical: ScrollIndicator { }
}
background: Rectangle {
color: Theme.surface
border.color: Theme.outline
border.width: 1
radius: 8
}
}
delegate: ItemDelegate {
width: transitionTypeComboBox.width
contentItem: Text {
text: modelData
color: Theme.textPrimary
font: transitionTypeComboBox.font
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
}
highlighted: transitionTypeComboBox.highlightedIndex === index
background: Rectangle {
color: parent.highlighted ? Theme.accentPrimary : "transparent"
}
}
}
}
}
// Transition FPS
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
Text {
text: "Transition FPS"
font.pixelSize: 13
font.bold: true
color: Theme.textPrimary
}
Text {
text: "Frames per second for transition animations"
font.pixelSize: 12
color: Theme.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
RowLayout {
Layout.fillWidth: true
Text {
text: Settings.settings.transitionFps + " FPS"
font.pixelSize: 13
color: Theme.textPrimary
}
Item {
Layout.fillWidth: true
}
}
Slider {
id: fpsSlider
Layout.fillWidth: true
from: 30
to: 500
stepSize: 5
value: Settings.settings.transitionFps
snapMode: Slider.SnapAlways
onMoved: {
Settings.settings.transitionFps = Math.round(value);
}
background: Rectangle {
x: fpsSlider.leftPadding
y: fpsSlider.topPadding + fpsSlider.availableHeight / 2 - height / 2
implicitWidth: 200
implicitHeight: 4
width: fpsSlider.availableWidth
height: implicitHeight
radius: 2
color: Theme.surfaceVariant
Rectangle {
width: fpsSlider.visualPosition * parent.width
height: parent.height
color: Theme.accentPrimary
radius: 2
}
}
handle: Rectangle {
x: fpsSlider.leftPadding + fpsSlider.visualPosition * (fpsSlider.availableWidth - width)
y: fpsSlider.topPadding + fpsSlider.availableHeight / 2 - height / 2
implicitWidth: 20
implicitHeight: 20
radius: 10
color: fpsSlider.pressed ? Theme.surfaceVariant : Theme.surface
border.color: Theme.accentPrimary
border.width: 2
}
}
}
// Transition Duration
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
Text {
text: "Transition Duration"
font.pixelSize: 13
font.bold: true
color: Theme.textPrimary
}
Text {
text: "Duration of transition animations in seconds"
font.pixelSize: 12
color: Theme.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
RowLayout {
Layout.fillWidth: true
Text {
text: Settings.settings.transitionDuration.toFixed(3) + " seconds"
font.pixelSize: 13
color: Theme.textPrimary
}
Item {
Layout.fillWidth: true
}
}
Slider {
id: durationSlider
Layout.fillWidth: true
from: 0.25
to: 10
stepSize: 0.05
value: Settings.settings.transitionDuration
snapMode: Slider.SnapAlways
onMoved: {
Settings.settings.transitionDuration = value;
}
background: Rectangle {
x: durationSlider.leftPadding
y: durationSlider.topPadding + durationSlider.availableHeight / 2 - height / 2
implicitWidth: 200
implicitHeight: 4
width: durationSlider.availableWidth
height: implicitHeight
radius: 2
color: Theme.surfaceVariant
Rectangle {
width: durationSlider.visualPosition * parent.width
height: parent.height
color: Theme.accentPrimary
radius: 2
}
}
handle: Rectangle {
x: durationSlider.leftPadding + durationSlider.visualPosition * (durationSlider.availableWidth - width)
y: durationSlider.topPadding + durationSlider.availableHeight / 2 - height / 2
implicitWidth: 20
implicitHeight: 20
radius: 10
color: durationSlider.pressed ? Theme.surfaceVariant : Theme.surface
border.color: Theme.accentPrimary
border.width: 2
}
}
}
}
}
}
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
}

View file

@ -89,7 +89,7 @@ Rectangle {
anchors.rightMargin: 12
anchors.topMargin: 6
anchors.bottomMargin: 6
text: Settings.settings.profileImage
text: Settings.settings.profileImage !== undefined ? Settings.settings.profileImage : ""
font.family: Theme.fontFamily
font.pixelSize: 13
color: Theme.textPrimary

View file

@ -16,6 +16,16 @@ Rectangle {
property string errorString: ""
property bool isVisible: false
// Auto-refetch weather when city changes
Connections {
target: Settings.settings
function onWeatherCityChanged() {
if (isVisible && city !== "") {
fetchCityWeather()
}
}
}
Component.onCompleted: {
if (isVisible) {
fetchCityWeather()

View file

@ -53,8 +53,13 @@ Scope {
property var notificationHistoryWin: notificationHistoryWin
}
Dock {
id: dock
Variants {
model: Quickshell.screens
Dock {
id: dock
property var modelData
}
}
Applauncher {