Settings: large cleanup and factorization. Should look much better.

This commit is contained in:
LemmyCook 2025-08-27 20:39:50 -04:00
parent 1206be34dc
commit 8302285388
21 changed files with 2434 additions and 2937 deletions

View file

@ -175,7 +175,7 @@ NPanel {
// Action buttons
RowLayout {
Layout.fillWidth: true
spacing: Style.marginS * scaling
spacing: Style.marginL * scaling
NIconButton {
icon: "refresh"
@ -187,7 +187,6 @@ NPanel {
colorBg: Color.mSurfaceVariant
colorFg: Color.mOnSurface
Layout.fillWidth: true
Layout.preferredHeight: 35 * scaling
}
NIconButton {
@ -201,7 +200,6 @@ NPanel {
colorBg: ArchUpdaterService.updateInProgress ? Color.mSurfaceVariant : Color.mPrimary
colorFg: ArchUpdaterService.updateInProgress ? Color.mOnSurfaceVariant : Color.mOnPrimary
Layout.fillWidth: true
Layout.preferredHeight: 35 * scaling
}
NIconButton {
@ -219,7 +217,6 @@ NPanel {
colorFg: ArchUpdaterService.updateInProgress ? Color.mOnSurfaceVariant : (ArchUpdaterService.selectedPackagesCount
> 0 ? Color.mOnSecondary : Color.mOnSurfaceVariant)
Layout.fillWidth: true
Layout.preferredHeight: 35 * scaling
}
}
}

View file

@ -267,7 +267,7 @@ NPanel {
// Tab label on the main right side
NText {
text: root.tabsModel[currentTabIndex].label
font.pointSize: Style.fontSizeL * scaling
font.pointSize: Style.fontSizeXL * scaling
font.weight: Style.fontWeightBold
color: Color.mPrimary
Layout.fillWidth: true
@ -287,21 +287,28 @@ NPanel {
Item {
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
Repeater {
model: root.tabsModel
onItemAdded: function (index, item) {
item.sourceComponent = root.tabsModel[index].source
}
delegate: Loader {
// All loaders will occupy the same space, stacked on top of each other.
anchors.fill: parent
visible: index === root.currentTabIndex
// The loader is only active (and uses memory) when its page is visible.
active: visible
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
Loader {
active: true
sourceComponent: root.tabsModel[index].source
width: scrollView.availableWidth
}
}
}
}
}
}

View file

@ -15,10 +15,6 @@ ColumnLayout {
property string currentVersion: "Unknown" // Fallback version
property var contributors: GitHubService.contributors
spacing: 0
Layout.fillWidth: true
Layout.fillHeight: true
Process {
id: currentVersionProcess
@ -41,23 +37,9 @@ ColumnLayout {
}
}
ScrollView {
id: scrollView
Layout.fillWidth: true
Layout.fillHeight: true
padding: Style.marginL * scaling
rightPadding: Style.marginM * scaling
clip: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ColumnLayout {
width: scrollView.availableWidth
spacing: 0
NText {
text: "Noctalia: quiet by design"
text: "Noctalia Shell"
font.pointSize: Style.fontSizeXXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
@ -65,14 +47,6 @@ ColumnLayout {
Layout.bottomMargin: Style.marginS * scaling
}
NText {
text: "It may just be another quickshell setup but it won't get in your way."
font.pointSize: Style.fontSizeM * scaling
color: Color.mOnSurface
Layout.alignment: Qt.AlignCenter
Layout.bottomMargin: Style.marginL * scaling
}
GridLayout {
Layout.alignment: Qt.AlignCenter
columns: 2
@ -163,8 +137,8 @@ ColumnLayout {
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL * 2 * scaling
Layout.bottomMargin: Style.marginL * scaling
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginxL * scaling
}
NText {
@ -258,5 +232,4 @@ ColumnLayout {
}
}
}
}
}

View file

@ -7,11 +7,8 @@ import qs.Commons
import qs.Services
ColumnLayout {
id: root
property real localVolume: AudioService.volume
// Connection used to open the pill when volume changes
Connections {
target: AudioService.sink?.audio ? AudioService.sink?.audio : null
function onVolumeChanged() {
@ -19,52 +16,13 @@ ColumnLayout {
}
}
spacing: 0
ScrollView {
id: scrollView
Layout.fillWidth: true
Layout.fillHeight: true
padding: Style.marginM * scaling
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: Style.marginXS * scaling
Layout.fillWidth: true
NText {
text: "Audio Output Volume"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
Layout.bottomMargin: Style.marginS * scaling
}
// Volume Controls
ColumnLayout {
spacing: Style.marginS * scaling
Layout.fillWidth: true
Layout.topMargin: Style.marginS * scaling
// Master Volume
ColumnLayout {
spacing: Style.marginS * scaling
Layout.fillWidth: true
NLabel {
label: "Master Volume"
label: "Output Volume"
description: "System-wide volume level."
}
@ -141,24 +99,22 @@ ColumnLayout {
}
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL * 2 * scaling
Layout.bottomMargin: Style.marginL * scaling
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
// AudioService Devices
ColumnLayout {
spacing: Style.marginL * scaling
Layout.fillWidth: true
spacing: Style.marginS * scaling
NText {
text: "Audio Devices"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
color: Color.mSecondary
Layout.bottomMargin: Style.marginS * scaling
}
@ -189,7 +145,6 @@ ColumnLayout {
}
}
}
}
// -------------------------------
// Input Devices
@ -223,25 +178,44 @@ ColumnLayout {
// Divider
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL * scaling
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
// MPRIS Player Preferences
// Media Player Preferences
ColumnLayout {
spacing: Style.marginL * scaling
Layout.fillWidth: true
NText {
text: "MPRIS Player Preferences"
text: "Media Player"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
color: Color.mSecondary
Layout.bottomMargin: Style.marginS * scaling
}
// Miniplayer section
NToggle {
label: "Show Album Art In Bar Media Player"
description: "Show the album art of the currently playing song next to the title."
checked: Settings.data.audio.showMiniplayerAlbumArt
onToggled: checked => {
Settings.data.audio.showMiniplayerAlbumArt = checked
}
}
NToggle {
label: "Show Audio Visualizer In Bar Media Player"
description: "Shows an audio visualizer in the background of the miniplayer."
checked: Settings.data.audio.showMiniplayerCava
onToggled: checked => {
Settings.data.audio.showMiniplayerCava = checked
}
}
// Preferred player (persistent)
NTextInput {
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
label: "Preferred Player"
description: "Substring to match MPRIS player (identity/bus/desktop)."
placeholderText: "e.g. spotify, vlc, mpv"
@ -266,7 +240,7 @@ ColumnLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
label: "Blacklist player"
description: "Substring, e.g. plex, shim, mpv"
description: "Substring, e.g. plex, shim, mpv."
placeholderText: "type substring and press +"
}
@ -355,46 +329,6 @@ ColumnLayout {
Layout.bottomMargin: Style.marginXL * scaling
}
// Bar Mini Media player
ColumnLayout {
spacing: Style.marginL * scaling
Layout.fillWidth: true
NText {
text: "Bar Media Player"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
Layout.bottomMargin: Style.marginS * scaling
}
// Miniplayer section
NToggle {
label: "Show Album Art In Bar Media Player"
description: "Show the album art of the currently playing song next to the title."
checked: Settings.data.audio.showMiniplayerAlbumArt
onToggled: checked => {
Settings.data.audio.showMiniplayerAlbumArt = checked
}
}
NToggle {
label: "Show Audio Visualizer In Bar Media Player"
description: "Shows an audio visualizer in the background of the miniplayer."
checked: Settings.data.audio.showMiniplayerCava
onToggled: checked => {
Settings.data.audio.showMiniplayerCava = checked
}
}
}
// Divider
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
// AudioService Visualizer Category
ColumnLayout {
spacing: Style.marginS * scaling
@ -404,7 +338,7 @@ ColumnLayout {
text: "Audio Visualizer"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
color: Color.mSecondary
Layout.bottomMargin: Style.marginS * scaling
}
@ -439,7 +373,7 @@ ColumnLayout {
NComboBox {
label: "Frame Rate"
description: "Target frame rate for audio visualizer. (default: 60)"
description: "Target frame rate for audio visualizer."
model: ListModel {
ListElement {
key: "30"
@ -476,6 +410,10 @@ ColumnLayout {
}
}
}
}
// Divider
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
}

View file

@ -6,54 +6,15 @@ import qs.Services
import qs.Widgets
ColumnLayout {
id: root
spacing: 0
ScrollView {
id: scrollView
Layout.fillWidth: true
Layout.fillHeight: true
padding: Style.marginM * scaling
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: Style.marginL * scaling
Layout.fillWidth: true
ColumnLayout {
spacing: Style.marginXXS * scaling
Layout.fillWidth: true
NText {
text: "Bar Position"
font.pointSize: Style.fontSizeL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
}
NText {
text: "Choose where to place the bar on the screen"
font.pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurfaceVariant
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
RowLayout {
NComboBox {
Layout.fillWidth: true
label: "Bar Position"
description: "Choose where to place the bar on the screen."
model: ListModel {
ListElement {
key: "top"
@ -65,9 +26,7 @@ ColumnLayout {
}
}
currentKey: Settings.data.bar.position
onSelected: key => {
Settings.data.bar.position = key
}
onSelected: key => Settings.data.bar.position = key
}
}
@ -150,11 +109,12 @@ ColumnLayout {
Settings.data.bar.showWorkspaceLabel = key
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL * scaling
Layout.bottomMargin: Style.marginL * scaling
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
// Widgets Management Section
@ -190,7 +150,6 @@ ColumnLayout {
sectionName: "Left"
widgetModel: Settings.data.bar.widgets.left
availableWidgets: availableWidgets
scrollView: scrollView
onAddWidget: (widgetName, section) => addWidgetToSection(widgetName, section)
onRemoveWidget: (section, index) => removeWidgetFromSection(section, index)
onReorderWidget: (section, fromIndex, toIndex) => reorderWidgetInSection(section, fromIndex, toIndex)
@ -201,7 +160,6 @@ ColumnLayout {
sectionName: "Center"
widgetModel: Settings.data.bar.widgets.center
availableWidgets: availableWidgets
scrollView: scrollView
onAddWidget: (widgetName, section) => addWidgetToSection(widgetName, section)
onRemoveWidget: (section, index) => removeWidgetFromSection(section, index)
onReorderWidget: (section, fromIndex, toIndex) => reorderWidgetInSection(section, fromIndex, toIndex)
@ -212,15 +170,17 @@ ColumnLayout {
sectionName: "Right"
widgetModel: Settings.data.bar.widgets.right
availableWidgets: availableWidgets
scrollView: scrollView
onAddWidget: (widgetName, section) => addWidgetToSection(widgetName, section)
onRemoveWidget: (section, index) => removeWidgetFromSection(section, index)
onReorderWidget: (section, fromIndex, toIndex) => reorderWidgetInSection(section, fromIndex, toIndex)
}
}
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
// Helper functions

View file

@ -6,33 +6,11 @@ import qs.Commons
import qs.Services
import qs.Widgets
Item {
ColumnLayout {
readonly property real scaling: ScalingService.scale(screen)
readonly property string tabIcon: "brightness_6"
readonly property string tabLabel: "Brightness"
Layout.fillWidth: true
Layout.fillHeight: true
ScrollView {
anchors.fill: parent
clip: true
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.horizontal.policy: ScrollBar.AsNeeded
contentWidth: parent.width
ColumnLayout {
width: parent.width
ColumnLayout {
spacing: Style.marginL * scaling
Layout.margins: Style.marginL * scaling
Layout.fillWidth: true
NText {
text: "Brightness Settings"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
}
// Brightness Step Section
ColumnLayout {
@ -54,16 +32,9 @@ Item {
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL * scaling
Layout.bottomMargin: Style.marginL * scaling
}
// Monitor Overview Section
ColumnLayout {
spacing: Style.marginS * scaling
Layout.fillWidth: true
spacing: Style.marginL * scaling
NLabel {
label: "Monitors Brightness Control"
@ -147,10 +118,9 @@ Item {
}
}
Item {
Layout.fillHeight: true
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
}

View file

@ -9,8 +9,6 @@ import qs.Widgets
ColumnLayout {
id: root
spacing: 0
// Helper function to get color from scheme file (supports dark/light variants)
function getSchemeColor(schemePath, colorKey) {
// Extract scheme name from path
@ -55,6 +53,28 @@ ColumnLayout {
}
}
// Simple process to check if matugen exists
Process {
id: matugenCheck
command: ["which", "matugen"]
running: false
onExited: function (exitCode) {
if (exitCode === 0) {
// Matugen exists, enable it
Settings.data.colorSchemes.useWallpaperColors = true
ColorSchemeService.changedWallpaper()
ToastService.showNotice("Matugen", "Enabled!")
} else {
// Matugen not found
ToastService.showWarning("Matugen", "Not installed!")
}
}
stdout: StdioCollector {}
stderr: StdioCollector {}
}
// A non-visual Item to host the Repeater that loads the color scheme files.
Item {
visible: false
@ -83,17 +103,6 @@ ColumnLayout {
}
}
// UI Code
ScrollView {
id: scrollView
Layout.fillWidth: true
Layout.fillHeight: true
padding: Style.marginM * scaling
clip: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ColumnLayout {
width: scrollView.availableWidth
spacing: 0
@ -159,36 +168,30 @@ ColumnLayout {
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL * scaling
Layout.bottomMargin: Style.marginL * scaling
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
ColumnLayout {
spacing: Style.marginXXS * scaling
spacing: Style.marginS * scaling
Layout.fillWidth: true
NText {
text: "Predefined Color Schemes"
font.pointSize: Style.fontSizeL * scaling
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
Layout.fillWidth: true
color: Color.mSecondary
}
NText {
text: "These color schemes only apply when 'Use Matugen' is disabled. When enabled, Matugen will generate colors based on your wallpaper instead. You can toggle between light and dark themes when using Matugen."
font.pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurface
text: "These color schemes are only active when 'Use Matugen' is turned off. With Matugen enabled, colors will be automatically generated from your wallpaper. You can still switch between light and dark themes while using Matugen."
font.pointSize: Style.fontSizeM * scaling
color: Color.mOnSurfaceVariant
Layout.fillWidth: true
wrapMode: Text.WordWrap
}
}
ColumnLayout {
spacing: Style.marginXS * scaling
Layout.fillWidth: true
Layout.topMargin: Style.marginL * scaling
// Color Schemes Grid
GridLayout {
columns: 4
@ -340,28 +343,10 @@ ColumnLayout {
}
}
}
}
}
// Simple process to check if matugen exists
Process {
id: matugenCheck
command: ["which", "matugen"]
running: false
onExited: function (exitCode) {
if (exitCode === 0) {
// Matugen exists, enable it
Settings.data.colorSchemes.useWallpaperColors = true
ColorSchemeService.changedWallpaper()
ToastService.showNotice("Matugen", "Enabled!")
} else {
// Matugen not found
ToastService.showWarning("Matugen", "Not installed!")
}
}
stdout: StdioCollector {}
stderr: StdioCollector {}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
}

View file

@ -6,13 +6,11 @@ import qs.Commons
import qs.Services
import qs.Widgets
Item {
ColumnLayout {
readonly property real scaling: ScalingService.scale(screen)
readonly property string tabIcon: "monitor"
readonly property string tabLabel: "Display"
readonly property int tabIndex: 5
Layout.fillWidth: true
Layout.fillHeight: true
// Time dropdown options (00:00 .. 23:30)
ListModel {
@ -45,38 +43,26 @@ Item {
})
}
ScrollView {
anchors.fill: parent
clip: true
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.horizontal.policy: ScrollBar.AsNeeded
contentWidth: Math.max(parent.width, 600 * scaling)
ColumnLayout {
id: contentColumn
width: Math.max(parent.width, 600 * scaling)
ColumnLayout {
spacing: Style.marginL * scaling
Layout.margins: Style.marginL * scaling
Layout.fillWidth: true
NText {
text: "Permonitor configuration"
font.pointSize: Style.fontSizeXXL * scaling
text: "Monitor-specific configuration"
font.pointSize: Style.fontSizeL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
}
NText {
text: "By default, bars and notifications are shown on all displays. Select one or more below to narrow your view."
font.pointSize: Style.fontSize * scaling
text: "Bars and notifications appear on all displays by default. Choose specific displays below to limit where they're shown."
font.pointSize: Style.fontSizeM * scaling
color: Color.mOnSurfaceVariant
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.preferredWidth: parent.width - (Style.marginL * 2 * scaling)
}
ColumnLayout {
spacing: Style.marginL * scaling
Layout.topMargin: Style.marginL * scaling
Repeater {
model: Quickshell.screens || []
delegate: Rectangle {
@ -134,8 +120,8 @@ Item {
checked: (Settings.data.notifications.monitors || []).indexOf(modelData.name) !== -1
onToggled: checked => {
if (checked) {
Settings.data.notifications.monitors = addMonitor(
Settings.data.notifications.monitors, modelData.name)
Settings.data.notifications.monitors = addMonitor(Settings.data.notifications.monitors,
modelData.name)
} else {
Settings.data.notifications.monitors = removeMonitor(
Settings.data.notifications.monitors, modelData.name)
@ -152,8 +138,7 @@ Item {
if (checked) {
Settings.data.dock.monitors = addMonitor(Settings.data.dock.monitors, modelData.name)
} else {
Settings.data.dock.monitors = removeMonitor(Settings.data.dock.monitors,
modelData.name)
Settings.data.dock.monitors = removeMonitor(Settings.data.dock.monitors, modelData.name)
}
}
}
@ -228,67 +213,54 @@ Item {
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
// Night Light Section
ColumnLayout {
spacing: Style.marginXS * scaling
NText {
text: "Night Light"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
Layout.topMargin: Style.marginXL * scaling
color: Color.mSecondary
}
NText {
text: "Reduce blue light emission to help you sleep better and reduce eye strain."
font.pointSize: Style.fontSize * scaling
font.pointSize: Style.fontSizeM * scaling
color: Color.mOnSurfaceVariant
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.preferredWidth: parent.width - (Style.marginL * 2 * scaling)
}
}
NToggle {
label: "Enable Night Light"
description: "Apply a warm color filter to reduce blue light emission."
checked: Settings.data.nightLight.enabled
onToggled: checked => {
Settings.data.nightLight.enabled = checked
}
onToggled: checked => Settings.data.nightLight.enabled = checked
}
NToggle {
label: "Auto Schedule"
description: "Automatically enable night light based on time schedule."
checked: Settings.data.nightLight.autoSchedule
enabled: Settings.data.nightLight.enabled
onToggled: checked => Settings.data.nightLight.autoSchedule = checked
}
// Intensity settings
ColumnLayout {
spacing: Style.marginXS * scaling
NText {
text: "Intensity"
font.pointSize: Style.fontSizeM * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
enabled: Settings.data.nightLight.enabled
NLabel {
label: "Intensity"
description: "Higher values create warmer light."
}
NText {
text: "Higher values create warmer (more orange) light, lower values create cooler (more blue) light."
font.pointSize: Style.fontSizeS * scaling
color: Color.mOnSurfaceVariant
wrapMode: Text.WordWrap
Layout.fillWidth: true
enabled: Settings.data.nightLight.enabled
}
}
RowLayout {
spacing: Style.marginS * scaling
Layout.fillWidth: true
enabled: Settings.data.nightLight.enabled
NSlider {
from: 0
@ -307,31 +279,24 @@ Item {
horizontalAlignment: Text.AlignRight
}
}
}
// Schedule settings
ColumnLayout {
spacing: Style.marginXS * scaling
NText {
text: "Schedule"
font.pointSize: Style.fontSizeM * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
enabled: Settings.data.nightLight.enabled
NLabel {
label: "Schedule"
description: "Set a start and end time for automatic schedule."
}
RowLayout {
spacing: Style.marginL * scaling
Layout.fillWidth: true
enabled: Settings.data.nightLight.enabled
ColumnLayout {
spacing: Style.marginXXS * scaling
Layout.fillWidth: true
Layout.fillWidth: false
spacing: Style.marginM * scaling
NText {
text: "Start Time"
font.pointSize: Style.fontSizeS * scaling
font.pointSize: Style.fontSizeM * scaling
color: Color.mOnSurfaceVariant
}
@ -340,33 +305,32 @@ Item {
currentKey: Settings.data.nightLight.startTime
placeholder: "Select start time"
onSelected: key => Settings.data.nightLight.startTime = key
}
preferredWidth: 120 * scaling
}
ColumnLayout {
spacing: Style.marginXXS * scaling
Layout.fillWidth: true
Item {// add a little more spacing
}
NText {
text: "Stop Time"
font.pointSize: Style.fontSizeS * scaling
font.pointSize: Style.fontSizeM * scaling
color: Color.mOnSurfaceVariant
}
NComboBox {
model: timeOptions
currentKey: Settings.data.nightLight.stopTime
placeholder: "Select stop time"
onSelected: key => Settings.data.nightLight.stopTime = key
preferredWidth: 120 * scaling
}
}
}
}
Item {
Layout.fillHeight: true
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
}

View file

@ -6,46 +6,8 @@ import qs.Services
import qs.Widgets
ColumnLayout {
id: root
spacing: 0
ScrollView {
id: scrollView
Layout.fillWidth: true
Layout.fillHeight: true
padding: Style.marginM * scaling
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: Style.marginL * scaling
Layout.fillWidth: true
NText {
text: "General Settings"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
}
// Profile section
ColumnLayout {
spacing: Style.marginS * scaling
Layout.fillWidth: true
Layout.topMargin: Style.marginS * scaling
RowLayout {
Layout.fillWidth: true
spacing: Style.marginL * scaling
@ -71,8 +33,6 @@ ColumnLayout {
}
}
}
}
}
NDivider {
Layout.fillWidth: true
@ -80,6 +40,7 @@ ColumnLayout {
Layout.bottomMargin: Style.marginXL * scaling
}
// User Interface
ColumnLayout {
spacing: Style.marginL * scaling
Layout.fillWidth: true
@ -88,7 +49,7 @@ ColumnLayout {
text: "User Interface"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
color: Color.mSecondary
Layout.bottomMargin: Style.marginS * scaling
}
@ -123,19 +84,9 @@ ColumnLayout {
spacing: Style.marginXXS * scaling
Layout.fillWidth: true
NText {
text: "Border radius"
font.pointSize: Style.fontSizeL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
}
NText {
text: "Adjust the rounded border of all UI elements"
font.pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurfaceVariant
wrapMode: Text.WordWrap
Layout.fillWidth: true
NLabel {
label: "Border radius"
description: "Adjust the rounded border of all UI elements."
}
RowLayout {
@ -158,30 +109,14 @@ ColumnLayout {
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginL * scaling
}
// Animation Speed
ColumnLayout {
spacing: Style.marginXXS * scaling
Layout.fillWidth: true
NText {
text: "Animation Speed"
font.pointSize: Style.fontSizeL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
}
NText {
text: "Adjust global animation speed (0.1× to 2.0×)"
font.pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurfaceVariant
wrapMode: Text.WordWrap
Layout.fillWidth: true
NLabel {
label: "Animation Speed"
description: "Adjust global animation speed."
}
RowLayout {
@ -203,18 +138,29 @@ ColumnLayout {
}
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
// Fonts
ColumnLayout {
spacing: Style.marginL * scaling
Layout.fillWidth: true
NText {
text: "Fonts"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
color: Color.mSecondary
Layout.bottomMargin: Style.marginS * scaling
}
// Font configuration section
ColumnLayout {
spacing: Style.marginS * scaling
spacing: Style.marginL * scaling
Layout.fillWidth: true
NTextInput {
@ -251,6 +197,10 @@ ColumnLayout {
}
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
}

View file

@ -6,62 +6,9 @@ import qs.Services
import qs.Widgets
ColumnLayout {
id: root
spacing: 0
ScrollView {
id: scrollView
Layout.fillWidth: true
Layout.fillHeight: true
padding: Style.marginM * scaling
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: Style.marginL * scaling
Layout.fillWidth: true
NText {
text: "Launcher"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
}
NToggle {
label: "Enable Clipboard History"
description: "Show clipboard history in the Launcher (command >clip)."
checked: Settings.data.appLauncher.enableClipboardHistory
onToggled: checked => {
Settings.data.appLauncher.enableClipboardHistory = checked
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL * scaling
Layout.bottomMargin: Style.marginS * scaling
}
NText {
text: "Launcher Position"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
Layout.bottomMargin: Style.marginS * scaling
}
NComboBox {
id: launcherPosition
@ -104,18 +51,32 @@ ColumnLayout {
}
}
NDivider {
NToggle {
label: "Enable Clipboard History"
description: "Show clipboard history in the launcher."
checked: Settings.data.appLauncher.enableClipboardHistory
onToggled: checked => {
Settings.data.appLauncher.enableClipboardHistory = checked
}
}
ColumnLayout {
spacing: Style.marginXXS * scaling
Layout.fillWidth: true
Layout.topMargin: Style.marginL * scaling
Layout.bottomMargin: Style.marginS * scaling
NText {
text: "Background Opacity"
font.pointSize: Style.fontSizeL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
}
NText {
text: "Launcher Background"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
Layout.bottomMargin: Style.marginS * scaling
text: "Adjust the background opacity of the launcher."
font.pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurfaceVariant
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
RowLayout {
@ -139,5 +100,10 @@ ColumnLayout {
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
}

View file

@ -7,39 +7,8 @@ import qs.Commons
import qs.Services
import qs.Widgets
ColumnLayout {
id: root
spacing: 0
ScrollView {
id: scrollView
Layout.fillWidth: true
Layout.fillHeight: true
padding: Style.marginM * scaling
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: Style.marginL * scaling
Layout.fillWidth: true
NText {
text: "Interfaces"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
}
NToggle {
label: "WiFi Enabled"
@ -70,7 +39,10 @@ ColumnLayout {
}
}
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
}

View file

@ -6,40 +6,7 @@ import qs.Services
import qs.Widgets
ColumnLayout {
id: root
spacing: 0
ScrollView {
id: scrollView
Layout.fillWidth: true
Layout.fillHeight: true
padding: Style.marginM * scaling
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: Style.marginXS * scaling
Layout.fillWidth: true
NText {
text: "Recordings"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
Layout.bottomMargin: Style.marginS * scaling
}
spacing: Style.marginL * scaling
// Output Directory
ColumnLayout {
@ -55,6 +22,7 @@ ColumnLayout {
onEditingFinished: {
Settings.data.screenRecorder.directory = text
}
Layout.fillWidth: true
}
ColumnLayout {
@ -75,8 +43,8 @@ ColumnLayout {
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL * 2 * scaling
Layout.bottomMargin: Style.marginL * scaling
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
// Video Settings
@ -88,7 +56,7 @@ ColumnLayout {
text: "Video Settings"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
color: Color.mSecondary
Layout.bottomMargin: Style.marginS * scaling
}
@ -115,7 +83,7 @@ ColumnLayout {
// Frame Rate
NComboBox {
label: "Frame Rate"
description: "Target frame rate for screen recordings. (default: 60)"
description: "Target frame rate for screen recordings."
model: ListModel {
ListElement {
key: "30"
@ -248,7 +216,7 @@ ColumnLayout {
text: "Audio Settings"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
color: Color.mSecondary
Layout.bottomMargin: Style.marginS * scaling
}
@ -296,7 +264,10 @@ ColumnLayout {
}
}
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
}

View file

@ -6,47 +6,8 @@ import qs.Services
import qs.Widgets
ColumnLayout {
id: root
spacing: 0
ScrollView {
id: scrollView
Layout.fillWidth: true
Layout.fillHeight: true
padding: Style.marginM * scaling
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: Style.marginXS * scaling
Layout.fillWidth: true
NText {
text: "Location"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
Layout.bottomMargin: Style.marginS * scaling
}
// Location section
ColumnLayout {
spacing: Style.marginM * scaling
Layout.fillWidth: true
Layout.topMargin: Style.marginS * scaling
NTextInput {
label: "Location name"
description: "Choose a known location near you."
@ -58,12 +19,11 @@ ColumnLayout {
LocationService.resetWeather()
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL * 2 * scaling
Layout.bottomMargin: Style.marginL * scaling
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
// Time section
@ -75,8 +35,7 @@ ColumnLayout {
text: "Time Format"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
Layout.bottomMargin: Style.marginS * scaling
color: Color.mSecondary
}
NToggle {
@ -109,8 +68,8 @@ ColumnLayout {
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL * 2 * scaling
Layout.bottomMargin: Style.marginL * scaling
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
// Weather section
@ -122,8 +81,7 @@ ColumnLayout {
text: "Weather"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
Layout.bottomMargin: Style.marginS * scaling
color: Color.mSecondary
}
NToggle {
@ -135,7 +93,10 @@ ColumnLayout {
}
}
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
}

View file

@ -6,34 +6,20 @@ import qs.Commons
import qs.Services
import qs.Widgets
Item {
ColumnLayout {
readonly property real scaling: ScalingService.scale(screen)
readonly property string tabIcon: "photo_library"
readonly property string tabLabel: "Wallpaper Selector"
readonly property int tabIndex: 7
Layout.fillWidth: true
Layout.fillHeight: true
ScrollView {
anchors.fill: parent
clip: true
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.horizontal.policy: ScrollBar.AsNeeded
contentWidth: parent.width
ColumnLayout {
width: parent.width
ColumnLayout {
spacing: Style.marginL * scaling
Layout.margins: Style.marginL * scaling
Layout.fillWidth: true
// Current wallpaper display
NText {
text: "Current Wallpaper"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
color: Color.mSecondary
}
Rectangle {
@ -54,10 +40,11 @@ Item {
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL * scaling
Layout.bottomMargin: Style.marginL * scaling
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
// Wallpaper selector
RowLayout {
Layout.fillWidth: true
@ -69,12 +56,12 @@ Item {
text: "Wallpaper Selector"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
color: Color.mSecondary
}
NText {
text: "Click on a wallpaper to set it as your current wallpaper."
color: Color.mOnSurface
color: Color.mOnSurfaceVariant
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
@ -102,8 +89,7 @@ Item {
Item {
Layout.fillWidth: true
Layout.preferredHeight: {
return Math.ceil(
WallpaperService.wallpaperList.length / wallpaperGridView.columns) * wallpaperGridView.cellHeight
return Math.ceil(WallpaperService.wallpaperList.length / wallpaperGridView.columns) * wallpaperGridView.cellHeight
}
GridView {
@ -117,8 +103,7 @@ Item {
interactive: false
property int columns: 5
property int itemSize: Math.floor(
(width - leftMargin - rightMargin - (4 * Style.marginS * scaling)) / columns)
property int itemSize: Math.floor((width - leftMargin - rightMargin - (4 * Style.marginS * scaling)) / columns)
cellWidth: Math.floor((width - leftMargin - rightMargin) / columns)
cellHeight: Math.floor(itemSize * 0.67) + Style.marginS * scaling
@ -151,19 +136,19 @@ Item {
Rectangle {
anchors.fill: parent
color: Color.transparent
border.color: isSelected ? Color.mPrimary : Color.mSurface
border.width: Math.max(1, Style.borderL * scaling)
border.color: isSelected ? Color.mSecondary : Color.mSurface
border.width: Math.max(1, Style.borderL * 1.5 * scaling)
}
// Selection tick-mark
Rectangle {
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: Style.marginXS * scaling
anchors.margins: Style.marginS * scaling
width: 28 * scaling
height: 28 * scaling
radius: width / 2
color: Color.mPrimary
color: Color.mSecondary
border.color: Color.mOutline
border.width: Math.max(1, Style.borderS * scaling)
visible: isSelected
@ -172,7 +157,7 @@ Item {
text: "check"
font.pointSize: Style.fontSizeM * scaling
font.weight: Style.fontWeightBold
color: Color.mOnPrimary
color: Color.mOnSecondary
anchors.centerIn: parent
}
}
@ -180,8 +165,8 @@ Item {
// Hover effect
Rectangle {
anchors.fill: parent
color: Color.mOnSurface
opacity: mouseArea.containsMouse ? 0.1 : 0
color: Color.mSurface
opacity: (mouseArea.containsMouse || isSelected) ? 0 : 0.4
radius: parent.radius
Behavior on opacity {
@ -240,7 +225,10 @@ Item {
}
}
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
}

View file

@ -7,52 +7,29 @@ import qs.Services
import qs.Widgets
ColumnLayout {
id: root
spacing: 0
// Process to check if swww is installed
Process {
id: swwwCheck
command: ["which", "swww"]
running: false
ScrollView {
id: scrollView
Layout.fillWidth: true
Layout.fillHeight: true
padding: Style.marginM * scaling
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
onExited: function (exitCode) {
if (exitCode === 0) {
// SWWW exists, enable it
Settings.data.wallpaper.swww.enabled = true
WallpaperService.startSWWWDaemon()
ToastService.showNotice("SWWW", "Enabled!")
} else {
// SWWW not found
ToastService.showWarning("SWWW", "Not installed!")
}
}
ColumnLayout {
spacing: Style.marginL * scaling
Layout.fillWidth: true
NText {
text: "Directory"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
Layout.bottomMargin: Style.marginS * scaling
stdout: StdioCollector {}
stderr: StdioCollector {}
}
// Wallpaper Settings Category
ColumnLayout {
spacing: Style.marginS * scaling
Layout.fillWidth: true
Layout.topMargin: Style.marginS * scaling
// Wallpaper Folder
ColumnLayout {
spacing: Style.marginS * scaling
Layout.fillWidth: true
NTextInput {
label: "Wallpaper Directory"
description: "Path to your wallpaper directory."
@ -62,14 +39,11 @@ ColumnLayout {
Settings.data.wallpaper.directory = text
}
}
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL * 2 * scaling
Layout.bottomMargin: Style.marginL * scaling
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
ColumnLayout {
@ -80,8 +54,7 @@ ColumnLayout {
text: "Automation"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
Layout.bottomMargin: Style.marginS * scaling
color: Color.mSecondary
}
// Random Wallpaper
@ -306,10 +279,11 @@ ColumnLayout {
id: customRow
visible: presetRow.customForcedVisible || !presetRow.isCurrentPreset
spacing: Style.marginS * scaling
Layout.topMargin: Style.marginS * scaling
NTextInput {
label: "Custom Interval"
description: "Enter time as HH:MM (e.g., 1:30)"
description: "Enter time as HH:MM (e.g., 1:30)."
text: {
const s = Settings.data.wallpaper.randomInterval
const h = Math.floor(s / 3600)
@ -339,28 +313,27 @@ ColumnLayout {
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL * 2 * scaling
Layout.bottomMargin: Style.marginL * scaling
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
// -------------------------------
// SWWW
// Swww
ColumnLayout {
spacing: Style.marginL * scaling
Layout.fillWidth: true
NText {
text: "SWWW"
text: "Swww"
font.pointSize: Style.fontSizeXXL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
Layout.bottomMargin: Style.marginS * scaling
color: Color.mSecondary
}
// Use SWWW
NToggle {
label: "Use SWWW"
description: "Use SWWW daemon for advanced wallpaper management."
label: "Use Swww"
description: "Use Swww daemon for advanced wallpaper management."
checked: Settings.data.wallpaper.swww.enabled
onToggled: checked => {
if (checked) {
@ -368,7 +341,7 @@ ColumnLayout {
swwwCheck.running = true
} else {
Settings.data.wallpaper.swww.enabled = false
ToastService.showNotice("SWWW", "Disabled")
ToastService.showNotice("Swww", "Disabled")
}
}
}
@ -383,7 +356,7 @@ ColumnLayout {
// Resize Mode
NComboBox {
label: "Resize Mode"
description: "How SWWW should resize wallpapers to fit the screen."
description: "How Swww should resize wallpapers to fit the screen."
model: ListModel {
ListElement {
key: "no"
@ -478,32 +451,14 @@ ColumnLayout {
// Transition FPS
ColumnLayout {
NLabel {
label: "Transition FPS"
description: "Frames per second for transition animations."
}
RowLayout {
Layout.fillWidth: true
ColumnLayout {
NText {
text: "Transition FPS"
font.weight: Style.fontWeightBold
color: Color.mOnSurface
}
NText {
text: "Frames per second for transition animations."
font.pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurface
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
}
NText {
text: sliderWpTransitionFps.value + " FPS"
Layout.alignment: Qt.AlignBottom | Qt.AlignRight
}
}
spacing: Style.marginL * scaling
NSlider {
id: sliderWpTransitionFps
Layout.fillWidth: true
from: 30
to: 500
@ -512,36 +467,23 @@ ColumnLayout {
onMoved: Settings.data.wallpaper.swww.transitionFps = Math.round(value)
cutoutColor: Color.mSurface
}
NText {
text: Settings.data.wallpaper.swww.transitionFps + " FPS"
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
}
}
}
// Transition Duration
ColumnLayout {
NLabel {
label: "Transition Duration"
description: "Duration of transition animations in seconds."
}
RowLayout {
Layout.fillWidth: true
ColumnLayout {
NText {
text: "Transition Duration"
font.weight: Style.fontWeightBold
color: Color.mOnSurface
}
NText {
text: "Duration of transition animations in seconds."
font.pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurface
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
}
NText {
text: sliderWpTransitionDuration.value.toFixed(2) + "s"
Layout.alignment: Qt.AlignBottom | Qt.AlignRight
}
}
spacing: Style.marginL * scaling
NSlider {
id: sliderWpTransitionDuration
Layout.fillWidth: true
from: 0.25
to: 10
@ -550,31 +492,18 @@ ColumnLayout {
onMoved: Settings.data.wallpaper.swww.transitionDuration = value
cutoutColor: Color.mSurface
}
NText {
text: Settings.data.wallpaper.swww.transitionDuration.toFixed(2) + "s"
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
}
}
}
}
}
// Process to check if swww is installed
Process {
id: swwwCheck
command: ["which", "swww"]
running: false
onExited: function (exitCode) {
if (exitCode === 0) {
// SWWW exists, enable it
Settings.data.wallpaper.swww.enabled = true
WallpaperService.startSWWWDaemon()
ToastService.showNotice("SWWW", "Enabled!")
} else {
// SWWW not found
ToastService.showWarning("SWWW", "Not installed!")
}
}
stdout: StdioCollector {}
stderr: StdioCollector {}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
}

View file

@ -5,10 +5,11 @@ import qs.Commons
import qs.Services
import qs.Widgets
ColumnLayout {
RowLayout {
id: root
readonly property real preferredHeight: Style.baseWidgetSize * 1.35 * scaling
readonly property real preferredHeight: Style.baseWidgetSize * 1.1 * scaling
property real preferredWidth: 320 * scaling
property string label: ""
property string description: ""
@ -23,11 +24,6 @@ ColumnLayout {
spacing: Style.marginS * scaling
Layout.fillWidth: true
NLabel {
label: root.label
description: root.description
}
function findIndexByKey(key) {
for (var i = 0; i < root.model.count; i++) {
if (root.model.get(i).key === key) {
@ -37,10 +33,15 @@ ColumnLayout {
return -1
}
NLabel {
label: root.label
description: root.description
}
ComboBox {
id: combo
Layout.preferredWidth: 320 * scaling
Layout.preferredWidth: root.preferredWidth
Layout.preferredHeight: height
model: model
currentIndex: findIndexByKey(currentKey)

View file

@ -11,7 +11,7 @@ ColumnLayout {
NText {
text: label
font.pointSize: Style.fontSizeM * scaling
font.pointSize: Style.fontSizeL * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
visible: label !== ""

View file

@ -10,7 +10,6 @@ NBox {
property string sectionName: ""
property var widgetModel: []
property var availableWidgets: []
property var scrollView: null
signal addWidget(string widgetName, string section)
signal removeWidget(string section, int index)
@ -23,7 +22,7 @@ NBox {
if (widgetCount === 0)
return 140 * scaling
var availableWidth = scrollView ? scrollView.availableWidth - (Style.marginM * scaling * 2) : 400 * scaling
var availableWidth = parent.width
var avgWidgetWidth = 150 * scaling
var widgetsPerRow = Math.max(1, Math.floor(availableWidth / avgWidgetWidth))
var rows = Math.ceil(widgetCount / widgetsPerRow)
@ -52,7 +51,7 @@ NBox {
ColumnLayout {
anchors.fill: parent
anchors.margins: Style.marginM * scaling
anchors.margins: Style.marginL * scaling
spacing: Style.marginM * scaling
RowLayout {
@ -189,13 +188,13 @@ NBox {
return
}
Logger.log("NSectionEditor", `Started dragging widget: ${modelData} at index ${index}`)
//Logger.log("NSectionEditor", `Started dragging widget: ${modelData} at index ${index}`)
// Bring to front when starting drag
widgetItem.z = 1000
}
onReleased: {
Logger.log("NSectionEditor", `Released widget: ${modelData} at index ${index}`)
//Logger.log("NSectionEditor", `Released widget: ${modelData} at index ${index}`)
// Reset z-index when drag ends
widgetItem.z = 0
@ -232,13 +231,13 @@ NBox {
if (targetIndex !== -1 && targetIndex !== index) {
const fromIndex = index
const toIndex = targetIndex
Logger.log(
"NSectionEditor",
`Dropped widget from index ${fromIndex} to position ${toIndex} (distance: ${minDistance.toFixed(
2)})`)
// Logger.log(
// "NSectionEditor",
// `Dropped widget from index ${fromIndex} to position ${toIndex} (distance: ${minDistance.toFixed(
// 2)})`)
reorderWidget(sectionName.toLowerCase(), fromIndex, toIndex)
} else {
Logger.log("NSectionEditor", `No valid drop target found for widget at index ${index}`)
Logger.warn("NSectionEditor", `No valid drop target found for widget at index ${index}`)
}
}
}
@ -264,17 +263,16 @@ NBox {
radius: Style.radiusS * scaling
}
onEntered: function (drag) {
Logger.log("NSectionEditor", "Entered start drop zone")
onEntered: function (drag) {//Logger.log("NSectionEditor", "Entered start drop zone")
}
onDropped: function (drop) {
Logger.log("NSectionEditor", "Dropped on start zone")
//Logger.log("NSectionEditor", "Dropped on start zone")
if (drop.source && drop.source.widgetIndex !== undefined) {
const fromIndex = drop.source.widgetIndex
const toIndex = 0 // Insert at the beginning
if (fromIndex !== toIndex) {
Logger.log("NSectionEditor", `Dropped widget from index ${fromIndex} to beginning`)
//Logger.log("NSectionEditor", `Dropped widget from index ${fromIndex} to beginning`)
reorderWidget(sectionName.toLowerCase(), fromIndex, toIndex)
}
}
@ -299,17 +297,16 @@ NBox {
radius: Style.radiusS * scaling
}
onEntered: function (drag) {
Logger.log("NSectionEditor", "Entered end drop zone")
onEntered: function (drag) {//Logger.log("NSectionEditor", "Entered end drop zone")
}
onDropped: function (drop) {
Logger.log("NSectionEditor", "Dropped on end zone")
//Logger.log("NSectionEditor", "Dropped on end zone")
if (drop.source && drop.source.widgetIndex !== undefined) {
const fromIndex = drop.source.widgetIndex
const toIndex = widgetModel.length // Insert at the end
if (fromIndex !== toIndex) {
Logger.log("NSectionEditor", `Dropped widget from index ${fromIndex} to end`)
//Logger.log("NSectionEditor", `Dropped widget from index ${fromIndex} to end`)
reorderWidget(sectionName.toLowerCase(), fromIndex, toIndex)
}
}

View file

@ -30,26 +30,9 @@ RowLayout {
Layout.fillWidth: true
ColumnLayout {
spacing: Style.marginXXS * scaling
Layout.fillWidth: true
NText {
text: label
font.pointSize: Style.fontSizeM * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
visible: label !== ""
}
NText {
text: description
font.pointSize: Style.fontSizeS * scaling
color: Color.mOnSurfaceVariant
wrapMode: Text.WordWrap
Layout.fillWidth: true
visible: description !== ""
}
NLabel {
label: root.label
description: root.description
}
// Value

View file

@ -150,7 +150,7 @@ Item {
id: labelText
text: root.label
color: Color.mOnSurface
font.pointSize: Style.fontSize * scaling
font.pointSize: Style.fontSizeM * scaling
font.weight: Style.fontWeightBold
wrapMode: Text.WordWrap
width: parent.width
@ -161,7 +161,7 @@ Item {
id: descriptionText
text: root.description
color: Color.mOnSurface
font.pointSize: Style.fontSize * scaling
font.pointSize: Style.fontSizeM * scaling
wrapMode: Text.WordWrap
width: parent.width
visible: text.length > 0
@ -176,7 +176,7 @@ Item {
color: Color.mOnSurface
fontPointSize: Style.fontSize * scaling
fontPointSize: Style.fontSizeM * scaling
sizeRatio: 0.8
Layout.alignment: Qt.AlignTop

View file

@ -19,24 +19,9 @@ RowLayout {
Layout.fillWidth: true
ColumnLayout {
spacing: Style.marginXXS * scaling
Layout.fillWidth: true
NText {
text: label
font.pointSize: Style.fontSizeM * scaling
font.weight: Style.fontWeightBold
color: Color.mOnSurface
}
NText {
text: description
font.pointSize: Style.fontSizeS * scaling
color: Color.mOnSurfaceVariant
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
NLabel {
label: root.label
description: root.description
}
Rectangle {