remove old Settings, rename new
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 11s
Python / lint-format (pull_request) Successful in 18s
Python / test (pull_request) Successful in 46s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m39s
C++ / build (pull_request) Successful in 2m26s

This commit is contained in:
2026-06-30 13:43:34 +02:00
parent deaeac4dbd
commit 38b9362515
93 changed files with 88 additions and 7943 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ import qs.Modules.Osd as Osd
import qs.Components.Toast as Toasts
import qs.Modules.Launcher as Launcher
import qs.Modules.Resources as Resources
import qs.Modules.SettingsNew as Settings
import qs.Modules.Settings as Settings
import qs.Modules.Drawing as Drawing
import qs.Modules.Dock as Dock
import qs.Modules.Clipboard as Clipboard
-370
View File
@@ -1,370 +0,0 @@
pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Widgets
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Modules as Modules
import qs.Config
import qs.Helpers
Item {
id: root
required property Item content
signal settingSelected(string category, string section, string settingName)
// Function to select category by key
function selectCategory(categoryKey: string) {
for (let i = 0; i < appearanceCats.count; i++) {
const item = appearanceCats.get(i);
if (item.key === categoryKey) {
appearanceView.currentIndex = i;
root.content.setCategory(item.key, item._index);
return;
}
}
for (let i = 0; i < systemCats.count; i++) {
const item = systemCats.get(i);
if (item.key === categoryKey) {
sysView.currentIndex = i;
root.content.setCategory(item.key, item._index);
return;
}
}
for (let i = 0; i < panelCats.count; i++) {
const item = panelCats.get(i);
if (item.key === categoryKey) {
panelsView.currentIndex = i;
root.content.setCategory(item.key, item._index);
return;
}
}
}
implicitHeight: searchBar.implicitHeight + Appearance.spacing.smaller + clayout.contentHeight + clayout.anchors.margins * 2
implicitWidth: clayout.contentWidth + clayout.anchors.margins * 2
ListModel {
id: systemCats
ListElement {
_index: 0
icon: "settings"
key: "general"
name: "General"
}
ListElement {
_index: 1
icon: "build_circle"
key: "services"
name: "Services"
}
ListElement {
_index: 2
icon: "notifications"
key: "notifications"
name: "Notifications"
}
ListElement {
_index: 3
icon: "handyman"
key: "utilities"
name: "Utilities"
}
ListElement {
_index: 4
icon: "cached"
key: "updates"
name: "Updates"
}
}
ListModel {
id: panelCats
ListElement {
_index: 5
icon: "settop_component"
key: "bar"
name: "Bar"
}
ListElement {
_index: 6
icon: "lock"
key: "lockscreen"
name: "Lockscreen"
}
ListElement {
_index: 7
icon: "view_sidebar"
key: "sidebar"
name: "Sidebar"
}
ListElement {
_index: 8
icon: "dashboard"
key: "dashboard"
name: "Dashboard"
}
ListElement {
_index: 9
icon: "display_settings"
key: "osd"
name: "On screen display"
}
ListElement {
_index: 10
icon: "rocket_launch"
key: "launcher"
name: "Launcher"
}
}
ListModel {
id: appearanceCats
ListElement {
_index: 11
icon: "wallpaper"
key: "wallpaper"
name: "Wallpaper"
}
ListElement {
_index: 12
icon: "screenshot_region"
key: "screenshot"
name: "Screenshot"
}
ListElement {
_index: 13
icon: "colors"
key: "appearance"
name: "Appearance"
}
}
CustomClippingRect {
anchors.fill: parent
color: DynamicColors.tPalette.m3surfaceContainer
radius: Appearance.rounding.normal
CustomFlickable {
id: clayout
anchors.fill: parent
anchors.margins: Appearance.padding.extraSmall
contentHeight: contentItem.childrenRect.height
contentWidth: contentItem.childrenRect.width
flickableDirection: Flickable.VerticalFlick
ColumnLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
spacing: Appearance.spacing.normal
CustomListView {
id: sysView
Layout.fillWidth: true
Layout.preferredHeight: contentItem.childrenRect.height
Layout.preferredWidth: contentItem.childrenRect.width
boundsBehavior: Flickable.StopAtBounds
highlightFollowsCurrentItem: false
interactive: false
model: systemCats
spacing: 2
delegate: Category {
view: sysView
}
// highlight: CustomRect {
// color: DynamicColors.palette.m3primary
// implicitHeight: sysView.currentItem?.implicitHeight ?? 0
// implicitWidth: sysView.width
// radius: Appearance.rounding.normal - Appearance.padding.smaller
// y: sysView.currentItem?.y ?? 0
//
// Behavior on y {
// Anim {
// duration: Appearance.anim.durations.small
// easing.bezierCurve: Appearance.anim.curves.expressiveEffects
// }
// }
// }
}
CustomListView {
id: panelsView
Layout.fillWidth: true
Layout.preferredHeight: contentItem.childrenRect.height
Layout.preferredWidth: contentItem.childrenRect.width
boundsBehavior: Flickable.StopAtBounds
contentWidth: contentItem.childrenRect.width
highlightFollowsCurrentItem: false
interactive: false
model: panelCats
spacing: 2
delegate: Category {
view: panelsView
}
// highlight: CustomRect {
// color: DynamicColors.palette.m3primary
// implicitHeight: panelsView.currentItem?.implicitHeight ?? 0
// implicitWidth: panelsView.width
// radius: Appearance.rounding.normal - Appearance.padding.smaller
// y: panelsView.currentItem?.y ?? 0
//
// Behavior on y {
// Anim {
// duration: Appearance.anim.durations.small
// easing.bezierCurve: Appearance.anim.curves.expressiveEffects
// }
// }
// }
}
CustomListView {
id: appearanceView
Layout.fillWidth: true
Layout.preferredHeight: contentItem.childrenRect.height
Layout.preferredWidth: contentItem.childrenRect.width
boundsBehavior: Flickable.StopAtBounds
contentWidth: contentItem.childrenRect.width
highlightFollowsCurrentItem: false
interactive: false
model: appearanceCats
spacing: 2
delegate: Category {
view: appearanceView
}
// highlight: CustomRect {
// color: DynamicColors.palette.m3primary
// implicitHeight: appearanceView.currentItem?.implicitHeight ?? 0
// implicitWidth: appearanceView.width
// radius: Appearance.rounding.normal - Appearance.padding.smaller
// y: appearanceView.currentItem?.y ?? 0
//
// Behavior on y {
// Anim {
// duration: Appearance.anim.durations.small
// easing.bezierCurve: Appearance.anim.curves.expressiveEffects
// }
// }
// }
}
}
}
}
component Category: CustomRect {
id: categoryItem
required property int _index
readonly property bool first: index === 0
required property string icon
required property int index
required property string key
readonly property bool last: index === view.model.count - 1
required property string name
readonly property bool selected: key === root.content.currentCategory
required property ListView view
bottomLeftRadius: layer.pressed ? Appearance.rounding.smallest : selected || last ? Appearance.rounding.normal - clayout.anchors.margins : Appearance.rounding.extraSmall
bottomRightRadius: layer.pressed ? Appearance.rounding.smallest : selected || last ? Appearance.rounding.normal - clayout.anchors.margins : Appearance.rounding.extraSmall
color: selected ? DynamicColors.palette.m3primary : DynamicColors.tPalette.m3surfaceContainer
implicitHeight: 50
implicitWidth: 256
topLeftRadius: layer.pressed ? Appearance.rounding.smallest : selected || first ? Appearance.rounding.normal - clayout.anchors.margins : Appearance.rounding.extraSmall
topRightRadius: layer.pressed ? Appearance.rounding.smallest : selected || first ? Appearance.rounding.normal - clayout.anchors.margins : Appearance.rounding.extraSmall
Behavior on bottomLeftRadius {
Anim {
type: Anim.FastEffects
}
}
Behavior on bottomRightRadius {
Anim {
type: Anim.FastEffects
}
}
Behavior on topLeftRadius {
Anim {
type: Anim.FastEffects
}
}
Behavior on topRightRadius {
Anim {
type: Anim.FastEffects
}
}
RowLayout {
id: layout
anchors.left: parent.left
anchors.margins: Appearance.padding.smaller
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
MaterialIcon {
id: icon
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.fillHeight: true
Layout.leftMargin: Appearance.padding.small
Layout.preferredWidth: icon.contentWidth
color: categoryItem.key === root.content.currentCategory ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface
fill: categoryItem.key === root.content.currentCategory ? 1 : 0
font.pointSize: Appearance.font.size.small * 2
text: categoryItem.icon
verticalAlignment: Text.AlignVCenter
Behavior on fill {
Anim {
}
}
}
CustomText {
id: text
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.fillHeight: true
Layout.fillWidth: true
Layout.leftMargin: Appearance.spacing.normal
color: categoryItem.key === root.content.currentCategory ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface
text: categoryItem.name
verticalAlignment: Text.AlignVCenter
}
}
StateLayer {
id: layer
color: categoryItem.key === root.content.currentCategory ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface
onClicked: {
root.content.setCategory(categoryItem.key, categoryItem._index);
categoryItem.view.currentIndex = categoryItem.index;
}
}
}
}
-162
View File
@@ -1,162 +0,0 @@
import QtQuick
import qs.Modules.Settings.Controls
import qs.Config
SettingsPage {
id: root
SettingsSection {
sectionId: "Scale"
SettingsHeader {
name: "Scale"
}
SettingSpinBox {
name: "Rounding scale"
object: Config.appearance.rounding
setting: "scale"
step: 0.1
}
Separator {
}
SettingSpinBox {
name: "Spacing scale"
object: Config.appearance.spacing
setting: "scale"
step: 0.1
}
Separator {
}
SettingSpinBox {
name: "Padding scale"
object: Config.appearance.padding
setting: "scale"
step: 0.1
}
Separator {
}
SettingSpinBox {
name: "Font size scale"
object: Config.appearance.font.size
setting: "scale"
step: 0.1
}
Separator {
}
SettingSpinBox {
name: "Animation duration scale"
object: Config.appearance.anim.durations
setting: "scale"
step: 0.1
}
Separator {
}
SettingSpinBox {
name: "Deform animation scale"
object: Config.appearance.deform
setting: "scale"
step: 0.1
}
}
SettingsSection {
sectionId: "Fonts"
SettingsHeader {
name: "Fonts"
}
SettingListView {
name: "Sans family"
object: Config.appearance.font.family
setting: "sans"
stringList: Qt.fontFamilies()
}
Separator {
}
SettingListView {
name: "Monospace family"
object: Config.appearance.font.family
setting: "mono"
stringList: Qt.fontFamilies()
}
}
SettingsSection {
sectionId: "Animation"
SettingsHeader {
name: "Animation"
}
SettingSpinBox {
name: "Media GIF speed adjustment"
object: Config.appearance.anim
setting: "mediaGifSpeedAdjustment"
step: 10
}
Separator {
}
SettingSpinBox {
max: 5
min: 0
name: "Session GIF speed"
object: Config.appearance.anim
setting: "sessionGifSpeed"
step: 0.1
}
}
SettingsSection {
sectionId: "Transparency"
SettingsHeader {
name: "Transparency"
}
SettingSwitch {
name: "Enable transparency"
object: Config.appearance.transparency
setting: "enabled"
}
Separator {
}
SettingSpinBox {
max: 1
min: 0
name: "Base opacity"
object: Config.appearance.transparency
setting: "base"
step: 0.05
}
Separator {
}
SettingSpinBox {
max: 1
min: 0
name: "Layer opacity"
object: Config.appearance.transparency
setting: "layers"
step: 0.05
}
}
}
@@ -1,48 +0,0 @@
import Quickshell
import QtQuick.Layouts
import qs.Modules.Settings.Controls
import qs.Config
SettingsPage {
id: root
required property ShellScreen screen
SettingsSection {
sectionId: "Wallpaper"
SettingsHeader {
name: "Wallpaper"
}
SettingSwitch {
name: "Enable wallpaper rendering"
object: Config.background
setting: "enabled"
}
Separator {
}
SettingSpinBox {
min: 0
name: "Fade duration"
object: Config.background
setting: "wallFadeDuration"
step: 50
}
Separator {
}
WallpaperCropper {
}
}
SettingsSection {
sectionId: "Wallpapers"
WallpaperGrid {
}
}
}
-217
View File
@@ -1,217 +0,0 @@
import qs.Modules.Settings.Controls
import qs.Config
SettingsPage {
SettingsSection {
sectionId: "Bar"
SettingsHeader {
name: "Bar"
}
SettingSwitch {
name: "Auto hide"
object: Config.bar
setting: "autoHide"
}
Separator {
}
SettingSpinBox {
min: 1
name: "Height"
object: Config.bar
setting: "height"
}
Separator {
}
SettingSpinBox {
min: 0
name: "Rounding"
object: Config.bar
setting: "rounding"
}
Separator {
}
SettingSpinBox {
min: 0
name: "Border"
object: Config.bar
setting: "border"
}
Separator {
}
SettingSpinBox {
min: 0
name: "Smoothing"
object: Config.bar
setting: "smoothing"
}
}
SettingsSection {
sectionId: "Tray"
SettingsHeader {
name: "System tray"
}
SettingSpinBox {
min: 16
name: "Tray icon size"
object: Config.bar.tray
setting: "trayIconSize"
}
}
SettingsSection {
sectionId: "Popouts"
SettingsHeader {
name: "Popouts"
}
SettingSwitch {
name: "Tray"
object: Config.bar.popouts
setting: "tray"
}
Separator {
}
SettingSwitch {
name: "Audio"
object: Config.bar.popouts
setting: "audio"
}
Separator {
}
SettingSwitch {
name: "Active window"
object: Config.bar.popouts
setting: "activeWindow"
}
Separator {
}
SettingSwitch {
name: "Resources"
object: Config.bar.popouts
setting: "resources"
}
Separator {
}
SettingSwitch {
name: "Clock"
object: Config.bar.popouts
setting: "clock"
}
Separator {
}
SettingSwitch {
name: "Network"
object: Config.bar.popouts
setting: "network"
}
Separator {
}
SettingSwitch {
name: "Power"
object: Config.bar.popouts
setting: "upower"
}
}
SettingsSection {
sectionId: "Entries"
SettingsHeader {
name: "Entries"
}
SettingBarEntryList {
name: "Bar entries"
object: Config.bar
setting: "entries"
}
}
SettingsSection {
sectionId: "Dock"
SettingsHeader {
name: "Dock"
}
SettingSwitch {
name: "Enable dock"
object: Config.dock
setting: "enable"
}
Separator {
}
SettingSpinBox {
min: 1
name: "Dock height"
object: Config.dock
setting: "height"
}
Separator {
}
SettingSwitch {
name: "Hover to reveal"
object: Config.dock
setting: "hoverToReveal"
}
Separator {
}
SettingSwitch {
name: "Pin on startup"
object: Config.dock
setting: "pinnedOnStartup"
}
Separator {
}
SettingStringList {
addLabel: qsTr("Add pinned app")
name: "Pinned apps"
object: Config.dock
setting: "pinnedApps"
}
Separator {
}
SettingStringList {
addLabel: qsTr("Add ignored regex")
name: "Ignored app regexes"
object: Config.dock
setting: "ignoredAppRegexes"
}
}
}
-218
View File
@@ -1,218 +0,0 @@
import qs.Modules.Settings.Controls
import qs.Config
SettingsPage {
SettingsSection {
sectionId: "Dashboard"
SettingsHeader {
name: "Dashboard"
}
SettingSwitch {
name: "Enable dashboard"
object: Config.dashboard
setting: "enabled"
}
Separator {
}
SettingSpinBox {
min: 0
name: "Media update interval"
object: Config.dashboard
setting: "mediaUpdateInterval"
step: 50
}
Separator {
}
SettingSpinBox {
min: 0
name: "Resource update interval"
object: Config.dashboard
setting: "resourceUpdateInterval"
step: 50
}
Separator {
}
SettingSpinBox {
min: 0
name: "Drag threshold"
object: Config.dashboard
setting: "dragThreshold"
}
}
SettingsSection {
sectionId: "Performance"
SettingsHeader {
name: "Performance"
}
SettingSwitch {
name: "Show battery"
object: Config.dashboard.performance
setting: "showBattery"
}
Separator {
}
SettingSwitch {
name: "Show GPU"
object: Config.dashboard.performance
setting: "showGpu"
}
Separator {
}
SettingSwitch {
name: "Show CPU"
object: Config.dashboard.performance
setting: "showCpu"
}
Separator {
}
SettingSwitch {
name: "Show memory"
object: Config.dashboard.performance
setting: "showMemory"
}
Separator {
}
SettingSwitch {
name: "Show storage"
object: Config.dashboard.performance
setting: "showStorage"
}
Separator {
}
SettingSwitch {
name: "Show network"
object: Config.dashboard.performance
setting: "showNetwork"
}
}
// SettingsSection {
// sectionId: "Layout Sizes"
//
// SettingsHeader {
// name: "Layout Sizes"
// }
//
// SettingReadOnly {
// name: "Tab indicator height"
// value: String(Config.dashboard.sizes.tabIndicatorHeight)
// }
//
// Separator {
// }
//
// SettingReadOnly {
// name: "Tab indicator spacing"
// value: String(Config.dashboard.sizes.tabIndicatorSpacing)
// }
//
// Separator {
// }
//
// SettingReadOnly {
// name: "Info width"
// value: String(Config.dashboard.sizes.infoWidth)
// }
//
// Separator {
// }
//
// SettingReadOnly {
// name: "Info icon size"
// value: String(Config.dashboard.sizes.infoIconSize)
// }
//
// Separator {
// }
//
// SettingReadOnly {
// name: "Date time width"
// value: String(Config.dashboard.sizes.dateTimeWidth)
// }
//
// Separator {
// }
//
// SettingReadOnly {
// name: "Media width"
// value: String(Config.dashboard.sizes.mediaWidth)
// }
//
// Separator {
// }
//
// SettingReadOnly {
// name: "Media progress sweep"
// value: String(Config.dashboard.sizes.mediaProgressSweep)
// }
//
// Separator {
// }
//
// SettingReadOnly {
// name: "Media progress thickness"
// value: String(Config.dashboard.sizes.mediaProgressThickness)
// }
//
// Separator {
// }
//
// SettingReadOnly {
// name: "Resource progress thickness"
// value: String(Config.dashboard.sizes.resourceProgessThickness)
// }
//
// Separator {
// }
//
// SettingReadOnly {
// name: "Weather width"
// value: String(Config.dashboard.sizes.weatherWidth)
// }
//
// Separator {
// }
//
// SettingReadOnly {
// name: "Media cover art size"
// value: String(Config.dashboard.sizes.mediaCoverArtSize)
// }
//
// Separator {
// }
//
// SettingReadOnly {
// name: "Media visualiser size"
// value: String(Config.dashboard.sizes.mediaVisualiserSize)
// }
//
// Separator {
// }
//
// SettingReadOnly {
// name: "Resource size"
// value: String(Config.dashboard.sizes.resourceSize)
// }
// }
}
-308
View File
@@ -1,308 +0,0 @@
import Quickshell
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import qs.Modules.Settings.Controls
import qs.Config
import qs.Components
import qs.Helpers
SettingsPage {
id: root
function schemeTypeItem(items, value) {
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (item.value === value)
return item;
}
return items[0] ?? null;
}
SettingsSection {
sectionId: "General"
SettingsHeader {
name: "General"
}
SettingInput {
name: "Logo"
object: Config.general
setting: "logo"
}
Separator {
}
SettingInput {
name: "Wallpaper path"
object: Config.general
setting: "wallpaperPath"
}
Separator {
}
SettingSwitch {
name: "Desktop icons"
object: Config.general
setting: "desktopIcons"
}
Separator {
}
SettingInput {
name: "Date format"
object: Config.general
setting: "dateFormat"
}
}
SettingsSection {
sectionId: "Color"
z: 1
SettingsHeader {
name: "Color"
}
CustomSplitButtonRow {
active: Config.general.color.mode === "light" ? menuItems[0] : menuItems[1]
enabled: Config.general.color.schemeGeneration
label: qsTr("Scheme mode")
menuItems: [
MenuItem {
icon: "light_mode"
text: qsTr("Light")
value: "light"
},
MenuItem {
icon: "dark_mode"
text: qsTr("Dark")
value: "dark"
}
]
onSelected: item => {
Config.general.color.mode = item.value;
Config.save();
if (item.value === "light")
ModeScheduler.applyLightMode();
else if (item.value === "dark")
ModeScheduler.applyDarkMode();
}
}
Separator {
}
CustomSplitButtonRow {
id: schemeType
active: root.schemeTypeItem(menuItems, Config.colors.schemeType)
enabled: Config.general.color.schemeGeneration
label: qsTr("Scheme type")
menuItems: [
MenuItem {
icon: "palette"
text: qsTr("Vibrant")
value: "vibrant"
},
MenuItem {
icon: "gesture"
text: qsTr("Expressive")
value: "expressive"
},
MenuItem {
icon: "contrast"
text: qsTr("Monochrome")
value: "monochrome"
},
MenuItem {
icon: "tonality"
text: qsTr("Neutral")
value: "neutral"
},
MenuItem {
icon: "gradient"
text: qsTr("Tonal spot")
value: "tonal-spot"
},
MenuItem {
icon: "target"
text: qsTr("Fidelity")
value: "fidelity"
},
MenuItem {
icon: "article"
text: qsTr("Content")
value: "content"
},
MenuItem {
icon: "colors"
text: qsTr("Rainbow")
value: "rainbow"
},
MenuItem {
icon: "nutrition"
text: qsTr("Fruit salad")
value: "fruit-salad"
}
]
onSelected: item => {
Config.colors.schemeType = item.value;
Config.save();
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--scheme", item.value]);
}
}
Separator {
}
SettingSwitch {
name: "Automatic color scheme"
object: Config.general.color
setting: "schemeGeneration"
}
Separator {
shouldBeActive: Config.general.color.schemeGeneration ? 0 : 1
}
SchemesListView {
name: "Color scheme presets"
object: Config.colors.presets
setting: "name"
shouldBeActive: Config.general.color.schemeGeneration ? 0 : 1
stringList: FetchPresets.presetNames()
}
Separator {
shouldBeActive: Config.colors.presets.name !== "" && !Config.general.color.schemeGeneration
}
SchemesListView {
name: "Preset variant"
object: Config.colors.presets
setting: "variant"
shouldBeActive: Config.colors.presets.name !== "" && !Config.general.color.schemeGeneration
stringList: FetchPresets.variantNames(Config.colors.presets.name)
onOptionSet: item => {
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--preset", `${Config.colors.presets.name.toLowerCase()}:${item}`]);
}
}
Separator {
shouldBeActive: Config.colors.presets.variant !== "" && FetchPresets.accents(Config.colors.presets.name, Config.colors.presets.variant).length > 0 && !Config.general.color.schemeGeneration
}
SchemesListView {
name: "Preset accent"
object: Config.colors.presets
setting: "accent"
shouldBeActive: Config.colors.presets.variant !== "" && FetchPresets.accents(Config.colors.presets.name, Config.colors.presets.variant).length > 0 && !Config.general.color.schemeGeneration
stringList: FetchPresets.accents(Config.colors.presets.name, Config.colors.presets.variant)
onOptionSet: item => {
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--preset", `${Config.colors.presets.name.toLowerCase()}:${Config.colors.presets.variant}`, "--accent", `${item}`]);
}
}
Separator {
shouldBeActive: Config.general.color.schemeGeneration ? 1 : 0
}
SettingSwitch {
name: "Smart color scheme"
object: Config.general.color
setting: "smart"
shouldBeActive: Config.general.color.schemeGeneration ? 1 : 0
}
Separator {
shouldBeActive: Config.general.color.schemeGeneration ? 1 : 0
}
TimeInput {
name: "Schedule dark mode"
object: Config.general.color
settings: ["scheduleDark", "scheduleDarkStart", "scheduleDarkEnd"]
shouldBeActive: Config.general.color.schemeGeneration
}
Separator {
}
HyprTimeInput {
name: "Schedule Hyprsunset"
object: Config.general.color
settings: ["scheduleHyprsunset", "scheduleHyprsunsetStart", "scheduleHyprsunsetEnd", "hyprsunsetTemp"]
}
Separator {
}
SettingSpinBox {
max: 20000
min: 1000
name: "Hyprsunset temperature"
object: Config.general.color
setting: "hyprsunsetTemp"
step: 200
}
}
SettingsSection {
sectionId: "Default Apps"
SettingsHeader {
name: "Default Apps"
}
SettingStringList {
addLabel: qsTr("Add terminal command")
name: "Terminal"
object: Config.general.apps
setting: "terminal"
}
Separator {
}
SettingStringList {
addLabel: qsTr("Add audio command")
name: "Audio"
object: Config.general.apps
setting: "audio"
}
Separator {
}
SettingStringList {
addLabel: qsTr("Add playback command")
name: "Playback"
object: Config.general.apps
setting: "playback"
}
Separator {
}
SettingStringList {
addLabel: qsTr("Add explorer command")
name: "Explorer"
object: Config.general.apps
setting: "explorer"
}
}
}
-165
View File
@@ -1,165 +0,0 @@
import qs.Modules.Settings.Controls
import qs.Config
SettingsPage {
SettingsSection {
sectionId: "Launcher"
SettingsHeader {
name: "Launcher"
}
SettingSpinBox {
min: 1
name: "Max apps shown"
object: Config.launcher
setting: "maxAppsShown"
}
Separator {
}
SettingSpinBox {
min: 1
name: "Max wallpapers shown"
object: Config.launcher
setting: "maxWallpapers"
}
Separator {
}
SettingInput {
name: "Action prefix"
object: Config.launcher
setting: "actionPrefix"
}
Separator {
}
SettingInput {
name: "Special prefix"
object: Config.launcher
setting: "specialPrefix"
}
Separator {
}
SettingSwitch {
name: "Use UWSM launch command"
object: Config.launcher
setting: "uwsm"
}
}
SettingsSection {
sectionId: "Fuzzy Search"
SettingsHeader {
name: "Fuzzy Search"
}
SettingSwitch {
name: "Apps"
object: Config.launcher.useFuzzy
setting: "apps"
}
Separator {
}
SettingSwitch {
name: "Actions"
object: Config.launcher.useFuzzy
setting: "actions"
}
Separator {
}
SettingSwitch {
name: "Schemes"
object: Config.launcher.useFuzzy
setting: "schemes"
}
Separator {
}
SettingSwitch {
name: "Variants"
object: Config.launcher.useFuzzy
setting: "variants"
}
Separator {
}
SettingSwitch {
name: "Wallpapers"
object: Config.launcher.useFuzzy
setting: "wallpapers"
}
}
SettingsSection {
sectionId: "Sizes"
SettingsHeader {
name: "Sizes"
}
SettingSpinBox {
min: 1
name: "Item width"
object: Config.launcher.sizes
setting: "itemWidth"
}
Separator {
}
SettingSpinBox {
min: 1
name: "Item height"
object: Config.launcher.sizes
setting: "itemHeight"
}
Separator {
}
SettingSpinBox {
min: 1
name: "Wallpaper width"
object: Config.launcher.sizes
setting: "wallpaperWidth"
}
Separator {
}
SettingSpinBox {
min: 1
name: "Wallpaper height"
object: Config.launcher.sizes
setting: "wallpaperHeight"
}
}
SettingsSection {
sectionId: "Actions"
SettingsHeader {
name: "Actions"
}
SettingActionList {
name: "Launcher actions"
object: Config.launcher
setting: "actions"
}
}
}
-125
View File
@@ -1,125 +0,0 @@
import qs.Modules.Settings.Categories.Lockscreen
import qs.Modules.Settings.Controls
import qs.Helpers
import qs.Config
SettingsPage {
id: root
SettingsSection {
sectionId: "Lockscreen"
SettingsHeader {
name: "Lockscreen"
}
SettingSwitch {
name: "Recolor logo"
object: Config.lock
setting: "recolorLogo"
}
Separator {
}
SettingSwitch {
name: "Enable fingerprint"
object: Config.lock
setting: "enableFprint"
}
Separator {
}
SettingSpinBox {
min: 1
name: "Max fingerprint tries"
object: Config.lock
setting: "maxFprintTries"
step: 1
}
Separator {
}
SettingSwitch {
name: "Show notification details"
object: Config.lock
setting: "showNotifContent"
}
Separator {
}
SettingSwitch {
name: "Show notification icon"
object: Config.lock
setting: "showNotifIcon"
}
Separator {
}
SettingSpinBox {
min: 0
name: "Blur amount"
object: Config.lock
setting: "blurAmount"
step: 1
}
Separator {
}
SettingSpinBox {
max: 2
min: 0.1
name: "Height multiplier"
object: Config.lock.sizes
setting: "heightMult"
step: 0.05
}
Separator {
}
SettingSpinBox {
max: 4
min: 0.5
name: "Aspect ratio"
object: Config.lock.sizes
setting: "ratio"
step: 0.05
}
Separator {
}
SettingSpinBox {
min: 100
name: "Center width"
object: Config.lock.sizes
setting: "centerWidth"
step: 10
}
}
SettingsSection {
sectionId: "Greeter"
SettingsHeader {
name: "Greeter"
}
SettingsIconButton {
name: "Install wallpaper and color scheme to greeter"
}
}
SettingsSection {
sectionId: "Idle"
Idle {
}
}
}
@@ -1,115 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
import qs.Modules.Settings.Controls
ColumnLayout {
id: root
property bool shouldBeActive: true
function addTimeoutEntry() {
let list = [...Config.general.idle.timeouts];
list.push({
name: "New Entry",
timeout: 600,
idleAction: "lock"
});
Config.general.idle.timeouts = list;
Config.save();
}
function deleteTimeoutEntry(index) {
let list = [...Config.general.idle.timeouts];
list.splice(index, 1);
Config.general.idle.timeouts = list;
Config.save();
}
function updateTimeoutEntry(i, key, value) {
const list = [...Config.general.idle.timeouts];
let entry = list[i];
entry[key] = value;
list[i] = entry;
Config.general.idle.timeouts = list;
Config.save();
}
anchors.left: parent.left
anchors.right: parent.right
height: shouldBeActive ? implicitHeight : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
spacing: Appearance.spacing.smaller
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Settings {
name: "Idle Monitors"
}
Repeater {
model: [...Config.general.idle.timeouts]
SettingList {
Layout.fillWidth: true
anchors.left: undefined
anchors.right: undefined
onAddActiveActionRequested: {
root.updateTimeoutEntry(index, "activeAction", "");
}
onDeleteRequested: function (index) {
root.deleteTimeoutEntry(index);
}
onFieldEdited: function (key, value) {
root.updateTimeoutEntry(index, key, value);
}
}
}
IconButton {
font.pointSize: Appearance.font.size.large
icon: "add"
onClicked: root.addTimeoutEntry()
}
component Settings: CustomRect {
id: settingsItem
required property string name
Layout.preferredHeight: 60
Layout.preferredWidth: 200
CustomText {
id: text
anchors.fill: parent
font.bold: true
font.pointSize: Appearance.font.size.large * 2
text: settingsItem.name
verticalAlignment: Text.AlignVCenter
}
}
}
@@ -1,116 +0,0 @@
import qs.Modules.Settings.Controls
import qs.Config
SettingsPage {
SettingsSection {
sectionId: "Notifications"
SettingsHeader {
name: "Notifications"
}
SettingSwitch {
name: "Expire notifications"
object: Config.notifs
setting: "expire"
}
Separator {
}
SettingSpinBox {
name: "Default expire timeout"
min: 0
object: Config.notifs
setting: "defaultExpireTimeout"
step: 100
}
Separator {
}
SettingSpinBox {
name: "App notification cooldown"
min: 0
object: Config.notifs
setting: "appNotifCooldown"
step: 100
}
Separator {
}
SettingSpinBox {
name: "Clear threshold"
max: 1
min: 0
object: Config.notifs
setting: "clearThreshold"
step: 0.05
}
Separator {
}
SettingSpinBox {
name: "Expand threshold"
min: 0
object: Config.notifs
setting: "expandThreshold"
}
Separator {
}
SettingSwitch {
name: "Action on click"
object: Config.notifs
setting: "actionOnClick"
}
Separator {
}
SettingSpinBox {
name: "Group preview count"
min: 1
object: Config.notifs
setting: "groupPreviewNum"
}
}
SettingsSection {
sectionId: "Sizes"
SettingsHeader {
name: "Sizes"
}
SettingSpinBox {
name: "Width"
min: 1
object: Config.notifs.sizes
setting: "width"
}
Separator {
}
SettingSpinBox {
name: "Image size"
min: 1
object: Config.notifs.sizes
setting: "image"
}
Separator {
}
SettingSpinBox {
name: "Badge size"
min: 1
object: Config.notifs.sizes
setting: "badge"
}
}
}
-81
View File
@@ -1,81 +0,0 @@
import qs.Modules.Settings.Controls
import qs.Config
SettingsPage {
SettingsSection {
sectionId: "On Screen Display"
SettingsHeader {
name: "On Screen Display"
}
SettingSwitch {
name: "Enable OSD"
object: Config.osd
setting: "enabled"
}
Separator {
}
SettingSpinBox {
name: "Hide delay"
min: 0
object: Config.osd
setting: "hideDelay"
step: 100
}
Separator {
}
SettingSwitch {
name: "Enable brightness OSD"
object: Config.osd
setting: "enableBrightness"
}
Separator {
}
SettingSwitch {
name: "Enable microphone OSD"
object: Config.osd
setting: "enableMicrophone"
}
Separator {
}
SettingSwitch {
name: "Brightness on all monitors"
object: Config.osd
setting: "allMonBrightness"
}
}
SettingsSection {
sectionId: "Sizes"
SettingsHeader {
name: "Sizes"
}
SettingSpinBox {
name: "Slider width"
min: 1
object: Config.osd.sizes
setting: "sliderWidth"
}
Separator {
}
SettingSpinBox {
name: "Slider height"
min: 1
object: Config.osd.sizes
setting: "sliderHeight"
}
}
}
-150
View File
@@ -1,150 +0,0 @@
import qs.Modules.Settings.Controls
import qs.Config
import qs.Components
SettingsPage {
SettingsSection {
sectionId: "Screenshot"
SettingsHeader {
name: "Screenshot"
}
SettingSwitch {
name: "Enable effects"
object: Config.screenshot
setting: "enable_pp"
}
Separator {
}
CustomSplitButtonRow {
active: Config.screenshot.mode === "manual" ? menuItems[0] : menuItems[1]
enabled: Config.screenshot.enable_pp
label: qsTr("Effects mode")
menuItems: [
MenuItem {
icon: "build"
text: qsTr("Manual")
value: "manual"
},
MenuItem {
icon: "rotate_auto"
text: qsTr("Auto")
value: "auto"
}
]
onSelected: item => {
Config.screenshot.mode = item.value;
Config.save();
}
}
Separator {
shouldBeActive: Config.screenshot.mode === "manual"
}
SettingSwitch {
enabled: Config.screenshot.enable_pp
name: "Enable rounded corners"
object: Config.screenshot
setting: "rounding"
shouldBeActive: Config.screenshot.mode === "manual"
}
Separator {
shouldBeActive: Config.screenshot.mode === "manual" && Config.screenshot.rounding
}
SettingSpinBox {
enabled: Config.screenshot.enable_pp
min: 0
name: "Corner radius"
object: Config.screenshot
setting: "radius"
shouldBeActive: Config.screenshot.mode === "manual" && Config.screenshot.rounding
step: 1
}
Separator {
shouldBeActive: Config.screenshot.mode === "manual"
}
SettingSwitch {
enabled: Config.screenshot.enable_pp
name: "Enable shadow"
object: Config.screenshot
setting: "shadow"
shouldBeActive: Config.screenshot.mode === "manual"
}
Separator {
shouldBeActive: Config.screenshot.mode === "manual" && Config.screenshot.shadow
}
SettingSpinBox {
enabled: Config.screenshot.enable_pp
min: 0
name: "Shadow blur amount"
object: Config.screenshot
setting: "shadow_blur"
shouldBeActive: Config.screenshot.mode === "manual" && Config.screenshot.shadow
step: 1
}
Separator {
shouldBeActive: Config.screenshot.mode === "manual" && Config.screenshot.shadow
}
// SettingSwitch {
// name: "Shadow color broken atm"
// object: Config.Screenshot
// setting: "shadow_color"
// shouldBeActive: Config.screenshot.mode === "manual"
// }
//
// Separator {
// shouldBeActive: Config.screenshot.mode === "manual"
// }
// SettingSpinBox {
// min: 1
// name: "Shadow passes"
// object: Config.screenshot
// setting: "shadow_blur_passes"
// shouldBeActive: Config.screenshot.mode === "manual"
// step: 1
// }
//
// Separator {
// shouldBeActive: Config.screenshot.mode === "manual"
// }
SettingSpinBox {
enabled: Config.screenshot.enable_pp
min: 0
name: "Shadow offset X"
object: Config.screenshot
setting: "shadow_offset_x"
shouldBeActive: Config.screenshot.mode === "manual" && Config.screenshot.shadow
step: 1
}
Separator {
shouldBeActive: Config.screenshot.mode === "manual" && Config.screenshot.shadow
}
SettingSpinBox {
enabled: Config.screenshot.enable_pp
min: 0
name: "Shadow offset Y"
object: Config.screenshot
setting: "shadow_offset_y"
shouldBeActive: Config.screenshot.mode === "manual" && Config.screenshot.shadow
step: 1
}
}
}
-145
View File
@@ -1,145 +0,0 @@
import qs.Modules.Settings.Controls
import qs.Config
SettingsPage {
SettingsSection {
sectionId: "Services"
SettingsHeader {
name: "Services"
}
SettingInput {
name: "Weather location"
object: Config.services
setting: "weatherLocation"
}
Separator {
}
SettingSwitch {
name: "Check for updates"
object: Config.services
setting: "updates"
}
Separator {
}
SettingSwitch {
name: "Use Fahrenheit"
object: Config.services
setting: "useFahrenheit"
}
Separator {
}
SettingSwitch {
name: "Use twelve hour clock"
object: Config.services
setting: "useTwelveHourClock"
}
Separator {
}
SettingSwitch {
name: "Enable ddcutil service"
object: Config.services
setting: "ddcutilService"
}
Separator {
}
SettingInput {
name: "GPU type"
object: Config.services
setting: "gpuType"
}
}
SettingsSection {
sectionId: "Media"
SettingsHeader {
name: "Media"
}
SettingSpinBox {
max: 1
min: 0
name: "Audio increment"
object: Config.services
setting: "audioIncrement"
step: 0.05
}
Separator {
}
SettingSpinBox {
max: 1
min: 0
name: "Brightness increment"
object: Config.services
setting: "brightnessIncrement"
step: 0.05
}
Separator {
}
SettingSpinBox {
max: 1.0
min: 0
name: "Minimum brightness"
object: Config.services
setting: "minBrightness"
step: 0.01
}
Separator {
}
SettingSpinBox {
max: 5
min: 0
name: "Max volume"
object: Config.services
setting: "maxVolume"
step: 0.05
}
Separator {
}
SettingInput {
name: "Default player"
object: Config.services
setting: "defaultPlayer"
}
Separator {
}
SettingSpinBox {
min: 1
name: "Visualizer resolution"
object: Config.services
setting: "visualizerBars"
step: 1
}
Separator {
}
SettingAliasList {
name: "Player aliases"
object: Config.services
setting: "playerAliases"
}
}
}
-28
View File
@@ -1,28 +0,0 @@
import qs.Modules.Settings.Controls
import qs.Config
SettingsPage {
SettingsSection {
sectionId: "Sidebar"
SettingsHeader {
name: "Sidebar"
}
SettingSwitch {
name: "Enable sidebar"
object: Config.sidebar
setting: "enabled"
}
Separator {
}
SettingSpinBox {
name: "Width"
min: 1
object: Config.sidebar.sizes
setting: "width"
}
}
}
@@ -1,197 +0,0 @@
pragma ComponentBehavior: Bound
import Quickshell
import QtQuick.Layouts
import QtQuick
import qs.Config
import qs.Helpers
import qs.Components
import qs.Modules.Settings.Controls
CustomClippingRect {
id: root
radius: Appearance.rounding.normal - Appearance.padding.smaller
ColumnLayout {
anchors.fill: parent
RowLayout {
Layout.fillWidth: true
Layout.margins: Appearance.padding.large
spacing: Appearance.spacing.large
MaterialIcon {
font.pointSize: Appearance.font.size.larger * 4
text: "update"
}
ColumnLayout {
CustomText {
font.pointSize: Appearance.font.size.large * 2
text: "System updates"
}
RowLayout {
id: row
Layout.fillWidth: true
CustomText {
id: text
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: `${Updates.availableUpdates} available updates`
}
CustomRect {
Layout.preferredHeight: 40
Layout.preferredWidth: 150
color: Updates.updating ? DynamicColors.layer(DynamicColors.palette.m3outline, 2) : DynamicColors.palette.m3primary
radius: Appearance.rounding.full
RowLayout {
anchors.centerIn: parent
MaterialIcon {
animate: true
color: DynamicColors.palette.m3onPrimary
font.pointSize: Appearance.font.size.large
text: Updates.updating ? "update" : "download"
}
CustomText {
color: Updates.updating ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3onPrimary
text: "Update all"
}
}
StateLayer {
color: DynamicColors.palette.m3onPrimary
enabled: !Updates.updating
onClicked: Updates.performSystemUpdate()
}
}
}
}
}
CustomListView {
id: view
readonly property int itemHeight: 50 + Appearance.padding.smaller * 2
Layout.fillHeight: true
Layout.fillWidth: true
clip: true
contentHeight: height
spacing: Appearance.spacing.normal
delegate: CustomRect {
id: update
required property var modelData
readonly property list<string> sections: modelData.update.split(" ")
color: DynamicColors.tPalette.m3surfaceContainer
implicitHeight: view.itemHeight
implicitWidth: parent.width
radius: Appearance.rounding.small - Appearance.padding.small
RowLayout {
anchors.fill: parent
anchors.leftMargin: Appearance.padding.smaller
anchors.rightMargin: Appearance.padding.smaller
MaterialIcon {
font.pointSize: Appearance.font.size.large * 2
text: "package_2"
}
ColumnLayout {
Layout.fillWidth: true
CustomText {
Layout.fillWidth: true
Layout.preferredHeight: 25
elide: Text.ElideRight
font.pointSize: Appearance.font.size.large
text: update.sections[0]
}
CustomText {
Layout.fillWidth: true
color: DynamicColors.palette.m3onSurfaceVariant
text: Updates.formatUpdateTime(update.modelData.timestamp)
}
}
RowLayout {
Layout.fillHeight: true
Layout.preferredWidth: 500
MarqueeText {
id: versionFrom
Layout.fillHeight: true
Layout.preferredWidth: 225
animate: true
color: DynamicColors.palette.m3tertiary
font.pointSize: Appearance.font.size.large
horizontalAlignment: Text.AlignHCenter
marqueeEnabled: true
pauseMs: 4000
text: update.sections[1]
width: 225
}
MaterialIcon {
Layout.fillHeight: true
color: DynamicColors.palette.m3secondary
font.pointSize: Appearance.font.size.extraLarge
horizontalAlignment: Text.AlignHCenter
text: "arrow_right_alt"
verticalAlignment: Text.AlignVCenter
}
MarqueeText {
id: versionTo
Layout.fillHeight: true
Layout.preferredWidth: 225
animate: true
color: DynamicColors.palette.m3primary
font.pointSize: Appearance.font.size.large
horizontalAlignment: Text.AlignHCenter
marqueeEnabled: true
pauseMs: 4000
text: update.sections[3]
width: 225
}
}
IconButton {
Layout.preferredHeight: width
icon: "download"
onClicked: {
Updates.performPackageUpdate(update.sections[0]);
}
}
}
}
model: ScriptModel {
id: script
objectProp: "update"
values: Object.entries(Updates.updates).sort((a, b) => b[1] - a[1]).map(([update, timestamp]) => ({
update,
timestamp
}))
}
}
}
}
-245
View File
@@ -1,245 +0,0 @@
import qs.Modules.Settings.Controls
import qs.Config
SettingsPage {
SettingsSection {
sectionId: "Utilities"
SettingsHeader {
name: "Utilities"
}
SettingSwitch {
name: "Enable utilities"
object: Config.utilities
setting: "enabled"
}
Separator {
}
SettingSpinBox {
min: 1
name: "Max toasts"
object: Config.utilities
setting: "maxToasts"
}
Separator {
}
SettingSpinBox {
min: 1
name: "Panel width"
object: Config.utilities.sizes
setting: "width"
}
Separator {
}
SettingSpinBox {
min: 1
name: "Toast width"
object: Config.utilities.sizes
setting: "toastWidth"
}
}
SettingsSection {
sectionId: "Clipboard"
SettingsHeader {
name: "Clipboard"
}
SettingSwitch {
name: "Enable clipboard history viewer"
object: Config.clipboard
setting: "enabled"
}
Separator {
}
SettingSpinBox {
max: 20
min: 1
name: "Max entries visible"
object: Config.clipboard
setting: "maxEntriesShown"
}
Separator {
}
SettingSpinBox {
max: 80
min: 30
name: "Entry height"
object: Config.clipboard.sizes
setting: "itemHeight"
}
Separator {
}
SettingSpinBox {
max: 700
min: 300
name: "Entry width"
object: Config.clipboard.sizes
setting: "width"
}
Separator {
}
SettingSpinBox {
max: 1800
min: 50
name: "Minimum preview width"
object: Config.clipboard.sizes
setting: "minPreviewWidth"
}
Separator {
}
SettingSpinBox {
max: 1800
min: 50
name: "Maximum preview width"
object: Config.clipboard.sizes
setting: "previewWidth"
}
}
SettingsSection {
sectionId: "Toasts"
SettingsHeader {
name: "Toasts"
}
SettingSwitch {
name: "Config loaded"
object: Config.utilities.toasts
setting: "configLoaded"
}
Separator {
}
SettingSwitch {
name: "Charging changed"
object: Config.utilities.toasts
setting: "chargingChanged"
}
Separator {
}
SettingSwitch {
name: "Game mode changed"
object: Config.utilities.toasts
setting: "gameModeChanged"
}
// Separator {
// }
//
// SettingSwitch {
// name: "Do not disturb changed"
// object: Config.utilities.toasts
// setting: "dndChanged"
// }
//
// Separator {
// }
//
// SettingSwitch {
// name: "Audio output changed"
// object: Config.utilities.toasts
// setting: "audioOutputChanged"
// }
//
// Separator {
// }
//
// SettingSwitch {
// name: "Audio input changed"
// object: Config.utilities.toasts
// setting: "audioInputChanged"
// }
//
// Separator {
// }
//
// SettingSwitch {
// name: "Caps lock changed"
// object: Config.utilities.toasts
// setting: "capsLockChanged"
// }
//
// Separator {
// }
//
// SettingSwitch {
// name: "Num lock changed"
// object: Config.utilities.toasts
// setting: "numLockChanged"
// }
//
// Separator {
// }
//
// SettingSwitch {
// name: "Keyboard layout changed"
// object: Config.utilities.toasts
// setting: "kbLayoutChanged"
// }
//
// Separator {
// }
//
// SettingSwitch {
// name: "VPN changed"
// object: Config.utilities.toasts
// setting: "vpnChanged"
// }
//
// Separator {
// }
//
// SettingSwitch {
// name: "Now playing"
// object: Config.utilities.toasts
// setting: "nowPlaying"
// }
}
// SettingsSection {
// sectionId: "VPN"
//
// SettingsHeader {
// name: "VPN"
// }
//
// SettingSwitch {
// name: "Enable VPN integration"
// object: Config.utilities.vpn
// setting: "enabled"
// }
//
// Separator {
// }
//
// SettingStringList {
// name: "Provider"
// addLabel: qsTr("Add VPN provider")
// object: Config.utilities.vpn
// setting: "provider"
// }
// }
}
@@ -2,7 +2,7 @@ import QtQuick
import QtQuick.Layouts
import qs.Config
import qs.Components
import qs.Modules.SettingsNew
import qs.Modules.Settings
ConnectedRect {
id: root
@@ -2,7 +2,7 @@ pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import qs.Modules.SettingsNew
import qs.Modules.Settings
import qs.Components
import qs.Config
@@ -1,7 +1,7 @@
import QtQuick
import QtQuick.Controls
import qs.Components
import qs.Modules.SettingsNew
import qs.Modules.Settings
import qs.Config
StackView {
+47 -369
View File
@@ -1,398 +1,76 @@
pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Widgets
import QtQuick
import QtQuick.Controls
import ZShell.Blobs
import qs.Components
import qs.Modules as Modules
import qs.Modules.Settings.Categories as Cat
import qs.Config
import qs.Helpers
Item {
CustomClippingRect {
id: root
property string currentCategory: "general"
property int currentIndex: 0
property int lastIndex: 0
readonly property real nonAnimHeight: Math.floor(screen.height / 1.5) + viewWrapper.anchors.margins * 2
readonly property real nonAnimWidth: view.implicitWidth + Math.floor(screen.width / 2) + viewWrapper.anchors.margins * 2
property string pendingSection: ""
property string pendingSetting: ""
required property ShellScreen screen
required property PersistentProperties visibilities
property color blobColor: DynamicColors.tPalette.m3surfaceContainerLow
readonly property real ratio: 16.0 / 9.0
readonly property SettingsState sState: SettingsState {
id: sState
function scrollToSetting(section: string, settingName: string) {
root.pendingSection = section;
root.pendingSetting = settingName;
scrollTimer.restart();
onClose: root.close()
}
function setCategory(category: string, index: int): void {
currentIndex = index;
currentCategory = category;
}
signal close
implicitHeight: nonAnimHeight
implicitWidth: nonAnimWidth
implicitHeight: sState.screen.height * 0.7
implicitWidth: implicitHeight * ratio
radius: Appearance.rounding.large + Appearance.padding.normal
Timer {
id: scrollTimer
interval: 50
onTriggered: {
if (root.pendingSection && stack.currentItem) {
stack.currentItem.scrollToSectionAndHighlight(root.pendingSection, root.pendingSetting);
root.pendingSection = "";
root.pendingSetting = "";
}
Behavior on blobColor {
CAnim {
}
}
Connections {
function onCurrentCategoryChanged() {
if (root.currentCategory === "general") {
stack.replaceCurrentItem(general, [], StackView.PopTransition);
root.lastIndex = root.currentIndex;
} else if (root.currentCategory === "wallpaper") {
if (root.currentIndex < root.lastIndex)
stack.replaceCurrentItem(background, [], StackView.PopTransition);
else
stack.replaceCurrentItem(background, [], StackView.PushTransition);
root.lastIndex = root.currentIndex;
} else if (root.currentCategory === "bar") {
if (root.currentIndex < root.lastIndex)
stack.replaceCurrentItem(bar, [], StackView.PopTransition);
else
stack.replaceCurrentItem(bar, [], StackView.PushTransition);
root.lastIndex = root.currentIndex;
} else if (root.currentCategory === "appearance") {
if (root.currentIndex < root.lastIndex)
stack.replaceCurrentItem(appearance, [], StackView.PopTransition);
else
stack.replaceCurrentItem(appearance, [], StackView.PushTransition);
root.lastIndex = root.currentIndex;
} else if (root.currentCategory === "lockscreen") {
if (root.currentIndex < root.lastIndex)
stack.replaceCurrentItem(lockscreen, [], StackView.PopTransition);
else
stack.replaceCurrentItem(lockscreen, [], StackView.PushTransition);
root.lastIndex = root.currentIndex;
} else if (root.currentCategory === "services") {
if (root.currentIndex < root.lastIndex)
stack.replaceCurrentItem(services, [], StackView.PopTransition);
else
stack.replaceCurrentItem(services, [], StackView.PushTransition);
root.lastIndex = root.currentIndex;
} else if (root.currentCategory === "notifications") {
if (root.currentIndex < root.lastIndex)
stack.replaceCurrentItem(notifications, [], StackView.PopTransition);
else
stack.replaceCurrentItem(notifications, [], StackView.PushTransition);
root.lastIndex = root.currentIndex;
} else if (root.currentCategory === "sidebar") {
if (root.currentIndex < root.lastIndex)
stack.replaceCurrentItem(sidebar, [], StackView.PopTransition);
else
stack.replaceCurrentItem(sidebar, [], StackView.PushTransition);
root.lastIndex = root.currentIndex;
} else if (root.currentCategory === "utilities") {
if (root.currentIndex < root.lastIndex)
stack.replaceCurrentItem(utilities, [], StackView.PopTransition);
else
stack.replaceCurrentItem(utilities, [], StackView.PushTransition);
root.lastIndex = root.currentIndex;
} else if (root.currentCategory === "dashboard") {
if (root.currentIndex < root.lastIndex)
stack.replaceCurrentItem(dashboard, [], StackView.PopTransition);
else
stack.replaceCurrentItem(dashboard, [], StackView.PushTransition);
root.lastIndex = root.currentIndex;
} else if (root.currentCategory === "osd") {
if (root.currentIndex < root.lastIndex)
stack.replaceCurrentItem(osd, [], StackView.PopTransition);
else
stack.replaceCurrentItem(osd, [], StackView.PushTransition);
root.lastIndex = root.currentIndex;
} else if (root.currentCategory === "launcher") {
if (root.currentIndex < root.lastIndex)
stack.replaceCurrentItem(launcher, [], StackView.PopTransition);
else
stack.replaceCurrentItem(launcher, [], StackView.PushTransition);
root.lastIndex = root.currentIndex;
} else if (root.currentCategory === "screenshot") {
if (root.currentIndex < root.lastIndex)
stack.replaceCurrentItem(screenshot, [], StackView.PopTransition);
else
stack.replaceCurrentItem(screenshot, [], StackView.PushTransition);
root.lastIndex = root.currentIndex;
} else if (root.currentCategory === "updates") {
if (root.currentIndex < root.lastIndex)
stack.replaceCurrentItem(updates, [], StackView.PopTransition);
else
stack.replaceCurrentItem(updates, [], StackView.PushTransition);
root.lastIndex = root.currentIndex;
}
}
target: root
TapHandler {
onTapped: root.focus = true
}
CustomClippingRect {
id: viewWrapper
BlobGroup {
id: blobGroup
color: root.blobColor
smoothing: Appearance.rounding.normal
}
BlobInvertedRect {
anchors.fill: parent
anchors.margins: Appearance.padding.smaller
radius: Appearance.rounding.large - Appearance.padding.smaller
SettingsSearch {
id: searchBar
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
onSettingSelected: (category, section, settingName) => {
layout.selectCategory(category);
root.scrollToSetting(section, settingName);
}
}
Item {
id: view
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.top: searchBar.bottom
anchors.topMargin: Appearance.spacing.smaller
implicitWidth: layout.implicitWidth
Categories {
id: layout
anchors.fill: parent
content: root
onSettingSelected: (category, section, settingName) => {
root.scrollToSetting(section, settingName);
}
}
}
CustomClippingRect {
id: categoryContent
anchors.bottom: parent.bottom
anchors.left: view.right
anchors.leftMargin: Appearance.spacing.smaller
anchors.right: parent.right
anchors.top: searchBar.bottom
anchors.topMargin: Appearance.spacing.smaller
color: DynamicColors.tPalette.m3surfaceContainer
radius: Appearance.rounding.normal
StackView {
id: stack
anchors.fill: parent
initialItem: general
popEnter: Transition {
SequentialAnimation {
Anim {
duration: 0
from: 0
property: "opacity"
to: 0
}
PauseAnimation {
duration: Appearance.anim.durations.expressiveEffects
}
ParallelAnimation {
Anim {
duration: Appearance.anim.durations.expressiveFastSpatial
from: 0
property: "opacity"
to: 1
}
Anim {
duration: Appearance.anim.durations.expressiveFastSpatial
from: -50
property: "y"
to: 0
}
}
}
}
popExit: Transition {
ParallelAnimation {
Anim {
duration: Appearance.anim.durations.expressiveFastSpatial
from: 1
property: "opacity"
to: 0
}
Anim {
duration: Appearance.anim.durations.expressiveFastSpatial
from: 0
property: "y"
to: 50
}
}
}
pushEnter: Transition {
SequentialAnimation {
Anim {
duration: 0
from: 0
property: "opacity"
to: 0
}
PauseAnimation {
duration: Appearance.anim.durations.expressiveEffects
}
ParallelAnimation {
Anim {
duration: Appearance.anim.durations.expressiveFastSpatial
from: 0
property: "opacity"
to: 1
}
Anim {
duration: Appearance.anim.durations.expressiveFastSpatial
from: 50
property: "y"
to: 0
}
}
}
}
pushExit: Transition {
ParallelAnimation {
Anim {
duration: Appearance.anim.durations.expressiveFastSpatial
from: 1
property: "opacity"
to: 0
}
Anim {
duration: Appearance.anim.durations.expressiveFastSpatial
from: 0
property: "y"
to: -50
}
}
}
}
}
borderBottom: Appearance.padding.normal
borderLeft: navPane.width + navPane.anchors.margins * 2
borderRight: Appearance.padding.normal
borderTop: Appearance.padding.normal
group: blobGroup
opacity: root.blobColor.a
radius: Appearance.rounding.large
}
Component {
id: general
NavPane {
id: navPane
Cat.General {
}
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.margins: Appearance.padding.large
anchors.top: parent.top
sState: root.sState
width: Math.min(600, Math.round(root.width / 3))
}
Component {
id: background
Cat.Background {
screen: root.screen
}
Pages {
anchors.bottom: parent.bottom
anchors.left: navPane.right
anchors.leftMargin: navPane.anchors.margins + anchors.margins
anchors.margins: Appearance.padding.extraLarge
anchors.right: parent.right
anchors.top: parent.top
sState: root.sState
}
Component {
id: appearance
Cat.Appearance {
}
}
Component {
id: bar
Cat.Bar {
}
}
Component {
id: lockscreen
Cat.Lockscreen {
}
}
Component {
id: services
Cat.Services {
}
}
Component {
id: notifications
Cat.Notifications {
}
}
Component {
id: sidebar
Cat.Sidebar {
}
}
Component {
id: utilities
Cat.Utilities {
}
}
Component {
id: dashboard
Cat.Dashboard {
}
}
Component {
id: osd
Cat.Osd {
}
}
Component {
id: launcher
Cat.Launcher {
}
}
Component {
id: screenshot
Cat.Screenshot {
}
}
Component {
id: updates
Cat.SystemUpdates {
}
PopupOverlay {
anchors.fill: parent
}
}
-660
View File
@@ -1,660 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Config
import qs.Components
import qs.Helpers
Item {
id: root
readonly property string endTime: {
var d = new Date(0, 0, 0, 0, 0, 0, 0);
d.setMinutes(object[settings[2]]);
return Qt.formatTime(d, "hh:mm AP");
}
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name
required property var object
required property list<string> settings
property bool shouldBeActive: true
readonly property string startTime: {
var d = new Date(0, 0, 0, 0, 0, 0, 0);
d.setMinutes(object[settings[1]]);
return Qt.formatTime(d, "hh:mm AP");
}
function commitChoice(choice: int, setting: string): void {
root.object[setting] = choice;
Config.save();
Hyprsunset.checkStartup();
}
function convertHour(timeValue: int): int {
return Math.floor(timeValue / 60);
}
function convertMinute(timeValue: int): int {
return timeValue % 60;
}
function convertToMinutes(hour: int, minute: int): int {
return hour * 60 + minute;
}
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? row.implicitHeight + Appearance.padding.smaller * 2 : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: true
CustomText {
id: text
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: root.name
}
CustomText {
Layout.alignment: Qt.AlignLeft
Layout.preferredWidth: Math.min(contentWidth, optionLayout.x - Appearance.spacing.normal)
color: DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.normal
text: qsTr("Hyprsunset will turn on at %1, and turn off at %2.").arg(root.startTime).arg(root.endTime)
wrapMode: Text.WordWrap
}
}
ColumnLayout {
id: optionLayout
Layout.fillHeight: true
Layout.fillWidth: true
RowLayout {
CustomText {
Layout.preferredWidth: spacer.x + spacer.width
text: qsTr("Start")
}
CustomText {
Layout.preferredWidth: endMinuteRect.width + endHourRect.width
text: qsTr("End")
}
CustomText {
Layout.alignment: Qt.AlignLeft | Qt.AlignHCenter
text: qsTr("Enabled: ")
}
CustomSwitch {
id: enabledSwitch
Layout.alignment: Qt.AlignRight | Qt.AlignHCenter
checked: root.object[root.settings[0]]
onToggled: {
root.object[root.settings[0]] = checked;
Config.save();
}
}
}
RowLayout {
Layout.fillHeight: true
CustomRect {
id: startHourRect
Layout.preferredHeight: 72
Layout.preferredWidth: 96
color: startHourField.focus ? DynamicColors.palette.m3onPrimaryContainer : DynamicColors.palette.m3surfaceContainerHighest
implicitHeight: 72
implicitWidth: 96
radius: Appearance.rounding.small
CustomRect {
anchors.fill: parent
border.color: startHourField.focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3surfaceContainerHighest
border.width: startHourField.focus ? 2 : 0
radius: parent.radius - border.width
Behavior on border.width {
Anim {
}
}
}
CustomTextField {
id: startHourField
function setConfigText(setting: string): string {
var val = root.convertHour(root.object[setting]);
if (val === 0) {
return "00";
}
return String(val);
}
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
clip: true
color: focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3onSurface
cursorHeight: height - Appearance.padding.normal * 2
font.family: "Roboto"
font.letterSpacing: -0.25
font.pixelSize: 56
font.weight: 400
horizontalAlignment: TextInput.AlignHCenter
text: setConfigText(root.settings[1])
verticalAlignment: TextInput.AlignVCenter
Keys.onPressed: event => {
if (event.key === Qt.Key_Backspace) {
event.accepted = true;
if (startHourField.text.length >= 2) {
startHourField.text = "0" + startHourField.text[0];
} else if (startHourField.text.length === 1) {
startHourField.text = "0";
}
return;
} else if (event.key === Qt.Key_Escape) {
event.accepted = true;
startHourField.text = setConfigText(root.settings[1]);
startHourField.focus = false;
} else if (event.key === Qt.Key_Return) {
startHourField.focus = false;
return;
} else if (event.key === Qt.Key_Tab) {
startMinuteField.focus = true;
} else if (event.key === Qt.Key_Backtab) {
endMinuteField.focus = true;
}
if (event.text.length === 1 && event.text >= "0" && event.text <= "9") {
event.accepted = true;
var digit = event.text;
var textLen = startHourField.text.length;
if (textLen >= 2 && startHourField.text[0] !== '0') {
return;
}
var val = 0;
if (textLen === 0) {
val = parseInt(digit);
} else if (textLen === 1) {
val = parseInt(startHourField.text + digit);
} else {
val = parseInt(startHourField.text[1] + digit);
}
val = Math.max(0, Math.min(23, val));
if (textLen >= 2 && val < 10) {
startHourField.text = "0" + val;
} else {
startHourField.text = val.toString();
}
}
event.accepted = true;
}
onCursorPositionChanged: cursorPosition = 2
onEditingFinished: {
root.commitChoice(root.convertToMinutes(parseInt(startHourField.text), parseInt(startMinuteField.text)), root.settings[1]);
}
onTextEdited: {
if (startHourField.text === "")
return;
var val = parseInt(startHourField.text);
if (isNaN(val))
return;
val = Math.max(0, Math.min(23, val));
var newText = val.toString();
if (newText !== startHourField.text)
startHourField.text = newText;
}
}
}
CustomText {
id: startSeparator
font.pointSize: Appearance.font.size.extraLarge
text: ":"
}
CustomRect {
id: startMinuteRect
Layout.preferredHeight: 72
Layout.preferredWidth: 96
color: startMinuteField.focus ? DynamicColors.palette.m3onPrimaryContainer : DynamicColors.palette.m3surfaceContainerHighest
implicitHeight: 72
implicitWidth: 96
radius: Appearance.rounding.small
CustomRect {
anchors.fill: parent
border.color: startMinuteField.focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3surfaceContainerHighest
border.width: startMinuteField.focus ? 2 : 0
radius: parent.radius - border.width
Behavior on border.width {
Anim {
}
}
}
CustomTextField {
id: startMinuteField
function setConfigText(setting: string): string {
var val = root.convertMinute(root.object[setting]);
if (val === 0) {
return "00";
}
return String(val);
}
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
clip: true
color: focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3onSurface
cursorHeight: height - Appearance.padding.normal * 2
font.family: "Roboto"
font.letterSpacing: -0.25
font.pixelSize: 56
font.weight: 400
horizontalAlignment: TextInput.AlignHCenter
text: setConfigText(root.settings[1])
verticalAlignment: TextInput.AlignVCenter
Keys.onPressed: event => {
if (event.key === Qt.Key_Backspace) {
event.accepted = true;
if (startMinuteField.text.length >= 2) {
startMinuteField.text = "0" + startMinuteField.text[0];
} else if (startMinuteField.text.length === 1) {
startMinuteField.text = "0";
}
return;
} else if (event.key === Qt.Key_Escape) {
event.accepted = true;
startMinuteField.text = setConfigText(root.settings[1]);
startMinuteField.focus = false;
} else if (event.key === Qt.Key_Return) {
startMinuteField.focus = false;
return;
} else if (event.key === Qt.Key_Tab) {
endHourField.focus = true;
} else if (event.key === Qt.Key_Backtab) {
startHourField.focus = true;
}
if (event.text.length === 1 && event.text >= "0" && event.text <= "9") {
event.accepted = true;
var digit = event.text;
var textLen = startMinuteField.text.length;
if (textLen >= 2 && startMinuteField.text[0] !== '0') {
return;
}
var val = 0;
if (textLen === 0) {
val = parseInt(digit);
} else if (textLen === 1) {
val = parseInt(startMinuteField.text + digit);
} else {
val = parseInt(startMinuteField.text[1] + digit);
}
val = Math.max(0, Math.min(59, val));
if (textLen >= 2 && val < 10) {
startMinuteField.text = "0" + val;
} else {
startMinuteField.text = val.toString();
}
}
event.accepted = true;
}
onCursorPositionChanged: cursorPosition = 2
onEditingFinished: {
root.commitChoice(root.convertToMinutes(parseInt(startHourField.text), parseInt(startMinuteField.text)), root.settings[1]);
}
onTextEdited: {
if (startMinuteField.text === "")
return;
var val = parseInt(startMinuteField.text);
if (isNaN(val))
return;
val = Math.max(0, Math.min(23, val));
var newText = val.toString();
if (newText !== startMinuteField.text)
startMinuteField.text = newText;
}
}
}
Item {
id: spacer
Layout.preferredWidth: Appearance.spacing.large
}
CustomRect {
id: endHourRect
Layout.preferredHeight: 72
Layout.preferredWidth: 96
color: endHourField.focus ? DynamicColors.palette.m3onPrimaryContainer : DynamicColors.palette.m3surfaceContainerHighest
implicitHeight: 72
implicitWidth: 96
radius: Appearance.rounding.small
CustomRect {
anchors.fill: parent
border.color: endHourField.focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3surfaceContainerHighest
border.width: endHourField.focus ? 2 : 0
radius: parent.radius - border.width
Behavior on border.width {
Anim {
}
}
}
CustomTextField {
id: endHourField
function setConfigText(setting: string): string {
var val = root.convertHour(root.object[setting]);
if (val === 0) {
return "00";
}
return String(val);
}
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
clip: true
color: focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3onSurface
cursorHeight: height - Appearance.padding.normal * 2
font.family: "Roboto"
font.letterSpacing: -0.25
font.pixelSize: 56
font.weight: 400
horizontalAlignment: TextInput.AlignHCenter
text: setConfigText(root.settings[2])
verticalAlignment: TextInput.AlignVCenter
Keys.onPressed: event => {
if (event.key === Qt.Key_Backspace) {
event.accepted = true;
if (endHourField.text.length >= 2) {
endHourField.text = "0" + endHourField.text[0];
} else if (endHourField.text.length === 1) {
endHourField.text = "0";
}
return;
} else if (event.key === Qt.Key_Escape) {
event.accepted = true;
endHourField.text = setConfigText(root.settings[2]);
endHourField.focus = false;
} else if (event.key === Qt.Key_Return) {
endHourField.focus = false;
return;
} else if (event.key === Qt.Key_Tab) {
endMinuteField.focus = true;
} else if (event.key === Qt.Key_Backtab) {
startMinuteField.focus = true;
}
if (event.text.length === 1 && event.text >= "0" && event.text <= "9") {
event.accepted = true;
var digit = event.text;
var textLen = endHourField.text.length;
if (textLen >= 2 && endHourField.text[0] !== '0') {
return;
}
var val = 0;
if (textLen === 0) {
val = parseInt(digit);
} else if (textLen === 1) {
val = parseInt(endHourField.text + digit);
} else {
val = parseInt(endHourField.text[1] + digit);
}
val = Math.max(0, Math.min(23, val));
if (textLen >= 2 && val < 10) {
endHourField.text = "0" + val;
} else {
endHourField.text = val.toString();
}
}
event.accepted = true;
}
onCursorPositionChanged: cursorPosition = 2
onEditingFinished: {
root.commitChoice(root.convertToMinutes(parseInt(endHourField.text), parseInt(endMinuteField.text)), root.settings[2]);
}
onTextEdited: {
if (endHourField.text === "")
return;
var val = parseInt(endHourField.text);
if (isNaN(val))
return;
val = Math.max(0, Math.min(23, val));
var newText = val.toString();
if (newText !== endHourField.text)
endHourField.text = newText;
}
}
}
CustomText {
id: endSeparator
font.pointSize: Appearance.font.size.extraLarge
text: ":"
}
CustomRect {
id: endMinuteRect
Layout.preferredHeight: 72
Layout.preferredWidth: 96
color: endMinuteField.focus ? DynamicColors.palette.m3onPrimaryContainer : DynamicColors.palette.m3surfaceContainerHighest
implicitHeight: 72
implicitWidth: 96
radius: Appearance.rounding.small
CustomRect {
anchors.fill: parent
border.color: endMinuteField.focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3surfaceContainerHighest
border.width: endMinuteField.focus ? 2 : 0
radius: parent.radius - border.width
Behavior on border.width {
Anim {
}
}
}
CustomTextField {
id: endMinuteField
function setConfigText(setting: string): string {
var val = root.convertMinute(root.object[setting]);
if (val === 0) {
return "00";
}
return String(val);
}
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
clip: true
color: focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3onSurface
cursorHeight: height - Appearance.padding.normal * 2
font.family: "Roboto"
font.letterSpacing: -0.25
font.pixelSize: 56
font.weight: 400
horizontalAlignment: TextInput.AlignHCenter
text: setConfigText(root.settings[2])
verticalAlignment: TextInput.AlignVCenter
Keys.onPressed: event => {
if (event.key === Qt.Key_Backspace) {
event.accepted = true;
if (endMinuteField.text.length >= 2) {
endMinuteField.text = "0" + endMinuteField.text[0];
} else if (endMinuteField.text.length === 1) {
endMinuteField.text = "0";
}
return;
} else if (event.key === Qt.Key_Escape) {
event.accepted = true;
endMinuteField.text = setConfigText(root.settings[2]);
endMinuteField.focus = false;
} else if (event.key === Qt.Key_Return) {
endMinuteField.focus = false;
return;
} else if (event.key === Qt.Key_Tab) {
startHourField.focus = true;
} else if (event.key === Qt.Key_Backtab) {
endHourField.focus = true;
}
if (event.text.length === 1 && event.text >= "0" && event.text <= "9") {
event.accepted = true;
var digit = event.text;
var textLen = endMinuteField.text.length;
if (textLen >= 2 && endMinuteField.text[0] !== '0') {
return;
}
var val = 0;
if (textLen === 0) {
val = parseInt(digit);
} else if (textLen === 1) {
val = parseInt(endMinuteField.text + digit);
} else {
val = parseInt(endMinuteField.text[1] + digit);
}
val = Math.max(0, Math.min(59, val));
if (textLen >= 2 && val < 10) {
endMinuteField.text = "0" + val;
} else {
endMinuteField.text = val.toString();
}
}
event.accepted = true;
}
onCursorPositionChanged: cursorPosition = 2
onEditingFinished: {
root.commitChoice(root.convertToMinutes(parseInt(endHourField.text), parseInt(endMinuteField.text)), root.settings[2]);
}
onTextEdited: {
if (endMinuteField.text === "")
return;
var val = parseInt(endMinuteField.text);
if (isNaN(val))
return;
val = Math.max(0, Math.min(23, val));
var newText = val.toString();
if (newText !== endMinuteField.text)
endMinuteField.text = newText;
}
}
}
}
RowLayout {
Layout.fillWidth: true
CustomText {
id: startHour
Layout.preferredWidth: startSeparator.x + startSeparator.width
text: qsTr("Hour")
}
CustomText {
id: startMinute
Layout.preferredWidth: spacer.x + spacer.width - x
text: qsTr("Minute")
}
CustomText {
Layout.preferredWidth: endSeparator.x + endSeparator.width - x
text: qsTr("Hour")
}
CustomText {
text: qsTr("Minute")
}
}
}
}
}
@@ -1,161 +0,0 @@
pragma ComponentBehavior: Bound
import Quickshell
import QtQuick
import QtQuick.Layouts
import qs.Config
import qs.Components
Item {
id: root
required property string name
required property var object
property alias row: row
required property string setting
property bool shouldBeActive: true
required property list<var> stringList
signal optionSet(option: string)
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? row.height : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
CustomText {
id: text
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: root.name
}
CustomClippingRect {
Layout.preferredHeight: 42 * 6 + Appearance.padding.normal * 2 + Appearance.spacing.small * 5
Layout.preferredWidth: 500
color: DynamicColors.tPalette.m3surfaceContainer
radius: (21 + Appearance.padding.normal) * Appearance.rounding.scale
CustomRect {
id: searchBox
anchors.left: parent.left
anchors.margins: Appearance.padding.normal
anchors.right: parent.right
anchors.top: parent.top
color: DynamicColors.tPalette.m3surfaceContainer
implicitHeight: 42
radius: Appearance.rounding.full
MaterialIcon {
id: searchIcon
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.leftMargin: Appearance.padding.large
anchors.top: parent.top
font.pointSize: Appearance.font.size.large
text: "search"
verticalAlignment: Text.AlignVCenter
}
CustomTextField {
id: textSearch
anchors.left: searchIcon.right
anchors.leftMargin: Appearance.spacing.small
anchors.right: parent.right
anchors.rightMargin: Appearance.spacing.normal
anchors.verticalCenter: parent.verticalCenter
placeholderText: "Search..."
}
}
CustomClippingRect {
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.margins: Appearance.padding.normal
anchors.right: parent.right
anchors.top: searchBox.bottom
bottomLeftRadius: 21
bottomRightRadius: 21
CustomListView {
anchors.fill: parent
clip: true
spacing: Appearance.spacing.small
delegate: CustomRect {
id: delegate
required property string modelData
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: 42
radius: Appearance.rounding.smallest
CustomText {
anchors.fill: parent
anchors.leftMargin: Appearance.padding.normal
text: modelData
verticalAlignment: Text.AlignVCenter
}
MaterialIcon {
anchors.fill: parent
anchors.rightMargin: Appearance.padding.normal
color: DynamicColors.palette.m3primary
font.pointSize: Appearance.font.size.large
horizontalAlignment: Text.AlignRight
text: "check_circle"
verticalAlignment: Text.AlignVCenter
visible: root.object[root.setting] === delegate.modelData
}
StateLayer {
onClicked: {
root.object[root.setting] = delegate.modelData;
root.optionSet(delegate.modelData);
Config.save();
}
}
}
model: ScriptModel {
values: {
const values = root.stringList;
const search = textSearch.text;
var regex = new RegExp(search, "i");
return values.filter(n => regex.test(n));
}
}
}
}
}
}
}
-31
View File
@@ -1,31 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
CustomRect {
id: root
property bool shouldBeActive: true
anchors.left: parent.left
anchors.right: parent.right
color: DynamicColors.tPalette.m3outlineVariant
implicitHeight: shouldBeActive ? 1 : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
}
@@ -1,282 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
import qs.Helpers
ColumnLayout {
id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name
required property var object
required property string setting
property bool shouldBeActive: true
function addAction() {
const list = [...root.object[root.setting]];
list.push({
name: "New Action",
icon: "bolt",
description: "",
command: [],
enabled: true,
dangerous: false
});
root.object[root.setting] = list;
Config.save();
}
function removeAction(index) {
const list = [...root.object[root.setting]];
list.splice(index, 1);
root.object[root.setting] = list;
Config.save();
}
function updateAction(index, key, value) {
const list = [...root.object[root.setting]];
const entry = list[index];
entry[key] = value;
list[index] = entry;
root.object[root.setting] = list;
Config.save();
}
anchors.left: parent.left
anchors.right: parent.right
height: shouldBeActive ? implicitHeight : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
spacing: Appearance.spacing.smaller
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
z: -1
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
CustomText {
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: root.name
}
Repeater {
model: [...root.object[root.setting]]
CustomRect {
required property int index
required property var modelData
Layout.fillWidth: true
Layout.preferredHeight: layout.implicitHeight + Appearance.padding.normal * 2
color: DynamicColors.tPalette.m3surfaceContainer
radius: Appearance.rounding.normal
ColumnLayout {
id: layout
anchors.left: parent.left
anchors.margins: Appearance.padding.normal
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Appearance.spacing.small
RowLayout {
Layout.fillWidth: true
CustomText {
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: modelData.name ?? qsTr("Action")
}
IconButton {
font.pointSize: Appearance.font.size.large
icon: "delete"
type: IconButton.Tonal
onClicked: root.removeAction(index)
}
}
Separator {
Layout.fillWidth: true
anchors.left: undefined
anchors.right: undefined
}
RowLayout {
Layout.fillWidth: true
CustomText {
Layout.fillWidth: true
text: qsTr("Name")
}
CustomRect {
Layout.preferredHeight: 33
Layout.preferredWidth: 350
color: DynamicColors.tPalette.m3surfaceContainerHigh
radius: Appearance.rounding.full
CustomTextField {
anchors.fill: parent
anchors.leftMargin: Appearance.padding.normal
anchors.rightMargin: Appearance.padding.normal
text: modelData.name ?? ""
onEditingFinished: root.updateAction(index, "name", text)
}
}
}
RowLayout {
Layout.fillWidth: true
CustomText {
Layout.fillWidth: true
text: qsTr("Icon")
}
CustomRect {
Layout.preferredHeight: 33
Layout.preferredWidth: 350
color: DynamicColors.tPalette.m3surfaceContainerHigh
radius: Appearance.rounding.full
CustomTextField {
anchors.fill: parent
anchors.leftMargin: Appearance.padding.normal
anchors.rightMargin: Appearance.padding.normal
text: modelData.icon ?? ""
onEditingFinished: root.updateAction(index, "icon", text)
}
}
}
RowLayout {
Layout.fillWidth: true
CustomText {
Layout.fillWidth: true
text: qsTr("Description")
}
CustomRect {
Layout.preferredHeight: 33
Layout.preferredWidth: 350
color: DynamicColors.tPalette.m3surfaceContainerHigh
radius: Appearance.rounding.full
CustomTextField {
anchors.fill: parent
anchors.leftMargin: Appearance.padding.normal
anchors.rightMargin: Appearance.padding.normal
text: modelData.description ?? ""
onEditingFinished: root.updateAction(index, "description", text)
}
}
}
StringListEditor {
Layout.fillWidth: true
addLabel: qsTr("Add command argument")
anchors.left: undefined
anchors.right: undefined
values: [...(modelData.command ?? [])]
onListEdited: function (values) {
root.updateAction(index, "command", values);
}
}
Separator {
Layout.fillWidth: true
anchors.left: undefined
anchors.right: undefined
}
RowLayout {
Layout.fillWidth: true
CustomText {
Layout.fillWidth: true
text: qsTr("Enabled")
}
CustomSwitch {
checked: modelData.enabled ?? true
onToggled: root.updateAction(index, "enabled", checked)
}
}
Separator {
Layout.fillWidth: true
anchors.left: undefined
anchors.right: undefined
}
RowLayout {
Layout.fillWidth: true
CustomText {
Layout.fillWidth: true
text: qsTr("Dangerous")
}
CustomSwitch {
checked: modelData.dangerous ?? false
onToggled: root.updateAction(index, "dangerous", checked)
}
}
}
}
}
RowLayout {
Layout.fillWidth: true
IconButton {
font.pointSize: Appearance.font.size.large
icon: "add"
onClicked: root.addAction()
}
CustomText {
Layout.fillWidth: true
text: qsTr("Add action")
}
}
}
@@ -1,203 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
import qs.Helpers
CustomRect {
id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name
required property var object
required property string setting
property bool shouldBeActive: true
function addAlias() {
const list = [...root.object[root.setting]];
list.push({
from: "",
to: ""
});
root.object[root.setting] = list;
Config.save();
}
function removeAlias(index) {
const list = [...root.object[root.setting]];
list.splice(index, 1);
root.object[root.setting] = list;
Config.save();
}
function updateAlias(index, key, value) {
const list = [...root.object[root.setting]];
const entry = [...list[index]];
entry[key] = value;
list[index] = entry;
root.object[root.setting] = list;
Config.save();
}
anchors.left: parent.left
anchors.right: parent.right
height: shouldBeActive ? layout.implicitHeight : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
z: -1
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
ColumnLayout {
id: layout
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Appearance.spacing.smaller
CustomText {
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: root.name
}
Repeater {
model: [...root.object[root.setting]]
Item {
required property int index
required property var modelData
Layout.fillWidth: true
Layout.preferredHeight: layout.implicitHeight + Appearance.padding.smaller * 2
CustomRect {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: -(Appearance.spacing.smaller / 2)
color: DynamicColors.tPalette.m3outlineVariant
implicitHeight: 1
visible: index !== 0
}
ColumnLayout {
id: layout
anchors.left: parent.left
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Appearance.spacing.small
RowLayout {
Layout.fillWidth: true
CustomText {
Layout.fillWidth: true
text: qsTr("From")
}
CustomRect {
Layout.preferredHeight: 33
Layout.preferredWidth: Math.max(Math.min(fromTextField.contentWidth + Appearance.padding.large * 2, 550), 50)
color: DynamicColors.tPalette.m3surfaceContainerHigh
radius: Appearance.rounding.full
CustomTextField {
id: fromTextField
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
implicitWidth: Math.min(contentWidth + Appearance.padding.normal * 2, 550)
text: modelData.from ?? ""
onEditingFinished: root.updateAlias(index, "from", text)
}
}
IconButton {
font.pointSize: Appearance.font.size.large
icon: "delete"
type: IconButton.Tonal
onClicked: root.removeAlias(index)
}
}
RowLayout {
Layout.fillWidth: true
CustomText {
Layout.fillWidth: true
text: qsTr("To")
}
CustomRect {
Layout.preferredHeight: 33
Layout.preferredWidth: Math.max(Math.min(toTextField.contentWidth + Appearance.padding.large * 2, 550), 50)
color: DynamicColors.tPalette.m3surfaceContainerHigh
radius: Appearance.rounding.full
CustomTextField {
id: toTextField
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
implicitWidth: Math.min(contentWidth + Appearance.padding.normal * 2, 550)
text: modelData.to ?? ""
onEditingFinished: root.updateAlias(index, "to", text)
}
}
}
}
}
}
RowLayout {
Layout.fillWidth: true
IconButton {
font.pointSize: Appearance.font.size.large
icon: "add"
onClicked: root.addAlias()
}
CustomText {
Layout.fillWidth: true
text: qsTr("Add alias")
}
}
}
}
@@ -1,241 +0,0 @@
pragma ComponentBehavior: Bound
import Quickshell
import QtQuick
import QtQuick.Layouts
import QtQml.Models
import qs.Components
import qs.Config
import qs.Helpers
Item {
id: root
property bool dragActive: false
property real dragHeight: 0
property real dragStartX: 0
property real dragStartY: 0
property real dragX: 0
property real dragY: 0
property var draggedModelData: null
property string draggedUid: ""
property bool dropAnimating: false
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name
required property var object
property var pendingCommitEntries: []
required property string setting
property bool shouldBeActive: true
property int uidCounter: 0
property var visualEntries: []
function ensureVisualEntries() {
if (!root.dragActive && !root.dropAnimating)
root.rebuildVisualEntries();
}
function iconForId(id) {
switch (id) {
case "workspaces":
return "dashboard";
case "audio":
return "volume_up";
case "media":
return "play_arrow";
case "resources":
return "monitoring";
case "updates":
return "system_update";
case "dash":
return "space_dashboard";
case "spacer":
return "horizontal_rule";
case "activeWindow":
return "web_asset";
case "tray":
return "widgets";
case "upower":
return "battery_full";
case "network":
return "wifi";
case "clock":
return "schedule";
case "notifBell":
return "notifications";
default:
return "drag_indicator";
}
}
function indexForUid(uid) {
for (let i = 0; i < root.visualEntries.length; i++) {
if (root.visualEntries[i].uid === uid)
return i;
}
return -1;
}
function labelForId(id) {
switch (id) {
case "workspaces":
return qsTr("Workspaces");
case "audio":
return qsTr("Audio");
case "media":
return qsTr("Media");
case "resources":
return qsTr("Resources");
case "updates":
return qsTr("Updates");
case "dash":
return qsTr("Dash");
case "spacer":
return qsTr("Spacer");
case "activeWindow":
return qsTr("Title");
case "tray":
return qsTr("Tray");
case "upower":
return qsTr("Power");
case "network":
return qsTr("Network");
case "clock":
return qsTr("Clock");
case "notifBell":
return qsTr("Notifs");
case "hyprsunset":
return qsTr("Night light");
default:
return id;
}
}
function rebuildVisualEntries() {
const entries = root.object[root.setting] ?? [];
const next = [];
for (let i = 0; i < entries.length; i++) {
const entry = entries[i];
let existing = null;
for (let j = 0; j < root.visualEntries.length; j++) {
if (root.visualEntries[j].entry === entry) {
existing = root.visualEntries[j];
break;
}
}
if (existing)
next.push(existing);
else
next.push({
uid: `entry-${root.uidCounter++}`,
entry
});
}
root.visualEntries = next;
}
function updateEntry(index, value) {
const list = [...root.object[root.setting]];
const entry = list[index];
entry.enabled = value;
list[index] = entry;
root.object[root.setting] = list;
Config.save();
}
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? layout.implicitHeight : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Component.onCompleted: root.rebuildVisualEntries()
CustomRect {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
z: -1
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout {
id: layout
anchors.fill: parent
// spacing: Appearance.spacing.smaller
DelegateModel {
id: visualModel
delegate: entryDelegate
model: ScriptModel {
objectProp: "uid"
values: root.visualEntries
}
}
Repeater {
delegate: entryDelegate
model: visualModel
}
}
Component {
id: entryDelegate
IconButton {
required property int index
required property var modelData
Layout.fillWidth: true
Layout.preferredWidth: implicitWidth + (stateLayer.pressed ? 18 : internalChecked ? 7 : 0)
checked: modelData.entry.enabled ?? true
font: Appearance.font.family.sans
// icon: root.iconForId(modelData.entry.id)
icon: root.labelForId(modelData.entry.id)
inactiveColor: DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHighest, 2)
isToggle: true
radius: stateLayer.pressed ? 6 / 2 : internalChecked ? 6 : 8
radiusAnim.duration: MaterialEasing.expressiveEffectsTime
radiusAnim.easing.bezierCurve: MaterialEasing.expressiveEffects
visible: !["spacer", "upower", "dash", "audio"].some(prefix => modelData.entry.id.startsWith(prefix))
Behavior on Layout.preferredWidth {
Anim {
duration: MaterialEasing.expressiveEffectsTime
easing.bezierCurve: MaterialEasing.expressiveEffects
}
}
onClicked: root.updateEntry(index, internalChecked)
}
}
}
@@ -1,214 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
import qs.Helpers
Item {
id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name
required property var object
required property list<string> settings
property bool shouldBeActive: true
function commitChoice(choice: int, setting: string): void {
root.object[setting] = choice;
Config.save();
}
function formattedValue(setting: string): string {
const value = root.object[setting];
if (value === null || value === undefined)
return "";
return String(value);
}
function hourToAmPm(hour) {
var h = Number(hour) % 24;
var d = new Date(2000, 0, 1, h, 0, 0);
return Qt.formatTime(d, "h AP");
}
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? row.implicitHeight + Appearance.padding.smaller * 2 : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: true
CustomText {
id: text
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: root.name
}
CustomText {
Layout.alignment: Qt.AlignLeft
color: DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.normal
text: qsTr("Hyprsunset will turn on at %1, and turn off at %2.").arg(root.hourToAmPm(root.object[root.settings[0]])).arg(root.hourToAmPm(root.object[root.settings[1]]))
}
}
ColumnLayout {
id: optionLayout
Layout.fillHeight: true
Layout.preferredWidth: 100
RowLayout {
Layout.preferredWidth: optionLayout.width
CustomText {
Layout.alignment: Qt.AlignLeft | Qt.AlignHCenter
Layout.fillWidth: true
text: qsTr("Enabled: ")
}
CustomSwitch {
id: enabledSwitch
Layout.alignment: Qt.AlignRight | Qt.AlignHCenter
checked: root.object[root.settings[2]]
onToggled: {
root.object[root.settings[2]] = checked;
Config.save();
}
}
}
RowLayout {
Layout.preferredWidth: optionLayout.width
z: setting2.expanded ? -1 : 1
CustomText {
Layout.alignment: Qt.AlignLeft | Qt.AlignHCenter
Layout.fillWidth: true
text: qsTr("Start: ")
}
SpinnerButton {
id: setting1
Layout.alignment: Qt.AlignRight | Qt.AlignHCenter
Layout.preferredHeight: Appearance.font.size.large + Appearance.padding.smaller * 2
Layout.preferredWidth: height * 2
currentIndex: root.object[root.settings[0]]
enabled: enabledSwitch.checked
text: root.formattedValue(root.settings[0])
menu.onItemSelected: item => {
root.commitChoice(item, root.settings[0]);
}
}
}
RowLayout {
Layout.preferredWidth: optionLayout.width
z: setting1.expanded ? -1 : 1
CustomText {
Layout.alignment: Qt.AlignLeft | Qt.AlignHCenter
Layout.fillWidth: true
text: qsTr("End: ")
}
SpinnerButton {
id: setting2
Layout.alignment: Qt.AlignRight | Qt.AlignHCenter
Layout.preferredHeight: Appearance.font.size.large + Appearance.padding.smaller * 2
Layout.preferredWidth: height * 2
currentIndex: root.object[root.settings[1]]
enabled: enabledSwitch.checked
text: root.formattedValue(root.settings[1])
menu.onItemSelected: item => {
root.commitChoice(item, root.settings[1]);
}
}
}
RowLayout {
Layout.preferredWidth: optionLayout.width
z: -2
CustomText {
Layout.alignment: Qt.AlignLeft | Qt.AlignHCenter
Layout.fillWidth: true
text: qsTr("Temp: ")
}
CustomRect {
id: rect
Layout.preferredHeight: 33
Layout.preferredWidth: Math.max(Math.min(textField.contentWidth + Appearance.padding.normal * 2, 200), 50)
color: DynamicColors.tPalette.m3surfaceContainerHigh
radius: Appearance.rounding.full
CustomTextField {
id: textField
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
implicitWidth: Math.min(contentWidth + Appearance.padding.normal * 2, 200)
text: root.formattedValue(root.settings[3])
onEditingFinished: {
root.object[root.settings[3]] = textField.text;
Config.save();
}
}
}
}
}
}
}
@@ -1,99 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
import qs.Helpers
Item {
id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name
required property var object
required property string setting
property bool shouldBeActive: true
function formattedValue(): string {
const value = root.object[root.setting];
if (value === null || value === undefined)
return "";
return String(value);
}
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? row.implicitHeight + Appearance.padding.smaller * 2 : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
CustomText {
id: text
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: root.name
}
CustomRect {
id: rect
Layout.preferredHeight: 33
Layout.preferredWidth: Math.max(Math.min(textField.contentWidth + Appearance.padding.large * 2, 550), 50)
color: DynamicColors.tPalette.m3surfaceContainerHigh
radius: Appearance.rounding.full
CustomTextField {
id: textField
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
implicitWidth: Math.min(contentWidth + Appearance.padding.normal * 2, 550)
text: root.formattedValue()
onEditingFinished: {
root.object[root.setting] = textField.text;
Config.save();
}
}
}
}
}
-297
View File
@@ -1,297 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
Item {
id: root
required property int index
required property var modelData
property bool shouldBeActive: true
signal addActiveActionRequested
signal deleteRequested(int index)
signal fieldEdited(string key, var value)
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? row.implicitHeight + Appearance.padding.smaller * 2 : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
CustomRect {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: -(Appearance.spacing.smaller / 2)
color: DynamicColors.tPalette.m3outlineVariant
implicitHeight: 1
visible: root.index !== 0
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Appearance.spacing.large
Item {
id: nameCell
property string draftName: ""
property bool editing: false
function beginEdit() {
draftName = root.modelData.name ?? "";
editing = true;
nameEditor.forceActiveFocus();
}
function cancelEdit() {
draftName = root.modelData.name ?? "";
editing = false;
}
function commitEdit() {
editing = false;
if (draftName !== (root.modelData.name ?? "")) {
root.fieldEdited("name", draftName);
}
}
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.fillHeight: true
Layout.preferredWidth: root.width / 2
HoverHandler {
id: nameHover
}
HoverIconButton {
id: editButton
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
font.pointSize: Appearance.font.size.large
icon: "edit"
shouldBeVisible: nameHover.hovered && !nameCell.editing
onClicked: nameCell.beginEdit()
}
CustomText {
anchors.left: parent.left
anchors.leftMargin: nameHover.hovered ? editButton.width + Appearance.spacing.smaller * 2 : 0
anchors.right: deleteButton.left
anchors.rightMargin: Appearance.spacing.small
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight // enable if CustomText supports it
font.pointSize: Appearance.font.size.larger
text: root.modelData.name
visible: !nameCell.editing
Behavior on anchors.leftMargin {
Anim {
}
}
}
HoverIconButton {
id: deleteButton
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
font.pointSize: Appearance.font.size.large
icon: "delete"
shouldBeVisible: nameHover.hovered && !nameCell.editing
onClicked: root.deleteRequested(root.index)
}
CustomRect {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
color: DynamicColors.tPalette.m3surface
implicitHeight: nameEditor.implicitHeight + (Appearance.padding.normal * 2)
implicitWidth: Math.min(nameEditor.contentWidth + (Appearance.padding.normal * 2), parent.width - Appearance.padding.normal)
radius: Appearance.rounding.small
visible: nameCell.editing
CustomTextField {
id: nameEditor
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
implicitWidth: Math.min(contentWidth + Appearance.padding.normal * 2, nameCell.width - Appearance.padding.normal)
text: nameCell.draftName
Keys.onEscapePressed: {
nameCell.cancelEdit();
}
onEditingFinished: {
nameCell.commitEdit();
}
onTextEdited: {
nameCell.draftName = nameEditor.text;
}
}
}
}
VSeparator {
}
ColumnLayout {
id: cLayout
Layout.fillWidth: true
RowLayout {
Layout.fillWidth: true
CustomText {
Layout.fillWidth: true
text: qsTr("Timeout")
}
CustomRect {
Layout.preferredHeight: 33
Layout.preferredWidth: Math.max(Math.min(timeField.contentWidth + Appearance.padding.normal * 3, 200), 50)
color: DynamicColors.tPalette.m3surface
radius: Appearance.rounding.small
CustomTextField {
id: timeField
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
text: String(root.modelData.timeout ?? "")
onEditingFinished: {
root.fieldEdited("timeout", Number(text));
}
}
}
}
Separator {
Layout.fillWidth: true
anchors.left: undefined
anchors.right: undefined
}
RowLayout {
Layout.fillWidth: true
CustomText {
Layout.fillWidth: true
text: qsTr("Idle Action")
}
CustomRect {
Layout.preferredHeight: 33
Layout.preferredWidth: Math.max(Math.min(idleField.contentWidth + Appearance.padding.normal * 3, 200), 50)
color: DynamicColors.tPalette.m3surface
radius: Appearance.rounding.small
CustomTextField {
id: idleField
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
text: root.modelData.idleAction ?? ""
onEditingFinished: {
root.fieldEdited("idleAction", text);
}
}
}
}
Separator {
Layout.fillWidth: true
anchors.left: undefined
anchors.right: undefined
}
Item {
Layout.fillWidth: true
implicitHeight: activeActionRow.visible ? activeActionRow.implicitHeight : addButtonRow.implicitHeight
RowLayout {
id: activeActionRow
anchors.left: parent.left
anchors.right: parent.right
visible: root.modelData.activeAction !== undefined
CustomText {
Layout.fillWidth: true
text: qsTr("Active Action")
}
CustomRect {
Layout.preferredHeight: 33
Layout.preferredWidth: Math.max(Math.min(actionField.contentWidth + Appearance.padding.normal * 3, 200), 50)
color: DynamicColors.tPalette.m3surface
radius: Appearance.rounding.small
CustomTextField {
id: actionField
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
text: root.modelData.activeAction ?? ""
onEditingFinished: {
root.fieldEdited("activeAction", text);
}
}
}
}
RowLayout {
id: addButtonRow
anchors.left: parent.left
anchors.right: parent.right
visible: root.modelData.activeAction === undefined
IconButton {
id: button
Layout.alignment: Qt.AlignLeft
font.pointSize: Appearance.font.size.large
icon: "add"
onClicked: root.addActiveActionRequested()
}
CustomText {
Layout.alignment: Qt.AlignLeft
text: qsTr("Add active action")
}
}
}
}
}
}
@@ -1,163 +0,0 @@
pragma ComponentBehavior: Bound
import Quickshell
import QtQuick
import QtQuick.Layouts
import qs.Config
import qs.Components
Item {
id: root
required property string name
required property var object
property alias row: row
required property string setting
property bool shouldBeActive: true
required property list<var> stringList
signal optionSet
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? row.height : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
CustomText {
id: text
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: root.name
}
CustomClippingRect {
id: fontArea
Layout.preferredHeight: 42 * 6 + Appearance.padding.normal * 2 + Appearance.spacing.small * 5
Layout.preferredWidth: 500
color: DynamicColors.tPalette.m3surfaceContainer
radius: (21 + Appearance.padding.normal) * Appearance.rounding.scale
CustomRect {
id: searchBox
anchors.left: parent.left
anchors.margins: Appearance.padding.normal
anchors.right: parent.right
anchors.top: parent.top
color: DynamicColors.tPalette.m3surfaceContainer
implicitHeight: 42
radius: Appearance.rounding.full
MaterialIcon {
id: searchIcon
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.leftMargin: Appearance.padding.large
anchors.top: parent.top
font.pointSize: Appearance.font.size.large
text: "search"
verticalAlignment: Text.AlignVCenter
}
CustomTextField {
id: fontSearch
anchors.left: searchIcon.right
anchors.leftMargin: Appearance.spacing.small
anchors.right: parent.right
anchors.rightMargin: Appearance.spacing.normal
anchors.verticalCenter: parent.verticalCenter
placeholderText: "Search..."
}
}
CustomClippingRect {
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.margins: Appearance.padding.normal
anchors.right: parent.right
anchors.top: searchBox.bottom
bottomLeftRadius: 21
bottomRightRadius: 21
CustomListView {
anchors.fill: parent
clip: true
spacing: Appearance.spacing.small
delegate: CustomRect {
id: fontDelegate
required property string modelData
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: 42
radius: Appearance.rounding.smallest
CustomText {
anchors.fill: parent
anchors.leftMargin: Appearance.padding.normal
text: modelData
verticalAlignment: Text.AlignVCenter
}
MaterialIcon {
anchors.fill: parent
anchors.rightMargin: Appearance.padding.normal
color: DynamicColors.palette.m3primary
font.pointSize: Appearance.font.size.large
horizontalAlignment: Text.AlignRight
text: "check_circle"
verticalAlignment: Text.AlignVCenter
visible: root.object[root.setting] === fontDelegate.modelData
}
StateLayer {
onClicked: {
root.object[root.setting] = fontDelegate.modelData;
root.optionSet();
Config.save();
}
}
}
model: ScriptModel {
values: {
const values = root.stringList;
const search = fontSearch.text;
var regex = new RegExp(search, "i");
return values.filter(n => regex.test(n));
}
}
}
}
}
}
}
@@ -1,70 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
import qs.Helpers
Item {
id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name
property bool shouldBeActive: true
required property string value
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? row.implicitHeight + Appearance.padding.smaller * 2 : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
CustomText {
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: root.name
}
CustomText {
color: DynamicColors.palette.m3onSurfaceVariant
font.family: Appearance.font.family.mono
font.pointSize: Appearance.font.size.normal
text: root.value
}
}
}
@@ -1,81 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
import qs.Helpers
Item {
id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
property real max: Infinity
property real min: -Infinity
required property string name
required property var object
required property string setting
property bool shouldBeActive: true
property real step: 1
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? row.implicitHeight + Appearance.padding.smaller * 2 : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
CustomText {
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: root.name
}
CustomSpinBox {
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
max: root.max
min: root.min
step: root.step
value: Number(root.object[root.setting] ?? 0)
onValueModified: function (value) {
root.object[root.setting] = value;
Config.save();
}
}
}
}
@@ -1,180 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
import qs.Helpers
Item {
id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name
required property var object
required property list<string> settings
property bool shouldBeActive: true
function commitChoice(choice: int, setting: string): void {
root.object[setting] = choice;
Config.save();
}
function formattedValue(setting: string): string {
const value = root.object[setting];
if (value === null || value === undefined)
return "";
return String(value);
}
function hourToAmPm(hour) {
var h = Number(hour) % 24;
var d = new Date(2000, 0, 1, h, 0, 0);
return Qt.formatTime(d, "h AP");
}
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? row.implicitHeight + Appearance.padding.smaller * 2 : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: true
CustomText {
id: text
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: root.name
}
CustomText {
Layout.alignment: Qt.AlignLeft
color: DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.normal
text: qsTr("Dark mode will turn on at %1, and turn off at %2.").arg(root.hourToAmPm(root.object[root.settings[0]])).arg(root.hourToAmPm(root.object[root.settings[1]]))
}
}
ColumnLayout {
id: optionLayout
Layout.fillHeight: true
Layout.preferredWidth: 100
RowLayout {
Layout.preferredWidth: optionLayout.width
CustomText {
Layout.alignment: Qt.AlignLeft | Qt.AlignHCenter
Layout.fillWidth: true
text: qsTr("Enabled: ")
}
CustomSwitch {
id: enabledSwitch
Layout.alignment: Qt.AlignRight | Qt.AlignHCenter
checked: root.object[root.settings[2]]
onToggled: {
root.object[root.settings[2]] = checked;
Config.save();
}
}
}
RowLayout {
Layout.preferredWidth: optionLayout.width
z: setting2.expanded ? -1 : 1
CustomText {
Layout.alignment: Qt.AlignLeft | Qt.AlignHCenter
Layout.fillWidth: true
text: qsTr("Start: ")
}
SpinnerButton {
id: setting1
Layout.alignment: Qt.AlignRight | Qt.AlignHCenter
Layout.preferredHeight: Appearance.font.size.large + Appearance.padding.smaller * 2
Layout.preferredWidth: height * 2
currentIndex: root.object[root.settings[0]]
enabled: enabledSwitch.checked
text: root.formattedValue(root.settings[0])
menu.onItemSelected: item => {
root.commitChoice(item, root.settings[0]);
}
}
}
RowLayout {
Layout.preferredWidth: optionLayout.width
z: setting1.expanded ? -1 : 1
CustomText {
Layout.alignment: Qt.AlignLeft | Qt.AlignHCenter
Layout.fillWidth: true
text: qsTr("End: ")
}
SpinnerButton {
id: setting2
Layout.alignment: Qt.AlignRight | Qt.AlignHCenter
Layout.preferredHeight: Appearance.font.size.large + Appearance.padding.smaller * 2
Layout.preferredWidth: height * 2
currentIndex: root.object[root.settings[1]]
enabled: enabledSwitch.checked
text: root.formattedValue(root.settings[1])
menu.onItemSelected: item => {
root.commitChoice(item, root.settings[1]);
}
}
}
}
}
}
@@ -1,78 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
import qs.Helpers
Item {
id: root
property string addLabel: qsTr("Add entry")
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name
required property var object
required property string setting
property bool shouldBeActive: true
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? layout.implicitHeight : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
ColumnLayout {
id: layout
anchors.left: parent.left
anchors.right: parent.right
spacing: Appearance.spacing.small
CustomText {
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: root.name
}
StringListEditor {
Layout.fillWidth: true
addLabel: root.addLabel
anchors.left: undefined
anchors.right: undefined
anchors.verticalCenter: undefined
values: [...(root.object[root.setting] ?? [])]
onListEdited: function (values) {
root.object[root.setting] = values;
Config.save();
}
}
}
}
@@ -1,79 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
import qs.Helpers
Item {
id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name
required property var object
required property string setting
property bool shouldBeActive: true
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? row.implicitHeight + Appearance.padding.smaller * 2 : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
CustomText {
id: text
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: root.name
}
CustomSwitch {
id: cswitch
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
checked: root.object[root.setting]
onToggled: {
root.object[root.setting] = checked;
Config.save();
}
}
}
}
@@ -1,25 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
CustomRect {
id: root
required property string name
property bool shouldBeActive: true
implicitHeight: 60
implicitWidth: 200
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
CustomText {
anchors.fill: parent
font.bold: true
font.pointSize: Appearance.font.size.large * 2
text: root.name
verticalAlignment: Text.AlignVCenter
}
}
@@ -1,83 +0,0 @@
import Quickshell
import QtQuick
import QtQuick.Layouts
import qs.Paths
import qs.Components
import qs.Config
import qs.Helpers
Item {
id: root
property alias button: iButton
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name
property bool shouldBeActive: true
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? row.implicitHeight + Appearance.padding.smaller * 2 : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
CustomText {
id: text
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: root.name
}
IconButton {
id: iButton
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
icon: "download"
onClicked: {
const lockBg = `${Paths.state}/lockscreen_bg.png`;
const scheme = `${Paths.state}/scheme.json`;
const face = `${Paths.home}/.face`;
const destination = "/etc/zshell-greeter/images";
Quickshell.execDetached(["pkexec", "sh", "-c", `mkdir -p ${destination}; cp ${lockBg} ${destination}; cp ${scheme} /etc/zshell-greeter; cp ${face} ${destination}`]);
}
}
}
}
@@ -1,76 +0,0 @@
import QtQuick
import QtQuick.Controls
import qs.Components
import qs.Config
import qs.Helpers
Item {
id: root
default property alias contentData: clayout.data
function scrollToSectionAndHighlight(sectionId: string, settingName: string): bool {
for (let i = 0; i < clayout.children.length; i++) {
const section = clayout.children[i];
if (section.sectionId === sectionId) {
const targetY = section.y - Appearance.padding.normal;
flickable.contentY = Math.max(0, Math.min(targetY, flickable.contentHeight - flickable.height));
SettingsHighlight.highlight(settingName);
return true;
}
}
return false;
}
CustomFlickable {
id: flickable
anchors.fill: parent
// for future:
// anchors.leftMargin: Appearance.padding.extraLarge
// anchors.rightMargin: Appearance.padding.extraLarge
clip: true
contentHeight: clayout.implicitHeight + clayout.anchors.margins * 2
CustomScrollBar.vertical: CustomScrollBar {
flickable: flickable
}
TapHandler {
acceptedButtons: Qt.LeftButton
onTapped: function (eventPoint) {
const menu = SettingsDropdowns.activeMenu;
if (!menu)
return;
const p = eventPoint.scenePosition;
if (SettingsDropdowns.hit(SettingsDropdowns.activeTrigger, p))
return;
if (SettingsDropdowns.hit(menu, p))
return;
SettingsDropdowns.closeActive();
}
}
Column {
id: clayout
anchors.left: parent.left
anchors.margins: Appearance.padding.extraSmall
anchors.right: parent.right
anchors.top: parent.top
spacing: Appearance.spacing.small
// move: Transition {
// Anim {
// properties: "y"
// }
// }
}
}
}
@@ -1,48 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
CustomRect {
id: root
default property alias contentData: layout.data
property real contentPadding: Appearance.padding.large
property string sectionId: ""
anchors.left: parent.left
anchors.right: parent.right
color: DynamicColors.tPalette.m3surfaceContainer
implicitHeight: layout.height + contentPadding * 2
radius: Appearance.rounding.normal - Appearance.padding.extraSmall
Behavior on implicitHeight {
Anim {
}
}
Behavior on y {
Anim {
}
}
Column {
id: layout
anchors.left: parent.left
anchors.margins: root.contentPadding
anchors.right: parent.right
anchors.top: parent.top
// anchors.verticalCenter: parent.verticalCenter
spacing: Appearance.spacing.normal
Behavior on height {
Anim {
}
}
move: Transition {
Anim {
properties: "y"
}
}
}
}
@@ -1,63 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Helpers
import qs.Config
CustomRect {
id: root
property alias currentIndex: menu.currentIndex
property bool enabled
property alias expanded: menu.expanded
property alias label: label
property alias menu: menu
property bool shouldBeActive: true
property alias text: label.text
color: enabled ? DynamicColors.palette.m3primary : DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHigh, 2)
opacity: shouldBeActive ? 1 : 0
radius: Appearance.rounding.full
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
z: expanded ? 100 : 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
CustomText {
id: label
anchors.centerIn: parent
color: root.enabled ? DynamicColors.palette.m3onPrimary : DynamicColors.layer(DynamicColors.palette.m3onSurface, 2)
font.pointSize: Appearance.font.size.large
}
StateLayer {
visible: root.enabled
onClicked: {
SettingsDropdowns.toggle(menu, root);
}
}
PathViewMenu {
id: menu
anchors.centerIn: parent
from: 1
implicitWidth: root.width
itemHeight: root.height
to: 24
}
}
@@ -1,126 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
ColumnLayout {
id: root
property string addLabel: qsTr("Add entry")
property bool shouldBeActive: true
property var values: []
signal listEdited(var values)
function addValue() {
const list = [...root.values];
list.push("");
root.listEdited(list);
}
function removeValue(index) {
const list = [...root.values];
list.splice(index, 1);
root.listEdited(list);
}
function updateValue(index, value) {
const list = [...root.values];
list[index] = value;
root.listEdited(list);
}
anchors.left: parent.left
anchors.right: parent.right
height: shouldBeActive ? implicitHeight : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
spacing: Appearance.spacing.smaller
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Repeater {
model: [...root.values]
Item {
required property int index
required property var modelData
Layout.fillWidth: true
Layout.preferredHeight: row.implicitHeight + Appearance.padding.smaller * 2
CustomRect {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: -(Appearance.spacing.smaller / 2)
color: DynamicColors.tPalette.m3outlineVariant
implicitHeight: 1
visible: index !== 0
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
CustomRect {
Layout.fillWidth: true
Layout.preferredHeight: 33
color: DynamicColors.tPalette.m3surfaceContainerHigh
radius: Appearance.rounding.full
CustomTextField {
anchors.fill: parent
anchors.leftMargin: Appearance.padding.normal
anchors.rightMargin: Appearance.padding.normal
text: String(modelData ?? "")
onEditingFinished: root.updateValue(index, text)
}
}
IconButton {
font.pointSize: Appearance.font.size.large
icon: "delete"
type: IconButton.Tonal
onClicked: root.removeValue(index)
}
}
}
}
RowLayout {
Layout.fillWidth: true
IconButton {
font.pointSize: Appearance.font.size.large
icon: "add"
onClicked: root.addValue()
}
CustomText {
Layout.fillWidth: true
text: root.addLabel
}
}
}
-661
View File
@@ -1,661 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Config
import qs.Components
import qs.Helpers
Item {
id: root
readonly property string endTime: {
var d = new Date(0, 0, 0, 0, 0, 0, 0);
d.setMinutes(object[settings[2]]);
return Qt.formatTime(d, "hh:mm AP");
}
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name
required property var object
required property list<string> settings
property bool shouldBeActive: true
readonly property string startTime: {
var d = new Date(0, 0, 0, 0, 0, 0, 0);
d.setMinutes(object[settings[1]]);
return Qt.formatTime(d, "hh:mm AP");
}
function commitChoice(choice: int, setting: string): void {
root.object[setting] = choice;
Config.save();
ModeScheduler.checkStartup();
}
function convertHour(timeValue: int): int {
return Math.floor(timeValue / 60);
}
function convertMinute(timeValue: int): int {
return timeValue % 60;
}
function convertToMinutes(hour: int, minute: int): int {
return hour * 60 + minute;
}
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? row.implicitHeight + Appearance.padding.smaller * 2 : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: true
CustomText {
id: text
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger
text: root.name
}
CustomText {
Layout.alignment: Qt.AlignLeft
Layout.preferredWidth: Math.min(contentWidth, optionLayout.x - Appearance.spacing.normal)
color: DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.normal
text: qsTr("Dark mode will turn on at %1, and turn off at %2.").arg(root.startTime).arg(root.endTime)
wrapMode: Text.WordWrap
}
}
ColumnLayout {
id: optionLayout
Layout.fillHeight: true
Layout.fillWidth: true
RowLayout {
CustomText {
Layout.preferredWidth: spacer.x + spacer.width
text: qsTr("Start")
}
CustomText {
Layout.preferredWidth: endMinuteRect.width + endHourRect.width
text: qsTr("End")
}
CustomText {
Layout.alignment: Qt.AlignLeft | Qt.AlignHCenter
text: qsTr("Enabled: ")
}
CustomSwitch {
id: enabledSwitch
Layout.alignment: Qt.AlignRight | Qt.AlignHCenter
checked: root.object[root.settings[0]]
onToggled: {
root.object[root.settings[0]] = checked;
Config.save();
ModeScheduler.checkStartup();
}
}
}
RowLayout {
Layout.fillHeight: true
CustomRect {
id: startHourRect
Layout.preferredHeight: 72
Layout.preferredWidth: 96
color: startHourField.focus ? DynamicColors.palette.m3onPrimaryContainer : DynamicColors.palette.m3surfaceContainerHighest
implicitHeight: 72
implicitWidth: 96
radius: Appearance.rounding.small
CustomRect {
anchors.fill: parent
border.color: startHourField.focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3surfaceContainerHighest
border.width: startHourField.focus ? 2 : 0
radius: parent.radius - border.width
Behavior on border.width {
Anim {
}
}
}
CustomTextField {
id: startHourField
function setConfigText(setting: string): string {
var val = root.convertHour(root.object[setting]);
if (val === 0) {
return "00";
}
return String(val);
}
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
clip: true
color: focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3onSurface
cursorHeight: height - Appearance.padding.normal * 2
font.family: "Roboto"
font.letterSpacing: -0.25
font.pixelSize: 56
font.weight: 400
horizontalAlignment: TextInput.AlignHCenter
text: setConfigText(root.settings[1])
verticalAlignment: TextInput.AlignVCenter
Keys.onPressed: event => {
if (event.key === Qt.Key_Backspace) {
event.accepted = true;
if (startHourField.text.length >= 2) {
startHourField.text = "0" + startHourField.text[0];
} else if (startHourField.text.length === 1) {
startHourField.text = "0";
}
return;
} else if (event.key === Qt.Key_Escape) {
event.accepted = true;
startHourField.text = setConfigText(root.settings[1]);
startHourField.focus = false;
} else if (event.key === Qt.Key_Return) {
startHourField.focus = false;
return;
} else if (event.key === Qt.Key_Tab) {
startMinuteField.focus = true;
} else if (event.key === Qt.Key_Backtab) {
endMinuteField.focus = true;
}
if (event.text.length === 1 && event.text >= "0" && event.text <= "9") {
event.accepted = true;
var digit = event.text;
var textLen = startHourField.text.length;
if (textLen >= 2 && startHourField.text[0] !== '0') {
return;
}
var val = 0;
if (textLen === 0) {
val = parseInt(digit);
} else if (textLen === 1) {
val = parseInt(startHourField.text + digit);
} else {
val = parseInt(startHourField.text[1] + digit);
}
val = Math.max(0, Math.min(23, val));
if (textLen >= 2 && val < 10) {
startHourField.text = "0" + val;
} else {
startHourField.text = val.toString();
}
}
event.accepted = true;
}
onCursorPositionChanged: cursorPosition = 2
onEditingFinished: {
root.commitChoice(root.convertToMinutes(parseInt(startHourField.text), parseInt(startMinuteField.text)), root.settings[1]);
}
onTextEdited: {
if (startHourField.text === "")
return;
var val = parseInt(startHourField.text);
if (isNaN(val))
return;
val = Math.max(0, Math.min(23, val));
var newText = val.toString();
if (newText !== startHourField.text)
startHourField.text = newText;
}
}
}
CustomText {
id: startSeparator
font.pointSize: Appearance.font.size.extraLarge
text: ":"
}
CustomRect {
id: startMinuteRect
Layout.preferredHeight: 72
Layout.preferredWidth: 96
color: startMinuteField.focus ? DynamicColors.palette.m3onPrimaryContainer : DynamicColors.palette.m3surfaceContainerHighest
implicitHeight: 72
implicitWidth: 96
radius: Appearance.rounding.small
CustomRect {
anchors.fill: parent
border.color: startMinuteField.focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3surfaceContainerHighest
border.width: startMinuteField.focus ? 2 : 0
radius: parent.radius - border.width
Behavior on border.width {
Anim {
}
}
}
CustomTextField {
id: startMinuteField
function setConfigText(setting: string): string {
var val = root.convertMinute(root.object[setting]);
if (val === 0) {
return "00";
}
return String(val);
}
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
clip: true
color: focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3onSurface
cursorHeight: height - Appearance.padding.normal * 2
font.family: "Roboto"
font.letterSpacing: -0.25
font.pixelSize: 56
font.weight: 400
horizontalAlignment: TextInput.AlignHCenter
text: setConfigText(root.settings[1])
verticalAlignment: TextInput.AlignVCenter
Keys.onPressed: event => {
if (event.key === Qt.Key_Backspace) {
event.accepted = true;
if (startMinuteField.text.length >= 2) {
startMinuteField.text = "0" + startMinuteField.text[0];
} else if (startMinuteField.text.length === 1) {
startMinuteField.text = "0";
}
return;
} else if (event.key === Qt.Key_Escape) {
event.accepted = true;
startMinuteField.text = setConfigText(root.settings[1]);
startMinuteField.focus = false;
} else if (event.key === Qt.Key_Return) {
startMinuteField.focus = false;
return;
} else if (event.key === Qt.Key_Tab) {
endHourField.focus = true;
} else if (event.key === Qt.Key_Backtab) {
startHourField.focus = true;
}
if (event.text.length === 1 && event.text >= "0" && event.text <= "9") {
event.accepted = true;
var digit = event.text;
var textLen = startMinuteField.text.length;
if (textLen >= 2 && startMinuteField.text[0] !== '0') {
return;
}
var val = 0;
if (textLen === 0) {
val = parseInt(digit);
} else if (textLen === 1) {
val = parseInt(startMinuteField.text + digit);
} else {
val = parseInt(startMinuteField.text[1] + digit);
}
val = Math.max(0, Math.min(59, val));
if (textLen >= 2 && val < 10) {
startMinuteField.text = "0" + val;
} else {
startMinuteField.text = val.toString();
}
}
event.accepted = true;
}
onCursorPositionChanged: cursorPosition = 2
onEditingFinished: {
root.commitChoice(root.convertToMinutes(parseInt(startHourField.text), parseInt(startMinuteField.text)), root.settings[1]);
}
onTextEdited: {
if (startMinuteField.text === "")
return;
var val = parseInt(startMinuteField.text);
if (isNaN(val))
return;
val = Math.max(0, Math.min(23, val));
var newText = val.toString();
if (newText !== startMinuteField.text)
startMinuteField.text = newText;
}
}
}
Item {
id: spacer
Layout.preferredWidth: Appearance.spacing.large
}
CustomRect {
id: endHourRect
Layout.preferredHeight: 72
Layout.preferredWidth: 96
color: endHourField.focus ? DynamicColors.palette.m3onPrimaryContainer : DynamicColors.palette.m3surfaceContainerHighest
implicitHeight: 72
implicitWidth: 96
radius: Appearance.rounding.small
CustomRect {
anchors.fill: parent
border.color: endHourField.focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3surfaceContainerHighest
border.width: endHourField.focus ? 2 : 0
radius: parent.radius - border.width
Behavior on border.width {
Anim {
}
}
}
CustomTextField {
id: endHourField
function setConfigText(setting: string): string {
var val = root.convertHour(root.object[setting]);
if (val === 0) {
return "00";
}
return String(val);
}
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
clip: true
color: focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3onSurface
cursorHeight: height - Appearance.padding.normal * 2
font.family: "Roboto"
font.letterSpacing: -0.25
font.pixelSize: 56
font.weight: 400
horizontalAlignment: TextInput.AlignHCenter
text: setConfigText(root.settings[2])
verticalAlignment: TextInput.AlignVCenter
Keys.onPressed: event => {
if (event.key === Qt.Key_Backspace) {
event.accepted = true;
if (endHourField.text.length >= 2) {
endHourField.text = "0" + endHourField.text[0];
} else if (endHourField.text.length === 1) {
endHourField.text = "0";
}
return;
} else if (event.key === Qt.Key_Escape) {
event.accepted = true;
endHourField.text = setConfigText(root.settings[2]);
endHourField.focus = false;
} else if (event.key === Qt.Key_Return) {
endHourField.focus = false;
return;
} else if (event.key === Qt.Key_Tab) {
endMinuteField.focus = true;
} else if (event.key === Qt.Key_Backtab) {
startMinuteField.focus = true;
}
if (event.text.length === 1 && event.text >= "0" && event.text <= "9") {
event.accepted = true;
var digit = event.text;
var textLen = endHourField.text.length;
if (textLen >= 2 && endHourField.text[0] !== '0') {
return;
}
var val = 0;
if (textLen === 0) {
val = parseInt(digit);
} else if (textLen === 1) {
val = parseInt(endHourField.text + digit);
} else {
val = parseInt(endHourField.text[1] + digit);
}
val = Math.max(0, Math.min(23, val));
if (textLen >= 2 && val < 10) {
endHourField.text = "0" + val;
} else {
endHourField.text = val.toString();
}
}
event.accepted = true;
}
onCursorPositionChanged: cursorPosition = 2
onEditingFinished: {
root.commitChoice(root.convertToMinutes(parseInt(endHourField.text), parseInt(endMinuteField.text)), root.settings[2]);
}
onTextEdited: {
if (endHourField.text === "")
return;
var val = parseInt(endHourField.text);
if (isNaN(val))
return;
val = Math.max(0, Math.min(23, val));
var newText = val.toString();
if (newText !== endHourField.text)
endHourField.text = newText;
}
}
}
CustomText {
id: endSeparator
font.pointSize: Appearance.font.size.extraLarge
text: ":"
}
CustomRect {
id: endMinuteRect
Layout.preferredHeight: 72
Layout.preferredWidth: 96
color: endMinuteField.focus ? DynamicColors.palette.m3onPrimaryContainer : DynamicColors.palette.m3surfaceContainerHighest
implicitHeight: 72
implicitWidth: 96
radius: Appearance.rounding.small
CustomRect {
anchors.fill: parent
border.color: endMinuteField.focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3surfaceContainerHighest
border.width: endMinuteField.focus ? 2 : 0
radius: parent.radius - border.width
Behavior on border.width {
Anim {
}
}
}
CustomTextField {
id: endMinuteField
function setConfigText(setting: string): string {
var val = root.convertMinute(root.object[setting]);
if (val === 0) {
return "00";
}
return String(val);
}
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
clip: true
color: focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3onSurface
cursorHeight: height - Appearance.padding.normal * 2
font.family: "Roboto"
font.letterSpacing: -0.25
font.pixelSize: 56
font.weight: 400
horizontalAlignment: TextInput.AlignHCenter
text: setConfigText(root.settings[2])
verticalAlignment: TextInput.AlignVCenter
Keys.onPressed: event => {
if (event.key === Qt.Key_Backspace) {
event.accepted = true;
if (endMinuteField.text.length >= 2) {
endMinuteField.text = "0" + endMinuteField.text[0];
} else if (endMinuteField.text.length === 1) {
endMinuteField.text = "0";
}
return;
} else if (event.key === Qt.Key_Escape) {
event.accepted = true;
endMinuteField.text = setConfigText(root.settings[2]);
endMinuteField.focus = false;
} else if (event.key === Qt.Key_Return) {
endMinuteField.focus = false;
return;
} else if (event.key === Qt.Key_Tab) {
startHourField.focus = true;
} else if (event.key === Qt.Key_Backtab) {
endHourField.focus = true;
}
if (event.text.length === 1 && event.text >= "0" && event.text <= "9") {
event.accepted = true;
var digit = event.text;
var textLen = endMinuteField.text.length;
if (textLen >= 2 && endMinuteField.text[0] !== '0') {
return;
}
var val = 0;
if (textLen === 0) {
val = parseInt(digit);
} else if (textLen === 1) {
val = parseInt(endMinuteField.text + digit);
} else {
val = parseInt(endMinuteField.text[1] + digit);
}
val = Math.max(0, Math.min(59, val));
if (textLen >= 2 && val < 10) {
endMinuteField.text = "0" + val;
} else {
endMinuteField.text = val.toString();
}
}
event.accepted = true;
}
onCursorPositionChanged: cursorPosition = 2
onEditingFinished: {
root.commitChoice(root.convertToMinutes(parseInt(endHourField.text), parseInt(endMinuteField.text)), root.settings[2]);
}
onTextEdited: {
if (endMinuteField.text === "")
return;
var val = parseInt(endMinuteField.text);
if (isNaN(val))
return;
val = Math.max(0, Math.min(23, val));
var newText = val.toString();
if (newText !== endMinuteField.text)
endMinuteField.text = newText;
}
}
}
}
RowLayout {
Layout.fillWidth: true
CustomText {
id: startHour
Layout.preferredWidth: startSeparator.x + startSeparator.width
text: qsTr("Hour")
}
CustomText {
id: startMinute
Layout.preferredWidth: spacer.x + spacer.width - x
text: qsTr("Minute")
}
CustomText {
Layout.preferredWidth: endSeparator.x + endSeparator.width - x
text: qsTr("Hour")
}
CustomText {
text: qsTr("Minute")
}
}
}
}
}
-12
View File
@@ -1,12 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
CustomRect {
id: root
Layout.fillHeight: true
Layout.preferredWidth: 1
color: DynamicColors.tPalette.m3outlineVariant
}
@@ -1,314 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Hyprland
import ZShell.Internal
import qs.Config
import qs.Components
import qs.Helpers
Item {
id: wrapper
property bool changesMade: false
property bool shouldBeActive: true
signal requestCrop
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: shouldBeActive ? 400 : 0
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
IconButton {
anchors.margins: Appearance.padding.normal
anchors.right: parent.right
anchors.top: parent.top
icon: "check"
opacity: wrapper.changesMade ? 1 : 0
scale: wrapper.changesMade ? 1 : 0
z: 2
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
onClicked: {
wrapper.requestCrop();
wrapper.changesMade = false;
}
}
RowLayout {
id: root
anchors.fill: parent
spacing: Appearance.spacing.normal
Repeater {
model: ScriptModel {
values: [...Quickshell.screens].sort((a, b) => {
return a.x - b.x;
})
}
Item {
id: delegate
required property ShellScreen modelData
function applyCrop(): void {
if (!cropRectLoader.item)
return;
const cropRect = cropRectLoader.item;
// We need to calculate the exact percentage coordinates that map perfectly
// to our C++ backend, regardless of current display scaling
const cropXPercent = (cropRect.x - cropRect.imageX) / scaledImg.paintedWidth;
const cropYPercent = (cropRect.y - cropRect.imageY) / scaledImg.paintedHeight;
const cropWidthPercent = cropRect.width / scaledImg.paintedWidth;
const cropHeightPercent = cropRect.height / scaledImg.paintedHeight;
const finalRect = Qt.rect(cropXPercent, cropYPercent, cropWidthPercent, cropHeightPercent);
// We just pass the percentages directly to the backend
Wallpapers.setCrop(delegate.modelData.name, finalRect, cropRect.zoom);
}
function zoomClipRect(zoom: real): void {
if (!cropRectLoader.item)
return;
const cropRect = cropRectLoader.item;
let oldCenterX = cropRect.x + cropRect.width * 0.5;
let oldCenterY = cropRect.y + cropRect.height * 0.5;
cropRect.zoom = zoom;
cropRect.x = oldCenterX - cropRect.width * 0.5;
cropRect.y = oldCenterY - cropRect.height * 0.5;
cropRect.clampToBounds();
}
Layout.fillHeight: true
Layout.fillWidth: true
Connections {
function onRequestCrop(): void {
delegate.applyCrop();
}
target: wrapper
}
RowLayout {
id: sliderLayout
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: 30
CustomSlider {
id: zoomSlider
Layout.fillWidth: true
Layout.leftMargin: Appearance.padding.normal
Layout.preferredHeight: Appearance.padding.larger * 3
Layout.rightMargin: Appearance.padding.normal
from: 1.0
implicitHeight: Appearance.padding.larger * 3
insetIcon: "crop"
to: 5.0
value: cropRectLoader.item ? cropRectLoader.item.zoom : 1.0
onInteraction: value => {
delegate.zoomClipRect(1 + (value * 4));
wrapper.changesMade = true;
}
}
}
CachingImage {
id: scaledImg
property var displayData
property real monitorScale: 1.0
anchors.bottom: sliderLayout.top
anchors.bottomMargin: Appearance.spacing.normal
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
asynchronous: true
fillMode: Image.PreserveAspectFit
retainWhileLoading: true
source: Wallpapers.current
sourceSize.height: parent.height
sourceSize.width: parent.width
onPaintedWidthChanged: {
if (paintedWidth > 0 && cropRectLoader.item) {
cropRectLoader.item.restoreFromData();
}
}
onSourceChanged: {
if (cropRectLoader.item) {
cropRectLoader.item.restoreFromData();
}
}
onStatusChanged: {
if (scaledImg.status == Image.Ready && cropRectLoader.item) {
cropRectLoader.item.restoreFromData();
}
}
CustomText {
id: monitorId
anchors.centerIn: parent
color: Qt.alpha(DynamicColors.palette.m3surface, 0.85)
font.pointSize: Appearance.font.size.large * 4
style: Text.Outline
styleColor: DynamicColors.palette.m3onSurface
text: delegate.modelData.name
}
Loader {
id: cropRectLoader
active: scaledImg.paintedWidth > 0
sourceComponent: Component {
CustomRect {
id: cropRect
property real aspectRatio: delegate.modelData.width / delegate.modelData.height
readonly property real baseHeight: baseWidth / aspectRatio
readonly property real baseWidth: {
let fittedHeight = scaledImg.paintedHeight;
let fittedWidth = fittedHeight * aspectRatio;
if (fittedWidth > scaledImg.paintedWidth) {
fittedWidth = scaledImg.paintedWidth;
fittedHeight = fittedWidth / aspectRatio;
}
return fittedWidth;
}
readonly property real imageX: (scaledImg.width - scaledImg.paintedWidth) / 2
readonly property real imageY: (scaledImg.height - scaledImg.paintedHeight) / 2
property real imgAspectRatio: scaledImg.paintedWidth / scaledImg.paintedHeight
property real zoom: 1.0
function centerInImage() {
x = imageX + (scaledImg.paintedWidth - width) / 2;
y = imageY + (scaledImg.paintedHeight - height) / 2;
}
function clampToBounds() {
x = Math.max(imageX, Math.min(x, imageX + scaledImg.paintedWidth - width));
y = Math.max(imageY, Math.min(y, imageY + scaledImg.paintedHeight - height));
}
function restoreFromData() {
let data = Wallpapers.getCrop(delegate.modelData.name);
if (data && (Math.abs(data.x) > 0.001 || Math.abs(data.y) > 0.001 || Math.abs(data.width - 1.0) > 0.001 || Math.abs(data.height - 1.0) > 0.001)) {
zoom = data.zoom > 0 ? data.zoom : 1.0;
x = imageX + (data.x * scaledImg.paintedWidth);
y = imageY + (data.y * scaledImg.paintedHeight);
clampToBounds();
} else {
zoom = 1.0;
centerInImage();
}
}
border.color: DynamicColors.palette.m3primary
border.width: 2
height: baseHeight / zoom
opacity: 1
width: baseWidth / zoom
Behavior on opacity {
Anim {
}
}
Component.onCompleted: {
restoreFromData();
}
onHeightChanged: clampToBounds()
onWidthChanged: clampToBounds()
}
}
}
MouseArea {
id: mouse
function updateCrop(mouseX, mouseY) {
if (!cropRectLoader.item)
return;
const cropRect = cropRectLoader.item;
let nx = mouseX - cropRect.width * 0.5;
let ny = mouseY - cropRect.height * 0.5;
nx = Math.max(cropRect.imageX, Math.min(nx, cropRect.imageX + scaledImg.paintedWidth - cropRect.width));
ny = Math.max(cropRect.imageY, Math.min(ny, cropRect.imageY + scaledImg.paintedHeight - cropRect.height));
cropRect.x = nx;
cropRect.y = ny;
}
anchors.fill: parent
hoverEnabled: true
preventStealing: true
onPositionChanged: mouse => {
if (pressed) {
updateCrop(mouse.x, mouse.y);
wrapper.changesMade = true;
}
}
onPressed: mouse => {
updateCrop(mouse.x, mouse.y);
wrapper.changesMade = true;
}
onReleased: {
wrapper.changesMade = true;
}
}
}
}
}
}
}
-158
View File
@@ -1,158 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import ZShell.Models
import qs.Components
import qs.Helpers
import qs.Config
GridView {
id: root
readonly property int columnsCount: Math.max(1, Math.floor(width / minCellWidth))
readonly property int minCellWidth: 200 + Appearance.spacing.normal
property bool shouldBeActive: true
anchors.left: parent.left
anchors.right: parent.right
cellHeight: 140 + Appearance.spacing.normal
cellWidth: width / columnsCount
clip: true
implicitHeight: shouldBeActive ? contentHeight : 0
interactive: false
model: Wallpapers.list
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
visible: opacity > 0
delegate: Item {
required property int index
readonly property bool isCurrent: modelData && modelData.path === Wallpapers.actualCurrent
readonly property real itemMargin: Appearance.spacing.normal
readonly property real itemRadius: Appearance.rounding.small
required property var modelData
height: root.cellHeight
width: root.cellWidth
CustomClippingRect {
id: image
anchors.bottomMargin: itemMargin
anchors.fill: parent
anchors.leftMargin: itemMargin
anchors.rightMargin: itemMargin
anchors.topMargin: itemMargin
antialiasing: true
color: DynamicColors.tPalette.m3surfaceContainer
radius: itemRadius
CachingImage {
id: cachingImage
anchors.fill: parent
antialiasing: true
cache: true
fillMode: Image.PreserveAspectCrop
opacity: status === Image.Ready ? 1 : 0
path: modelData.path
smooth: true
sourceSize: Qt.size(width, height)
visible: opacity > 0
Behavior on opacity {
NumberAnimation {
duration: 1000
easing.type: Easing.OutQuad
}
}
}
Image {
id: fallbackImage
anchors.fill: parent
antialiasing: true
asynchronous: true
cache: true
fillMode: Image.PreserveAspectCrop
opacity: status === Image.Ready && cachingImage.status !== Image.Ready ? 1 : 0
smooth: true
source: fallbackTimer.triggered && cachingImage.status !== Image.Ready ? modelData.path : ""
sourceSize: Qt.size(width, height)
visible: opacity > 0
Behavior on opacity {
NumberAnimation {
duration: 1000
easing.type: Easing.OutQuad
}
}
}
Rectangle {
anchors.fill: parent
antialiasing: true
border.color: DynamicColors.palette.m3primary
border.width: isCurrent ? 2 : 0
color: "transparent"
radius: itemRadius + 2
smooth: true
Behavior on border.width {
NumberAnimation {
duration: 150
easing.type: Easing.OutQuad
}
}
MaterialIcon {
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.top: parent.top
color: DynamicColors.palette.m3primary
font.pointSize: Appearance.font.size.large
text: "check_circle"
visible: isCurrent
}
}
Timer {
id: fallbackTimer
property bool triggered: false
interval: 800
running: cachingImage.status === Image.Loading || cachingImage.status === Image.Null
onTriggered: triggered = true
}
}
StateLayer {
anchors.bottomMargin: itemMargin
anchors.fill: parent
anchors.leftMargin: itemMargin
anchors.rightMargin: itemMargin
anchors.topMargin: itemMargin
radius: itemRadius
onClicked: {
Wallpapers.setWallpaper(modelData.path);
}
}
}
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
Behavior on y {
Anim {
}
}
}
@@ -1,7 +1,7 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Modules.SettingsNew.NavPane
import qs.Modules.Settings.NavPane
import qs.Config
ColumnLayout {
@@ -4,7 +4,7 @@ import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
import qs.Modules.SettingsNew
import qs.Modules.Settings
VerticalFadeFlickable {
id: root
@@ -4,14 +4,14 @@ import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
import qs.Modules.SettingsNew.Common
import qs.Modules.SettingsNew.Pages
import qs.Modules.SettingsNew.Pages.Wallpaper
import qs.Modules.SettingsNew.Pages.Audio
import qs.Modules.SettingsNew.Pages.Apps
import qs.Modules.SettingsNew.Pages.Panels
import qs.Modules.SettingsNew.Pages.Panels.Bar
import qs.Modules.SettingsNew.Pages.Services
import qs.Modules.Settings.Common
import qs.Modules.Settings.Pages
import qs.Modules.Settings.Pages.Wallpaper
import qs.Modules.Settings.Pages.Audio
import qs.Modules.Settings.Pages.Apps
import qs.Modules.Settings.Pages.Panels
import qs.Modules.Settings.Pages.Panels.Bar
import qs.Modules.Settings.Pages.Services
QtObject {
id: root
@@ -2,7 +2,7 @@ import QtQuick
import QtQuick.Layouts
import Quickshell.Io
import ZShell
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
import qs.Config
import qs.Helpers
import qs.Components
@@ -7,7 +7,7 @@ import Quickshell.Widgets
import qs.Components
import qs.Config
import qs.Helpers
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -5,7 +5,7 @@ import Quickshell.Widgets
import qs.Components
import qs.Config
import qs.Helpers
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -8,7 +8,7 @@ import ZShell
import qs.Helpers
import qs.Components
import qs.Config
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -4,7 +4,7 @@ import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Services.Pipewire
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
import qs.Helpers
import qs.Components
import qs.Config
@@ -5,7 +5,7 @@ import QtQuick.Layouts
import qs.Daemons
import qs.Config
import qs.Components
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
import qs.Helpers
PageBase {
@@ -3,7 +3,7 @@ pragma ComponentBehavior: Bound
import QtQuick.Layouts
import qs.Config
import qs.Components
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -2,7 +2,7 @@ pragma ComponentBehavior: Bound
import QtQuick.Layouts
import qs.Config
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -2,7 +2,7 @@ pragma ComponentBehavior: Bound
import QtQuick.Layouts
import qs.Config
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -2,7 +2,7 @@ pragma ComponentBehavior: Bound
import QtQuick.Layouts
import qs.Config
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -4,7 +4,7 @@ import QtQuick
import QtQuick.Layouts
import qs.Config
import qs.Components
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -4,7 +4,7 @@ import QtQuick
import QtQuick.Layouts
import qs.Config
import qs.Components
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -4,7 +4,7 @@ import QtQuick
import QtQuick.Layouts
import qs.Config
import qs.Components
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -4,7 +4,7 @@ import QtQuick
import QtQuick.Layouts
import qs.Config
import qs.Components
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -1,6 +1,6 @@
import QtQuick.Layouts
import qs.Config
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -6,8 +6,8 @@ import ZShell.Components
import qs.Helpers
import qs.Components
import qs.Config
import qs.Modules.SettingsNew
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -2,7 +2,7 @@ import QtQuick
import QtQuick.Layouts
import qs.Config
import qs.Components
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -5,7 +5,7 @@ import ZShell.Services
import qs.Components
import qs.Helpers
import qs.Config
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -7,7 +7,7 @@ import qs.Paths
import qs.Helpers
import qs.Components
import qs.Config
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings.Common
PageBase {
id: root
@@ -6,8 +6,8 @@ import ZShell.Components
import qs.Helpers
import qs.Components
import qs.Config
import qs.Modules.SettingsNew
import qs.Modules.SettingsNew.Common
import qs.Modules.Settings
import qs.Modules.Settings.Common
PageBase {
id: root
-317
View File
@@ -1,317 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import qs.Components
import qs.Config
import "../../scripts/fuzzysort.js" as Fuzzy
import "../../scripts/SettingsIndex.mjs" as SettingsIndex
Item {
id: root
property alias text: searchField.text
signal settingSelected(string category, string section, string settingName)
function close() {
searchField.text = "";
searchField.focus = false;
popup.close();
}
function search(query) {
resultsModel.clear();
if (!query || query.trim() === "") {
popup.close();
return;
}
const results = SettingsIndex.searchSettings(query, Fuzzy);
for (const result of results.slice(0, 10)) {
resultsModel.append({
name: result.name,
category: result.category,
categoryName: result.categoryName,
section: result.section,
matchType: result.matchType
});
}
if (resultsModel.count > 0) {
popup.open();
} else {
popup.close();
}
}
implicitHeight: searchContainer.implicitHeight
implicitWidth: 200
Shortcut {
sequence: "/"
onActivated: searchField.forceActiveFocus()
}
ListModel {
id: resultsModel
}
CustomRect {
id: searchContainer
anchors.fill: parent
color: DynamicColors.tPalette.m3surfaceContainerHigh
implicitHeight: searchRow.implicitHeight + Appearance.padding.small * 2
radius: Appearance.rounding.full
RowLayout {
id: searchRow
anchors.fill: parent
anchors.leftMargin: Appearance.padding.normal
anchors.rightMargin: Appearance.padding.small
spacing: Appearance.spacing.small
MaterialIcon {
Layout.alignment: Qt.AlignVCenter
color: DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.larger
text: "search"
}
CustomTextField {
id: searchField
Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true
font.pointSize: Appearance.font.size.small
placeholderText: qsTr("Search settings...")
Keys.onDownPressed: {
if (popup.visible && resultsList.count > 0) {
resultsList.currentIndex = Math.min(resultsList.currentIndex + 1, resultsList.count - 1);
}
}
Keys.onEscapePressed: {
root.close();
}
Keys.onReturnPressed: {
if (popup.visible && resultsList.currentIndex >= 0) {
const item = resultsModel.get(resultsList.currentIndex);
root.settingSelected(item.category, item.section, item.name);
root.close();
}
}
Keys.onUpPressed: {
if (popup.visible && resultsList.count > 0) {
resultsList.currentIndex = Math.max(resultsList.currentIndex - 1, 0);
}
}
onTextChanged: {
searchTimer.restart();
}
}
// Clear button
IconButton {
Layout.alignment: Qt.AlignVCenter
font.pointSize: Appearance.font.size.larger
icon: "close"
opacity: searchField.text.length > 0 ? 1 : 0
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.small
}
}
onClicked: {
root.close();
}
}
}
}
// Debounce timer for search
Timer {
id: searchTimer
interval: 150
onTriggered: root.search(searchField.text)
}
// Results dropdown
Popup {
id: popup
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
implicitHeight: Math.min(resultsList.contentHeight + Appearance.padding.small * 2 + 10, (55 + Appearance.spacing.smaller) * 5 - Appearance.spacing.smaller + 10 + Appearance.padding.small * 2)
implicitWidth: root.width + Appearance.padding.small * 2
modal: false
padding: 0
x: root.width / 2 - popup.width / 2
y: searchContainer.height + Appearance.spacing.small - 5
background: Item {
}
contentItem: Item {
property alias view: resultsList
Elevation {
id: popupShadow
anchors.centerIn: parent
height: popup.implicitHeight - 10
level: 2
radius: Appearance.rounding.normal
width: popup.implicitWidth - 10
CustomRect {
anchors.fill: parent
color: DynamicColors.palette.m3surfaceContainer
radius: Appearance.rounding.normal
CustomListView {
id: resultsList
anchors.fill: parent
anchors.margins: Appearance.padding.small
clip: true
currentIndex: 0
highlightFollowsCurrentItem: false
highlightRangeMode: ListView.ApplyRange
model: resultsModel
preferredHighlightBegin: 0
preferredHighlightEnd: height
spacing: Appearance.spacing.smaller
delegate: SearchResultItem {
required property string category
required property string categoryName
required property int index
required property string matchType
required property string name
required property string section
highlighted: index === resultsList.currentIndex
width: resultsList.width
onClicked: {
root.settingSelected(category, section, name);
root.close();
}
}
highlight: CustomRect {
color: DynamicColors.palette.m3primary
implicitHeight: resultsList.currentItem?.implicitHeight ?? 0
implicitWidth: resultsList.width
radius: Appearance.rounding.normal - Appearance.padding.smaller
y: resultsList.currentItem?.y ?? 0
Behavior on y {
Anim {
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
}
}
}
}
}
}
}
enter: Transition {
Anim {
duration: Appearance.anim.durations.small
from: 0
property: "opacity"
to: 1
}
Anim {
duration: Appearance.anim.durations.small
from: 0.95
property: "scale"
to: 1.0
}
}
exit: Transition {
Anim {
duration: Appearance.anim.durations.smaller
from: 1
property: "opacity"
to: 0
}
}
}
// Search result item component
component SearchResultItem: CustomRect {
id: resultItem
property bool highlighted: false
signal clicked
implicitHeight: 45 + Appearance.padding.small * 2
radius: Appearance.rounding.small
ColumnLayout {
id: resultLayout
anchors.left: parent.left
anchors.margins: Appearance.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: 2
// Setting name
CustomText {
Layout.fillWidth: true
color: highlighted ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface
elide: Text.ElideRight
font.pointSize: Appearance.font.size.small
font.weight: Font.Medium
text: resultItem.name
}
// Category and section path
RowLayout {
Layout.fillWidth: true
spacing: Appearance.spacing.smaller
CustomText {
color: highlighted ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.smaller
opacity: 0.8
text: resultItem.categoryName
}
CustomText {
color: highlighted ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.smaller
opacity: 0.6
text: ""
}
CustomText {
Layout.fillWidth: true
color: highlighted ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurfaceVariant
elide: Text.ElideRight
font.pointSize: Appearance.font.size.smaller
opacity: 0.8
text: resultItem.section
}
}
}
StateLayer {
onClicked: resultItem.clicked()
}
}
}
+5 -3
View File
@@ -13,7 +13,6 @@ Item {
readonly property bool shouldBeActive: visibilities.settings
required property PersistentProperties visibilities
anchors.topMargin: (-implicitHeight - 5) * offsetScale
implicitHeight: content.implicitHeight
implicitWidth: content.implicitWidth
opacity: 1 - offsetScale
@@ -37,8 +36,11 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
sourceComponent: Content {
screen: root.screen
visibilities: root.visibilities
sState.animatingContainer: content.opacity < 1
sState.currentPageIdx: ["wallpaper"][0]
sState.screen: root.screen
onClose: console.log("shouldclose")
}
}
}
-76
View File
@@ -1,76 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import ZShell.Blobs
import qs.Components
import qs.Config
CustomClippingRect {
id: root
property color blobColor: DynamicColors.tPalette.m3surfaceContainerLow
readonly property real ratio: 16.0 / 9.0
readonly property SettingsState sState: SettingsState {
id: sState
onClose: root.close()
}
signal close
implicitHeight: sState.screen.height * 0.7
implicitWidth: implicitHeight * ratio
radius: Appearance.rounding.large + Appearance.padding.normal
Behavior on blobColor {
CAnim {
}
}
TapHandler {
onTapped: root.focus = true
}
BlobGroup {
id: blobGroup
color: root.blobColor
smoothing: Appearance.rounding.normal
}
BlobInvertedRect {
anchors.fill: parent
borderBottom: Appearance.padding.normal
borderLeft: navPane.width + navPane.anchors.margins * 2
borderRight: Appearance.padding.normal
borderTop: Appearance.padding.normal
group: blobGroup
opacity: root.blobColor.a
radius: Appearance.rounding.large
}
NavPane {
id: navPane
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.margins: Appearance.padding.large
anchors.top: parent.top
sState: root.sState
width: Math.min(600, Math.round(root.width / 3))
}
Pages {
anchors.bottom: parent.bottom
anchors.left: navPane.right
anchors.leftMargin: navPane.anchors.margins + anchors.margins
anchors.margins: Appearance.padding.extraLarge
anchors.right: parent.right
anchors.top: parent.top
sState: root.sState
}
PopupOverlay {
anchors.fill: parent
}
}
-47
View File
@@ -1,47 +0,0 @@
import Quickshell
import QtQuick
import qs.Components
import qs.Config
import qs.Helpers
Item {
id: root
property real offsetScale: shouldBeActive ? 0 : 1
required property var panels
required property ShellScreen screen
readonly property bool shouldBeActive: visibilities.settings
required property PersistentProperties visibilities
implicitHeight: content.implicitHeight
implicitWidth: content.implicitWidth
opacity: 1 - offsetScale
visible: offsetScale < 1
Behavior on offsetScale {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
CustomClippingRect {
anchors.fill: parent
Loader {
id: content
active: root.shouldBeActive || root.visible
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
sourceComponent: Content {
sState.animatingContainer: content.opacity < 1
sState.currentPageIdx: ["wallpaper"][0]
sState.screen: root.screen
onClose: console.log("shouldclose")
}
}
}
}