Add wallpaper tab
This commit is contained in:
parent
69d84752f3
commit
61e852ed51
7 changed files with 1091 additions and 122 deletions
|
|
@ -120,7 +120,7 @@ Item {
|
|||
Column {
|
||||
id: notificationColumn
|
||||
anchors.right: parent.right
|
||||
spacing: window.spacing
|
||||
spacing: panelWindow.spacing
|
||||
width: parent.width
|
||||
clip: false
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
118
Widgets/SettingsWindow/Tabs/Components/WallpaperSelector.qml
Normal file
118
Widgets/SettingsWindow/Tabs/Components/WallpaperSelector.qml
Normal 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;
|
||||
}
|
||||
}
|
||||
802
Widgets/SettingsWindow/Tabs/Wallpaper.qml
Normal file
802
Widgets/SettingsWindow/Tabs/Wallpaper.qml
Normal 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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -53,8 +53,13 @@ Scope {
|
|||
property var notificationHistoryWin: notificationHistoryWin
|
||||
}
|
||||
|
||||
Dock {
|
||||
id: dock
|
||||
Variants {
|
||||
model: Quickshell.screens
|
||||
|
||||
Dock {
|
||||
id: dock
|
||||
property var modelData
|
||||
}
|
||||
}
|
||||
|
||||
Applauncher {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue