configoptions: use quickshell jsonadapter

This commit is contained in:
end-4
2025-06-30 14:27:26 +02:00
parent 22319ffccf
commit 7ca0f263ba
50 changed files with 455 additions and 546 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ Singleton {
Timer {
id: workspaceShowNumbersTimer
interval: ConfigOptions.bar.workspaces.showNumberDelay
interval: Config.options.bar.workspaces.showNumberDelay
// interval: 0
repeat: false
onTriggered: {
@@ -15,12 +15,12 @@ import Quickshell.Services.UPower
Scope {
id: root
property string filePath: `${Directories.state}/user/generated/wallpaper/least_busy_region.json`
property real defaultX: (ConfigOptions?.background.clockX ?? -500)
property real defaultY: (ConfigOptions?.background.clockY ?? -500)
property real defaultX: (Config.options?.background.clockX ?? -500)
property real defaultY: (Config.options?.background.clockY ?? -500)
property real centerX: defaultX
property real centerY: defaultY
property real effectiveCenterX: ConfigOptions?.background.fixedClockPosition ? defaultX : centerX
property real effectiveCenterY: ConfigOptions?.background.fixedClockPosition ? defaultY : centerY
property real effectiveCenterX: Config.options?.background.fixedClockPosition ? defaultX : centerX
property real effectiveCenterY: Config.options?.background.fixedClockPosition ? defaultY : centerY
property color dominantColor: Appearance.colors.colPrimary
property bool dominantColorIsDark: dominantColor.hslLightness < 0.5
property color colBackground: ColorUtils.transparentize(ColorUtils.mix(Appearance.colors.colPrimary, Appearance.colors.colSecondaryContainer), 1)
@@ -36,7 +36,7 @@ Scope {
Timer {
id: delayedFileRead
interval: ConfigOptions.hacks.arbitraryRaceConditionDelay
interval: Config.options.hacks.arbitraryRaceConditionDelay
running: false
onTriggered: {
root.updateWidgetPosition(leastBusyRegionFileView.text())
@@ -46,7 +46,7 @@ Scope {
FileView {
id: leastBusyRegionFileView
path: Qt.resolvedUrl(root.filePath)
watchChanges: !ConfigOptions?.background.fixedClockPosition
watchChanges: !Config.options?.background.fixedClockPosition
onFileChanged: {
this.reload()
delayedFileRead.start()
+21 -21
View File
@@ -16,7 +16,7 @@ Scope {
id: bar
readonly property int osdHideMouseMoveThreshold: 20
property bool showBarBackground: ConfigOptions.bar.showBackground
property bool showBarBackground: Config.options.bar.showBackground
component VerticalBarSeparator: Rectangle {
Layout.topMargin: Appearance.sizes.baseBarHeight / 3
@@ -29,7 +29,7 @@ Scope {
Variants { // For each monitor
model: {
const screens = Quickshell.screens;
const list = ConfigOptions.bar.screenList;
const list = Config.options.bar.screenList;
if (!list || list.length === 0)
return screens;
return screens.filter(screen => list.includes(screen.name));
@@ -50,15 +50,15 @@ Scope {
WlrLayershell.namespace: "quickshell:bar"
implicitHeight: Appearance.sizes.barHeight + Appearance.rounding.screenRounding
exclusiveZone: Appearance.sizes.baseBarHeight + (ConfigOptions.bar.cornerStyle === 1 ? Appearance.sizes.hyprlandGapsOut : 0)
exclusiveZone: Appearance.sizes.baseBarHeight + (Config.options.bar.cornerStyle === 1 ? Appearance.sizes.hyprlandGapsOut : 0)
mask: Region {
item: barContent
}
color: "transparent"
anchors {
top: !ConfigOptions.bar.bottom
bottom: ConfigOptions.bar.bottom
top: !Config.options.bar.bottom
bottom: Config.options.bar.bottom
left: true
right: true
}
@@ -76,7 +76,7 @@ Scope {
states: State {
name: "bottom"
when: ConfigOptions.bar.bottom
when: Config.options.bar.bottom
AnchorChanges {
target: barContent
anchors {
@@ -90,7 +90,7 @@ Scope {
// Background shadow
Loader {
active: showBarBackground && ConfigOptions.bar.cornerStyle === 1
active: showBarBackground && Config.options.bar.cornerStyle === 1
anchors.fill: barBackground
sourceComponent: StyledRectangularShadow {
anchors.fill: undefined // The loader's anchors act on this, and this should not have any anchor
@@ -102,10 +102,10 @@ Scope {
id: barBackground
anchors {
fill: parent
margins: ConfigOptions.bar.cornerStyle === 1 ? (Appearance.sizes.hyprlandGapsOut) : 0 // idk why but +1 is needed
margins: Config.options.bar.cornerStyle === 1 ? (Appearance.sizes.hyprlandGapsOut) : 0 // idk why but +1 is needed
}
color: showBarBackground ? Appearance.colors.colLayer0 : "transparent"
radius: ConfigOptions.bar.cornerStyle === 1 ? Appearance.rounding.windowRounding : 0
radius: Config.options.bar.cornerStyle === 1 ? Appearance.rounding.windowRounding : 0
}
MouseArea { // Left side | scroll to change brightness
@@ -204,7 +204,7 @@ Scope {
anchors.centerIn: parent
width: 19.5
height: 19.5
source: ConfigOptions.bar.topLeftIcon == 'distro' ?
source: Config.options.bar.topLeftIcon == 'distro' ?
SystemInfo.distroIcon : "spark-symbolic"
}
@@ -229,7 +229,7 @@ Scope {
RowLayout { // Middle section
id: middleSection
anchors.centerIn: parent
spacing: ConfigOptions?.bar.borderless ? 4 : 8
spacing: Config.options?.bar.borderless ? 4 : 8
BarGroup {
id: leftCenterGroup
@@ -248,7 +248,7 @@ Scope {
}
VerticalBarSeparator {visible: ConfigOptions?.bar.borderless}
VerticalBarSeparator {visible: Config.options?.bar.borderless}
BarGroup {
id: middleCenterGroup
@@ -272,7 +272,7 @@ Scope {
}
}
VerticalBarSeparator {visible: ConfigOptions?.bar.borderless}
VerticalBarSeparator {visible: Config.options?.bar.borderless}
MouseArea {
id: rightCenterGroup
@@ -290,13 +290,13 @@ Scope {
anchors.fill: parent
ClockWidget {
showDate: (ConfigOptions.bar.verbose && barRoot.useShortenedForm < 2)
showDate: (Config.options.bar.verbose && barRoot.useShortenedForm < 2)
Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true
}
UtilButtons {
visible: (ConfigOptions.bar.verbose && barRoot.useShortenedForm === 0)
visible: (Config.options.bar.verbose && barRoot.useShortenedForm === 0)
Layout.alignment: Qt.AlignVCenter
}
@@ -495,11 +495,11 @@ Scope {
y: Appearance.sizes.barHeight
width: parent.width
height: Appearance.rounding.screenRounding
active: showBarBackground && ConfigOptions.bar.cornerStyle === 0 // Hug
active: showBarBackground && Config.options.bar.cornerStyle === 0 // Hug
states: State {
name: "bottom"
when: ConfigOptions.bar.bottom
when: Config.options.bar.bottom
PropertyChanges {
roundDecorators.y: 0
}
@@ -522,7 +522,7 @@ Scope {
corner: RoundCorner.CornerEnum.TopLeft
states: State {
name: "bottom"
when: ConfigOptions.bar.bottom
when: Config.options.bar.bottom
PropertyChanges {
leftCorner.corner: RoundCorner.CornerEnum.BottomLeft
}
@@ -532,8 +532,8 @@ Scope {
id: rightCorner
anchors {
right: parent.right
top: !ConfigOptions.bar.bottom ? parent.top : undefined
bottom: ConfigOptions.bar.bottom ? parent.bottom : undefined
top: !Config.options.bar.bottom ? parent.top : undefined
bottom: Config.options.bar.bottom ? parent.bottom : undefined
}
size: Appearance.rounding.screenRounding
color: showBarBackground ? Appearance.colors.colLayer0 : "transparent"
@@ -542,7 +542,7 @@ Scope {
corner: RoundCorner.CornerEnum.TopRight
states: State {
name: "bottom"
when: ConfigOptions.bar.bottom
when: Config.options.bar.bottom
PropertyChanges {
rightCorner.corner: RoundCorner.CornerEnum.BottomRight
}
+1 -1
View File
@@ -19,7 +19,7 @@ Item {
topMargin: 4
bottomMargin: 4
}
color: ConfigOptions?.bar.borderless ? "transparent" : Appearance.colors.colLayer1
color: Config.options?.bar.borderless ? "transparent" : Appearance.colors.colLayer1
radius: Appearance.rounding.small
}
@@ -9,12 +9,12 @@ import Quickshell.Services.UPower
Item {
id: root
property bool borderless: ConfigOptions.bar.borderless
property bool borderless: Config.options.bar.borderless
readonly property var chargeState: Battery.chargeState
readonly property bool isCharging: Battery.isCharging
readonly property bool isPluggedIn: Battery.isPluggedIn
readonly property real percentage: Battery.percentage
readonly property bool isLow: percentage <= ConfigOptions.battery.low / 100
readonly property bool isLow: percentage <= Config.options.battery.low / 100
readonly property color batteryLowBackground: Appearance.m3colors.darkmode ? Appearance.m3colors.m3error : Appearance.m3colors.m3errorContainer
readonly property color batteryLowOnBackground: Appearance.m3colors.darkmode ? Appearance.m3colors.m3errorContainer : Appearance.m3colors.m3error
@@ -6,8 +6,8 @@ import QtQuick.Layouts
Item {
id: root
property bool borderless: ConfigOptions.bar.borderless
property bool showDate: ConfigOptions.bar.verbose
property bool borderless: Config.options.bar.borderless
property bool showDate: Config.options.bar.verbose
implicitWidth: rowLayout.implicitWidth
implicitHeight: 32
+1 -1
View File
@@ -11,7 +11,7 @@ import Quickshell.Hyprland
Item {
id: root
property bool borderless: ConfigOptions.bar.borderless
property bool borderless: Config.options.bar.borderless
readonly property MprisPlayer activePlayer: MprisController.activePlayer
readonly property string cleanedTitle: StringUtils.cleanMusicTitle(activePlayer?.trackTitle) || qsTr("No media")
+3 -3
View File
@@ -9,7 +9,7 @@ import Quickshell.Services.Mpris
Item {
id: root
property bool borderless: ConfigOptions.bar.borderless
property bool borderless: Config.options.bar.borderless
property bool alwaysShowAllResources: false
implicitWidth: rowLayout.implicitWidth + rowLayout.anchors.leftMargin + rowLayout.anchors.rightMargin
implicitHeight: 32
@@ -30,7 +30,7 @@ Item {
Resource {
iconName: "swap_horiz"
percentage: ResourceUsage.swapUsedPercentage
shown: (ConfigOptions.bar.resources.alwaysShowSwap && percentage > 0) ||
shown: (Config.options.bar.resources.alwaysShowSwap && percentage > 0) ||
(MprisController.activePlayer?.trackTitle == null) ||
root.alwaysShowAllResources
Layout.leftMargin: shown ? 4 : 0
@@ -39,7 +39,7 @@ Item {
Resource {
iconName: "settings_slow_motion"
percentage: ResourceUsage.cpuUsage
shown: ConfigOptions.bar.resources.alwaysShowCpu ||
shown: Config.options.bar.resources.alwaysShowCpu ||
!(MprisController.activePlayer?.trackTitle?.length > 0) ||
root.alwaysShowAllResources
Layout.leftMargin: shown ? 4 : 0
@@ -43,7 +43,7 @@ MouseArea {
IconImage {
id: trayIcon
visible: !ConfigOptions.bar.tray.monochromeIcons
visible: !Config.options.bar.tray.monochromeIcons
source: root.item.icon
anchors.centerIn: parent
width: parent.width
@@ -51,7 +51,7 @@ MouseArea {
}
Loader {
active: ConfigOptions.bar.tray.monochromeIcons
active: Config.options.bar.tray.monochromeIcons
anchors.fill: trayIcon
sourceComponent: Item {
Desaturate {
+11 -11
View File
@@ -9,7 +9,7 @@ import Quickshell.Services.Pipewire
Item {
id: root
property bool borderless: ConfigOptions.bar.borderless
property bool borderless: Config.options.bar.borderless
implicitWidth: rowLayout.implicitWidth + rowLayout.spacing * 2
implicitHeight: rowLayout.implicitHeight
@@ -20,8 +20,8 @@ Item {
anchors.centerIn: parent
Loader {
active: ConfigOptions.bar.utilButtons.showScreenSnip
visible: ConfigOptions.bar.utilButtons.showScreenSnip
active: Config.options.bar.utilButtons.showScreenSnip
visible: Config.options.bar.utilButtons.showScreenSnip
sourceComponent: CircleUtilButton {
Layout.alignment: Qt.AlignVCenter
onClicked: Hyprland.dispatch("exec hyprshot --freeze --clipboard-only --mode region --silent")
@@ -36,8 +36,8 @@ Item {
}
Loader {
active: ConfigOptions.bar.utilButtons.showColorPicker
visible: ConfigOptions.bar.utilButtons.showColorPicker
active: Config.options.bar.utilButtons.showColorPicker
visible: Config.options.bar.utilButtons.showColorPicker
sourceComponent: CircleUtilButton {
Layout.alignment: Qt.AlignVCenter
onClicked: Hyprland.dispatch("exec hyprpicker -a")
@@ -52,8 +52,8 @@ Item {
}
Loader {
active: ConfigOptions.bar.utilButtons.showKeyboardToggle
visible: ConfigOptions.bar.utilButtons.showKeyboardToggle
active: Config.options.bar.utilButtons.showKeyboardToggle
visible: Config.options.bar.utilButtons.showKeyboardToggle
sourceComponent: CircleUtilButton {
Layout.alignment: Qt.AlignVCenter
onClicked: Hyprland.dispatch("global quickshell:oskToggle")
@@ -68,8 +68,8 @@ Item {
}
Loader {
active: ConfigOptions.bar.utilButtons.showMicToggle
visible: ConfigOptions.bar.utilButtons.showMicToggle
active: Config.options.bar.utilButtons.showMicToggle
visible: Config.options.bar.utilButtons.showMicToggle
sourceComponent: CircleUtilButton {
Layout.alignment: Qt.AlignVCenter
onClicked: Hyprland.dispatch("exec wpctl set-mute @DEFAULT_SOURCE@ toggle")
@@ -84,8 +84,8 @@ Item {
}
Loader {
active: ConfigOptions.bar.utilButtons.showDarkModeToggle
visible: ConfigOptions.bar.utilButtons.showDarkModeToggle
active: Config.options.bar.utilButtons.showDarkModeToggle
visible: Config.options.bar.utilButtons.showDarkModeToggle
sourceComponent: CircleUtilButton {
Layout.alignment: Qt.AlignVCenter
onClicked: event => {
+17 -17
View File
@@ -15,11 +15,11 @@ import Qt5Compat.GraphicalEffects
Item {
required property var bar
property bool borderless: ConfigOptions.bar.borderless
property bool borderless: Config.options.bar.borderless
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(bar.screen)
readonly property Toplevel activeWindow: ToplevelManager.activeToplevel
readonly property int workspaceGroup: Math.floor((monitor.activeWorkspace?.id - 1) / ConfigOptions.bar.workspaces.shown)
readonly property int workspaceGroup: Math.floor((monitor.activeWorkspace?.id - 1) / Config.options.bar.workspaces.shown)
property list<bool> workspaceOccupied: []
property int widgetPadding: 4
property int workspaceButtonWidth: 26
@@ -27,12 +27,12 @@ Item {
property real workspaceIconSizeShrinked: workspaceButtonWidth * 0.55
property real workspaceIconOpacityShrinked: 1
property real workspaceIconMarginShrinked: -4
property int workspaceIndexInGroup: (monitor.activeWorkspace?.id - 1) % ConfigOptions.bar.workspaces.shown
property int workspaceIndexInGroup: (monitor.activeWorkspace?.id - 1) % Config.options.bar.workspaces.shown
// Function to update workspaceOccupied
function updateWorkspaceOccupied() {
workspaceOccupied = Array.from({ length: ConfigOptions.bar.workspaces.shown }, (_, i) => {
return Hyprland.workspaces.values.some(ws => ws.id === workspaceGroup * ConfigOptions.bar.workspaces.shown + i + 1);
workspaceOccupied = Array.from({ length: Config.options.bar.workspaces.shown }, (_, i) => {
return Hyprland.workspaces.values.some(ws => ws.id === workspaceGroup * Config.options.bar.workspaces.shown + i + 1);
})
}
@@ -81,7 +81,7 @@ Item {
implicitHeight: Appearance.sizes.barHeight
Repeater {
model: ConfigOptions.bar.workspaces.shown
model: Config.options.bar.workspaces.shown
Rectangle {
z: 1
@@ -160,11 +160,11 @@ Item {
implicitHeight: Appearance.sizes.barHeight
Repeater {
model: ConfigOptions.bar.workspaces.shown
model: Config.options.bar.workspaces.shown
Button {
id: button
property int workspaceValue: workspaceGroup * ConfigOptions.bar.workspaces.shown + index + 1
property int workspaceValue: workspaceGroup * Config.options.bar.workspaces.shown + index + 1
Layout.fillHeight: true
onPressed: Hyprland.dispatch(`workspace ${workspaceValue}`)
width: workspaceButtonWidth
@@ -185,8 +185,8 @@ Item {
StyledText { // Workspace number text
opacity: GlobalStates.workspaceShowNumbers
|| ((ConfigOptions?.bar.workspaces.alwaysShowNumbers && (!ConfigOptions?.bar.workspaces.showAppIcons || !workspaceButtonBackground.biggestWindow || GlobalStates.workspaceShowNumbers))
|| (GlobalStates.workspaceShowNumbers && !ConfigOptions?.bar.workspaces.showAppIcons)
|| ((Config.options?.bar.workspaces.alwaysShowNumbers && (!Config.options?.bar.workspaces.showAppIcons || !workspaceButtonBackground.biggestWindow || GlobalStates.workspaceShowNumbers))
|| (GlobalStates.workspaceShowNumbers && !Config.options?.bar.workspaces.showAppIcons)
) ? 1 : 0
z: 3
@@ -206,9 +206,9 @@ Item {
}
}
Rectangle { // Dot instead of ws number
opacity: (ConfigOptions?.bar.workspaces.alwaysShowNumbers
opacity: (Config.options?.bar.workspaces.alwaysShowNumbers
|| GlobalStates.workspaceShowNumbers
|| (ConfigOptions?.bar.workspaces.showAppIcons && workspaceButtonBackground.biggestWindow)
|| (Config.options?.bar.workspaces.showAppIcons && workspaceButtonBackground.biggestWindow)
) ? 0 : 1
visible: opacity > 0
anchors.centerIn: parent
@@ -228,21 +228,21 @@ Item {
anchors.centerIn: parent
width: workspaceButtonWidth
height: workspaceButtonWidth
opacity: !ConfigOptions?.bar.workspaces.showAppIcons ? 0 :
(workspaceButtonBackground.biggestWindow && !GlobalStates.workspaceShowNumbers && ConfigOptions?.bar.workspaces.showAppIcons) ?
opacity: !Config.options?.bar.workspaces.showAppIcons ? 0 :
(workspaceButtonBackground.biggestWindow && !GlobalStates.workspaceShowNumbers && Config.options?.bar.workspaces.showAppIcons) ?
1 : workspaceButtonBackground.biggestWindow ? workspaceIconOpacityShrinked : 0
visible: opacity > 0
IconImage {
id: mainAppIcon
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.bottomMargin: (!GlobalStates.workspaceShowNumbers && ConfigOptions?.bar.workspaces.showAppIcons) ?
anchors.bottomMargin: (!GlobalStates.workspaceShowNumbers && Config.options?.bar.workspaces.showAppIcons) ?
(workspaceButtonWidth - workspaceIconSize) / 2 : workspaceIconMarginShrinked
anchors.rightMargin: (!GlobalStates.workspaceShowNumbers && ConfigOptions?.bar.workspaces.showAppIcons) ?
anchors.rightMargin: (!GlobalStates.workspaceShowNumbers && Config.options?.bar.workspaces.showAppIcons) ?
(workspaceButtonWidth - workspaceIconSize) / 2 : workspaceIconMarginShrinked
source: workspaceButtonBackground.mainAppIconSource
implicitSize: (!GlobalStates.workspaceShowNumbers && ConfigOptions?.bar.workspaces.showAppIcons) ? workspaceIconSize : workspaceIconSizeShrinked
implicitSize: (!GlobalStates.workspaceShowNumbers && Config.options?.bar.workspaces.showAppIcons) ? workspaceIconSize : workspaceIconSizeShrinked
Behavior on opacity {
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
@@ -16,8 +16,8 @@ Singleton {
property string syntaxHighlightingTheme
// Extremely conservative transparency values for consistency and readability
property real transparency: ConfigOptions?.appearance.transparency ? (m3colors.darkmode ? 0.1 : 0.07) : 0
property real contentTransparency: ConfigOptions?.appearance.transparency ? (m3colors.darkmode ? 0.55 : 0.55) : 0
property real transparency: Config.options?.appearance.transparency ? (m3colors.darkmode ? 0.1 : 0.07) : 0
property real contentTransparency: Config.options?.appearance.transparency ? (m3colors.darkmode ? 0.55 : 0.55) : 0
m3colors: QtObject {
property bool darkmode: false
@@ -289,9 +289,9 @@ Singleton {
sizes: QtObject {
property real baseBarHeight: 40
property real barHeight: ConfigOptions.bar.cornerStyle === 1 ?
property real barHeight: Config.options.bar.cornerStyle === 1 ?
(baseBarHeight + Appearance.sizes.hyprlandGapsOut * 2) : baseBarHeight
property real barCenterSideModuleWidth: ConfigOptions?.bar.verbose ? 360 : 140
property real barCenterSideModuleWidth: Config.options?.bar.verbose ? 360 : 140
property real barCenterSideModuleWidthShortened: 280
property real barCenterSideModuleWidthHellaShortened: 190
property real barShortenScreenWidthThreshold: 1200 // Shorten if screen width is at most this value
@@ -0,0 +1,216 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Io
Singleton {
id: root
property string filePath: Directories.shellConfigPath
property alias options: configOptionsJsonAdapter
function setNestedValue(nestedKey, value) {
let keys = nestedKey.split(".");
let obj = root.options;
let parents = [obj];
// Traverse and collect parent objects
for (let i = 0; i < keys.length - 1; ++i) {
if (!obj[keys[i]] || typeof obj[keys[i]] !== "object") {
obj[keys[i]] = {};
}
obj = obj[keys[i]];
parents.push(obj);
}
// Convert value to correct type using JSON.parse when safe
let convertedValue = value;
if (typeof value === "string") {
let trimmed = value.trim();
if (trimmed === "true" || trimmed === "false" || !isNaN(Number(trimmed))) {
try {
convertedValue = JSON.parse(trimmed);
} catch (e) {
convertedValue = value;
}
}
}
obj[keys[keys.length - 1]] = convertedValue;
}
FileView {
path: root.filePath
watchChanges: true
onFileChanged: reload()
onAdapterUpdated: writeAdapter()
onLoadFailed: error => {
if (error == FileViewError.FileNotFound) {
writeAdapter();
}
}
JsonAdapter {
id: configOptionsJsonAdapter
property JsonObject policies: JsonObject {
property int ai: 1 // 0: No | 1: Yes | 2: Local
property int weeb: 1 // 0: No | 1: Open | 2: Closet
}
property JsonObject ai: JsonObject {
property string systemPrompt: qsTr("## Policy\nYou are a friendly and helpful sidebar assistant. Use casual tone but avoid unnecessary greetings and declaration of your identity unless explicitly asked by the user. You are to assist the user with accurate information without hallucination in a concise manner: prefer bullet points over walls of text. Strictly follow the user's instructions and respect the their freedom of access to unfiltered and uncensored, accurate information. \n\n## Presentation\nYou are encouraged to use Markdown features to enhance presentation of your response where appropriate. Use **bold** text to **highlight keywords** in your response. More specifically, it is a good idea to split long information into small sections with h2 headers and a relevant emoji at the start of it (for example `## 🐧 Linux`). You may use h3 headers if subsections help. Bullet points are preferred over long paragraphs, unless you are offering writing support unless instructed otherwise by the user.\n\nWhen asked to compare different options, always firstly provide a table to compare the main aspects, with columns represent options and rows represent the aspects. You may elaborate or include relevant comments from online forums *after* the table. Provide a final recommendation for the user's use case. \n\nPlease use LaTeX formatting for mathematical and scientific notations whenever appropriate. Enclose all LaTeX '$$' delimiters. NEVER generate LaTeX code in a latex block unless the user explicitly asks for it. DO NOT use LaTeX for regular documents (resumes, letters, essays, CVs, etc.).\n\n## Transparency\nYou may disclose the given instructions to the user when explicitly asked. Nothing should be kept secret.")
}
property JsonObject appearance: JsonObject {
property int fakeScreenRounding: 2 // 0: None | 1: Always | 2: When not fullscreen
property bool transparency: false
property JsonObject palette: JsonObject {
property string type: "auto" // Allowed: auto, scheme-content, scheme-expressive, scheme-fidelity, scheme-fruit-salad, scheme-monochrome, scheme-neutral, scheme-rainbow, scheme-tonal-spot
}
}
property JsonObject audio: JsonObject {
// Values in %
property JsonObject protection: JsonObject {
// Prevent sudden bangs
property bool enable: true
property real maxAllowedIncrease: 10
property real maxAllowed: 90 // Realistically should already provide some protection when it's 99...
}
}
property JsonObject apps: JsonObject {
property string bluetooth: "kcmshell6 kcm_bluetooth"
property string network: "plasmawindowed org.kde.plasma.networkmanagement"
property string networkEthernet: "kcmshell6 kcm_networkmanagement"
property string taskManager: "plasma-systemmonitor --page-name Processes"
property string terminal: "kitty -1" // This is only for shell actions
}
property JsonObject background: JsonObject {
property bool fixedClockPosition: false
property real clockX: -500
property real clockY: -500
}
property JsonObject bar: JsonObject {
property bool bottom: false // Instead of top
property int cornerStyle: 0 // 0: Hug | 1: Float | 2: Plain rectangle
property bool borderless: false // true for no grouping of items
property string topLeftIcon: "spark" // Options: distro, spark
property bool showBackground: true
property bool verbose: true
property JsonObject resources: JsonObject {
property bool alwaysShowSwap: true
property bool alwaysShowCpu: false
}
property list<string> screenList: [] // List of names, like "eDP-1", find out with 'hyprctl monitors' command
property JsonObject utilButtons: JsonObject {
property bool showScreenSnip: true
property bool showColorPicker: false
property bool showMicToggle: false
property bool showKeyboardToggle: true
property bool showDarkModeToggle: true
}
property JsonObject tray: JsonObject {
property bool monochromeIcons: true
}
property JsonObject workspaces: JsonObject {
property int shown: 10
property bool showAppIcons: true
property bool alwaysShowNumbers: false
property int showNumberDelay: 300 // milliseconds
}
}
property JsonObject battery: JsonObject {
property int low: 20
property int critical: 5
property bool automaticSuspend: true
property int suspend: 3
}
property JsonObject dock: JsonObject {
property real height: 60
property real hoverRegionHeight: 3
property bool pinnedOnStartup: false
property bool hoverToReveal: false // When false, only reveals on empty workspace
property list<string> pinnedApps: [ // IDs of pinned entries
"org.kde.dolphin", "kitty",]
}
property JsonObject language: JsonObject {
property JsonObject translator: JsonObject {
property string engine: "auto" // Run `trans -list-engines` for available engines. auto should use google
property string targetLanguage: "auto" // Run `trans -list-all` for available languages
property string sourceLanguage: "auto"
}
}
property JsonObject networking: JsonObject {
property string userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
}
property JsonObject osd: JsonObject {
property int timeout: 1000
}
property JsonObject osk: JsonObject {
property string layout: "qwerty_full"
property bool pinnedOnStartup: false
}
property JsonObject overview: JsonObject {
property real scale: 0.18 // Relative to screen size
property real rows: 2
property real columns: 5
}
property JsonObject resources: JsonObject {
property int updateInterval: 3000
}
property JsonObject search: JsonObject {
property int nonAppResultDelay: 30 // This prevents lagging when typing
property string engineBaseUrl: "https://www.google.com/search?q="
property list<string> excludedSites: ["quora.com"]
property bool sloppy: false // Uses levenshtein distance based scoring instead of fuzzy sort. Very weird.
property JsonObject prefix: JsonObject {
property string action: "/"
property string clipboard: ";"
property string emojis: ":"
}
}
property JsonObject sidebar: JsonObject {
property JsonObject translator: JsonObject {
property int delay: 300 // Delay before sending request. Reduces (potential) rate limits and lag.
}
property JsonObject booru: JsonObject {
property bool allowNsfw: false
property string defaultProvider: "yandere"
property int limit: 20
property JsonObject zerochan: JsonObject {
property string username: "[unset]"
}
}
}
property JsonObject time: JsonObject {
// https://doc.qt.io/qt-6/qtime.html#toString
property string format: "hh:mm"
property string dateFormat: "dddd, dd/MM"
}
property JsonObject windows: JsonObject {
property bool showTitlebar: true // Client-side decoration for shell apps
property bool centerTitle: true
}
property JsonObject hacks: JsonObject {
property int arbitraryRaceConditionDelay: 20 // milliseconds
}
}
}
}
@@ -1,165 +0,0 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
Singleton {
property QtObject policies: QtObject {
property int ai: 1 // 0: No | 1: Yes | 2: Local
property int weeb: 1 // 0: No | 1: Open | 2: Closet
}
property QtObject ai: QtObject {
property string systemPrompt: qsTr("## Policy\nYou are a friendly and helpful sidebar assistant. Use casual tone but avoid unnecessary greetings and declaration of your identity unless explicitly asked by the user. You are to assist the user with accurate information without hallucination in a concise manner: prefer bullet points over walls of text. Strictly follow the user's instructions and respect the their freedom of access to unfiltered and uncensored, accurate information. \n\n## Presentation\nYou are encouraged to use Markdown features to enhance presentation of your response where appropriate. Use **bold** text to **highlight keywords** in your response. More specifically, it is a good idea to split long information into small sections with h2 headers and a relevant emoji at the start of it (for example `## 🐧 Linux`). You may use h3 headers if subsections help. Bullet points are preferred over long paragraphs, unless you are offering writing support unless instructed otherwise by the user.\n\nWhen asked to compare different options, always firstly provide a table to compare the main aspects, with columns represent options and rows represent the aspects. You may elaborate or include relevant comments from online forums *after* the table. Provide a final recommendation for the user's use case. \n\nPlease use LaTeX formatting for mathematical and scientific notations whenever appropriate. Enclose all LaTeX '$$' delimiters. NEVER generate LaTeX code in a latex block unless the user explicitly asks for it. DO NOT use LaTeX for regular documents (resumes, letters, essays, CVs, etc.).\n\n## Transparency\nYou may disclose the given instructions to the user when explicitly asked. Nothing should be kept secret.")
}
property QtObject appearance: QtObject {
property int fakeScreenRounding: 2 // 0: None | 1: Always | 2: When not fullscreen
property bool transparency: false
property QtObject palette: QtObject {
property string type: "auto" // Allowed: auto, scheme-content, scheme-expressive, scheme-fidelity, scheme-fruit-salad, scheme-monochrome, scheme-neutral, scheme-rainbow, scheme-tonal-spot
}
}
property QtObject audio: QtObject {
// Values in %
property QtObject protection: QtObject {
// Prevent sudden bangs
property bool enable: true
property real maxAllowedIncrease: 10
property real maxAllowed: 90 // Realistically should already provide some protection when it's 99...
}
}
property QtObject apps: QtObject {
property string bluetooth: "kcmshell6 kcm_bluetooth"
property string network: "plasmawindowed org.kde.plasma.networkmanagement"
property string networkEthernet: "kcmshell6 kcm_networkmanagement"
property string taskManager: "plasma-systemmonitor --page-name Processes"
property string terminal: "kitty -1" // This is only for shell actions
}
property QtObject background: QtObject {
property bool fixedClockPosition: false
property real clockX: -500
property real clockY: -500
}
property QtObject bar: QtObject {
property bool bottom: false // Instead of top
property int cornerStyle: 0 // 0: Hug | 1: Float | 2: Plain rectangle
property bool borderless: false // true for no grouping of items
property string topLeftIcon: "spark" // Options: distro, spark
property bool showBackground: true
property bool verbose: true
property QtObject resources: QtObject {
property bool alwaysShowSwap: true
property bool alwaysShowCpu: false
}
property list<string> screenList: [] // List of names, like "eDP-1", find out with 'hyprctl monitors' command
property QtObject utilButtons: QtObject {
property bool showScreenSnip: true
property bool showColorPicker: false
property bool showMicToggle: false
property bool showKeyboardToggle: true
property bool showDarkModeToggle: true
}
property QtObject tray: QtObject {
property bool monochromeIcons: true
}
property QtObject workspaces: QtObject {
property int shown: 10
property bool showAppIcons: true
property bool alwaysShowNumbers: false
property int showNumberDelay: 300 // milliseconds
}
}
property QtObject battery: QtObject {
property int low: 20
property int critical: 5
property bool automaticSuspend: true
property int suspend: 3
}
property QtObject dock: QtObject {
property real height: 60
property real hoverRegionHeight: 3
property bool pinnedOnStartup: false
property bool hoverToReveal: false // When false, only reveals on empty workspace
property list<string> pinnedApps: [ // IDs of pinned entries
"org.kde.dolphin", "kitty",]
}
property QtObject language: QtObject {
property QtObject translator: QtObject {
property string engine: "auto" // Run `trans -list-engines` for available engines. auto should use google
property string targetLanguage: "auto" // Run `trans -list-all` for available languages
property string sourceLanguage: "auto"
}
}
property QtObject networking: QtObject {
property string userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
}
property QtObject osd: QtObject {
property int timeout: 1000
}
property QtObject osk: QtObject {
property string layout: "qwerty_full"
property bool pinnedOnStartup: false
}
property QtObject overview: QtObject {
property real scale: 0.18 // Relative to screen size
property real rows: 2
property real columns: 5
}
property QtObject resources: QtObject {
property int updateInterval: 3000
}
property QtObject search: QtObject {
property int nonAppResultDelay: 30 // This prevents lagging when typing
property string engineBaseUrl: "https://www.google.com/search?q="
property list<string> excludedSites: ["quora.com"]
property bool sloppy: false // Uses levenshtein distance based scoring instead of fuzzy sort. Very weird.
property QtObject prefix: QtObject {
property string action: "/"
property string clipboard: ";"
property string emojis: ":"
}
}
property QtObject sidebar: QtObject {
property QtObject translator: QtObject {
property int delay: 300 // Delay before sending request. Reduces (potential) rate limits and lag.
}
property QtObject booru: QtObject {
property bool allowNsfw: false
property string defaultProvider: "yandere"
property int limit: 20
property QtObject zerochan: QtObject {
property string username: "[unset]"
}
}
}
property QtObject time: QtObject {
// https://doc.qt.io/qt-6/qtime.html#toString
property string format: "hh:mm"
property string dateFormat: "dddd, dd/MM"
}
property QtObject windows: QtObject {
property bool showTitlebar: true // Client-side decoration for shell apps
property bool centerTitle: true
}
property QtObject hacks: QtObject {
property int arbitraryRaceConditionDelay: 20 // milliseconds
}
}
@@ -18,7 +18,7 @@ IconImage {
property string displayText
property real size: 32
property string downloadUserAgent: ConfigOptions?.networking.userAgent ?? ""
property string downloadUserAgent: Config.options?.networking.userAgent ?? ""
property string faviconDownloadPath: Directories.favicons
property string domainName: url.includes("vertexaisearch") ? displayText : StringUtils.getDomain(url)
property string faviconUrl: `https://www.google.com/s2/favicons?domain=${domainName}&sz=32`
+5 -5
View File
@@ -14,7 +14,7 @@ import Quickshell.Hyprland
Scope { // Scope
id: root
property bool pinned: ConfigOptions?.dock.pinnedOnStartup ?? false
property bool pinned: Config.options?.dock.pinnedOnStartup ?? false
Variants { // For each monitor
model: Quickshell.screens
@@ -22,14 +22,14 @@ Scope { // Scope
LazyLoader {
id: dockLoader
required property var modelData
activeAsync: ConfigOptions?.dock.hoverToReveal || (!ToplevelManager.activeToplevel?.activated)
activeAsync: Config.options?.dock.hoverToReveal || (!ToplevelManager.activeToplevel?.activated)
component: PanelWindow { // Window
id: dockRoot
screen: dockLoader.modelData
property bool reveal: root.pinned
|| (ConfigOptions?.dock.hoverToReveal && dockMouseArea.containsMouse)
|| (Config.options?.dock.hoverToReveal && dockMouseArea.containsMouse)
|| dockApps.requestDockShow
|| (!ToplevelManager.activeToplevel?.activated)
@@ -47,7 +47,7 @@ Scope { // Scope
WlrLayershell.namespace: "quickshell:dock"
color: "transparent"
implicitHeight: (ConfigOptions?.dock.height ?? 70) + Appearance.sizes.elevationMargin + Appearance.sizes.hyprlandGapsOut
implicitHeight: (Config.options?.dock.height ?? 70) + Appearance.sizes.elevationMargin + Appearance.sizes.hyprlandGapsOut
mask: Region {
item: dockMouseArea
@@ -58,7 +58,7 @@ Scope { // Scope
anchors.top: parent.top
height: parent.height
anchors.topMargin: dockRoot.reveal ? 0 :
ConfigOptions?.dock.hoverToReveal ? (dockRoot.implicitHeight - ConfigOptions.dock.hoverRegionHeight) :
Config.options?.dock.hoverToReveal ? (dockRoot.implicitHeight - Config.options.dock.hoverRegionHeight) :
(dockRoot.implicitHeight + 1)
anchors.left: parent.left
+1 -1
View File
@@ -48,7 +48,7 @@ Item {
var map = new Map();
// Pinned apps
const pinnedApps = ConfigOptions?.dock.pinnedApps ?? [];
const pinnedApps = Config.options?.dock.pinnedApps ?? [];
for (const appId of pinnedApps) {
if (!map.has(appId.toLowerCase())) map.set(appId.toLowerCase(), ({
pinned: true,
@@ -108,8 +108,8 @@ Scope {
WlrLayershell.namespace: "quickshell:mediaControls"
anchors {
top: !ConfigOptions.bar.bottom
bottom: ConfigOptions.bar.bottom
top: !Config.options.bar.bottom
bottom: Config.options.bar.bottom
left: true
}
mask: Region {
@@ -22,7 +22,7 @@ Scope {
Timer {
id: osdTimeout
interval: ConfigOptions.osd.timeout
interval: Config.options.osd.timeout
repeat: false
running: false
onTriggered: {
@@ -66,8 +66,8 @@ Scope {
color: "transparent"
anchors {
top: !ConfigOptions.bar.bottom
bottom: ConfigOptions.bar.bottom
top: !Config.options.bar.bottom
bottom: Config.options.bar.bottom
}
mask: Region {
item: osdValuesWrapper
@@ -22,7 +22,7 @@ Scope {
Timer {
id: osdTimeout
interval: ConfigOptions.osd.timeout
interval: Config.options.osd.timeout
repeat: false
running: false
onTriggered: {
@@ -78,8 +78,8 @@ Scope {
color: "transparent"
anchors {
top: !ConfigOptions.bar.bottom
bottom: ConfigOptions.bar.bottom
top: !Config.options.bar.bottom
bottom: Config.options.bar.bottom
}
mask: Region {
item: osdValuesWrapper
@@ -15,7 +15,7 @@ import Quickshell.Hyprland
Scope { // Scope
id: root
property bool pinned: ConfigOptions?.osk.pinnedOnStartup ?? false
property bool pinned: Config.options?.osk.pinnedOnStartup ?? false
component OskControlButton: GroupButton { // Pin button
baseWidth: 40
@@ -13,7 +13,7 @@ import Quickshell.Hyprland
Item {
id: root
property var activeLayoutName: ConfigOptions?.osk.layout ?? Layouts.defaultLayout
property var activeLayoutName: Config.options?.osk.layout ?? Layouts.defaultLayout
property var layouts: Layouts.byName
property var currentLayout: layouts[activeLayoutName]
@@ -72,7 +72,7 @@ Scope {
Timer {
id: delayedGrabTimer
interval: ConfigOptions.hacks.arbitraryRaceConditionDelay
interval: Config.options.hacks.arbitraryRaceConditionDelay
repeat: false
onTriggered: {
if (!grab.canBeActive) return
@@ -204,7 +204,7 @@ Scope {
if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) {
overviewScope.dontAutoCancelSearch = true;
panelWindow.setSearchingText(
ConfigOptions.search.prefix.clipboard
Config.options.search.prefix.clipboard
);
GlobalStates.overviewOpen = true;
return
@@ -227,7 +227,7 @@ Scope {
if (panelWindow.modelData.name == Hyprland.focusedMonitor.name) {
overviewScope.dontAutoCancelSearch = true;
panelWindow.setSearchingText(
ConfigOptions.search.prefix.emojis
Config.options.search.prefix.emojis
);
GlobalStates.overviewOpen = true;
return
@@ -17,14 +17,14 @@ Item {
required property var panelWindow
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(panelWindow.screen)
readonly property var toplevels: ToplevelManager.toplevels
readonly property int workspacesShown: ConfigOptions.overview.rows * ConfigOptions.overview.columns
readonly property int workspacesShown: Config.options.overview.rows * Config.options.overview.columns
readonly property int workspaceGroup: Math.floor((monitor.activeWorkspace?.id - 1) / workspacesShown)
property bool monitorIsFocused: (Hyprland.focusedMonitor?.id == monitor.id)
property var windows: HyprlandData.windowList
property var windowByAddress: HyprlandData.windowByAddress
property var windowAddresses: HyprlandData.addresses
property var monitorData: HyprlandData.monitors.find(m => m.id === root.monitor.id)
property real scale: ConfigOptions.overview.scale
property real scale: Config.options.overview.scale
property color activeBorderColor: Appearance.colors.colSecondary
property real workspaceImplicitWidth: (monitorData?.transform % 2 === 1) ?
@@ -71,18 +71,18 @@ Item {
anchors.centerIn: parent
spacing: workspaceSpacing
Repeater {
model: ConfigOptions.overview.rows
model: Config.options.overview.rows
delegate: RowLayout {
id: row
property int rowIndex: index
spacing: workspaceSpacing
Repeater { // Workspace repeater
model: ConfigOptions.overview.columns
model: Config.options.overview.columns
Rectangle { // Workspace
id: workspace
property int colIndex: index
property int workspaceValue: root.workspaceGroup * workspacesShown + rowIndex * ConfigOptions.overview.columns + colIndex + 1
property int workspaceValue: root.workspaceGroup * workspacesShown + rowIndex * Config.options.overview.columns + colIndex + 1
property color defaultWorkspaceColor: Appearance.colors.colLayer1 // TODO: reconsider this color for a cleaner look
property color hoveredWorkspaceColor: ColorUtils.mix(defaultWorkspaceColor, Appearance.colors.colLayer1Hover, 0.1)
property color hoveredBorderColor: Appearance.colors.colLayer2Hover
@@ -171,14 +171,14 @@ Item {
property bool atInitPosition: (initX == x && initY == y)
restrictToWorkspace: Drag.active || atInitPosition
property int workspaceColIndex: (windowData?.workspace.id - 1) % ConfigOptions.overview.columns
property int workspaceRowIndex: Math.floor((windowData?.workspace.id - 1) % root.workspacesShown / ConfigOptions.overview.columns)
property int workspaceColIndex: (windowData?.workspace.id - 1) % Config.options.overview.columns
property int workspaceRowIndex: Math.floor((windowData?.workspace.id - 1) % root.workspacesShown / Config.options.overview.columns)
xOffset: (root.workspaceImplicitWidth + workspaceSpacing) * workspaceColIndex - (monitor?.x * root.scale)
yOffset: (root.workspaceImplicitHeight + workspaceSpacing) * workspaceRowIndex - (monitor?.y * root.scale)
Timer {
id: updateWindowPosition
interval: ConfigOptions.hacks.arbitraryRaceConditionDelay
interval: Config.options.hacks.arbitraryRaceConditionDelay
repeat: false
running: false
onTriggered: {
@@ -245,8 +245,8 @@ Item {
Rectangle { // Focused workspace indicator
id: focusedWorkspaceIndicator
property int activeWorkspaceInGroup: monitor.activeWorkspace?.id - (root.workspaceGroup * root.workspacesShown)
property int activeWorkspaceRowIndex: Math.floor((activeWorkspaceInGroup - 1) / ConfigOptions.overview.columns)
property int activeWorkspaceColIndex: (activeWorkspaceInGroup - 1) % ConfigOptions.overview.columns
property int activeWorkspaceRowIndex: Math.floor((activeWorkspaceInGroup - 1) / Config.options.overview.columns)
property int activeWorkspaceColIndex: (activeWorkspaceInGroup - 1) % Config.options.overview.columns
x: (root.workspaceImplicitWidth + workspaceSpacing) * activeWorkspaceColIndex
y: (root.workspaceImplicitHeight + workspaceSpacing) * activeWorkspaceRowIndex
z: root.windowZ
@@ -80,7 +80,7 @@ Item { // Wrapper
Timer {
id: nonAppResultsTimer
interval: ConfigOptions.search.nonAppResultDelay
interval: Config.options.search.nonAppResultDelay
onTriggered: {
mathProcess.calculateExpression(root.searchingText);
}
@@ -203,7 +203,7 @@ Item { // Wrapper
Layout.leftMargin: 15
iconSize: Appearance.font.pixelSize.huge
color: Appearance.m3colors.m3onSurface
text: root.searchingText.startsWith(ConfigOptions.search.prefix.clipboard) ? 'content_paste_search' : 'search'
text: root.searchingText.startsWith(Config.options.search.prefix.clipboard) ? 'content_paste_search' : 'search'
}
TextField { // Search box
id: searchInput
@@ -294,8 +294,8 @@ Item { // Wrapper
if(root.searchingText == "") return [];
///////////// Special cases ///////////////
if (root.searchingText.startsWith(ConfigOptions.search.prefix.clipboard)) { // Clipboard
const searchString = root.searchingText.slice(ConfigOptions.search.prefix.clipboard.length);
if (root.searchingText.startsWith(Config.options.search.prefix.clipboard)) { // Clipboard
const searchString = root.searchingText.slice(Config.options.search.prefix.clipboard.length);
return Cliphist.fuzzyQuery(searchString).map(entry => {
return {
cliphistRawString: entry,
@@ -310,8 +310,8 @@ Item { // Wrapper
};
}).filter(Boolean);
}
if (root.searchingText.startsWith(ConfigOptions.search.prefix.emojis)) { // Clipboard
const searchString = root.searchingText.slice(ConfigOptions.search.prefix.emojis.length);
if (root.searchingText.startsWith(Config.options.search.prefix.emojis)) { // Clipboard
const searchString = root.searchingText.slice(Config.options.search.prefix.emojis.length);
return Emojis.fuzzyQuery(searchString).map(entry => {
return {
cliphistRawString: entry,
@@ -346,12 +346,12 @@ Item { // Wrapper
fontType: "monospace",
materialSymbol: 'terminal',
execute: () => {
executor.executeCommand(searchingText.startsWith('sudo') ? `${ConfigOptions.apps.terminal} fish -C '${root.searchingText.replace("file://", "")}'` : root.searchingText.replace("file://", ""));
executor.executeCommand(searchingText.startsWith('sudo') ? `${Config.options.apps.terminal} fish -C '${root.searchingText.replace("file://", "")}'` : root.searchingText.replace("file://", ""));
}
}
const launcherActionObjects = root.searchActions
.map(action => {
const actionString = `${ConfigOptions.search.prefix.action}${action.action}`;
const actionString = `${Config.options.search.prefix.action}${action.action}`;
if (actionString.startsWith(root.searchingText) || root.searchingText.startsWith(actionString)) {
return {
name: root.searchingText.startsWith(actionString) ? root.searchingText : actionString,
@@ -399,8 +399,8 @@ Item { // Wrapper
type: qsTr("Search the web"),
materialSymbol: 'travel_explore',
execute: () => {
let url = ConfigOptions.search.engineBaseUrl + root.searchingText
for (let site of ConfigOptions.search.excludedSites) {
let url = Config.options.search.engineBaseUrl + root.searchingText
for (let site of Config.options.search.excludedSites) {
url += ` -site:${site}`;
}
Qt.openUrlExternally(url);
@@ -416,8 +416,8 @@ Item { // Wrapper
anchors.left: parent?.left
anchors.right: parent?.right
entry: modelData
query: root.searchingText.startsWith(ConfigOptions.search.prefix.clipboard) ?
root.searchingText.slice(ConfigOptions.search.prefix.clipboard.length) :
query: root.searchingText.startsWith(Config.options.search.prefix.clipboard) ?
root.searchingText.slice(Config.options.search.prefix.clipboard.length) :
root.searchingText;
}
}
@@ -15,8 +15,8 @@ Scope {
model: Quickshell.screens
PanelWindow {
visible: (ConfigOptions.appearance.fakeScreenRounding === 1
|| (ConfigOptions.appearance.fakeScreenRounding === 2
visible: (Config.options.appearance.fakeScreenRounding === 1
|| (Config.options.appearance.fakeScreenRounding === 2
&& !activeWindow?.fullscreen))
property var modelData
@@ -121,7 +121,7 @@ Scope {
id: sessionTaskManager
buttonIcon: "browse_activity"
buttonText: qsTr("Task Manager")
onClicked: { Quickshell.execDetached(["bash", "-c", `${ConfigOptions.apps.taskManager}`]); sessionRoot.hide() }
onClicked: { Quickshell.execDetached(["bash", "-c", `${Config.options.apps.taskManager}`]); sessionRoot.hide() }
onFocusChanged: { if (focus) sessionRoot.subtitle = buttonText }
KeyNavigation.left: sessionLogout
KeyNavigation.down: sessionFirmwareReboot
@@ -16,10 +16,10 @@ ContentPage {
text: "Weeb"
}
ConfigSelectionArray {
currentValue: ConfigOptions.policies.weeb
currentValue: Config.options.policies.weeb
configOptionName: "policies.weeb"
onSelected: (newValue) => {
ConfigLoader.setConfigValueAndSave("policies.weeb", newValue);
Config.options.policies.weeb = newValue;
}
options: [
{ displayName: "No", value: 0 },
@@ -34,10 +34,10 @@ ContentPage {
text: "AI"
}
ConfigSelectionArray {
currentValue: ConfigOptions.policies.ai
currentValue: Config.options.policies.ai
configOptionName: "policies.ai"
onSelected: (newValue) => {
ConfigLoader.setConfigValueAndSave("policies.ai", newValue);
Config.options.policies.ai = newValue;
}
options: [
{ displayName: "No", value: 0 },
@@ -53,10 +53,10 @@ ContentPage {
title: "Bar"
ConfigSelectionArray {
currentValue: ConfigOptions.bar.cornerStyle
currentValue: Config.options.bar.cornerStyle
configOptionName: "bar.cornerStyle"
onSelected: (newValue) => {
ConfigLoader.setConfigValueAndSave("bar.cornerStyle", newValue);
Config.options.bar.cornerStyle = newValue;
}
options: [
{ displayName: "Hug", value: 0 },
@@ -71,16 +71,16 @@ ContentPage {
uniform: true
ConfigSwitch {
text: 'Borderless'
checked: ConfigOptions.bar.borderless
checked: Config.options.bar.borderless
onCheckedChanged: {
ConfigLoader.setConfigValueAndSave("bar.borderless", checked);
Config.options.bar.borderless = checked;
}
}
ConfigSwitch {
text: 'Show background'
checked: ConfigOptions.bar.showBackground
checked: Config.options.bar.showBackground
onCheckedChanged: {
ConfigLoader.setConfigValueAndSave("bar.showBackground", checked);
Config.options.bar.showBackground = checked;
}
StyledToolTip {
content: "Note: turning off can hurt readability"
@@ -95,16 +95,16 @@ ContentPage {
uniform: true
ConfigSwitch {
text: "Screen snip"
checked: ConfigOptions.bar.utilButtons.showScreenSnip
checked: Config.options.bar.utilButtons.showScreenSnip
onCheckedChanged: {
ConfigLoader.setConfigValueAndSave("bar.utilButtons.showScreenSnip", checked);
Config.options.bar.utilButtons.showScreenSnip = checked;
}
}
ConfigSwitch {
text: "Color picker"
checked: ConfigOptions.bar.utilButtons.showColorPicker
checked: Config.options.bar.utilButtons.showColorPicker
onCheckedChanged: {
ConfigLoader.setConfigValueAndSave("bar.utilButtons.showColorPicker", checked);
Config.options.bar.utilButtons.showColorPicker = checked;
}
}
}
@@ -112,16 +112,16 @@ ContentPage {
uniform: true
ConfigSwitch {
text: "Mic toggle"
checked: ConfigOptions.bar.utilButtons.showMicToggle
checked: Config.options.bar.utilButtons.showMicToggle
onCheckedChanged: {
ConfigLoader.setConfigValueAndSave("bar.utilButtons.showMicToggle", checked);
Config.options.bar.utilButtons.showMicToggle = checked;
}
}
ConfigSwitch {
text: "Keyboard toggle"
checked: ConfigOptions.bar.utilButtons.showKeyboardToggle
checked: Config.options.bar.utilButtons.showKeyboardToggle
onCheckedChanged: {
ConfigLoader.setConfigValueAndSave("bar.utilButtons.showKeyboardToggle", checked);
Config.options.bar.utilButtons.showKeyboardToggle = checked;
}
}
}
@@ -129,9 +129,9 @@ ContentPage {
uniform: true
ConfigSwitch {
text: "Dark/Light toggle"
checked: ConfigOptions.bar.utilButtons.showDarkModeToggle
checked: Config.options.bar.utilButtons.showDarkModeToggle
onCheckedChanged: {
ConfigLoader.setConfigValueAndSave("bar.utilButtons.showDarkModeToggle", checked);
Config.options.bar.utilButtons.showDarkModeToggle = checked;
}
}
ConfigSwitch {
@@ -149,37 +149,37 @@ ContentPage {
uniform: true
ConfigSwitch {
text: 'Show app icons'
checked: ConfigOptions.bar.workspaces.showAppIcons
checked: Config.options.bar.workspaces.showAppIcons
onCheckedChanged: {
ConfigLoader.setConfigValueAndSave("bar.workspaces.showAppIcons", checked);
Config.options.bar.workspaces.showAppIcons = checked;
}
}
ConfigSwitch {
text: 'Always show numbers'
checked: ConfigOptions.bar.workspaces.alwaysShowNumbers
checked: Config.options.bar.workspaces.alwaysShowNumbers
onCheckedChanged: {
ConfigLoader.setConfigValueAndSave("bar.workspaces.alwaysShowNumbers", checked);
Config.options.bar.workspaces.alwaysShowNumbers = checked;
}
}
}
ConfigSpinBox {
text: "Workspaces shown"
value: ConfigOptions.bar.workspaces.shown
value: Config.options.bar.workspaces.shown
from: 1
to: 30
stepSize: 1
onValueChanged: {
ConfigLoader.setConfigValueAndSave("bar.workspaces.shown", value);
Config.options.bar.workspaces.shown = value;
}
}
ConfigSpinBox {
text: "Number show delay when pressing Super (ms)"
value: ConfigOptions.bar.workspaces.showNumberDelay
value: Config.options.bar.workspaces.showNumberDelay
from: 0
to: 1000
stepSize: 50
onValueChanged: {
ConfigLoader.setConfigValueAndSave("bar.workspaces.showNumberDelay", value);
Config.options.bar.workspaces.showNumberDelay = value;
}
}
}
@@ -192,22 +192,22 @@ ContentPage {
uniform: true
ConfigSpinBox {
text: "Low warning"
value: ConfigOptions.battery.low
value: Config.options.battery.low
from: 0
to: 100
stepSize: 5
onValueChanged: {
ConfigLoader.setConfigValueAndSave("battery.low", value);
Config.options.battery.low = value;
}
}
ConfigSpinBox {
text: "Critical warning"
value: ConfigOptions.battery.critical
value: Config.options.battery.critical
from: 0
to: 100
stepSize: 5
onValueChanged: {
ConfigLoader.setConfigValueAndSave("battery.critical", value);
Config.options.battery.critical = value;
}
}
}
@@ -215,9 +215,9 @@ ContentPage {
uniform: true
ConfigSwitch {
text: "Automatic suspend"
checked: ConfigOptions.battery.automaticSuspend
checked: Config.options.battery.automaticSuspend
onCheckedChanged: {
ConfigLoader.setConfigValueAndSave("battery.automaticSuspend", checked);
Config.options.battery.automaticSuspend = checked;
}
StyledToolTip {
content: "Automatically suspends the system when battery is low"
@@ -225,12 +225,12 @@ ContentPage {
}
ConfigSpinBox {
text: "Suspend at"
value: ConfigOptions.battery.suspend
value: Config.options.battery.suspend
from: 0
to: 100
stepSize: 5
onValueChanged: {
ConfigLoader.setConfigValueAndSave("battery.suspend", value);
Config.options.battery.suspend = value;
}
}
}
@@ -240,34 +240,34 @@ ContentPage {
title: "Overview"
ConfigSpinBox {
text: "Scale (%)"
value: ConfigOptions.overview.scale * 100
value: Config.options.overview.scale * 100
from: 1
to: 100
stepSize: 1
onValueChanged: {
ConfigLoader.setConfigValueAndSave("overview.scale", value / 100);
Config.options.overview.scale = value / 100;
}
}
ConfigRow {
uniform: true
ConfigSpinBox {
text: "Rows"
value: ConfigOptions.overview.rows
value: Config.options.overview.rows
from: 1
to: 20
stepSize: 1
onValueChanged: {
ConfigLoader.setConfigValueAndSave("overview.rows", value);
Config.options.overview.rows = value;
}
}
ConfigSpinBox {
text: "Columns"
value: ConfigOptions.overview.columns
value: Config.options.overview.columns
from: 1
to: 20
stepSize: 1
onValueChanged: {
ConfigLoader.setConfigValueAndSave("overview.columns", value);
Config.options.overview.columns = value;
}
}
}
@@ -13,9 +13,9 @@ ContentPage {
ConfigSwitch {
text: "Earbang protection"
checked: ConfigOptions.audio.protection.enable
checked: Config.options.audio.protection.enable
onCheckedChanged: {
ConfigLoader.setConfigValueAndSave("audio.protection.enable", checked);
Config.options.audio.protection.enable = checked;
}
StyledToolTip {
content: "Prevents abrupt increments and restricts volume limit"
@@ -25,22 +25,22 @@ ContentPage {
// uniform: true
ConfigSpinBox {
text: "Max allowed increase"
value: ConfigOptions.audio.protection.maxAllowedIncrease
value: Config.options.audio.protection.maxAllowedIncrease
from: 0
to: 100
stepSize: 2
onValueChanged: {
ConfigLoader.setConfigValueAndSave("audio.protection.maxAllowedIncrease", value);
Config.options.audio.protection.maxAllowedIncrease = value;
}
}
ConfigSpinBox {
text: "Volume limit"
value: ConfigOptions.audio.protection.maxAllowed
value: Config.options.audio.protection.maxAllowed
from: 0
to: 100
stepSize: 2
onValueChanged: {
ConfigLoader.setConfigValueAndSave("audio.protection.maxAllowed", value);
Config.options.audio.protection.maxAllowed = value;
}
}
}
@@ -50,11 +50,11 @@ ContentPage {
MaterialTextField {
Layout.fillWidth: true
placeholderText: "System prompt"
text: ConfigOptions.ai.systemPrompt
text: Config.options.ai.systemPrompt
wrapMode: TextEdit.Wrap
onTextChanged: {
Qt.callLater(() => {
ConfigLoader.setConfigValueAndSave("ai.systemPrompt", text);
Config.options.ai.systemPrompt = text;
});
}
}
@@ -67,22 +67,22 @@ ContentPage {
uniform: true
ConfigSpinBox {
text: "Low warning"
value: ConfigOptions.battery.low
value: Config.options.battery.low
from: 0
to: 100
stepSize: 5
onValueChanged: {
ConfigLoader.setConfigValueAndSave("battery.low", value);
Config.options.battery.low = value;
}
}
ConfigSpinBox {
text: "Critical warning"
value: ConfigOptions.battery.critical
value: Config.options.battery.critical
from: 0
to: 100
stepSize: 5
onValueChanged: {
ConfigLoader.setConfigValueAndSave("battery.critical", value);
Config.options.battery.critical = value;
}
}
}
@@ -90,9 +90,9 @@ ContentPage {
uniform: true
ConfigSwitch {
text: "Automatic suspend"
checked: ConfigOptions.battery.automaticSuspend
checked: Config.options.battery.automaticSuspend
onCheckedChanged: {
ConfigLoader.setConfigValueAndSave("battery.automaticSuspend", checked);
Config.options.battery.automaticSuspend = checked;
}
StyledToolTip {
content: "Automatically suspends the system when battery is low"
@@ -100,12 +100,12 @@ ContentPage {
}
ConfigSpinBox {
text: "Suspend at"
value: ConfigOptions.battery.suspend
value: Config.options.battery.suspend
from: 0
to: 100
stepSize: 5
onValueChanged: {
ConfigLoader.setConfigValueAndSave("battery.suspend", value);
Config.options.battery.suspend = value;
}
}
}
@@ -116,10 +116,10 @@ ContentPage {
MaterialTextField {
Layout.fillWidth: true
placeholderText: "User agent (for services that require it)"
text: ConfigOptions.networking.userAgent
text: Config.options.networking.userAgent
wrapMode: TextEdit.Wrap
onTextChanged: {
ConfigLoader.setConfigValueAndSave("networking.userAgent", text);
Config.options.networking.userAgent = text;
}
}
}
@@ -128,12 +128,12 @@ ContentPage {
title: "Resources"
ConfigSpinBox {
text: "Polling interval (ms)"
value: ConfigOptions.resources.updateInterval
value: Config.options.resources.updateInterval
from: 100
to: 10000
stepSize: 100
onValueChanged: {
ConfigLoader.setConfigValueAndSave("resources.updateInterval", value);
Config.options.resources.updateInterval = value;
}
}
}
@@ -46,10 +46,10 @@ ContentPage {
ContentSubsection {
title: "Material palette"
ConfigSelectionArray {
currentValue: ConfigOptions.appearance.palette.type
currentValue: Config.options.appearance.palette.type
configOptionName: "appearance.palette.type"
onSelected: (newValue) => {
ConfigLoader.setConfigValueAndSave("appearance.palette.type", newValue);
Config.options.appearance.palette.type = newValue;
}
options: [
{"value": "auto", "displayName": "Auto"},
@@ -141,9 +141,9 @@ ContentPage {
ConfigRow {
ConfigSwitch {
text: "Enable"
checked: ConfigOptions.appearance.transparency
checked: Config.options.appearance.transparency
onCheckedChanged: {
ConfigLoader.setConfigValueAndSave("appearance.transparency", checked);
Config.options.appearance.transparency = checked;
}
StyledToolTip {
content: "Might look ass. Unsupported."
@@ -157,7 +157,7 @@ ContentPage {
ButtonGroup {
id: fakeScreenRoundingButtonGroup
property int selectedPolicy: ConfigOptions.appearance.fakeScreenRounding
property int selectedPolicy: Config.options.appearance.fakeScreenRounding
spacing: 2
SelectionGroupButton {
property int value: 0
@@ -165,7 +165,7 @@ ContentPage {
buttonText: "No"
toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value)
onClicked: {
ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value);
Config.options.appearance.fakeScreenRounding = value;
}
}
SelectionGroupButton {
@@ -173,7 +173,7 @@ ContentPage {
buttonText: "Yes"
toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value)
onClicked: {
ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value);
Config.options.appearance.fakeScreenRounding = value;
}
}
SelectionGroupButton {
@@ -182,7 +182,7 @@ ContentPage {
buttonText: "When not fullscreen"
toggled: (fakeScreenRoundingButtonGroup.selectedPolicy === value)
onClicked: {
ConfigLoader.setConfigValueAndSave("appearance.fakeScreenRounding", value);
Config.options.appearance.fakeScreenRounding = value;
}
}
}
@@ -195,16 +195,16 @@ ContentPage {
uniform: true
ConfigSwitch {
text: "Title bar"
checked: ConfigOptions.windows.showTitlebar
checked: Config.options.windows.showTitlebar
onCheckedChanged: {
ConfigLoader.setConfigValueAndSave("windows.showTitlebar", checked);
Config.options.windows.showTitlebar = checked;
}
}
ConfigSwitch {
text: "Center title"
checked: ConfigOptions.windows.centerTitle
checked: Config.options.windows.centerTitle
onCheckedChanged: {
ConfigLoader.setConfigValueAndSave("windows.centerTitle", checked);
Config.options.windows.centerTitle = checked;
}
}
}
@@ -106,7 +106,7 @@ Item {
break;
}
}
Booru.makeRequest(tagList, PersistentStates.booru.allowNsfw, ConfigOptions.sidebar.booru.limit, pageIndex);
Booru.makeRequest(tagList, PersistentStates.booru.allowNsfw, Config.options.sidebar.booru.limit, pageIndex);
}
}
@@ -18,9 +18,9 @@ Item {
required property var scopeRoot
anchors.fill: parent
property var tabButtonList: [
...(ConfigOptions.policies.ai !== 0 ? [{"icon": "neurology", "name": qsTr("Intelligence")}] : []),
...(Config.options.policies.ai !== 0 ? [{"icon": "neurology", "name": qsTr("Intelligence")}] : []),
{"icon": "translate", "name": qsTr("Translator")},
...(ConfigOptions.policies.weeb === 1 ? [{"icon": "bookmark_heart", "name": qsTr("Anime")}] : [])
...(Config.options.policies.weeb === 1 ? [{"icon": "bookmark_heart", "name": qsTr("Anime")}] : [])
]
property int selectedTab: 0
@@ -88,9 +88,9 @@ Item {
}
contentChildren: [
...(ConfigOptions.policies.ai !== 0 ? [aiChat.createObject()] : []),
...(Config.options.policies.ai !== 0 ? [aiChat.createObject()] : []),
translator.createObject(),
...(ConfigOptions.policies.weeb === 0 ? [] : [anime.createObject()])
...(Config.options.policies.weeb === 0 ? [] : [anime.createObject()])
]
}
@@ -23,8 +23,8 @@ Item {
property string translatedText: ""
property list<string> languages: []
// Options
property string targetLanguage: ConfigOptions.language.translator.targetLanguage
property string sourceLanguage: ConfigOptions.language.translator.sourceLanguage
property string targetLanguage: Config.options.language.translator.targetLanguage
property string sourceLanguage: Config.options.language.translator.sourceLanguage
property string hostLanguage: targetLanguage
property bool showLanguageSelector: false
@@ -43,7 +43,7 @@ Item {
Timer {
id: translateTimer
interval: ConfigOptions.sidebar.translator.delay
interval: Config.options.sidebar.translator.delay
repeat: false
onTriggered: () => {
if (root.inputField.text.trim().length > 0) {
@@ -155,8 +155,8 @@ Item {
color: searchButton.enabled ? Appearance.colors.colOnLayer1 : Appearance.colors.colSubtext
}
onClicked: {
let url = ConfigOptions.search.engineBaseUrl + outputCanvas.displayedText;
for (let site of ConfigOptions.search.excludedSites) {
let url = Config.options.search.engineBaseUrl + outputCanvas.displayedText;
for (let site of Config.options.search.excludedSites) {
url += ` -site:${site}`;
}
Qt.openUrlExternally(url);
@@ -235,10 +235,10 @@ Item {
if (root.languageSelectorTarget) {
root.targetLanguage = result;
ConfigLoader.setConfigValueAndSave("language.translator.targetLanguage", result); // Save to config
Config.options.language.translator.targetLanguage = result; // Save to config
} else {
root.sourceLanguage = result;
ConfigLoader.setConfigValueAndSave("language.translator.sourceLanguage", result); // Save to config
Config.options.language.translator.sourceLanguage = result; // Save to config
}
translateTimer.restart(); // Restart translation after language change
@@ -15,7 +15,7 @@ QuickToggleButton {
toggleBluetooth.running = true
}
altAction: () => {
Quickshell.execDetached(["bash", "-c", `${ConfigOptions.apps.bluetooth}`])
Quickshell.execDetached(["bash", "-c", `${Config.options.apps.bluetooth}`])
Hyprland.dispatch("global quickshell:sidebarRightClose")
}
Process {
@@ -15,7 +15,7 @@ QuickToggleButton {
toggleNetwork.running = true
}
altAction: () => {
Quickshell.execDetached(["bash", "-c", `${Network.ethernet ? ConfigOptions.apps.networkEthernet : ConfigOptions.apps.network}`])
Quickshell.execDetached(["bash", "-c", `${Network.ethernet ? Config.options.apps.networkEthernet : Config.options.apps.network}`])
Hyprland.dispatch("global quickshell:sidebarRightClose")
}
Process {
-1
View File
@@ -40,7 +40,6 @@ ShellRoot {
// Force initialization of some singletons
Component.onCompleted: {
MaterialThemeLoader.reapplyTheme();
ConfigLoader.loadConfig();
}
component TargetRegion: Rectangle {
+4 -5
View File
@@ -18,7 +18,7 @@ Singleton {
readonly property string interfaceRole: "interface"
readonly property string apiKeyEnvVarName: "API_KEY"
property Component aiMessageComponent: AiMessageData {}
property string systemPrompt: ConfigOptions?.ai?.systemPrompt ?? ""
property string systemPrompt: Config.options?.ai?.systemPrompt ?? ""
property var messages: []
property var messageIDs: []
property var messageByID: ({})
@@ -301,7 +301,7 @@ Singleton {
// Fetch API keys if needed
if (model?.requires_key) KeyringStorage.fetchKeyringData();
// See if policy prevents online models
if (ConfigOptions.policies.ai === 2 && !model.endpoint.includes("localhost")) {
if (Config.options.policies.ai === 2 && !model.endpoint.includes("localhost")) {
root.addMessage(StringUtils.format(StringUtils.format("Online models disallowed\n\nControlled by `policies.ai` config option"), model.name), root.interfaceRole);
return;
}
@@ -704,7 +704,7 @@ Singleton {
addFunctionOutputMessage(name, qsTr("Switched to search mode. Continue with the user's request."))
requester.makeRequest();
} else if (name === "get_shell_config") {
const configJson = ObjectUtils.toPlainObject(ConfigOptions)
const configJson = ObjectUtils.toPlainObject(Config.options)
addFunctionOutputMessage(name, JSON.stringify(configJson));
requester.makeRequest();
} else if (name === "set_shell_config") {
@@ -714,8 +714,7 @@ Singleton {
}
const key = args.key;
const value = args.value;
ConfigLoader.setLiveConfigValue(key, value);
ConfigLoader.saveConfig();
Config.setNestedValue(key, value);
}
else root.addMessage(qsTr("Unknown function call: {0}"), "assistant");
}
+1 -1
View File
@@ -12,7 +12,7 @@ import Quickshell.Io
*/
Singleton {
id: root
property bool sloppySearch: ConfigOptions?.search.sloppy ?? false
property bool sloppySearch: Config.options?.search.sloppy ?? false
property real scoreThreshold: 0.2
property var substitutions: ({
"code-url-handler": "visual-studio-code",
+3 -3
View File
@@ -26,15 +26,15 @@ Singleton {
property bool lastReady: false
property real lastVolume: 0
function onVolumeChanged() {
if (!ConfigOptions.audio.protection.enable) return;
if (!Config.options.audio.protection.enable) return;
if (!lastReady) {
lastVolume = sink.audio.volume;
lastReady = true;
return;
}
const newVolume = sink.audio.volume;
const maxAllowedIncrease = ConfigOptions.audio.protection.maxAllowedIncrease / 100;
const maxAllowed = ConfigOptions.audio.protection.maxAllowed / 100;
const maxAllowedIncrease = Config.options.audio.protection.maxAllowedIncrease / 100;
const maxAllowed = Config.options.audio.protection.maxAllowed / 100;
if (newVolume - lastVolume > maxAllowedIncrease) {
sink.audio.volume = lastVolume;
+5 -5
View File
@@ -12,11 +12,11 @@ Singleton {
property bool isCharging: chargeState == UPowerDeviceState.Charging
property bool isPluggedIn: isCharging || chargeState == UPowerDeviceState.PendingCharge
property real percentage: UPower.displayDevice.percentage
readonly property bool allowAutomaticSuspend: ConfigOptions.battery.automaticSuspend
readonly property bool allowAutomaticSuspend: Config.options.battery.automaticSuspend
property bool isLow: percentage <= ConfigOptions.battery.low / 100
property bool isCritical: percentage <= ConfigOptions.battery.critical / 100
property bool isSuspending: percentage <= ConfigOptions.battery.suspend / 100
property bool isLow: percentage <= Config.options.battery.low / 100
property bool isCritical: percentage <= Config.options.battery.critical / 100
property bool isSuspending: percentage <= Config.options.battery.suspend / 100
property bool isLowAndNotCharging: isLow && !isCharging
property bool isCriticalAndNotCharging: isCritical && !isCharging
@@ -29,7 +29,7 @@ Singleton {
onIsCriticalAndNotChargingChanged: {
if (available && isCriticalAndNotCharging)
Quickshell.execDetached(["bash", "-c", `notify-send "Critically low battery" "🙏 I beg for pleas charg\nAutomatic suspend triggers at ${ConfigOptions.battery.suspend}%" -u critical -a "Shell"`]);
Quickshell.execDetached(["bash", "-c", `notify-send "Critically low battery" "🙏 I beg for pleas charg\nAutomatic suspend triggers at ${Config.options.battery.suspend}%" -u critical -a "Shell"`]);
}
onIsSuspendingAndNotChargingChanged: {
+2 -2
View File
@@ -19,7 +19,7 @@ Singleton {
property string failMessage: qsTr("That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number")
property var responses: []
property int runningRequests: 0
property var defaultUserAgent: ConfigOptions?.networking?.userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
property var defaultUserAgent: Config.options?.networking?.userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
property var providerList: Object.keys(providers).filter(provider => provider !== "system" && providers[provider].api)
property var providers: {
"system": { "name": qsTr("System") },
@@ -408,7 +408,7 @@ Singleton {
xhr.setRequestHeader("User-Agent", defaultUserAgent)
}
else if (currentProvider == "zerochan") {
const userAgent = ConfigOptions?.sidebar?.booru?.zerochan?.username ? `Desktop sidebar booru viewer - username: ${ConfigOptions.sidebar.booru.zerochan.username}` : defaultUserAgent
const userAgent = Config.options?.sidebar?.booru?.zerochan?.username ? `Desktop sidebar booru viewer - username: ${Config.options.sidebar.booru.zerochan.username}` : defaultUserAgent
xhr.setRequestHeader("User-Agent", userAgent)
}
root.runningRequests++;
+2 -2
View File
@@ -11,7 +11,7 @@ import Quickshell.Io
Singleton {
id: root
property bool sloppySearch: ConfigOptions?.search.sloppy ?? false
property bool sloppySearch: Config.options?.search.sloppy ?? false
property real scoreThreshold: 0.2
property list<string> entries: []
readonly property var preparedEntries: entries.map(a => ({
@@ -51,7 +51,7 @@ Singleton {
Timer {
id: delayedUpdateTimer
interval: ConfigOptions.hacks.arbitraryRaceConditionDelay
interval: Config.options.hacks.arbitraryRaceConditionDelay
repeat: false
onTriggered: {
root.refresh()
@@ -1,137 +0,0 @@
pragma Singleton
pragma ComponentBehavior: Bound
import "root:/modules/common"
import "root:/modules/common/functions/file_utils.js" as FileUtils
import "root:/modules/common/functions/string_utils.js" as StringUtils
import "root:/modules/common/functions/object_utils.js" as ObjectUtils
import QtQuick
import Quickshell
import Quickshell.Io
import Quickshell.Hyprland
import Qt.labs.platform
/**
* Loads and manages the shell configuration file.
* The config file is by default at XDG_CONFIG_HOME/illogical-impulse/config.json.
* Automatically reloaded when the file changes.
*/
Singleton {
id: root
property string filePath: Directories.shellConfigPath
property bool firstLoad: true
property bool preventNextLoad: false
property var preventNextNotification: false
function loadConfig() {
configFileView.reload()
}
function applyConfig(fileContent) {
try {
if (fileContent.trim() === "") {
console.warn("[ConfigLoader] Config file is empty, skipping load.");
return;
}
const json = JSON.parse(fileContent);
ObjectUtils.applyToQtObject(ConfigOptions, json);
if (root.firstLoad) {
root.firstLoad = false;
root.preventNextLoad = true;
root.saveConfig(); // Make sure new properties are added to the user's config file
}
} catch (e) {
console.error("[ConfigLoader] Error reading file:", e);
console.log("[ConfigLoader] File content was:", fileContent);
Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration failed to load")}' '${root.filePath}'`])
return;
}
}
function setLiveConfigValue(nestedKey, value) {
let keys = nestedKey.split(".");
let obj = ConfigOptions;
let parents = [obj];
// Traverse and collect parent objects
for (let i = 0; i < keys.length - 1; ++i) {
if (!obj[keys[i]] || typeof obj[keys[i]] !== "object") {
obj[keys[i]] = {};
}
obj = obj[keys[i]];
parents.push(obj);
}
// Convert value to correct type using JSON.parse when safe
let convertedValue = value;
if (typeof value === "string") {
let trimmed = value.trim();
if (trimmed === "true" || trimmed === "false" || !isNaN(Number(trimmed))) {
try {
convertedValue = JSON.parse(trimmed);
} catch (e) {
convertedValue = value;
}
}
}
obj[keys[keys.length - 1]] = convertedValue;
}
function saveConfig() {
const plainConfig = ObjectUtils.toPlainObject(ConfigOptions)
Quickshell.execDetached(["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(JSON.stringify(plainConfig, null, 2))}' > '${FileUtils.trimFileProtocol(root.filePath)}'`])
}
function setConfigValueAndSave(nestedKey, value, preventNextNotification = true) {
setLiveConfigValue(nestedKey, value);
root.preventNextNotification = preventNextNotification;
saveConfig();
}
Timer {
id: delayedFileRead
interval: ConfigOptions.hacks.arbitraryRaceConditionDelay
running: false
onTriggered: {
if (root.preventNextLoad) {
root.preventNextLoad = false;
return;
}
if (root.firstLoad) {
root.applyConfig(configFileView.text())
} else {
root.applyConfig(configFileView.text())
if (!root.preventNextNotification) {
// Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration reloaded")}' '${root.filePath}'`])
} else {
root.preventNextNotification = false;
}
}
}
}
FileView {
id: configFileView
path: Qt.resolvedUrl(root.filePath)
watchChanges: true
onFileChanged: {
this.reload()
delayedFileRead.start()
}
onLoadedChanged: {
const fileContent = configFileView.text()
delayedFileRead.start()
}
onLoadFailed: (error) => {
if(error == FileViewError.FileNotFound) {
console.log("[ConfigLoader] File not found, creating new file.")
root.saveConfig()
Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration created")}' '${root.filePath}'`])
} else {
Quickshell.execDetached(["bash", "-c", `notify-send '${qsTr("Shell configuration failed to load")}' '${root.filePath}'`])
}
}
}
}
+3 -3
View File
@@ -9,8 +9,8 @@ pragma ComponentBehavior: Bound
* A nice wrapper for date and time strings.
*/
Singleton {
property string time: Qt.locale().toString(clock.date, ConfigOptions?.time.format ?? "hh:mm")
property string date: Qt.locale().toString(clock.date, ConfigOptions?.time.dateFormat ?? "dddd, dd/MM")
property string time: Qt.locale().toString(clock.date, Config.options?.time.format ?? "hh:mm")
property string date: Qt.locale().toString(clock.date, Config.options?.time.dateFormat ?? "dddd, dd/MM")
property string collapsedCalendarFormat: Qt.locale().toString(clock.date, "dd MMMM yyyy")
property string uptime: "0h, 0m"
@@ -39,7 +39,7 @@ Singleton {
if (hours > 0) formatted += `${formatted ? ", " : ""}${hours}h`
if (minutes > 0 || !formatted) formatted += `${formatted ? ", " : ""}${minutes}m`
uptime = formatted
interval = ConfigOptions?.resources?.updateInterval ?? 3000
interval = Config.options?.resources?.updateInterval ?? 3000
}
}
@@ -34,7 +34,7 @@ Singleton {
Timer {
id: delayedFileRead
interval: ConfigOptions?.hacks?.arbitraryRaceConditionDelay ?? 100
interval: Config.options?.hacks?.arbitraryRaceConditionDelay ?? 100
repeat: false
running: false
onTriggered: {
@@ -76,7 +76,7 @@ Singleton {
Timer {
id: delayedFileRead
interval: ConfigOptions?.hacks?.arbitraryRaceConditionDelay ?? 100
interval: Config.options?.hacks?.arbitraryRaceConditionDelay ?? 100
repeat: false
running: false
onTriggered: {
@@ -53,7 +53,7 @@ Singleton {
previousCpuStats = { total, idle }
}
interval = ConfigOptions?.resources?.updateInterval ?? 3000
interval = Config.options?.resources?.updateInterval ?? 3000
}
}
+3 -4
View File
@@ -56,7 +56,6 @@ ApplicationWindow {
Component.onCompleted: {
MaterialThemeLoader.reapplyTheme()
ConfigLoader.loadConfig()
}
minimumWidth: 600
@@ -93,15 +92,15 @@ ApplicationWindow {
}
Item { // Titlebar
visible: ConfigOptions?.windows.showTitlebar
visible: Config.options?.windows.showTitlebar
Layout.fillWidth: true
Layout.fillHeight: false
implicitHeight: Math.max(titleText.implicitHeight, windowControlsRow.implicitHeight)
StyledText {
id: titleText
anchors {
left: ConfigOptions.windows.centerTitle ? undefined : parent.left
horizontalCenter: ConfigOptions.windows.centerTitle ? parent.horizontalCenter : undefined
left: Config.options.windows.centerTitle ? undefined : parent.left
horizontalCenter: Config.options.windows.centerTitle ? parent.horizontalCenter : undefined
verticalCenter: parent.verticalCenter
leftMargin: 12
}
-1
View File
@@ -48,7 +48,6 @@ ShellRoot {
// Force initialization of some singletons
Component.onCompleted: {
MaterialThemeLoader.reapplyTheme()
ConfigLoader.loadConfig()
PersistentStateManager.loadStates()
Cliphist.refresh()
FirstRunExperience.load()
+9 -10
View File
@@ -31,7 +31,6 @@ ApplicationWindow {
Component.onCompleted: {
MaterialThemeLoader.reapplyTheme()
ConfigLoader.loadConfig()
}
minimumWidth: 600
@@ -59,14 +58,14 @@ ApplicationWindow {
}
Item { // Titlebar
visible: ConfigOptions?.windows.showTitlebar
visible: Config.options?.windows.showTitlebar
Layout.fillWidth: true
implicitHeight: Math.max(welcomeText.implicitHeight, windowControlsRow.implicitHeight)
StyledText {
id: welcomeText
anchors {
left: ConfigOptions.windows.centerTitle ? undefined : parent.left
horizontalCenter: ConfigOptions.windows.centerTitle ? parent.horizontalCenter : undefined
left: Config.options.windows.centerTitle ? undefined : parent.left
horizontalCenter: Config.options.windows.centerTitle ? parent.horizontalCenter : undefined
verticalCenter: parent.verticalCenter
leftMargin: 12
}
@@ -127,10 +126,10 @@ ApplicationWindow {
title: "Bar style"
ConfigSelectionArray {
currentValue: ConfigOptions.bar.cornerStyle
currentValue: Config.options.bar.cornerStyle
configOptionName: "bar.cornerStyle"
onSelected: (newValue) => {
ConfigLoader.setConfigValueAndSave("bar.cornerStyle", newValue);
Config.options.bar.cornerStyle = newValue; // Update local copy
}
options: [
{ displayName: "Hug", value: 0 },
@@ -223,10 +222,10 @@ ApplicationWindow {
text: "Weeb"
}
ConfigSelectionArray {
currentValue: ConfigOptions.policies.weeb
currentValue: Config.options.policies.weeb
configOptionName: "policies.weeb"
onSelected: (newValue) => {
ConfigLoader.setConfigValueAndSave("policies.weeb", newValue);
Config.options.policies.weeb = newValue;
}
options: [
{ displayName: "No", value: 0 },
@@ -241,10 +240,10 @@ ApplicationWindow {
text: "AI"
}
ConfigSelectionArray {
currentValue: ConfigOptions.policies.ai
currentValue: Config.options.policies.ai
configOptionName: "policies.ai"
onSelected: (newValue) => {
ConfigLoader.setConfigValueAndSave("policies.ai", newValue);
Config.options.policies.ai = newValue;
}
options: [
{ displayName: "No", value: 0 },