Watch
1
0
Fork
You've already forked souveraine
0
souveraine/surfaces/quickshell/modules/common/Config.qml

845 lines
44 KiB
QML

pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Io
import qs.modules.common.functions
Singleton {
id: root
property string filePath: Directories.shellConfigPath
property alias options: configOptionsJsonAdapter
property bool ready: false
property int readWriteDelay: 50 // milliseconds
property bool blockWrites: false
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;
}
Timer {
id: fileReloadTimer
interval: root.readWriteDelay
repeat: false
onTriggered: {
configFileView.reload()
}
}
Timer {
id: fileWriteTimer
interval: root.readWriteDelay
repeat: false
onTriggered: {
configFileView.writeAdapter()
}
}
FileView {
id: configFileView
path: root.filePath
watchChanges: true
blockWrites: root.blockWrites
onFileChanged: fileReloadTimer.restart()
onAdapterUpdated: fileWriteTimer.restart()
onLoaded: root.ready = true
onLoadFailed: error => {
if (error == FileViewError.FileNotFound) {
writeAdapter();
}
}
JsonAdapter {
id: configOptionsJsonAdapter
property string panelFamily: "ii" // "ii", "waffle"
// Souveraine form-factor gate. Flip to true on a phone deploy:
// gates the Phone settings category and (later) the single-column
// layout. Laptop deploys stay false and see the stock page set.
property JsonObject souveraine: JsonObject {
property bool phone: false
}
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: "## Style\n- Use casual tone, don't be formal!\n- Always be brief and to the point, unless asked otherwise\n- Don't repeat the user's question\n- Be approachable: Avoid using overly complicated, domain-specific terms and provide analogies when asked to explain a concept\n\n## Context (ignore when irrelevant)\n- You are a helpful and inspiring sidebar assistant on a {DISTRO} Linux system\n- Desktop environment: {DE}\n- Current date & time: {DATETIME}\n- Focused app: {WINDOWCLASS}\n\n## Presentation\n- Use Markdown features in your response: \n - **Bold** text to **highlight keywords** in your response\n - **Split long information into small sections** with h2 headers and a relevant emoji at the start of it (for example `## 🐧 Linux`). Bullet points are preferred over long paragraphs, unless you're offering writing support or instructed otherwise by the user.\n- Asked to compare different options? You should firstly use a table to compare the main aspects, then elaborate or include relevant comments from online forums *after* the table. Make sure to provide a final recommendation for the user's use case!\n- 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\nThanks!\n"
property string tool: "functions" // search, functions, or none
property list<var> extraModels: [
{
"api_format": "openai", // Most of the time you want "openai". Use "gemini" for Google's models
"description": "This is a custom model. Edit the config to add more! | Anyway, this is DeepSeek R1 Distill LLaMA 70B",
"endpoint": "https://openrouter.ai/api/v1/chat/completions",
"homepage": "https://openrouter.ai/deepseek/deepseek-r1-distill-llama-70b:free", // Not mandatory
"icon": "spark-symbolic", // Not mandatory
"key_get_link": "https://openrouter.ai/settings/keys", // Not mandatory
"key_id": "openrouter",
"model": "deepseek/deepseek-r1-distill-llama-70b:free",
"name": "Custom: DS R1 Dstl. LLaMA 70B",
"requires_key": true
}
]
}
property JsonObject appearance: JsonObject {
property bool extraBackgroundTint: true
property int fakeScreenRounding: 2 // 0: None | 1: Always | 2: When not fullscreen
property JsonObject fonts: JsonObject {
property string main: "Google Sans Flex"
property string numbers: "Google Sans Flex"
property string title: "Google Sans Flex"
property string iconNerd: "JetBrains Mono NF"
property string monospace: "JetBrains Mono NF"
property string reading: "Readex Pro"
property string expressive: "Space Grotesk"
}
property JsonObject transparency: JsonObject {
property bool enable: false
property bool automatic: true
property real backgroundTransparency: 0.11
property real contentTransparency: 0.57
}
property JsonObject wallpaperTheming: JsonObject {
property bool enableAppsAndShell: true
property bool enableQtApps: true
property bool enableTerminal: true
property JsonObject terminalGenerationProps: JsonObject {
property real harmony: 0.6
property real harmonizeThreshold: 100
property real termFgBoost: 0.35
property bool forceDarkMode: 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 string accentColor: ""
}
}
property JsonObject audio: JsonObject {
// Values in %
property JsonObject protection: JsonObject {
// Prevent sudden bangs
property bool enable: false
property real maxAllowedIncrease: 10
property real maxAllowed: 99
}
}
property JsonObject apps: JsonObject {
property string bluetooth: "kcmshell6 kcm_bluetooth"
property string changePassword: "kitty -1 --hold=yes fish -i -c 'passwd'"
property string network: "kcmshell6 kcm_networkmanagement"
property string manageUser: "kcmshell6 kcm_users"
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 string update: "kitty -1 --hold=yes fish -i -c 'pkexec pacman -Syu'"
property string volumeMixer: `~/.config/hypr/hyprland/scripts/launch_first_available.sh "pavucontrol-qt" "pavucontrol"`
}
property JsonObject background: JsonObject {
property JsonObject widgets: JsonObject {
property JsonObject clock: JsonObject {
property bool enable: true
property bool showOnlyWhenLocked: false
property string placementStrategy: "leastBusy" // "free", "leastBusy", "mostBusy"
property real x: 100
property real y: 100
property string style: "cookie" // Options: "cookie", "digital"
property string styleLocked: "cookie" // Options: "cookie", "digital"
property JsonObject cookie: JsonObject {
// aiStyling gates the categorize step in
// switchwall.sh (it must be true for wallpapers to
// be AI-categorized on apply). aiPreset is the
// SEPARATE gate for CookieClock applying a
// category preset over the user's configured clock
// style — split 2026-08-05 after turning on
// aiStyling rewrote the phone's clock
// (applyStyle writes these keys). Default off: the
// clock keeps whatever the user set.
property bool aiStyling: false
property bool aiPreset: false
property int sides: 14
property string dialNumberStyle: "full" // Options: "dots" , "numbers", "full" , "none"
property string hourHandStyle: "fill" // Options: "classic", "fill", "hollow", "hide"
property string minuteHandStyle: "medium" // Options "classic", "thin", "medium", "bold", "hide"
property string secondHandStyle: "dot" // Options: "dot", "line", "classic", "hide"
property string dateStyle: "bubble" // Options: "border", "rect", "bubble" , "hide"
property bool timeIndicators: true
property bool hourMarks: false
property bool dateInClock: true
property bool constantlyRotate: false
property bool useSineCookie: false
}
property JsonObject digital: JsonObject {
property bool adaptiveAlignment: true
property bool showDate: true
property bool animateChange: true
property bool vertical: false
property JsonObject font: JsonObject {
property string family: "Google Sans Flex"
property real weight: 350
property real width: 100
property real size: 90
property real roundness: 0
}
}
property JsonObject quote: JsonObject {
property bool enable: false
property string text: ""
}
}
property JsonObject weather: JsonObject {
property bool enable: false
property string placementStrategy: "free" // "free", "leastBusy", "mostBusy"
property real x: 400
property real y: 100
}
// Backported 2026-07-13 from laptop-upstream Config: the
// borrowed Background.qml reads these unconditionally, and
// their absence threw TypeErrors on the laptop. Keys only —
// we are NOT pulling the desktop-widget rendering machinery
// into this phone-first shell; enable defaults to false.
property JsonObject visualizer: JsonObject {
property bool enable: false
property string placementStrategy: "free"
property real x: 500
property real y: 500
property int bars: 30
property string style: "bars"
property bool vertical: false
}
property JsonObject stats: JsonObject {
property bool enable: false
property string placementStrategy: "free"
property real x: 150
property real y: 300
property string githubUsername: ""
property string codeforcesUsername: ""
property bool showGraphs: false
}
property JsonObject systemResources: JsonObject {
property bool enable: false
property string placementStrategy: "free"
property real x: 150
property real y: 600
property bool showGraphs: false
}
}
property string wallpaperPath: ""
property string thumbnailPath: ""
// Optional local derivatives for unlike display shapes. The
// original wallpaper remains canonical; variants are never a
// destructive replacement for it.
property string portraitVariantPath: ""
property string landscapeVariantPath: ""
property real wallpaperFocalX: 0.5
property real wallpaperFocalY: 0.5
property bool hideWhenFullscreen: true
property JsonObject parallax: JsonObject {
property bool vertical: false
property bool autoVertical: false
property bool enableWorkspace: false
property real workspaceZoom: 1.07 // Relative to wallpaper size
property bool enableSidebar: false
property real widgetsFactor: 1.2
}
}
property JsonObject bar: JsonObject {
property JsonObject autoHide: JsonObject {
property bool enable: false
property int hoverRegionWidth: 2
property bool pushWindows: false
property JsonObject showWhenPressingSuper: JsonObject {
property bool enable: true
property int delay: 140
}
}
property bool bottom: false // Instead of top
property int cornerStyle: 0 // 0: Hug | 1: Float | 2: Plain rectangle
property bool floatStyleShadow: true // Show shadow behind bar when cornerStyle == 1 (Float)
property bool borderless: false // true for no grouping of items
property string topLeftIcon: "spark" // Options: "distro" or any icon name in ~/.config/quickshell/ii/assets/icons
property bool showBackground: true
property bool verbose: true
property bool vertical: false
property JsonObject resources: JsonObject {
property bool alwaysShowSwap: true
property bool alwaysShowCpu: true
property int memoryWarningThreshold: 95
property int swapWarningThreshold: 85
property int cpuWarningThreshold: 90
}
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 bool showPerformanceProfileToggle: false
property bool showScreenRecord: false
}
property JsonObject workspaces: JsonObject {
property bool monochromeIcons: true
property int shown: 10
property bool showAppIcons: true
property bool alwaysShowNumbers: false
property int showNumberDelay: 300 // milliseconds
property list<string> numberMap: ["1", "2"] // Characters to show instead of numbers on workspace indicator
property bool useNerdFont: false
}
// Backported 2026-07-13: borrowed ClaudeUsage service + bar
// widget read these unconditionally. Keys only, enable=false.
property JsonObject claudeUsage: JsonObject {
property bool enable: false // Show a Claude (Pro/Max) subscription usage gauge in the bar
property bool defaultWeekly: false // Start on the 7-day window; click to switch session <-> week
property int warningThreshold: 90 // Turn red at/above this utilization (%)
property int fetchInterval: 5 // minutes
}
property JsonObject weather: JsonObject {
property bool enable: false
property bool enableGPS: true // gps based location
property string city: "" // When 'enableGPS' is false
property bool useUSCS: false // Instead of metric (SI) units
property int fetchInterval: 10 // minutes
}
property JsonObject indicators: JsonObject {
property JsonObject notifications: JsonObject {
property bool showUnreadCount: false
}
}
property JsonObject tooltips: JsonObject {
property bool clickToShow: false
}
}
property JsonObject battery: JsonObject {
property int low: 20
property int critical: 5
property int full: 101
property bool automaticSuspend: true
property int suspend: 3
}
property JsonObject calendar: JsonObject {
property string locale: "en-GB"
}
property JsonObject cheatsheet: JsonObject {
// Use a nerdfont to see the icons
// 0: 󰖳 | 1: 󰌽 | 2: 󰘳 | 3:  | 4: 󰨡
// 5:  | 6:  | 7: 󰣇 | 8:  | 9: 
// 10:  | 11:  | 12:  | 13:  | 14: 󱄛
property string superKey: ""
property bool useMacSymbol: false
property bool splitButtons: false
property bool useMouseSymbol: false
property bool useFnSymbol: false
property JsonObject fontSize: JsonObject {
property int key: Appearance.font.pixelSize.smaller
property int comment: Appearance.font.pixelSize.smaller
}
}
property JsonObject conflictKiller: JsonObject {
property bool autoKillNotificationDaemons: false
// DO NOT auto-kill trays here. On this phone kded6 is not a
// competing Plasma tray — it is the StatusNotifierWatcher that
// ii's OWN tray (Quickshell.Services.SystemTray) registers as a
// host with (IsStatusNotifierHostRegistered=true). Killing it
// just makes D-Bus re-activate it on ii's next tray call — an
// infinite loop. Our services/ConflictKiller.qml override drops
// the kded6 check entirely. Leave this false.
property bool autoKillTrays: false
}
property JsonObject crosshair: JsonObject {
// Valorant crosshair format. Use https://www.vcrdb.net/builder
property string code: "0;P;d;1;0l;10;0o;2;1b;0"
}
property JsonObject dock: JsonObject {
property bool enable: false
property bool monochromeIcons: true
property real height: 60
property real hoverRegionHeight: 2
property bool pinnedOnStartup: false
property bool hoverToReveal: true // When false, only reveals on empty workspace
property list<string> pinnedApps: [ // IDs of pinned entries
"org.kde.dolphin", "kitty",]
property list<string> ignoredAppRegexes: []
// Fan-out stacks (macOS "Fan" mode). Each entry is
// "stackId|appId,appId,appId" — phone-local, no Phosh sync.
// stackId is a display label; members render as an arc.
property list<string> stacks: []
// Feel knobs (single source — components read these, never
// hardcode): dragDwellMs = how long a drag hovers an icon
// or stack before it reads as combine-intent (GNOME's
// rule); gestureRailHeight = bottom strip the dock reserves
// for Souveraine's integrated navigation rail, visually and
// in its input mask.
property int dragDwellMs: 500
property real gestureRailHeight: 32
}
property JsonObject interactions: JsonObject {
property JsonObject scrolling: JsonObject {
property bool fasterTouchpadScroll: false // Enable faster scrolling with touchpad
property int mouseScrollDeltaThreshold: 120 // delta >= this then it gets detected as mouse scroll rather than touchpad
property int mouseScrollFactor: 120
property int touchpadScrollFactor: 450
}
property JsonObject deadPixelWorkaround: JsonObject { // Hyprland leaves out 1 pixel on the right for interactions
property bool enable: false
}
}
property JsonObject language: JsonObject {
property string ui: "auto" // UI language. "auto" for system locale, or specific language code like "zh_CN", "en_US"
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 launcher: JsonObject {
property list<string> pinnedApps: [ "org.kde.dolphin", "kitty", "cmake-gui"]
}
property JsonObject light: JsonObject {
property JsonObject night: JsonObject {
property bool automatic: true
property string from: "19:00" // Format: "HH:mm", 24-hour time
property string to: "06:30" // Format: "HH:mm", 24-hour time
property int colorTemperature: 5000
}
property JsonObject antiFlashbang: JsonObject {
property bool enable: false
}
}
property JsonObject lock: JsonObject {
property bool useHyprlock: false
property bool launchOnStartup: false
property int dpmsTimeout: 3
property string unlockHook: ""
// Souveraine: PIN keypad surface for touch panels (phone).
// The OSK can't rise above a session lock, so the lock
// surface must carry its own input.
property bool touchKeypad: false
property JsonObject blur: JsonObject {
property bool enable: true
property real radius: 100
property real extraZoom: 1.1
}
property bool centerClock: true
// 12-hour glance clock (am/pm). Off = 24-hour.
property bool twelveHourClock: true
// Lock-screen wallpaper. Empty = follow the system wallpaper
// (background.wallpaperPath); a path pins the lock's own.
property string wallpaperPath: ""
property bool showLockedText: true
// Souveraine-owned lock cards. Transport controls are
// ambient; media metadata remains personal by default.
property JsonObject content: JsonObject {
property bool showMediaControls: true
property bool mediaMetadataAmbient: false
property bool showBattery: true
// App identity + count are ambient; the summary line is
// personal until promoted. Bodies never render on lock.
property bool showNotifications: true
property bool notificationContentAmbient: false
}
property JsonObject idle: JsonObject {
// Native idle-notify remains opt-in until verified on the
// Pixel compositor; hypridle is the current adapter.
property bool nativeCoordinatorEnabled: false
// The lock timer is the one the user sets. The dim is
// expressed RELATIVE to it — how long before the lock the
// screen starts fading — so the two can never cross and
// moving one moves the other. They were independent
// absolutes (120 and 300), which meant picking a dim
// longer than the lock silently produced a dim that never
// fired. sessiond's lock-screen dim has always been
// relative (`dim_at = budget - dim_grace`); this is the
// shell saying the same thing the same way.
//
// Default 180 reproduces the old pair exactly: 300 - 180 =
// 120. An existing config.json keeps its lockAfterSeconds
// and picks this default up, so nobody's timing changes.
property int lockAfterSeconds: 300
property int dimBeforeLockSeconds: 180
// Backlight level while Dimmed; Active restores the
// brightnessctl-saved value.
property string dimBrightness: "30%"
}
property JsonObject security: JsonObject {
property bool unlockKeyring: true
property bool requirePasswordToPower: false
// Whether the lock surface may trigger power-off / reboot
// at all. Off by default (fail-closed): a destructive
// action from the locked screen is opt-in. The system
// polkit rule (souveraine-login1.rules) lets the active
// session power off without challenge once unlocked; this
// gate keeps the *locked* surface from reaching it until
// the user enables it. requirePasswordToPower then arms
// the action to be confirmed by the PIN unlock.
property bool allowPowerFromLock: false
}
// Step-up authentication grants for sensitive operations.
// The PAM service (souveraine-stepup) is root-owned system
// config and must be installed separately before enabling.
property JsonObject stepUp: JsonObject {
property int grantTtlMs: 300000 // 5 minutes
property bool enabled: false // requires souveraine-stepup PAM service
}
property bool materialShapeChars: true
}
property JsonObject media: JsonObject {
// Attempt to remove dupes (the aggregator playerctl one and browsers' native ones when there's plasma browser integration)
property bool filterDuplicatePlayers: true
}
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 notifications: JsonObject {
property int timeout: 7000
// Upstream modules (NotificationPopup, settings InterfaceConfig)
// read forceMonitor; the old "monitor" name left that undefined
// and threw a TypeError on every popup evaluation.
property JsonObject forceMonitor: JsonObject {
property bool enable: false
property string name: "" // Name of the monitor to show notifications on, like "eDP-1". Find out with 'hyprctl monitors' command
}
}
property JsonObject osd: JsonObject {
property int timeout: 1000
}
property JsonObject osk: JsonObject {
property string layout: "qwerty_full"
property bool pinnedOnStartup: false
}
// Speech services — network STT/TTS on Casey's VPN. The shell
// and the souveraine-stt/tts CLIs read the same config file, so
// the settings page here is the single source of truth for both.
property JsonObject speech: JsonObject {
property JsonObject stt: JsonObject {
property bool enable: true
// faster-whisper REST bridge: POST multipart 'audio'
// (WAV) -> {"text": ...}. /health for the status probe.
property string endpoint: "http://10.10.20.19:7862/transcribe"
}
property JsonObject tts: JsonObject {
property bool enable: false
// Speech-synthesis endpoint: POST {"text": ...} -> audio
// stream. Empty until a TTS server exists on the VPN.
property string endpoint: ""
}
}
// Text-selection action menu (TASK-18).
//
// OPT-IN ON PURPOSE, and do not flip this default casually. When
// enabled, the shell watches the compositor's primary selection,
// which means it observes EVERY piece of text the user highlights
// anywhere on the device — including a password highlighted inside
// a password manager. No tier in SESSION-AUTHORITY-DOCTRINE §2
// covers an ambient capability of that reach, so the user turns it
// on knowingly or it does not run. Selection.qml additionally kills
// its watcher whenever the session is locked and never persists or
// logs selection content.
property JsonObject selection: JsonObject {
property bool enable: false
// Read Aloud is the one action with a live backend today; it
// routes through Speech.speak() and so also obeys
// speech.tts.enable. The rest are stubs until they earn a
// backend (TASK-18: a stubbed action is fine, a janky menu is not).
property bool readAloud: true
// Agent actions ("Talk about this" / "Add to our conversation")
// reach conversation history, which is `personal` tier — they
// stay dark until the session is genuinely unlocked.
property bool agentActions: true
// Reference lookups stay strictly local/offline by default,
// per TASK-18's stated default stance: never touch the agent.
property bool referenceActions: true
}
property JsonObject overlay: JsonObject {
property bool openingZoomAnimation: true
property bool darkenScreen: true
property real clickthroughOpacity: 0.8
property JsonObject floatingImage: JsonObject {
property string imageSource: "https://media.tenor.com/H5U5bJzj3oAAAAAi/kukuru.gif"
property real scale: 0.5
}
}
property JsonObject overview: JsonObject {
property bool enable: true
property real scale: 0.18 // Relative to screen size
property real rows: 2
property real columns: 5
property bool orderRightLeft: false
property bool orderBottomUp: false
property bool centerIcons: true
// The app drawer's own grid (TASK-14). Kept nested instead of
// overloading rows/columns above — those are the desktop
// overview's workspace-grid knobs, and the drawer is a
// different density. The settings app writes these.
property JsonObject appGrid: JsonObject {
property int columns: 4
property int rows: 5
property int iconSize: 44
}
}
property JsonObject regionSelector: JsonObject {
property JsonObject targetRegions: JsonObject {
property bool windows: true
property bool layers: false
property bool content: true
property bool showLabel: false
property real opacity: 0.3
property real contentRegionOpacity: 0.8
property int selectionPadding: 5
}
property JsonObject rect: JsonObject {
property bool showAimLines: true
}
property JsonObject circle: JsonObject {
property int strokeWidth: 6
property int padding: 10
}
property JsonObject annotation: JsonObject {
property bool useSatty: false
}
}
property JsonObject resources: JsonObject {
property int updateInterval: 3000
property int historyLength: 60
}
property JsonObject tray: JsonObject {
property bool monochromeIcons: true
property bool showItemId: false
property bool invertPinnedItems: true // Makes the below a whitelist for the tray and blacklist for the pinned area
property list<var> pinnedItems: [ "Fcitx" ]
property bool filterPassive: true
}
property JsonObject musicRecognition: JsonObject {
property int timeout: 16
property int interval: 4
}
property bool autoIdleInhibit: false
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", "facebook.com"]
property bool sloppy: false // Uses levenshtein distance based scoring instead of fuzzy sort. Very weird.
property JsonObject prefix: JsonObject {
property bool showDefaultActionsWithoutPrefix: true
property string action: "/"
property string app: ">"
property string clipboard: ";"
property string emojis: ":"
property string math: "="
property string shellCommand: "$"
property string webSearch: "?"
}
property JsonObject imageSearch: JsonObject {
property string imageSearchEngineBaseUrl: "https://lens.google.com/uploadbyurl?url="
property bool useCircleSelection: false
}
// Backported 2026-07-13: borrowed LauncherSearch reads this
// unconditionally. Key only, enable=false.
property JsonObject fileSearch: JsonObject {
property bool enable: false
property list<string> paths: [Directories.home]
property list<string> exclude: [".git", "node_modules", "target", "build"]
property bool excludeHiddenDirs: true
property int maxResults: 30
}
}
property JsonObject sidebar: JsonObject {
property bool keepRightSidebarLoaded: true
property int width: 460 // Collapsed sidebar width in px
property int widthExtended: 750 // Extended (Ctrl+O) sidebar width in px
property JsonObject translator: JsonObject {
property bool enable: false
property int delay: 300 // Delay before sending request. Reduces (potential) rate limits and lag.
}
property JsonObject ai: JsonObject {
property bool textFadeIn: false
}
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 cornerOpen: JsonObject {
property bool enable: true
property bool bottom: false
property bool valueScroll: true
property bool clickless: false
property int cornerRegionWidth: 250
property int cornerRegionHeight: 5
property bool visualize: false
property bool clicklessCornerEnd: true
property int clicklessCornerVerticalOffset: 1
}
property JsonObject quickToggles: JsonObject {
property string style: "android" // Options: classic, android
property JsonObject android: JsonObject {
property int columns: 5
property list<var> toggles: [
{ "size": 2, "type": "network" },
{ "size": 2, "type": "bluetooth" },
{ "size": 1, "type": "idleInhibitor" },
{ "size": 1, "type": "mic" },
{ "size": 2, "type": "audio" },
{ "size": 2, "type": "nightLight" }
]
}
}
property JsonObject quickSliders: JsonObject {
property bool enable: false
property bool showMic: false
property bool showVolume: true
property bool showBrightness: true
}
}
property JsonObject screenRecord: JsonObject {
property string savePath: Directories.videos.replace("file://","") // strip "file://"
}
property JsonObject screenSnip: JsonObject {
property string savePath: "" // only copy to clipboard when empty
}
property JsonObject sounds: JsonObject {
property bool battery: false
property bool pomodoro: false
property string theme: "freedesktop"
}
property JsonObject time: JsonObject {
// https://doc.qt.io/qt-6/qtime.html#toString
property string format: "hh:mm"
property string shortDateFormat: "dd/MM"
property string dateWithYearFormat: "dd/MM/yyyy"
property string dateFormat: "ddd, dd/MM"
property JsonObject pomodoro: JsonObject {
property int breakTime: 300
property int cyclesBeforeLongBreak: 4
property int focus: 1500
property int longBreak: 900
}
property bool secondPrecision: false
}
property JsonObject updates: JsonObject {
property bool enableCheck: true
property int checkInterval: 120 // minutes
property int adviseUpdateThreshold: 75 // packages
property int stronglyAdviseUpdateThreshold: 200 // packages
}
property JsonObject wallpaperSelector: JsonObject {
property bool useSystemFileDialog: false
}
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
}
property JsonObject workSafety: JsonObject {
property JsonObject enable: JsonObject {
property bool wallpaper: false
property bool clipboard: false
}
property JsonObject triggerCondition: JsonObject {
property list<string> networkNameKeywords: ["airport", "cafe", "college", "company", "eduroam", "free", "guest", "public", "school", "university"]
property list<string> fileKeywords: ["anime", "booru", "ecchi", "hentai", "yande.re", "konachan", "breast", "nipples", "pussy", "nsfw", "spoiler", "girl"]
property list<string> linkKeywords: ["hentai", "porn", "sukebei", "hitomi.la", "rule34", "gelbooru", "fanbox", "dlsite"]
}
}
property JsonObject waffles: JsonObject {
// Some spots are kinda janky/awkward. Setting the following to
// false will make (some) stuff also be like that for accuracy.
// Example: the right-click menu of the Start button
property JsonObject tweaks: JsonObject {
property bool switchHandlePositionFix: true
property bool smootherMenuAnimations: true
property bool smootherSearchBar: true
}
property JsonObject bar: JsonObject {
property bool bottom: true
property bool leftAlignApps: false
}
property JsonObject actionCenter: JsonObject {
property list<string> toggles: [ "network", "vpn", "bluetooth", "easyEffects", "powerProfile", "idleInhibitor", "nightLight", "darkMode", "antiFlashbang", "cloudflareWarp", "mic", "musicRecognition", "notifications", "onScreenKeyboard", "gameMode", "screenSnip", "colorPicker" ]
}
property JsonObject calendar: JsonObject {
property bool force2CharDayOfWeek: true
}
}
}
}
}